Browse Source

LA: drop iterative solver IIterator abstraction, simplifications

optimization-1
Christoph Ruegg 13 years ago
parent
commit
78b99a51b1
  1. 40
      src/Numerics/LinearAlgebra/Complex/Solvers/BiCgStab.cs
  2. 53
      src/Numerics/LinearAlgebra/Complex/Solvers/CompositeSolver.cs
  3. 40
      src/Numerics/LinearAlgebra/Complex/Solvers/GpBiCg.cs
  4. 16
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterator.cs
  5. 40
      src/Numerics/LinearAlgebra/Complex/Solvers/MlkBiCgStab.cs
  6. 44
      src/Numerics/LinearAlgebra/Complex/Solvers/TFQMR.cs
  7. 40
      src/Numerics/LinearAlgebra/Complex32/Solvers/BiCgStab.cs
  8. 52
      src/Numerics/LinearAlgebra/Complex32/Solvers/CompositeSolver.cs
  9. 40
      src/Numerics/LinearAlgebra/Complex32/Solvers/GpBiCg.cs
  10. 16
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterator.cs
  11. 40
      src/Numerics/LinearAlgebra/Complex32/Solvers/MlkBiCgStab.cs
  12. 44
      src/Numerics/LinearAlgebra/Complex32/Solvers/TFQMR.cs
  13. 76
      src/Numerics/LinearAlgebra/Double/Solvers/BiCgStab.cs
  14. 54
      src/Numerics/LinearAlgebra/Double/Solvers/CompositeSolver.cs
  15. 84
      src/Numerics/LinearAlgebra/Double/Solvers/GpBiCg.cs
  16. 16
      src/Numerics/LinearAlgebra/Double/Solvers/Iterator.cs
  17. 94
      src/Numerics/LinearAlgebra/Double/Solvers/MlkBiCgStab.cs
  18. 81
      src/Numerics/LinearAlgebra/Double/Solvers/TFQMR.cs
  19. 72
      src/Numerics/LinearAlgebra/Single/Solvers/BiCgStab.cs
  20. 54
      src/Numerics/LinearAlgebra/Single/Solvers/CompositeSolver.cs
  21. 40
      src/Numerics/LinearAlgebra/Single/Solvers/GpBiCg.cs
  22. 16
      src/Numerics/LinearAlgebra/Single/Solvers/Iterator.cs
  23. 94
      src/Numerics/LinearAlgebra/Single/Solvers/MlkBiCgStab.cs
  24. 44
      src/Numerics/LinearAlgebra/Single/Solvers/TFQMR.cs
  25. 4
      src/Numerics/LinearAlgebra/Solvers/IIterativeSolver.cs
  26. 77
      src/Numerics/LinearAlgebra/Solvers/IIterator.cs
  27. 131
      src/Numerics/LinearAlgebra/Solvers/Iterator.cs
  28. 1
      src/Numerics/Numerics.csproj
  29. 7
      src/UnitTests/LinearAlgebraTests/Complex/Solvers/Iterative/BiCgStabTest.cs
  30. 7
      src/UnitTests/LinearAlgebraTests/Complex/Solvers/Iterative/GpBiCgTest.cs
  31. 7
      src/UnitTests/LinearAlgebraTests/Complex/Solvers/Iterative/MlkBiCgStabTest.cs
  32. 7
      src/UnitTests/LinearAlgebraTests/Complex/Solvers/Iterative/TFQMRTest.cs
  33. 163
      src/UnitTests/LinearAlgebraTests/Complex/Solvers/IteratorTest.cs
  34. 13
      src/UnitTests/LinearAlgebraTests/Complex32/Solvers/Iterative/BiCgStabTest.cs
  35. 9
      src/UnitTests/LinearAlgebraTests/Complex32/Solvers/Iterative/GpBiCgTest.cs
  36. 13
      src/UnitTests/LinearAlgebraTests/Complex32/Solvers/Iterative/MlkBiCgStabTest.cs
  37. 13
      src/UnitTests/LinearAlgebraTests/Complex32/Solvers/Iterative/TFQMRTest.cs
  38. 163
      src/UnitTests/LinearAlgebraTests/Complex32/Solvers/IteratorTest.cs
  39. 7
      src/UnitTests/LinearAlgebraTests/Double/Solvers/Iterative/BiCgStabTest.cs
  40. 7
      src/UnitTests/LinearAlgebraTests/Double/Solvers/Iterative/GpBiCgTest.cs
  41. 7
      src/UnitTests/LinearAlgebraTests/Double/Solvers/Iterative/MlkBiCgStabTest.cs
  42. 7
      src/UnitTests/LinearAlgebraTests/Double/Solvers/Iterative/TFQMRTest.cs
  43. 163
      src/UnitTests/LinearAlgebraTests/Double/Solvers/IteratorTest.cs
  44. 13
      src/UnitTests/LinearAlgebraTests/Single/Solvers/Iterative/BiCgStabTest.cs
  45. 13
      src/UnitTests/LinearAlgebraTests/Single/Solvers/Iterative/GpBiCgTest.cs
  46. 13
      src/UnitTests/LinearAlgebraTests/Single/Solvers/Iterative/MlkBiCgStabTest.cs
  47. 13
      src/UnitTests/LinearAlgebraTests/Single/Solvers/Iterative/TFQMRTest.cs
  48. 163
      src/UnitTests/LinearAlgebraTests/Single/Solvers/IteratorTest.cs

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

