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)); }
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); }
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)); }
/// <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); }
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); }
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)); }
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. }
/// <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); }