// 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);
                }
            }
        }
예제 #4
0
        /// <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();
        }
예제 #5
0
 private void ReleaseResources()
 {
     if (factorization != null)
     {
         factorization.Dispose();
         factorization = null;
     }
 }
예제 #6
0
        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);
        }
예제 #8
0
 public override void HandleMatrixWillBeSet()
 {
     mustFactorize = true;
     if (factorization != null)
     {
         factorization.Dispose();
         factorization = null;
     }
     //TODO: make sure the native memory allocated has been cleared. We need all the available memory we can get.
 }
        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);
            }
        }