@ -88,7 +88,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<Complex> _iterator;
Iterator<Complex> _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
@ -99,7 +99,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public BiCgStab()
@ -115,18 +115,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IIterator<Complex> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(Iterator<Complex> iterator)
: this(null, iterator)
{
}
@ -135,7 +135,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -149,19 +149,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IPreConditioner<Complex> preconditioner, IIterator<Complex> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IPreConditioner<Complex> preconditioner, Iterator<Complex> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -177,10 +177,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Complex> iterator)
public void SetIterator(Iterator<Complex> iterator)
{
_iterator = iterator;
}
@ -460,19 +460,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<Complex> result, Vector<Complex> source, Vector<Complex> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -44,6 +44,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#endif
/// <summary>
@ -64,6 +65,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
public sealed class CompositeSolver : IIterativeSolver<Complex>
{
#region Internal class - DoubleComparer
/// <summary>
/// An <c>IComparer</c> used to compare double precision floating points.
/// </summary>
@ -88,19 +90,20 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
{
return x.CompareTo(y, 1);
}
}
}
#endregion
/// <summary>
/// The default status used if the solver is not running.
/// </summary>
private static readonly ICalculationStatus NonRunningStatus = new CalculationIndetermined();
static readonly ICalculationStatus NonRunningStatus = new CalculationIndetermined();
/// <summary>
/// The default status used if the solver is running.
/// </summary>
private static readonly ICalculationStatus RunningStatus = new CalculationRunning();
static readonly ICalculationStatus RunningStatus = new CalculationRunning();
#if PORTABLE
private static readonly Dictionary<double, List<IIterativeSolverSetup<Complex>>> SolverSetups = new Dictionary<double, List<IIterativeSolverSetup<Complex>>>();
#else
@ -108,7 +111,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// The collection of iterative solver setups. Stored based on the
/// ratio between the relative speed and relative accuracy.
/// </summary>
private static readonly SortedList<double, List<IIterativeSolverSetup<Complex>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<Complex>>>(new DoubleComparer());
static readonly SortedList<double, List<IIterativeSolverSetup<Complex>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<Complex>>>(new DoubleComparer());
#endif
#region Solver information loading methods
@ -168,7 +171,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
// 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.
@ -273,7 +276,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
{
interfaceTypes.Clear();
interfaceTypes.AddRange(type.GetInterfaces());
if (!interfaceTypes.Any(match => typeof(IIterativeSolverSetup<Complex>).IsAssignableFrom(match)))
if (!interfaceTypes.Any(match => typeof (IIterativeSolverSetup<Complex>).IsAssignableFrom(match)))
{
continue;
}
@ -284,7 +287,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
{
// 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);
setup = (IIterativeSolverSetup<Complex>) Activator.CreateInstance(type);
}
catch (ArgumentException)
{
@ -324,7 +327,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
// Ok we want the solver, so store the object
var ratio = setup.SolutionSpeed / setup.Reliability;
var ratio = setup.SolutionSpeed/setup.Reliability;
if (!SolverSetups.ContainsKey(ratio))
{
SolverSetups.Add(ratio, new List<IIterativeSolverSetup<Complex>>());
@ -333,35 +336,35 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
var list = SolverSetups[ratio];
list.Add(setup);
}
}
}
#endregion
/// <summary>
/// The collection of solvers that will be used to
/// </summary>
private readonly List<IIterativeSolver<Complex>> _solvers = new List<IIterativeSolver<Complex>>();
readonly List<IIterativeSolver<Complex>> _solvers = new List<IIterativeSolver<Complex>>();
/// <summary>
/// The status of the calculation.
/// </summary>
private ICalculationStatus _status = NonRunningStatus;
ICalculationStatus _status = NonRunningStatus;
/// <summary>
/// The iterator that is used to control the iteration process.
/// </summary>
private IIterator<Complex> _iterator;
Iterator<Complex> _iterator;
/// <summary>
/// A flag indicating if the solver has been stopped or not.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// The solver that is currently running. Reference is used to be able to stop the
/// solver if the user cancels the solve process.
/// </summary>
private IIterativeSolver<Complex> _currentSolver;
IIterativeSolver<Complex> _currentSolver;
/// <summary>
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the default iterator.
@ -374,7 +377,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the specified iterator.
/// </summary>
/// <param name="iterator">The iterator that will be used to control the iteration process. </param>
public CompositeSolver(IIterator<Complex> iterator)
public CompositeSolver(Iterator<Complex> iterator)
{
_iterator = iterator;
}
@ -383,7 +386,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Sets the <c>IIterator</c> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Complex> iterator)
public void SetIterator(Iterator<Complex> iterator)
{
_iterator = iterator;
}
@ -393,9 +396,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </summary>
public ICalculationStatus IterationResult
{
get
{
return _status;
get
{
return _status;
}
}
@ -409,7 +412,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
{
_hasBeenStopped = true;
if (_currentSolver != null)
{
{
_currentSolver.StopSolve();
}
}
@ -501,7 +504,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
try
{
// Reset the iterator and pass it to the solver
_iterator.ResetToPrecalculationState();
_iterator.Reset();
solver.SetIterator(_iterator);
// Start the solver
@ -519,7 +522,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
// There was no fatal breakdown so check the status
if (_iterator.Status is CalculationConverged)
if (_iterator.HasConverged)
{
// We're done
internalResult.CopyTo(result);
@ -529,7 +532,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
// We're not done
// Either:
// - calculation finished without convergence
if (_iterator.Status is CalculationStoppedWithoutConvergence)
if (_iterator.HasStoppedWithoutConvergence)
{
// Copy the internal result to the result vector and
// continue with the calculation.
@ -558,7 +561,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <summary>
/// Load solvers
/// </summary>
private void LoadSolvers()
void LoadSolvers()
{
if (SolverSetups.Count == 0)
{

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

@ -86,7 +86,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<Complex> _iterator;
Iterator<Complex> _iterator;
/// <summary>
/// Indicates the number of <c>BiCGStab</c> steps should be taken
@ -109,7 +109,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public GpBiCg()
@ -125,18 +125,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IIterator<Complex> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(Iterator<Complex> iterator)
: this(null, iterator)
{
}
@ -145,7 +145,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -159,19 +159,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IPreConditioner<Complex> preconditioner, IIterator<Complex> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IPreConditioner<Complex> preconditioner, Iterator<Complex> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -225,10 +225,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Complex> iterator)
public void SetIterator(Iterator<Complex> iterator)
{
_iterator = iterator;
}
@ -543,19 +543,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<Complex> result, Vector<Complex> source, Vector<Complex> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

16
src/Numerics/LinearAlgebra/Complex/Solvers/Iterator.cs

@ -51,16 +51,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <summary>
/// Creates a default iterator with all the <see cref="IIterationStopCriterium{T}"/> objects.
/// </summary>
/// <returns>A new <see cref="IIterator{T}"/> object.</returns>
public static IIterator<Complex> CreateDefault()
/// <returns>A new <see cref="Iterator{T}"/> object.</returns>
public static Iterator<Complex> CreateDefault()
{
var iterator = new Iterator<Complex>();
iterator.Add(new FailureStopCriterium());
iterator.Add(new DivergenceStopCriterium());
iterator.Add(new IterationCountStopCriterium<Complex>());
iterator.Add(new ResidualStopCriterium());
return iterator;
return new Iterator<Complex>(
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex>(),
new ResidualStopCriterium());
}
}
}

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

@ -92,7 +92,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<Complex> _iterator;
Iterator<Complex> _iterator;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
@ -113,7 +113,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public MlkBiCgStab()
@ -129,18 +129,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IIterator<Complex> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(Iterator<Complex> iterator)
: this(null, iterator)
{
}
@ -149,7 +149,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -163,19 +163,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IPreConditioner<Complex> preconditioner, IIterator<Complex> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IPreConditioner<Complex> preconditioner, Iterator<Complex> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -223,10 +223,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Complex> iterator)
public void SetIterator(Iterator<Complex> iterator)
{
_iterator = iterator;
}
@ -726,19 +726,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<Complex> result, Vector<Complex> source, Vector<Complex> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -77,7 +77,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<Complex> _iterator;
Iterator<Complex> _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
@ -88,7 +88,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public TFQMR()
@ -104,18 +104,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IIterator<Complex> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(Iterator<Complex> iterator)
: this(null, iterator)
{
}
@ -124,7 +124,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -138,19 +138,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IPreConditioner<Complex> preconditioner, IIterator<Complex> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IPreConditioner<Complex> preconditioner, Iterator<Complex> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -166,10 +166,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Complex> iterator)
public void SetIterator(Iterator<Complex> iterator)
{
_iterator = iterator;
}
@ -315,7 +315,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1))
{
// FAIL HERE
_iterator.IterationCancelled();
_iterator.Cancel();
break;
}
@ -388,7 +388,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
if (rho.Real.AlmostEqual(0, 1) && rho.Imaginary.AlmostEqual(0, 1))
{
// FAIL HERE
_iterator.IterationCancelled();
_iterator.Cancel();
break;
}
@ -450,19 +450,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<Complex> result, Vector<Complex> source, Vector<Complex> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -81,7 +81,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<Numerics.Complex32> _iterator;
Iterator<Numerics.Complex32> _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
@ -92,7 +92,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public BiCgStab()
@ -108,18 +108,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IIterator<Numerics.Complex32> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(Iterator<Numerics.Complex32> iterator)
: this(null, iterator)
{
}
@ -128,7 +128,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -142,19 +142,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IPreConditioner<Numerics.Complex32> preconditioner, IIterator<Numerics.Complex32> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IPreConditioner<Numerics.Complex32> preconditioner, Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -170,10 +170,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Numerics.Complex32> iterator)
public void SetIterator(Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
}
@ -453,19 +453,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<Numerics.Complex32> result, Vector<Numerics.Complex32> source, Vector<Numerics.Complex32> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -57,6 +57,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
public sealed class CompositeSolver : IIterativeSolver<Numerics.Complex32>
{
#region Internal class - DoubleComparer
/// <summary>
/// An <c>IComparer</c> used to compare double precision floating points.
/// </summary>
@ -81,19 +82,20 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
{
return x.CompareTo(y, 1);
}
}
}
#endregion
/// <summary>
/// The default status used if the solver is not running.
/// </summary>
private static readonly ICalculationStatus NonRunningStatus = new CalculationIndetermined();
static readonly ICalculationStatus NonRunningStatus = new CalculationIndetermined();
/// <summary>
/// The default status used if the solver is running.
/// </summary>
private static readonly ICalculationStatus RunningStatus = new CalculationRunning();
static readonly ICalculationStatus RunningStatus = new CalculationRunning();
#if PORTABLE
private static readonly Dictionary<double, List<IIterativeSolverSetup<Complex32>>> SolverSetups = new Dictionary<double, List<IIterativeSolverSetup<Complex32>>>();
#else
@ -101,7 +103,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// The collection of iterative solver setups. Stored based on the
/// ratio between the relative speed and relative accuracy.
/// </summary>
private static readonly SortedList<double, List<IIterativeSolverSetup<Numerics.Complex32>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<Numerics.Complex32>>>(new DoubleComparer());
static readonly SortedList<double, List<IIterativeSolverSetup<Numerics.Complex32>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<Numerics.Complex32>>>(new DoubleComparer());
#endif
#region Solver information loading methods
@ -161,7 +163,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
// 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.
@ -266,7 +268,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
{
interfaceTypes.Clear();
interfaceTypes.AddRange(type.GetInterfaces());
if (!interfaceTypes.Any(match => typeof(IIterativeSolverSetup<Numerics.Complex32>).IsAssignableFrom(match)))
if (!interfaceTypes.Any(match => typeof (IIterativeSolverSetup<Numerics.Complex32>).IsAssignableFrom(match)))
{
continue;
}
@ -277,7 +279,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
{
// 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);
setup = (IIterativeSolverSetup<Numerics.Complex32>) Activator.CreateInstance(type);
}
catch (ArgumentException)
{
@ -317,7 +319,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
// Ok we want the solver, so store the object
var ratio = setup.SolutionSpeed / setup.Reliability;
var ratio = setup.SolutionSpeed/setup.Reliability;
if (!SolverSetups.ContainsKey(ratio))
{
SolverSetups.Add(ratio, new List<IIterativeSolverSetup<Numerics.Complex32>>());
@ -326,35 +328,35 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
var list = SolverSetups[ratio];
list.Add(setup);
}
}
}
#endregion
/// <summary>
/// The collection of solvers that will be used to
/// </summary>
private readonly List<IIterativeSolver<Numerics.Complex32>> _solvers = new List<IIterativeSolver<Numerics.Complex32>>();
readonly List<IIterativeSolver<Numerics.Complex32>> _solvers = new List<IIterativeSolver<Numerics.Complex32>>();
/// <summary>
/// The status of the calculation.
/// </summary>
private ICalculationStatus _status = NonRunningStatus;
ICalculationStatus _status = NonRunningStatus;
/// <summary>
/// The iterator that is used to control the iteration process.
/// </summary>
private IIterator<Numerics.Complex32> _iterator;
Iterator<Numerics.Complex32> _iterator;
/// <summary>
/// A flag indicating if the solver has been stopped or not.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// The solver that is currently running. Reference is used to be able to stop the
/// solver if the user cancels the solve process.
/// </summary>
private IIterativeSolver<Numerics.Complex32> _currentSolver;
IIterativeSolver<Numerics.Complex32> _currentSolver;
/// <summary>
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the default iterator.
@ -367,7 +369,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the specified iterator.
/// </summary>
/// <param name="iterator">The iterator that will be used to control the iteration process. </param>
public CompositeSolver(IIterator<Numerics.Complex32> iterator)
public CompositeSolver(Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
}
@ -376,7 +378,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Sets the <c>IIterator</c> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Numerics.Complex32> iterator)
public void SetIterator(Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
}
@ -386,9 +388,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </summary>
public ICalculationStatus IterationResult
{
get
{
return _status;
get
{
return _status;
}
}
@ -402,7 +404,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
{
_hasBeenStopped = true;
if (_currentSolver != null)
{
{
_currentSolver.StopSolve();
}
}
@ -494,7 +496,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
try
{
// Reset the iterator and pass it to the solver
_iterator.ResetToPrecalculationState();
_iterator.Reset();
solver.SetIterator(_iterator);
// Start the solver
@ -512,7 +514,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
// There was no fatal breakdown so check the status
if (_iterator.Status is CalculationConverged)
if (_iterator.HasConverged)
{
// We're done
internalResult.CopyTo(result);
@ -522,7 +524,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
// We're not done
// Either:
// - calculation finished without convergence
if (_iterator.Status is CalculationStoppedWithoutConvergence)
if (_iterator.HasStoppedWithoutConvergence)
{
// Copy the internal result to the result vector and
// continue with the calculation.
@ -551,7 +553,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <summary>
/// Load solvers
/// </summary>
private void LoadSolvers()
void LoadSolvers()
{
if (SolverSetups.Count == 0)
{

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

@ -79,7 +79,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<Numerics.Complex32> _iterator;
Iterator<Numerics.Complex32> _iterator;
/// <summary>
/// Indicates the number of <c>BiCGStab</c> steps should be taken
@ -102,7 +102,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public GpBiCg()
@ -118,18 +118,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IIterator<Numerics.Complex32> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(Iterator<Numerics.Complex32> iterator)
: this(null, iterator)
{
}
@ -138,7 +138,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -152,19 +152,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IPreConditioner<Numerics.Complex32> preconditioner, IIterator<Numerics.Complex32> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IPreConditioner<Numerics.Complex32> preconditioner, Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -218,10 +218,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Numerics.Complex32> iterator)
public void SetIterator(Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
}
@ -541,19 +541,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<Numerics.Complex32> result, Vector<Numerics.Complex32> source, Vector<Numerics.Complex32> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

16
src/Numerics/LinearAlgebra/Complex32/Solvers/Iterator.cs

@ -46,16 +46,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <summary>
/// Creates a default iterator with all the <see cref="IIterationStopCriterium{T}"/> objects.
/// </summary>
/// <returns>A new <see cref="IIterator{T}"/> object.</returns>
public static IIterator<Complex32> CreateDefault()
/// <returns>A new <see cref="Iterator{T}"/> object.</returns>
public static Iterator<Complex32> CreateDefault()
{
var iterator = new Iterator<Complex32>();
iterator.Add(new FailureStopCriterium());
iterator.Add(new DivergenceStopCriterium());
iterator.Add(new IterationCountStopCriterium<Complex32>());
iterator.Add(new ResidualStopCriterium());
return iterator;
return new Iterator<Complex32>(
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex32>(),
new ResidualStopCriterium());
}
}
}

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

@ -84,7 +84,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<Numerics.Complex32> _iterator;
Iterator<Numerics.Complex32> _iterator;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
@ -105,7 +105,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public MlkBiCgStab()
@ -121,18 +121,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IIterator<Numerics.Complex32> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(Iterator<Numerics.Complex32> iterator)
: this(null, iterator)
{
}
@ -141,7 +141,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -155,19 +155,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IPreConditioner<Numerics.Complex32> preconditioner, IIterator<Numerics.Complex32> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IPreConditioner<Numerics.Complex32> preconditioner, Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -215,10 +215,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Numerics.Complex32> iterator)
public void SetIterator(Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
}
@ -723,19 +723,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<Numerics.Complex32> result, Vector<Numerics.Complex32> source, Vector<Numerics.Complex32> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -69,7 +69,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<Numerics.Complex32> _iterator;
Iterator<Numerics.Complex32> _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
@ -80,7 +80,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public TFQMR()
@ -96,18 +96,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IIterator<Numerics.Complex32> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(Iterator<Numerics.Complex32> iterator)
: this(null, iterator)
{
}
@ -116,7 +116,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -130,19 +130,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IPreConditioner<Numerics.Complex32> preconditioner, IIterator<Numerics.Complex32> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IPreConditioner<Numerics.Complex32> preconditioner, Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -158,10 +158,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<Numerics.Complex32> iterator)
public void SetIterator(Iterator<Numerics.Complex32> iterator)
{
_iterator = iterator;
}
@ -312,7 +312,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1))
{
// FAIL HERE
_iterator.IterationCancelled();
_iterator.Cancel();
break;
}
@ -385,7 +385,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
if (rho.Real.AlmostEqual(0, 1) && rho.Imaginary.AlmostEqual(0, 1))
{
// FAIL HERE
_iterator.IterationCancelled();
_iterator.Cancel();
break;
}
@ -447,19 +447,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<Numerics.Complex32> result, Vector<Numerics.Complex32> source, Vector<Numerics.Complex32> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -70,29 +70,29 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <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>
private IPreConditioner<double> _preconditioner;
IPreConditioner<double> _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator<double> _iterator;
Iterator<double> _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public BiCgStab() : this(null, null)
@ -107,18 +107,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IIterator<double> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(Iterator<double> iterator)
: this(null, iterator)
{
}
@ -127,7 +127,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -141,19 +141,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IPreConditioner<double> preconditioner, IIterator<double> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IPreConditioner<double> preconditioner, Iterator<double> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -169,10 +169,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<double> iterator)
public void SetIterator(Iterator<double> iterator)
{
_iterator = iterator;
}
@ -182,9 +182,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
public ICalculationStatus IterationResult
{
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
}
@ -274,9 +274,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
_preconditioner = new UnitPreconditioner<double>();
}
_preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector
// This is basically a SAXPY so it could be made a lot faster
@ -285,7 +285,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
// Choose r~ (for example, r~ = r_0)
var tempResiduals = residuals.Clone();
// create seven temporary vectors needed to hold temporary
// coefficients. All vectors are mangled in each iteration.
// These are defined here to prevent stressing the garbage collector
@ -321,7 +321,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
if (iterationNumber != 0)
{
// beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
var beta = (currentRho / oldRho) * (alpha / omega);
var beta = (currentRho/oldRho)*(alpha/omega);
// p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
nu.Multiply(-omega, temp);
@ -340,12 +340,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
// SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~
matrix.Multiply(vecPdash, nu);
// alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
alpha = currentRho * 1 / tempResiduals.DotProduct(nu);
alpha = currentRho*1/tempResiduals.DotProduct(nu);
// s = r_(i-1) - alpha_i nu_i
nu.Multiply(-alpha, temp);
@ -389,7 +389,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
matrix.Multiply(vecSdash, temp);
// omega_i = temp^T s / temp^T temp
omega = temp.DotProduct(vecS) / temp.DotProduct(temp);
omega = temp.DotProduct(vecS)/temp.DotProduct(temp);
// x_i = x_(i-1) + alpha_i p^ + omega_i s^
temp.Multiply(-omega, residuals);
@ -403,7 +403,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
vecPdash.Multiply(alpha, temp);
result.Add(temp, temp2);
temp2.CopyTo(result);
// for continuation it is necessary that omega_i != 0.0
// If omega is only 1 ULP from zero then we fail.
if (omega.AlmostEqual(0, 1))
@ -433,11 +433,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</param>
private static void CalculateTrueResidual(Matrix<double> matrix, Vector<double> residual, Vector<double> x, Vector<double> b)
static void CalculateTrueResidual(Matrix<double> matrix, Vector<double> residual, Vector<double> x, Vector<double> b)
{
// -Ax = residual
matrix.Multiply(x, residual);
// Do not use residual = residual.Negate() because it creates another object
residual.Multiply(-1, residual);
@ -453,21 +453,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector<double> result, Vector<double> source, Vector<double> residuals)
bool ShouldContinue(int iterationNumber, Vector<double> result, Vector<double> source, Vector<double> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -57,6 +57,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
public sealed class CompositeSolver : IIterativeSolver<double>
{
#region Internal class - DoubleComparer
/// <summary>
/// An <c>IComparer</c> used to compare double precision floating points.
/// </summary>
@ -78,19 +79,20 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
return x.CompareTo(y, 1);
}
}
}
#endregion
/// <summary>
/// The default status used if the solver is not running.
/// </summary>
private static readonly ICalculationStatus NonRunningStatus = new CalculationIndetermined();
static readonly ICalculationStatus NonRunningStatus = new CalculationIndetermined();
/// <summary>
/// The default status used if the solver is running.
/// </summary>
private static readonly ICalculationStatus RunningStatus = new CalculationRunning();
static readonly ICalculationStatus RunningStatus = new CalculationRunning();
#if PORTABLE
private static readonly Dictionary<double, List<IIterativeSolverSetup<double>>> SolverSetups = new Dictionary<double, List<IIterativeSolverSetup<double>>>();
#else
@ -98,7 +100,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// The collection of iterative solver setups. Stored based on the
/// ratio between the relative speed and relative accuracy.
/// </summary>
private static readonly SortedList<double, List<IIterativeSolverSetup<double>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<double>>>(new DoubleComparer());
static readonly SortedList<double, List<IIterativeSolverSetup<double>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<double>>>(new DoubleComparer());
#endif
#region Solver information loading methods
@ -158,7 +160,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
// 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.
@ -263,7 +265,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
interfaceTypes.Clear();
interfaceTypes.AddRange(type.GetInterfaces());
if (!interfaceTypes.Any(match => typeof(IIterativeSolverSetup<double>).IsAssignableFrom(match)))
if (!interfaceTypes.Any(match => typeof (IIterativeSolverSetup<double>).IsAssignableFrom(match)))
{
continue;
}
@ -274,7 +276,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
// 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);
setup = (IIterativeSolverSetup<double>) Activator.CreateInstance(type);
}
catch (ArgumentException)
{
@ -314,7 +316,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
// Ok we want the solver, so store the object
var ratio = setup.SolutionSpeed / setup.Reliability;
var ratio = setup.SolutionSpeed/setup.Reliability;
if (!SolverSetups.ContainsKey(ratio))
{
SolverSetups.Add(ratio, new List<IIterativeSolverSetup<double>>());
@ -323,35 +325,35 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
var list = SolverSetups[ratio];
list.Add(setup);
}
}
}
#endregion
/// <summary>
/// The collection of solvers that will be used to
/// </summary>
private readonly List<IIterativeSolver<double>> _solvers = new List<IIterativeSolver<double>>();
readonly List<IIterativeSolver<double>> _solvers = new List<IIterativeSolver<double>>();
/// <summary>
/// The status of the calculation.
/// </summary>
private ICalculationStatus _status = NonRunningStatus;
ICalculationStatus _status = NonRunningStatus;
/// <summary>
/// The iterator that is used to control the iteration process.
/// </summary>
private IIterator<double> _iterator;
Iterator<double> _iterator;
/// <summary>
/// A flag indicating if the solver has been stopped or not.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// The solver that is currently running. Reference is used to be able to stop the
/// solver if the user cancels the solve process.
/// </summary>
private IIterativeSolver<double> _currentSolver;
IIterativeSolver<double> _currentSolver;
/// <summary>
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the default iterator.
@ -364,16 +366,16 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the specified iterator.
/// </summary>
/// <param name="iterator">The iterator that will be used to control the iteration process. </param>
public CompositeSolver(IIterator<double> iterator)
public CompositeSolver(Iterator<double> iterator)
{
_iterator = iterator;
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<double> iterator)
public void SetIterator(Iterator<double> iterator)
{
_iterator = iterator;
}
@ -383,9 +385,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
public ICalculationStatus IterationResult
{
get
{
return _status;
get
{
return _status;
}
}
@ -399,7 +401,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
_hasBeenStopped = true;
if (_currentSolver != null)
{
{
_currentSolver.StopSolve();
}
}
@ -491,7 +493,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
try
{
// Reset the iterator and pass it to the solver
_iterator.ResetToPrecalculationState();
_iterator.Reset();
solver.SetIterator(_iterator);
// Start the solver
@ -509,7 +511,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
// There was no fatal breakdown so check the status
if (_iterator.Status is CalculationConverged)
if (_iterator.HasConverged)
{
// We're done
internalResult.CopyTo(result);
@ -519,7 +521,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
// We're not done
// Either:
// - calculation finished without convergence
if (_iterator.Status is CalculationStoppedWithoutConvergence)
if (_iterator.HasStoppedWithoutConvergence)
{
// Copy the internal result to the result vector and
// continue with the calculation.
@ -548,7 +550,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <summary>
/// Load solvers
/// </summary>
private void LoadSolvers()
void LoadSolvers()
{
if (SolverSetups.Count == 0)
{

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

@ -68,41 +68,41 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <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>
private IPreConditioner<double> _preconditioner;
IPreConditioner<double> _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator<double> _iterator;
Iterator<double> _iterator;
/// <summary>
/// Indicates the number of <c>BiCGStab</c> steps should be taken
/// before switching.
/// </summary>
private int _numberOfBiCgStabSteps = 1;
int _numberOfBiCgStabSteps = 1;
/// <summary>
/// Indicates the number of <c>GPBiCG</c> steps should be taken
/// before switching.
/// </summary>
private int _numberOfGpbiCgSteps = 4;
int _numberOfGpbiCgSteps = 4;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public GpBiCg() : this(null, null)
@ -117,18 +117,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IIterator<double> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(Iterator<double> iterator)
: this(null, iterator)
{
}
@ -137,7 +137,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -151,19 +151,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IPreConditioner<double> preconditioner, IIterator<double> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IPreConditioner<double> preconditioner, Iterator<double> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -187,7 +187,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
throw new ArgumentOutOfRangeException("value");
}
_numberOfBiCgStabSteps = value;
_numberOfBiCgStabSteps = value;
}
}
@ -223,10 +223,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<double> iterator)
public void SetIterator(Iterator<double> iterator)
{
_iterator = iterator;
}
@ -236,7 +236,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
public ICalculationStatus IterationResult
{
get
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
@ -329,7 +329,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
_preconditioner = new UnitPreconditioner<double>();
}
_preconditioner.Initialize(matrix);
// x_0 is initial guess
@ -384,7 +384,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
matrix.Multiply(temp, s);
// alpha_k = (r*_0 * r_k) / (r*_0 * s_k)
var alpha = rdash.DotProduct(residuals) / rdash.DotProduct(s);
var alpha = rdash.DotProduct(residuals)/rdash.DotProduct(s);
// y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k
s.Subtract(w, temp);
@ -400,14 +400,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
// t_k = r_k - alpha_k s_k
s.Multiply(-alpha, temp2);
residuals.Add(temp2, t);
// Solve M d_k = t_k
_preconditioner.Approximate(t, temp);
// c_k = A d_k
matrix.Multiply(temp, c);
var cdot = c.DotProduct(c);
// cDot can only be zero if c is a zero vector
// We'll set cDot to 1 if it is zero to prevent NaN's
// Note that the calculation should continue fine because
@ -427,7 +427,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber))
{
// sigma_k = (c_k * t_k) / (c_k * c_k)
sigma = ctdot / cdot;
sigma = ctdot/cdot;
// eta_k = 0
eta = 0;
@ -448,13 +448,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
var ytdot = y.DotProduct(t);
var cydot = c.DotProduct(y);
var denom = (cdot * ydot) - (cydot * cydot);
var denom = (cdot*ydot) - (cydot*cydot);
// sigma_k = ((y_k * y_k)(c_k * t_k) - (y_k * t_k)(c_k * y_k)) / ((c_k * c_k)(y_k * y_k) - (y_k * c_k)(c_k * y_k))
sigma = ((ydot * ctdot) - (ytdot * cydot)) / denom;
sigma = ((ydot*ctdot) - (ytdot*cydot))/denom;
// eta_k = ((c_k * c_k)(y_k * t_k) - (y_k * c_k)(c_k * t_k)) / ((c_k * c_k)(y_k * y_k) - (y_k * c_k)(c_k * y_k))
eta = ((cdot * ytdot) - (cydot * ctdot)) / denom;
eta = ((cdot*ytdot) - (cydot*ctdot))/denom;
}
// u_k = sigma_k s_k + eta_k (t_(k-1) - r_k + beta_(k-1) u_(k-1))
@ -482,7 +482,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
p.Multiply(alpha, temp2);
xtemp.Add(temp2, temp3);
temp3.CopyTo(xtemp);
xtemp.Add(z, temp3);
temp3.CopyTo(xtemp);
@ -500,7 +500,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
// beta_k = alpha_k / sigma_k * (r*_0 * r_(k+1)) / (r*_0 * r_k)
// But first we check if there is a possible NaN. If so just reset beta to zero.
beta = (!sigma.AlmostEqual(0, 1)) ? alpha / sigma * rdash.DotProduct(residuals) / rdash.DotProduct(t0) : 0;
beta = (!sigma.AlmostEqual(0, 1)) ? alpha/sigma*rdash.DotProduct(residuals)/rdash.DotProduct(t0) : 0;
// w_k = c_k + beta_k s_k
s.Multiply(beta, temp2);
@ -529,7 +529,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</param>
private static void CalculateTrueResidual(Matrix<double> matrix, Vector<double> residual, Vector<double> x, Vector<double> b)
static void CalculateTrueResidual(Matrix<double> matrix, Vector<double> residual, Vector<double> x, Vector<double> b)
{
// -Ax = residual
matrix.Multiply(x, residual);
@ -547,33 +547,31 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector<double> result, Vector<double> source, Vector<double> residuals)
bool ShouldContinue(int iterationNumber, Vector<double> result, Vector<double> source, Vector<double> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>
/// Decide if to do steps with BiCgStab
/// </summary>
/// <param name="iterationNumber">Number of iteration</param>
/// <returns><c>true</c> if yes, otherwise <c>false</c></returns>
private bool ShouldRunBiCgStabSteps(int iterationNumber)
bool ShouldRunBiCgStabSteps(int iterationNumber)
{
// Run the first steps as BiCGStab
// The number of steps past a whole iteration set
var difference = iterationNumber % (_numberOfBiCgStabSteps + _numberOfGpbiCgSteps);
var difference = iterationNumber%(_numberOfBiCgStabSteps + _numberOfGpbiCgSteps);
// Do steps with BiCGStab if:
// - The difference is zero or more (i.e. we have done zero or more complete cycles)

16
src/Numerics/LinearAlgebra/Double/Solvers/Iterator.cs

@ -44,16 +44,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <summary>
/// Creates a default iterator with all the <see cref="IIterationStopCriterium{T}"/> objects.
/// </summary>
/// <returns>A new <see cref="IIterator{T}"/> object.</returns>
public static IIterator<double> CreateDefault()
/// <returns>A new <see cref="Iterator{T}"/> object.</returns>
public static Iterator<double> CreateDefault()
{
var iterator = new Iterator<double>();
iterator.Add(new FailureStopCriterium());
iterator.Add(new DivergenceStopCriterium());
iterator.Add(new IterationCountStopCriterium<double>());
iterator.Add(new ResidualStopCriterium());
return iterator;
return new Iterator<double>(
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<double>(),
new ResidualStopCriterium());
}
}
}

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

