Browse Source

LA: Complex iterative solvers must use conjugated dot-product #128

v2
Christoph Ruegg 13 years ago
parent
commit
ec6527a27d
  1. 49
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/BiCgStab.cs
  2. 15
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/GpBiCg.cs
  3. 89
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/MlkBiCgStab.cs
  4. 13
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/TFQMR.cs
  5. 48
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/BiCgStab.cs
  6. 14
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/GpBiCg.cs
  7. 90
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/MlkBiCgStab.cs
  8. 12
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/TFQMR.cs
  9. 8
      src/Numerics/LinearAlgebra/Double/Solvers/Iterative/TFQMR.cs
  10. 2
      src/Numerics/LinearAlgebra/Generic/Vector.Arithmetic.cs
  11. 6
      src/Numerics/LinearAlgebra/Single/Solvers/Iterative/TFQMR.cs

49
src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/BiCgStab.cs

@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex; using Complex = Numerics.Complex;
#else #else
using Complex = System.Numerics.Complex; using Complex = System.Numerics.Complex;
#endif #endif
/// <summary> /// <summary>
@ -76,24 +77,24 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no /// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator. /// iterator.
/// </summary> /// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined(); static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary> /// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default /// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used. /// pre-conditioner will be used.
/// </summary> /// </summary>
private IPreConditioner _preconditioner; IPreConditioner _preconditioner;
/// <summary> /// <summary>
/// The iterative process controller. /// The iterative process controller.
/// </summary> /// </summary>
private IIterator _iterator; IIterator _iterator;
/// <summary> /// <summary>
/// Indicates if the user has stopped the solver. /// Indicates if the user has stopped the solver.
/// </summary> /// </summary>
private bool _hasBeenStopped; bool _hasBeenStopped;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class. /// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary> /// </summary>
@ -101,7 +102,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with /// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner. /// the standard settings and a default preconditioner.
/// </remarks> /// </remarks>
public BiCgStab() : this(null, null) public BiCgStab()
: this(null, null)
{ {
} }
@ -124,7 +126,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process. </param> /// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IIterator iterator) : this(null, iterator) public BiCgStab(IIterator iterator)
: this(null, iterator)
{ {
} }
@ -136,7 +139,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// the standard settings. /// the standard settings.
/// </remarks> /// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param> /// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param>
public BiCgStab(IPreConditioner preconditioner) : this(preconditioner, null) public BiCgStab(IPreConditioner preconditioner)
: this(preconditioner, null)
{ {
} }
@ -186,10 +190,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// </summary> /// </summary>
public ICalculationStatus IterationResult public ICalculationStatus IterationResult
{ {
get get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
} }
/// <summary> /// <summary>
@ -278,9 +279,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
{ {
_preconditioner = new UnitPreconditioner(); _preconditioner = new UnitPreconditioner();
} }
_preconditioner.Initialize(matrix); _preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0 // Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector // In this case we take x_0 = vector
// This is basically a SAXPY so it could be made a lot faster // This is basically a SAXPY so it could be made a lot faster
@ -312,7 +313,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
{ {
// rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1) // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
var oldRho = currentRho; var oldRho = currentRho;
currentRho = tempResiduals.DotProduct(residuals); currentRho = tempResiduals.ConjugateDotProduct(residuals);
// if (rho_(i-1) == 0) // METHOD FAILS // if (rho_(i-1) == 0) // METHOD FAILS
// If rho is only 1 ULP from zero then we fail. // If rho is only 1 ULP from zero then we fail.
@ -325,7 +326,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
if (iterationNumber != 0) if (iterationNumber != 0)
{ {
// beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1)) // 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)) // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
nu.Multiply(-omega, temp); nu.Multiply(-omega, temp);
@ -344,12 +345,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// SOLVE Mp~ = p_i // M = preconditioner // SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash); _preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~ // nu_i = Ap~
matrix.Multiply(vecPdash, nu); matrix.Multiply(vecPdash, nu);
// alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i) // 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.ConjugateDotProduct(nu);
// s = r_(i-1) - alpha_i nu_i // s = r_(i-1) - alpha_i nu_i
nu.Multiply(-alpha, temp); nu.Multiply(-alpha, temp);
@ -393,7 +394,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(vecSdash, temp); matrix.Multiply(vecSdash, temp);
// omega_i = temp^T s / temp^T temp // omega_i = temp^T s / temp^T temp
omega = temp.DotProduct(vecS) / temp.DotProduct(temp); omega = temp.ConjugateDotProduct(vecS)/temp.ConjugateDotProduct(temp);
// x_i = x_(i-1) + alpha_i p^ + omega_i s^ // x_i = x_(i-1) + alpha_i p^ + omega_i s^
temp.Multiply(-omega, residuals); temp.Multiply(-omega, residuals);
@ -437,11 +438,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="residual">Residual values in <see cref="Vector"/>.</param> /// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param> /// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</param> /// <param name="b">Instance of the <see cref="Vector"/> b.</param>
private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b) static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
{ {
// -Ax = residual // -Ax = residual
matrix.Multiply(x, residual); matrix.Multiply(x, residual);
// Do not use residual = residual.Negate() because it creates another object // Do not use residual = residual.Negate() because it creates another object
residual.Multiply(-1, residual); residual.Multiply(-1, residual);
@ -457,7 +458,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param> /// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param> /// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns> /// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals) bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
{ {
if (_hasBeenStopped) if (_hasBeenStopped)
{ {
@ -493,7 +494,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
throw new ArgumentNullException("input"); throw new ArgumentNullException("input");
} }
var result = (Matrix)matrix.CreateMatrix(input.RowCount, input.ColumnCount); var result = (Matrix) matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result); Solve(matrix, input, result);
return result; return result;
} }
@ -529,7 +530,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
for (var column = 0; column < input.ColumnCount; column++) for (var column = 0; column < input.ColumnCount; column++)
{ {
var solution = Solve(matrix, (Vector)input.Column(column)); var solution = Solve(matrix, (Vector) input.Column(column));
foreach (var element in solution.GetIndexedEnumerator()) foreach (var element in solution.GetIndexedEnumerator())
{ {
result.At(element.Item1, column, element.Item2); result.At(element.Item1, column, element.Item2);

15
src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/GpBiCg.cs

@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex; using Complex = Numerics.Complex;
#else #else
using Complex = System.Numerics.Complex; using Complex = System.Numerics.Complex;
#endif #endif
/// <summary> /// <summary>
@ -377,7 +378,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(temp, s); matrix.Multiply(temp, s);
// alpha_k = (r*_0 * r_k) / (r*_0 * s_k) // alpha_k = (r*_0 * r_k) / (r*_0 * s_k)
var alpha = rdash.DotProduct(residuals)/rdash.DotProduct(s); var alpha = rdash.ConjugateDotProduct(residuals)/rdash.ConjugateDotProduct(s);
// y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k // y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k
s.Subtract(w, temp); s.Subtract(w, temp);
@ -399,7 +400,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// c_k = A d_k // c_k = A d_k
matrix.Multiply(temp, c); matrix.Multiply(temp, c);
var cdot = c.DotProduct(c); var cdot = c.ConjugateDotProduct(c);
// cDot can only be zero if c is a zero vector // 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 // We'll set cDot to 1 if it is zero to prevent NaN's
@ -414,7 +415,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// to do at least one at the start to initialize the // to do at least one at the start to initialize the
// system, but we'll only have to take special measures // system, but we'll only have to take special measures
// if we don't do any so ... // if we don't do any so ...
var ctdot = c.DotProduct(t); var ctdot = c.ConjugateDotProduct(t);
Complex eta; Complex eta;
Complex sigma; Complex sigma;
if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber)) if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber))
@ -427,7 +428,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
} }
else else
{ {
var ydot = y.DotProduct(y); var ydot = y.ConjugateDotProduct(y);
// yDot can only be zero if y is a zero vector // yDot can only be zero if y is a zero vector
// We'll set yDot to 1 if it is zero to prevent NaN's // We'll set yDot to 1 if it is zero to prevent NaN's
@ -438,8 +439,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
ydot = 1.0; ydot = 1.0;
} }
var ytdot = y.DotProduct(t); var ytdot = y.ConjugateDotProduct(t);
var cydot = c.DotProduct(y); var cydot = c.ConjugateDotProduct(y);
var denom = (cdot*ydot) - (cydot*cydot); var denom = (cdot*ydot) - (cydot*cydot);
@ -493,7 +494,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// beta_k = alpha_k / sigma_k * (r*_0 * r_(k+1)) / (r*_0 * r_k) // 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. // But first we check if there is a possible NaN. If so just reset beta to zero.
beta = (!sigma.Real.AlmostEqual(0, 1) || !sigma.Imaginary.AlmostEqual(0, 1)) ? alpha/sigma*rdash.DotProduct(residuals)/rdash.DotProduct(t0) : 0; beta = (!sigma.Real.AlmostEqual(0, 1) || !sigma.Imaginary.AlmostEqual(0, 1)) ? alpha/sigma*rdash.ConjugateDotProduct(residuals)/rdash.ConjugateDotProduct(t0) : 0;
// w_k = c_k + beta_k s_k // w_k = c_k + beta_k s_k
s.Multiply(beta, temp2); s.Multiply(beta, temp2);

89
src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/MlkBiCgStab.cs

@ -43,6 +43,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex; using Complex = Numerics.Complex;
#else #else
using Complex = System.Numerics.Complex; using Complex = System.Numerics.Complex;
#endif #endif
/// <summary> /// <summary>
@ -73,39 +74,39 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <summary> /// <summary>
/// The default number of starting vectors. /// The default number of starting vectors.
/// </summary> /// </summary>
private const int DefaultNumberOfStartingVectors = 50; const int DefaultNumberOfStartingVectors = 50;
/// <summary> /// <summary>
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no /// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator. /// iterator.
/// </summary> /// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined(); static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary> /// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default /// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used. /// pre-conditioner will be used.
/// </summary> /// </summary>
private IPreConditioner _preconditioner; IPreConditioner _preconditioner;
/// <summary> /// <summary>
/// The iterative process controller. /// The iterative process controller.
/// </summary> /// </summary>
private IIterator _iterator; IIterator _iterator;
/// <summary> /// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space. /// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary> /// </summary>
private IList<Vector> _startingVectors; IList<Vector> _startingVectors;
/// <summary> /// <summary>
/// The number of starting vectors used by the algorithm /// The number of starting vectors used by the algorithm
/// </summary> /// </summary>
private int _numberOfStartingVectors = DefaultNumberOfStartingVectors; int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
/// <summary> /// <summary>
/// Indicates if the user has stopped the solver. /// Indicates if the user has stopped the solver.
/// </summary> /// </summary>
private bool _hasBeenStopped; bool _hasBeenStopped;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class. /// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
@ -114,7 +115,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with /// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner. /// the standard settings and a default preconditioner.
/// </remarks> /// </remarks>
public MlkBiCgStab() : this(null, null) public MlkBiCgStab()
: this(null, null)
{ {
} }
@ -137,7 +139,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process.</param> /// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IIterator iterator) : this(null, iterator) public MlkBiCgStab(IIterator iterator)
: this(null, iterator)
{ {
} }
@ -149,7 +152,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// the standard settings. /// the standard settings.
/// </remarks> /// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param> /// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param>
public MlkBiCgStab(IPreConditioner preconditioner) : this(preconditioner, null) public MlkBiCgStab(IPreConditioner preconditioner)
: this(preconditioner, null)
{ {
} }
@ -186,10 +190,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
public int NumberOfStartingVectors public int NumberOfStartingVectors
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return _numberOfStartingVectors; }
{
return _numberOfStartingVectors;
}
[DebuggerStepThrough] [DebuggerStepThrough]
set set
@ -236,10 +237,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
public IList<Vector> StartingVectors public IList<Vector> StartingVectors
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return _startingVectors; }
{
return _startingVectors;
}
[DebuggerStepThrough] [DebuggerStepThrough]
set set
@ -261,10 +259,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
public ICalculationStatus IterationResult public ICalculationStatus IterationResult
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
} }
/// <summary> /// <summary>
@ -348,7 +343,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
{ {
_preconditioner = new UnitPreconditioner(); _preconditioner = new UnitPreconditioner();
} }
_preconditioner.Initialize(matrix); _preconditioner.Initialize(matrix);
// Choose an initial guess x_0 // Choose an initial guess x_0
@ -402,7 +397,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
Vector zw = new DenseVector(residuals.Count); Vector zw = new DenseVector(residuals.Count);
var d = CreateVectorArray(_startingVectors.Count, residuals.Count); var d = CreateVectorArray(_startingVectors.Count, residuals.Count);
// g_0 = r_0 // g_0 = r_0
var g = CreateVectorArray(_startingVectors.Count, residuals.Count); var g = CreateVectorArray(_startingVectors.Count, residuals.Count);
residuals.CopyTo(g[k - 1]); residuals.CopyTo(g[k - 1]);
@ -420,14 +415,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(gtemp, w[k - 1]); matrix.Multiply(gtemp, w[k - 1]);
// c_((j-1)k+k) = q^T_1 w_((j-1)k+k) // c_((j-1)k+k) = q^T_1 w_((j-1)k+k)
c[k - 1] = _startingVectors[0].DotProduct(w[k - 1]); c[k - 1] = _startingVectors[0].ConjugateDotProduct(w[k - 1]);
if (c[k - 1].Real.AlmostEqual(0, 1) && c[k - 1].Imaginary.AlmostEqual(0, 1)) if (c[k - 1].Real.AlmostEqual(0, 1) && c[k - 1].Imaginary.AlmostEqual(0, 1))
{ {
throw new Exception("Iterative solver experience a numerical break down"); throw new Exception("Iterative solver experience a numerical break down");
} }
// alpha_(jk+1) = q^T_1 r_((j-1)k+k) / c_((j-1)k+k) // 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].ConjugateDotProduct(residuals)/c[k - 1];
// u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k) // u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k)
w[k - 1].Multiply(-alpha, temp); w[k - 1].Multiply(-alpha, temp);
@ -439,7 +434,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2 // rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
matrix.Multiply(temp1, temp); matrix.Multiply(temp1, temp);
var rho = temp.DotProduct(temp); var rho = temp.ConjugateDotProduct(temp);
// If rho is zero then temp is a zero vector and we're probably // If rho is zero then temp is a zero vector and we're probably
// about to have zero residuals (i.e. an exact solution). // about to have zero residuals (i.e. an exact solution).
@ -449,7 +444,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
rho = 1.0; rho = 1.0;
} }
rho = -u.DotProduct(temp) / rho; rho = -u.ConjugateDotProduct(temp)/rho;
// r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1) // r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1)
u.CopyTo(residuals); u.CopyTo(residuals);
@ -502,7 +497,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
for (var s = i; s < k - 1; s++) 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^(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].ConjugateDotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s) // z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s)
d[s].Multiply(beta, temp); d[s].Multiply(beta, temp);
@ -521,7 +516,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
} }
} }
beta = rho * c[k - 1]; beta = rho*c[k - 1];
if (beta.Real.AlmostEqual(0, 1) && beta.Imaginary.AlmostEqual(0, 1)) if (beta.Real.AlmostEqual(0, 1) && beta.Imaginary.AlmostEqual(0, 1))
{ {
throw new Exception("Iterative solver experience a numerical break down"); throw new Exception("Iterative solver experience a numerical break down");
@ -530,7 +525,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// 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)) // 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); zw.Multiply(rho, temp2);
residuals.Add(temp2, temp); residuals.Add(temp2, temp);
beta = -_startingVectors[0].DotProduct(temp) / beta; beta = -_startingVectors[0].ConjugateDotProduct(temp)/beta;
// z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k) // z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k)
g[k - 1].Multiply(beta, temp); g[k - 1].Multiply(beta, temp);
@ -550,7 +545,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
for (var s = 0; s < i - 1; s++) for (var s = 0; s < i - 1; s++)
{ {
// beta^(jk+i)_(jk+s) = -q^T_s+1 z_d / c_(jk+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].ConjugateDotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s) // z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s)
d[s].Multiply(beta, temp); d[s].Multiply(beta, temp);
@ -573,14 +568,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
if (i < k - 1) if (i < k - 1)
{ {
// c_(jk+1) = q^T_i+1 d_(jk+i) // c_(jk+1) = q^T_i+1 d_(jk+i)
c[i] = _startingVectors[i + 1].DotProduct(d[i]); c[i] = _startingVectors[i + 1].ConjugateDotProduct(d[i]);
if (c[i].Real.AlmostEqual(0, 1) && c[i].Imaginary.AlmostEqual(0, 1)) if (c[i].Real.AlmostEqual(0, 1) && c[i].Imaginary.AlmostEqual(0, 1))
{ {
throw new Exception("Iterative solver experience a numerical break down"); throw new Exception("Iterative solver experience a numerical break down");
} }
// alpha_(jk+i+1) = q^T_(i+1) u_(jk+i) / c_(jk+i) // 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].ConjugateDotProduct(u)/c[i];
// u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i) // u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i)
d[i].Multiply(-alpha, temp); d[i].Multiply(-alpha, temp);
@ -591,7 +586,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
_preconditioner.Approximate(g[i], gtemp); _preconditioner.Approximate(g[i], gtemp);
// x_(jk+i+1) = x_(jk+i) + rho_(j+1) alpha_(jk+i+1) g~_(jk+i) // 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); xtemp.Add(temp, temp2);
temp2.CopyTo(xtemp); temp2.CopyTo(xtemp);
@ -599,7 +594,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(gtemp, w[i]); matrix.Multiply(gtemp, w[i]);
// r_(jk+i+1) = r_(jk+i) - rho_(j+1) alpha_(jk+i+1) w_(jk+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); residuals.Add(temp, temp2);
temp2.CopyTo(residuals); temp2.CopyTo(residuals);
@ -626,7 +621,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="maximumNumberOfStartingVectors">Maximum number</param> /// <param name="maximumNumberOfStartingVectors">Maximum number</param>
/// <param name="numberOfVariables">Number of variables</param> /// <param name="numberOfVariables">Number of variables</param>
/// <returns>Number of starting vectors to create</returns> /// <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 // Create no more starting vectors than the size of the problem - 1
return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 1)); return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 1));
@ -643,7 +638,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// the <paramref name="numberOfVariables"/> is smaller than /// the <paramref name="numberOfVariables"/> is smaller than
/// the <paramref name="maximumNumberOfStartingVectors"/>. /// the <paramref name="maximumNumberOfStartingVectors"/>.
/// </returns> /// </returns>
private static IList<Vector> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables) static IList<Vector> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
{ {
// Create no more starting vectors than the size of the problem - 1 // Create no more starting vectors than the size of the problem - 1
// Get random values and then orthogonalize them with // Get random values and then orthogonalize them with
@ -677,10 +672,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
var result = new List<Vector>(); var result = new List<Vector>();
for (var i = 0; i < orthogonalMatrix.ColumnCount; i++) for (var i = 0; i < orthogonalMatrix.ColumnCount; i++)
{ {
result.Add((Vector)orthogonalMatrix.Column(i)); result.Add((Vector) orthogonalMatrix.Column(i));
// Normalize the result vector // Normalize the result vector
result[i].Multiply(1 / result[i].L2Norm(), result[i]); result[i].Multiply(1/result[i].L2Norm(), result[i]);
} }
return result; return result;
@ -692,7 +687,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="arraySize">Number of vectors</param> /// <param name="arraySize">Number of vectors</param>
/// <param name="vectorSize">Size of each vector</param> /// <param name="vectorSize">Size of each vector</param>
/// <returns>Array of random vectors</returns> /// <returns>Array of random vectors</returns>
private static Vector[] CreateVectorArray(int arraySize, int vectorSize) static Vector[] CreateVectorArray(int arraySize, int vectorSize)
{ {
var result = new Vector[arraySize]; var result = new Vector[arraySize];
for (var i = 0; i < result.Length; i++) for (var i = 0; i < result.Length; i++)
@ -710,7 +705,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="residual">Residual <see cref="Vector"/> data.</param> /// <param name="residual">Residual <see cref="Vector"/> data.</param>
/// <param name="x">x <see cref="Vector"/> data.</param> /// <param name="x">x <see cref="Vector"/> data.</param>
/// <param name="b">b <see cref="Vector"/> data.</param> /// <param name="b">b <see cref="Vector"/> data.</param>
private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b) static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
{ {
// -Ax = residual // -Ax = residual
matrix.Multiply(x, residual); matrix.Multiply(x, residual);
@ -728,7 +723,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param> /// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param> /// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns> /// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals) bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
{ {
if (_hasBeenStopped) if (_hasBeenStopped)
{ {
@ -764,7 +759,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
throw new ArgumentNullException("input"); throw new ArgumentNullException("input");
} }
var result = (Matrix)matrix.CreateMatrix(input.RowCount, input.ColumnCount); var result = (Matrix) matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result); Solve(matrix, input, result);
return result; return result;
} }
@ -800,7 +795,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
for (var column = 0; column < input.ColumnCount; column++) for (var column = 0; column < input.ColumnCount; column++)
{ {
var solution = Solve(matrix, (Vector)input.Column(column)); var solution = Solve(matrix, (Vector) input.Column(column));
foreach (var element in solution.GetIndexedEnumerator()) foreach (var element in solution.GetIndexedEnumerator())
{ {
result.At(element.Item1, column, element.Item2); result.At(element.Item1, column, element.Item2);

13
src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/TFQMR.cs

@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex; using Complex = Numerics.Complex;
#else #else
using Complex = System.Numerics.Complex; using Complex = System.Numerics.Complex;
#endif #endif
/// <summary> /// <summary>
@ -282,15 +283,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
var temp1 = new DenseVector(input.Count); var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count); var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.L2Norm();
// Define the scalars // Define the scalars
Complex alpha = 0; Complex alpha = 0;
Complex eta = 0; Complex eta = 0;
double theta = 0; double theta = 0;
var tau = startNorm.Real; // Initialize
var tau = input.L2Norm().Real;
Complex rho = tau*tau; Complex rho = tau*tau;
// Calculate the initial values for v // Calculate the initial values for v
@ -311,7 +310,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
if (IsEven(iterationNumber)) if (IsEven(iterationNumber))
{ {
// sigma = (v, r) // sigma = (v, r)
var sigma = v.DotProduct(r.Conjugate()); var sigma = r.ConjugateDotProduct(v);
if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1)) if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1))
{ {
// FAIL HERE // FAIL HERE
@ -349,7 +348,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
yinternal.Add(temp, d); yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau // theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.L2Norm().Real / tau; theta = pseudoResiduals.L2Norm().Real/tau;
var c = 1/Math.Sqrt(1 + (theta*theta)); var c = 1/Math.Sqrt(1 + (theta*theta));
// tau = tau * theta * c // tau = tau * theta * c
@ -392,7 +391,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
break; break;
} }
var rhoNew = pseudoResiduals.DotProduct(r.Conjugate()); var rhoNew = r.ConjugateDotProduct(pseudoResiduals);
var beta = rhoNew/rho; var beta = rhoNew/rho;
// Update rho for the next loop // Update rho for the next loop

48
src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/BiCgStab.cs

@ -71,24 +71,24 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no /// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator. /// iterator.
/// </summary> /// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined(); static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary> /// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default /// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used. /// pre-conditioner will be used.
/// </summary> /// </summary>
private IPreConditioner _preconditioner; IPreConditioner _preconditioner;
/// <summary> /// <summary>
/// The iterative process controller. /// The iterative process controller.
/// </summary> /// </summary>
private IIterator _iterator; IIterator _iterator;
/// <summary> /// <summary>
/// Indicates if the user has stopped the solver. /// Indicates if the user has stopped the solver.
/// </summary> /// </summary>
private bool _hasBeenStopped; bool _hasBeenStopped;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class. /// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary> /// </summary>
@ -96,7 +96,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with /// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner. /// the standard settings and a default preconditioner.
/// </remarks> /// </remarks>
public BiCgStab() : this(null, null) public BiCgStab()
: this(null, null)
{ {
} }
@ -119,7 +120,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process. </param> /// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IIterator iterator) : this(null, iterator) public BiCgStab(IIterator iterator)
: this(null, iterator)
{ {
} }
@ -131,7 +133,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// the standard settings. /// the standard settings.
/// </remarks> /// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param> /// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param>
public BiCgStab(IPreConditioner preconditioner) : this(preconditioner, null) public BiCgStab(IPreConditioner preconditioner)
: this(preconditioner, null)
{ {
} }
@ -181,10 +184,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// </summary> /// </summary>
public ICalculationStatus IterationResult public ICalculationStatus IterationResult
{ {
get get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
} }
/// <summary> /// <summary>
@ -273,9 +273,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
{ {
_preconditioner = new UnitPreconditioner(); _preconditioner = new UnitPreconditioner();
} }
_preconditioner.Initialize(matrix); _preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0 // Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector // In this case we take x_0 = vector
// This is basically a SAXPY so it could be made a lot faster // This is basically a SAXPY so it could be made a lot faster
@ -307,7 +307,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
{ {
// rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1) // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
var oldRho = currentRho; var oldRho = currentRho;
currentRho = tempResiduals.DotProduct(residuals); currentRho = tempResiduals.ConjugateDotProduct(residuals);
// if (rho_(i-1) == 0) // METHOD FAILS // if (rho_(i-1) == 0) // METHOD FAILS
// If rho is only 1 ULP from zero then we fail. // If rho is only 1 ULP from zero then we fail.
@ -320,7 +320,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
if (iterationNumber != 0) if (iterationNumber != 0)
{ {
// beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1)) // 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)) // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
nu.Multiply(-omega, temp); nu.Multiply(-omega, temp);
@ -339,12 +339,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// SOLVE Mp~ = p_i // M = preconditioner // SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash); _preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~ // nu_i = Ap~
matrix.Multiply(vecPdash, nu); matrix.Multiply(vecPdash, nu);
// alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i) // 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.ConjugateDotProduct(nu);
// s = r_(i-1) - alpha_i nu_i // s = r_(i-1) - alpha_i nu_i
nu.Multiply(-alpha, temp); nu.Multiply(-alpha, temp);
@ -388,7 +388,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(vecSdash, temp); matrix.Multiply(vecSdash, temp);
// omega_i = temp^T s / temp^T temp // omega_i = temp^T s / temp^T temp
omega = temp.DotProduct(vecS) / temp.DotProduct(temp); omega = temp.ConjugateDotProduct(vecS)/temp.ConjugateDotProduct(temp);
// x_i = x_(i-1) + alpha_i p^ + omega_i s^ // x_i = x_(i-1) + alpha_i p^ + omega_i s^
temp.Multiply(-omega, residuals); temp.Multiply(-omega, residuals);
@ -432,11 +432,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="residual">Residual values in <see cref="Vector"/>.</param> /// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param> /// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</param> /// <param name="b">Instance of the <see cref="Vector"/> b.</param>
private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b) static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
{ {
// -Ax = residual // -Ax = residual
matrix.Multiply(x, residual); matrix.Multiply(x, residual);
// Do not use residual = residual.Negate() because it creates another object // Do not use residual = residual.Negate() because it creates another object
residual.Multiply(-1, residual); residual.Multiply(-1, residual);
@ -452,7 +452,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param> /// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param> /// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns> /// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals) bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
{ {
if (_hasBeenStopped) if (_hasBeenStopped)
{ {
@ -488,7 +488,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
throw new ArgumentNullException("input"); throw new ArgumentNullException("input");
} }
var result = (Matrix)matrix.CreateMatrix(input.RowCount, input.ColumnCount); var result = (Matrix) matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result); Solve(matrix, input, result);
return result; return result;
} }
@ -524,7 +524,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
for (var column = 0; column < input.ColumnCount; column++) for (var column = 0; column < input.ColumnCount; column++)
{ {
var solution = Solve(matrix, (Vector)input.Column(column)); var solution = Solve(matrix, (Vector) input.Column(column));
foreach (var element in solution.GetIndexedEnumerator()) foreach (var element in solution.GetIndexedEnumerator())
{ {
result.At(element.Item1, column, element.Item2); result.At(element.Item1, column, element.Item2);

14
src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/GpBiCg.cs

@ -377,7 +377,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(temp, s); matrix.Multiply(temp, s);
// alpha_k = (r*_0 * r_k) / (r*_0 * s_k) // alpha_k = (r*_0 * r_k) / (r*_0 * s_k)
var alpha = rdash.DotProduct(residuals)/rdash.DotProduct(s); var alpha = rdash.ConjugateDotProduct(residuals)/rdash.ConjugateDotProduct(s);
// y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k // y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k
s.Subtract(w, temp); s.Subtract(w, temp);
@ -399,7 +399,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// c_k = A d_k // c_k = A d_k
matrix.Multiply(temp, c); matrix.Multiply(temp, c);
var cdot = c.DotProduct(c); var cdot = c.ConjugateDotProduct(c);
// cDot can only be zero if c is a zero vector // 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 // We'll set cDot to 1 if it is zero to prevent NaN's
@ -414,7 +414,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// to do at least one at the start to initialize the // to do at least one at the start to initialize the
// system, but we'll only have to take special measures // system, but we'll only have to take special measures
// if we don't do any so ... // if we don't do any so ...
var ctdot = c.DotProduct(t); var ctdot = c.ConjugateDotProduct(t);
Complex32 eta; Complex32 eta;
Complex32 sigma; Complex32 sigma;
if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber)) if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber))
@ -427,7 +427,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
} }
else else
{ {
var ydot = y.DotProduct(y); var ydot = y.ConjugateDotProduct(y);
// yDot can only be zero if y is a zero vector // yDot can only be zero if y is a zero vector
// We'll set yDot to 1 if it is zero to prevent NaN's // We'll set yDot to 1 if it is zero to prevent NaN's
@ -438,8 +438,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
ydot = 1.0f; ydot = 1.0f;
} }
var ytdot = y.DotProduct(t); var ytdot = y.ConjugateDotProduct(t);
var cydot = c.DotProduct(y); var cydot = c.ConjugateDotProduct(y);
var denom = (cdot*ydot) - (cydot*cydot); var denom = (cdot*ydot) - (cydot*cydot);
@ -493,7 +493,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// beta_k = alpha_k / sigma_k * (r*_0 * r_(k+1)) / (r*_0 * r_k) // 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. // But first we check if there is a possible NaN. If so just reset beta to zero.
beta = (!sigma.Real.AlmostEqual(0, 1) || !sigma.Imaginary.AlmostEqual(0, 1)) ? alpha/sigma*rdash.DotProduct(residuals)/rdash.DotProduct(t0) : 0; beta = (!sigma.Real.AlmostEqual(0, 1) || !sigma.Imaginary.AlmostEqual(0, 1)) ? alpha/sigma*rdash.ConjugateDotProduct(residuals)/rdash.ConjugateDotProduct(t0) : 0;
// w_k = c_k + beta_k s_k // w_k = c_k + beta_k s_k
s.Multiply(beta, temp2); s.Multiply(beta, temp2);

90
src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/MlkBiCgStab.cs

@ -68,39 +68,39 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <summary> /// <summary>
/// The default number of starting vectors. /// The default number of starting vectors.
/// </summary> /// </summary>
private const int DefaultNumberOfStartingVectors = 50; const int DefaultNumberOfStartingVectors = 50;
/// <summary> /// <summary>
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no /// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator. /// iterator.
/// </summary> /// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined(); static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary> /// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default /// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used. /// pre-conditioner will be used.
/// </summary> /// </summary>
private IPreConditioner _preconditioner; IPreConditioner _preconditioner;
/// <summary> /// <summary>
/// The iterative process controller. /// The iterative process controller.
/// </summary> /// </summary>
private IIterator _iterator; IIterator _iterator;
/// <summary> /// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space. /// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary> /// </summary>
private IList<Vector> _startingVectors; IList<Vector> _startingVectors;
/// <summary> /// <summary>
/// The number of starting vectors used by the algorithm /// The number of starting vectors used by the algorithm
/// </summary> /// </summary>
private int _numberOfStartingVectors = DefaultNumberOfStartingVectors; int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
/// <summary> /// <summary>
/// Indicates if the user has stopped the solver. /// Indicates if the user has stopped the solver.
/// </summary> /// </summary>
private bool _hasBeenStopped; bool _hasBeenStopped;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class. /// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
@ -109,7 +109,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with /// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner. /// the standard settings and a default preconditioner.
/// </remarks> /// </remarks>
public MlkBiCgStab() : this(null, null) public MlkBiCgStab()
: this(null, null)
{ {
} }
@ -132,7 +133,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process.</param> /// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IIterator iterator) : this(null, iterator) public MlkBiCgStab(IIterator iterator)
: this(null, iterator)
{ {
} }
@ -144,7 +146,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// the standard settings. /// the standard settings.
/// </remarks> /// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param> /// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param>
public MlkBiCgStab(IPreConditioner preconditioner) : this(preconditioner, null) public MlkBiCgStab(IPreConditioner preconditioner)
: this(preconditioner, null)
{ {
} }
@ -181,10 +184,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
public int NumberOfStartingVectors public int NumberOfStartingVectors
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return _numberOfStartingVectors; }
{
return _numberOfStartingVectors;
}
[DebuggerStepThrough] [DebuggerStepThrough]
set set
@ -231,10 +231,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
public IList<Vector> StartingVectors public IList<Vector> StartingVectors
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return _startingVectors; }
{
return _startingVectors;
}
[DebuggerStepThrough] [DebuggerStepThrough]
set set
@ -256,10 +253,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
public ICalculationStatus IterationResult public ICalculationStatus IterationResult
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
} }
/// <summary> /// <summary>
@ -348,7 +342,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
{ {
_preconditioner = new UnitPreconditioner(); _preconditioner = new UnitPreconditioner();
} }
_preconditioner.Initialize(matrix); _preconditioner.Initialize(matrix);
// Choose an initial guess x_0 // Choose an initial guess x_0
@ -402,7 +396,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
Vector zw = new DenseVector(residuals.Count); Vector zw = new DenseVector(residuals.Count);
var d = CreateVectorArray(_startingVectors.Count, residuals.Count); var d = CreateVectorArray(_startingVectors.Count, residuals.Count);
// g_0 = r_0 // g_0 = r_0
var g = CreateVectorArray(_startingVectors.Count, residuals.Count); var g = CreateVectorArray(_startingVectors.Count, residuals.Count);
residuals.CopyTo(g[k - 1]); residuals.CopyTo(g[k - 1]);
@ -420,14 +414,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(gtemp, w[k - 1]); matrix.Multiply(gtemp, w[k - 1]);
// c_((j-1)k+k) = q^T_1 w_((j-1)k+k) // c_((j-1)k+k) = q^T_1 w_((j-1)k+k)
c[k - 1] = _startingVectors[0].DotProduct(w[k - 1]); c[k - 1] = _startingVectors[0].ConjugateDotProduct(w[k - 1]);
if (c[k - 1].Real.AlmostEqual(0, 1) && c[k - 1].Imaginary.AlmostEqual(0, 1)) if (c[k - 1].Real.AlmostEqual(0, 1) && c[k - 1].Imaginary.AlmostEqual(0, 1))
{ {
throw new Exception("Iterative solver experience a numerical break down"); throw new Exception("Iterative solver experience a numerical break down");
} }
// alpha_(jk+1) = q^T_1 r_((j-1)k+k) / c_((j-1)k+k) // 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].ConjugateDotProduct(residuals)/c[k - 1];
// u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k) // u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k)
w[k - 1].Multiply(-alpha, temp); w[k - 1].Multiply(-alpha, temp);
@ -439,7 +433,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2 // rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
matrix.Multiply(temp1, temp); matrix.Multiply(temp1, temp);
var rho = temp.DotProduct(temp); var rho = temp.ConjugateDotProduct(temp);
// If rho is zero then temp is a zero vector and we're probably // If rho is zero then temp is a zero vector and we're probably
// about to have zero residuals (i.e. an exact solution). // about to have zero residuals (i.e. an exact solution).
@ -449,7 +443,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
rho = 1.0f; rho = 1.0f;
} }
rho = -u.DotProduct(temp) / rho; rho = -u.ConjugateDotProduct(temp)/rho;
// r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1) // r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1)
u.CopyTo(residuals); u.CopyTo(residuals);
@ -502,7 +496,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
for (var s = i; s < k - 1; s++) 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^(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].ConjugateDotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s) // z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s)
d[s].Multiply(beta, temp); d[s].Multiply(beta, temp);
@ -521,7 +515,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
} }
} }
beta = rho * c[k - 1]; beta = rho*c[k - 1];
if (beta.Real.AlmostEqual(0, 1) && beta.Imaginary.AlmostEqual(0, 1)) if (beta.Real.AlmostEqual(0, 1) && beta.Imaginary.AlmostEqual(0, 1))
{ {
throw new Exception("Iterative solver experience a numerical break down"); throw new Exception("Iterative solver experience a numerical break down");
@ -530,7 +524,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// 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)) // 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); zw.Multiply(rho, temp2);
residuals.Add(temp2, temp); residuals.Add(temp2, temp);
beta = -_startingVectors[0].DotProduct(temp) / beta; beta = -_startingVectors[0].ConjugateDotProduct(temp)/beta;
// z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k) // z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k)
g[k - 1].Multiply(beta, temp); g[k - 1].Multiply(beta, temp);
@ -550,7 +544,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
for (var s = 0; s < i - 1; s++) for (var s = 0; s < i - 1; s++)
{ {
// beta^(jk+i)_(jk+s) = -q^T_s+1 z_d / c_(jk+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].ConjugateDotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s) // z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s)
d[s].Multiply(beta, temp); d[s].Multiply(beta, temp);
@ -573,14 +567,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
if (i < k - 1) if (i < k - 1)
{ {
// c_(jk+1) = q^T_i+1 d_(jk+i) // c_(jk+1) = q^T_i+1 d_(jk+i)
c[i] = _startingVectors[i + 1].DotProduct(d[i]); c[i] = _startingVectors[i + 1].ConjugateDotProduct(d[i]);
if (c[i].Real.AlmostEqual(0, 1) && c[i].Imaginary.AlmostEqual(0, 1)) if (c[i].Real.AlmostEqual(0, 1) && c[i].Imaginary.AlmostEqual(0, 1))
{ {
throw new Exception("Iterative solver experience a numerical break down"); throw new Exception("Iterative solver experience a numerical break down");
} }
// alpha_(jk+i+1) = q^T_(i+1) u_(jk+i) / c_(jk+i) // 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].ConjugateDotProduct(u)/c[i];
// u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i) // u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i)
d[i].Multiply(-alpha, temp); d[i].Multiply(-alpha, temp);
@ -591,7 +585,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
_preconditioner.Approximate(g[i], gtemp); _preconditioner.Approximate(g[i], gtemp);
// x_(jk+i+1) = x_(jk+i) + rho_(j+1) alpha_(jk+i+1) g~_(jk+i) // 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); xtemp.Add(temp, temp2);
temp2.CopyTo(xtemp); temp2.CopyTo(xtemp);
@ -599,7 +593,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(gtemp, w[i]); matrix.Multiply(gtemp, w[i]);
// r_(jk+i+1) = r_(jk+i) - rho_(j+1) alpha_(jk+i+1) w_(jk+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); residuals.Add(temp, temp2);
temp2.CopyTo(residuals); temp2.CopyTo(residuals);
@ -626,7 +620,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="maximumNumberOfStartingVectors">Maximum number</param> /// <param name="maximumNumberOfStartingVectors">Maximum number</param>
/// <param name="numberOfVariables">Number of variables</param> /// <param name="numberOfVariables">Number of variables</param>
/// <returns>Number of starting vectors to create</returns> /// <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 // Create no more starting vectors than the size of the problem - 1
return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 1)); return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 1));
@ -643,7 +637,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// the <paramref name="numberOfVariables"/> is smaller than /// the <paramref name="numberOfVariables"/> is smaller than
/// the <paramref name="maximumNumberOfStartingVectors"/>. /// the <paramref name="maximumNumberOfStartingVectors"/>.
/// </returns> /// </returns>
private static IList<Vector> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables) static IList<Vector> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
{ {
// Create no more starting vectors than the size of the problem - 1 // Create no more starting vectors than the size of the problem - 1
// Get random values and then orthogonalize them with // Get random values and then orthogonalize them with
@ -662,7 +656,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
var samplesIm = distribution.Samples().Take(matrix.RowCount).ToArray(); var samplesIm = distribution.Samples().Take(matrix.RowCount).ToArray();
for (int j = 0; j < matrix.RowCount; j++) for (int j = 0; j < matrix.RowCount; j++)
{ {
samples[j] = new Complex32((float)samplesRe[j], (float)samplesIm[j]); samples[j] = new Complex32((float) samplesRe[j], (float) samplesIm[j]);
} }
// Set the column // Set the column
@ -677,10 +671,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
var result = new List<Vector>(); var result = new List<Vector>();
for (var i = 0; i < orthogonalMatrix.ColumnCount; i++) for (var i = 0; i < orthogonalMatrix.ColumnCount; i++)
{ {
result.Add((Vector)orthogonalMatrix.Column(i)); result.Add((Vector) orthogonalMatrix.Column(i));
// Normalize the result vector // Normalize the result vector
result[i].Multiply(1 / result[i].L2Norm().Real, result[i]); result[i].Multiply(1/result[i].L2Norm().Real, result[i]);
} }
return result; return result;
@ -692,7 +686,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="arraySize">Number of vectors</param> /// <param name="arraySize">Number of vectors</param>
/// <param name="vectorSize">Size of each vector</param> /// <param name="vectorSize">Size of each vector</param>
/// <returns>Array of random vectors</returns> /// <returns>Array of random vectors</returns>
private static Vector[] CreateVectorArray(int arraySize, int vectorSize) static Vector[] CreateVectorArray(int arraySize, int vectorSize)
{ {
var result = new Vector[arraySize]; var result = new Vector[arraySize];
for (var i = 0; i < result.Length; i++) for (var i = 0; i < result.Length; i++)
@ -710,7 +704,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="residual">Residual <see cref="Vector"/> data.</param> /// <param name="residual">Residual <see cref="Vector"/> data.</param>
/// <param name="x">x <see cref="Vector"/> data.</param> /// <param name="x">x <see cref="Vector"/> data.</param>
/// <param name="b">b <see cref="Vector"/> data.</param> /// <param name="b">b <see cref="Vector"/> data.</param>
private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b) static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
{ {
// -Ax = residual // -Ax = residual
matrix.Multiply(x, residual); matrix.Multiply(x, residual);
@ -728,7 +722,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param> /// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param> /// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns> /// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals) bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
{ {
if (_hasBeenStopped) if (_hasBeenStopped)
{ {
@ -764,7 +758,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
throw new ArgumentNullException("input"); throw new ArgumentNullException("input");
} }
var result = (Matrix)matrix.CreateMatrix(input.RowCount, input.ColumnCount); var result = (Matrix) matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result); Solve(matrix, input, result);
return result; return result;
} }
@ -800,7 +794,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
for (var column = 0; column < input.ColumnCount; column++) for (var column = 0; column < input.ColumnCount; column++)
{ {
var solution = Solve(matrix, (Vector)input.Column(column)); var solution = Solve(matrix, (Vector) input.Column(column));
foreach (var element in solution.GetIndexedEnumerator()) foreach (var element in solution.GetIndexedEnumerator())
{ {
result.At(element.Item1, column, element.Item2); result.At(element.Item1, column, element.Item2);

12
src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/TFQMR.cs

@ -282,15 +282,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
var temp1 = new DenseVector(input.Count); var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count); var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.L2Norm();
// Define the scalars // Define the scalars
Complex32 alpha = 0; Complex32 alpha = 0;
Complex32 eta = 0; Complex32 eta = 0;
float theta = 0; float theta = 0;
var tau = startNorm.Real; // Initialize
var tau = input.L2Norm().Real;
Complex32 rho = tau*tau; Complex32 rho = tau*tau;
// Calculate the initial values for v // Calculate the initial values for v
@ -311,7 +309,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
if (IsEven(iterationNumber)) if (IsEven(iterationNumber))
{ {
// sigma = (v, r) // sigma = (v, r)
var sigma = v.DotProduct(r.Conjugate()); var sigma = r.ConjugateDotProduct(v);
if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1)) if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1))
{ {
// FAIL HERE // FAIL HERE
@ -349,7 +347,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
yinternal.Add(temp, d); yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau // theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.L2Norm().Real / tau; theta = pseudoResiduals.L2Norm().Real/tau;
var c = 1/(float) Math.Sqrt(1 + (theta*theta)); var c = 1/(float) Math.Sqrt(1 + (theta*theta));
// tau = tau * theta * c // tau = tau * theta * c
@ -392,7 +390,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
break; break;
} }
var rhoNew = pseudoResiduals.DotProduct(r.Conjugate()); var rhoNew = r.ConjugateDotProduct(pseudoResiduals);
var beta = rhoNew/rho; var beta = rhoNew/rho;
// Update rho for the next loop // Update rho for the next loop

8
src/Numerics/LinearAlgebra/Double/Solvers/Iterative/TFQMR.cs

@ -280,17 +280,15 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.Iterative
var temp = new DenseVector(input.Count); var temp = new DenseVector(input.Count);
var temp1 = new DenseVector(input.Count); var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count); var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.L2Norm();
// Define the scalars // Define the scalars
double alpha = 0; double alpha = 0;
double eta = 0; double eta = 0;
double theta = 0; double theta = 0;
var tau = startNorm; // Initialize
var rho = tau * tau; var tau = input.L2Norm();
var rho = tau*tau;
// Calculate the initial values for v // Calculate the initial values for v
// M temp = yEven // M temp = yEven

2
src/Numerics/LinearAlgebra/Generic/Vector.Arithmetic.cs

@ -513,6 +513,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// <returns>The sum of a[i]*b[i] for all i.</returns> /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// <exception cref="ArgumentException">If <paramref name="other"/> is not of the same size.</exception> /// <exception cref="ArgumentException">If <paramref name="other"/> is not of the same size.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="other"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="other"/> is <see langword="null"/>.</exception>
/// <seealso cref="ConjugateDotProduct"/>
public T DotProduct(Vector<T> other) public T DotProduct(Vector<T> other)
{ {
if (other == null) throw new ArgumentNullException("other"); if (other == null) throw new ArgumentNullException("other");
@ -528,6 +529,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// <returns>The sum of conj(a[i])*b[i] for all i.</returns> /// <returns>The sum of conj(a[i])*b[i] for all i.</returns>
/// <exception cref="ArgumentException">If <paramref name="other"/> is not of the same size.</exception> /// <exception cref="ArgumentException">If <paramref name="other"/> is not of the same size.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="other"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="other"/> is <see langword="null"/>.</exception>
/// <seealso cref="DotProduct"/>
public T ConjugateDotProduct(Vector<T> other) public T ConjugateDotProduct(Vector<T> other)
{ {
if (other == null) throw new ArgumentNullException("other"); if (other == null) throw new ArgumentNullException("other");

6
src/Numerics/LinearAlgebra/Single/Solvers/Iterative/TFQMR.cs

@ -281,15 +281,13 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers.Iterative
var temp1 = new DenseVector(input.Count); var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count); var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.L2Norm();
// Define the scalars // Define the scalars
float alpha = 0; float alpha = 0;
float eta = 0; float eta = 0;
float theta = 0; float theta = 0;
var tau = startNorm; // Initialize
var tau = input.L2Norm();
var rho = tau*tau; var rho = tau*tau;
// Calculate the initial values for v // Calculate the initial values for v

Loading…
Cancel
Save