Exemple #1
0
        /// <summary>
        /// Ordering and symbolic analysis for a Cholesky factorization.
        /// </summary>
        /// <param name="A">Matrix to factorize.</param>
        /// <param name="p">Permutation.</param>
        private void SymbolicAnalysis(CompressedColumnStorage <Complex> A, int[] p)
        {
            int n = A.ColumnCount;

            var sym = this.S = new SymbolicFactorization();

            // Find inverse permutation.
            sym.pinv = Permutation.Invert(p);

            // C = spones(triu(A(P,P)))
            var C = PermuteSym(A, sym.pinv, false);

            // Find etree of C.
            sym.parent = GraphHelper.EliminationTree(n, n, C.ColumnPointers, C.RowIndices, false);

            // Postorder the etree.
            var post = GraphHelper.TreePostorder(sym.parent, n);

            // Find column counts of chol(C)
            var c = GraphHelper.ColumnCounts(SymbolicColumnStorage.Create(C, false), sym.parent, post, false);

            sym.cp = new int[n + 1];

            // Find column pointers for L
            sym.unz = sym.lnz = Helper.CumulativeSum(sym.cp, c, n);
        }
Exemple #2
0
        /// <summary>
        /// Symbolic ordering and analysis for QR.
        /// </summary>
        private void SymbolicAnalysis(ColumnOrdering order, CompressedColumnStorage <double> A)
        {
            int m = A.RowCount;
            int n = A.ColumnCount;

            var sym = this.symFactor = new SymbolicFactorization();

            // Fill-reducing ordering
            sym.q = AMD.Generate(A, order);

            var C = order > 0 ? Permute(A, null, sym.q) : SymbolicColumnStorage.Create(A);

            // etree of C'*C, where C=A(:,q)
            sym.parent = GraphHelper.EliminationTree(m, n, C.ColumnPointers, C.RowIndices, true);
            int[] post = GraphHelper.TreePostorder(sym.parent, n);
            sym.cp = GraphHelper.ColumnCounts(C, sym.parent, post, true); // col counts chol(C'*C)

            bool ok = C != null && sym.parent != null && sym.cp != null && CountV(C);

            if (ok)
            {
                sym.unz = 0;
                for (int k = 0; k < n; k++)
                {
                    sym.unz += sym.cp[k];
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Ordering and symbolic analysis for a Cholesky factorization
        /// </summary>
        /// <param name="order"></param>
        /// <param name="A"></param>
        /// <returns></returns>
        static SymbolicFactorization SymbolicAnalysis(int order, SparseMatrix A)
        {
            int n = A.n;

            int[] c, post, P;

            SymbolicFactorization S = new SymbolicFactorization(); // allocate result S

            P      = Ordering.AMD(order, A);                       // P = amd(A+A'), or natural
            S.pinv = Common.InversePermutation(P, n);              // find inverse permutation

            if (order != 0 && S.pinv == null)
            {
                return(null);
            }

            SparseMatrix C = A.PermuteSym(S.pinv, false);             // C = spones(triu(A(P,P)))

            S.parent = Common.EliminationTree(C, false);              // find etree of C
            post     = Common.TreePostorder(S.parent, n);             // postorder the etree
            c        = Common.ColumnCounts(C, S.parent, post, false); // find column counts of chol(C)

            S.cp  = new int[n + 1];                                   // allocate result S.cp
            S.unz = S.lnz = Common.CumulativeSum(S.cp, c, n);         // find column pointers for L

            return(S);
        }
Exemple #4
0
        /// <summary>
        /// Symbolic ordering and analysis for LU.
        /// </summary>
        /// <param name="A"></param>
        /// <param name="p">Permutation.</param>
        private void SymbolicAnalysis(CompressedColumnStorage <Complex> A, int[] p)
        {
            var sym = this.S = new SymbolicFactorization();

            // Fill-reducing ordering
            sym.q = p;

            // Guess nnz(L) and nnz(U)
            sym.unz = sym.lnz = 4 * (A.ColumnPointers[n]) + n;
        }
Exemple #5
0
        /// <summary>
        /// Symbolic ordering and analysis for LU.
        /// </summary>
        /// <param name="order"></param>
        /// <param name="A"></param>
        private void SymbolicAnalysis(ColumnOrdering order, CompressedColumnStorage <double> A)
        {
            var sym = this.symFactor = new SymbolicFactorization();

            // Fill-reducing ordering
            sym.q = AMD.Generate(A, order);

            // Guess nnz(L) and nnz(U)
            sym.unz = sym.lnz = 4 * (A.ColumnPointers[n]) + n;
        }
Exemple #6
0
        /// <summary>
        /// Symbolic ordering and analysis for LU.
        /// </summary>
        /// <param name="order"></param>
        /// <param name="A"></param>
        /// <returns></returns>
        static SymbolicFactorization SymbolicAnalysis(int order, SparseMatrix A)
        { // ori: cs_sqr
            int n = A.n;

            SymbolicFactorization S = new SymbolicFactorization(); // allocate result S

            S.q = Ordering.AMD(order, A);                          // fill-reducing ordering

            if (order != 0 && S.q == null)
            {
                return(null);
            }

            S.unz = 4 * (A.p[n]) + n; // For LU factorization only
            S.lnz = S.unz;            // Guess nnz(L) and nnz(U)

            return(S);                // return result S
        }
Exemple #7
0
        /// <summary>
        /// Symbolic ordering and analysis for QR
        /// </summary>
        static SymbolicFactorization SymbolicAnalysis(int order, SparseMatrix A)
        { // ori: cs_sqr
            int  n = A.n, k;
            bool ok = true;

            int[] post;

            SymbolicFactorization S = new SymbolicFactorization(); // allocate result S

            S.q = Ordering.AMD(order, A);                          // fill-reducing ordering

            if (order != 0 && S.q == null)
            {
                return(null);
            }

            SparseMatrix C = order > 0 ? (SparseMatrix)A.Permute(null, S.q, false) : A;

            S.parent = Common.EliminationTree(C, true);              // etree of C'*C, where C=A(:,q)
            post     = Common.TreePostorder(S.parent, n);
            S.cp     = Common.ColumnCounts(C, S.parent, post, true); // col counts chol(C'*C)

            ok = C != null && S.parent != null && S.cp != null && CountV(C, S);

            if (ok)
            {
                for (S.unz = 0, k = 0; k < n; k++)
                {
                    S.unz += S.cp[k];
                }
            }

            ok = ok && S.lnz >= 0 && S.unz >= 0; // int overflow guard

            return(ok ? S : null);               // return result S
        }
Exemple #8
0
        /// <summary>
        /// Ordering and symbolic analysis for a LDL' factorization.
        /// </summary>
        /// <param name="order">Column ordering.</param>
        /// <param name="A">Matrix to factorize.</param>
        private void SymbolicAnalysis(ColumnOrdering order, CompressedColumnStorage <double> A)
        {
            int n = A.ColumnCount;

            var sym = this.S = new SymbolicFactorization();

            var ap = A.ColumnPointers;
            var ai = A.RowIndices;

            // P = amd(A+A') or natural
            var P    = AMD.Generate(A, order);
            var Pinv = Permutation.Invert(P);

            // 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];

            int i, k, p, kk, p2;

            for (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
                kk        = (P != null) ? (P[k]) : (k); // kth original, or permuted, column
                p2        = ap[kk + 1];
                for (p = ap[kk]; p < p2; p++)
                {
                    // A(i,k) is nonzero (original or permuted A)
                    i = (Pinv != null) ? (Pinv[ai[p]]) : (ai[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 (k = 0; k < n; k++)
            {
                lp[k + 1] = lp[k] + lnz[k];
            }

            sym.parent = parent;
            sym.cp     = lp;
            sym.q      = P;
            sym.pinv   = Pinv;
        }
Exemple #9
0
        /// <summary>
        /// Compute the Numeric Cholesky factorization, L = chol (A, [pinv parent cp]).
        /// </summary>
        /// <returns>Numeric Cholesky factorization</returns>
        public static NumericFactorization Factorize(SparseMatrix A, SymbolicFactorization S)
        {
            Complex d, lki;

            Complex[] Lx, x, Cx;
            int       top, i, p, k;

            int[] Li, Lp, cp, pinv, s, c, parent, Cp, Ci;

            SparseMatrix         L, C;
            NumericFactorization N = new NumericFactorization(); // allocate result

            int n = A.n;

            c = new int[n];     // get int workspace
            s = new int[n];
            x = new Complex[n]; // get double workspace

            cp     = S.cp;
            pinv   = S.pinv;
            parent = S.parent;

            C = pinv != null?A.PermuteSym(pinv, true) : A;

            Cp = C.p;
            Ci = C.i;
            Cx = C.x;

            N.L = L = new SparseMatrix(n, n, cp[n], true); // allocate result
            Lp  = L.p;
            Li  = L.i;
            Lx  = L.x;

            for (k = 0; k < n; k++)
            {
                Lp[k] = c[k] = cp[k];
            }
            for (k = 0; k < n; k++) // compute L(k,:) for L*L' = C
            {
                // Nonzero pattern of L(k,:)
                top  = Common.EReach(C, k, parent, s, c); // find pattern of L(k,:)
                x[k] = 0;                                 // x (0:k) is now zero
                for (p = Cp[k]; p < Cp[k + 1]; p++)       // x = full(triu(C(:,k)))
                {
                    if (Ci[p] <= k)
                    {
                        x[Ci[p]] = Cx[p];
                    }
                }
                d    = x[k]; // d = C(k,k)
                x[k] = 0;    // clear x for k+1st iteration

                // Triangular solve
                for (; top < n; top++)       // solve L(0:k-1,0:k-1) * x = C(:,k)
                {
                    i    = s[top];           // s [top..n-1] is pattern of L(k,:)
                    lki  = x[i] / Lx[Lp[i]]; // L(k,i) = x (i) / L(i,i)
                    x[i] = 0;                // clear x for k+1st iteration
                    for (p = Lp[i] + 1; p < c[i]; p++)
                    {
                        x[Li[p]] -= Lx[p] * lki;
                    }
                    d    -= lki * Complex.Conjugate(lki); // d = d - L(k,i)*L(k,i)
                    p     = c[i]++;
                    Li[p] = k;                            // store L(k,i) in column i
                    Lx[p] = Complex.Conjugate(lki);
                }
                // Compute L(k,k)
                if (d.Real <= 0 || d.Imaginary != 0)
                {
                    return(null); // not pos def
                }

                p     = c[k]++;
                Li[p] = k; // store L(k,k) = sqrt (d) in column k
                Lx[p] = Complex.Sqrt(d);
            }
            Lp[n] = cp[n]; // finalize L

            return(N);     // success
        }
Exemple #10
0
        /// <summary>
        /// Sparse QR factorization [V,beta,pinv,R] = qr (A)
        /// </summary>
        static NumericFactorization Factorize(SparseMatrix A, SymbolicFactorization S)
        {
            double[] Beta;
            int      i, p, p1, top, len, col;

            int m = A.m;
            int n = A.n;

            int[]     Ap = A.p;
            int[]     Ai = A.i;
            Complex[] Ax = A.x;

            int[] q      = S.q;
            int[] parent = S.parent;
            int[] pinv   = S.pinv;
            int   m2     = S.m2;

            int vnz = S.lnz;
            int rnz = S.unz;

            int[] leftmost = S.leftmost;

            int[]     w = new int[m2 + n]; // get int workspace
            Complex[] x = new Complex[m2]; // get double workspace

            int s = m2;                    // offset into w

            SparseMatrix         R, V;
            NumericFactorization N = new NumericFactorization(); // allocate result

            N.L = V = new SparseMatrix(m2, n, vnz, true);        // allocate result V
            N.U = R = new SparseMatrix(m2, n, rnz, true);        // allocate result R
            N.B = Beta = new double[n];                          // allocate result Beta

            int[]     Rp = R.p;
            int[]     Ri = R.i;
            Complex[] Rx = R.x;

            int[]     Vp = V.p;
            int[]     Vi = V.i;
            Complex[] Vx = V.x;

            for (i = 0; i < m2; i++)
            {
                w[i] = -1; // clear w, to mark nodes
            }

            rnz = 0; vnz = 0;
            for (int k = 0; k < n; k++) // compute V and R
            {
                Rp[k]     = rnz;        // R(:,k) starts here
                Vp[k]     = p1 = vnz;   // V(:,k) starts here
                w[k]      = k;          // add V(k,k) to pattern of V
                Vi[vnz++] = k;
                top       = n;
                col       = q != null ? q[k] : k;
                for (p = Ap[col]; p < Ap[col + 1]; p++)     // find R(:,k) pattern
                {
                    i = leftmost[Ai[p]];                    // i = min(find(A(i,q)))
                    for (len = 0; w[i] != k; i = parent[i]) // traverse up to k
                    {
                        //len++;
                        w[s + len++] = i;
                        w[i]         = k;
                    }
                    while (len > 0)
                    {
                        --top;
                        --len;
                        w[s + top] = w[s + len]; // push path on stack
                    }
                    i    = pinv[Ai[p]];          // i = permuted row of A(:,col)
                    x[i] = Ax[p];                // x (i) = A(:,col)
                    if (i > k && w[i] < k)       // pattern of V(:,k) = x (k+1:m)
                    {
                        Vi[vnz++] = i;           // add i to pattern of V(:,k)
                        w[i]      = k;
                    }
                }
                for (p = top; p < n; p++)               // for each i in pattern of R(:,k)
                {
                    i = w[s + p];                       // R(i,k) is nonzero
                    ApplyHouseholder(V, i, Beta[i], x); // apply (V(i),Beta(i)) to x
                    Ri[rnz]   = i;                      // R(i,k) = x(i)
                    Rx[rnz++] = x[i];
                    x[i]      = 0;
                    if (parent[i] == k)
                    {
                        vnz = V.Scatter(i, 0, w, null, k, V, vnz);
                    }
                }
                for (p = p1; p < vnz; p++) // gather V(:,k) = x
                {
                    Vx[p]    = x[Vi[p]];
                    x[Vi[p]] = 0;
                }
                Ri[rnz]   = k;                                                // R(k,k) = norm (x)
                Rx[rnz++] = CreateHouseholder(Vx, p1, ref Beta[k], vnz - p1); // [v,beta]=house(x)
            }
            Rp[n] = rnz;                                                      // finalize R
            Vp[n] = vnz;                                                      // finalize V

            return(N);                                                        // success
        }
Exemple #11
0
        /// <summary>
        /// Compute nnz(V) = S.lnz, S.pinv, S.leftmost, S.m2 from A and S.parent
        /// </summary>
        static bool CountV(SparseMatrix A, SymbolicFactorization S)
        {
            int i, k, p, pa, n = A.n, m = A.m;

            int[] Ap = A.p, Ai = A.i, head,
            tail, nque, pinv, leftmost, w, parent = S.parent;

            S.pinv     = pinv = new int[m + n]; // allocate pinv,
            S.leftmost = leftmost = new int[m]; // and leftmost

            w    = new int[m];                  // get workspace
            head = new int[n];
            tail = new int[n];
            nque = new int[n]; // Initialized to 0's

            for (k = 0; k < n; k++)
            {
                head[k] = -1;                     // queue k is empty
            }
            for (k = 0; k < n; k++)
            {
                tail[k] = -1;
            }
            for (i = 0; i < m; i++)
            {
                leftmost[i] = -1;
            }
            for (k = n - 1; k >= 0; k--)
            {
                for (p = Ap[k]; p < Ap[k + 1]; p++)
                {
                    leftmost[Ai[p]] = k; // leftmost[i] = min(find(A(i,:)))
                }
            }
            for (i = m - 1; i >= 0; i--) // scan rows in reverse order
            {
                pinv[i] = -1;            // row i is not yet ordered
                k       = leftmost[i];
                if (k == -1)
                {
                    continue;          // row i is empty
                }
                if (nque[k]++ == 0)
                {
                    tail[k] = i;   // first row in queue k
                }
                w[i]    = head[k]; // put i at head of queue k
                head[k] = i;
            }
            S.lnz = 0;
            S.m2  = m;
            for (k = 0; k < n; k++) // find row permutation and nnz(V)
            {
                i = head[k];        // remove row i from queue k
                S.lnz++;            // count V(k,k) as nonzero
                if (i < 0)
                {
                    i = S.m2++; // add a fictitious row
                }
                pinv[i] = k;    // associate row i with V(:,k)
                if (--nque[k] <= 0)
                {
                    continue;               // skip if V(k+1:m,k) is empty
                }
                S.lnz += nque[k];           // nque [k] is nnz (V(k+1:m,k))
                if ((pa = parent[k]) != -1) // move all rows to parent of k
                {
                    if (nque[pa] == 0)
                    {
                        tail[pa] = tail[k];
                    }
                    w[tail[k]] = head[pa];
                    head[pa]   = w[i];
                    nque[pa]  += nque[k];
                }
            }
            for (i = 0; i < m; i++)
            {
                if (pinv[i] < 0)
                {
                    pinv[i] = k++;
                }
            }

            return(true);
        }
Exemple #12
0
        // [L,U,pinv]=lu(A, [q lnz unz]). lnz and unz can be guess
        static NumericFactorization Factorize(SparseMatrix A, SymbolicFactorization S, double tol)
        {
            int i, n = A.n;

            int[] q = S.q;

            int lnz = S.lnz;
            int unz = S.unz;

            int[] pinv;

            NumericFactorization N = new NumericFactorization(); // allocate result

            SparseMatrix L, U;

            N.L    = L = new SparseMatrix(n, n, lnz, true); // allocate result L
            N.U    = U = new SparseMatrix(n, n, unz, true); // allocate result U
            N.pinv = pinv = new int[n];                     // allocate result pinv

            double[] x  = new double[n];                    // get double workspace
            int[]    xi = new int[2 * n];                   // get int workspace

            for (i = 0; i < n; i++)
            {
                pinv[i] = -1; // no rows pivotal yet
            }

            lnz = unz = 0;

            int    ipiv, top, p, col;
            double pivot, a, t;

            int[]    Li, Ui, Lp = L.p, Up = U.p;
            double[] Lx, Ux;

            for (int k = 0; k < n; k++) // compute L(:,k) and U(:,k)
            {
                // Triangular solve
                Lp[k] = lnz; // L(:,k) starts here
                Up[k] = unz; // U(:,k) starts here
                if ((lnz + n > L.nzmax && !L.Resize(2 * L.nzmax + n)) ||
                    (unz + n > U.nzmax && !U.Resize(2 * U.nzmax + n)))
                {
                    return(null);
                }
                Li  = L.i;
                Lx  = L.x;
                Ui  = U.i;
                Ux  = U.x;
                col = q != null ? (q[k]) : k;
                top = Triangular.SolveSp(L, A, col, xi, x, pinv, true);  // x = L\A(:,col)

                // Find pivot
                ipiv = -1;
                a    = -1;
                for (p = top; p < n; p++)
                {
                    i = xi[p];       // x(i) is nonzero
                    if (pinv[i] < 0) // row i is not yet pivotal
                    {
                        if ((t = Math.Abs(x[i])) > a)
                        {
                            a    = t; // largest pivot candidate so far
                            ipiv = i;
                        }
                    }
                    else // x(i) is the entry U(pinv[i],k)
                    {
                        Ui[unz]   = pinv[i];
                        Ux[unz++] = x[i];
                    }
                }
                if (ipiv == -1 || a <= 0)
                {
                    return(null);
                }

                if (pinv[col] < 0 && Math.Abs(x[col]) >= a * tol)
                {
                    ipiv = col;
                }

                // Divide by pivot
                pivot      = x[ipiv];     // the chosen pivot
                Ui[unz]    = k;           // last entry in U(:,k) is U(k,k)
                Ux[unz++]  = pivot;
                pinv[ipiv] = k;           // ipiv is the kth pivot row
                Li[lnz]    = ipiv;        // first entry in L(:,k) is L(k,k) = 1
                Lx[lnz++]  = 1;
                for (p = top; p < n; p++) // L(k+1:n,k) = x / pivot
                {
                    i = xi[p];
                    if (pinv[i] < 0)              // x(i) is an entry in L(:,k)
                    {
                        Li[lnz]   = i;            // save unpermuted row in L
                        Lx[lnz++] = x[i] / pivot; // scale pivot column
                    }
                    x[i] = 0;                     // x [0..n-1] = 0 for next k
                }
            }

            // Finalize L and U
            Lp[n] = lnz;
            Up[n] = unz;
            Li    = L.i; // fix row indices of L for final pinv
            for (p = 0; p < lnz; p++)
            {
                Li[p] = pinv[Li[p]];
            }
            L.Resize(0); // remove extra space from L and U
            U.Resize(0);

            return(N); // success
        }
Exemple #13
0
        public static CCS GenerateP_Delta_Mpc(Model target, LoadCase loadCase, IRrefFinder rrefFinder)
        {
            target.ReIndexNodes();

            var n = target.Nodes.Count;

            var boundaryConditions = GetModelBoundaryConditions(target, loadCase);


            var lastRow = 0;

            #region step 1
            //step 1: combine all eqs to one system

            //var filledCols = new bool[6 * n];

            var extraEqCount = 0;

            foreach (var mpcElm in target.MpcElements)
            {
                if (mpcElm.AppliesForLoadCase(loadCase))
                {
                    extraEqCount += mpcElm.GetExtraEquationsCount();
                }
            }

            extraEqCount += boundaryConditions.RowCount;

            var allEqsCrd = new CoordinateStorage <double>(extraEqCount, n * 6 + 1, 1);//rows: extra eqs, cols: 6*n+1 (+1 is for right hand side)

            foreach (var mpcElm in target.MpcElements)
            {
                if (mpcElm.AppliesForLoadCase(loadCase))
                {
                    var extras = mpcElm.GetExtraEquations();

                    extras.EnumerateMembers((row, col, val) =>
                    {
                        allEqsCrd.At(row + lastRow, col, val);
                    });

                    lastRow += extras.RowCount;
                }
            }

            {
                boundaryConditions.EnumerateMembers((row, col, val) =>
                {
                    allEqsCrd.At(row + lastRow, col, val);
                });

                lastRow += boundaryConditions.RowCount;
            }

            var allEqs = allEqsCrd.ToCCs();

            #endregion

            #region comment

            /*
             #region step 2
             * //step 2: create adjacency matrix of variables
             *
             * //step 2-1: find nonzero pattern
             * var allEqsNonzeroPattern = allEqs.Clone();
             *
             * for (var i = 0; i < allEqsNonzeroPattern.Values.Length; i++)
             *  allEqsNonzeroPattern.Values[i] = 1;
             *
             * //https://math.stackexchange.com/questions/2340450/extract-independent-sub-systems-from-a-bigger-linear-eq-system
             * var tmp = allEqsNonzeroPattern.Transpose();
             *
             * var variableAdj = tmp.Multiply(allEqsNonzeroPattern);
             #endregion
             *
             #region step 3
             * //extract parts
             * var parts = EnumerateGraphParts(variableAdj);
             *
             #endregion
             *
             #region step 4
             * {
             *
             *  allEqs.EnumerateColumns((colNum, vals) =>
             *  {
             *      if (vals.Count == 0)
             *      Console.WriteLine("Col {0} have {1} nonzeros", colNum, vals.Count);
             *  });
             *
             *  var order = ColumnOrdering.MinimumDegreeAtPlusA;
             *
             *  // Partial pivoting tolerance (0.0 to 1.0)
             *  double tolerance = 1.0;
             *
             *  var lu = CSparse.Double.Factorization.SparseLU.Create(allEqs, order, tolerance);
             *
             * }
             *
             #endregion
             */

            #endregion


            rrefFinder.CalculateRref(allEqs);


            var q = AMD.Generate(allEqs, ColumnOrdering.MinimumDegreeAtA);

            var s = new SymbolicFactorization()
            {
                q = q
            };



            var qr = CSparse.Double.Factorization.SparseQR.Create(allEqs, ColumnOrdering.MinimumDegreeAtA);

            var r = ((CCS)ReflectionUtils.GetFactorR(qr, "R"));
            //var q = ((CCS)ReflectionUtils.GetFactorR(qr, "Q"));
            //var s = ((SymbolicFactorization)ReflectionUtils.GetFactorR(qr, "S"));



            var idependents = new bool[allEqs.RowCount];

            var rd = allEqs.ToDenseMatrix();


            r.EnumerateMembers((row, col, val) =>
            {
                if (row == col)
                {
                    if (Math.Abs(val) < 1e-6)
                    {
                        return;
                    }
                }

                idependents[row] = true;
            }
                               );


            //var t=qr.
            throw new NotImplementedException();

            //return buf.ToCCs();
        }