diff --git a/src/Numerics/RootFinding/Broyden.cs b/src/Numerics/RootFinding/Broyden.cs index 264ef82d..0453188e 100644 --- a/src/Numerics/RootFinding/Broyden.cs +++ b/src/Numerics/RootFinding/Broyden.cs @@ -45,12 +45,13 @@ namespace MathNet.Numerics.RootFinding /// Initial guess of the root. /// Desired accuracy. The root will be refined until the accuracy or the maximum number of iterations is reached. Default 1e-8. /// Maximum number of iterations. Default 100. + /// Relative step size for calculating the Jacobian matrix at first step. Default 1.0e-4 /// Returns the root with the specified accuracy. /// - public static double[] FindRoot(Func f, double[] initialGuess, double accuracy = 1e-8, int maxIterations = 100) + public static double[] FindRoot(Func f, double[] initialGuess, double accuracy = 1e-8, int maxIterations = 100, double jacobianStepSize = 1.0e-4) { double[] root; - if (TryFindRoot(f, initialGuess, accuracy, maxIterations, out root)) + if (TryFindRootWithJacobianStep(f, initialGuess, accuracy, maxIterations, jacobianStepSize, out root)) { return root; } @@ -63,9 +64,10 @@ namespace MathNet.Numerics.RootFinding /// 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. + /// Relative step size for calculating the Jacobian matrix at first step. /// 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) + public static bool TryFindRootWithJacobianStep(Func f, double[] initialGuess, double accuracy, int maxIterations, double jacobianStepSize, out double[] root) { var x = new DenseVector(initialGuess); @@ -73,7 +75,7 @@ namespace MathNet.Numerics.RootFinding var y = new DenseVector(y0); double g = y.L2Norm(); - Matrix B = CalculateApproximateJacobian(f, initialGuess, y0); + Matrix B = CalculateApproximateJacobian(f, initialGuess, y0, jacobianStepSize); for (int i = 0; i <= maxIterations; i++) { @@ -116,6 +118,17 @@ namespace MathNet.Numerics.RootFinding root = null; return false; } + /// Find a solution of the equation f(x)=0. + /// The function to find roots from. + /// 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) + { + return TryFindRootWithJacobianStep(f, initialGuess, accuracy, maxIterations, 1.0e-4, out root); + } /// /// Helper method to calculate an approximation of the Jacobian. @@ -123,7 +136,8 @@ namespace MathNet.Numerics.RootFinding /// The function. /// The argument (initial guess). /// The result (of initial guess). - static Matrix CalculateApproximateJacobian(Func f, double[] x0, double[] y0) + /// Relative step size for calculating the Jacobian. + static Matrix CalculateApproximateJacobian(Func f, double[] x0, double[] y0, double jacobianStepSize) { int dim = x0.Length; var B = new DenseMatrix(dim); @@ -133,11 +147,7 @@ namespace MathNet.Numerics.RootFinding for (int j = 0; j < dim; j++) { - double h = Math.Abs(x0[j])*1.0e-4; - if (h == 0.0) - { - h = 1.0e-4; - } + double h = (1.0+Math.Abs(x0[j]))*jacobianStepSize; var xj = x[j]; x[j] = xj + h;