예제 #1
0
        public void Test6()
        {
            MatrixD A = new MatrixD(new double[, ] {
                { -21, 2, -4, 0 },
                { 2, 3, 0.1, -1 },
                { 2, 10, 111.1, -11 },
                { 23, 112, 111.1, -143 }
            });
            VectorD b = new VectorD(new double[] { 20, 28, -12, 0.1 });

            SorMethodD solver = new SorMethodD();

            solver.MaxNumberOfIterations = 4;
            VectorD x = solver.Solve(A, null, b);

            VectorD solution = MatrixD.SolveLinearEquations(A, b);

            Assert.IsFalse(VectorD.AreNumericallyEqual(solution, x));
            Assert.AreEqual(4, solver.NumberOfIterations);

            // Compare with Gauss-Seidel. Must be equal.
            GaussSeidelMethodD gsSolver = new GaussSeidelMethodD();

            gsSolver.MaxNumberOfIterations = 4;
            VectorD gsSolution = gsSolver.Solve(A, null, b);

            Assert.IsTrue(VectorD.AreNumericallyEqual(gsSolution, x));
        }
예제 #2
0
        public void TestWarmStarting()
        {
            MatrixD A = new MatrixD(new double[, ] {
                { -21, 2, -4, 0 },
                { 2, 3, 0.1, -1 },
                { 2, 10, 111.1, -11 },
                { 23, 112, 111.1, -143 }
            });
            VectorD b = new VectorD(new double[] { 20, 28, -12, 0.1 });

            SorMethodD solver             = new SorMethodD();
            VectorD    x                  = solver.Solve(A, null, b);
            int        fullIterationCount = solver.NumberOfIterations;

            VectorD solution = MatrixD.SolveLinearEquations(A, b);

            Assert.IsTrue(VectorD.AreNumericallyEqual(solution, x));

            // Now test make separate solve calls with warm-starting
            solver.MaxNumberOfIterations = 3;
            x = solver.Solve(A, null, b);
            Assert.AreEqual(3, solver.NumberOfIterations);
            solver.MaxNumberOfIterations = 100;
            x = solver.Solve(A, x, b);
            Assert.AreEqual(fullIterationCount, solver.NumberOfIterations + 3);
        }
예제 #3
0
        public void Test()
        {
            // Make a random list.
            RandomHelper.Random = new Random(77);
            List <VectorD> points = new List <VectorD>();

            for (int i = 0; i < 10; i++)
            {
                var vector = new VectorD(4);
                RandomHelper.Random.NextVectorD(vector, -1, 10);
                points.Add(vector);
            }

            PrincipalComponentAnalysisD pca = new PrincipalComponentAnalysisD(points);

            Assert.Greater(pca.Variances[0], pca.Variances[1]);
            Assert.Greater(pca.Variances[1], pca.Variances[2]);
            Assert.Greater(pca.Variances[2], pca.Variances[3]);
            Assert.Greater(pca.Variances[3], 0);

            Assert.IsTrue(pca.V.GetColumn(0).IsNumericallyNormalized);
            Assert.IsTrue(pca.V.GetColumn(1).IsNumericallyNormalized);
            Assert.IsTrue(pca.V.GetColumn(2).IsNumericallyNormalized);
            Assert.IsTrue(pca.V.GetColumn(3).IsNumericallyNormalized);

            // Compute covariance matrix and check if it is diagonal in the transformed space.
            MatrixD cov            = StatisticsHelper.ComputeCovarianceMatrix(points);
            MatrixD transformedCov = pca.V.Transposed * cov * pca.V;

            for (int row = 0; row < transformedCov.NumberOfRows; row++)
            {
                for (int column = 0; column < transformedCov.NumberOfColumns; column++)
                {
                    if (row != column)
                    {
                        Assert.IsTrue(Numeric.IsZero(transformedCov[row, column]));
                    }
                }
            }

            // The principal components must be Eigenvectors which means that multiplying with the covariance
            // matrix does only change the length!
            VectorD v0       = pca.V.GetColumn(0);
            VectorD v0Result = cov * v0;

            Assert.IsTrue(VectorD.AreNumericallyEqual(v0.Normalized, v0Result.Normalized));
            VectorD v1       = pca.V.GetColumn(1);
            VectorD v1Result = cov * v1;

            Assert.IsTrue(VectorD.AreNumericallyEqual(v1.Normalized, v1Result.Normalized));
            VectorD v2       = pca.V.GetColumn(2);
            VectorD v2Result = cov * v2;

            Assert.IsTrue(VectorD.AreNumericallyEqual(v2.Normalized, v2Result.Normalized));
            VectorD v3       = pca.V.GetColumn(3);
            VectorD v3Result = cov * v3;

            Assert.IsTrue(VectorD.AreNumericallyEqual(v3.Normalized, v3Result.Normalized));
        }
