Esempio n. 1
0
        public static SparseEqSystem Generate(CSparse.Double.SparseMatrix eqSystem)
        {
            var buf     = new SparseEqSystem();
            var lastCol = eqSystem.ColumnCount;

            var eqs     = buf.Equations = new SparseRow[eqSystem.RowCount];
            var colNnzs = buf.ColumnNonzeros = new int[eqSystem.ColumnCount];

            buf.RowNonzeros = new int[eqSystem.RowCount];


            for (var i = 0; i < eqs.Length; i++)
            {
                buf.Equations[i] = new SparseRow(1);
            }


            foreach (var tuple in eqSystem.EnumerateIndexed())
            {
                var rw  = tuple.Item1; //tuple.Item1;
                var col = tuple.Item2; //tuple.Item2;
                var val = tuple.Item3;

                eqs[rw].Add(col, val);

                if (col != lastCol)
                {
                    colNnzs[col]++;
                }
            }


            for (var i = 0; i < eqs.Length; i++)
            {
                buf.RowNonzeros[i] = buf.Equations[i].CalcNnz(lastCol);
            }

            buf.RowCount    = eqSystem.RowCount;
            buf.ColumnCount = eqSystem.ColumnCount;

            return(buf);
        }
        public CCS CalculateRref(CCS a)
        {
            var singleMemberColumns = 00;

            var aTran = a.Transpose();

            var n = a.ColumnCount;

            for (var i = 0; i < n; i++)
            {
                if (a.GetNnzcForColumn(i) == 1)
                {
                    singleMemberColumns++;
                }
            }

            if (singleMemberColumns == a.RowCount)
            {
                return((CCS)a.Clone());
            }

            var pat  = new CoordinateStorage <double>(a.RowCount, a.ColumnCount - 1, 1);
            var bCrd = new CoordinateStorage <double>(a.RowCount, a.ColumnCount - 1, 1);//a matrix without last column

            a.EnumerateIndexed((row, col, val) =>
            {
                if (col != a.ColumnCount - 1)
                {
                    pat.At(row, col, 1);
                    bCrd.At(row, col, val);
                }
            });
            //nonzero pattern of a, except last column

            var b     = bCrd.ToCCs();
            var bTran = b.Transpose();

            var patt   = pat.ToCCs();
            var pattTr = patt.Transpose();


            var varGraph = pattTr.Multiply(patt);

            varGraph.Values.FillWith(1);

            var eqnGraph = patt.Multiply(pattTr);

            eqnGraph.Values.FillWith(1);



            if (!varGraph.IsSymmetric() || !eqnGraph.IsSymmetric())
            {
                throw new Exception();
            }

            var eqnParts = CalcUtil.EnumerateGraphParts(eqnGraph);

            var varParts = CalcUtil.EnumerateGraphParts(varGraph);

            var varVisited = new bool[varGraph.ColumnCount];

            foreach (var eqnPart in eqnParts)
            {
                //i'th independent system.
                var firstEq = eqnPart.First();

                int firstVarOfFirstEq = -1;

                /*
                 * patt.EnumerateRowMembers(firstEq, (row, col, val) => {
                 * if (firstValOfFirstEq != -1)
                 *  firstValOfFirstEq = col;
                 * );
                 */


                pattTr.EnumerateColumnMembers(firstEq, (row, col, val) =>
                {
                    if (firstVarOfFirstEq == -1)
                    {
                        firstVarOfFirstEq = row;
                    }
                });

                //var firstVar = patt.EnumerateColumnMembers()

                var connectedVariables = CalcUtil.DepthFirstSearch(varGraph, varVisited, firstVarOfFirstEq);

                connectedVariables.Sort();

                var vp = new Dictionary <int, int>();//variablePermute

                //vp[a] = b, a: number of variable in original system
                // b: index of variable in connectedVariables

                for (var i = 0; i < connectedVariables.Count; i++)
                {
                    vp[connectedVariables[i]] = i;
                }


                var denseSubSytem = new Matrix(eqnPart.Count, connectedVariables.Count + 1);////i'th independent system as dense

                // Convert sparse to dense.
                //var dns = Matrix.OfMatrix(aTran);

                for (var i = 0; i < eqnPart.Count; i++)
                {
                    //insert i'th eqn into denseSubSytem

                    var row = i;

                    var st = aTran.ColumnPointers[i];
                    var en = aTran.ColumnPointers[i + 1];

                    for (int j = st; j < en; j++)
                    {
                        var col = aTran.RowIndices[j];

                        if (col == a.ColumnCount - 1)
                        {
                            continue;
                        }

                        var val = aTran.Values[j];


                        denseSubSytem[i, vp[col]] = val;
                    }
                }
            }

            throw new NotImplementedException();
        }
        public Tuple <CCS, double[]> CalculateDisplacementPermutation(CCS a)
        {
            //based on this solution : https://github.com/wo80/CSparse.NET/issues/7#issuecomment-317268696

            if (a.RowCount < a.ColumnCount)
            {
                //For a matrix A with rows < columns, SparseQR does a factorization of the transpose A'
                //so we add zero rows to A and make it rectangular!

                var a2 = new CoordinateStorage <double>(a.ColumnCount, a.ColumnCount, a.NonZerosCount);

                foreach (var t in a.EnumerateIndexed())
                {
                    a2.At(t.Item1, t.Item2, t.Item3);
                }

                a = a2.ToCCs();
            }

            SparseMatrix buf;

            var n = a.RowCount;
            var m = a.ColumnCount;

            var order = ColumnOrdering.MinimumDegreeAtA;

            var sp = System.Diagnostics.Stopwatch.StartNew();

            var qr = SparseQR.Create(a, order);

            var t2 = sp.ElapsedMilliseconds;


            var r = GetFactorR(qr);
            var q = GetFactorQ(qr);

            var leads = new int[a.RowCount];

            leads.FillWith(-1);

            var epsilon = 1e-8;

            foreach (var t in r.EnumerateIndexed())
            {
                if (Math.Abs(t.Item3) > epsilon)
                {
                    if (leads[t.Item1] == -1)
                    {
                        leads[t.Item1] = t.Item2;
                    }
                    else
                    {
                        leads[t.Item1] = Math.Min(leads[t.Item1], t.Item2);
                    }
                }
            }

            var leadCount = leads.Count(i => i != -1);

            {
                var nnzApprox = leadCount;
                var p1Crd     = new CoordinateStorage <double>(leadCount, r.RowCount, nnzApprox);
                var p2Crd     = new CoordinateStorage <double>(r.ColumnCount, leadCount, nnzApprox);
                var p2pCrd    = new CoordinateStorage <double>(r.ColumnCount, r.ColumnCount - leadCount, nnzApprox);

                var cnt1 = 0;
                var cnt2 = 0;

                for (var i = 0; i < leads.Length; i++)
                {
                    if (leads[i] != -1)
                    {
                        var j = leads[i];

                        p1Crd.At(cnt1, i, 1);
                        p2Crd.At(j, cnt1, 1);

                        cnt1++;
                    }

                    if (leads[i] == -1)
                    {
                        var j = i;// leads[i];

                        p2pCrd.At(j, cnt2, 1);

                        cnt2++;
                    }
                }

                var p1  = p1Crd.ToCCs();
                var p2  = p2Crd.ToCCs();
                var p2p = p2pCrd.ToCCs();

                //var rp = r.Transpose();

                var rdep = p1.Multiply(r).Multiply(p2);

                var rinDep = p1.Multiply(r).Multiply(p2p);



                var qr2 = SparseQR.Create(rdep, order);

                var t = sp.ElapsedMilliseconds;

                var right = new double[rinDep.RowCount];
                var sol   = new double[rinDep.RowCount];

                var bufCrd = new CoordinateStorage <double>(leadCount, a.ColumnCount - leadCount, leadCount);

                for (var j = 0; j < rinDep.ColumnCount; j++)
                {
                    //put the j'th column of r into the rightSide

                    right.FillWith(0);

                    {
                        var col = j;

                        var st  = rinDep.ColumnPointers[j];
                        var end = rinDep.ColumnPointers[j + 1];

                        for (var ii = st; ii < end; ii++)
                        {
                            var row = rinDep.RowIndices[ii];

                            var val = rinDep.Values[ii];

                            right[row] = val;
                        }
                    }

                    qr2.Solve(right, sol);

                    for (var i = 0; i < rdep.RowCount; i++)
                    {
                        bufCrd.At(i, j, sol[i]);
                    }
                }

                buf = bufCrd.ToCCs();
            }

            //var top = buf.ToDenseMatrix();

            var buft = buf.Transpose();


            var masterCount = a.ColumnCount - 1 - leadCount;

            //var p_d_dense = new Matrix(a.ColumnCount - 1, masterCount);

            var p_d = new CoordinateStorage <double>(a.ColumnCount - 1, masterCount, 1);

            var rightSideDense = new double[a.ColumnCount - 1];
            var rightSide      = new double[a.ColumnCount - 1];

            var cnt  = 0;
            var cnt3 = 0;

            for (var i = 0; i < a.ColumnCount - 1; i++)
            {
                if (leads[i] != -1)
                {
                    /*{//dense
                     *  var rw = top.ExtractRow(cnt).CoreArray;
                     *
                     *  var right = rw.Last();
                     *  Array.Resize(ref rw, rw.Length - 1);
                     *
                     *  for (var j = 0; j < rw.Length; j++)
                     *  {
                     *      p_d_dense[i, j] = -rw[j];
                     *  }
                     *
                     *  rightSideDense[i] = -right;
                     * }*/

                    {//sparse
                        var right = 0.0;

                        foreach (var t in buft.EnumerateColumnMembers(cnt))//enumerate column members of transposed matrix
                        {
                            if (t.Item1 != p_d.ColumnCount)
                            {
                                p_d.At(i, t.Item1, -t.Item2);
                            }
                            else
                            {
                                right = t.Item2;
                            }
                        }

                        rightSide[i] = -right;
                    }


                    cnt++;
                }
                else
                {
                    {
                        var t = cnt3++;
                        //p_d_dense[i, t] = 1;
                        p_d.At(i, t, 1);
                    }
                }
            }

            //var top2 = p_d_dense;//.ToDenseMatrix();
            //var top3 = p_d.ToCCs().ToDenseMatrix();

            //var d = (top2 - top3);
            //var d2 = rightSide.Plus(rightSideDense, -1);


            var pdd = (CCS)p_d.ToCCs();

            return(Tuple.Create(pdd, rightSide));

            var tol = 1e-6;

            throw new NotImplementedException();
        }
