diff --git a/src/Numerics/RootFinding/Broyden.cs b/src/Numerics/RootFinding/Broyden.cs
index 292b9cc2..ee62255a 100644
--- a/src/Numerics/RootFinding/Broyden.cs
+++ b/src/Numerics/RootFinding/Broyden.cs
@@ -31,6 +31,7 @@
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Generic;
using System;
+using MathNet.Numerics.Properties;
namespace MathNet.Numerics.RootFinding
{
@@ -54,59 +55,58 @@ namespace MathNet.Numerics.RootFinding
{
return root;
}
- throw new NonConvergenceException("The algorithm has exceeded the number of iterations allowed");
+ throw new NonConvergenceException(Resources.RootFindingFailed);
}
/// Find a solution of the equation f(x)=0.
/// The function to find roots from.
- /// The low value of the range where the root is supposed to be.
+ /// Initial guess of the root.
/// Desired accuracy. The root will be refined until the accuracy or the maximum number of iterations is reached.
/// Maximum number of iterations. Usually 100.
/// The root that was found, if any. Undefined if the function returns false.
/// True if a root with the specified accuracy was found, else false.
public static bool TryFindRoot(Func f, double[] initialGuess, double accuracy, int maxIterations, out double[] root)
{
- double[] F = f(initialGuess);
- DenseVector FVect = new DenseVector(F);
- double g = FVect.Norm(2);
+ var x = new DenseVector(initialGuess);
- Matrix B = CalculateApproximateJacobian(f, initialGuess, F);
+ double[] y0 = f(initialGuess);
+ var y = new DenseVector(y0);
+ double g = y.Norm(2);
- Vector x = new DenseVector(initialGuess);
+ Matrix B = CalculateApproximateJacobian(f, initialGuess, y0);
for (int i = 0; i <= maxIterations; i++)
{
- Vector dx = -B.LU().Solve(FVect);
- Vector xnew = x + dx;
- double[] FNew = f(xnew.ToArray());
- DenseVector FNewVect = new DenseVector(FNew);
- double gNew = FNewVect.Norm(2);
- if (gNew > g)
+ var dx = (DenseVector) (-B.LU().Solve(y));
+ var xnew = x + dx;
+ var ynew = new DenseVector(f(xnew.Values));
+ double gnew = ynew.Norm(2);
+
+ if (gnew > g)
{
- double g2 = g * g;
- double scale = g2 / (g2 + gNew * gNew);
+ double g2 = g*g;
+ double scale = g2/(g2 + gnew*gnew);
if (scale == 0.0) scale = 1.0e-4;
- dx = scale * dx;
+ dx = scale*dx;
xnew = x + dx;
- FNew = f(xnew.ToArray());
- FNewVect = new DenseVector(FNew);
- gNew = FNewVect.Norm(2);
+ ynew = new DenseVector(f(xnew.Values));
+ gnew = ynew.Norm(2);
}
- if (gNew < accuracy)
+ if (gnew < accuracy)
{
- root = xnew.ToArray();
+ root = xnew.Values;
return true;
}
// update Jacobian B
- DenseVector dF = FNewVect - FVect;
- Matrix dB = (dF - B.Multiply(dx)).ToColumnMatrix() * dx.Multiply(1.0 / Math.Pow(dx.Norm(2),2)).ToRowMatrix();
+ DenseVector dF = ynew - y;
+ Matrix dB = (dF - B.Multiply(dx)).ToColumnMatrix()*dx.Multiply(1.0/Math.Pow(dx.Norm(2), 2)).ToRowMatrix();
B = B + dB;
x = xnew;
- FVect = FNewVect;
- g = gNew;
+ y = ynew;
+ g = gnew;
}
root = null;
@@ -119,25 +119,27 @@ namespace MathNet.Numerics.RootFinding
/// The function.
/// The argument.
///
- private static Matrix CalculateApproximateJacobian(Func f, double[] x0, double[] F0)
+ static Matrix CalculateApproximateJacobian(Func f, double[] x0, double[] y0)
{
int dim = x0.Length;
- double[] xpos = new double[dim];
- DenseMatrix B = new DenseMatrix(dim);
+ var B = new DenseMatrix(dim);
+
+ var x = new double[dim];
+ Array.Copy(x0, x, dim);
for (int j = 0; j < dim; j++)
{
- Array.Copy(x0, xpos, dim);
-
- double h = Math.Abs(x0[j]) * 1.0e-4;
+ double h = Math.Abs(x0[j])*1.0e-4;
if (h == 0.0) h = 1.0e-4;
- xpos[j] += h;
- double[] Fpos = f(xpos);
+ var xj = x[j];
+ x[j] = xj + h;
+ double[] y = f(x);
+ x[j] = xj;
for (int i = 0; i < dim; i++)
{
- B[i, j] = (Fpos[i] - F0[i]) / h;
+ B.At(i, j, (y[i] - y0[i])/h);
}
}