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); }
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()); }
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); }
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); }
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); }
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); }
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))); } }
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(); }
public DisposableSparseQR(SparseMatrix matrix) { qr = SparseQR.Create(matrix, ColumnOrdering.MinimumDegreeAtA); }
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>; }