示例#1
0
        internal T DeterminantLaplace(int diagLength)
        {
            if (diagLength == 1)
            {
                return(ConstantsAndFunctions <T> .Forward(this.GetValueNoCheck(0, 0)));
            }
            var det = ConstantsAndFunctions <T> .CreateZero();

            var sign = ConstantsAndFunctions <T> .CreateOne();

            var temp = SquareMatrixFactory <T> .GetMatrix(diagLength);

            for (int i = 0; i < diagLength; i++)
            {
                GetCofactor(this, temp, 0, i, diagLength);
                det = ConstantsAndFunctions <T> .Add(det,
                                                     ConstantsAndFunctions <T> .Multiply(
                                                         sign,
                                                         ConstantsAndFunctions <T> .Multiply(
                                                             this.GetValueNoCheck(0, i),
                                                             temp.DeterminantLaplace(diagLength - 1)
                                                             ))
                                                     );

                sign = ConstantsAndFunctions <T> .Negate(sign);
            }
            return(det);
        }
示例#2
0
        // TODO: how to avoid code duplication?
        /// <summary>
        /// Performs simple Gaussian elimination method on a tensor
        ///
        /// O(N^3)
        /// </summary>
        public T DeterminantGaussianSimple()
        {
            #if ALLOW_EXCEPTIONS
            if (!IsMatrix)
            {
                throw new InvalidShapeException("this should be matrix");
            }
            if (Shape[0] != Shape[1])
            {
                throw new InvalidShapeException("this should be square matrix");
            }
            #endif
            if (Shape[0] == 1)
            {
                return(ConstantsAndFunctions <T> .Forward(this.GetValueNoCheck(0, 0)));
            }

            var n = Shape[0];

            var elemMatrix = this.Forward();
            for (int k = 1; k < n; k++)
            {
                for (int j = k; j < n; j++)
                {
                    var m = ConstantsAndFunctions <T> .Divide(
                        ConstantsAndFunctions <T> .Forward(elemMatrix.GetValueNoCheck(j, k - 1)),
                        ConstantsAndFunctions <T> .Forward(elemMatrix.GetValueNoCheck(k - 1, k - 1))
                        );

                    for (int i = 0; i < n; i++)
                    {
                        var curr = ConstantsAndFunctions <T> .Forward(elemMatrix.GetValueNoCheck(j, i));

                        elemMatrix.SetValueNoCheck(ConstantsAndFunctions <T> .Subtract(
                                                       curr,
                                                       ConstantsAndFunctions <T> .Multiply(
                                                           m,
                                                           elemMatrix.GetValueNoCheck(k - 1, i)
                                                           )
                                                       ), j, i);
                    }
                }
            }

            var det = ConstantsAndFunctions <T> .CreateOne();

            for (int i = 0; i < n; i++)
            {
                det = ConstantsAndFunctions <T> .Multiply(det, elemMatrix.GetValueNoCheck(i, i));
            }

            return(det);
        }
示例#3
0
        /// <summary>
        /// Returns adjugate matrix
        ///
        /// O(N^5)
        /// </summary>
        public GenTensor <T> Adjoint()
        {
            #if ALLOW_EXCEPTIONS
            if (!IsSquareMatrix)
            {
                throw new InvalidShapeException("Matrix should be square");
            }
            #endif
            var diagLength = Shape.shape[0];
            var res        = GenTensor <T> .CreateSquareMatrix(diagLength);

            var temp = SquareMatrixFactory <T> .GetMatrix(diagLength);

            if (diagLength == 1)
            {
                res.SetValueNoCheck(ConstantsAndFunctions <T> .CreateOne(), 0, 0);
                return(res);
            }

            var toNegate = false;

            for (int x = 0; x < diagLength; x++)
            {
                for (int y = 0; y < diagLength; y++)
                {
                    GetCofactor(this, temp, x, y, diagLength);
                    toNegate = (x + y) % 2 == 1;
                    var det = temp.DeterminantGaussianSafeDivision(diagLength - 1);
                    if (toNegate)
                    {
                        res.SetValueNoCheck(ConstantsAndFunctions <T> .Negate(det), y, x);
                    }
                    else
                    {
                        res.SetValueNoCheck(det, y, x);
                    }
                }
            }

            return(res);
        }
示例#4
0
        /// <summary>
        /// Finds Determinant with possible overflow
        /// because it uses fractions for avoiding division
        ///
        /// O(N^3)
        /// </summary>
        internal T DeterminantGaussianSafeDivision(int diagLength)
        {
            InitIfNotInitted();
            #if ALLOW_EXCEPTIONS
            if (!IsMatrix)
            {
                throw new InvalidShapeException("this should be matrix");
            }
            if (Shape[0] != Shape[1])
            {
                throw new InvalidShapeException("this should be square matrix");
            }
            #endif

            if (Shape[0] == 1)
            {
                return(ConstantsAndFunctions <T> .Forward(this.GetValueNoCheck(0, 0)));
            }

            var n          = diagLength;
            var elemMatrix = InnerGaussianEliminationSafeDivision(n);

            var det =
                ConstantsAndFunctions <SafeDivisionWrapper <T> > .CreateOne();

            for (int i = 0; i < n; i++)
            {
                det = ConstantsAndFunctions <SafeDivisionWrapper <T> > .Multiply(det, elemMatrix.GetValueNoCheck(i, i));
            }

            if (ConstantsAndFunctions <T> .IsZero(det.den))
            {
                return(ConstantsAndFunctions <T> .CreateZero());
            }
            return(det.Count());
        }
示例#5
0
 public SafeDivisionWrapper(W val)
 {
     num = val;
     den = ConstantsAndFunctions <W> .CreateOne();
 }
示例#6
0
        private static void InitIfNotInitted()
        {
            if (isFracInitted)
            {
                return;
            }
            isFracInitted = true;

            ConstantsAndFunctions <SafeDivisionWrapper <T> > .Add =
                (a, b) =>
                new SafeDivisionWrapper <T>(
                    ConstantsAndFunctions <T> .Add(
                        ConstantsAndFunctions <T> .Multiply(a.num, b.den),
                        ConstantsAndFunctions <T> .Multiply(a.den, b.num)
                        ),
                    ConstantsAndFunctions <T> .Multiply(a.den, b.den)
                    );

            ConstantsAndFunctions <SafeDivisionWrapper <T> > .Subtract =
                (a, b) =>
                new SafeDivisionWrapper <T>(
                    ConstantsAndFunctions <T> .Subtract(
                        ConstantsAndFunctions <T> .Multiply(a.num, b.den),
                        ConstantsAndFunctions <T> .Multiply(a.den, b.num)
                        ),
                    ConstantsAndFunctions <T> .Multiply(a.den, b.den)
                    );

            ConstantsAndFunctions <SafeDivisionWrapper <T> > .Multiply =
                (a, b) =>
                new SafeDivisionWrapper <T>(
                    ConstantsAndFunctions <T> .Multiply(a.num, b.num),
                    ConstantsAndFunctions <T> .Multiply(a.den, b.den)
                    );

            ConstantsAndFunctions <SafeDivisionWrapper <T> > .Divide =
                (a, b) =>
                new SafeDivisionWrapper <T>(
                    ConstantsAndFunctions <T> .Multiply(a.num, b.den),
                    ConstantsAndFunctions <T> .Multiply(a.den, b.num)
                    );

            ConstantsAndFunctions <SafeDivisionWrapper <T> > .CreateOne = () =>
                                                                          new SafeDivisionWrapper <T>(ConstantsAndFunctions <T> .CreateOne());
        }