Esempio n. 4
0
        public Tuple <CCS, double[]> CalculateDisplacementPermutation(CCS a)
        {
            //based on this solution : https://github.com/wo80/CSparse.NET/issues/7#issuecomment-317268696

            if (a.RowCount < a.ColumnCount)
            {
                //For a matrix A with rows < columns, SparseQR does a factorization of the transpose A'
                //so we add zero rows to A and make it rectangular!

                var a2 = new CoordinateStorage <double>(a.ColumnCount, a.ColumnCount, a.NonZerosCount);

                foreach (var t in a.EnumerateIndexed())
                {
                    a2.At(t.Item1, t.Item2, t.Item3);
                }

                a = a2.ToCCs();
            }

            //var adense = a.ToDenseMatrix();

            SparseMatrix buf;

            var n = a.RowCount;
            var m = a.ColumnCount;

            var order = ColumnOrdering.Natural;

            var sp = System.Diagnostics.Stopwatch.StartNew();

            var qr = SparseQR.Create(a, order);

            var t2 = sp.ElapsedMilliseconds;


            var r = GetFactorR(qr);
            var q = GetFactorQ(qr);
            var s = GetSymbolicFactorization(qr);

            var leads = new int[a.RowCount];

            leads.FillWith(-1);
            //leads[i] = columnIndex of first nonzero in i'th row of r fasctor
            //if leads[i] == -1, then there is no nonzero in row[i] then i'th equation in original a matrix in non usable
            //this will be used for rdep and rindep

            var epsilon = 1e-8;


            foreach (var r_item in r.EnumerateIndexed())
            {
                var rowNum = r_item.Item1;
                var colNum = r_item.Item2;
                var val    = r_item.Item3;


                if (Math.Abs(val) <= epsilon)
                {
                    ;                        //then row at
                }
                if (Math.Abs(val) > epsilon) //Then, if abs(R[i, i]) > tol, you found an independent row
                //Make sure to take row permutations into account (again, you can get the SymbolicFactorization containing row and column permutations using reflection)
                {
                    if (leads[rowNum] == -1)
                    {
                        leads[rowNum] = colNum;
                    }
                    else
                    {
                        leads[rowNum] = Math.Min(leads[rowNum], colNum);
                    }
                }
            }



            //throw new NotImplementedException("above section not right");

            var leadCount = leads.Count(i => i != -1);

            {
                var nnzApprox = leadCount;
                var p1Crd     = new CoordinateStorage <double>(leadCount, r.RowCount, nnzApprox);
                var p2Crd     = new CoordinateStorage <double>(r.ColumnCount, leadCount, nnzApprox);
                var p2pCrd    = new CoordinateStorage <double>(r.ColumnCount, r.ColumnCount - leadCount, nnzApprox);

                var cnt1 = 0;
                var cnt2 = 0;

                for (var i = 0; i < leads.Length; i++)
                {
                    if (leads[i] != -1)
                    {
                        var j = leads[i];

                        p1Crd.At(cnt1, i, 1);
                        p2Crd.At(j, cnt1, 1);

                        cnt1++;
                    }

                    if (leads[i] == -1)
                    {
                        var j = i;// leads[i];

                        p2pCrd.At(j, cnt2, 1);

                        cnt2++;
                    }
                }

                var p1  = p1Crd.ToCCs();
                var p2  = p2Crd.ToCCs();
                var p2p = p2pCrd.ToCCs();

                //var rp = r.Transpose();

                var rdep = p1.Multiply(r).Multiply(p2);

                var rinDep = p1.Multiply(r).Multiply(p2p);

                var qr2 = SparseQR.Create(rdep, order);

                var t = sp.ElapsedMilliseconds;

                var right = new double[rinDep.RowCount];
                var sol   = new double[rinDep.RowCount];

                var bufCrd = new CoordinateStorage <double>(leadCount, a.ColumnCount - leadCount, leadCount);

                for (var j = 0; j < rinDep.ColumnCount; j++)
                {
                    //put the j'th column of r into the rightSide

                    right.FillWith(0);

                    {
                        var col = j;

                        var st  = rinDep.ColumnPointers[j];
                        var end = rinDep.ColumnPointers[j + 1];

                        for (var ii = st; ii < end; ii++)
                        {
                            var row = rinDep.RowIndices[ii];

                            var val = rinDep.Values[ii];

                            right[row] = val;
                        }
                    }

                    qr2.Solve(right, sol);

                    for (var i = 0; i < rdep.RowCount; i++)
                    {
                        bufCrd.At(i, j, sol[i]);
                    }
                }

                buf = bufCrd.ToCCs();
            }

            //var top = buf.ToDenseMatrix();

            var buft = buf.Transpose();


            var masterCount = a.ColumnCount - 1 - leadCount;

            //var p_d_dense = new Matrix(a.ColumnCount - 1, masterCount);

            var p_d = new CoordinateStorage <double>(a.ColumnCount - 1, masterCount, 1);

            var rightSideDense = new double[a.ColumnCount - 1];
            var rightSide      = new double[a.ColumnCount - 1];

            var cnt  = 0;
            var cnt3 = 0;

            for (var i = 0; i < a.ColumnCount - 1; i++)
            {
                if (leads[i] != -1)
                {
                    /*{//dense
                     *  var rw = top.ExtractRow(cnt).CoreArray;
                     *
                     *  var right = rw.Last();
                     *  Array.Resize(ref rw, rw.Length - 1);
                     *
                     *  for (var j = 0; j < rw.Length; j++)
                     *  {
                     *      p_d_dense[i, j] = -rw[j];
                     *  }
                     *
                     *  rightSideDense[i] = -right;
                     * }*/

                    {//sparse
                        var right = 0.0;

                        //var rowNum = s.pinv[i];

                        foreach (var t in buft.EnumerateColumnMembers(cnt))//enumerate column members of transposed matrix
                        {
                            var rowNum = i;
                            var colNum = t.Item1;


                            //var colNum = s.q[t.Item1];

                            var value = t.Item2;

                            if (t.Item1 != p_d.ColumnCount)
                            {
                                p_d.At(rowNum, colNum, -value);
                            }
                            else
                            {
                                right = value;
                            }
                        }

                        //rightSide[s.cp[i]] = -right;
                        rightSide[i] = -right;
                    }


                    cnt++;
                }
                else
                {
                    var t = cnt3++;

                    var rowNum = i; // s.pinv[ i];
                    var colNum = t; // s.q[ t];

                    p_d.At(rowNum, colNum, 1);
                }
            }

            //var top2 = p_d_dense;//.ToDenseMatrix();
            //var top3 = p_d.ToCCs().ToDenseMatrix();

            //var d = (top2 - top3);
            //var d2 = rightSide.Plus(rightSideDense, -1);


            var pdd = (CCS)p_d.ToCCs();

            return(Tuple.Create(pdd, rightSide));

            var tol = 1e-6;

            throw new NotImplementedException();
        }