private static void TestReordering() { Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse); int order = SparseSymm5by5.Order; int[] rowIndices = SparseSymm5by5.CscRowIndices; int[] colOffsets = SparseSymm5by5.CscColOffsets; int[] permutation = new int[order]; IntPtr common = SuiteSparsePInvokes.CreateCommon(0, 0); int status = SuiteSparsePInvokes.ReorderAMDUpper(order, rowIndices.Length, rowIndices, colOffsets, permutation, out int factorNNZ, common); Assert.True(status == 1, "SuiteSparse reordering failed. A possible reason is the lack of enough available memory"); comparer.AssertEqual(SparseSymm5by5.MatlabPermutationAMD, permutation); SuiteSparsePInvokes.DestroyCommon(ref common); }
/// <summary> /// Find a fill reducing permutation for the sparsity pattern of a symmetric matrix defined by the parameters. /// The returned permutation is new-to-old, namely reordered[i] = original[permutation[i]]. /// </summary> /// <param name="order">The number of rows/columns of the symmetric matrix.</param> /// <param name="nonZerosUpper">The number of (structural) non-zero entries in the upper triangle of the symmetric /// matrix.</param> /// <param name="cscRowIndices">Row indices of the upper triangle entries of the symmetric matrix, in Compressed Sparse /// Columns format. All row indices of the same column must be sorted.</param> /// <param name="cscColOffsets">Column offsets of the upper triangle entries of the symmetric matrix, in Compressed /// Sparse Columns format. All column offsets must be sorted.</param> /// <returns>permutation: An array containing the new-to-old fill reducing permutation. /// stats: Measuments taken by SuiteSparse during the execution of AMD.</returns> /// <exception cref="SuiteSparseException">Thrown if SuiteSparse dlls cannot be loaded or if AMD fails.</exception> public (int[] permutation, ReorderingStatistics stats) FindPermutation(int order, int nonZerosUpper, int[] cscRowIndices, int[] cscColOffsets) { var permutation = new int[order]; IntPtr common = SuiteSparsePInvokes.CreateCommon(0, 0); if (common == IntPtr.Zero) { throw new SuiteSparseException("Failed to initialize SuiteSparse."); } int status = SuiteSparsePInvokes.ReorderAMDUpper(order, nonZerosUpper, cscRowIndices, cscColOffsets, permutation, out int nnzFactor, common); if (status == 0) { throw new SuiteSparseException("AMD failed. This could be caused by the matrix being so large it" + " cannot be processed with the available memory."); } SuiteSparsePInvokes.DestroyCommon(ref common); return(permutation, new ReorderingStatistics(nnzFactor, -1)); }
/// <summary> /// Find a fill reducing permutation for the sparsity pattern of a symmetric matrix defined by the parameters. /// The returned permutation is new-to-old, namely reordered[i] = original[permutation[i]]. /// </summary> /// <param name="order">The number of rows/columns of the symmetric matrix.</param> /// <param name="cscRowIndices">Row indices of the upper triangle entries of the symmetric matrix, in Compressed Sparse /// Columns format. All row indices of the same column must be sorted.</param> /// <param name="cscColOffsets">Column offsets of the upper triangle entries of the symmetric matrix, in Compressed /// Sparse Columns format. All column offsets must be sorted.</param> /// <param name="constraints">Array of length = order with ordering constraints. Its values must be /// 0 <= <paramref name="constraints"/>[i] < order. If <paramref name="constraints"/> = NULL, no constraints /// will be enforced. /// Example: <paramref name="constraints"/> = { 2, 0, 0, 0, 1 }. This means that indices 1, 2, 3 that have /// <paramref name="constraints"/>[i] = 0, will be ordered before index 4 with <paramref name="constraints"/>[4] = 1, /// which will be ordered before index 0 with <paramref name="constraints"/>[0] = 2. Indeed for a certain pattern, /// permutation = { 3, 2, 1, 4, 0 } (remember permutation is a new-to-old /// mapping).</param> /// <returns>permutation: An array containing the new-to-old fill reducing permutation. /// stats: Measuments taken by SuiteSparse during the execution of AMD.</returns> /// <exception cref="ArgumentException">If <paramref name="order"/>, <paramref name="cscRowIndices"/> or /// <paramref name="cscColOffsets"/> do not describe a valid symmetric matrix.</exception> /// <exception cref="SuiteSparseException">Thrown if SuiteSparse dlls cannot be loaded, or if there is not enough memory /// to allocate during CAMD.</exception> public (int[] permutation, ReorderingStatistics stats) FindPermutation(int order, int[] cscRowIndices, int[] cscColOffsets, int[] constraints) { var permutation = new int[order]; int status = SuiteSparsePInvokes.ReorderCAMD(order, cscRowIndices, cscColOffsets, constraints, denseThreshold, aggressiveAbsorption ? 1 : 0, permutation, out int nnzFactor, out int numMovedDense); // Error checking //if (status == 1) throw new SuiteSparseException("The matrix had unsorted columns, but was otherwise ok."); if (status == 2) { throw new ArgumentException( "The arrays that describe the non zero pattern of the matrix were invalid or the permutation buffer was NULL."); } else if (status == 3) { throw new SuiteSparseException("Not enough memory could be allocated"); } return(permutation, new ReorderingStatistics(nnzFactor, numMovedDense)); }
private static void TestCholeskySolver() { Skip.IfNot(TestSettings.TestSuiteSparse, TestSettings.MessageWhenSkippingSuiteSparse); // Define linear system 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 }; double[] rhs = new double[n] { 6.0, 14.0, 11.0, 12.0 }; double[] solutionExpected = { 1.0, 1.0, 1.0, 1.0 }; double[] solution = new double[n]; // Solve it using SuiteSparse IntPtr handle = SuiteSparsePInvokes.CreateCommon(0, 0); int status = SuiteSparsePInvokes.FactorizeCSCUpper(n, nnz, values, rowIndices, colOffsets, out IntPtr factor, handle); Assert.True(status == -1); int nnzFactor = SuiteSparsePInvokes.GetFactorNonZeros(factor); Console.WriteLine($"Before factorization: nnz = {nnz}"); Console.WriteLine($"After factorization: nnz = {nnzFactor}"); SuiteSparsePInvokes.Solve(0, n, 1, factor, rhs, solution, handle); comparer.AssertEqual(solutionExpected, solution); SuiteSparsePInvokes.DestroyFactor(ref factor, handle); SuiteSparsePInvokes.DestroyCommon(ref handle); }