@ -67,45 +67,45 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <summary>
/// The default number of starting vectors.
/// </summary>
private const int DefaultNumberOfStartingVectors = 50;
const int DefaultNumberOfStartingVectors = 50;
/// <summary>
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <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>
private IPreConditioner<double> _preconditioner;
IPreConditioner<double> _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator<double> _iterator;
Iterator<double> _iterator;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary>
private IList<Vector<double>> _startingVectors;
IList<Vector<double>> _startingVectors;
/// <summary>
/// The number of starting vectors used by the algorithm
/// </summary>
private int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public MlkBiCgStab() : this(null, null)
@ -120,18 +120,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IIterator<double> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(Iterator<double> iterator)
: this(null, iterator)
{
}
@ -140,7 +140,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -154,19 +154,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IPreConditioner<double> preconditioner, IIterator<double> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IPreConditioner<double> preconditioner, Iterator<double> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -217,10 +217,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<double> iterator)
public void SetIterator(Iterator<double> iterator)
{
_iterator = iterator;
}
@ -349,7 +349,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
{
_preconditioner = new UnitPreconditioner<double>();
}
_preconditioner.Initialize(matrix);
// Choose an initial guess x_0
@ -403,7 +403,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
var zw = new DenseVector(residuals.Count);
var d = CreateVectorArray(_startingVectors.Count, residuals.Count);
// g_0 = r_0
var g = CreateVectorArray(_startingVectors.Count, residuals.Count);
residuals.CopyTo(g[k - 1]);
@ -428,7 +428,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
// alpha_(jk+1) = q^T_1 r_((j-1)k+k) / c_((j-1)k+k)
var alpha = _startingVectors[0].DotProduct(residuals) / c[k - 1];
var alpha = _startingVectors[0].DotProduct(residuals)/c[k - 1];
// u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k)
w[k - 1].Multiply(-alpha, temp);
@ -450,7 +450,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
rho = 1.0;
}
rho = -u.DotProduct(temp) / rho;
rho = -u.DotProduct(temp)/rho;
// r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1)
u.CopyTo(residuals);
@ -468,7 +468,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
gtemp.Multiply(alpha, gtemp);
xtemp.Add(gtemp, temp2);
temp2.CopyTo(xtemp);
// Check convergence and stop if we are converged.
if (!ShouldContinue(iterationNumber, xtemp, input, residuals))
{
@ -503,7 +503,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
for (var s = i; s < k - 1; s++)
{
// beta^(jk+i)_((j-1)k+s) = -q^t_(s+1) z_d / c_((j-1)k+s)
beta = -_startingVectors[s + 1].DotProduct(zd) / c[s];
beta = -_startingVectors[s + 1].DotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s)
d[s].Multiply(beta, temp);
@ -522,7 +522,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
}
beta = rho * c[k - 1];
beta = rho*c[k - 1];
if (beta.AlmostEqual(0, 1))
{
throw new Exception("Iterative solver experience a numerical break down");
@ -531,7 +531,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
// beta^(jk+i)_((j-1)k+k) = -(q^T_1 (r_(jk+1) + rho_(j+1) z_w)) / (rho_(j+1) c_((j-1)k+k))
zw.Multiply(rho, temp2);
residuals.Add(temp2, temp);
beta = -_startingVectors[0].DotProduct(temp) / beta;
beta = -_startingVectors[0].DotProduct(temp)/beta;
// z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k)
g[k - 1].Multiply(beta, temp);
@ -551,7 +551,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
for (var s = 0; s < i - 1; s++)
{
// beta^(jk+i)_(jk+s) = -q^T_s+1 z_d / c_(jk+s)
beta = -_startingVectors[s + 1].DotProduct(zd) / c[s];
beta = -_startingVectors[s + 1].DotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s)
d[s].Multiply(beta, temp);
@ -581,7 +581,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
// alpha_(jk+i+1) = q^T_(i+1) u_(jk+i) / c_(jk+i)
alpha = _startingVectors[i + 1].DotProduct(u) / c[i];
alpha = _startingVectors[i + 1].DotProduct(u)/c[i];
// u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i)
d[i].Multiply(-alpha, temp);
@ -592,7 +592,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
_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);
gtemp.Multiply(rho*alpha, temp);
xtemp.Add(temp, temp2);
temp2.CopyTo(xtemp);
@ -600,7 +600,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
matrix.Multiply(gtemp, w[i]);
// r_(jk+i+1) = r_(jk+i) - rho_(j+1) alpha_(jk+i+1) w_(jk+i)
w[i].Multiply(-rho * alpha, temp);
w[i].Multiply(-rho*alpha, temp);
residuals.Add(temp, temp2);
temp2.CopyTo(residuals);
@ -627,7 +627,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="maximumNumberOfStartingVectors">Maximum number</param>
/// <param name="numberOfVariables">Number of variables</param>
/// <returns>Number of starting vectors to create</returns>
private static int NumberOfStartingVectorsToCreate(int maximumNumberOfStartingVectors, int numberOfVariables)
static int NumberOfStartingVectorsToCreate(int maximumNumberOfStartingVectors, int numberOfVariables)
{
// Create no more starting vectors than the size of the problem - 1
return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 1));
@ -644,7 +644,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// the <paramref name="numberOfVariables"/> is smaller than
/// the <paramref name="maximumNumberOfStartingVectors"/>.
/// </returns>
private static IList<Vector<double>> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
static IList<Vector<double>> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
{
// Create no more starting vectors than the size of the problem - 1
// Get random values and then orthogonalize them with
@ -659,7 +659,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
for (var i = 0; i < matrix.ColumnCount; i++)
{
var samples = distribution.Samples().Take(matrix.RowCount).ToArray();
// Set the column
matrix.SetColumn(i, samples);
}
@ -673,9 +673,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
for (var i = 0; i < orthogonalMatrix.ColumnCount; i++)
{
result.Add(orthogonalMatrix.Column(i));
// Normalize the result vector
result[i].Multiply(1 / result[i].L2Norm(), result[i]);
result[i].Multiply(1/result[i].L2Norm(), result[i]);
}
return result;
@ -687,7 +687,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="arraySize">Number of vectors</param>
/// <param name="vectorSize">Size of each vector</param>
/// <returns>Array of random vectors</returns>
private static Vector<double>[] CreateVectorArray(int arraySize, int vectorSize)
static Vector<double>[] CreateVectorArray(int arraySize, int vectorSize)
{
var result = new Vector<double>[arraySize];
for (var i = 0; i < result.Length; i++)
@ -705,7 +705,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="residual">Residual <see cref="Vector"/> data.</param>
/// <param name="x">x <see cref="Vector"/> data.</param>
/// <param name="b">b <see cref="Vector"/> data.</param>
private static void CalculateTrueResidual(Matrix<double> matrix, Vector<double> residual, Vector<double> x, Vector<double> b)
static void CalculateTrueResidual(Matrix<double> matrix, Vector<double> residual, Vector<double> x, Vector<double> b)
{
// -Ax = residual
matrix.Multiply(x, residual);
@ -723,21 +723,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector<double> result, Vector<double> source, Vector<double> residuals)
bool ShouldContinue(int iterationNumber, Vector<double> result, Vector<double> source, Vector<double> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -29,7 +29,6 @@
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Double.Solvers.Preconditioners;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using MathNet.Numerics.Properties;
@ -59,29 +58,29 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <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>
private IPreConditioner<double> _preconditioner;
IPreConditioner<double> _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator<double> _iterator;
Iterator<double> _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public TFQMR() : this(null, null)
@ -96,18 +95,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IIterator<double> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(Iterator<double> iterator)
: this(null, iterator)
{
}
@ -116,7 +115,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -130,19 +129,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IPreConditioner<double> preconditioner, IIterator<double> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IPreConditioner<double> preconditioner, Iterator<double> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -158,10 +157,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<double> iterator)
public void SetIterator(Iterator<double> iterator)
{
_iterator = iterator;
}
@ -171,9 +170,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
public ICalculationStatus IterationResult
{
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
}
@ -296,7 +295,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
// Calculate the initial values for v
// M temp = yEven
_preconditioner.Approximate(yeven, temp);
// v = A temp
matrix.Multiply(temp, v);
@ -315,12 +314,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
if (sigma.AlmostEqual(0, 1))
{
// FAIL HERE
_iterator.IterationCancelled();
_iterator.Cancel();
break;
}
// alpha = rho / sigma
alpha = rho / sigma;
alpha = rho/sigma;
// yOdd = yEven - alpha * v
v.Multiply(-alpha, temp1);
@ -345,18 +344,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
temp2.CopyTo(pseudoResiduals);
// d = yOdd + theta * theta * eta / alpha * d
d.Multiply(theta * theta * eta / alpha, temp);
d.Multiply(theta*theta*eta/alpha, temp);
yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.L2Norm() / tau;
var c = 1 / Math.Sqrt(1 + (theta * theta));
theta = pseudoResiduals.L2Norm()/tau;
var c = 1/Math.Sqrt(1 + (theta*theta));
// tau = tau * theta * c
tau *= theta * c;
tau *= theta*c;
// eta = c^2 * alpha
eta = c * c * alpha;
eta = c*c*alpha;
// x = x + eta * d
d.Multiply(eta, temp1);
@ -388,12 +387,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
if (rho.AlmostEqual(0, 1))
{
// FAIL HERE
_iterator.IterationCancelled();
_iterator.Cancel();
break;
}
var rhoNew = pseudoResiduals.DotProduct(r);
var beta = rhoNew / rho;
var beta = rhoNew/rho;
// Update rho for the next loop
rho = rhoNew;
@ -430,7 +429,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</param>
private static void CalculateTrueResidual(Matrix<double> matrix, Vector<double> residual, Vector<double> x, Vector<double> b)
static void CalculateTrueResidual(Matrix<double> matrix, Vector<double> residual, Vector<double> x, Vector<double> b)
{
// -Ax = residual
matrix.Multiply(x, residual);
@ -448,21 +447,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector<double> result, Vector<double> source, Vector<double> residuals)
bool ShouldContinue(int iterationNumber, Vector<double> result, Vector<double> source, Vector<double> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>
@ -470,9 +467,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers
/// </summary>
/// <param name="number">Number to check</param>
/// <returns><c>true</c> if <paramref name="number"/> even, otherwise <c>false</c></returns>
private static bool IsEven(int number)
static bool IsEven(int number)
{
return number % 2 == 0;
return number%2 == 0;
}
/// <summary>

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

@ -70,29 +70,29 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <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>
private IPreConditioner<float> _preconditioner;
IPreConditioner<float> _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator<float> _iterator;
Iterator<float> _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public BiCgStab() : this(null, null)
@ -107,18 +107,18 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IIterator<float> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(Iterator<float> iterator)
: this(null, iterator)
{
}
@ -127,7 +127,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -141,19 +141,19 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IPreConditioner<float> preconditioner, IIterator<float> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IPreConditioner<float> preconditioner, Iterator<float> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -169,10 +169,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<float> iterator)
public void SetIterator(Iterator<float> iterator)
{
_iterator = iterator;
}
@ -182,9 +182,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </summary>
public ICalculationStatus IterationResult
{
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
}
@ -274,9 +274,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
_preconditioner = new UnitPreconditioner<float>();
}
_preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector
// This is basically a SAXPY so it could be made a lot faster
@ -321,7 +321,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
if (iterationNumber != 0)
{
// beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
var beta = (currentRho / oldRho) * (alpha / omega);
var beta = (currentRho/oldRho)*(alpha/omega);
// p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
nu.Multiply(-omega, temp);
@ -340,12 +340,12 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
// SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~
matrix.Multiply(vecPdash, nu);
// alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
alpha = currentRho * 1 / tempResiduals.DotProduct(nu);
alpha = currentRho*1/tempResiduals.DotProduct(nu);
// s = r_(i-1) - alpha_i nu_i
nu.Multiply(-alpha, temp);
@ -389,7 +389,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
matrix.Multiply(vecSdash, temp);
// omega_i = temp^T s / temp^T temp
omega = temp.DotProduct(vecS) / temp.DotProduct(temp);
omega = temp.DotProduct(vecS)/temp.DotProduct(temp);
// x_i = x_(i-1) + alpha_i p^ + omega_i s^
temp.Multiply(-omega, residuals);
@ -433,11 +433,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</param>
private static void CalculateTrueResidual(Matrix<float> matrix, Vector<float> residual, Vector<float> x, Vector<float> b)
static void CalculateTrueResidual(Matrix<float> matrix, Vector<float> residual, Vector<float> x, Vector<float> b)
{
// -Ax = residual
matrix.Multiply(x, residual);
// Do not use residual = residual.Negate() because it creates another object
residual.Multiply(-1, residual);
@ -453,21 +453,19 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector<float> result, Vector<float> source, Vector<float> residuals)
bool ShouldContinue(int iterationNumber, Vector<float> result, Vector<float> source, Vector<float> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -57,6 +57,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
public sealed class CompositeSolver : IIterativeSolver<float>
{
#region Internal class - DoubleComparer
/// <summary>
/// An <c>IComparer</c> used to compare double precision floating points.
/// </summary>
@ -81,19 +82,20 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
return x.CompareTo(y, 1);
}
}
}
#endregion
/// <summary>
/// The default status used if the solver is not running.
/// </summary>
private static readonly ICalculationStatus NonRunningStatus = new CalculationIndetermined();
static readonly ICalculationStatus NonRunningStatus = new CalculationIndetermined();
/// <summary>
/// The default status used if the solver is running.
/// </summary>
private static readonly ICalculationStatus RunningStatus = new CalculationRunning();
static readonly ICalculationStatus RunningStatus = new CalculationRunning();
#if PORTABLE
private static readonly Dictionary<double, List<IIterativeSolverSetup<float>>> SolverSetups = new Dictionary<double, List<IIterativeSolverSetup<float>>>();
#else
@ -101,7 +103,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// The collection of iterative solver setups. Stored based on the
/// ratio between the relative speed and relative accuracy.
/// </summary>
private static readonly SortedList<double, List<IIterativeSolverSetup<float>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<float>>>(new DoubleComparer());
static readonly SortedList<double, List<IIterativeSolverSetup<float>>> SolverSetups = new SortedList<double, List<IIterativeSolverSetup<float>>>(new DoubleComparer());
#endif
#region Solver information loading methods
@ -161,7 +163,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
// 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.
@ -266,7 +268,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
interfaceTypes.Clear();
interfaceTypes.AddRange(type.GetInterfaces());
if (!interfaceTypes.Any(match => typeof(IIterativeSolverSetup<float>).IsAssignableFrom(match)))
if (!interfaceTypes.Any(match => typeof (IIterativeSolverSetup<float>).IsAssignableFrom(match)))
{
continue;
}
@ -277,7 +279,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
// 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);
setup = (IIterativeSolverSetup<float>) Activator.CreateInstance(type);
}
catch (ArgumentException)
{
@ -317,7 +319,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
// Ok we want the solver, so store the object
var ratio = setup.SolutionSpeed / setup.Reliability;
var ratio = setup.SolutionSpeed/setup.Reliability;
if (!SolverSetups.ContainsKey(ratio))
{
SolverSetups.Add(ratio, new List<IIterativeSolverSetup<float>>());
@ -326,35 +328,35 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
var list = SolverSetups[ratio];
list.Add(setup);
}
}
}
#endregion
/// <summary>
/// The collection of solvers that will be used to
/// </summary>
private readonly List<IIterativeSolver<float>> _solvers = new List<IIterativeSolver<float>>();
readonly List<IIterativeSolver<float>> _solvers = new List<IIterativeSolver<float>>();
/// <summary>
/// The status of the calculation.
/// </summary>
private ICalculationStatus _status = NonRunningStatus;
ICalculationStatus _status = NonRunningStatus;
/// <summary>
/// The iterator that is used to control the iteration process.
/// </summary>
private IIterator<float> _iterator;
Iterator<float> _iterator;
/// <summary>
/// A flag indicating if the solver has been stopped or not.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// The solver that is currently running. Reference is used to be able to stop the
/// solver if the user cancels the solve process.
/// </summary>
private IIterativeSolver<float> _currentSolver;
IIterativeSolver<float> _currentSolver;
/// <summary>
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the default iterator.
@ -367,16 +369,16 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// Initializes a new instance of the <see cref="CompositeSolver"/> class with the specified iterator.
/// </summary>
/// <param name="iterator">The iterator that will be used to control the iteration process. </param>
public CompositeSolver(IIterator<float> iterator)
public CompositeSolver(Iterator<float> iterator)
{
_iterator = iterator;
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<float> iterator)
public void SetIterator(Iterator<float> iterator)
{
_iterator = iterator;
}
@ -386,9 +388,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </summary>
public ICalculationStatus IterationResult
{
get
{
return _status;
get
{
return _status;
}
}
@ -402,7 +404,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
_hasBeenStopped = true;
if (_currentSolver != null)
{
{
_currentSolver.StopSolve();
}
}
@ -494,7 +496,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
try
{
// Reset the iterator and pass it to the solver
_iterator.ResetToPrecalculationState();
_iterator.Reset();
solver.SetIterator(_iterator);
// Start the solver
@ -512,7 +514,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
// There was no fatal breakdown so check the status
if (_iterator.Status is CalculationConverged)
if (_iterator.HasConverged)
{
// We're done
internalResult.CopyTo(result);
@ -522,7 +524,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
// We're not done
// Either:
// - calculation finished without convergence
if (_iterator.Status is CalculationStoppedWithoutConvergence)
if (_iterator.HasStoppedWithoutConvergence)
{
// Copy the internal result to the result vector and
// continue with the calculation.
@ -551,7 +553,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <summary>
/// Load solvers
/// </summary>
private void LoadSolvers()
void LoadSolvers()
{
if (SolverSetups.Count == 0)
{

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

@ -79,7 +79,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<float> _iterator;
Iterator<float> _iterator;
/// <summary>
/// Indicates the number of <c>BiCGStab</c> steps should be taken
@ -102,7 +102,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public GpBiCg()
@ -118,18 +118,18 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IIterator<float> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(Iterator<float> iterator)
: this(null, iterator)
{
}
@ -138,7 +138,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// Initializes a new instance of the <see cref="GpBiCg"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -152,19 +152,19 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IPreConditioner<float> preconditioner, IIterator<float> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public GpBiCg(IPreConditioner<float> preconditioner, Iterator<float> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -218,10 +218,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<float> iterator)
public void SetIterator(Iterator<float> iterator)
{
_iterator = iterator;
}
@ -541,19 +541,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<float> result, Vector<float> source, Vector<float> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

16
src/Numerics/LinearAlgebra/Single/Solvers/Iterator.cs

@ -44,16 +44,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <summary>
/// Creates a default iterator with all the <see cref="IIterationStopCriterium{T}"/> objects.
/// </summary>
/// <returns>A new <see cref="IIterator{T}"/> object.</returns>
public static IIterator<float> CreateDefault()
/// <returns>A new <see cref="Iterator{T}"/> object.</returns>
public static Iterator<float> CreateDefault()
{
var iterator = new Iterator<float>();
iterator.Add(new FailureStopCriterium());
iterator.Add(new DivergenceStopCriterium());
iterator.Add(new IterationCountStopCriterium<float>());
iterator.Add(new ResidualStopCriterium());
return iterator;
return new Iterator<float>(
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<float>(),
new ResidualStopCriterium());
}
}
}

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

@ -66,45 +66,45 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <summary>
/// The default number of starting vectors.
/// </summary>
private const int DefaultNumberOfStartingVectors = 50;
const int DefaultNumberOfStartingVectors = 50;
/// <summary>
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <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>
private IPreConditioner<float> _preconditioner;
IPreConditioner<float> _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator<float> _iterator;
Iterator<float> _iterator;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary>
private IList<Vector<float>> _startingVectors;
IList<Vector<float>> _startingVectors;
/// <summary>
/// The number of starting vectors used by the algorithm
/// </summary>
private int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public MlkBiCgStab() : this(null, null)
@ -119,18 +119,18 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IIterator<float> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(Iterator<float> iterator)
: this(null, iterator)
{
}
@ -139,7 +139,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -153,19 +153,19 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IPreConditioner<float> preconditioner, IIterator<float> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IPreConditioner<float> preconditioner, Iterator<float> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -216,10 +216,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<float> iterator)
public void SetIterator(Iterator<float> iterator)
{
_iterator = iterator;
}
@ -348,7 +348,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
{
_preconditioner = new UnitPreconditioner<float>();
}
_preconditioner.Initialize(matrix);
// Choose an initial guess x_0
@ -402,7 +402,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
var zw = new DenseVector(residuals.Count);
var d = CreateVectorArray(_startingVectors.Count, residuals.Count);
// g_0 = r_0
var g = CreateVectorArray(_startingVectors.Count, residuals.Count);
residuals.CopyTo(g[k - 1]);
@ -427,7 +427,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
// alpha_(jk+1) = q^T_1 r_((j-1)k+k) / c_((j-1)k+k)
var alpha = _startingVectors[0].DotProduct(residuals) / c[k - 1];
var alpha = _startingVectors[0].DotProduct(residuals)/c[k - 1];
// u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k)
w[k - 1].Multiply(-alpha, temp);
@ -449,7 +449,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
rho = 1.0f;
}
rho = -u.DotProduct(temp) / rho;
rho = -u.DotProduct(temp)/rho;
// r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1)
u.CopyTo(residuals);
@ -502,7 +502,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
for (var s = i; s < k - 1; s++)
{
// beta^(jk+i)_((j-1)k+s) = -q^t_(s+1) z_d / c_((j-1)k+s)
beta = -_startingVectors[s + 1].DotProduct(zd) / c[s];
beta = -_startingVectors[s + 1].DotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s)
d[s].Multiply(beta, temp);
@ -521,7 +521,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
}
beta = rho * c[k - 1];
beta = rho*c[k - 1];
if (beta.AlmostEqual(0, 1))
{
throw new Exception("Iterative solver experience a numerical break down");
@ -530,7 +530,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
// beta^(jk+i)_((j-1)k+k) = -(q^T_1 (r_(jk+1) + rho_(j+1) z_w)) / (rho_(j+1) c_((j-1)k+k))
zw.Multiply(rho, temp2);
residuals.Add(temp2, temp);
beta = -_startingVectors[0].DotProduct(temp) / beta;
beta = -_startingVectors[0].DotProduct(temp)/beta;
// z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k)
g[k - 1].Multiply(beta, temp);
@ -550,7 +550,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
for (var s = 0; s < i - 1; s++)
{
// beta^(jk+i)_(jk+s) = -q^T_s+1 z_d / c_(jk+s)
beta = -_startingVectors[s + 1].DotProduct(zd) / c[s];
beta = -_startingVectors[s + 1].DotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s)
d[s].Multiply(beta, temp);
@ -580,7 +580,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
// alpha_(jk+i+1) = q^T_(i+1) u_(jk+i) / c_(jk+i)
alpha = _startingVectors[i + 1].DotProduct(u) / c[i];
alpha = _startingVectors[i + 1].DotProduct(u)/c[i];
// u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i)
d[i].Multiply(-alpha, temp);
@ -591,7 +591,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
_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);
gtemp.Multiply(rho*alpha, temp);
xtemp.Add(temp, temp2);
temp2.CopyTo(xtemp);
@ -599,7 +599,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
matrix.Multiply(gtemp, w[i]);
// r_(jk+i+1) = r_(jk+i) - rho_(j+1) alpha_(jk+i+1) w_(jk+i)
w[i].Multiply(-rho * alpha, temp);
w[i].Multiply(-rho*alpha, temp);
residuals.Add(temp, temp2);
temp2.CopyTo(residuals);
@ -626,7 +626,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="maximumNumberOfStartingVectors">Maximum number</param>
/// <param name="numberOfVariables">Number of variables</param>
/// <returns>Number of starting vectors to create</returns>
private static int NumberOfStartingVectorsToCreate(int maximumNumberOfStartingVectors, int numberOfVariables)
static int NumberOfStartingVectorsToCreate(int maximumNumberOfStartingVectors, int numberOfVariables)
{
// Create no more starting vectors than the size of the problem - 1
return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 1));
@ -643,7 +643,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// the <paramref name="numberOfVariables"/> is smaller than
/// the <paramref name="maximumNumberOfStartingVectors"/>.
/// </returns>
private static IList<Vector<float>> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
static IList<Vector<float>> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
{
// Create no more starting vectors than the size of the problem - 1
// Get random values and then orthogonalize them with
@ -660,9 +660,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
var samples = new float[matrix.RowCount];
for (var j = 0; j < matrix.RowCount; j++)
{
samples[j] = (float)distribution.Sample();
samples[j] = (float) distribution.Sample();
}
// Set the column
matrix.SetColumn(i, samples);
}
@ -676,9 +676,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
for (var i = 0; i < orthogonalMatrix.ColumnCount; i++)
{
result.Add(orthogonalMatrix.Column(i));
// Normalize the result vector
result[i].Multiply(1 / result[i].L2Norm(), result[i]);
result[i].Multiply(1/result[i].L2Norm(), result[i]);
}
return result;
@ -690,7 +690,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="arraySize">Number of vectors</param>
/// <param name="vectorSize">Size of each vector</param>
/// <returns>Array of random vectors</returns>
private static Vector<float>[] CreateVectorArray(int arraySize, int vectorSize)
static Vector<float>[] CreateVectorArray(int arraySize, int vectorSize)
{
var result = new Vector<float>[arraySize];
for (var i = 0; i < result.Length; i++)
@ -708,7 +708,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="residual">Residual <see cref="Vector"/> data.</param>
/// <param name="x">x <see cref="Vector"/> data.</param>
/// <param name="b">b <see cref="Vector"/> data.</param>
private static void CalculateTrueResidual(Matrix<float> matrix, Vector<float> residual, Vector<float> x, Vector<float> b)
static void CalculateTrueResidual(Matrix<float> matrix, Vector<float> residual, Vector<float> x, Vector<float> b)
{
// -Ax = residual
matrix.Multiply(x, residual);
@ -726,21 +726,19 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector<float> result, Vector<float> source, Vector<float> residuals)
bool ShouldContinue(int iterationNumber, Vector<float> result, Vector<float> source, Vector<float> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -69,7 +69,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <summary>
/// The iterative process controller.
/// </summary>
IIterator<float> _iterator;
Iterator<float> _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
@ -80,7 +80,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public TFQMR()
@ -96,18 +96,18 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// When using this constructor the solver will use a default preconditioner.
/// </para>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// the iterative procedure by calling the <see cref="Iterator{T}.Status"/> property.
/// </item>
/// </list>
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IIterator<float> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(Iterator<float> iterator)
: this(null, iterator)
{
}
@ -116,7 +116,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// Initializes a new instance of the <see cref="TFQMR"/> class.
/// </summary>
/// <remarks>
/// When using this constructor the solver will use the <see cref="IIterator{T}"/> with
/// When using this constructor the solver will use the <see cref="Iterator{T}"/> with
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner{T}"/> that will be used to precondition the matrix equation.</param>
@ -130,19 +130,19 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// </summary>
/// <remarks>
/// <para>
/// The main advantages of using a user defined <see cref="IIterator{T}"/> are:
/// 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="IIterator{T}.Status"/> property.
/// 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>
/// <param name="iterator">The <see cref="IIterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IPreConditioner<float> preconditioner, IIterator<float> iterator)
/// <param name="iterator">The <see cref="Iterator{T}"/> that will be used to monitor the iterative process.</param>
public TFQMR(IPreConditioner<float> preconditioner, Iterator<float> iterator)
{
_iterator = iterator;
_preconditioner = preconditioner;
@ -158,10 +158,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
}
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
public void SetIterator(IIterator<float> iterator)
public void SetIterator(Iterator<float> iterator)
{
_iterator = iterator;
}
@ -312,7 +312,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
if (sigma.AlmostEqual(0, 1))
{
// FAIL HERE
_iterator.IterationCancelled();
_iterator.Cancel();
break;
}
@ -385,7 +385,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
if (rho.AlmostEqual(0, 1))
{
// FAIL HERE
_iterator.IterationCancelled();
_iterator.Cancel();
break;
}
@ -447,19 +447,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
bool ShouldContinue(int iterationNumber, Vector<float> result, Vector<float> source, Vector<float> residuals)
{
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
if (_hasBeenStopped)
{
_iterator.IterationCancelled();
_iterator.Cancel();
return true;
}
_iterator.DetermineStatus(iterationNumber, result, source, residuals);
var status = _iterator.Status;
// We stop if either:
// - the user has stopped the calculation
// - the calculation needs to be stopped from a numerical point of view (divergence, convergence etc.)
return (!status.TerminatesCalculation) && (!_hasBeenStopped);
return !_iterator.DetermineStatus(iterationNumber, result, source, residuals).TerminatesCalculation;
}
/// <summary>

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

@ -47,10 +47,10 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
void StopSolve();
/// <summary>
/// Sets the <see cref="IIterator{T}"/> that will be used to track the iterative process.
/// Sets the <see cref="Iterator{T}"/> that will be used to track the iterative process.
/// </summary>
/// <param name="iterator">The iterator.</param>
void SetIterator(IIterator<T> iterator);
void SetIterator(Iterator<T> iterator);
/// <summary>
/// Gets the status of the iteration once the calculation is finished.

77
src/Numerics/LinearAlgebra/Solvers/IIterator.cs

@ -1,77 +0,0 @@
// <copyright file="IIterator.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;
namespace MathNet.Numerics.LinearAlgebra.Solvers
{
/// <summary>
/// Defines the base interface for iterators that help control an iterative calculation.
/// </summary>
public interface IIterator<T> where T : struct, IEquatable<T>, IFormattable
{
/// <summary>
/// Indicates to the iterator that the iterative process has been cancelled.
/// </summary>
/// <remarks>Does not reset the stop-criteria.</remarks>
void IterationCancelled();
/// <summary>
/// Determines the status of the iterative calculation based on the stop criteria stored
/// by the current <see cref="IIterator{T}"/>. Status is set to <c>Status</c> field of current object.
/// </summary>
/// <param name="iterationNumber">The number of iterations that have passed so far.</param>
/// <param name="solutionVector">The vector containing the current solution values.</param>
/// <param name="sourceVector">The right hand side vector.</param>
/// <param name="residualVector">The vector containing the current residual vectors.</param>
/// <remarks>
/// The individual iterators may internally track the progress of the calculation based
/// on the invocation of this method. Therefore this method should only be called if the
/// calculation has moved forwards at least one step.
/// </remarks>
void DetermineStatus(int iterationNumber, Vector<T> solutionVector, Vector<T> sourceVector, Vector<T> residualVector);
/// <summary>
/// Gets the current calculation status.
/// </summary>
/// <remarks><see langword="null" /> is not a legal value. Status should be set in <see cref="DetermineStatus"/> implementation.</remarks>.
ICalculationStatus Status { get; }
/// <summary>
/// Resets the <see cref="IIterator{T}"/> to the pre-calculation state.
/// </summary>
/// <remarks>
/// Note to implementers: Invoking this method should not clear the user defined
/// property values, only the state that is used to track the progress of the
/// calculation.
/// </remarks>
void ResetToPrecalculationState();
}
}

131
src/Numerics/LinearAlgebra/Solvers/Iterator.cs

@ -39,34 +39,29 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
/// <summary>
/// An iterator that is used to check if an iterative calculation should continue or stop.
/// </summary>
public sealed class Iterator<T> : IIterator<T> where T : struct, IEquatable<T>, IFormattable
public sealed class Iterator<T> where T : struct, IEquatable<T>, IFormattable
{
/// <summary>
/// The default status for the iterator.
/// </summary>
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary>
/// The collection that holds all the stop criteria and the flag indicating if they should be added
/// to the child iterators.
/// </summary>
readonly List<IIterationStopCriterium<T>> _stopCriterias = new List<IIterationStopCriterium<T>>();
readonly List<IIterationStopCriterium<T>> _stopCriteria;
/// <summary>
/// The status of the iterator.
/// </summary>
ICalculationStatus _status = DefaultStatus;
ICalculationStatus _status = new CalculationIndetermined();
/// <summary>
/// Indicates if the iteration was canceled.
/// </summary>
bool _wasIterationCancelled;
/// <summary>
/// Initializes a new instance of the <see cref="Iterator{T}"/> class.
/// Initializes a new instance of the <see cref="Iterator{T}"/> class with the specified stop criteria.
/// </summary>
public Iterator() : this(null)
/// <param name="stopCriteria">
/// The specified stop criteria. Only one stop criterium of each type can be passed in. None
/// of the stop criteria will be passed on to child iterators.
/// </param>
public Iterator(params IIterationStopCriterium<T>[] stopCriteria)
{
_stopCriteria = new List<IIterationStopCriterium<T>>(stopCriteria);
}
/// <summary>
@ -76,83 +71,38 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
/// The specified stop criteria. Only one stop criterium of each type can be passed in. None
/// of the stop criteria will be passed on to child iterators.
/// </param>
/// <exception cref="ArgumentException">Thrown if <paramref name="stopCriteria"/> contains multiple stop criteria of the same type.</exception>
public Iterator(IEnumerable<IIterationStopCriterium<T>> stopCriteria)
{
// Add the stop criteria
if (stopCriteria == null)
{
return;
}
foreach (var stopCriterium in stopCriteria.Where(stopCriterium => stopCriterium != null))
{
Add(stopCriterium);
}
}
/// <summary>
/// Adds an <see cref="IIterationStopCriterium{T}"/> to the internal collection of stop-criteria. Only a
/// single stop criterium of each type can be stored.
/// </summary>
/// <param name="stopCriterium">The stop criterium to add.</param>
public void Add(IIterationStopCriterium<T> stopCriterium)
{
_stopCriterias.Add(stopCriterium);
_stopCriteria = new List<IIterationStopCriterium<T>>(stopCriteria);
}
/// <summary>
/// Removes the <see cref="IIterationStopCriterium{T}"/> from the internal collection.
/// </summary>
/// <param name="stopCriterium">The stop criterium that must be removed.</param>
public void Remove(IIterationStopCriterium<T> stopCriterium)
{
_stopCriterias.Remove(stopCriterium);
}
/// <summary>
/// Indicates if the specific stop criterium is stored by the <see cref="IIterator{T}"/>.
/// </summary>
/// <param name="stopCriterium">The stop criterium.</param>
/// <returns><c>true</c> if the <see cref="IIterator{T}"/> contains the stop criterium; otherwise <c>false</c>.</returns>
public bool Contains(IIterationStopCriterium<T> stopCriterium)
{
return _stopCriterias.Contains(stopCriterium);
}
/// <summary>
/// Gets the number of stored stop criteria.
/// Gets the current calculation status.
/// </summary>
/// <remarks>Used for testing only.</remarks>
internal int NumberOfCriteria
public ICalculationStatus Status
{
get { return _stopCriterias.Count; }
get { return _status; }
}
/// <summary>
/// Gets an <c>IEnumerator</c> that enumerates over all the stored stop criteria.
/// True if the calculation has converged to the desired convergence levels.
/// </summary>
/// <remarks>Used for testing only.</remarks>
internal IEnumerable<IIterationStopCriterium<T>> StoredStopCriteria
public bool HasConverged
{
get { return _stopCriterias; }
get { return _status is CalculationConverged; }
}
/// <summary>
/// Indicates to the iterator that the iterative process has been cancelled.
/// True if the calculation has been stopped due to reaching the stopping limits but that convergence was not achieved.
/// </summary>
/// <remarks>
/// Does not reset the stop-criteria.
/// </remarks>
public void IterationCancelled()
public bool HasStoppedWithoutConvergence
{
_wasIterationCancelled = true;
_status = new CalculationCancelled();
get { return _status is CalculationStoppedWithoutConvergence; }
}
/// <summary>
/// Determines the status of the iterative calculation based on the stop criteria stored
/// by the current <see cref="IIterator{T}"/>. Result is set into <c>Status</c> field.
/// by the current <see cref="Iterator{T}"/>. Result is set into <c>Status</c> field.
/// </summary>
/// <param name="iterationNumber">The number of iterations that have passed so far.</param>
/// <param name="solutionVector">The vector containing the current solution values.</param>
@ -163,9 +113,9 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
/// on the invocation of this method. Therefore this method should only be called if the
/// calculation has moved forwards at least one step.
/// </remarks>
public void DetermineStatus(int iterationNumber, Vector<T> solutionVector, Vector<T> sourceVector, Vector<T> residualVector)
public ICalculationStatus DetermineStatus(int iterationNumber, Vector<T> solutionVector, Vector<T> sourceVector, Vector<T> residualVector)
{
if (_stopCriterias.Count == 0)
if (_stopCriteria.Count == 0)
{
throw new ArgumentException(Resources.StopCriteriumMissing);
}
@ -176,12 +126,12 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
}
// While we're cancelled we don't call on the stop-criteria.
if (_wasIterationCancelled)
if (_status is CalculationCancelled)
{
return;
return _status;
}
foreach (var stopCriterium in _stopCriterias)
foreach (var stopCriterium in _stopCriteria)
{
var status = stopCriterium.DetermineStatus(iterationNumber, solutionVector, sourceVector, residualVector);
@ -196,7 +146,7 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
}
_status = status;
return;
return _status;
}
// Got all the way through
@ -205,29 +155,31 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
{
_status = new CalculationRunning();
}
return _status;
}
/// <summary>
/// Gets the current calculation status.
/// Indicates to the iterator that the iterative process has been cancelled.
/// </summary>
public ICalculationStatus Status
/// <remarks>
/// Does not reset the stop-criteria.
/// </remarks>
public void Cancel()
{
get { return _status; }
_status = new CalculationCancelled();
}
/// <summary>
/// Resets the <see cref="IIterator{T}"/> to the pre-calculation state.
/// Resets the <see cref="Iterator{T}"/> to the pre-calculation state.
/// </summary>
public void ResetToPrecalculationState()
public void Reset()
{
// Indicate that we're no longer cancelled.
_wasIterationCancelled = false;
// Reset the status.
_status = DefaultStatus;
_status = new CalculationIndetermined();
// Reset the stop-criteria
foreach (var stopCriterium in _stopCriterias)
foreach (var stopCriterium in _stopCriteria)
{
stopCriterium.ResetToPrecalculationState();
}
@ -237,10 +189,9 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers
/// Creates a deep clone of the current iterator.
/// </summary>
/// <returns>The deep clone of the current iterator.</returns>
public IIterator<T> Clone()
public Iterator<T> Clone()
{
var stopCriteria = _stopCriterias.Select(stopCriterium => stopCriterium.Clone()).ToList();
return new Iterator<T>(stopCriteria);
return new Iterator<T>(_stopCriteria.Select(sc => sc.Clone()));
}
}
}

