/// <summary> /// Permutes a symmetric sparse matrix. C = PAP' where A and C are symmetric. /// </summary> /// <param name="A">column-compressed matrix (only upper triangular part is used)</param> /// <param name="pinv">size n, inverse permutation</param> /// <param name="values">allocate pattern only if false, values and pattern otherwise</param> /// <returns>Permuted matrix, C = PAP'</returns> private CompressedColumnStorage <double> PermuteSym(CompressedColumnStorage <double> A, int[] pinv, bool values) { int i, j, p, q, i2, j2; int n = A.ColumnCount; var ap = A.ColumnPointers; var ai = A.RowIndices; var ax = A.Values; values = values && (ax != null); var result = A.Clone(values); var cp = result.ColumnPointers; var ci = result.RowIndices; var cx = result.Values; int[] w = new int[n]; // get workspace for (j = 0; j < n; j++) // count entries in each column of C { j2 = pinv != null ? pinv[j] : j; // column j of A is column j2 of C for (p = ap[j]; p < ap[j + 1]; p++) { i = ai[p]; if (i > j) { continue; // skip lower triangular part of A } i2 = pinv != null ? pinv[i] : i; // row i of A is row i2 of C w[Math.Max(i2, j2)]++; // column count of C } } Helper.CumulativeSum(cp, w, n); // compute column pointers of C for (j = 0; j < n; j++) { j2 = pinv != null ? pinv[j] : j; // column j of A is column j2 of C for (p = ap[j]; p < ap[j + 1]; p++) { i = ai[p]; if (i > j) { continue; // skip lower triangular part of A } i2 = pinv != null ? pinv[i] : i; // row i of A is row i2 of C ci[q = w[Math.Max(i2, j2)]++] = Math.Min(i2, j2); if (cx != null) { cx[q] = ax[p]; } } } return(result); }
private double Solve(CompressedColumnStorage <T> matrix, T[] input, T[] x, bool symmetric, Stopwatch timer) { // Make a copy of the data (the solver might modify it). var A = matrix.Clone(); var b = (T[])input.Clone(); timer.Restart(); using (var solver = CreateSolver(A, symmetric)) { solver.Solve(b, x); } timer.Stop(); return(timer.Elapsed.TotalMilliseconds); }