Browse Source

LA: iterative solver no longer stateful on preconditioner

pull/163/head
Christoph Ruegg 13 years ago
parent
commit
c035c55dd7
  1. 12
      src/Examples/LinearAlgebra/IterativeSolvers/CompositeSolverExample.cs
  2. 65
      src/Numerics/LinearAlgebra/Complex/Solvers/BiCgStab.cs
  3. 329
      src/Numerics/LinearAlgebra/Complex/Solvers/CompositeSolver.cs
  4. 67
      src/Numerics/LinearAlgebra/Complex/Solvers/GpBiCg.cs
  5. 68
      src/Numerics/LinearAlgebra/Complex/Solvers/MlkBiCgStab.cs
  6. 71
      src/Numerics/LinearAlgebra/Complex/Solvers/TFQMR.cs
  7. 66
      src/Numerics/LinearAlgebra/Complex32/Solvers/BiCgStab.cs
  8. 328
      src/Numerics/LinearAlgebra/Complex32/Solvers/CompositeSolver.cs
  9. 72
      src/Numerics/LinearAlgebra/Complex32/Solvers/GpBiCg.cs
  10. 68
      src/Numerics/LinearAlgebra/Complex32/Solvers/MlkBiCgStab.cs
  11. 71
      src/Numerics/LinearAlgebra/Complex32/Solvers/TFQMR.cs
  12. 65
      src/Numerics/LinearAlgebra/Double/Solvers/BiCgStab.cs
  13. 336
      src/Numerics/LinearAlgebra/Double/Solvers/CompositeSolver.cs
  14. 67
      src/Numerics/LinearAlgebra/Double/Solvers/GpBiCg.cs
  15. 67
      src/Numerics/LinearAlgebra/Double/Solvers/MlkBiCgStab.cs
  16. 71
      src/Numerics/LinearAlgebra/Double/Solvers/TFQMR.cs
  17. 65
      src/Numerics/LinearAlgebra/Single/Solvers/BiCgStab.cs
  18. 330
      src/Numerics/LinearAlgebra/Single/Solvers/CompositeSolver.cs
  19. 67
      src/Numerics/LinearAlgebra/Single/Solvers/GpBiCg.cs
  20. 67
      src/Numerics/LinearAlgebra/Single/Solvers/MlkBiCgStab.cs
  21. 71
      src/Numerics/LinearAlgebra/Single/Solvers/TFQMR.cs
  22. 8
      src/Numerics/LinearAlgebra/Solvers/IIterativeSolver.cs
  23. 11
      src/Numerics/LinearAlgebra/Solvers/IIterativeSolverSetup.cs
  24. 138
      src/Numerics/LinearAlgebra/Solvers/SolverSetup.cs
  25. 1
      src/Numerics/Numerics.csproj

12
src/Examples/LinearAlgebra/IterativeSolvers/CompositeSolverExample.cs

@ -109,10 +109,7 @@ namespace Examples.LinearAlgebra.IterativeSolversExamples
// Load all suitable solvers from current assembly. Below in this example, there is user-defined solver
// "class UserBiCgStab : IIterativeSolverSetup<double>" which uses regular BiCgStab solver. But user may create any other solver
// and solver setup classes which implement IIterativeSolverSetup<T> and pass assembly to next function:
CompositeSolver.LoadSolverInformationFromAssembly(Assembly.GetExecutingAssembly());
// Create composite solver
var solver = new CompositeSolver();
var solver = new CompositeSolver(SolverSetup<double>.LoadFromAssembly(Assembly.GetExecutingAssembly()));
// 1. Solve the matrix equation
var resultX = solver.Solve(matrixA, vectorB, monitor);
@ -178,11 +175,16 @@ namespace Examples.LinearAlgebra.IterativeSolversExamples
/// given by this setup.
/// </summary>
/// <returns>A new <see cref="IIterativeSolver{T}"/>.</returns>
public IIterativeSolver<double> CreateNew()
public IIterativeSolver<double> CreateSolver()
{
return new BiCgStab();
}
public IPreConditioner<double> CreatePreconditioner()
{
return null;
}
/// <summary>
/// Gets the relative speed of the solver.
/// </summary>

65
src/Numerics/LinearAlgebra/Complex/Solvers/BiCgStab.cs

@ -72,12 +72,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </remarks>
public sealed class BiCgStab : IIterativeSolver<Complex>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<Complex> _preconditioner;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
@ -94,36 +88,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation. </param>
public BiCgStab(IPreConditioner<Complex> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<Complex> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -142,10 +106,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="vector">The solution <see cref="Vector"/>, <c>b</c>.</param>
/// <returns>The result <see cref="Vector"/>, <c>x</c>.</returns>
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null)
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -156,7 +120,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
/// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -201,12 +165,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<Complex>();
preconditioner = new UnitPreconditioner<Complex>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector
@ -270,7 +234,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
// SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash);
preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~
matrix.Multiply(vecPdash, nu);
@ -314,7 +278,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
// SOLVE Ms~ = s
_preconditioner.Approximate(vecS, vecSdash);
preconditioner.Approximate(vecS, vecSdash);
// temp = As~
matrix.Multiply(vecSdash, temp);
@ -407,10 +371,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Matrix"/>, <c>B</c>.</param>
/// <returns>The result <see cref="Matrix"/>, <c>X</c>.</returns>
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null)
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -421,7 +385,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Matrix"/>, <c>B</c>.</param>
/// <param name="result">The result <see cref="Matrix"/>, <c>X</c></param>
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -433,9 +397,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Complex>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

329
src/Numerics/LinearAlgebra/Complex/Solvers/CompositeSolver.cs

