From 59cebe9f01e6da6ebd2f52e56154fa2930e76f04 Mon Sep 17 00:00:00 2001 From: joemoorhouse Date: Sun, 10 Nov 2013 00:42:44 +0000 Subject: [PATCH] Add options for NonLinearLeastSquaresMinimizer. Add options for NonLinearLeastSquaresMinimizer. --- .../NonLinearLeastSquaresMinimizer.cs | 51 ++++++++++++++++--- .../Optimization/IOptimizationProvider.cs | 4 +- .../Mkl/MklOptimizationProvider.cs | 15 +++--- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/Numerics/Optimization/NonLinearLeastSquaresMinimizer.cs b/src/Numerics/Optimization/NonLinearLeastSquaresMinimizer.cs index 533869b5..5611477c 100644 --- a/src/Numerics/Optimization/NonLinearLeastSquaresMinimizer.cs +++ b/src/Numerics/Optimization/NonLinearLeastSquaresMinimizer.cs @@ -13,14 +13,51 @@ namespace MathNet.Numerics.Optimization /// public class NonLinearLeastSquaresMinimizer { + public class Options + { + public int MaximumIterations = 1000; + + public int MaximumTrialStepIterations = 100; + + public ConvergenceType ConvergenceType; + + /// + /// Convergence if Δ < Criterion0, Δ is trust region size. + /// + public double Criterion0 = 1e-7; + + /// + /// Convergence if |r|2 < Criterion1, r is residuals vector. + /// + public double Criterion1 = 1e-7; + + /// + /// Jacobian considered singular if |J(:,j)|2 < Criterion2 for any j. + /// + public double Criterion2 = 1e-7; + + /// + /// Jacobian considered singular if |s|2 < Criterion3. s is trial step. + /// + public double Criterion3 = 1e-7; + + /// + /// |r|2 - |r - Js|2 < Criterion4 + /// + public double Criterion4 = 1e-7; + + public double TrialStepPrecision = 1e-10; + + /// + /// Only if Jacobian calculated by central differences. + /// + public double JacobianPrecision = 1e-8; + } + /// - /// Criterion0: Δ < eps(0) (trust region solvers only) - /// Criterion1: ||F(x)||2 < eps(1) - /// Criterion2: The Jacobian matrix is singular.||J(x)(1:m,j)||2 < eps(2), j = 1, ..., n - /// Criterion3: ||s||2 < eps(3) - /// Criterion4: ||F(x)||2 - ||F(x) - J(x)s||2 < eps(4) + /// For details of convergence criteria, see Options. /// - public enum ConvergenceType { NoneMaxIterationExceeded, Criterion0, Criterion1, Criterion2, Criterion3, Criterion4, SingularJacobian, Error }; + public enum ConvergenceType { NoneMaxIterationExceeded, Criterion0, Criterion1, Criterion2, Criterion3, Criterion4, Error }; public class Result { @@ -36,7 +73,7 @@ namespace MathNet.Numerics.Optimization /// /// /// - /// + /// Initial guess of parameters, p. /// jac_j(x, p) = df / dp_j /// public static double[] CurveFit(double[] x, double[] y, Func f, diff --git a/src/Numerics/Providers/Optimization/IOptimizationProvider.cs b/src/Numerics/Providers/Optimization/IOptimizationProvider.cs index b5463849..3e2400ba 100644 --- a/src/Numerics/Providers/Optimization/IOptimizationProvider.cs +++ b/src/Numerics/Providers/Optimization/IOptimizationProvider.cs @@ -57,7 +57,7 @@ namespace MathNet.Numerics.Providers.Optimization where T : struct { NonLinearLeastSquaresMinimizer.Result NonLinearLeastSquaresUnboundedMinimize( - int residualsLength, T[] initialGuess, LeastSquaresForwardModel function, - out T[] parameters, Jacobian jacobianFunction = null); + int residualsLength, T[] initialGuess, LeastSquaresForwardModel function, + out T[] parameters, Jacobian jacobianFunction = null, NonLinearLeastSquaresMinimizer.Options options = null); } } diff --git a/src/Numerics/Providers/Optimization/Mkl/MklOptimizationProvider.cs b/src/Numerics/Providers/Optimization/Mkl/MklOptimizationProvider.cs index 571ca076..eeac095e 100644 --- a/src/Numerics/Providers/Optimization/Mkl/MklOptimizationProvider.cs +++ b/src/Numerics/Providers/Optimization/Mkl/MklOptimizationProvider.cs @@ -42,8 +42,9 @@ namespace MathNet.Numerics.Providers.Optimization.Mkl { const int TR_SUCCESS = 1501; - public NonLinearLeastSquaresMinimizer.Result NonLinearLeastSquaresUnboundedMinimize(int residualsLength, double[] initialGuess, LeastSquaresForwardModel function, out double[] parameters, Jacobian jacobianFunction = null) + public NonLinearLeastSquaresMinimizer.Result NonLinearLeastSquaresUnboundedMinimize(int residualsLength, double[] initialGuess, LeastSquaresForwardModel function, out double[] parameters, Jacobian jacobianFunction = null, NonLinearLeastSquaresMinimizer.Options options = null) { + if (options == null) options = new NonLinearLeastSquaresMinimizer.Options(); bool analyticJacobian = jacobianFunction != null; double[] residuals = new double[residualsLength]; double[] residualsMinus = new double[residualsLength]; @@ -53,15 +54,15 @@ namespace MathNet.Numerics.Providers.Optimization.Mkl double[] eps = new double[6]; // stop criteria int i; - for (i = 0; i < 6; i++) - eps[i] = 1e-8; + eps[0] = options.Criterion0; eps[1] = options.Criterion1; eps[2] = options.Criterion2; + eps[3] = options.Criterion3; eps[4] = options.Criterion4; eps[5] = options.TrialStepPrecision; for (i = 0; i < initialGuess.Length; i++) parameters[i] = initialGuess[i]; int successful; - int maxIterations = 1000, maxTrialStepIterations = 100; + int maxIterations = options.MaximumIterations, maxTrialStepIterations = options.MaximumTrialStepIterations; IntPtr solverHandle = IntPtr.Zero; IntPtr jacobianHandle = IntPtr.Zero; @@ -70,7 +71,7 @@ namespace MathNet.Numerics.Providers.Optimization.Mkl double initialStepBound = 0.0; - double jacobianPrecision = 1e-8; + double jacobianPrecision = options.JacobianPrecision; // zero initial values: for (i = 0; i < residuals.Length; i++) @@ -185,7 +186,7 @@ namespace MathNet.Numerics.Providers.Optimization.Mkl case -3: convergenceType = NonLinearLeastSquaresMinimizer.ConvergenceType.Criterion1; break; case -4: - convergenceType = NonLinearLeastSquaresMinimizer.ConvergenceType.SingularJacobian; break; + convergenceType = NonLinearLeastSquaresMinimizer.ConvergenceType.Criterion2; break; case -5: convergenceType = NonLinearLeastSquaresMinimizer.ConvergenceType.Criterion3; break; case -6: @@ -193,7 +194,7 @@ namespace MathNet.Numerics.Providers.Optimization.Mkl } // no errors, find reason for stopping; - return new NonLinearLeastSquaresMinimizer.Result() { ConvergenceType = convergenceType }; + return new NonLinearLeastSquaresMinimizer.Result() { ConvergenceType = convergenceType, NumberOfIterations = iterations }; } public static NonLinearLeastSquaresMinimizer.Result ErrorResult()