예제 #4
0
        /// <summary>
        /// Solves the specified linear system of equations <i>Ax=b</i>.
        /// </summary>
        /// <param name="matrixA">The matrix A.</param>
        /// <param name="initialX">
        /// The initial guess for x. If this value is <see langword="null"/>, a zero vector will be used
        /// as initial guess.
        /// </param>
        /// <param name="vectorB">The vector b.</param>
        /// <returns>The solution vector x.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixA"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="vectorB"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="matrixA"/> is not a square matrix.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of elements of <paramref name="initialX"/> does not match.
        /// </exception>
        public override VectorD Solve(MatrixD matrixA, VectorD initialX, VectorD vectorB)
        {
            NumberOfIterations = 0;

            if (matrixA == null)
            {
                throw new ArgumentNullException("matrixA");
            }
            if (vectorB == null)
            {
                throw new ArgumentNullException("vectorB");
            }
            if (matrixA.IsSquare == false)
            {
                throw new ArgumentException("Matrix A must be a square matrix.", "matrixA");
            }
            if (matrixA.NumberOfRows != vectorB.NumberOfElements)
            {
                throw new ArgumentException("The number of rows of A and b do not match.");
            }
            if (initialX != null && initialX.NumberOfElements != vectorB.NumberOfElements)
            {
                throw new ArgumentException("The number of elements of the initial guess for x and b do not match.");
            }

            VectorD xOld        = initialX ?? new VectorD(vectorB.NumberOfElements);
            VectorD xNew        = new VectorD(vectorB.NumberOfElements);
            bool    isConverged = false;

            // Make iterations until max iteration count or the result has converged.
            for (int i = 0; i < MaxNumberOfIterations && !isConverged; i++)
            {
                for (int j = 0; j < vectorB.NumberOfElements; j++)
                {
                    double delta = 0;
                    for (int k = 0; k < j; k++)
                    {
                        delta += matrixA[j, k] * xNew[k];
                    }

                    for (int k = j + 1; k < vectorB.NumberOfElements; k++)
                    {
                        delta += matrixA[j, k] * xOld[k];
                    }

                    delta   = (vectorB[j] - delta) / matrixA[j, j];
                    xNew[j] = xOld[j] + RelaxationFactor * (delta - xOld[j]);
                }

                // Test convergence
                isConverged = VectorD.AreNumericallyEqual(xOld, xNew, Epsilon);

                xOld = xNew.Clone();
                NumberOfIterations = i + 1;
            }

            return(xNew);
        }
        public void CosineInterpolationVectorD()
        {
            VectorD v      = new VectorD(new[] { 1.0, 10.0, 100.0, 1000.0 });
            VectorD w      = new VectorD(new[] { 2.0, 20.0, 200.0, 2000.0 });
            VectorD lerp0  = InterpolationHelper.CosineInterpolation(v, w, 0.0);
            VectorD lerp1  = InterpolationHelper.CosineInterpolation(v, w, 1.0);
            VectorD lerp05 = InterpolationHelper.CosineInterpolation(v, w, 0.5);

            Assert.AreEqual(v, lerp0);
            Assert.AreEqual(w, lerp1);
            Assert.IsTrue(VectorD.AreNumericallyEqual(new VectorD(new[] { 1.5, 15.0, 150.0, 1500.0 }), lerp05));
        }
        public void Test1()
        {
            MatrixD A = new MatrixD(new double[, ] {
                { 4 }
            });
            VectorD b = new VectorD(new double[] { 20 });

            GaussSeidelMethodD solver = new GaussSeidelMethodD();
            VectorD            x      = solver.Solve(A, null, b);

            Assert.IsTrue(VectorD.AreNumericallyEqual(new VectorD(1, 5), x));
            Assert.AreEqual(2, solver.NumberOfIterations);
        }
예제 #7
0
        public void SolveWithDefaultInitialGuess()
        {
            MatrixD A = new MatrixD(new double[, ] {
                { 4 }
            });
            VectorD b = new VectorD(new double[] { 20 });

            JacobiMethodD solver = new JacobiMethodD();
            VectorD       x      = solver.Solve(A, b);

            Assert.IsTrue(VectorD.AreNumericallyEqual(new VectorD(1, 5), x));
            Assert.AreEqual(2, solver.NumberOfIterations);
        }
예제 #8
0
        public void Test3()
        {
            MatrixD A = new MatrixD(new double[, ] {
                { 2, 0 },
                { 0, 2 }
            });
            VectorD b = new VectorD(new double[] { 20, 28 });

            JacobiMethodD solver = new JacobiMethodD();
            VectorD       x      = solver.Solve(A, null, b);

            Assert.IsTrue(VectorD.AreNumericallyEqual(b / 2, x));
            Assert.AreEqual(2, solver.NumberOfIterations);
        }
        public void Test4()
        {
            MatrixD A = new MatrixD(new double[, ] {
                { -12, 2 },
                { 2, 3 }
            });
            VectorD b = new VectorD(new double[] { 20, 28 });

            GaussSeidelMethodD solver = new GaussSeidelMethodD();
            VectorD            x      = solver.Solve(A, null, b);

            VectorD solution = MatrixD.SolveLinearEquations(A, b);

            Assert.IsTrue(VectorD.AreNumericallyEqual(solution, x));
        }
        public void Test5()
        {
            MatrixD A = new MatrixD(new double[, ] {
                { -21, 2, -4, 0 },
                { 2, 3, 0.1, -1 },
                { 2, 10, 111.1, -11 },
                { 23, 112, 111.1, -143 }
            });
            VectorD b = new VectorD(new double[] { 20, 28, -12, 0.1 });

            GaussSeidelMethodD solver = new GaussSeidelMethodD();
            VectorD            x      = solver.Solve(A, null, b);

            VectorD solution = MatrixD.SolveLinearEquations(A, b);

            Assert.IsTrue(VectorD.AreNumericallyEqual(solution, x));
        }