1
src/Numerics/Numerics.csproj

@ -218,7 +218,6 @@
<Compile Include="LinearAlgebra\Double\Matrix.cs" />
<Compile Include="LinearAlgebra\Solvers\IIterativeSolver.cs" />
<Compile Include="LinearAlgebra\Solvers\IIterativeSolverSetup.cs" />
<Compile Include="LinearAlgebra\Solvers\IIterator.cs" />
<Compile Include="LinearAlgebra\Solvers\IPreConditioner.cs" />
<Compile Include="LinearAlgebra\Solvers\IIterationStopCriterium.cs" />
<Compile Include="LinearAlgebra\Double\SparseMatrix.cs" />

7
src/UnitTests/LinearAlgebraTests/Complex/Solvers/Iterative/BiCgStabTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Complex;
using MathNet.Numerics.LinearAlgebra.Complex.Solvers;
using MathNet.Numerics.LinearAlgebra.Complex.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterative
@ -115,7 +114,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -160,7 +159,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -238,7 +237,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)

7
src/UnitTests/LinearAlgebraTests/Complex/Solvers/Iterative/GpBiCgTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Complex;
using MathNet.Numerics.LinearAlgebra.Complex.Solvers;
using MathNet.Numerics.LinearAlgebra.Complex.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterative
@ -115,7 +114,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -161,7 +160,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -240,7 +239,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)

