// will probably not work since the matrix will not always be positive definite //[SkippableFact] private static void TestRowAdditionReverse() { Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse); Matrix original = Matrix.CreateFromArray(SparsePosDef10by10.Matrix); Vector rhs = Vector.CreateFromArray(SparsePosDef10by10.Rhs); // Start the matrix as diagonal var matrixExpected = Matrix.CreateIdentity(original.NumColumns); var dok = DokSymmetric.CreateIdentity(SparsePosDef10by10.Order); var factor = CholeskySuiteSparse.Factorize(dok.BuildSymmetricCscMatrix(true), false); for (int i = 0; i < matrixExpected.NumRows; ++i) { // Update matrix Vector newRowVector = original.GetRow(i); matrixExpected.SetSubrow(i, newRowVector); matrixExpected.SetSubcolumn(i, newRowVector); //Console.WriteLine($"\nOnly dofs [0, {i}]"); factor.AddRow(i, SparseVector.CreateFromDense(newRowVector)); // Solve new linear system Vector solutionExpected = matrixExpected.FactorCholesky(true).SolveLinearSystem(rhs); Vector solutionComputed = factor.SolveLinearSystem(rhs); comparer.AssertEqual(solutionExpected, solutionComputed); } }
private static void TestSystemSolution1() { Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse); // Define linear system var rhs = Vector.CreateFromArray(new double[] { 6.0, 14.0, 11.0, 12.0 }); var solutionExpected = Vector.CreateFromArray(new double[] { 1.0, 1.0, 1.0, 1.0 }); var matrixDOK = DokSymmetric.CreateEmpty(4); matrixDOK[0, 0] = 4.0; matrixDOK[0, 2] = 2.0; matrixDOK[1, 1] = 10.0; matrixDOK[1, 2] = 1.0; matrixDOK[1, 3] = 3.0; matrixDOK[2, 2] = 8.0; matrixDOK[3, 3] = 9.0; SymmetricCscMatrix matrixCSC = matrixDOK.BuildSymmetricCscMatrix(true); //const int n = 4; //const int nnz = 7; //int[] colOffsets = new int[n + 1] { 0, 1, 2, 5, nnz }; //int[] rowIndices = new int[nnz] { 0, 1, 0, 1, 2, 1, 3 }; //double[] values = new double[nnz] { 4.0, 10.0, 2.0, 1.0, 8.0, 3.0, 9.0 }; //SymmetricCSC matrixCSC = new SymmetricCSC(values, rowIndices, colOffsets, false); //Solve it using SuiteSparse using (var factor = CholeskySuiteSparse.Factorize(matrixCSC, true)) { Vector solution = factor.SolveLinearSystem(rhs); comparer.AssertEqual(solutionExpected, solution); } }
public static void MemoryConsumptionDebugging() { int order = 100000; int bandwidth = 200; for (int rep = 0; rep < 10; ++rep) { var dok = DokSymmetric.CreateEmpty(order); for (int i = 0; i < order; ++i) { dok[i, i] = 10.0; if (i >= bandwidth) { dok[i - bandwidth, i] = 1.0; } else { dok[0, i] = 1.0; } } dok[0, 0] = 10.0; SymmetricCscMatrix matrix = dok.BuildSymmetricCscMatrix(true); var rhs = Vector.CreateWithValue(order, 2.0); var solution = Vector.CreateZero(order); using (var factorization = CholeskySuiteSparse.Factorize(matrix, true)) { factorization.SolveLinearSystem(rhs, solution); } } }
/// <summary> /// Solves the linear system with back-forward substitution. If the matrix has been modified, it will be refactorized. /// </summary> public override void Solve() { var watch = new Stopwatch(); if (linearSystem.SolutionConcrete == null) { linearSystem.SolutionConcrete = linearSystem.CreateZeroVectorConcrete(); } //else linearSystem.Solution.Clear(); // no need to waste computational time on this in a direct solver // Factorization if (mustFactorize) { watch.Start(); factorization = CholeskySuiteSparse.Factorize(linearSystem.Matrix, useSuperNodalFactorization); watch.Stop(); Logger.LogTaskDuration("Matrix factorization", watch.ElapsedMilliseconds); watch.Reset(); mustFactorize = false; } // Substitutions watch.Start(); factorization.SolveLinearSystem(linearSystem.RhsConcrete, linearSystem.SolutionConcrete); watch.Stop(); Logger.LogTaskDuration("Back/forward substitutions", watch.ElapsedMilliseconds); Logger.IncrementAnalysisStep(); }
protected override Matrix InverseSystemMatrixTimesOtherMatrix(IMatrixView otherMatrix) { var watch = new Stopwatch(); // Factorization if (mustFactorize) { watch.Start(); factorization = CholeskySuiteSparse.Factorize(linearSystem.Matrix, useSuperNodalFactorization); watch.Stop(); Logger.LogTaskDuration("Matrix factorization", watch.ElapsedMilliseconds); watch.Reset(); mustFactorize = false; } // Substitutions watch.Start(); Matrix solutionVectors; if (otherMatrix is Matrix otherDense) { return(factorization.SolveLinearSystems(otherDense)); } else { try { // If there is enough memory, copy the RHS matrix to a dense one, to speed up computations. //TODO: must be benchmarked, if it is actually more efficient than solving column by column. Matrix rhsVectors = otherMatrix.CopyToFullMatrix(); solutionVectors = factorization.SolveLinearSystems(rhsVectors); } catch (InsufficientMemoryException) //TODO: what about OutOfMemoryException? { // Solution vectors int systemOrder = linearSystem.Matrix.NumColumns; int numRhs = otherMatrix.NumColumns; solutionVectors = Matrix.CreateZero(systemOrder, numRhs); Vector solutionVector = linearSystem.CreateZeroVectorConcrete(); // Solve each linear system separately, to avoid copying the RHS matrix to a dense one. for (int j = 0; j < numRhs; ++j) { if (j != 0) { solutionVector.Clear(); } Vector rhsVector = otherMatrix.GetColumn(j); factorization.SolveLinearSystem(rhsVector, solutionVector); solutionVectors.SetSubcolumn(j, solutionVector); } } } watch.Stop(); Logger.LogTaskDuration("Back/forward substitutions", watch.ElapsedMilliseconds); Logger.IncrementAnalysisStep(); return(solutionVectors); }
private static void CheckSystemSolution2() { Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse); int order = SparsePosDef10by10.Order; // Build the matrices and right hand sides var dense = Matrix.CreateFromArray(SparsePosDef10by10.Matrix); //var skyline = SkylineMatrix.CreateFromArrays(order, SparsePositiveDefinite.skylineValues, // SparsePositiveDefinite.skylineDiagOffsets, false); //var dok = DOKSymmetricColMajor.CreateFromSparseMatrix(skyline); var dok = DokSymmetric.CreateEmpty(order); for (int j = 0; j < order; ++j) { for (int i = 0; i <= j; ++i) { if (dense[i, j] != 0) { dok[i, j] = dense[i, j]; } } } Vector b = Vector.CreateFromArray(SparsePosDef10by10.Rhs); Matrix B = Matrix.CreateFromArray(SquareInvertible10by10.Matrix); // Solve using dense algebra CholeskyFull chol = dense.FactorCholesky(false); Matrix U = chol.GetFactorU(); Matrix L = U.Transpose(); Vector xSolveExpect = chol.SolveLinearSystem(b); Matrix XSolveExpect = dense.Invert() * B; Vector xBackExpect = U.Invert() * b; Matrix XBackExpect = U.Invert() * B; Vector xForwardExpect = L.Invert() * b; Matrix XForwardExpect = L.Invert() * B; // Solve using SuiteSparse var(values, rowIndices, colOffsets) = dok.BuildSymmetricCscArrays(true); CholeskySuiteSparse factor = CholeskySuiteSparse.Factorize(order, values.Length, values, rowIndices, colOffsets, true); Vector xSolveComput = factor.SolveLinearSystem(b); Matrix XSolveComput = factor.SolveLinearSystems(B); Vector xBackComput = factor.BackSubstitution(b); Matrix XBackComput = factor.BackSubstitutions(B); Vector xForwardComput = factor.ForwardSubstitution(b); Matrix XForwardComput = factor.ForwardSubstitutions(B); Vector xSolveComput2 = factor.BackSubstitution(factor.ForwardSubstitution(b)); // Check results comparer.AssertEqual(xSolveExpect, xSolveComput); comparer.AssertEqual(XSolveExpect, XSolveComput); comparer.AssertEqual(xBackExpect, xBackComput); comparer.AssertEqual(XBackExpect, XBackComput); comparer.AssertEqual(xForwardExpect, xForwardComput); comparer.AssertEqual(XForwardExpect, XForwardComput); }
private static void TestRowDeletion() { Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse); Matrix original = Matrix.CreateFromArray(SparsePosDef10by10.Matrix); Vector rhs = Vector.CreateFromArray(SparsePosDef10by10.Rhs); // Start the matrix from the original var matrixExpected = Matrix.CreateFromArray(SparsePosDef10by10.Matrix); var dok = DokSymmetric.CreateEmpty(SparsePosDef10by10.Order); for (int j = 0; j < matrixExpected.NumColumns; ++j) { for (int i = 0; i <= j; ++i) { if (matrixExpected[i, j] != 0) { dok[i, j] = matrixExpected[i, j]; } } } var factor = CholeskySuiteSparse.Factorize(dok.BuildSymmetricCscMatrix(true), false); for (int i = 0; i < matrixExpected.NumRows; ++i) { // Update matrix Vector identityRow = Vector.CreateZero(matrixExpected.NumColumns); identityRow[i] = 1.0; matrixExpected.SetSubrow(i, identityRow); matrixExpected.SetSubcolumn(i, identityRow); //Console.WriteLine($"\nOnly dofs [{i + 1}, 10)"); factor.DeleteRow(i); // Solve new linear system Vector solutionExpected = matrixExpected.FactorCholesky(false).SolveLinearSystem(rhs); Vector solutionComputed = factor.SolveLinearSystem(rhs); comparer.AssertEqual(solutionExpected, solutionComputed); } }