@ -30,9 +30,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.Properties;
@ -43,7 +41,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#endif
/// <summary>
@ -63,276 +60,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </remarks>
public sealed class CompositeSolver : IIterativeSolver<Complex>
{
#region Internal class - DoubleComparer
/// <summary>
/// An <c>IComparer</c> used to compare double precision floating points.
/// </summary>
/// NOTE: The instance of this class is used only in <see cref="SolverSetups"/>. If C# suppports interface inheritence
/// NOTE: and methods in anonymous types, then this class should be deleted and anonymous type implemented with IComaprer support
/// NOTE: in <see cref="SolverSetups"/> constructor
public sealed class DoubleComparer : IComparer<double>
{
/// <summary>
/// Compares two double values based on the selected comparison method.
/// </summary>
/// <param name="x">The first double to compare.</param>
/// <param name="y">The second double to compare.</param>
/// <returns>
/// A 32-bit signed integer that indicates the relative order of the objects being compared. The return
/// value has the following meanings:
/// Value Meaning Less than zero This object is less than the other parameter.
/// Zero This object is equal to other.
/// Greater than zero This object is greater than other.
/// </returns>
public int Compare(double x, double y)
{
return x.CompareTo(y, 1);
}
}
#endregion
#if PORTABLE
private static readonly Dictionary<double, List<IIterativeSolverSetup<Complex>>> SolverSetups = new Dictionary<double, List<IIterativeSolverSetup<Complex>>>();
#else
/// <summary>
/// The collection of iterative solver setups. Stored based on the
/// ratio between the relative speed and relative accuracy.
/// </summary>
static readonly SortedList<double, List<IIterativeSolverSetup<Complex>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<Complex>>>(new DoubleComparer());
#endif
#region Solver information loading methods
/// <summary>
/// Loads all the available <see cref="IIterativeSolverSetup{T}"/> objects from the MathNet.Numerics assembly.
/// </summary>
public static void LoadSolverInformation()
{
LoadSolverInformation(new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the MathNet.Numerics assembly.
/// </summary>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformation(Type[] typesToExclude)
{
LoadSolverInformationFromAssembly(Assembly.GetExecutingAssembly(), typesToExclude);
}
#if !PORTABLE
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the file location.
/// </summary>
/// <param name="assemblyLocation">The fully qualified path to the assembly.</param>
public static void LoadSolverInformationFromAssembly(string assemblyLocation)
{
LoadSolverInformationFromAssembly(assemblyLocation, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the file location.
/// </summary>
/// <param name="assemblyLocation">The fully qualified path to the assembly.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded. </param>
public static void LoadSolverInformationFromAssembly(string assemblyLocation, params Type[] typesToExclude)
{
if (assemblyLocation == null)
{
throw new ArgumentNullException("assemblyLocation");
}
if (assemblyLocation.Length == 0)
{
throw new ArgumentException();
}
if (!File.Exists(assemblyLocation))
{
throw new FileNotFoundException();
}
// Get the assembly name
var assemblyFileName = Path.GetFileNameWithoutExtension(assemblyLocation);
// Now load the assembly with an AssemblyName
var assemblyName = new AssemblyName(assemblyFileName);
var assembly = Assembly.Load(assemblyName.FullName);
// <ay throws:
// ArgumentNullException --> Can't get this because we checked that the file exists.
// FileNotFoundException --> Can't get this because we checked that the file exists.
// FileLoadException
// BadImageFormatException
// Now we can load the solver information.
LoadSolverInformationFromAssembly(assembly, typesToExclude);
}
#endif
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the assembly name.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects. </param>
public static void LoadSolverInformationFromAssembly(AssemblyName assemblyName)
{
LoadSolverInformationFromAssembly(assemblyName, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the assembly name.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(AssemblyName assemblyName, params Type[] typesToExclude)
{
if (assemblyName == null)
{
throw new ArgumentNullException("assemblyName");
}
var assembly = Assembly.Load(assemblyName.FullName);
// May throw:
// ArgumentNullException --> Can't get this because we checked it.
// FileNotFoundException
// FileLoadException
// BadImageFormatException
// Now we can load the solver information.
LoadSolverInformationFromAssembly(assembly, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the type.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
public static void LoadSolverInformationFromAssembly(Type typeInAssembly)
{
LoadSolverInformationFromAssembly(typeInAssembly, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the type.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(Type typeInAssembly, params Type[] typesToExclude)
{
if (typeInAssembly == null)
{
throw new ArgumentNullException("typeInAssembly");
}
LoadSolverInformationFromAssembly(typeInAssembly.Assembly, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
public static void LoadSolverInformationFromAssembly(Assembly assembly)
{
LoadSolverInformationFromAssembly(assembly, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(Assembly assembly, params Type[] typesToExclude)
{
if (assembly == null)
{
throw new ArgumentNullException("assembly");
}
if (typesToExclude == null)
{
throw new ArgumentNullException("typesToExclude");
}
var excludedTypes = new List<Type>(typesToExclude);
// Load all the types in the assembly
// Find all the types that implement IIterativeSolverSetup
// Create an object of each of these types
// Get the type of the iterative solver that will be instantiated by the setup object
// Check if it's on the excluding list, if so throw the setup object away otherwise keep it.
var interfaceTypes = new List<Type>();
foreach (var type in assembly.GetTypes().Where(type => (!type.IsAbstract && !type.IsEnum && !type.IsInterface && type.IsVisible)))
{
interfaceTypes.Clear();
interfaceTypes.AddRange(type.GetInterfaces());
if (!interfaceTypes.Any(match => typeof (IIterativeSolverSetup<Complex>).IsAssignableFrom(match)))
{
continue;
}
// See if we actually want this type of iterative solver
IIterativeSolverSetup<Complex> setup;
try
{
// If something goes wrong we just ignore it and move on with the next type.
// There should probably be a log somewhere indicating that something went wrong?
setup = (IIterativeSolverSetup<Complex>) Activator.CreateInstance(type);
}
catch (ArgumentException)
{
continue;
}
catch (NotSupportedException)
{
continue;
}
catch (TargetInvocationException)
{
continue;
}
#if !PORTABLE
catch (MethodAccessException)
{
continue;
}
catch (MissingMethodException)
{
continue;
}
#endif
catch (MemberAccessException)
{
continue;
}
catch (TypeLoadException)
{
continue;
}
if (excludedTypes.Any(match => match.IsAssignableFrom(setup.SolverType) ||
match.IsAssignableFrom(setup.PreconditionerType)))
{
continue;
}
// Ok we want the solver, so store the object
var ratio = setup.SolutionSpeed/setup.Reliability;
if (!SolverSetups.ContainsKey(ratio))
{
SolverSetups.Add(ratio, new List<IIterativeSolverSetup<Complex>>());
}
var list = SolverSetups[ratio];
list.Add(setup);
}
}
#endregion
/// <summary>
/// The collection of solvers that will be used to
/// The collection of solvers that will be used
/// </summary>
readonly List<IIterativeSolver<Complex>> _solvers = new List<IIterativeSolver<Complex>>();
readonly List<Tuple<IIterativeSolver<Complex>, IPreConditioner<Complex>>> _solvers;
/// <summary>
/// The status of the calculation.
@ -350,11 +81,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </summary>
IIterativeSolver<Complex> _currentSolver;
/// <summary>
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the default iterator.
/// </summary>
public CompositeSolver()
public CompositeSolver(IEnumerable<IIterativeSolverSetup<Complex>> solvers)
{
_solvers = solvers.Select(setup => new Tuple<IIterativeSolver<Complex>, IPreConditioner<Complex>>(setup.CreateSolver(), setup.CreatePreconditioner() ?? new UnitPreconditioner<Complex>())).ToList();
}
/// <summary>
@ -380,10 +109,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null)
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -394,7 +123,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <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>
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -419,13 +148,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
// Load the solvers into our own internal data structure
// Once we have solvers we can always reuse them.
if (_solvers.Count == 0)
{
LoadSolvers();
}
// Create a copy of the solution and result vectors so we can use them
// later on
var internalInput = input.Clone();
@ -434,7 +156,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
foreach (var solver in _solvers.TakeWhile(solver => !_hasBeenStopped))
{
// Store a reference to the solver so we can stop it.
_currentSolver = solver;
_currentSolver = solver.Item1;
try
{
@ -442,7 +164,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator.Reset();
// Start the solver
solver.Solve(matrix, internalInput, internalResult, iterator);
solver.Item1.Solve(matrix, internalInput, internalResult, iterator, solver.Item2);
_status = iterator.Status;
}
catch (Exception)
@ -490,26 +212,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
_currentSolver = null;
}
/// <summary>
/// Load solvers
/// </summary>
void LoadSolvers()
{
if (SolverSetups.Count == 0)
{
throw new Exception("IIterativeSolverSetup objects not found");
}
#if PORTABLE
foreach (var setup in SolverSetups.OrderBy(solver => solver.Key, new DoubleComparer()).Select(pair => pair.Value).SelectMany(setups => setups))
#else
foreach (var setup in SolverSetups.Select(pair => pair.Value).SelectMany(setups => setups))
#endif
{
_solvers.Add(setup.CreateNew());
}
}
/// <summary>
/// Solves the matrix equation AX = B, where A is the coefficient matrix, B is the
/// solution matrix and X is the unknown matrix.
@ -517,10 +219,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null)
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -531,7 +233,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -543,9 +245,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Complex>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

67
src/Numerics/LinearAlgebra/Complex/Solvers/GpBiCg.cs

@ -70,12 +70,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </remarks>
public sealed class GpBiCg : IIterativeSolver<Complex>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <c>null</c>, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<Complex> _preconditioner;
/// <summary>
/// Indicates the number of <c>BiCGStab</c> steps should be taken
/// before switching.
@ -104,27 +98,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public GpBiCg(IPreConditioner<Complex> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets the number of steps taken with the <c>BiCgStab</c> algorithm
/// before switching over to the <c>GPBiCG</c> algorithm.
@ -163,15 +136,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<Complex> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -191,10 +155,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null)
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -205,7 +169,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <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>
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -245,12 +209,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<Complex>();
preconditioner = new UnitPreconditioner<Complex>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// x_0 is initial guess
// Take x_0 = 0
@ -298,7 +262,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
residuals.Add(temp2, p);
// Solve M b_k = p_k
_preconditioner.Approximate(p, temp);
preconditioner.Approximate(p, temp);
// s_k = A b_k
matrix.Multiply(temp, s);
@ -322,7 +286,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
residuals.Add(temp2, t);
// Solve M d_k = t_k
_preconditioner.Approximate(t, temp);
preconditioner.Approximate(t, temp);
// c_k = A d_k
matrix.Multiply(temp, c);
@ -427,7 +391,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
c.Add(temp2, w);
// Get the real value
_preconditioner.Approximate(xtemp, result);
preconditioner.Approximate(xtemp, result);
// Now check for convergence
if (!ShouldContinue(iterator, iterationNumber, result, input, residuals))
@ -507,10 +471,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null)
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -521,7 +485,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -533,9 +497,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Complex>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

68
src/Numerics/LinearAlgebra/Complex/Solvers/MlkBiCgStab.cs

@ -32,6 +32,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.Properties;
@ -76,12 +77,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </summary>
const int DefaultNumberOfStartingVectors = 50;
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<Complex> _preconditioner;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary>
@ -108,27 +103,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public MlkBiCgStab(IPreConditioner<Complex> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets the number of starting vectors.
/// </summary>
@ -161,15 +135,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
_numberOfStartingVectors = DefaultNumberOfStartingVectors;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<Complex> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets a series of orthonormal vectors which will be used as basis for the
/// Krylov sub-space.
@ -211,10 +176,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null)
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -225,7 +190,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <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>
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -265,12 +230,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<Complex>();
preconditioner = new UnitPreconditioner<Complex>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// Choose an initial guess x_0
// Take x_0 = 0
@ -335,7 +300,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
while (ShouldContinue(iterator, iterationNumber, xtemp, input, residuals))
{
// SOLVE M g~_((j-1)k+k) = g_((j-1)k+k)
_preconditioner.Approximate(g[k - 1], gtemp);
preconditioner.Approximate(g[k - 1], gtemp);
// w_((j-1)k+k) = A g~_((j-1)k+k)
matrix.Multiply(gtemp, w[k - 1]);
@ -355,7 +320,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
residuals.Add(temp, u);
// SOLVE M u~_(jk+1) = u_(jk+1)
_preconditioner.Approximate(u, temp1);
preconditioner.Approximate(u, temp1);
temp1.CopyTo(utemp);
// rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
@ -509,7 +474,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
temp2.CopyTo(u);
// SOLVE M g~_(jk+i) = g_(jk+i)
_preconditioner.Approximate(g[i], gtemp);
preconditioner.Approximate(g[i], gtemp);
// x_(jk+i+1) = x_(jk+i) + rho_(j+1) alpha_(jk+i+1) g~_(jk+i)
gtemp.Multiply(rho*alpha, temp);
@ -672,10 +637,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null)
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -686,7 +651,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -698,9 +663,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Complex>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

71
src/Numerics/LinearAlgebra/Complex/Solvers/TFQMR.cs

@ -61,12 +61,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </remarks>
public sealed class TFQMR : IIterativeSolver<Complex>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<Complex> _preconditioner;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
@ -83,36 +77,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public TFQMR(IPreConditioner<Complex> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<Complex> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -131,10 +95,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null)
public Vector<Complex> Solve(Matrix<Complex> matrix, Vector<Complex> vector, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -145,7 +109,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <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>
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Vector<Complex> input, Vector<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -185,12 +149,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<Complex>();
preconditioner = new UnitPreconditioner<Complex>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
var d = new DenseVector(input.Count);
var r = DenseVector.OfVector(input);
@ -221,7 +185,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
// Calculate the initial values for v
// M temp = yEven
_preconditioner.Approximate(yeven, temp);
preconditioner.Approximate(yeven, temp);
// v = A temp
matrix.Multiply(temp, v);
@ -253,7 +217,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
yeven.Add(temp1, yodd);
// Solve M temp = yOdd
_preconditioner.Approximate(yodd, temp);
preconditioner.Approximate(yodd, temp);
// uOdd = A temp
matrix.Multiply(temp, uodd);
@ -293,7 +257,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
if (!ShouldContinue(iterator, iterationNumber, result, input, pseudoResiduals))
{
// Calculate the real values
_preconditioner.Approximate(x, result);
preconditioner.Approximate(x, result);
// Calculate the true residual. Use the temp vector for that
// so that we don't pollute the pseudoResidual vector for no
@ -329,7 +293,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
pseudoResiduals.Add(temp1, yeven);
// Solve M temp = yOdd
_preconditioner.Approximate(yeven, temp);
preconditioner.Approximate(yeven, temp);
// uOdd = A temp
matrix.Multiply(temp, ueven);
@ -343,7 +307,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
// Calculate the real values
_preconditioner.Approximate(x, result);
preconditioner.Approximate(x, result);
iterationNumber++;
}
@ -407,10 +371,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null)
public Matrix<Complex> Solve(Matrix<Complex> matrix, Matrix<Complex> input, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -421,7 +385,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null)
public void Solve(Matrix<Complex> matrix, Matrix<Complex> input, Matrix<Complex> result, Iterator<Complex> iterator = null, IPreConditioner<Complex> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -433,9 +397,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
iterator = new Iterator<Complex>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Complex>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

66
src/Numerics/LinearAlgebra/Complex32/Solvers/BiCgStab.cs

@ -29,6 +29,7 @@
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Preconditioners;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.Properties;
@ -65,12 +66,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </remarks>
public sealed class BiCgStab : IIterativeSolver<Numerics.Complex32>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<Numerics.Complex32> _preconditioner;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
@ -87,36 +82,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation. </param>
public BiCgStab(IPreConditioner<Numerics.Complex32> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<Numerics.Complex32> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -135,10 +100,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="vector">The solution <see cref="Vector"/>, <c>b</c>.</param>
/// <returns>The result <see cref="Vector"/>, <c>x</c>.</returns>
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null)
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -149,7 +114,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
/// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -194,12 +159,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<Numerics.Complex32>();
preconditioner = new UnitPreconditioner<Numerics.Complex32>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector
@ -263,7 +228,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
// SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash);
preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~
matrix.Multiply(vecPdash, nu);
@ -307,7 +272,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
// SOLVE Ms~ = s
_preconditioner.Approximate(vecS, vecSdash);
preconditioner.Approximate(vecS, vecSdash);
// temp = As~
matrix.Multiply(vecSdash, temp);
@ -400,10 +365,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Matrix"/>, <c>B</c>.</param>
/// <returns>The result <see cref="Matrix"/>, <c>X</c>.</returns>
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null)
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -414,7 +379,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Matrix"/>, <c>B</c>.</param>
/// <param name="result">The result <see cref="Matrix"/>, <c>X</c></param>
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -426,9 +391,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Numerics.Complex32>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

328
src/Numerics/LinearAlgebra/Complex32/Solvers/CompositeSolver.cs

@ -30,9 +30,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.Properties;
@ -55,276 +53,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </remarks>
public sealed class CompositeSolver : IIterativeSolver<Numerics.Complex32>
{
#region Internal class - DoubleComparer
/// <summary>
/// An <c>IComparer</c> used to compare double precision floating points.
/// </summary>
/// NOTE: The instance of this class is used only in <see cref="SolverSetups"/>. If C# suppports interface inheritence
/// NOTE: and methods in anonymous types, then this class should be deleted and anonymous type implemented with IComaprer support
/// NOTE: in <see cref="SolverSetups"/> constructor
public sealed class DoubleComparer : IComparer<double>
{
/// <summary>
/// Compares two double values based on the selected comparison method.
/// </summary>
/// <param name="x">The first double to compare.</param>
/// <param name="y">The second double to compare.</param>
/// <returns>
/// A 32-bit signed integer that indicates the relative order of the objects being compared. The return
/// value has the following meanings:
/// Value Meaning Less than zero This object is less than the other parameter.
/// Zero This object is equal to other.
/// Greater than zero This object is greater than other.
/// </returns>
public int Compare(double x, double y)
{
return x.CompareTo(y, 1);
}
}
#endregion
#if PORTABLE
private static readonly Dictionary<double, List<IIterativeSolverSetup<Numerics.Complex32>>> SolverSetups = new Dictionary<double, List<IIterativeSolverSetup<Numerics.Complex32>>>();
#else
/// <summary>
/// The collection of iterative solver setups. Stored based on the
/// ratio between the relative speed and relative accuracy.
/// The collection of solvers that will be used
/// </summary>
static readonly SortedList<double, List<IIterativeSolverSetup<Numerics.Complex32>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<Numerics.Complex32>>>(new DoubleComparer());
#endif
#region Solver information loading methods
/// <summary>
/// Loads all the available <see cref="IIterativeSolverSetup{T}"/> objects from the MathNet.Numerics assembly.
/// </summary>
public static void LoadSolverInformation()
{
LoadSolverInformation(new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the MathNet.Numerics assembly.
/// </summary>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformation(Type[] typesToExclude)
{
LoadSolverInformationFromAssembly(Assembly.GetExecutingAssembly(), typesToExclude);
}
#if !PORTABLE
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the file location.
/// </summary>
/// <param name="assemblyLocation">The fully qualified path to the assembly.</param>
public static void LoadSolverInformationFromAssembly(string assemblyLocation)
{
LoadSolverInformationFromAssembly(assemblyLocation, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the file location.
/// </summary>
/// <param name="assemblyLocation">The fully qualified path to the assembly.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded. </param>
public static void LoadSolverInformationFromAssembly(string assemblyLocation, params Type[] typesToExclude)
{
if (assemblyLocation == null)
{
throw new ArgumentNullException("assemblyLocation");
}
if (assemblyLocation.Length == 0)
{
throw new ArgumentException();
}
if (!File.Exists(assemblyLocation))
{
throw new FileNotFoundException();
}
// Get the assembly name
var assemblyFileName = Path.GetFileNameWithoutExtension(assemblyLocation);
// Now load the assembly with an AssemblyName
var assemblyName = new AssemblyName(assemblyFileName);
var assembly = Assembly.Load(assemblyName.FullName);
// <ay throws:
// ArgumentNullException --> Can't get this because we checked that the file exists.
// FileNotFoundException --> Can't get this because we checked that the file exists.
// FileLoadException
// BadImageFormatException
// Now we can load the solver information.
LoadSolverInformationFromAssembly(assembly, typesToExclude);
}
#endif
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the assembly name.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects. </param>
public static void LoadSolverInformationFromAssembly(AssemblyName assemblyName)
{
LoadSolverInformationFromAssembly(assemblyName, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the assembly name.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(AssemblyName assemblyName, params Type[] typesToExclude)
{
if (assemblyName == null)
{
throw new ArgumentNullException("assemblyName");
}
var assembly = Assembly.Load(assemblyName.FullName);
// May throw:
// ArgumentNullException --> Can't get this because we checked it.
// FileNotFoundException
// FileLoadException
// BadImageFormatException
// Now we can load the solver information.
LoadSolverInformationFromAssembly(assembly, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the type.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
public static void LoadSolverInformationFromAssembly(Type typeInAssembly)
{
LoadSolverInformationFromAssembly(typeInAssembly, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the type.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(Type typeInAssembly, params Type[] typesToExclude)
{
if (typeInAssembly == null)
{
throw new ArgumentNullException("typeInAssembly");
}
LoadSolverInformationFromAssembly(typeInAssembly.Assembly, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
public static void LoadSolverInformationFromAssembly(Assembly assembly)
{
LoadSolverInformationFromAssembly(assembly, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(Assembly assembly, params Type[] typesToExclude)
{
if (assembly == null)
{
throw new ArgumentNullException("assembly");
}
if (typesToExclude == null)
{
throw new ArgumentNullException("typesToExclude");
}
var excludedTypes = new List<Type>(typesToExclude);
// Load all the types in the assembly
// Find all the types that implement IIterativeSolverSetup
// Create an object of each of these types
// Get the type of the iterative solver that will be instantiated by the setup object
// Check if it's on the excluding list, if so throw the setup object away otherwise keep it.
var interfaceTypes = new List<Type>();
foreach (var type in assembly.GetTypes().Where(type => (!type.IsAbstract && !type.IsEnum && !type.IsInterface && type.IsVisible)))
{
interfaceTypes.Clear();
interfaceTypes.AddRange(type.GetInterfaces());
if (!interfaceTypes.Any(match => typeof (IIterativeSolverSetup<Numerics.Complex32>).IsAssignableFrom(match)))
{
continue;
}
// See if we actually want this type of iterative solver
IIterativeSolverSetup<Numerics.Complex32> setup;
try
{
// If something goes wrong we just ignore it and move on with the next type.
// There should probably be a log somewhere indicating that something went wrong?
setup = (IIterativeSolverSetup<Numerics.Complex32>) Activator.CreateInstance(type);
}
catch (ArgumentException)
{
continue;
}
catch (NotSupportedException)
{
continue;
}
catch (TargetInvocationException)
{
continue;
}
#if !PORTABLE
catch (MethodAccessException)
{
continue;
}
catch (MissingMethodException)
{
continue;
}
#endif
catch (MemberAccessException)
{
continue;
}
catch (TypeLoadException)
{
continue;
}
if (excludedTypes.Any(match => match.IsAssignableFrom(setup.SolverType) ||
match.IsAssignableFrom(setup.PreconditionerType)))
{
continue;
}
// Ok we want the solver, so store the object
var ratio = setup.SolutionSpeed/setup.Reliability;
if (!SolverSetups.ContainsKey(ratio))
{
SolverSetups.Add(ratio, new List<IIterativeSolverSetup<Numerics.Complex32>>());
}
var list = SolverSetups[ratio];
list.Add(setup);
}
}
#endregion
/// <summary>
/// The collection of solvers that will be used to
/// </summary>
readonly List<IIterativeSolver<Numerics.Complex32>> _solvers = new List<IIterativeSolver<Numerics.Complex32>>();
readonly List<Tuple<IIterativeSolver<Numerics.Complex32>, IPreConditioner<Numerics.Complex32>>> _solvers;
/// <summary>
/// The status of the calculation.
@ -342,11 +74,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </summary>
IIterativeSolver<Numerics.Complex32> _currentSolver;
/// <summary>
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the default iterator.
/// </summary>
public CompositeSolver()
public CompositeSolver(IEnumerable<IIterativeSolverSetup<Numerics.Complex32>> solvers)
{
_solvers = solvers.Select(setup => new Tuple<IIterativeSolver<Numerics.Complex32>, IPreConditioner<Numerics.Complex32>>(setup.CreateSolver(), setup.CreatePreconditioner() ?? new UnitPreconditioner<Numerics.Complex32>())).ToList();
}
/// <summary>
@ -372,10 +102,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null)
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -386,7 +116,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <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>
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -411,13 +141,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
// Load the solvers into our own internal data structure
// Once we have solvers we can always reuse them.
if (_solvers.Count == 0)
{
LoadSolvers();
}
// Create a copy of the solution and result vectors so we can use them
// later on
var internalInput = input.Clone();
@ -426,7 +149,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
foreach (var solver in _solvers.TakeWhile(solver => !_hasBeenStopped))
{
// Store a reference to the solver so we can stop it.
_currentSolver = solver;
_currentSolver = solver.Item1;
try
{
@ -434,7 +157,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator.Reset();
// Start the solver
solver.Solve(matrix, internalInput, internalResult, iterator);
solver.Item1.Solve(matrix, internalInput, internalResult, iterator, solver.Item2);
_status = iterator.Status;
}
catch (Exception)
@ -482,26 +205,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
_currentSolver = null;
}
/// <summary>
/// Load solvers
/// </summary>
void LoadSolvers()
{
if (SolverSetups.Count == 0)
{
throw new Exception("IIterativeSolverSetup objects not found");
}
#if PORTABLE
foreach (var setup in SolverSetups.OrderBy(solver => solver.Key, new DoubleComparer()).Select(pair => pair.Value).SelectMany(setups => setups))
#else
foreach (var setup in SolverSetups.Select(pair => pair.Value).SelectMany(setups => setups))
#endif
{
_solvers.Add(setup.CreateNew());
}
}
/// <summary>
/// Solves the matrix equation AX = B, where A is the coefficient matrix, B is the
/// solution matrix and X is the unknown matrix.
@ -509,10 +212,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null)
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -523,7 +226,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -535,9 +238,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Numerics.Complex32>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

72
src/Numerics/LinearAlgebra/Complex32/Solvers/GpBiCg.cs

@ -63,12 +63,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </remarks>
public sealed class GpBiCg : IIterativeSolver<Numerics.Complex32>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <c>null</c>, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<Numerics.Complex32> _preconditioner;
/// <summary>
/// Indicates the number of <c>BiCGStab</c> steps should be taken
/// before switching.
@ -97,27 +91,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public GpBiCg(IPreConditioner<Numerics.Complex32> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets the number of steps taken with the <c>BiCgStab</c> algorithm
/// before switching over to the <c>GPBiCG</c> algorithm.
@ -156,15 +129,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<Numerics.Complex32> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -184,10 +148,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null)
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -198,7 +162,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <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>
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -243,12 +207,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<Numerics.Complex32>();
preconditioner = new UnitPreconditioner<Numerics.Complex32>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// x_0 is initial guess
// Take x_0 = 0
@ -296,7 +260,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
residuals.Add(temp2, p);
// Solve M b_k = p_k
_preconditioner.Approximate(p, temp);
preconditioner.Approximate(p, temp);
// s_k = A b_k
matrix.Multiply(temp, s);
@ -320,7 +284,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
residuals.Add(temp2, t);
// Solve M d_k = t_k
_preconditioner.Approximate(t, temp);
preconditioner.Approximate(t, temp);
// c_k = A d_k
matrix.Multiply(temp, c);
@ -425,7 +389,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
c.Add(temp2, w);
// Get the real value
_preconditioner.Approximate(xtemp, result);
preconditioner.Approximate(xtemp, result);
// Now check for convergence
if (!ShouldContinue(iterator, iterationNumber, result, input, residuals))
@ -505,10 +469,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null)
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -519,16 +483,26 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
throw Matrix.DimensionsDontMatch<ArgumentException>(matrix, input, result);
}
if (iterator == null)
{
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Numerics.Complex32>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

68
src/Numerics/LinearAlgebra/Complex32/Solvers/MlkBiCgStab.cs

@ -33,6 +33,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Preconditioners;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.Properties;
@ -68,12 +69,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </summary>
const int DefaultNumberOfStartingVectors = 50;
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<Numerics.Complex32> _preconditioner;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary>
@ -100,27 +95,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public MlkBiCgStab(IPreConditioner<Numerics.Complex32> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets the number of starting vectors.
/// </summary>
@ -153,15 +127,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
_numberOfStartingVectors = DefaultNumberOfStartingVectors;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<Numerics.Complex32> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets a series of orthonormal vectors which will be used as basis for the
/// Krylov sub-space.
@ -203,10 +168,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null)
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -217,7 +182,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <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>
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -262,12 +227,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<Numerics.Complex32>();
preconditioner = new UnitPreconditioner<Numerics.Complex32>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// Choose an initial guess x_0
// Take x_0 = 0
@ -332,7 +297,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
while (ShouldContinue(iterator, iterationNumber, xtemp, input, residuals))
{
// SOLVE M g~_((j-1)k+k) = g_((j-1)k+k)
_preconditioner.Approximate(g[k - 1], gtemp);
preconditioner.Approximate(g[k - 1], gtemp);
// w_((j-1)k+k) = A g~_((j-1)k+k)
matrix.Multiply(gtemp, w[k - 1]);
@ -352,7 +317,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
residuals.Add(temp, u);
// SOLVE M u~_(jk+1) = u_(jk+1)
_preconditioner.Approximate(u, temp1);
preconditioner.Approximate(u, temp1);
temp1.CopyTo(utemp);
// rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
@ -506,7 +471,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
temp2.CopyTo(u);
// SOLVE M g~_(jk+i) = g_(jk+i)
_preconditioner.Approximate(g[i], gtemp);
preconditioner.Approximate(g[i], gtemp);
// x_(jk+i+1) = x_(jk+i) + rho_(j+1) alpha_(jk+i+1) g~_(jk+i)
gtemp.Multiply(rho*alpha, temp);
@ -669,10 +634,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null)
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -683,7 +648,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -695,9 +660,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Numerics.Complex32>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

71
src/Numerics/LinearAlgebra/Complex32/Solvers/TFQMR.cs

@ -53,12 +53,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </remarks>
public sealed class TFQMR : IIterativeSolver<Numerics.Complex32>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<Numerics.Complex32> _preconditioner;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
@ -75,36 +69,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public TFQMR(IPreConditioner<Numerics.Complex32> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<Numerics.Complex32> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -123,10 +87,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null)
public Vector<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> vector, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -137,7 +101,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <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>
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Vector<Numerics.Complex32> input, Vector<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -182,12 +146,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<Numerics.Complex32>();
preconditioner = new UnitPreconditioner<Numerics.Complex32>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
var d = new DenseVector(input.Count);
var r = DenseVector.OfVector(input);
@ -218,7 +182,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
// Calculate the initial values for v
// M temp = yEven
_preconditioner.Approximate(yeven, temp);
preconditioner.Approximate(yeven, temp);
// v = A temp
matrix.Multiply(temp, v);
@ -250,7 +214,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
yeven.Add(temp1, yodd);
// Solve M temp = yOdd
_preconditioner.Approximate(yodd, temp);
preconditioner.Approximate(yodd, temp);
// uOdd = A temp
matrix.Multiply(temp, uodd);
@ -290,7 +254,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
if (!ShouldContinue(iterator, iterationNumber, result, input, pseudoResiduals))
{
// Calculate the real values
_preconditioner.Approximate(x, result);
preconditioner.Approximate(x, result);
// Calculate the true residual. Use the temp vector for that
// so that we don't pollute the pseudoResidual vector for no
@ -326,7 +290,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
pseudoResiduals.Add(temp1, yeven);
// Solve M temp = yOdd
_preconditioner.Approximate(yeven, temp);
preconditioner.Approximate(yeven, temp);
// uOdd = A temp
matrix.Multiply(temp, ueven);
@ -340,7 +304,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
// Calculate the real values
_preconditioner.Approximate(x, result);
preconditioner.Approximate(x, result);
iterationNumber++;
}
@ -404,10 +368,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null)
public Matrix<Numerics.Complex32> Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -418,7 +382,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null)
public void Solve(Matrix<Numerics.Complex32> matrix, Matrix<Numerics.Complex32> input, Matrix<Numerics.Complex32> result, Iterator<Numerics.Complex32> iterator = null, IPreConditioner<Numerics.Complex32> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -430,9 +394,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
iterator = new Iterator<Numerics.Complex32>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<Numerics.Complex32>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

65
src/Numerics/LinearAlgebra/Double/Solvers/BiCgStab.cs

@ -65,12 +65,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </remarks>
public sealed class BiCgStab : IIterativeSolver<double>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<double> _preconditioner;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
@ -87,36 +81,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation. </param>
public BiCgStab(IPreConditioner<double> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<double> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -135,10 +99,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="vector">The solution <see cref="Vector"/>, <c>b</c>.</param>
/// <returns>The result <see cref="Vector"/>, <c>x</c>.</returns>
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null)
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -149,7 +113,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
/// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -194,12 +158,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<double>();
preconditioner = new UnitPreconditioner<double>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector
@ -263,7 +227,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
// SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash);
preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~
matrix.Multiply(vecPdash, nu);
@ -307,7 +271,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
// SOLVE Ms~ = s
_preconditioner.Approximate(vecS, vecSdash);
preconditioner.Approximate(vecS, vecSdash);
// temp = As~
matrix.Multiply(vecSdash, temp);
@ -400,10 +364,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Matrix"/>, <c>B</c>.</param>
/// <returns>The result <see cref="Matrix"/>, <c>X</c>.</returns>
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null)
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -414,7 +378,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Matrix"/>, <c>B</c>.</param>
/// <param name="result">The result <see cref="Matrix"/>, <c>X</c></param>
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -426,9 +390,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<double>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

336
src/Numerics/LinearAlgebra/Double/Solvers/CompositeSolver.cs

@ -30,9 +30,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.Properties;
@ -55,273 +53,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </remarks>
public sealed class CompositeSolver : IIterativeSolver<double>
{
#region Internal class - DoubleComparer
/// <summary>
/// An <c>IComparer</c> used to compare double precision floating points.
/// </summary>
public sealed class DoubleComparer : IComparer<double>
{
/// <summary>
/// Compares two double values based on the selected comparison method.
/// </summary>
/// <param name="x">The first double to compare.</param>
/// <param name="y">The second double to compare.</param>
/// <returns>
/// A 32-bit signed integer that indicates the relative order of the objects being compared. The return
/// value has the following meanings:
/// Value Meaning Less than zero This object is less than the other parameter.
/// Zero This object is equal to other.
/// Greater than zero This object is greater than other.
/// </returns>
public int Compare(double x, double y)
{
return x.CompareTo(y, 1);
}
}
#endregion
#if PORTABLE
private static readonly Dictionary<double, List<IIterativeSolverSetup<double>>> SolverSetups = new Dictionary<double, List<IIterativeSolverSetup<double>>>();
#else
/// <summary>
/// The collection of iterative solver setups. Stored based on the
/// ratio between the relative speed and relative accuracy.
/// </summary>
static readonly SortedList<double, List<IIterativeSolverSetup<double>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<double>>>(new DoubleComparer());
#endif
#region Solver information loading methods
/// <summary>
/// Loads all the available <see cref="IIterativeSolverSetup{T}"/> objects from the MathNet.Numerics assembly.
/// </summary>
public static void LoadSolverInformation()
{
LoadSolverInformation(new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the MathNet.Numerics assembly.
/// </summary>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformation(Type[] typesToExclude)
{
LoadSolverInformationFromAssembly(Assembly.GetExecutingAssembly(), typesToExclude);
}
#if !PORTABLE
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the file location.
/// </summary>
/// <param name="assemblyLocation">The fully qualified path to the assembly.</param>
public static void LoadSolverInformationFromAssembly(string assemblyLocation)
{
LoadSolverInformationFromAssembly(assemblyLocation, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the file location.
/// </summary>
/// <param name="assemblyLocation">The fully qualified path to the assembly.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded. </param>
public static void LoadSolverInformationFromAssembly(string assemblyLocation, params Type[] typesToExclude)
{
if (assemblyLocation == null)
{
throw new ArgumentNullException("assemblyLocation");
}
if (assemblyLocation.Length == 0)
{
throw new ArgumentException();
}
if (!File.Exists(assemblyLocation))
{
throw new FileNotFoundException();
}
// Get the assembly name
var assemblyFileName = Path.GetFileNameWithoutExtension(assemblyLocation);
// Now load the assembly with an AssemblyName
var assemblyName = new AssemblyName(assemblyFileName);
var assembly = Assembly.Load(assemblyName.FullName);
// <ay throws:
// ArgumentNullException --> Can't get this because we checked that the file exists.
// FileNotFoundException --> Can't get this because we checked that the file exists.
// FileLoadException
// BadImageFormatException
// Now we can load the solver information.
LoadSolverInformationFromAssembly(assembly, typesToExclude);
}
#endif
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the assembly name.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects. </param>
public static void LoadSolverInformationFromAssembly(AssemblyName assemblyName)
{
LoadSolverInformationFromAssembly(assemblyName, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the assembly name.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(AssemblyName assemblyName, params Type[] typesToExclude)
{
if (assemblyName == null)
{
throw new ArgumentNullException("assemblyName");
}
var assembly = Assembly.Load(assemblyName.FullName);
// May throw:
// ArgumentNullException --> Can't get this because we checked it.
// FileNotFoundException
// FileLoadException
// BadImageFormatException
// Now we can load the solver information.
LoadSolverInformationFromAssembly(assembly, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the type.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
public static void LoadSolverInformationFromAssembly(Type typeInAssembly)
{
LoadSolverInformationFromAssembly(typeInAssembly, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the type.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(Type typeInAssembly, params Type[] typesToExclude)
{
if (typeInAssembly == null)
{
throw new ArgumentNullException("typeInAssembly");
}
LoadSolverInformationFromAssembly(typeInAssembly.Assembly, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
public static void LoadSolverInformationFromAssembly(Assembly assembly)
{
LoadSolverInformationFromAssembly(assembly, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// The collection of solvers that will be used
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(Assembly assembly, params Type[] typesToExclude)
{
if (assembly == null)
{
throw new ArgumentNullException("assembly");
}
if (typesToExclude == null)
{
throw new ArgumentNullException("typesToExclude");
}
var excludedTypes = new List<Type>(typesToExclude);
// Load all the types in the assembly
// Find all the types that implement IIterativeSolverSetup
// Create an object of each of these types
// Get the type of the iterative solver that will be instantiated by the setup object
// Check if it's on the excluding list, if so throw the setup object away otherwise keep it.
var interfaceTypes = new List<Type>();
foreach (var type in assembly.GetTypes().Where(type => (!type.IsAbstract && !type.IsEnum && !type.IsInterface && type.IsVisible)))
{
interfaceTypes.Clear();
interfaceTypes.AddRange(type.GetInterfaces());
if (!interfaceTypes.Any(match => typeof (IIterativeSolverSetup<double>).IsAssignableFrom(match)))
{
continue;
}
// See if we actually want this type of iterative solver
IIterativeSolverSetup<double> setup;
try
{
// If something goes wrong we just ignore it and move on with the next type.
// There should probably be a log somewhere indicating that something went wrong?
setup = (IIterativeSolverSetup<double>) Activator.CreateInstance(type);
}
catch (ArgumentException)
{
continue;
}
catch (NotSupportedException)
{
continue;
}
catch (TargetInvocationException)
{
continue;
}
#if !PORTABLE
catch (MethodAccessException)
{
continue;
}
catch (MissingMethodException)
{
continue;
}
#endif
catch (MemberAccessException)
{
continue;
}
catch (TypeLoadException)
{
continue;
}
if (excludedTypes.Any(match => match.IsAssignableFrom(setup.SolverType) ||
match.IsAssignableFrom(setup.PreconditionerType)))
{
continue;
}
// Ok we want the solver, so store the object
var ratio = setup.SolutionSpeed/setup.Reliability;
if (!SolverSetups.ContainsKey(ratio))
{
SolverSetups.Add(ratio, new List<IIterativeSolverSetup<double>>());
}
var list = SolverSetups[ratio];
list.Add(setup);
}
}
#endregion
/// <summary>
/// The collection of solvers that will be used to
/// </summary>
readonly List<IIterativeSolver<double>> _solvers = new List<IIterativeSolver<double>>();
readonly List<Tuple<IIterativeSolver<double>, IPreConditioner<double>>> _solvers;
/// <summary>
/// The status of the calculation.
@ -339,22 +74,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
IIterativeSolver<double> _currentSolver;
/// <summary>
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the default iterator.
/// </summary>
public CompositeSolver()
{
}
/// <summary>
/// Gets the status of the iteration once the calculation is finished.
/// </summary>
public IterationStatus IterationResult
public CompositeSolver(IEnumerable<IIterativeSolverSetup<double>> solvers)
{
get
{
return _status;
}
_solvers = solvers.Select(setup => new Tuple<IIterativeSolver<double>, IPreConditioner<double>>(setup.CreateSolver(), setup.CreatePreconditioner() ?? new UnitPreconditioner<double>())).ToList();
}
/// <summary>
@ -380,10 +102,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null)
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -394,7 +116,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <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>
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -419,13 +141,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
// Load the solvers into our own internal data structure
// Once we have solvers we can always reuse them.
if (_solvers.Count == 0)
{
LoadSolvers();
}
// Create a copy of the solution and result vectors so we can use them
// later on
var internalInput = input.Clone();
@ -434,7 +149,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
foreach (var solver in _solvers.TakeWhile(solver => !_hasBeenStopped))
{
// Store a reference to the solver so we can stop it.
_currentSolver = solver;
_currentSolver = solver.Item1;
try
{
@ -442,7 +157,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator.Reset();
// Start the solver
solver.Solve(matrix, internalInput, internalResult, iterator);
solver.Item1.Solve(matrix, internalInput, internalResult, iterator, solver.Item2);
_status = iterator.Status;
}
catch (Exception)
@ -490,26 +205,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
_currentSolver = null;
}
/// <summary>
/// Load solvers
/// </summary>
void LoadSolvers()
{
if (SolverSetups.Count == 0)
{
throw new Exception("IIterativeSolverSetup objects not found");
}
#if PORTABLE
foreach (var setup in SolverSetups.OrderBy(solver => solver.Key, new DoubleComparer()).Select(pair => pair.Value).SelectMany(setups => setups))
#else
foreach (var setup in SolverSetups.Select(pair => pair.Value).SelectMany(setups => setups))
#endif
{
_solvers.Add(setup.CreateNew());
}
}
/// <summary>
/// Solves the matrix equation AX = B, where A is the coefficient matrix, B is the
/// solution matrix and X is the unknown matrix.
@ -517,10 +212,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null)
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -531,7 +226,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -543,9 +238,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<double>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

67
src/Numerics/LinearAlgebra/Double/Solvers/GpBiCg.cs

@ -63,12 +63,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </remarks>
public sealed class GpBiCg : IIterativeSolver<double>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <c>null</c>, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<double> _preconditioner;
/// <summary>
/// Indicates the number of <c>BiCGStab</c> steps should be taken
/// before switching.
@ -97,27 +91,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public GpBiCg(IPreConditioner<double> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets the number of steps taken with the <c>BiCgStab</c> algorithm
/// before switching over to the <c>GPBiCG</c> algorithm.
@ -162,15 +135,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<double> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -190,10 +154,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null)
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -204,7 +168,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <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>
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -249,12 +213,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<double>();
preconditioner = new UnitPreconditioner<double>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// x_0 is initial guess
// Take x_0 = 0
@ -302,7 +266,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
residuals.Add(temp2, p);
// Solve M b_k = p_k
_preconditioner.Approximate(p, temp);
preconditioner.Approximate(p, temp);
// s_k = A b_k
matrix.Multiply(temp, s);
@ -326,7 +290,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
residuals.Add(temp2, t);
// Solve M d_k = t_k
_preconditioner.Approximate(t, temp);
preconditioner.Approximate(t, temp);
// c_k = A d_k
matrix.Multiply(temp, c);
@ -431,7 +395,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
c.Add(temp2, w);
// Get the real value
_preconditioner.Approximate(xtemp, result);
preconditioner.Approximate(xtemp, result);
// Now check for convergence
if (!ShouldContinue(iterator, iterationNumber, result, input, residuals))
@ -511,10 +475,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null)
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -525,7 +489,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -537,9 +501,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<double>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

67
src/Numerics/LinearAlgebra/Double/Solvers/MlkBiCgStab.cs

@ -68,12 +68,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
const int DefaultNumberOfStartingVectors = 50;
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<double> _preconditioner;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary>
@ -100,27 +94,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public MlkBiCgStab(IPreConditioner<double> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets the number of starting vectors.
/// </summary>
@ -156,15 +129,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
_numberOfStartingVectors = DefaultNumberOfStartingVectors;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<double> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets a series of orthonormal vectors which will be used as basis for the
/// Krylov sub-space.
@ -209,10 +173,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null)
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -223,7 +187,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <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>
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -268,12 +232,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<double>();
preconditioner = new UnitPreconditioner<double>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// Choose an initial guess x_0
// Take x_0 = 0
@ -338,7 +302,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
while (ShouldContinue(iterator, iterationNumber, xtemp, input, residuals))
{
// SOLVE M g~_((j-1)k+k) = g_((j-1)k+k)
_preconditioner.Approximate(g[k - 1], gtemp);
preconditioner.Approximate(g[k - 1], gtemp);
// w_((j-1)k+k) = A g~_((j-1)k+k)
matrix.Multiply(gtemp, w[k - 1]);
@ -358,7 +322,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
residuals.Add(temp, u);
// SOLVE M u~_(jk+1) = u_(jk+1)
_preconditioner.Approximate(u, temp1);
preconditioner.Approximate(u, temp1);
temp1.CopyTo(utemp);
// rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
@ -512,7 +476,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
temp2.CopyTo(u);
// SOLVE M g~_(jk+i) = g_(jk+i)
_preconditioner.Approximate(g[i], gtemp);
preconditioner.Approximate(g[i], gtemp);
// x_(jk+i+1) = x_(jk+i) + rho_(j+1) alpha_(jk+i+1) g~_(jk+i)
gtemp.Multiply(rho*alpha, temp);
@ -669,10 +633,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null)
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -683,7 +647,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -695,9 +659,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<double>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

71
src/Numerics/LinearAlgebra/Double/Solvers/TFQMR.cs

@ -53,12 +53,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </remarks>
public sealed class TFQMR : IIterativeSolver<double>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<double> _preconditioner;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
@ -75,36 +69,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public TFQMR(IPreConditioner<double> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<double> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -123,10 +87,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null)
public Vector<double> Solve(Matrix<double> matrix, Vector<double> vector, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -137,7 +101,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <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>
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Vector<double> input, Vector<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -182,12 +146,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<double>();
preconditioner = new UnitPreconditioner<double>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
var d = new DenseVector(input.Count);
var r = DenseVector.OfVector(input);
@ -218,7 +182,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
// Calculate the initial values for v
// M temp = yEven
_preconditioner.Approximate(yeven, temp);
preconditioner.Approximate(yeven, temp);
// v = A temp
matrix.Multiply(temp, v);
@ -250,7 +214,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
yeven.Add(temp1, yodd);
// Solve M temp = yOdd
_preconditioner.Approximate(yodd, temp);
preconditioner.Approximate(yodd, temp);
// uOdd = A temp
matrix.Multiply(temp, uodd);
@ -290,7 +254,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
if (!ShouldContinue(iterator, iterationNumber, result, input, pseudoResiduals))
{
// Calculate the real values
_preconditioner.Approximate(x, result);
preconditioner.Approximate(x, result);
// Calculate the true residual. Use the temp vector for that
// so that we don't pollute the pseudoResidual vector for no
@ -326,7 +290,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
pseudoResiduals.Add(temp1, yeven);
// Solve M temp = yOdd
_preconditioner.Approximate(yeven, temp);
preconditioner.Approximate(yeven, temp);
// uOdd = A temp
matrix.Multiply(temp, ueven);
@ -340,7 +304,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
// Calculate the real values
_preconditioner.Approximate(x, result);
preconditioner.Approximate(x, result);
iterationNumber++;
}
@ -404,10 +368,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null)
public Matrix<double> Solve(Matrix<double> matrix, Matrix<double> input, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -418,7 +382,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null)
public void Solve(Matrix<double> matrix, Matrix<double> input, Matrix<double> result, Iterator<double> iterator = null, IPreConditioner<double> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -430,9 +394,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
iterator = new Iterator<double>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<double>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

65
src/Numerics/LinearAlgebra/Single/Solvers/BiCgStab.cs

@ -65,12 +65,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </remarks>
public sealed class BiCgStab : IIterativeSolver<float>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<float> _preconditioner;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
@ -87,36 +81,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation. </param>
public BiCgStab(IPreConditioner<float> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<float> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -135,10 +99,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="vector">The solution <see cref="Vector"/>, <c>b</c>.</param>
/// <returns>The result <see cref="Vector"/>, <c>x</c>.</returns>
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null)
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -149,7 +113,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
/// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -194,12 +158,12 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<float>();
preconditioner = new UnitPreconditioner<float>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector
@ -263,7 +227,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
// SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash);
preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~
matrix.Multiply(vecPdash, nu);
@ -307,7 +271,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
// SOLVE Ms~ = s
_preconditioner.Approximate(vecS, vecSdash);
preconditioner.Approximate(vecS, vecSdash);
// temp = As~
matrix.Multiply(vecSdash, temp);
@ -400,10 +364,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Matrix"/>, <c>B</c>.</param>
/// <returns>The result <see cref="Matrix"/>, <c>X</c>.</returns>
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null)
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -414,7 +378,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
/// <param name="input">The solution <see cref="Matrix"/>, <c>B</c>.</param>
/// <param name="result">The result <see cref="Matrix"/>, <c>X</c></param>
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -426,9 +390,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<float>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

330
src/Numerics/LinearAlgebra/Single/Solvers/CompositeSolver.cs

@ -30,9 +30,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.Properties;
@ -55,276 +53,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </remarks>
public sealed class CompositeSolver : IIterativeSolver<float>
{
#region Internal class - DoubleComparer
/// <summary>
/// An <c>IComparer</c> used to compare double precision floating points.
/// </summary>
/// NOTE: The instance of this class is used only in <see cref="SolverSetups"/>. If C# suppports interface inheritence
/// NOTE: and methods in anonymous types, then this class should be deleted and anonymous type implemented with IComaprer support
/// NOTE: in <see cref="SolverSetups"/> constructor
public sealed class DoubleComparer : IComparer<double>
{
/// <summary>
/// Compares two double values based on the selected comparison method.
/// </summary>
/// <param name="x">The first double to compare.</param>
/// <param name="y">The second double to compare.</param>
/// <returns>
/// A 32-bit signed integer that indicates the relative order of the objects being compared. The return
/// value has the following meanings:
/// Value Meaning Less than zero This object is less than the other parameter.
/// Zero This object is equal to other.
/// Greater than zero This object is greater than other.
/// </returns>
public int Compare(double x, double y)
{
return x.CompareTo(y, 1);
}
}
#endregion
#if PORTABLE
private static readonly Dictionary<double, List<IIterativeSolverSetup<float>>> SolverSetups = new Dictionary<double, List<IIterativeSolverSetup<float>>>();
#else
/// <summary>
/// The collection of iterative solver setups. Stored based on the
/// ratio between the relative speed and relative accuracy.
/// The collection of solvers that will be used
/// </summary>
static readonly SortedList<double, List<IIterativeSolverSetup<float>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<float>>>(new DoubleComparer());
#endif
#region Solver information loading methods
/// <summary>
/// Loads all the available <see cref="IIterativeSolverSetup{T}"/> objects from the MathNet.Numerics assembly.
/// </summary>
public static void LoadSolverInformation()
{
LoadSolverInformation(new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the MathNet.Numerics assembly.
/// </summary>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformation(Type[] typesToExclude)
{
LoadSolverInformationFromAssembly(Assembly.GetExecutingAssembly(), typesToExclude);
}
#if !PORTABLE
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the file location.
/// </summary>
/// <param name="assemblyLocation">The fully qualified path to the assembly.</param>
public static void LoadSolverInformationFromAssembly(string assemblyLocation)
{
LoadSolverInformationFromAssembly(assemblyLocation, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the file location.
/// </summary>
/// <param name="assemblyLocation">The fully qualified path to the assembly.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded. </param>
public static void LoadSolverInformationFromAssembly(string assemblyLocation, params Type[] typesToExclude)
{
if (assemblyLocation == null)
{
throw new ArgumentNullException("assemblyLocation");
}
if (assemblyLocation.Length == 0)
{
throw new ArgumentException();
}
if (!File.Exists(assemblyLocation))
{
throw new FileNotFoundException();
}
// Get the assembly name
var assemblyFileName = Path.GetFileNameWithoutExtension(assemblyLocation);
// Now load the assembly with an AssemblyName
var assemblyName = new AssemblyName(assemblyFileName);
var assembly = Assembly.Load(assemblyName.FullName);
// <ay throws:
// ArgumentNullException --> Can't get this because we checked that the file exists.
// FileNotFoundException --> Can't get this because we checked that the file exists.
// FileLoadException
// BadImageFormatException
// Now we can load the solver information.
LoadSolverInformationFromAssembly(assembly, typesToExclude);
}
#endif
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the assembly name.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects. </param>
public static void LoadSolverInformationFromAssembly(AssemblyName assemblyName)
{
LoadSolverInformationFromAssembly(assemblyName, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the assembly name.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(AssemblyName assemblyName, params Type[] typesToExclude)
{
if (assemblyName == null)
{
throw new ArgumentNullException("assemblyName");
}
var assembly = Assembly.Load(assemblyName.FullName);
// May throw:
// ArgumentNullException --> Can't get this because we checked it.
// FileNotFoundException
// FileLoadException
// BadImageFormatException
// Now we can load the solver information.
LoadSolverInformationFromAssembly(assembly, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the type.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
public static void LoadSolverInformationFromAssembly(Type typeInAssembly)
{
LoadSolverInformationFromAssembly(typeInAssembly, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the assembly specified by the type.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(Type typeInAssembly, params Type[] typesToExclude)
{
if (typeInAssembly == null)
{
throw new ArgumentNullException("typeInAssembly");
}
LoadSolverInformationFromAssembly(typeInAssembly.Assembly, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
public static void LoadSolverInformationFromAssembly(Assembly assembly)
{
LoadSolverInformationFromAssembly(assembly, new Type[0]);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static void LoadSolverInformationFromAssembly(Assembly assembly, params Type[] typesToExclude)
{
if (assembly == null)
{
throw new ArgumentNullException("assembly");
}
if (typesToExclude == null)
{
throw new ArgumentNullException("typesToExclude");
}
var excludedTypes = new List<Type>(typesToExclude);
// Load all the types in the assembly
// Find all the types that implement IIterativeSolverSetup
// Create an object of each of these types
// Get the type of the iterative solver that will be instantiated by the setup object
// Check if it's on the excluding list, if so throw the setup object away otherwise keep it.
var interfaceTypes = new List<Type>();
foreach (var type in assembly.GetTypes().Where(type => (!type.IsAbstract && !type.IsEnum && !type.IsInterface && type.IsVisible)))
{
interfaceTypes.Clear();
interfaceTypes.AddRange(type.GetInterfaces());
if (!interfaceTypes.Any(match => typeof (IIterativeSolverSetup<float>).IsAssignableFrom(match)))
{
continue;
}
// See if we actually want this type of iterative solver
IIterativeSolverSetup<float> setup;
try
{
// If something goes wrong we just ignore it and move on with the next type.
// There should probably be a log somewhere indicating that something went wrong?
setup = (IIterativeSolverSetup<float>) Activator.CreateInstance(type);
}
catch (ArgumentException)
{
continue;
}
catch (NotSupportedException)
{
continue;
}
catch (TargetInvocationException)
{
continue;
}
#if !PORTABLE
catch (MethodAccessException)
{
continue;
}
catch (MissingMethodException)
{
continue;
}
#endif
catch (MemberAccessException)
{
continue;
}
catch (TypeLoadException)
{
continue;
}
if (excludedTypes.Any(match => match.IsAssignableFrom(setup.SolverType) ||
match.IsAssignableFrom(setup.PreconditionerType)))
{
continue;
}
// Ok we want the solver, so store the object
var ratio = setup.SolutionSpeed/setup.Reliability;
if (!SolverSetups.ContainsKey(ratio))
{
SolverSetups.Add(ratio, new List<IIterativeSolverSetup<float>>());
}
var list = SolverSetups[ratio];
list.Add(setup);
}
}
#endregion
/// <summary>
/// The collection of solvers that will be used to
/// </summary>
readonly List<IIterativeSolver<float>> _solvers = new List<IIterativeSolver<float>>();
readonly List<Tuple<IIterativeSolver<float>, IPreConditioner<float>>> _solvers;
/// <summary>
/// The status of the calculation.
@ -342,15 +74,13 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </summary>
IIterativeSolver<float> _currentSolver;
/// <summary>
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the default iterator.
/// </summary>
public CompositeSolver()
public CompositeSolver(IEnumerable<IIterativeSolverSetup<float>> solvers)
{
_solvers = solvers.Select(setup => new Tuple<IIterativeSolver<float>, IPreConditioner<float>>(setup.CreateSolver(), setup.CreatePreconditioner() ?? new UnitPreconditioner<float>())).ToList();
}
/// <summary>
/// Stops the solve process.
/// Stops the solve process.
/// </summary>
/// <remarks>
/// Note that it may take an indetermined amount of time for the solver to actually stop the process.
@ -372,10 +102,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null)
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -386,7 +116,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <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>
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -411,13 +141,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
// Load the solvers into our own internal data structure
// Once we have solvers we can always reuse them.
if (_solvers.Count == 0)
{
LoadSolvers();
}
// Create a copy of the solution and result vectors so we can use them
// later on
var internalInput = input.Clone();
@ -426,7 +149,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
foreach (var solver in _solvers.TakeWhile(solver => !_hasBeenStopped))
{
// Store a reference to the solver so we can stop it.
_currentSolver = solver;
_currentSolver = solver.Item1;
try
{
@ -434,7 +157,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator.Reset();
// Start the solver
solver.Solve(matrix, internalInput, internalResult, iterator);
solver.Item1.Solve(matrix, internalInput, internalResult, iterator, solver.Item2);
_status = iterator.Status;
}
catch (Exception)
@ -482,26 +205,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
_currentSolver = null;
}
/// <summary>
/// Load solvers
/// </summary>
void LoadSolvers()
{
if (SolverSetups.Count == 0)
{
throw new Exception("IIterativeSolverSetup objects not found");
}
#if PORTABLE
foreach (var setup in SolverSetups.OrderBy(solver => solver.Key, new DoubleComparer()).Select(pair => pair.Value).SelectMany(setups => setups))
#else
foreach (var setup in SolverSetups.Select(pair => pair.Value).SelectMany(setups => setups))
#endif
{
_solvers.Add(setup.CreateNew());
}
}
/// <summary>
/// Solves the matrix equation AX = B, where A is the coefficient matrix, B is the
/// solution matrix and X is the unknown matrix.
@ -509,10 +212,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null)
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -523,7 +226,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -535,9 +238,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<float>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

67
src/Numerics/LinearAlgebra/Single/Solvers/GpBiCg.cs

@ -63,12 +63,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </remarks>
public sealed class GpBiCg : IIterativeSolver<float>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <c>null</c>, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<float> _preconditioner;
/// <summary>
/// Indicates the number of <c>BiCGStab</c> steps should be taken
/// before switching.
@ -97,27 +91,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public GpBiCg(IPreConditioner<float> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets the number of steps taken with the <c>BiCgStab</c> algorithm
/// before switching over to the <c>GPBiCG</c> algorithm.
@ -156,15 +129,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<float> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -184,10 +148,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null)
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -198,7 +162,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <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>
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -243,12 +207,12 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<float>();
preconditioner = new UnitPreconditioner<float>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// x_0 is initial guess
// Take x_0 = 0
@ -296,7 +260,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
residuals.Add(temp2, p);
// Solve M b_k = p_k
_preconditioner.Approximate(p, temp);
preconditioner.Approximate(p, temp);
// s_k = A b_k
matrix.Multiply(temp, s);
@ -320,7 +284,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
residuals.Add(temp2, t);
// Solve M d_k = t_k
_preconditioner.Approximate(t, temp);
preconditioner.Approximate(t, temp);
// c_k = A d_k
matrix.Multiply(temp, c);
@ -425,7 +389,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
c.Add(temp2, w);
// Get the real value
_preconditioner.Approximate(xtemp, result);
preconditioner.Approximate(xtemp, result);
// Now check for convergence
if (!ShouldContinue(iterator, iterationNumber, result, input, residuals))
@ -505,10 +469,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null)
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -519,7 +483,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -531,9 +495,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<float>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

67
src/Numerics/LinearAlgebra/Single/Solvers/MlkBiCgStab.cs

@ -67,12 +67,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </summary>
const int DefaultNumberOfStartingVectors = 50;
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<float> _preconditioner;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary>
@ -99,27 +93,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public MlkBiCgStab(IPreConditioner<float> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets the number of starting vectors.
/// </summary>
@ -155,15 +128,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
_numberOfStartingVectors = DefaultNumberOfStartingVectors;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<float> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Gets or sets a series of orthonormal vectors which will be used as basis for the
/// Krylov sub-space.
@ -208,10 +172,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null)
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -222,7 +186,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <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>
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -267,12 +231,12 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<float>();
preconditioner = new UnitPreconditioner<float>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
// Choose an initial guess x_0
// Take x_0 = 0
@ -337,7 +301,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
while (ShouldContinue(iterator, iterationNumber, xtemp, input, residuals))
{
// SOLVE M g~_((j-1)k+k) = g_((j-1)k+k)
_preconditioner.Approximate(g[k - 1], gtemp);
preconditioner.Approximate(g[k - 1], gtemp);
// w_((j-1)k+k) = A g~_((j-1)k+k)
matrix.Multiply(gtemp, w[k - 1]);
@ -357,7 +321,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
residuals.Add(temp, u);
// SOLVE M u~_(jk+1) = u_(jk+1)
_preconditioner.Approximate(u, temp1);
preconditioner.Approximate(u, temp1);
temp1.CopyTo(utemp);
// rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
@ -511,7 +475,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
temp2.CopyTo(u);
// SOLVE M g~_(jk+i) = g_(jk+i)
_preconditioner.Approximate(g[i], gtemp);
preconditioner.Approximate(g[i], gtemp);
// x_(jk+i+1) = x_(jk+i) + rho_(j+1) alpha_(jk+i+1) g~_(jk+i)
gtemp.Multiply(rho*alpha, temp);
@ -672,10 +636,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null)
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -686,7 +650,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -698,9 +662,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<float>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

71
src/Numerics/LinearAlgebra/Single/Solvers/TFQMR.cs

@ -53,12 +53,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </remarks>
public sealed class TFQMR : IIterativeSolver<float>
{
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
IPreConditioner<float> _preconditioner;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
@ -75,36 +69,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="Iterator{T}"/> are:
/// <list type="number">
/// <item>It is possible to set the desired convergence limits.</item>
/// <item>
/// It is possible to check the reason for which the solver finished
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
public TFQMR(IPreConditioner<float> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Sets the <see cref="IPreConditioner{T}"/> that will be used to precondition the iterative process.
/// </summary>
/// <param name="preconditioner">The preconditioner.</param>
public void SetPreconditioner(IPreConditioner<float> preconditioner)
{
_preconditioner = preconditioner;
}
/// <summary>
/// Stops the solve process.
/// </summary>
@ -123,10 +87,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null)
public Vector<float> Solve(Matrix<float> matrix, Vector<float> vector, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = new DenseVector(matrix.RowCount);
Solve(matrix, vector, result, iterator);
Solve(matrix, vector, result, iterator, preconditioner);
return result;
}
@ -137,7 +101,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <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>
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Vector<float> input, Vector<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
// If we were stopped before, we are no longer
// We're doing this at the start of the method to ensure
@ -182,12 +146,12 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
if (_preconditioner == null)
if (preconditioner == null)
{
_preconditioner = new UnitPreconditioner<float>();
preconditioner = new UnitPreconditioner<float>();
}
_preconditioner.Initialize(matrix);
preconditioner.Initialize(matrix);
var d = new DenseVector(input.Count);
var r = DenseVector.OfVector(input);
@ -218,7 +182,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
// Calculate the initial values for v
// M temp = yEven
_preconditioner.Approximate(yeven, temp);
preconditioner.Approximate(yeven, temp);
// v = A temp
matrix.Multiply(temp, v);
@ -250,7 +214,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
yeven.Add(temp1, yodd);
// Solve M temp = yOdd
_preconditioner.Approximate(yodd, temp);
preconditioner.Approximate(yodd, temp);
// uOdd = A temp
matrix.Multiply(temp, uodd);
@ -290,7 +254,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
if (!ShouldContinue(iterator, iterationNumber, result, input, pseudoResiduals))
{
// Calculate the real values
_preconditioner.Approximate(x, result);
preconditioner.Approximate(x, result);
// Calculate the true residual. Use the temp vector for that
// so that we don't pollute the pseudoResidual vector for no
@ -326,7 +290,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
pseudoResiduals.Add(temp1, yeven);
// Solve M temp = yOdd
_preconditioner.Approximate(yeven, temp);
preconditioner.Approximate(yeven, temp);
// uOdd = A temp
matrix.Multiply(temp, ueven);
@ -340,7 +304,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
// Calculate the real values
_preconditioner.Approximate(x, result);
preconditioner.Approximate(x, result);
iterationNumber++;
}
@ -404,10 +368,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null)
public Matrix<float> Solve(Matrix<float> matrix, Matrix<float> input, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
var result = matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result, iterator);
Solve(matrix, input, result, iterator, preconditioner);
return result;
}
@ -418,7 +382,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null)
public void Solve(Matrix<float> matrix, Matrix<float> input, Matrix<float> result, Iterator<float> iterator = null, IPreConditioner<float> preconditioner = null)
{
if (matrix.RowCount != input.RowCount || input.RowCount != result.RowCount || input.ColumnCount != result.ColumnCount)
{
@ -430,9 +394,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
iterator = new Iterator<float>(Iterator.CreateDefaultStopCriteria());
}
if (preconditioner == null)
{
preconditioner = new UnitPreconditioner<float>();
}
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, input.Column(column), iterator);
var solution = Solve(matrix, input.Column(column), iterator, preconditioner);
foreach (var element in solution.EnumerateNonZeroIndexed())
{
result.At(element.Item1, column, element.Item2);

8
src/Numerics/LinearAlgebra/Solvers/IIterativeSolver.cs

@ -53,7 +53,7 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="vector">The solution vector, <c>b</c>.</param>
/// <returns>The result vector, <c>x</c>.</returns>
Vector<T> Solve(Matrix<T> matrix, Vector<T> vector, Iterator<T> iterator = null);
Vector<T> Solve(Matrix<T> matrix, Vector<T> vector, Iterator<T> iterator = null, IPreConditioner<T> preconditioner = null);
/// <summary>
/// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
@ -62,7 +62,7 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
/// <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>
void Solve(Matrix<T> matrix, Vector<T> input, Vector<T> result, Iterator<T> iterator = null);
void Solve(Matrix<T> matrix, Vector<T> input, Vector<T> result, Iterator<T> iterator = null, IPreConditioner<T> preconditioner = null);
/// <summary>
/// Solves the matrix equation AX = B, where A is the coefficient matrix, B is the
@ -71,7 +71,7 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <returns>The result matrix, <c>X</c>.</returns>
Matrix<T> Solve(Matrix<T> matrix, Matrix<T> input, Iterator<T> iterator = null);
Matrix<T> Solve(Matrix<T> matrix, Matrix<T> input, Iterator<T> iterator = null, IPreConditioner<T> preconditioner = null);
/// <summary>
/// Solves the matrix equation AX = B, where A is the coefficient matrix, B is the
@ -80,6 +80,6 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
/// <param name="matrix">The coefficient matrix, <c>A</c>.</param>
/// <param name="input">The solution matrix, <c>B</c>.</param>
/// <param name="result">The result matrix, <c>X</c></param>
void Solve(Matrix<T> matrix, Matrix<T> input, Matrix<T> result, Iterator<T> iterator = null);
void Solve(Matrix<T> matrix, Matrix<T> input, Matrix<T> result, Iterator<T> iterator = null, IPreConditioner<T> preconditioner = null);
}
}

11
src/Numerics/LinearAlgebra/Solvers/IIterativeSolverSetup.cs

@ -50,11 +50,14 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
Type PreconditionerType { get; }
/// <summary>
/// Creates a fully functional iterative solver with the default settings
/// given by this setup.
/// Creates the iterative solver to be used.
/// </summary>
/// <returns>A new <see cref="IIterativeSolver{T}"/>.</returns>
IIterativeSolver<T> CreateNew();
IIterativeSolver<T> CreateSolver();
/// <summary>
/// Creates the preconditioner to be used by default (can be overwritten).
/// </summary>
IPreConditioner<T> CreatePreconditioner();
/// <summary>
/// Gets the relative speed of the solver.

138
src/Numerics/LinearAlgebra/Solvers/SolverSetup.cs

@ -0,0 +1,138 @@
// <copyright file="SolverSetup.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace MathNet.Numerics.LinearAlgebra.Solvers
{
public static class SolverSetup<T> where T : struct, IEquatable<T>, IFormattable
{
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static IEnumerable<IIterativeSolverSetup<T>> LoadFromAssembly(Assembly assembly, bool ignoreFailed, params Type[] typesToExclude)
{
var excludedTypes = new List<Type>(typesToExclude);
var setupInterfaceType = typeof (IIterativeSolverSetup<T>);
var candidates = assembly.GetTypes()
.Where(type => !type.IsAbstract && !type.IsEnum && !type.IsInterface && type.IsVisible)
.Where(type => type.GetInterfaces().Any(setupInterfaceType.IsAssignableFrom));
var setups = new List<IIterativeSolverSetup<T>>();
foreach (var type in candidates)
{
try
{
setups.Add((IIterativeSolverSetup<T>) Activator.CreateInstance(type));
}
catch
{
if (!ignoreFailed)
{
throw;
}
}
}
return setups
.Where(s => !excludedTypes.Any(t => t.IsAssignableFrom(s.SolverType) || t.IsAssignableFrom(s.PreconditionerType)))
.OrderBy(s => s.SolutionSpeed/s.Reliability);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assembly">The assembly which will be searched for setup objects.</param>
public static IEnumerable<IIterativeSolverSetup<T>> LoadFromAssembly(Assembly assembly)
{
return LoadFromAssembly(assembly, true);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static IEnumerable<IIterativeSolverSetup<T>> LoadFromAssembly(Type typeInAssembly, bool ignoreFailed, params Type[] typesToExclude)
{
return LoadFromAssembly(typeInAssembly.Assembly, ignoreFailed, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="typeInAssembly">The type in the assembly which should be searched for setup objects.</param>
public static IEnumerable<IIterativeSolverSetup<T>> LoadFromAssembly(Type typeInAssembly)
{
return LoadFromAssembly(typeInAssembly.Assembly, true);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects.</param>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static IEnumerable<IIterativeSolverSetup<T>> LoadFromAssembly(AssemblyName assemblyName, bool ignoreFailed, params Type[] typesToExclude)
{
return LoadFromAssembly(Assembly.Load(assemblyName.FullName), ignoreFailed, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the specified assembly.
/// </summary>
/// <param name="assemblyName">The <see cref="AssemblyName"/> of the assembly that should be searched for setup objects.</param>
public static IEnumerable<IIterativeSolverSetup<T>> LoadFromAssembly(AssemblyName assemblyName)
{
return LoadFromAssembly(Assembly.Load(assemblyName.FullName), true);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the Math.NET Numerics assembly.
/// </summary>
/// <param name="typesToExclude">The <see cref="IIterativeSolver{T}"/> types that should not be loaded.</param>
public static IEnumerable<IIterativeSolverSetup<T>> Load(Type[] typesToExclude)
{
return LoadFromAssembly(Assembly.GetExecutingAssembly(), false, typesToExclude);
}
/// <summary>
/// Loads the available <see cref="IIterativeSolverSetup{T}"/> objects from the Math.NET Numerics assembly.
/// </summary>
public static IEnumerable<IIterativeSolverSetup<T>> Load()
{
return LoadFromAssembly(Assembly.GetExecutingAssembly(), false);
}
}
}

1
src/Numerics/Numerics.csproj

@ -126,6 +126,7 @@
<Compile Include="LinearAlgebra\Solvers\IterationStatus.cs" />
<Compile Include="LinearAlgebra\Solvers\Iterator.cs" />
<Compile Include="LinearAlgebra\Solvers\IterationCountStopCriterium.cs" />
<Compile Include="LinearAlgebra\Solvers\SolverSetup.cs" />
<Compile Include="Providers\LinearAlgebra\Acml\AcmlLinearAlgebraProvider.Complex.cs" />
<Compile Include="Providers\LinearAlgebra\Acml\AcmlLinearAlgebraProvider.Complex32.cs" />
<Compile Include="Providers\LinearAlgebra\Acml\AcmlLinearAlgebraProvider.Double.cs" />

Loading…
Cancel
Save