Esempio n. 1
0
        public void TestSolveOverdetermined()
        {
            // Load matrix from a file.
            var A = ResourceLoader.Get <double>("general-40x20.mat");

            int m = A.RowCount;
            int n = A.ColumnCount;

            Assert.IsTrue(m > n);

            // Create test data.
            var x = Helper.CreateTestVector(n);
            var b = Helper.Multiply(A, x);
            var r = Vector.Clone(b);

            var qr = SparseQR.Create(A, ColumnOrdering.MinimumDegreeAtA);

            // Compute min norm(Ax - b).
            qr.Solve(b, x);

            // Compute residual r = b - Ax.
            A.Multiply(-1.0, x, 1.0, r);

            Assert.IsTrue(Vector.Norm(r) < EPS);
        }
Esempio n. 2
0
        private static void QrTest()
        {
            var coord = new CoordinateStorage <double>(7, 7, 1);

            coord.At(0, 2, 1);
            coord.At(0, 3, 1);
            coord.At(0, 4, 3);
            coord.At(0, 6, 2);

            coord.At(1, 2, 2);
            coord.At(1, 3, 6);
            coord.At(1, 4, 1);
            coord.At(1, 6, 5);

            coord.At(2, 2, 3);
            coord.At(2, 3, 7);
            coord.At(2, 4, 4);
            coord.At(2, 6, 7);

            var ccs = coord.ToCCs();

            var qr = SparseQR.Create(ccs, ColumnOrdering.Natural);

            //var r = GetFactorR(qr, "R").ToDenseMatrix();
            //var q = GetFactorR(qr, "Q").ToDenseMatrix();


            //var t = (q * r.Transpose());
        }
Esempio n. 3
0
        public void TestSolveUnderdetermined()
        {
            // Load matrix from a file.
            var A = ResourceLoader.Get <double>("general-20x40.mat");

            int m = A.RowCount;
            int n = A.ColumnCount;

            Assert.IsTrue(m < n);

            // Create test data.
            var x = Helper.CreateTestVector(n);
            var b = Helper.Multiply(A, x);
            var r = Vector.Clone(b);

            var qr = SparseQR.Create(A, ColumnOrdering.MinimumDegreeAtA);

            // Assuming A has full rank m, we have N(A) = n - m degrees of freedom.
            // Compute solution x with min norm(Ax - b).
            qr.Solve(b, x);

            // Compute residuals.
            A.Multiply(-1.0, x, 1.0, r);

            Assert.IsTrue(Vector.Norm(r) < EPS);
        }
Esempio n. 4
0
        public static Vector SolveQR(CompressedColumnStorage <double> A, Vector x, Vector b, out bool status, out string algorithm)
        {
            var orderings = new[] { CSparse.ColumnOrdering.MinimumDegreeAtA, CSparse.ColumnOrdering.MinimumDegreeAtPlusA, CSparse.ColumnOrdering.MinimumDegreeStS, CSparse.ColumnOrdering.Natural };

            status    = false;
            algorithm = "QR";
            foreach (var ordering in orderings)
            {
                try
                {
                    if (A.RowCount == A.ColumnCount)
                    {
                        var qr = new SparseQR(A, ordering);
                        var xc = x.Clone();
                        var bc = b.Clone();
                        qr.Solve(bc.ToDouble(), xc.ToDouble());
                        algorithm = "QR/" + ordering;
                        status    = true;
                        return(xc);
                    }
                }
                catch (Exception e)
                {
                    status = false;
                }
            }
            return(x);
        }
Esempio n. 5
0
        public void TestSolveTranspose()
        {
            // Load matrix from a file.
            var A = ResourceLoader.Get <Complex>("general-40x40.mat");

            Assert.AreEqual(A.RowCount, A.ColumnCount);

            var AT = A.Transpose();

            // Create test data.
            var x = Helper.CreateTestVector(A.ColumnCount);
            var b = Helper.Multiply(AT, x);
            var r = Vector.Clone(b);

            // Create LU factorization.
            var qr = SparseQR.Create(A, ColumnOrdering.MinimumDegreeAtA);

            // Solve A'x = b.
            qr.SolveTranspose(b, x);

            // Compute residual r = b - A'x.
            AT.Multiply(-1.0, x, 1.0, r);

            Assert.IsTrue(Vector.Norm(r.Length, r) < EPS);
        }
