forked from tsai/mathnet-numerics
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
9.1 KiB
261 lines
9.1 KiB
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
|
|
{
|
|
using LinearAlgebra.Double;
|
|
using LinearAlgebra.Double.Solvers;
|
|
using LinearAlgebra.Double.Solvers.Iterative;
|
|
using LinearAlgebra.Double.Solvers.Status;
|
|
using LinearAlgebra.Double.Solvers.StopCriterium;
|
|
using MbUnit.Framework;
|
|
|
|
[TestFixture]
|
|
public class MlkBiCgStabTest
|
|
{
|
|
private const double ConvergenceBoundary = 1e-10;
|
|
private const int MaximumIterations = 1000;
|
|
|
|
[Test]
|
|
[ExpectedArgumentException]
|
|
public void SolveWideMatrix()
|
|
{
|
|
var matrix = new SparseMatrix(2, 3);
|
|
Vector input = new DenseVector(2);
|
|
|
|
var solver = new MlkBiCgStab();
|
|
solver.Solve(matrix, input);
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedArgumentException]
|
|
public void SolveLongMatrix()
|
|
{
|
|
var matrix = new SparseMatrix(3, 2);
|
|
Vector input = new DenseVector(3);
|
|
|
|
var solver = new MlkBiCgStab();
|
|
solver.Solve(matrix, input);
|
|
}
|
|
|
|
[Test]
|
|
[MultipleAsserts]
|
|
public void SolveUnitMatrixAndBackMultiply()
|
|
{
|
|
// Create the identity matrix
|
|
Matrix matrix = SparseMatrix.Identity(100);
|
|
|
|
// Create the y vector
|
|
Vector y = new DenseVector(matrix.RowCount, 1);
|
|
|
|
// Create an iteration monitor which will keep track of iterative convergence
|
|
var monitor = new Iterator(new IIterationStopCriterium[]
|
|
{
|
|
new IterationCountStopCriterium(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.Status is CalculationConverged, "#04");
|
|
|
|
// Now compare the vectors
|
|
for (var i = 0; i < y.Count; i++)
|
|
{
|
|
Assert.IsTrue((y[i] - z[i]).IsSmaller(ConvergenceBoundary, 1), "#05-" + i);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
[MultipleAsserts]
|
|
public void SolveScaledUnitMatrixAndBackMultiply()
|
|
{
|
|
// Create the identity matrix
|
|
Matrix matrix = SparseMatrix.Identity(100);
|
|
|
|
// Scale it with a funny number
|
|
matrix.Multiply(System.Math.PI);
|
|
|
|
// Create the y vector
|
|
Vector y = new DenseVector(matrix.RowCount, 1);
|
|
|
|
// Create an iteration monitor which will keep track of iterative convergence
|
|
var monitor = new Iterator(new IIterationStopCriterium[]
|
|
{
|
|
new IterationCountStopCriterium(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.Status is CalculationConverged, "#04");
|
|
|
|
// Now compare the vectors
|
|
for (var i = 0; i < y.Count; i++)
|
|
{
|
|
Assert.IsTrue((y[i] - z[i]).IsSmaller(ConvergenceBoundary, 1), "#05-" + i);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
[MultipleAsserts]
|
|
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
|
|
Vector y = new DenseVector(matrix.RowCount, 1);
|
|
|
|
// Create an iteration monitor which will keep track of iterative convergence
|
|
var monitor = new Iterator(new IIterationStopCriterium[]
|
|
{
|
|
new IterationCountStopCriterium(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.Status is CalculationConverged, "#04");
|
|
|
|
// Now compare the vectors
|
|
for (var i = 0; i < y.Count; i++)
|
|
{
|
|
Assert.IsTrue(System.Math.Abs(y[i] - z[i]).IsSmaller(ConvergenceBoundary, 1), "#05-" + i);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
[Row(4)]
|
|
[Row(8)]
|
|
[Row(10)]
|
|
[MultipleAsserts]
|
|
public void CanSolveForRandomVector(int order)
|
|
{
|
|
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(order, order);
|
|
var vectorb = MatrixLoader.GenerateRandomDenseVector(order);
|
|
|
|
var monitor = new Iterator(new IIterationStopCriterium[]
|
|
{
|
|
new IterationCountStopCriterium(1000),
|
|
new ResidualStopCriterium(1e-10),
|
|
});
|
|
var solver = new MlkBiCgStab(monitor);
|
|
|
|
var resultx = solver.Solve(matrixA, vectorb);
|
|
Assert.AreEqual(matrixA.ColumnCount, resultx.Count);
|
|
|
|
var bReconstruct = matrixA * resultx;
|
|
|
|
// Check the reconstruction.
|
|
for (var i = 0; i < order; i++)
|
|
{
|
|
Assert.AreApproximatelyEqual(vectorb[i], bReconstruct[i], 1e-7);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
[Row(4)]
|
|
[Row(8)]
|
|
[Row(10)]
|
|
[MultipleAsserts]
|
|
public void CanSolveForRandomMatrix(int order)
|
|
{
|
|
var matrixA = MatrixLoader.GenerateRandomDenseMatrix(order, order);
|
|
var matrixB = MatrixLoader.GenerateRandomDenseMatrix(order, order);
|
|
|
|
var monitor = new Iterator(new IIterationStopCriterium[]
|
|
{
|
|
new IterationCountStopCriterium(1000),
|
|
new ResidualStopCriterium(1e-10)
|
|
});
|
|
var solver = new MlkBiCgStab(monitor);
|
|
var matrixX = solver.Solve(matrixA, matrixB);
|
|
|
|
// 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.AreApproximatelyEqual(matrixB[i, j], matrixBReconstruct[i, j], 1.0e-7);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|