From 9f48af911ce46d45f8c99043801310d95c1dc7be Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sat, 15 Jul 2017 17:13:41 +0200 Subject: [PATCH] Optimization: NewtonMinimizer: allow static usage --- .../Optimization/NelderMeadSimplex.cs | 4 +-- src/Numerics/Optimization/NewtonMinimizer.cs | 30 ++++++++----------- .../OptimizationTests/NewtonMinimizerTests.cs | 3 +- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/Numerics/Optimization/NelderMeadSimplex.cs b/src/Numerics/Optimization/NelderMeadSimplex.cs index 68551786..50fed8e2 100644 --- a/src/Numerics/Optimization/NelderMeadSimplex.cs +++ b/src/Numerics/Optimization/NelderMeadSimplex.cs @@ -87,7 +87,7 @@ namespace MathNet.Numerics.Optimization /// The objective function, no gradient or hessian needed /// The intial guess /// The minimum point - public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector initialGuess, double convergenceTolerance, int maximumIterations) + public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector initialGuess, double convergenceTolerance, int maximumIterations=1000) { var initalPertubation = new LinearAlgebra.Double.DenseVector(initialGuess.Count); for (int i = 0; i < initialGuess.Count; i++) @@ -104,7 +104,7 @@ namespace MathNet.Numerics.Optimization /// The intial guess /// The inital pertubation /// The minimum point - public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector initialGuess, Vector initalPertubation, double convergenceTolerance, int maximumIterations) + public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector initialGuess, Vector initalPertubation, double convergenceTolerance, int maximumIterations=1000) { // confirm that we are in a position to commence if (objectiveFunction == null) diff --git a/src/Numerics/Optimization/NewtonMinimizer.cs b/src/Numerics/Optimization/NewtonMinimizer.cs index 8ca0c384..6d57086d 100644 --- a/src/Numerics/Optimization/NewtonMinimizer.cs +++ b/src/Numerics/Optimization/NewtonMinimizer.cs @@ -33,7 +33,7 @@ using MathNet.Numerics.Optimization.LineSearch; namespace MathNet.Numerics.Optimization { - public class NewtonMinimizer + public sealed class NewtonMinimizer { public double GradientTolerance { get; set; } public int MaximumIterations { get; set; } @@ -47,6 +47,11 @@ namespace MathNet.Numerics.Optimization } public MinimizationResult FindMinimum(IObjectiveFunction objective, Vector initialGuess) + { + return FindMinimum(objective, initialGuess, GradientTolerance, MaximumIterations, UseLineSearch); + } + + public static MinimizationResult FindMinimum(IObjectiveFunction objective, Vector initialGuess, double gradientTolerance, int maxIterations=1000, bool useLineSearch = false) { if (!objective.IsGradientSupported) { @@ -61,7 +66,7 @@ namespace MathNet.Numerics.Optimization // Check that we're not already done objective.EvaluateAt(initialGuess); ValidateGradient(objective); - if (ExitCriteriaSatisfied(objective.Gradient)) + if (objective.Gradient.Norm(2.0) < gradientTolerance) { return new MinimizationResult(objective, 0, ExitCondition.AbsoluteGradient); } @@ -74,7 +79,7 @@ namespace MathNet.Numerics.Optimization int totalLineSearchSteps = 0; int iterationsWithNontrivialLineSearch = 0; bool tmpLineSearch = false; - while (!ExitCriteriaSatisfied(objective.Gradient) && iterations < MaximumIterations) + while (objective.Gradient.Norm(2.0) >= gradientTolerance && iterations < maxIterations) { ValidateHessian(objective); @@ -85,7 +90,7 @@ namespace MathNet.Numerics.Optimization tmpLineSearch = true; } - if (UseLineSearch || tmpLineSearch) + if (useLineSearch || tmpLineSearch) { LineSearchResult result; try @@ -112,19 +117,14 @@ namespace MathNet.Numerics.Optimization iterations += 1; } - if (iterations == MaximumIterations) + if (iterations == maxIterations) { - throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", MaximumIterations)); + throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", maxIterations)); } return new MinimizationWithLineSearchResult(objective, iterations, ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch); } - bool ExitCriteriaSatisfied(Vector gradient) - { - return gradient.Norm(2.0) < GradientTolerance; - } - static void ValidateGradient(IObjectiveFunctionEvaluation eval) { foreach (var x in eval.Gradient) @@ -136,13 +136,7 @@ namespace MathNet.Numerics.Optimization } } - private void ValidateObjective(IObjectiveFunctionEvaluation eval) - { - if (Double.IsNaN(eval.Value) || Double.IsInfinity(eval.Value)) - throw new EvaluationException("Non-finite objective function returned.", eval); - } - - private void ValidateHessian(IObjectiveFunctionEvaluation eval) + static void ValidateHessian(IObjectiveFunctionEvaluation eval) { for (int ii = 0; ii < eval.Hessian.RowCount; ++ii) { diff --git a/src/UnitTests/OptimizationTests/NewtonMinimizerTests.cs b/src/UnitTests/OptimizationTests/NewtonMinimizerTests.cs index 6abb04de..7cdf65f5 100644 --- a/src/UnitTests/OptimizationTests/NewtonMinimizerTests.cs +++ b/src/UnitTests/OptimizationTests/NewtonMinimizerTests.cs @@ -198,9 +198,8 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests public void Mgh_Tests(TestFunctions.TestCase test_case) { var obj = new MghObjectiveFunction(test_case.Function, true, true); - var solver = new NewtonMinimizer(1e-8, 1000, useLineSearch: false); - var result = solver.FindMinimum(obj, test_case.InitialGuess); + var result = NewtonMinimizer.FindMinimum(obj, test_case.InitialGuess, 1e-8, 1000, useLineSearch: false); if (test_case.MinimizingPoint != null) {