public static Vector operator *(Vector v, double multiple) { Vector vector = new Vector(v.Size); for (int index = 0; index < v.Size; index++) { vector[index] = multiple * v[index]; } return vector; }
private void UpdateDgvResult(src.Vector_.Vector vec) { if (this.dgvRightPart.InvokeRequired) { this.Invoke(new UpdateDgvResultCallback(UpdateDgvResult), new object[] { vec }); } else { updateDgvResult(vec); } }
private void updateDgvInitial(src.Vector_.Vector vec) { tabControl1.SelectedIndex = 1; ClearDgv(dgvInitial); if (vec.Size > maxDrawSize) { dgvInitial.Rows.Add("Vector is too big to draw"); return; } for (var i = 0; i < vec.Size; i++) { dgvInitial.Rows.Add(vec[i].ToString()); } }
private void updateDgvRightPart(src.Vector_.Vector vec) { tabControl1.SelectedIndex = 0; ClearDgv(dgvRightPart); if (vec.Size > maxDrawSize) { dgvRightPart.Rows.Add("Vector is too big to draw"); return; } for (var i = 0; i < vec.Size; i++) { String[] strs = new String[1]; strs[0] = vec[i].ToString(); dgvRightPart.Rows.Add(strs); } }
private void updateDgvResult(src.Vector_.Vector vec) { tabControl1.SelectedIndex = 2; ClearDgv(dgvResult); if (vec == null) { return; } if (vec.Size > maxDrawSize) { dgvResult.Rows.Add("Vector is too big to draw"); return; } for (var i = 0; i < vec.Size; i++) { dgvResult.Rows.Add(vec[i].ToString()); } }
public void TestProfileFormatJacobi() { int predCoeff = 0; Vector expectedAnswer = new Vector(dim); for (int i = 0; i < dim; i++) expectedAnswer[i] = i + 1; var matrix = generateProfileMatrix(predCoeff); var rightPart = generateRightPart(matrix, expectedAnswer); Jacobi solver = new Jacobi(); EmptyPreconditioner precond = EmptyPreconditioner.Create(matrix); Vector answer = solver.Solve(precond, rightPart, new Vector(dim), Logger.Instance, Logger.Instance, new JacobiParametrs(eps, maxIter)); Console.Write("Generate complete...\n"); for (int i = 0; i < dim; i++) { Console.Write(expectedAnswer[i].ToString() + "\t" + answer[i].ToString() + "\n"); Assert.AreEqual(expectedAnswer[i], answer[i], 0.001, "Not equal!"); } }
public abstract Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger,ISolverLogger solverLogger, ISolverParametrs solverParametrs);
public Vector SSolve(Vector x) { return lLTmatrix.LSolve(x, true); }
public override Vector USolve(Vector x, bool UseDiagonal) { if (x.Size != _count) throw new Exception("Несовпадение длин у операндов USolve"); Vector vector = (Vector)x.Clone(); if (UseDiagonal) { for (int row = _count - 1; row >= 0; row--) { vector[row] /= _di[row]; int start = row - (_ig[row + 1] - _ig[row]); for (int column = _ig[row + 1] - 1, index = row - 1; index >= start; column--, index--) vector[index] -= _au[column] * vector[row]; } } else { for (int row = _count - 1; row >= 0; row--) { int start = row - (_ig[row + 1] - _ig[row]); for (int column = _ig[row + 1] - 1, index = row - 1; index >= start; column--, index--) vector[index] -= _au[column] * vector[row]; } } return vector; }
public abstract Vector UtMult(Vector x, bool UseDiagonal);
public override Vector UtSolve(Vector x, bool UseDiagonal) { if (n == x.Size) { Vector result = (Vector)x.Clone(); if (UseDiagonal) { result[0] /= di[0]; // Обработка части al, где есть 0 for (int i = 1; i < bandWidth; i++)// обрабатываем i строку { for (int j = bandWidth - i; j < bandWidth; j++) result[i] -= au[i][j] * result[j + i - bandWidth]; result[i] /= di[i]; } //Обработка без 0 for (int i = bandWidth; i < n; i++) { for (int j = i - bandWidth; j < i; j++) result[i] -= au[i][j - i + bandWidth] * result[j]; result[i] /= di[i]; } } else { // Обработка части al, где есть 0 for (int i = 1; i < bandWidth; i++)// обрабатываем i строку for (int j = bandWidth - i; j < bandWidth; j++) result[i] -= au[i][j] * result[j + i - bandWidth]; //Обработка без 0 for (int i = bandWidth; i < n; i++) for (int j = i - bandWidth; j < i; j++) result[i] -= au[i][j - i + bandWidth] * result[j]; } return result; } else throw new Exception("Ленточный формат: Несовпадение размерностей матрицы и вектора при обратном (T) ходе"); }
public override Vector USolve(Vector x, bool UseDiagonal) { if (n == x.Size) { //Vector result = new Vector(n); // Разобраться с присваиванием, пока обобщенно написано //result = x; Vector result = (Vector) x.Clone(); if (UseDiagonal) { result[n - 1] /= di[n - 1]; // без 0 for (int i = n - 1; i >= bandWidth; i--) { for (int j = bandWidth - 1; j >= 0; j--) result[i + j - bandWidth] -= au[i][j] * result[i]; result[i - 1] /= di[i - 1]; } // с 0 for (int i = bandWidth - 1; i > 0; i--) { for (int j = bandWidth - 1; j >= bandWidth - i; j--) result[i + j - bandWidth] -= au[i][j] * result[i]; result[i - 1] /= di[i - 1]; } } else { // без 0 for (int i = n - 1; i >= bandWidth; i--) for (int j = bandWidth - 1; j >= 0; j--) result[i + j - bandWidth] -= au[i][j] * result[i]; // с 0 for (int i = bandWidth - 1; i > 0; i--) for (int j = bandWidth - 1; j >= bandWidth - i; j--) result[i + j - bandWidth] -= au[i][j] * result[i]; } return result; } else throw new Exception("Ленточный формат: Несовпадение размерностей матрицы и вектора при обратном ходе"); }
public static Vector Mult(Vector v1, Vector v2) { if (v1.Size == v2.Size) { Vector vector = new Vector(v1.Size); for (int index = 0; index < v1.Size; index++) { vector[index] = v1[index] * v2[index]; } return vector; } else throw new Exception("Несовпадение длин у операндов при умножении векторов"); }
// Возведение каждого элемента вектора в степень -1 public static Vector Inverse(Vector v) { Vector vector = new Vector(v.Size); for (int index = 0; index < v.Size; index++) { vector[index] = 1.0 / v[index]; } return vector; }
public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs) { GMRESParameters GMRESParameters = solverParametrs as GMRESParameters; if (GMRESParameters != null) { Vector[] V, H; Vector residual, x, d, z, w, tmp; bool continueCalculations; double epsilon = GMRESParameters.Epsilon; int m = GMRESParameters.M; int maxIterations = GMRESParameters.MaxIterations; int n = rightPart.Size; x = initialSolution; residual = rightPart - matrix.SourceMatrix.Multiply(x); residual = matrix.SSolve(residual); double rightPartNorm = matrix.SSolve(rightPart).Norm(); double residualNorm = residual.Norm(); if (System.Double.IsInfinity(residualNorm / rightPartNorm)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by GMRES."); return x; } if (System.Double.IsNaN(residualNorm / rightPartNorm)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by GMRES."); return x; } x = matrix.QMultiply(initialSolution); V = new Vector[m]; for (int i = 0; i < m; i++) V[i] = new Vector(n); H = new Vector[m]; for (int i = 0; i < m; i++) H[i] = new Vector(m + 1); d = new Vector(m + 1); for (int k = 1; k <= maxIterations && residualNorm / rightPartNorm > epsilon; k++) { d.Nullify(); V[0] = residual * (1.0 / residualNorm); continueCalculations = true; for (int j = 1; j <= m && continueCalculations; j++) { tmp = matrix.QSolve(V[j - 1]); w = matrix.SSolve(matrix.SourceMatrix.Multiply(tmp)); for (int l = 1; l <= j; l++) { H[j - 1][l - 1] = V[l - 1] * w; w = w - V[l - 1] * H[j - 1][l - 1]; } H[j - 1][j] = w.Norm(); if (Math.Abs(H[j - 1][j]) < 1e-10) { m = j; continueCalculations = false; } else { if(j != m) V[j] = w * (1.0 / H[j - 1][j]); } } d[0] = residualNorm; z = solveMinSqrProblem(d, H, m); x = x + multiplyMatrixVector(z, V); tmp = rightPart - matrix.SourceMatrix.Multiply(matrix.QSolve(x)); residual = matrix.SSolve(tmp); residualNorm = residual.Norm(); if (System.Double.IsInfinity(residualNorm / rightPartNorm)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by GMRES."); return x; } if (System.Double.IsNaN(residualNorm / rightPartNorm)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by GMRES."); return x; } solverLogger.AddIterationInfo(k, residualNorm / rightPartNorm); } return matrix.QSolve(x); } else { logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in GMRES"); throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in GMRES"); } }
Vector solveMinSqrProblem(Vector d, Vector[] H, int m) { int m2 = H.Length; Vector result = new Vector(m2); Vector[] H_previous, H2; Vector d1, d2; double ci, si, tmp; double[] tmp1, tmp2; tmp1 = new double[m]; tmp2 = new double[m]; double tmp11, tmp22; H_previous = new Vector[m2]; for (int i = 0; i < m2; i++) H_previous[i] = H[i]; H2 = new Vector[m]; for (int i = 0; i < m; i++) H2[i] = new Vector(m); d1 = d;//размер m2+1 d2 = new Vector(m); for (int i = 0; i < m; i++) { tmp = Math.Sqrt(H_previous[i][i] * H_previous[i][i] + H[i][i + 1] * H[i][i + 1]); ci = H_previous[i][i] / tmp; si = H[i][i + 1] / tmp; #region H_prev=R*H_prev //расчитываем заранее элементы строк, где блок синусов-косинусов for (int l = 0; l < m; l++) { tmp1[l] = H_previous[l][i] * ci + H_previous[l][i + 1] * si; tmp2[l] = -H_previous[l][i] * si + H_previous[l][i + 1] * ci; } //заполняем строки,где блок синусов-косинусов for (int l = 0; l < m; l++) { H_previous[l][i] = tmp1[l]; H_previous[l][i + 1] = tmp2[l]; } #endregion #region d1=R*d1 //рассчитываем элементы вектора, где блок синусов-косинусов tmp11 = d1[i] * ci + d1[i + 1] * si; tmp22 = -d1[i] * si + d1[i + 1] * ci; //заполняем элементы вектора, где блок синусов-косинусов //остальные не изменяются d1[i] = tmp11; d1[i + 1] = tmp22; #endregion } //исключаем m+1-ю строку и m+1-й элемент for (int j = 0; j < m; j++) { for (int i = 0; i < m; i++) H2[j][i] = H_previous[j][i]; d2[j] = d1[j]; } //находим неизвестный вектор из СЛАУ H2*result=d2 for (int i = m - 1; i >= 0; i--) { result[i] = d2[i]; for (int j = i + 1; j < m; j++) { result[i] -= result[j] * H2[j][i]; } result[i] = result[i] / H2[i][i]; } return result; }
Vector multiplyMatrixVector(Vector vector, Vector[] matrix) { int n_lines = matrix[0].Size; int n_columns = matrix.Length; Vector result = new Vector(n_lines); result.Nullify(); if(vector.Size == n_columns) { for (int j = 0; j < n_columns; j++) for (int i = 0; i < n_lines; i++) result[i] += matrix[j][i] * vector[j]; } else throw new Exception("GMRES: Несовпадение длины вектора и числа столбцов матрицы"); return result; }
public override Vector UtSolve(Vector x, bool UseDiagonal) { if (x.Size != _count) throw new Exception("Несовпадение длин у операндов UtSolve"); Vector vector = new Vector(_count); if (UseDiagonal) { for (int row = 0; row < _count; row++) { double sumRow = 0; int index = row - (_ig[row + 1] - _ig[row]); for (int column = _ig[row]; index < row; column++, index++) sumRow += _au[column] * vector[index]; vector[row] = (x[row] - sumRow) / _di[row]; } } else { for (int row = 0; row < _count; row++) { double sumRow = 0; int index = row - (_ig[row + 1] - _ig[row]); for (int column = _ig[row]; index < row; column++, index++) sumRow += _au[column] * vector[index]; vector[row] = x[row] - sumRow; } } return vector; }
public override Vector UtMult(Vector x, bool UseDiagonal) { if (x.Size != _count) throw new Exception("Несовпадение длин у операндов UtMult"); Vector vector = new Vector(_count); for (int column = 0; column < _count; column++) { int index = _ig[column]; for (int row = column - (_ig[column + 1] - index); row < column; row++, index++) vector[column] += _au[index] * x[row]; } if (UseDiagonal) for (int index = 0; index < _count; index++) vector[index] += _di[index] * x[index]; return vector; }
public override Vector TMultiply(Vector x) { Vector result = new Vector(n); result.Nullify(); if (n == x.Size) { // Верхний треугольник // Обработка части au, где есть 0 for (int i = 1; i < bandWidth; i++)// обрабатываем i строку for (int j = bandWidth - i; j < bandWidth; j++) result[i] += au[i][j] * x[j + i - bandWidth]; //Обработка без 0 for (int i = bandWidth; i < n; i++) for (int j = i - bandWidth; j < i; j++) result[i] += au[i][j - i + bandWidth] * x[j]; //Диагональ for (int i = 0; i < n; i++) result[i] += di[i] * x[i]; //Нижний треугольник for (int j = 0; j < bandWidth; j++) { for (int i = bandWidth - j; i < n; i++) result[i - bandWidth + j] += al[i][j] * x[i]; } return result; } throw new Exception("Ленточный формат: Несовпадение размерностей матрицы и вектора при умножении(T)"); }
public override Vector UMult(Vector x, bool UseDiagonal) { if (n == x.Size) { Vector result = new Vector(n); result.Nullify(); for (int j = 0; j < bandWidth; j++) { for (int i = bandWidth - j; i < n; i++) result[i - bandWidth + j] += au[i][j] * x[i]; } if (UseDiagonal) { for (int i = 0; i < n; i++) result[i] += di[i] * x[i]; } return result; } else throw new Exception("Ленточный формат: Несовпадение размерностей матрицы и вектора при умножении верхнего треугольника"); }
public object Clone() { var vec = _vector.Clone() as double[]; Vector newvec = new Vector(vec); return newvec; }
public override Vector UtMult(Vector x, bool UseDiagonal) { if (n == x.Size) { Vector result = new Vector(n); result.Nullify(); if (UseDiagonal) { result[0] = di[0] * x[0]; // Обработка части al, где есть 0 for (int i = 1; i < bandWidth; i++)// обрабатываем i строку { for (int j = bandWidth - i; j < bandWidth; j++) result[i] += au[i][j] * x[j + i - bandWidth]; result[i] += di[i] * x[i]; } //Обработка без 0 for (int i = bandWidth; i < n; i++) { for (int j = i - bandWidth; j < i; j++) result[i] += au[i][j - i + bandWidth] * x[j]; result[i] += di[i] * x[i]; } } else { // Обработка части al, где есть 0 for (int i = 1; i < bandWidth; i++)// обрабатываем i строку for (int j = bandWidth - i; j < bandWidth; j++) result[i] += au[i][j] * x[j + i - bandWidth]; //Обработка без 0 for (int i = bandWidth; i < n; i++) for (int j = i - bandWidth; j < i; j++) result[i] += au[i][j - i + bandWidth] * x[j]; } return result; } else throw new Exception("Ленточный формат: Несовпадение размерностей матрицы и вектора при умножении верхнего(T) треугольника"); }
public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs) { MSGParametrs ConGradParametrs = solverParametrs as MSGParametrs; if (ConGradParametrs == null) { logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in MSG"); throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in MSG"); } else { //prestart int oIter = 0; double alpha, beta, oNev, bNev, scalRO, scaleRN; Vector x = initialSolution, rNew, rOld, z, ap, p; rOld = rightPart - matrix.SourceMatrix.Multiply(x); z = matrix.QSolve(matrix.SSolve(rOld)); p = z; ap = matrix.SourceMatrix.Multiply(p); bNev = rightPart.Norm(); oNev = rOld.Norm() / bNev; scalRO = z * rOld; // x = matrix.QSolve(x); solverLogger.AddIterationInfo(oIter, oNev);//logger if (System.Double.IsInfinity(oNev)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by MSG."); return x; } if (System.Double.IsNaN(oNev)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by MSG."); return x; } while (oIter < ConGradParametrs.MaxIterations && oNev > ConGradParametrs.Epsilon) { alpha = scalRO / (ap * p); x = x + p * alpha; //if (oIter % 100 == 0) //rNew = matrix.QMultiply(rightPart - matrix.SMultiply(matrix.SourceMatrix.Multiply(x))); //else rNew = rOld - ap * alpha; z = matrix.QSolve(matrix.SSolve(rNew)); scaleRN = z * rNew; beta = scaleRN / scalRO; scalRO = scaleRN; p = z + p * beta; ap = matrix.SourceMatrix.Multiply(p); rOld = rNew; oIter++; oNev = rNew.Norm() / bNev; if (System.Double.IsInfinity(oNev)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by MSG."); return x; } if (System.Double.IsNaN(oNev)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by MSG."); return x; } solverLogger.AddIterationInfo(oIter, oNev);//logger } return x; } }
public abstract Vector TMultiply(Vector x);
public override Vector USolve(Vector x, bool UseDiagonal) { if (x.Size != n) throw new Exception("Несовпадение длин у операндов при USolve"); else { int i, j; Vector v; if (UseDiagonal == true)// Деление на динагональ { v = (Vector)x.Clone();// в смысле копирование элементов for (i = n - 1; i >= 0; i--) { v[i] /= di[i]; for (j = ia[i]; j < ia[i + 1]; j++) v[ja[j]] -= au[j] * v[i]; } return v; } else// Без деления на диагональ { v = (Vector)x.Clone();// в смысле копирование элементов for (i = n - 1; i >= 0; i--) for (j = ia[i]; j < ia[i + 1]; j++) v[ja[j]] -= au[j] * v[i]; return v; } } }
public abstract Vector UtSolve(Vector x, bool UseDiagonal);
public override Vector UtSolve(Vector x, bool UseDiagonal) { if (x.Size != n) throw new Exception("Несовпадение длин у операндов при UtSolve"); else { int i, j; double result; Vector v = new Vector(n); if (UseDiagonal == true)// Деление на динагональ { for (i = 0; i < n; i++) { result = 0; for (j = ia[i]; j < ia[i + 1]; j++) result += au[j] * v[ja[j]]; v[i] = (x[i] - result) / di[i]; } return v; } else// Без деления на диагональ { for (i = 0; i < n; i++) { result = 0; for (j = ia[i]; j < ia[i + 1]; j++) result += au[j] * v[ja[j]]; v[i] = (x[i] - result); } return v; } } }
public override Vector TMultiply(Vector x) { if (x.Size != n) throw new Exception("Несовпадение длин у операндов при TMultiply"); else { int i, j; Vector v = new Vector(n); for (i = 0; i < n; i++) { v[i] = di[i] * x[i]; for (j = ia[i]; j < ia[i + 1]; j++) { v[i] += au[j] * x[ja[j]]; v[ja[j]] += al[j] * x[i]; } } return v; } }
public static Vector operator +(Vector v1, Vector v2) { if (v1.Size == v2.Size) { Vector vector = new Vector(v1.Size); for (int index = 0; index < v1.Size; index++) { vector[index] = v1[index] + v2[index]; } return vector; } else throw new Exception("Несовпадение длин у операндов при сложении"); }
public override Vector UtMult(Vector x, bool UseDiagonal) { if (x.Size != n) throw new Exception("Несовпадение длин у операндов при UtMult"); else { int i, j; Vector v = new Vector(n); if (UseDiagonal == true)// если умножение с диагональю { for (i = 0; i < n; i++) { v[i] = di[i] * x[i]; for (j = ia[i]; j < ia[i + 1]; j++) v[i] += au[j] * x[ja[j]]; } return v; } else// если без диагонали { for (i = 0; i < n; i++) for (j = ia[i]; j < ia[i + 1]; j++) v[i] += au[j] * x[ja[j]]; return v; } } }
public Vector QSolve(Vector x) { return lLTmatrix.USolve(x, true); }
public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs) { JacobiParametrs JacParametrs = solverParametrs as JacobiParametrs; if (JacParametrs != null) { Vector x, r, diagonal; int size, k; double relativeResidual, w, rightPartNorm; Vector Db, Dx, Lx, Ux, DULx; size = initialSolution.Size; x = new Vector(size); r = new Vector(size); diagonal = new Vector(size); x = initialSolution; w = JacParametrs.Relaxation; diagonal = matrix.SourceMatrix.Diagonal; rightPartNorm = rightPart.Norm(); Dx = Vector.Mult(diagonal, x); Lx = matrix.SourceMatrix.LMult(x, false); Ux = matrix.SourceMatrix.UMult(x, false); r = Lx + Dx + Ux - rightPart; relativeResidual = r.Norm() / rightPartNorm; if (System.Double.IsInfinity(relativeResidual)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by Jacobi."); return x; } if (System.Double.IsNaN(relativeResidual)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by Jacobi."); return x; } Db = Vector.Division(rightPart, diagonal); solverLogger.AddIterationInfo(0, relativeResidual); for (k = 1; k <= solverParametrs.MaxIterations && relativeResidual > solverParametrs.Epsilon; k++) { DULx = Vector.Division(Ux + Lx, diagonal); x = (Db - DULx) * w + x * (1 - w); Dx = Vector.Mult(diagonal, x); Lx = matrix.SourceMatrix.LMult(x, false); Ux = matrix.SourceMatrix.UMult(x, false); r = Lx + Dx + Ux - rightPart; relativeResidual = r.Norm() / rightPartNorm; if (System.Double.IsInfinity(relativeResidual)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by Jacobi."); return x; } if (System.Double.IsNaN(relativeResidual)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by Jacobi."); return x; } solverLogger.AddIterationInfo(k, relativeResidual); } return x; } else { logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in Jacobi"); throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in Jacobi"); } }
public Vector SMultiply(Vector x) { return lLTmatrix.LMult(x, true); }