public RowBasedMatrix IncompleteCholesky(double droptol) { // suppose this matrix is symmetric, square and sorted int n = this.RowSize; int nAdd = 0; RowBasedMatrix L = new RowBasedMatrix(n); for (int i = 0; i < n; i++) { List <Element> r = rows[i]; List <Element> rr1 = L.rows[i]; double drop = 0; double norm = 0; foreach (Element e in r) { norm += e.value * e.value; } norm = Math.Sqrt(norm) * droptol; int k = 0; for (int j = 0; j < i; j++) { double sum = 0; if (k < r.Count && r[k].colIndex == j) { sum = r[k++].value; } int c1 = 0, c2 = 0; List <Element> rr2 = L.rows[j]; while (c1 < rr1.Count && c2 < rr2.Count) { Element e1 = rr1[c1]; Element e2 = rr2[c2]; if (e1.colIndex >= j) { break; } if (e2.colIndex >= j) { break; } if (e1.colIndex > e2.colIndex) { c2++; } else if (e1.colIndex < e2.colIndex) { c1++; } else { sum -= e1.value * e2.value; c1++; c2++; } } while (rr2[c2].colIndex < j) { c2++; } sum /= rr2[c2].value; if (Math.Abs(sum) > norm) { rr1.Add(new Element(j, sum)); nAdd++; } else { drop += sum; } } if (r[k].colIndex != i) { throw new Exception(); } double diag = r[k].value; // + drop; for (int c = 0; c < rr1.Count && rr1[c].colIndex < i; c++) { diag -= rr1[c].value * rr1[c].value; } if (diag > 0.0) { rr1.Add(new Element(i, Math.Sqrt(diag))); } else { throw new Exception(); } } //FormMain.CurrForm.OutputText("drops:" + nAdd.ToString()); return(L); }
public void CG_SolveATA(double[] x, double[] b, int maxIter, double eps, int recompute, RowBasedMatrix inv) { int n = x.Length; int iter = 0; double[] r = new double[n]; double[] d = new double[n]; double[] q = new double[n]; double[] s = new double[n]; double[] t = new double[n]; double errNew = 0, errold = 0; for (int i = 0; i < n; i++) { r[i] = b[i]; } for (int i = 0; i < RowSize; i++) { double sum = 0; foreach (Element e in rows[i]) { sum += e.value * x[e.colIndex]; } foreach (Element e in rows[i]) { r[e.colIndex] -= e.value * sum; } } inv.Cholesky_Solve(d, r); for (int i = 0; i < n; i++) { errNew += r[i] * d[i]; } double tolerance = eps * errNew; //FormMain.CurrForm.OutputText("0:" + errNew.ToString()); while (iter < maxIter && errNew > tolerance) { iter++; double dAd = 0; for (int i = 0; i < n; i++) { q[i] = 0; } for (int i = 0; i < RowSize; i++) { double sum = 0; foreach (Element e in rows[i]) { sum += e.value * d[e.colIndex]; } foreach (Element e in rows[i]) { q[e.colIndex] += e.value * sum; } } for (int i = 0; i < n; i++) { dAd += d[i] * q[i]; } double alpha = errNew / dAd; for (int i = 0; i < n; i++) { x[i] += alpha * d[i]; } if (iter % recompute == 0) { for (int i = 0; i < n; i++) { r[i] = b[i]; } for (int i = 0; i < RowSize; i++) { double sum = 0; foreach (Element e in rows[i]) { sum += e.value * x[e.colIndex]; } foreach (Element e in rows[i]) { r[e.colIndex] -= e.value * sum; } } //FormMain.CurrForm.OutputText(iter + ":" + errNew.ToString()); } else { for (int i = 0; i < n; i++) { r[i] -= alpha * q[i]; } } inv.Cholesky_Solve(s, r); errold = errNew; errNew = 0; for (int i = 0; i < n; i++) { errNew += r[i] * s[i]; } double beta = errNew / errold; for (int i = 0; i < n; i++) { d[i] = s[i] + beta * d[i]; } } double err = 0; for (int i = 0; i < n; i++) { err += r[i] * r[i]; } //FormMain.CurrForm.OutputText(iter + ":" + err.ToString()); }
public RowBasedMatrix IncompleteCholesky() { // suppose this matrix is symmetric, square and sorted int n = this.RowSize; RowBasedMatrix L = new RowBasedMatrix(n); for (int i = 0; i < n; i++) { List <Element> r = rows[i]; List <Element> rr1 = L.rows[i]; for (int j = 0; j < r.Count; j++) { Element e = r[j]; if (e.colIndex == i) { double sum = e.value; for (int c = 0; c < rr1.Count && rr1[c].colIndex < i; c++) { sum -= rr1[c].value * rr1[c].value; } if (sum > 0.0) { rr1.Add(new Element(i, Math.Sqrt(sum))); } else { rr1.Add(new Element(i, 10e-12)); } } else if (e.colIndex < i) { List <Element> rr2 = L.rows[e.colIndex]; double sum = e.value; int c1 = 0, c2 = 0; while (c1 < rr1.Count && c2 < rr2.Count) { Element e1 = rr1[c1]; Element e2 = rr2[c2]; if (e1.colIndex >= e.colIndex) { break; } if (e2.colIndex >= e.colIndex) { break; } if (e1.colIndex > e2.colIndex) { c2++; } else if (e1.colIndex < e2.colIndex) { c1++; } else { sum -= e1.value * e2.value; c1++; c2++; } } while (rr2[c2].colIndex < e.colIndex) { c2++; } rr1.Add(new Element(e.colIndex, sum / rr2[c2].value)); } } } return(L); }