예제 #1
0
 /// <summary>
 /// Solves the system of equations analytically.
 /// </summary>
 /// <param name="b">The b.</param>
 /// <param name="IsASymmetric">if set to <c>true</c> [a is symmetric].</param>
 /// <param name="potentialDiagonals">The potential diagonals.</param>
 /// <returns>System.Double[].</returns>
 public IList <double> SolveAnalytically(IList <double> b, bool IsASymmetric = false)
 {
     if (IsASymmetric)
     {
         if (ValuesChanged || TopologyChanged)
         {
             MatrixInCCS = convertToCCS(this);
         }
         if (TopologyChanged)
         {
             symbolicFactorizationMat = CSparse.SymbolicAnalysisLDL(MatrixInCCS);
         }
         if (ValuesChanged || TopologyChanged)
         {
             CSparse.FactorizeLDL(MatrixInCCS, symbolicFactorizationMat, out D, out FactorizationMatrix);
         }
         TopologyChanged = ValuesChanged = false;
         return(CSparse.SolveLDL(b, FactorizationMatrix, D, symbolicFactorizationMat.InversePermute));
     }
     else
     {
         var ccs = convertToCCS(this);
         var columnPermutation = ApproximateMinimumDegree.Generate(
             new SymbolicColumnStorage(ccs), NumCols);
         CompressedColumnStorage L, U;
         int[] pinv;
         // Numeric LU factorization
         CSparse.FactorizeLU(ccs, columnPermutation, out L, out U, out pinv);
         var x = CSparse.ApplyInverse(pinv, b, NumCols);              // x = b(p)
         CSparse.SolveLower(L, x);                                    // x = L\x.
         CSparse.SolveUpper(U, x);                                    // x = U\x.
         return(CSparse.ApplyInverse(columnPermutation, x, NumCols)); // b(q) = x
     }
 }
예제 #2
0
        /// <summary>
        /// Solve Gx=b(:,k), where G is either upper (lo=false) or lower (lo=true)
        /// triangular.
        /// </summary>
        /// <param name="G">lower or upper triangular matrix in column-compressed form</param>
        /// <param name="B">right hand side, b=B(:,k)</param>
        /// <param name="k">use kth column of B as right hand side</param>
        /// <param name="xi">size 2*n, nonzero pattern of x in xi[top..n-1]</param>
        /// <param name="x">size n, x in x[xi[top..n-1]]</param>
        /// <param name="pinv">mapping of rows to columns of G, ignored if null</param>
        /// <param name="lo">true if lower triangular, false if upper</param>
        /// <returns>top, -1 in error</returns>
        private static int SolveSp(CompressedColumnStorage G, CompressedColumnStorage B,
                                   int k, int[] xi, double[] x, int[] pinv, bool lo)
        {
            if (xi == null || x == null)
            {
                return(-1);
            }
            var gColPointers = G.ColumnPointers;
            var gRowIndices  = G.RowIndices;
            var gValues      = G.Values;
            var bColPointers = B.ColumnPointers;
            var bRowIndices  = B.RowIndices;
            var bValues      = B.Values;
            var n            = G.ncols;

            // xi[top..n-1]=Reach(B(:,k))
            var top = ApproximateMinimumDegree.Reach(gColPointers, gRowIndices, bColPointers, bRowIndices, n, k, xi,
                                                     pinv);

            for (var i = top; i < n; i++)
            {
                x[xi[i]] = 0; // clear x
            }
            for (var i = bColPointers[k]; i < bColPointers[k + 1]; i++)
            {
                x[bRowIndices[i]] = bValues[i]; // scatter B
            }
            for (var px = top; px < n; px++)
            {
                var j = xi[px];
                var J = pinv != null ? pinv[j] : j;
                if (J < 0)
                {
                    continue;                                                    // column J is empty
                }
                x[j] /= gValues[lo ? gColPointers[J] : gColPointers[J + 1] - 1]; // x(j) /= G(j,j)
                var p = lo ? gColPointers[J] + 1 : gColPointers[J];              // lo: L(j,j) 1st entry
                var q = lo ? gColPointers[J + 1] : gColPointers[J + 1] - 1;
                for (; p < q; p++)
                {
                    x[gRowIndices[p]] -= gValues[p] * x[j]; // x(i) -= G(i,j) * x(j)
                }
            }
            // Return top of stack.
            return(top);
        }
예제 #3
0
        /// <summary>
        /// Symbolics the analysis LDL.
        /// </summary>
        /// <param name="A">a.</param>
        /// <returns>SymbolicFactorization.</returns>
        internal static SymbolicFactorization SymbolicAnalysisLDL(CompressedColumnStorage A)
        {
            var n            = A.ncols;
            var aColPointers = A.ColumnPointers;
            var aRowIndices  = A.RowIndices;

            // P = amd(A+A') or natural
            var permute    = ApproximateMinimumDegree.Generate(A);
            var invPermute = Invert(permute);

            // Output: column pointers and elimination tree.
            var lp     = new int[n + 1];
            var parent = new int[n];

            // Workspace
            var lnz  = new int[n];
            var flag = new int[n];

            for (var k = 0; k < n; k++)
            {
                // L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k)
                parent[k] = -1; // parent of k is not yet known
                flag[k]   = k;  // mark node k as visited
                lnz[k]    = 0;  // count of nonzeros in column k of L
                var kk = permute != null ? permute[k] : k;
                var p2 = aColPointers[kk + 1];
                int p;
                for (p = aColPointers[kk]; p < p2; p++)
                {
                    // A(i,k) is nonzero (original or permuted A)
                    var i = invPermute != null ? invPermute[aRowIndices[p]] : aRowIndices[p];
                    if (i < k)
                    {
                        // follow path from i to root of etree, stop at flagged node
                        for (; flag[i] != k; i = parent[i])
                        {
                            // find parent of i if not yet determined
                            if (parent[i] == -1)
                            {
                                parent[i] = k;
                            }
                            lnz[i]++;    // L(k,i) is nonzero
                            flag[i] = k; // mark i as visited
                        }
                    }
                }
            }
            // construct Lp index array from Lnz column counts
            lp[0] = 0;
            for (var k = 0; k < n; k++)
            {
                lp[k + 1] = lp[k] + lnz[k];
            }
            return(new SymbolicFactorization
            {
                ParentIndices = parent,
                ColumnPointers = lp,
                PermutationVector = permute,
                InversePermute = invPermute
            });
        }