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(); }
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(); }