7
src/UnitTests/LinearAlgebraTests/Complex/Solvers/Iterative/MlkBiCgStabTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Complex;
using MathNet.Numerics.LinearAlgebra.Complex.Solvers;
using MathNet.Numerics.LinearAlgebra.Complex.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterative
@ -116,7 +115,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -161,7 +160,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -239,7 +238,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)

7
src/UnitTests/LinearAlgebraTests/Complex/Solvers/Iterative/TFQMRTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Complex;
using MathNet.Numerics.LinearAlgebra.Complex.Solvers;
using MathNet.Numerics.LinearAlgebra.Complex.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterative
@ -116,7 +115,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -161,7 +160,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -239,7 +238,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers.Iterativ
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)

163
src/UnitTests/LinearAlgebraTests/Complex/Solvers/IteratorTest.cs

@ -46,135 +46,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers
[TestFixture]
public class IteratorTest
{
/// <summary>
/// Can create with <c>null</c> collection.
/// </summary>
[Test]
public void CreateWithNullCollection()
{
var iterator = new Iterator<Complex>(null);
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with empty collection.
/// </summary>
[Test]
public void CreateWithEmptyCollection()
{
var iterator = new Iterator<Complex>(new IIterationStopCriterium<Complex>[] { });
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with collection with <c>nulls</c>.
/// </summary>
[Test]
public void CreateWithCollectionWithNulls()
{
var iterator = new Iterator<Complex>(new IIterationStopCriterium<Complex>[] { null, null });
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with collection.
/// </summary>
[Test]
public void CreateWithCollection()
{
var criteria = new List<IIterationStopCriterium<Complex>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<Complex>(criteria);
Assert.IsNotNull(iterator, "Should have an iterator");
// Check that we have all the criteria
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in iterator.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => ReferenceEquals(c, criterium)), "Criterium missing");
}
}
/// <summary>
/// Can add criterium.
/// </summary>
[Test]
public void Add()
{
var criteria = new List<IIterationStopCriterium<Complex>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<Complex>();
Assert.AreEqual(0, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in criteria)
{
iterator.Add(criterium);
Assert.IsTrue(iterator.Contains(criterium), "Missing criterium");
}
// Check that we have all the criteria
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in iterator.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => ReferenceEquals(c, criterium)), "Criterium missing");
}
}
/// <summary>
/// Can remove with non-existing stop criterium.
/// </summary>
[Test]
public void RemoveWithNonExistingStopCriterium()
{
var criteria = new List<IIterationStopCriterium<Complex>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex>(),
};
var iterator = new Iterator<Complex>(criteria);
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
iterator.Remove(new ResidualStopCriterium());
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
}
/// <summary>
/// Can remove.
/// </summary>
[Test]
public void Remove()
{
var criteria = new List<IIterationStopCriterium<Complex>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<Complex>(criteria);
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in criteria)
{
iterator.Remove(criterium);
Assert.IsFalse(iterator.Contains(criterium), "Did not remove the criterium");
}
}
/// <summary>
/// Determine status without stop criteria throws <c>ArgumentException</c>.
/// </summary>
@ -332,43 +203,11 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Solvers
DenseVector.Create(3, i => 4));
Assert.IsInstanceOf(typeof (CalculationRunning), iterator.Status, "Incorrect status");
iterator.ResetToPrecalculationState();
iterator.Reset();
Assert.IsInstanceOf(typeof (CalculationIndetermined), iterator.Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[0].Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[1].Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[2].Status, "Incorrect status");
}
/// <summary>
/// Can clone.
/// </summary>
[Test]
public void Clone()
{
var criteria = new List<IIterationStopCriterium<Complex>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<Complex>(criteria);
var clonedIterator = iterator.Clone();
Assert.IsInstanceOf(typeof(Iterator<Complex>), clonedIterator, "Incorrect type");
var clone = clonedIterator as Iterator<Complex>;
Assert.IsNotNull(clone);
// ReSharper disable PossibleNullReferenceException
Assert.AreEqual(iterator.NumberOfCriteria, clone.NumberOfCriteria, "Incorrect criterium count");
// ReSharper restore PossibleNullReferenceException
foreach (var criterium in clone.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => c.GetType() == criterium.GetType()), "Criterium missing");
}
}
}
}