예제 #11
0
        public void Test6()
        {
            MatrixD A = new MatrixD(new double[, ] {
                { -21, 2, -4, 0 },
                { 2, 3, 0.1, -1 },
                { 2, 10, 111.1, -11 },
                { 23, 112, 111.1, -143 }
            });
            VectorD b = new VectorD(new double[] { 20, 28, -12, 0.1 });

            JacobiMethodD solver = new JacobiMethodD();

            solver.MaxNumberOfIterations = 10;
            VectorD x = solver.Solve(A, null, b);

            VectorD solution = MatrixD.SolveLinearEquations(A, b);

            Assert.IsFalse(VectorD.AreNumericallyEqual(solution, x));
            Assert.AreEqual(10, solver.NumberOfIterations);
        }
        public void Test7()
        {
            MatrixD A = new MatrixD(new double[, ] {
                { -21, 2, -4, 0 },
                { 2, 3, 0.1, -1 },
                { 2, 10, 111.1, -11 },
                { 23, 112, 111.1, -143 }
            });
            VectorD b = new VectorD(new double[] { 20, 28, -12, 0.1 });

            GaussSeidelMethodD solver = new GaussSeidelMethodD();

            solver.Epsilon = 0.0001;
            VectorD x = solver.Solve(A, null, b);

            VectorD solution = MatrixD.SolveLinearEquations(A, b);

            Assert.IsTrue(VectorD.AreNumericallyEqual(solution, x, 0.1));
            Assert.IsFalse(VectorD.AreNumericallyEqual(solution, x));
            Assert.Greater(26, solver.NumberOfIterations); // For normal accuracy (EpsilonD) we need 26 iterations.
        }
예제 #13
0
        /// <summary>
        /// Solves the specified linear system of equations <i>Ax=b</i>.
        /// </summary>
        /// <param name="matrixA">The matrix A.</param>
        /// <param name="initialX">
        /// The initial guess for x. If this value is <see langword="null"/>, a zero vector will be used
        /// as initial guess.
        /// </param>
        /// <param name="vectorB">The vector b.</param>
        /// <returns>The solution vector x.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="matrixA"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="vectorB"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="matrixA"/> is not a square matrix.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The number of elements of <paramref name="initialX"/> does not match.
        /// </exception>
        public override VectorD Solve(MatrixD matrixA, VectorD initialX, VectorD vectorB)
        {
            // TODO: We can possible improve the method by reordering after each step.
            // This can be done randomly or we sort by the "convergence" of the elements.
            // See book Physics-Based Animation.

            NumberOfIterations = 0;

            if (matrixA == null)
            {
                throw new ArgumentNullException("matrixA");
            }
            if (vectorB == null)
            {
                throw new ArgumentNullException("vectorB");
            }
            if (matrixA.IsSquare == false)
            {
                throw new ArgumentException("Matrix A must be a square matrix.", "matrixA");
            }
            if (matrixA.NumberOfRows != vectorB.NumberOfElements)
            {
                throw new ArgumentException("The number of rows of A and b do not match.");
            }
            if (initialX != null && initialX.NumberOfElements != vectorB.NumberOfElements)
            {
                throw new ArgumentException("The number of elements of the initial guess for x and b do not match.");
            }

            VectorD xOld        = initialX ?? new VectorD(vectorB.NumberOfElements);
            VectorD xNew        = new VectorD(vectorB.NumberOfElements);
            bool    isConverged = false;

            // Make iterations until max iteration count or the result has converged.
            for (int i = 0; i < MaxNumberOfIterations && !isConverged; i++)
            {
                for (int j = 0; j < vectorB.NumberOfElements; j++)
                {
                    double delta = 0;
                    for (int k = 0; k < j; k++)
                    {
                        delta += matrixA[j, k] * xOld[k];
                    }

                    for (int k = j + 1; k < vectorB.NumberOfElements; k++)
                    {
                        delta += matrixA[j, k] * xOld[k];
                    }

                    xNew[j] = (vectorB[j] - delta) / matrixA[j, j];
                }

                // Test convergence
                isConverged = VectorD.AreNumericallyEqual(xOld, xNew, Epsilon);

                xOld = xNew.Clone();
                NumberOfIterations = i + 1;
            }

            return(xNew);
        }