public void DetermineStatus() { var criteria = new List<IIterationStopCriterium<Complex>> { new FailureStopCriterium(), new DivergenceStopCriterium(), new IterationCountStopCriterium<Complex>(1) }; var iterator = new Iterator<Complex>(criteria); // First step, nothing should happen. iterator.DetermineStatus( 0, DenseVector.Create(3, i => 4), DenseVector.Create(3, i => 4), DenseVector.Create(3, i => 4)); Assert.AreEqual(IterationStatus.Continue, iterator.Status, "Incorrect status"); // Second step, should run out of iterations. iterator.DetermineStatus( 1, DenseVector.Create(3, i => 4), DenseVector.Create(3, i => 4), DenseVector.Create(3, i => 4)); Assert.AreEqual(IterationStatus.StoppedWithoutConvergence, iterator.Status, "Incorrect status"); }
public void CanSolveForRandomMatrix(int order) { var matrixA = MatrixLoader.GenerateRandomDenseMatrix(order, order); var matrixB = MatrixLoader.GenerateRandomDenseMatrix(order, order); var monitor = new Iterator<Complex>( new IterationCountStopCriterium<Complex>(1000), new ResidualStopCriterium(1e-10)); var solver = new BiCgStab(); var matrixX = matrixA.SolveIterative(matrixB, solver, monitor); // The solution X row dimension is equal to the column dimension of A Assert.AreEqual(matrixA.ColumnCount, matrixX.RowCount); // The solution X has the same number of columns as B Assert.AreEqual(matrixB.ColumnCount, matrixX.ColumnCount); var matrixBReconstruct = matrixA*matrixX; // Check the reconstruction. for (var i = 0; i < matrixB.RowCount; i++) { for (var j = 0; j < matrixB.ColumnCount; j++) { Assert.AreEqual(matrixB[i, j].Real, matrixBReconstruct[i, j].Real, 1.0e-5); Assert.AreEqual(matrixB[i, j].Imaginary, matrixBReconstruct[i, j].Imaginary, 1.0e-5); } } }
/// <summary> /// Creates a default iterator with all the <see cref="IIterationStopCriterium"/> objects. /// </summary> /// <returns>A new <see cref="IIterator"/> object.</returns> public static IIterator CreateDefault() { var iterator = new Iterator(); iterator.Add(new FailureStopCriterium()); iterator.Add(new DivergenceStopCriterium()); iterator.Add(new IterationCountStopCriterium()); iterator.Add(new ResidualStopCriterium()); return iterator; }
public void SolveUnitMatrixAndBackMultiply() { // Create the identity matrix var matrix = SparseMatrix.CreateIdentity(100); // Create the y vector var y = Vector<Complex>.Build.Dense(matrix.RowCount, 1); // Create an iteration monitor which will keep track of iterative convergence var monitor = new Iterator<Complex>( new IterationCountStopCriterium<Complex>(MaximumIterations), new ResidualStopCriterium<Complex>(ConvergenceBoundary), new DivergenceStopCriterium<Complex>(), new FailureStopCriterium<Complex>()); var solver = new TFQMR(); // Solve equation Ax = y var x = matrix.SolveIterative(y, solver, monitor); // Now compare the results Assert.IsNotNull(x, "#02"); Assert.AreEqual(y.Count, x.Count, "#03"); // Back multiply the vector var z = matrix.Multiply(x); // Check that the solution converged Assert.IsTrue(monitor.Status == IterationStatus.Converged, "#04"); // Now compare the vectors Assert.LessOrEqual(Distance.Chebyshev(y, z), 2*ConvergenceBoundary); }
public void SolvePoissonMatrixAndBackMultiply() { // Create the matrix var matrix = new SparseMatrix(100); // Assemble the matrix. We assume we're solving the Poisson equation // on a rectangular 10 x 10 grid const int GridSize = 10; // The pattern is: // 0 .... 0 -1 0 0 0 0 0 0 0 0 -1 4 -1 0 0 0 0 0 0 0 0 -1 0 0 ... 0 for (var i = 0; i < matrix.RowCount; i++) { // Insert the first set of -1's if (i > (GridSize - 1)) { matrix[i, i - GridSize] = -1; } // Insert the second set of -1's if (i > 0) { matrix[i, i - 1] = -1; } // Insert the centerline values matrix[i, i] = 4; // Insert the first trailing set of -1's if (i < matrix.RowCount - 1) { matrix[i, i + 1] = -1; } // Insert the second trailing set of -1's if (i < matrix.RowCount - GridSize) { matrix[i, i + GridSize] = -1; } } // Create the y vector var y = Vector<Complex>.Build.Dense(matrix.RowCount, 1); // Create an iteration monitor which will keep track of iterative convergence var monitor = new Iterator<Complex>( new IterationCountStopCriterium<Complex>(MaximumIterations), new ResidualStopCriterium<Complex>(ConvergenceBoundary), new DivergenceStopCriterium<Complex>(), new FailureStopCriterium<Complex>()); var solver = new TFQMR(); // Solve equation Ax = y var x = matrix.SolveIterative(y, solver, monitor); // Now compare the results Assert.IsNotNull(x, "#02"); Assert.AreEqual(y.Count, x.Count, "#03"); // Back multiply the vector var z = matrix.Multiply(x); // Check that the solution converged Assert.IsTrue(monitor.Status == IterationStatus.Converged, "#04"); // Now compare the vectors Assert.LessOrEqual(Distance.Chebyshev(y, z), 2*ConvergenceBoundary); }
public void CanSolveForRandomVector(int order) { var matrixA = Matrix<Complex>.Build.Random(order, order, 1); var vectorb = Vector<Complex>.Build.Random(order, 1); var monitor = new Iterator<Complex>( new IterationCountStopCriterium<Complex>(1000), new ResidualStopCriterium<Complex>(1e-10)); var solver = new TFQMR(); var resultx = matrixA.SolveIterative(vectorb, solver, monitor); Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var matrixBReconstruct = matrixA*resultx; // Check the reconstruction. for (var i = 0; i < order; i++) { Assert.AreEqual(vectorb[i].Real, matrixBReconstruct[i].Real, 1e-5); Assert.AreEqual(vectorb[i].Imaginary, matrixBReconstruct[i].Imaginary, 1e-5); } }
public void SolveUnitMatrixAndBackMultiply() { // Create the identity matrix var matrix = SparseMatrix.Identity(100); // Create the y vector var y = DenseVector.Create(matrix.RowCount, i => Complex.One); // Create an iteration monitor which will keep track of iterative convergence var monitor = new Iterator<Complex>( new IterationCountStopCriterium<Complex>(MaximumIterations), new ResidualStopCriterium(ConvergenceBoundary), new DivergenceStopCriterium(), new FailureStopCriterium()); var solver = new BiCgStab(); // Solve equation Ax = y var x = matrix.SolveIterative(y, solver, monitor); // Now compare the results Assert.IsNotNull(x, "#02"); Assert.AreEqual(y.Count, x.Count, "#03"); // Back multiply the vector var z = matrix.Multiply(x); // Check that the solution converged Assert.IsTrue(monitor.Status == IterationStatus.Converged, "#04"); // Now compare the vectors for (var i = 0; i < y.Count; i++) { Assert.IsTrue((y[i] - z[i]).Magnitude.IsSmaller(ConvergenceBoundary, 1), "#05-" + i); } }
public void SolveScaledUnitMatrixAndBackMultiply() { // Create the identity matrix var matrix = SparseMatrix.CreateIdentity(100); // Scale it with a funny number matrix.Multiply(Math.PI, matrix); // Create the y vector var y = Vector<Complex>.Build.Dense(matrix.RowCount, 1); // Create an iteration monitor which will keep track of iterative convergence var monitor = new Iterator<Complex>( new IterationCountStopCriterion<Complex>(MaximumIterations), new ResidualStopCriterion<Complex>(ConvergenceBoundary), new DivergenceStopCriterion<Complex>(), new FailureStopCriterion<Complex>()); var solver = new MlkBiCgStab(); // Solve equation Ax = y var x = matrix.SolveIterative(y, solver, monitor); // Now compare the results Assert.IsNotNull(x, "#02"); Assert.AreEqual(y.Count, x.Count, "#03"); // Back multiply the vector var z = matrix.Multiply(x); // Check that the solution converged Assert.IsTrue(monitor.Status == IterationStatus.Converged, "#04"); // Now compare the vectors for (var i = 0; i < y.Count; i++) { Assert.GreaterOrEqual(ConvergenceBoundary, (y[i] - z[i]).Magnitude, "#05-" + i); } }
public void SolvePoissonMatrixAndBackMultiply() { // Create the matrix var matrix = new SparseMatrix(100); // Assemble the matrix. We assume we're solving the Poisson equation // on a rectangular 10 x 10 grid const int GridSize = 10; // The pattern is: // 0 .... 0 -1 0 0 0 0 0 0 0 0 -1 4 -1 0 0 0 0 0 0 0 0 -1 0 0 ... 0 for (var i = 0; i < matrix.RowCount; i++) { // Insert the first set of -1's if (i > (GridSize - 1)) { matrix[i, i - GridSize] = -1; } // Insert the second set of -1's if (i > 0) { matrix[i, i - 1] = -1; } // Insert the centerline values matrix[i, i] = 4; // Insert the first trailing set of -1's if (i < matrix.RowCount - 1) { matrix[i, i + 1] = -1; } // Insert the second trailing set of -1's if (i < matrix.RowCount - GridSize) { matrix[i, i + GridSize] = -1; } } // Create the y vector var y = DenseVector.Create(matrix.RowCount, i => 1); // Create an iteration monitor which will keep track of iterative convergence var monitor = new Iterator<Complex>(new IIterationStopCriterium<Complex>[] { new IterationCountStopCriterium<Complex>(MaximumIterations), new ResidualStopCriterium(ConvergenceBoundary), new DivergenceStopCriterium(), new FailureStopCriterium() }); var solver = new MlkBiCgStab(monitor); // Solve equation Ax = y var x = solver.Solve(matrix, y); // Now compare the results Assert.IsNotNull(x, "#02"); Assert.AreEqual(y.Count, x.Count, "#03"); // Back multiply the vector var z = matrix.Multiply(x); // Check that the solution converged Assert.IsTrue(monitor.HasConverged, "#04"); // Now compare the vectors for (var i = 0; i < y.Count; i++) { Assert.IsTrue((y[i] - z[i]).Magnitude.IsSmaller(ConvergenceBoundary, 1), "#05-" + i); } }
public void CanSolveForRandomVector(int order) { var matrixA = MatrixLoader.GenerateRandomDenseMatrix(order, order); var vectorb = MatrixLoader.GenerateRandomDenseVector(order); var monitor = new Iterator<Complex>(new IIterationStopCriterium<Complex>[] { new IterationCountStopCriterium<Complex>(1000), new ResidualStopCriterium(1e-10), }); var solver = new MlkBiCgStab(monitor); var resultx = solver.Solve(matrixA, vectorb); Assert.AreEqual(matrixA.ColumnCount, resultx.Count); var matrixBReconstruct = matrixA*resultx; // Check the reconstruction. for (var i = 0; i < order; i++) { Assert.AreEqual(vectorb[i].Real, matrixBReconstruct[i].Real, 1e-5); Assert.AreEqual(vectorb[i].Imaginary, matrixBReconstruct[i].Imaginary, 1e-5); } }
public void DetermineStatusWithNegativeIterationNumberThrowsArgumentOutOfRangeException() { var criteria = new List<IIterationStopCriterium<Complex>> { new FailureStopCriterium(), new DivergenceStopCriterium(), new IterationCountStopCriterium<Complex>(), new ResidualStopCriterium() }; var iterator = new Iterator<Complex>(criteria); Assert.Throws<ArgumentOutOfRangeException>(() => iterator.DetermineStatus( -1, DenseVector.Create(3, i => 4), DenseVector.Create(3, i => 5), DenseVector.Create(3, i => 6))); }
public void ResetToPrecalculationState() { var criteria = new List<IIterationStopCriterium<Complex>> { new FailureStopCriterium(), new DivergenceStopCriterium(), new IterationCountStopCriterium<Complex>(1) }; var iterator = new Iterator<Complex>(criteria); // First step, nothing should happen. iterator.DetermineStatus( 0, DenseVector.Create(3, i => 4), DenseVector.Create(3, i => 4), DenseVector.Create(3, i => 4)); Assert.AreEqual(IterationStatus.Continue, iterator.Status, "Incorrect status"); iterator.Reset(); Assert.AreEqual(IterationStatus.Continue, iterator.Status, "Incorrect status"); Assert.AreEqual(IterationStatus.Continue, criteria[0].Status, "Incorrect status"); Assert.AreEqual(IterationStatus.Continue, criteria[1].Status, "Incorrect status"); Assert.AreEqual(IterationStatus.Continue, criteria[2].Status, "Incorrect status"); }
public void DetermineStatusWithoutStopCriteriaDoesNotThrow() { var iterator = new Iterator<Complex>(); Assert.DoesNotThrow(() => iterator.DetermineStatus( 0, DenseVector.Create(3, i => 4), DenseVector.Create(3, i => 5), DenseVector.Create(3, i => 6))); }
/// <summary> /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the /// solution vector and x is the unknown vector. /// </summary> /// <param name="matrix">The coefficient matrix, <c>A</c>.</param> /// <param name="input">The solution vector, <c>b</c></param> /// <param name="result">The result vector, <c>x</c></param> /// <param name="iterator">The iterator to use to control when to stop iterating.</param> /// <param name="preconditioner">The preconditioner to use for approximations.</param> public void Solve(Matrix <Complex> matrix, Vector <Complex> input, Vector <Complex> result, Iterator <Complex> iterator, IPreconditioner <Complex> preconditioner) { if (matrix.RowCount != matrix.ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSquare, nameof(matrix)); } if (result.Count != input.Count) { throw new ArgumentException(Resources.ArgumentVectorsSameLength); } if (iterator == null) { iterator = new Iterator <Complex>(); } if (preconditioner == null) { preconditioner = new UnitPreconditioner <Complex>(); } // Create a copy of the solution and result vectors so we can use them // later on var internalInput = input.Clone(); var internalResult = result.Clone(); foreach (var solver in _solvers) { // Store a reference to the solver so we can stop it. IterationStatus status; try { // Reset the iterator and pass it to the solver iterator.Reset(); // Start the solver solver.Item1.Solve(matrix, internalInput, internalResult, iterator, solver.Item2 ?? preconditioner); status = iterator.Status; } catch (Exception) { // The solver broke down. // Log a message about this // Switch to the next preconditioner. // Reset the solution vector to the previous solution input.CopyTo(internalInput); continue; } // There was no fatal breakdown so check the status if (status == IterationStatus.Converged) { // We're done internalResult.CopyTo(result); break; } // We're not done // Either: // - calculation finished without convergence if (status == IterationStatus.StoppedWithoutConvergence) { // Copy the internal result to the result vector and // continue with the calculation. internalResult.CopyTo(result); } else { // - calculation failed --> restart with the original vector // - calculation diverged --> restart with the original vector // - Some unknown status occurred --> To be safe restart. input.CopyTo(internalInput); } } }