13
src/UnitTests/LinearAlgebraTests/Complex32/Solvers/Iterative/BiCgStabTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Complex32;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterative
@ -115,7 +114,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -160,7 +159,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -238,7 +237,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -266,13 +265,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var monitor = new Iterator<Complex32>(new IIterationStopCriterium<Complex32>[]
{
new IterationCountStopCriterium<Complex32>(1000),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration)),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration))
});
var solver = new BiCgStab(monitor);
var resultx = solver.Solve(matrixA, vectorb);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;
@ -314,7 +313,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var solver = new BiCgStab(monitor);
var matrixX = solver.Solve(matrixA, matrixB);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;

9
src/UnitTests/LinearAlgebraTests/Complex32/Solvers/Iterative/GpBiCgTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Complex32;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterative
@ -115,7 +114,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -161,7 +160,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -240,7 +239,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -270,7 +269,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var resultx = solver.Solve(matrixA, vectorb);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;

13
src/UnitTests/LinearAlgebraTests/Complex32/Solvers/Iterative/MlkBiCgStabTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Complex32;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterative
@ -116,7 +115,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -161,7 +160,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -239,7 +238,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -263,13 +262,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var monitor = new Iterator<Complex32>(new IIterationStopCriterium<Complex32>[]
{
new IterationCountStopCriterium<Complex32>(1000),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration)),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration))
});
var solver = new MlkBiCgStab(monitor);
var resultx = solver.Solve(matrixA, vectorb);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;
@ -311,7 +310,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var solver = new MlkBiCgStab(monitor);
var matrixX = solver.Solve(matrixA, matrixB);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;

