From 83d609727df58cb71cb92bf43057054bde6b21f7 Mon Sep 17 00:00:00 2001 From: Tom McTiernan Date: Wed, 2 Oct 2019 14:16:12 +0100 Subject: [PATCH] Detect early completion in BfgsBMinimizer --- .../OptimizationTests/BfgsBMinimizerTests.cs | 36 +++++++++++++++++++ src/Numerics/Optimization/BfgsBMinimizer.cs | 8 ++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/Numerics.Tests/OptimizationTests/BfgsBMinimizerTests.cs b/src/Numerics.Tests/OptimizationTests/BfgsBMinimizerTests.cs index fd9be504..e98582f6 100644 --- a/src/Numerics.Tests/OptimizationTests/BfgsBMinimizerTests.cs +++ b/src/Numerics.Tests/OptimizationTests/BfgsBMinimizerTests.cs @@ -121,6 +121,42 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests Assert.That(Math.Abs(result.MinimizingPoint[1] - RosenbrockFunction.Minimum[1]), Is.LessThan(1e-3)); } + [Test] + public void FindMinimum_Quadratic() + { + var obj = ObjectiveFunction.Gradient( + x => x[0] * x[0] + x[1] * x[1], + x => new DenseVector(new[] {2 * x[0], 2 * x[1]}) + ); + var solver = new BfgsBMinimizer(1e-5, 1e-5, 1e-5, maximumIterations: 1000); + var lowerBound = new DenseVector(new[] {-1.0, -1.0}); + var upperBound = new DenseVector(new[] {2.0, 2.0}); + var initialGuess = new DenseVector(new[] {1.5, 1.5}); + + var result = solver.FindMinimum(obj, lowerBound, upperBound, initialGuess); + + Assert.That(Math.Abs(result.MinimizingPoint[0] - 0.0), Is.LessThan(1e-3)); + Assert.That(Math.Abs(result.MinimizingPoint[1] - 0.0), Is.LessThan(1e-3)); + } + + [Test] + public void FindMinimum_Quadratic_TwoBoundaries() + { + var obj = ObjectiveFunction.Gradient( + x => x[0] * x[0] + x[1] * x[1], + x => new DenseVector(new[] {2 * x[0], 2 * x[1]}) + ); + var solver = new BfgsBMinimizer(1e-5, 1e-5, 1e-5, maximumIterations: 1000); + var lowerBound = new DenseVector(new[] {1.0, 1.0}); + var upperBound = new DenseVector(new[] {2.0, 2.0}); + var initialGuess = new DenseVector(new[] {1.5, 1.5}); + + var result = solver.FindMinimum(obj, lowerBound, upperBound, initialGuess); + + Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); + Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); + } + [Test] public void FindMinimum_Rosenbrock_MinimumGreateerOrEqualToLowerBoundary() { diff --git a/src/Numerics/Optimization/BfgsBMinimizer.cs b/src/Numerics/Optimization/BfgsBMinimizer.cs index 524f7f08..a1f79d96 100644 --- a/src/Numerics/Optimization/BfgsBMinimizer.cs +++ b/src/Numerics/Optimization/BfgsBMinimizer.cs @@ -74,7 +74,7 @@ namespace MathNet.Numerics.Optimization ValidateGradientAndObjective(objective); // Check that we're not already done - ExitCondition currentExitCondition = ExitCriteriaSatisfied(objective, null, 0); + var currentExitCondition = ExitCriteriaSatisfied(objective, null, 0); if (currentExitCondition != ExitCondition.None) return new MinimizationResult(objective, 0, currentExitCondition); @@ -140,6 +140,12 @@ namespace MathNet.Numerics.Optimization var previousPoint = objective.Fork(); var candidatePoint = lineSearchResult.FunctionInfoAtMinimum; + + // Check that we're not done + currentExitCondition = ExitCriteriaSatisfied(candidatePoint, previousPoint, 0); + if (currentExitCondition != ExitCondition.None) + return new MinimizationResult(candidatePoint, 0, currentExitCondition); + var gradient = candidatePoint.Gradient; var step = candidatePoint.Point - initialGuess;