Esempio n. 6
0
        public void TestEmptyFactorize(int rows, int columns)
        {
            var A = new SparseMatrix(rows, columns, 0);

            var qr = SparseQR.Create(A, ColumnOrdering.MinimumDegreeAtA);

            Assert.NotNull(qr);
            Assert.IsTrue(qr.NonZerosCount == -rows);
        }
Esempio n. 7
0
        public void TestSolve()
        {
            // Load matrix from a file.
            var A = ResourceLoader.Get <double>("general-40x40.mat");

            Assert.AreEqual(A.RowCount, A.ColumnCount);

            // Create test data.
            var x = Helper.CreateTestVector(A.ColumnCount);
            var b = Helper.Multiply(A, x);
            var r = Vector.Clone(b);

            var qr = SparseQR.Create(A, ColumnOrdering.MinimumDegreeAtA);

            // Solve Ax = b.
            qr.Solve(b, x);

            // Compute residual r = b - Ax.
            A.Multiply(-1.0, x, 1.0, r);

            Assert.IsTrue(Vector.Norm(r) < EPS);
        }
        /// <inheritdoc />
        public void Initialize()
        {
            var matrix = A;
            var sp     = new Stopwatch();

            sp.Start();

            qr =
                SparseQR.Create(matrix, ColumnOrdering.MinimumDegreeAtPlusA);


            IsInitialized = true;

            sp.Stop();

            if (Target != null)
            {
                Target.Trace.Write(TraceRecord.Create(BriefFiniteElementNet.Common.TraceLevel.Info,
                                                      string.Format(CultureInfo.CurrentCulture, "QR decomposition of matrix took about {0:#,##0} ms",
                                                                    sp.ElapsedMilliseconds)));
            }
        }
Esempio n. 9
0
        public void TestSolveTransposeUnderdetermined()
        {
            // Load matrix from a file.
            var A = ResourceLoader.Get <double>("general-20x40.mat");

            Assert.IsTrue(A.RowCount < A.ColumnCount);

            var AT = A.Transpose();

            // Create test data.
            var x = Helper.CreateTestVector(A.RowCount);
            var b = Helper.Multiply(AT, x);
            var r = Vector.Clone(b);

            var qr = SparseQR.Create(A, ColumnOrdering.MinimumDegreeAtA);

            qr.SolveTranspose(b, x);

            // Compute residuals.
            AT.Multiply(-1.0, x, 1.0, r);

            Assert.IsTrue(Vector.Norm(r.Length, r) < EPS);
        }
        SymbolicFactorization GetSymbolicFactorization(SparseQR qr)
        {
            var info = typeof(SparseQR).GetField("S", BindingFlags.Instance | BindingFlags.NonPublic);

            return(info.GetValue(qr) as SymbolicFactorization);
        }
        CompressedColumnStorage <double> GetFactorQ(SparseQR qr)
        {
            var info = typeof(SparseQR).GetField("Q", BindingFlags.Instance | BindingFlags.NonPublic);

            return(info.GetValue(qr) as CompressedColumnStorage <double>);
        }
        public Tuple <SparseMatrix, double[]> CalculateDisplacementPermutation(SparseMatrix a)
        {
            if (a.RowCount < a.ColumnCount)
            {
                // See https://github.com/wo80/CSparse.NET/issues/7#issuecomment-317268696
                //
                // 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 square!
                //
                // Since the matrix entries are in column order, reshaping is just a matter of
                // setting the correct row count and then reusing the existing storage arrays.

                a = new SparseMatrix(a.ColumnCount, a.ColumnCount, a.Values, a.RowIndices, a.ColumnPointers);
            }

            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 = p_d.ToCCs();

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

            var tol = 1e-6;

            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. 14
0
 public DisposableSparseQR(SparseMatrix matrix)
 {
     qr = SparseQR.Create(matrix, ColumnOrdering.MinimumDegreeAtA);
 }
Esempio n. 15
0
        public static object GetFactorR(SparseQR qr, string field)
        {
            var info = typeof(SparseQR).GetField(field, BindingFlags.Instance | BindingFlags.NonPublic);

            return(info.GetValue(qr));// as CompressedColumnStorage<double>;
        }