13
src/UnitTests/LinearAlgebraTests/Complex32/Solvers/Iterative/TFQMRTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Complex32;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers;
using MathNet.Numerics.LinearAlgebra.Complex32.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterative
@ -116,7 +115,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -161,7 +160,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -239,7 +238,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -263,13 +262,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var monitor = new Iterator<Complex32>(new IIterationStopCriterium<Complex32>[]
{
new IterationCountStopCriterium<Complex32>(1000),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration)),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration))
});
var solver = new TFQMR(monitor);
var resultx = solver.Solve(matrixA, vectorb);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;
@ -311,7 +310,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers.Iterat
var solver = new TFQMR(monitor);
var matrixX = solver.Solve(matrixA, matrixB);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;

163
src/UnitTests/LinearAlgebraTests/Complex32/Solvers/IteratorTest.cs

@ -46,135 +46,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers
[TestFixture]
public class IteratorTest
{
/// <summary>
/// Can create with <c>null</c> collection.
/// </summary>
[Test]
public void CreateWithNullCollection()
{
var iterator = new Iterator<Complex32>(null);
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with empty collection.
/// </summary>
[Test]
public void CreateWithEmptyCollection()
{
var iterator = new Iterator<Complex32>(new IIterationStopCriterium<Complex32>[] { });
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with collection with <c>nulls</c>.
/// </summary>
[Test]
public void CreateWithCollectionWithNulls()
{
var iterator = new Iterator<Complex32>(new IIterationStopCriterium<Complex32>[] { null, null });
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with collection.
/// </summary>
[Test]
public void CreateWithCollection()
{
var criteria = new List<IIterationStopCriterium<Complex32>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex32>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<Complex32>(criteria);
Assert.IsNotNull(iterator, "Should have an iterator");
// Check that we have all the criteria
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in iterator.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => ReferenceEquals(c, criterium)), "Criterium missing");
}
}
/// <summary>
/// Can add criterium.
/// </summary>
[Test]
public void Add()
{
var criteria = new List<IIterationStopCriterium<Complex32>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex32>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<Complex32>();
Assert.AreEqual(0, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in criteria)
{
iterator.Add(criterium);
Assert.IsTrue(iterator.Contains(criterium), "Missing criterium");
}
// Check that we have all the criteria
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in iterator.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => ReferenceEquals(c, criterium)), "Criterium missing");
}
}
/// <summary>
/// Can remove with non-existing stop criterium.
/// </summary>
[Test]
public void RemoveWithNonExistingStopCriterium()
{
var criteria = new List<IIterationStopCriterium<Complex32>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex32>(),
};
var iterator = new Iterator<Complex32>(criteria);
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
iterator.Remove(new ResidualStopCriterium());
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
}
/// <summary>
/// Can remove.
/// </summary>
[Test]
public void Remove()
{
var criteria = new List<IIterationStopCriterium<Complex32>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex32>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<Complex32>(criteria);
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in criteria)
{
iterator.Remove(criterium);
Assert.IsFalse(iterator.Contains(criterium), "Did not remove the criterium");
}
}
/// <summary>
/// Determine status without stop criteria throws <c>ArgumentException</c>.
/// </summary>
@ -332,43 +203,11 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Solvers
DenseVector.Create(3, i => 4));
Assert.IsInstanceOf(typeof (CalculationRunning), iterator.Status, "Incorrect status");
iterator.ResetToPrecalculationState();
iterator.Reset();
Assert.IsInstanceOf(typeof (CalculationIndetermined), iterator.Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[0].Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[1].Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[2].Status, "Incorrect status");
}
/// <summary>
/// Can clone.
/// </summary>
[Test]
public void Clone()
{
var criteria = new List<IIterationStopCriterium<Complex32>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<Complex32>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<Complex32>(criteria);
var clonedIterator = iterator.Clone();
Assert.IsInstanceOf(typeof(Iterator<Complex32>), clonedIterator, "Incorrect type");
var clone = clonedIterator as Iterator<Complex32>;
Assert.IsNotNull(clone);
// ReSharper disable PossibleNullReferenceException
Assert.AreEqual(iterator.NumberOfCriteria, clone.NumberOfCriteria, "Incorrect criterium count");
// ReSharper restore PossibleNullReferenceException
foreach (var criterium in clone.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => c.GetType() == criterium.GetType()), "Criterium missing");
}
}
}
}

