private void ssor(ISparseRowAccessMatrix A, double[] xdata) { int n = A.RowCount; // M = (D+L) D^{-1} (D+L)^T // Solves (1/omega)*(D+L) y = b for (int i = 0; i < n; ++i) { // Do nothing if we get a divide by zero if (Math.Abs(diag[i]) == 0.0) { continue; } IntDoubleVectorPair Arow = A.GetRow(i); double[] Adat = Arow.data; int[] Aind = Arow.indices; double sum = 0; for (int j = 0; j < Aind.Length && Aind[j] < i; ++j) { sum += Adat[j] * xdata[Aind[j]]; } xdata[i] = (omega / diag[i]) * (xdata[i] - sum); } // Solves (omega/(2-omega))*D^{-1} z = y for (int i = 0; i < n; ++i) { // No need to do anything if (Math.Abs(diag[i]) == 0.0) { continue; } xdata[i] = (2 - omega) / omega * diag[i] * xdata[i]; } // Solves (1/omega)*(D+L)^T x = z for (int i = n - 1; i >= 0; --i) { // Do nothing if we get a divide by zero if (Math.Abs(diag[i]) == 0.0) { continue; } IntDoubleVectorPair Arow = A.GetRow(i); double[] Adat = Arow.data; int[] Aind = Arow.indices; double sum = 0; for (int j = diagInd[i] + 1; j < Aind.Length; ++j) { sum += Adat[j] * xdata[Aind[j]]; } xdata[i] = (omega / diag[i]) * (xdata[i] - sum); } }
public override void Setup(IMatrix A) { int n = A.RowCount; diag = new double[n]; diagInd = new int[n]; // Get the diagonal and its indices if (A is ISparseRowAccessMatrix) { for (int i = 0; i < n; ++i) { IntDoubleVectorPair Arow = ((ISparseRowAccessMatrix)A).GetRow(i); int ind = Array.BinarySearch(Arow.indices, i); if (ind < 0) { throw new ArgumentException("Diagonal not present"); } diag[i] = Arow.data[ind]; diagInd[i] = ind; } } else if (A is ISparseRowColumnAccessMatrix) { IntIntDoubleVectorTriple Amat = ((ISparseRowColumnAccessMatrix)A).Matrix; for (int i = 0; i < n; ++i) { int ind = Arrays.binarySearch(Amat.major, i, Amat.minor[i], Amat.minor[i + 1]); if (ind < 0) { throw new ArgumentException("Diagonal not present"); } diag[i] = Amat.data[ind]; diagInd[i] = ind; } } else if (A is IDenseRowColumnAccessMatrix) { IntDoubleVectorPair Amat = ((IDenseRowColumnAccessMatrix)A).Matrix; for (int i = 0; i < n; ++i) { diagInd[i] = Amat.indices[i] + i; diag[i] = Amat.data[diagInd[i]]; } } else if (A is IDenseRowAccessMatrix) { for (int i = 0; i < n; ++i) { double[] Arow = ((IDenseRowAccessMatrix)A).GetRow(i); diagInd[i] = i; diag[i] = Arow[i]; } } else { throw new NotSupportedException(); } }
private void ssor(IDenseRowColumnAccessMatrix A, double[] xdata) { int n = A.RowCount; IntDoubleVectorPair Amat = A.Matrix; // M = (D+L) D^{-1} (D+L)^T // Solves (1/omega)*(D+L) y = b for (int i = 0; i < n; ++i) { // Do nothing if we get a divide by zero if (Math.Abs(diag[i]) == 0.0) { continue; } double sum = 0; for (int j = Amat.indices[i], k = 0; j < diagInd[i]; ++j, ++k) { sum += Amat.data[j] * xdata[k]; } xdata[i] = (omega / diag[i]) * (xdata[i] - sum); } // Solves (omega/(2-omega))*D^{-1} z = y for (int i = 0; i < n; ++i) { // No need to do anything if (Math.Abs(diag[i]) == 0.0) { continue; } xdata[i] = (2 - omega) / omega * diag[i] * xdata[i]; } // Solves (1/omega)*(D+L)^T x = z for (int i = n - 1; i >= 0; --i) { // Do nothing if we get a divide by zero if (Math.Abs(diag[i]) == 0.0) { continue; } double sum = 0; for (int j = diagInd[i] + 1, k = i + 1; j < n; ++j, ++k) { sum += Amat.data[j] * xdata[k]; } xdata[i] = (omega / diag[i]) * (xdata[i] - sum); } }
private void sor(IDenseRowColumnAccessMatrix A, double[] bdata, double[] xdata) { IntDoubleVectorPair Amat = A.Matrix; for (int i = 0; i < A.RowCount; ++i) { double newVal = 0, diagVal = 0.0; for (int j = Amat.indices[i], k = 0; j < Amat.indices[i + 1]; ++j, ++k) { if (k != i) { newVal += Amat.data[j] * xdata[k]; } else { diagVal = Amat.data[j]; } } newVal = (bdata[i] - newVal) / diagVal; xdata[i] += omega * (newVal - xdata[i]); } }
private void sor(ISparseRowAccessMatrix A, double[] bdata, double[] xdata) { for (int i = 0; i < A.RowCount; ++i) { IntDoubleVectorPair Arow = A.GetRow(i); double newVal = 0, diagVal = 0.0; for (int j = 0; j < Arow.indices.Length; ++j) { if (Arow.indices[j] != i) { newVal += Arow.data[j] * xdata[Arow.indices[j]]; } else { diagVal = Arow.data[j]; } } newVal = (bdata[i] - newVal) / diagVal; xdata[i] += omega * (newVal - xdata[i]); } }
/// <summary> F is upper-triangular, and F<sup>T</sup> is solved for.</summary> /// <param name="data">Initially the right hand side. Overwritten with solution.</param> /// <param name="diagDiv">True if the diagonal will be divided with.</param> protected internal virtual void SolveUT(double[] data, bool diagDiv) { for (int i = 0; i < F.RowCount; ++i) { IntDoubleVectorPair cur = F.GetRow(i); int[] curInd = cur.indices; double[] curDat = cur.data; // Solve at current position if (diagDiv) { data[i] /= curDat[diagInd[i]]; } double val = data[i]; // Move over to right hand side for (int j = diagInd[i] + 1; j < curInd.Length; ++j) { data[curInd[j]] -= curDat[j] * val; } } }
/// <summary> F is upper-triangular, and it is solved for.</summary> /// <param name="data">Initially the right hand side. Overwritten with solution.</param> /// <param name="diagDiv">True if the diagonal will be divided with.</param> protected internal virtual void SolveU(double[] data, bool diagDiv) { for (int i = F.RowCount - 1; i >= 0; --i) { IntDoubleVectorPair cur = F.GetRow(i); int[] curInd = cur.indices; double[] curDat = cur.data; double sum = 0; for (int j = diagInd[i] + 1; j < curInd.Length; ++j) { sum += curDat[j] * data[curInd[j]]; } data[i] -= sum; // Divide by diagonal. The factorization guarantees its existence if (diagDiv) { data[i] /= curDat[diagInd[i]]; } } }
private void gaussSeidel(ISparseRowAccessMatrix A, double[] bdat, double[] xdat) { for (int i = 0; i < A.RowCount; ++i) { IntDoubleVectorPair Arow = A.GetRow(i); int[] ArowInd = Arow.indices; double[] ArowDat = Arow.data; double newVal = 0, diagVal = 0.0; for (int j = 0; j < ArowInd.Length; ++j) { if (ArowInd[j] != i) { newVal += ArowDat[j] * xdat[ArowInd[j]]; } else { diagVal = ArowDat[j]; } } xdat[i] = (bdat[i] - newVal) / diagVal; } }
/// <summary> F is lower-triangular, and it is solved for.</summary> /// <param name="data">Initially the right hand side. Overwritten with solution.</param> /// <param name="diagDiv">True if the diagonal will be divided with.</param> protected internal virtual void solveL(double[] data, bool diagDiv) { for (int i = 0; i < F.RowCount; ++i) { IntDoubleVectorPair cur = F.GetRow(i); int[] curInd = cur.indices; double[] curDat = cur.data; double sum = 0; int j = 0; for (; curInd[j] < i; ++j) { sum += curDat[j] * data[curInd[j]]; } data[i] -= sum; // Divide by diagonal. The factorization guarantees its existence if (diagDiv) { data[i] /= curDat[j]; } } }
protected internal override void Factor() { double diagMod = initShift; int n = A.RowCount; diagInd = new int[n]; double[] curRow = new double[n]; //UPGRADE_NOTE: Label 'outer' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"' while (true) { // Copy A into F, and ensure non-zero diagonal Blas.Default.AddDiagonal(diagMod, Blas.Default.Copy(A, F)); // Clear cache of diagonal indices SupportClass.ArraySupport.Fill(diagInd, -1); GetDiagIndex(0); // Row-based Gaussian elimination for (int i = 1; i < n; ++i) { // Get current row in dense format IntDoubleVectorPair curRowI = F.GetRow(i); curRow = Blas.Default.Scatter(curRowI, curRow); // Check for empty row if (curRowI.indices.Length == 0) { diagMod += shift; //UPGRADE_NOTE: Labeled continue statement was changed to a goto statement. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1015_3"' goto outer; } // Traverse all active rows for (int j = 0; j < curRowI.indices.Length && curRowI.indices[j] < i; ++j) { IntDoubleVectorPair actRow = F.GetRow(curRowI.indices[j]); // Check for missing or zero diagonal int diag = GetDiagIndex(curRowI.indices[j], actRow.indices); if (diag < 0 || actRow.data[diag] == 0) { diagMod += shift; //UPGRADE_NOTE: Labeled continue statement was changed to a goto statement. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1015_3"' goto outer; } // Get multiplier (to be stored in L) double mult = (-curRow[curRowI.indices[j]]) / actRow.data[diag]; curRow[curRowI.indices[j]] = -mult; // Reduce everything on the upper diagonal of current row for (int k = diag + 1; k < actRow.indices.Length; ++k) { curRow[actRow.indices[k]] += mult * actRow.data[k]; } } // Put updated row back into the factor matrix // We either keep or discard filled in values if (fill) { F.SetRow(i, Blas.Default.Gather(curRow)); } else { F.SetRow(i, Blas.Default.Gather(curRowI.indices, curRow)); } } // No errors during factorization break; //UPGRADE_NOTE: Label 'outer' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"' outer: ; } }
protected internal override void Factor() { double diagMod = initShift; int n = F.RowCount; this.diagInd = new int[n]; double[] actRow = new double[n]; //UPGRADE_NOTE: Label 'outer' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"' while (true) { // Copy A into F, and ensure non-zero diagonal Blas.Default.AddDiagonal(diagMod, Blas.Default.Copy(A, F)); // Extract the upper triangular part for (int i = 0; i < n; ++i) { IntDoubleVectorPair curRow = F.GetRow(i); int diagInd = Array.BinarySearch(curRow.indices, i); if (diagInd < 0) { diagMod += shift; //UPGRADE_NOTE: Labeled continue statement was changed to a goto statement. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1015_3"' goto outer; } int[] index = new int[curRow.indices.Length - diagInd]; double[] data = new double[curRow.data.Length - diagInd]; Array.Copy(curRow.indices, diagInd, index, 0, index.Length); Array.Copy(curRow.data, diagInd, data, 0, data.Length); F.SetRow(i, new IntDoubleVectorPair(index, data)); } // Factorize for (int i = 0; i < n; ++i) { // Get current row IntDoubleVectorPair curRow = F.GetRow(i); // We must have positive entries on the diagonal if (curRow.data.Length == 0 || curRow.data[0] <= 0.0) { diagMod += shift; //UPGRADE_NOTE: Labeled continue statement was changed to a goto statement. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1015_3"' goto outer; } // Divide by rooted diagonal double diag = curRow.data[0] = Math.Sqrt(curRow.data[0]); for (int j = 1; j < curRow.data.Length; ++j) { curRow.data[j] /= diag; } F.SetRow(i, curRow); // Reduce submatrix using current row for (int j = 1; j < curRow.indices.Length; ++j) { // Active row in dense format IntDoubleVectorPair actRowI = F.GetRow(curRow.indices[j]); actRow = Blas.Default.Scatter(actRowI, actRow); // Reduce active row double factor = curRow.data[j]; for (int k = j; k < curRow.data.Length; ++k) { actRow[curRow.indices[k]] -= factor * curRow.data[k]; } // Put updated row back into the factor matrix // We either keep or discard filled in values if (fill) { F.SetRow(i, Blas.Default.Gather(actRow)); } else { F.SetRow(i, Blas.Default.Gather(actRowI.indices, actRow)); } } } // No errors during factorization break; //UPGRADE_NOTE: Label 'outer' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"' outer: ; } }
protected internal override void SolveI(IMatrix A, double[] eig, IVector[] x) { // Number of eigenvalues wanted and the maximum factorization size int n = eig.Length, m = A.RowCount; // Current factorization size, increment, and new size int nv = n, inc = 2, nvn = Math.Min(nv * inc, m); // These holds the matrix factorization IVector[] q = Factory.createVectors(x); for (int i = 0; i < nv; ++i) { q[i] = Blas.Default.Copy(x[i], q[i]); } double[] alpha = new double[nv], beta = new double[nv]; // Work-vector IVector z = Factory.createVector(q[0]); // Initial factorization Lanczos(A, q, alpha, beta, z, 0); // Compute the eigenvalues, and estimate residuals double[] r = new double[n]; int[] ind = new int[n]; EigenvalueDecomposition evd = new EigenvalueDecomposition(alpha, beta); EstimateResidual(nv, beta, evd, r, ind); // Continue while not converged or until the factorization is complete // Increase the size of the factorization at each iteration for (iter.Reset(); !iter.Converged(r, eig, x) && nv < m; iter.MoveNext(), nv = nvn, nvn = Math.Min(nv * inc, m)) { // Allocate more memory for larger factorization IVector[] qn = new IVector[nvn]; double[] alphan = new double[nvn], betan = new double[nvn]; Expand(q, alpha, beta, qn, alphan, betan); q = qn; alpha = alphan; beta = betan; // Compute larger factorization, starting at previous offset Lanczos(A, q, alpha, beta, z, nv - 1); // Get eigenvalues and the residuals evd = new EigenvalueDecomposition(alpha, beta); EstimateResidual(nv, beta, evd, r, ind); Console.Error.WriteLine(nvn); } // Get the eigenvalues (only real) double[] eigLoc = evd.RealEigenvalues; for (int i = 0; i < eig.Length; ++i) { eig[i] = eigLoc[ind[i]]; } // Compute the eigenvectors (x=q*V) IDenseAccessVector[] qa = new IDenseAccessVector[x.Length], xa = new IDenseAccessVector[x.Length]; for (int i = 0; i < x.Length; ++i) { qa[i] = (IDenseAccessVector)q[ind[i]]; xa[i] = (IDenseAccessVector)x[i]; } //Prod(qa, evd.getV(), xa); TODO: clean this Prod(qa, evd.EigenVectors, xa); // Sort by the eigenvalues IntDoubleVectorPair[] s = new IntDoubleVectorPair[eig.Length]; for (int i = 0; i < s.Length; ++i) { s[i] = new IntDoubleVectorPair(this, eig[i], i, xa[i]); } Array.Sort(s); // Extract and return for (int i = 0; i < s.Length; ++i) { eig[i] = s[i].d; x[i] = s[i].v; } et.Eigenvalue(eig); }