7
src/UnitTests/LinearAlgebraTests/Double/Solvers/Iterative/BiCgStabTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Double.Solvers;
using MathNet.Numerics.LinearAlgebra.Double.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
@ -113,7 +112,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -158,7 +157,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -236,7 +235,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)

7
src/UnitTests/LinearAlgebraTests/Double/Solvers/Iterative/GpBiCgTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Double.Solvers;
using MathNet.Numerics.LinearAlgebra.Double.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
@ -113,7 +112,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -159,7 +158,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -238,7 +237,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)

7
src/UnitTests/LinearAlgebraTests/Double/Solvers/Iterative/MlkBiCgStabTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Double.Solvers;
using MathNet.Numerics.LinearAlgebra.Double.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
@ -114,7 +113,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -159,7 +158,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -237,7 +236,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)

7
src/UnitTests/LinearAlgebraTests/Double/Solvers/Iterative/TFQMRTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Double.Solvers;
using MathNet.Numerics.LinearAlgebra.Double.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
@ -114,7 +113,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -159,7 +158,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -237,7 +236,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)

163
src/UnitTests/LinearAlgebraTests/Double/Solvers/IteratorTest.cs

@ -44,135 +44,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers
[TestFixture]
public class IteratorTest
{
/// <summary>
/// Can create with <c>null</c> collection.
/// </summary>
[Test]
public void CreateWithNullCollection()
{
var iterator = new Iterator<double>(null);
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with empty collection.
/// </summary>
[Test]
public void CreateWithEmptyCollection()
{
var iterator = new Iterator<double>(new IIterationStopCriterium<double>[] { });
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with collection with <c>nulls</c>.
/// </summary>
[Test]
public void CreateWithCollectionWithNulls()
{
var iterator = new Iterator<double>(new IIterationStopCriterium<double>[] { null, null });
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with collection.
/// </summary>
[Test]
public void CreateWithCollection()
{
var criteria = new List<IIterationStopCriterium<double>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<double>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<double>(criteria);
Assert.IsNotNull(iterator, "Should have an iterator");
// Check that we have all the criteria
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in iterator.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => ReferenceEquals(c, criterium)), "Criterium missing");
}
}
/// <summary>
/// Can add criterium.
/// </summary>
[Test]
public void Add()
{
var criteria = new List<IIterationStopCriterium<double>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<double>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<double>();
Assert.AreEqual(0, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in criteria)
{
iterator.Add(criterium);
Assert.IsTrue(iterator.Contains(criterium), "Missing criterium");
}
// Check that we have all the criteria
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in iterator.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => ReferenceEquals(c, criterium)), "Criterium missing");
}
}
/// <summary>
/// Can remove with non-existing stop criterium.
/// </summary>
[Test]
public void RemoveWithNonExistingStopCriterium()
{
var criteria = new List<IIterationStopCriterium<double>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<double>(),
};
var iterator = new Iterator<double>(criteria);
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
iterator.Remove(new ResidualStopCriterium());
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
}
/// <summary>
/// Can remove.
/// </summary>
[Test]
public void Remove()
{
var criteria = new List<IIterationStopCriterium<double>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<double>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<double>(criteria);
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in criteria)
{
iterator.Remove(criterium);
Assert.IsFalse(iterator.Contains(criterium), "Did not remove the criterium");
}
}
/// <summary>
/// Determine status without stop criteria throws <c>ArgumentException</c>.
/// </summary>
@ -330,43 +201,11 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Solvers
DenseVector.Create(3, i => 4));
Assert.IsInstanceOf(typeof (CalculationRunning), iterator.Status, "Incorrect status");
iterator.ResetToPrecalculationState();
iterator.Reset();
Assert.IsInstanceOf(typeof (CalculationIndetermined), iterator.Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[0].Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[1].Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[2].Status, "Incorrect status");
}
/// <summary>
/// Can clone.
/// </summary>
[Test]
public void Clone()
{
var criteria = new List<IIterationStopCriterium<double>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<double>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<double>(criteria);
var clonedIterator = iterator.Clone();
Assert.IsInstanceOf(typeof(Iterator<double>), clonedIterator, "Incorrect type");
var clone = clonedIterator as Iterator<double>;
Assert.IsNotNull(clone);
// ReSharper disable PossibleNullReferenceException
Assert.AreEqual(iterator.NumberOfCriteria, clone.NumberOfCriteria, "Incorrect criterium count");
// ReSharper restore PossibleNullReferenceException
foreach (var criterium in clone.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => c.GetType().Equals(criterium.GetType())), "Criterium missing");
}
}
}
}

13
src/UnitTests/LinearAlgebraTests/Single/Solvers/Iterative/BiCgStabTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Single;
using MathNet.Numerics.LinearAlgebra.Single.Solvers;
using MathNet.Numerics.LinearAlgebra.Single.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
@ -113,7 +112,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -158,7 +157,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -236,7 +235,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -262,12 +261,12 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var monitor = new Iterator<float>(new IIterationStopCriterium<float>[]
{
new IterationCountStopCriterium<float>(MaximumIterations),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration)),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration))
});
var solver = new BiCgStab(monitor);
var resultx = solver.Solve(matrixA, vectorb);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;
@ -308,7 +307,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var solver = new BiCgStab(monitor);
var matrixX = solver.Solve(matrixA, matrixB);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;

13
src/UnitTests/LinearAlgebraTests/Single/Solvers/Iterative/GpBiCgTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Single;
using MathNet.Numerics.LinearAlgebra.Single.Solvers;
using MathNet.Numerics.LinearAlgebra.Single.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
@ -113,7 +112,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -159,7 +158,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -238,7 +237,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -264,12 +263,12 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var monitor = new Iterator<float>(new IIterationStopCriterium<float>[]
{
new IterationCountStopCriterium<float>(MaximumIterations),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration)),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration))
});
var solver = new GpBiCg(monitor);
var resultx = solver.Solve(matrixA, vectorb);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;
@ -310,7 +309,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var solver = new GpBiCg(monitor);
var matrixX = solver.Solve(matrixA, matrixB);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;

13
src/UnitTests/LinearAlgebraTests/Single/Solvers/Iterative/MlkBiCgStabTest.cs

@ -34,7 +34,6 @@ using MathNet.Numerics.LinearAlgebra.Single;
using MathNet.Numerics.LinearAlgebra.Single.Solvers;
using MathNet.Numerics.LinearAlgebra.Single.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
@ -115,7 +114,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -160,7 +159,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -242,7 +241,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
continue;
}
if (!(monitor.Status is CalculationConverged))
if (!(monitor.HasConverged))
{
continue;
}
@ -281,12 +280,12 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var monitor = new Iterator<float>(new IIterationStopCriterium<float>[]
{
new IterationCountStopCriterium<float>(MaximumIterations),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration)),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration))
});
var solver = new MlkBiCgStab(monitor);
var resultx = solver.Solve(matrixA, vectorb);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;
@ -329,7 +328,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var solver = new MlkBiCgStab(monitor);
var matrixX = solver.Solve(matrixA, matrixB);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;

13
src/UnitTests/LinearAlgebraTests/Single/Solvers/Iterative/TFQMRTest.cs

@ -33,7 +33,6 @@ using MathNet.Numerics.LinearAlgebra.Single;
using MathNet.Numerics.LinearAlgebra.Single.Solvers;
using MathNet.Numerics.LinearAlgebra.Single.Solvers.StopCriterium;
using MathNet.Numerics.LinearAlgebra.Solvers;
using MathNet.Numerics.LinearAlgebra.Solvers.Status;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
@ -114,7 +113,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -159,7 +158,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -237,7 +236,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var z = matrix.Multiply(x);
// Check that the solution converged
Assert.IsTrue(monitor.Status is CalculationConverged, "#04");
Assert.IsTrue(monitor.HasConverged, "#04");
// Now compare the vectors
for (var i = 0; i < y.Count; i++)
@ -263,12 +262,12 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var monitor = new Iterator<float>(new IIterationStopCriterium<float>[]
{
new IterationCountStopCriterium<float>(MaximumIterations),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration)),
new ResidualStopCriterium((float) Math.Pow(1.0/10.0, iteration))
});
var solver = new TFQMR(monitor);
var resultx = solver.Solve(matrixA, vectorb);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;
@ -309,7 +308,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers.Iterative
var solver = new TFQMR(monitor);
var matrixX = solver.Solve(matrixA, matrixB);
if (!(monitor.Status is CalculationConverged))
if (!monitor.HasConverged)
{
// Solution was not found, try again downgrading convergence boundary
continue;

163
src/UnitTests/LinearAlgebraTests/Single/Solvers/IteratorTest.cs

@ -44,135 +44,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers
[TestFixture]
public class IteratorTest
{
/// <summary>
/// Can create with <c>null</c> collection.
/// </summary>
[Test]
public void CreateWithNullCollection()
{
var iterator = new Iterator<float>(null);
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with empty collection.
/// </summary>
[Test]
public void CreateWithEmptyCollection()
{
var iterator = new Iterator<float>(new IIterationStopCriterium<float>[] { });
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with collection with <c>nulls</c>.
/// </summary>
[Test]
public void CreateWithCollectionWithNulls()
{
var iterator = new Iterator<float>(new IIterationStopCriterium<float>[] { null, null });
Assert.IsNotNull(iterator, "Should have an iterator");
Assert.AreEqual(0, iterator.NumberOfCriteria, "There shouldn't be any criteria");
}
/// <summary>
/// Can create with collection.
/// </summary>
[Test]
public void CreateWithCollection()
{
var criteria = new List<IIterationStopCriterium<float>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<float>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<float>(criteria);
Assert.IsNotNull(iterator, "Should have an iterator");
// Check that we have all the criteria
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in iterator.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => ReferenceEquals(c, criterium)), "Criterium missing");
}
}
/// <summary>
/// Can add criterium.
/// </summary>
[Test]
public void Add()
{
var criteria = new List<IIterationStopCriterium<float>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<float>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<float>();
Assert.AreEqual(0, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in criteria)
{
iterator.Add(criterium);
Assert.IsTrue(iterator.Contains(criterium), "Missing criterium");
}
// Check that we have all the criteria
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in iterator.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => ReferenceEquals(c, criterium)), "Criterium missing");
}
}
/// <summary>
/// Can remove with non-existing stop criterium.
/// </summary>
[Test]
public void RemoveWithNonExistingStopCriterium()
{
var criteria = new List<IIterationStopCriterium<float>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<float>(),
};
var iterator = new Iterator<float>(criteria);
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
iterator.Remove(new ResidualStopCriterium());
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
}
/// <summary>
/// Can remove.
/// </summary>
[Test]
public void Remove()
{
var criteria = new List<IIterationStopCriterium<float>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<float>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<float>(criteria);
Assert.AreEqual(criteria.Count, iterator.NumberOfCriteria, "Incorrect criterium count");
foreach (var criterium in criteria)
{
iterator.Remove(criterium);
Assert.IsFalse(iterator.Contains(criterium), "Did not remove the criterium");
}
}
/// <summary>
/// Determine status without stop criteria throws <c>ArgumentException</c>.
/// </summary>
@ -330,43 +201,11 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Solvers
DenseVector.Create(3, i => 4));
Assert.IsInstanceOf(typeof (CalculationRunning), iterator.Status, "Incorrect status");
iterator.ResetToPrecalculationState();
iterator.Reset();
Assert.IsInstanceOf(typeof (CalculationIndetermined), iterator.Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[0].Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[1].Status, "Incorrect status");
Assert.IsInstanceOf(typeof (CalculationIndetermined), criteria[2].Status, "Incorrect status");
}
/// <summary>
/// Can clone.
/// </summary>
[Test]
public void Clone()
{
var criteria = new List<IIterationStopCriterium<float>>
{
new FailureStopCriterium(),
new DivergenceStopCriterium(),
new IterationCountStopCriterium<float>(),
new ResidualStopCriterium()
};
var iterator = new Iterator<float>(criteria);
var clonedIterator = iterator.Clone();
Assert.IsInstanceOf(typeof(Iterator<float>), clonedIterator, "Incorrect type");
var clone = clonedIterator as Iterator<float>;
Assert.IsNotNull(clone);
// ReSharper disable PossibleNullReferenceException
Assert.AreEqual(iterator.NumberOfCriteria, clone.NumberOfCriteria, "Incorrect criterium count");
// ReSharper restore PossibleNullReferenceException
foreach (var criterium in clone.StoredStopCriteria)
{
Assert.IsTrue(criteria.Exists(c => c.GetType() == criterium.GetType()), "Criterium missing");
}
}
}
}

Loading…
Cancel
Save