diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index 7e7ca7e5..78035dd0 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -264,6 +264,7 @@ + diff --git a/src/Numerics/Optimization/GoldenSectionMinimizer.cs b/src/Numerics/Optimization/GoldenSectionMinimizer.cs index 6ce12c2d..018dd70a 100644 --- a/src/Numerics/Optimization/GoldenSectionMinimizer.cs +++ b/src/Numerics/Optimization/GoldenSectionMinimizer.cs @@ -13,7 +13,7 @@ namespace MathNet.Numerics.Optimization MaximumIterations = maxIterations; } - public MinimizationResult FindMinimum(IObjectiveFunction1D objective, double lowerBound, double upperBound) + public MinimizationResult1D FindMinimum(IObjectiveFunction1D objective, double lowerBound, double upperBound) { double middlePointX = lowerBound + (upperBound - lowerBound) / (1 + Constants.GoldenRatio); IEvaluation1D lower = objective.Evaluate(lowerBound); @@ -37,19 +37,29 @@ namespace MathNet.Numerics.Optimization var test = objective.Evaluate(testX); ValueChecker(test.Value, testX); - if (test.Value > middle.Value) + if (test.Point < middle.Point) { - if (test.Point < middle.Point) + if (test.Value > middle.Value) + { lower = test; + } else - upper = test; + { + upper = middle; + middle = test; + } } else { - if (test.Point < middle.Point) - upper = middle; + if (test.Value > middle.Value) + { + upper = test; + } else + { lower = middle; + middle = test; + } } iterations += 1; @@ -58,7 +68,7 @@ namespace MathNet.Numerics.Optimization if (iterations == MaximumIterations) throw new MaximumIterationsException("Max iterations reached."); - return null; + return new MinimizationResult1D(middle, iterations, MinimizationResult.ExitCondition.BoundTolerance); } private void ValueChecker(double value, double point) diff --git a/src/Numerics/Optimization/MinimizationResult1D.cs b/src/Numerics/Optimization/MinimizationResult1D.cs new file mode 100644 index 00000000..c1e6f65a --- /dev/null +++ b/src/Numerics/Optimization/MinimizationResult1D.cs @@ -0,0 +1,17 @@ +namespace MathNet.Numerics.Optimization +{ + public class MinimizationResult1D + { + public double MinimizingPoint { get { return FunctionInfoAtMinimum.Point; } } + public IEvaluation1D FunctionInfoAtMinimum { get; private set; } + public int Iterations { get; private set; } + public MinimizationResult.ExitCondition ReasonForExit { get; private set; } + + public MinimizationResult1D(IEvaluation1D functionInfo, int iterations, MinimizationResult.ExitCondition reasonForExit) + { + FunctionInfoAtMinimum = functionInfo; + Iterations = iterations; + ReasonForExit = reasonForExit; + } + } +} diff --git a/src/UnitTests/OptimizationTests/TestBfgsMinimizer.cs b/src/UnitTests/OptimizationTests/TestBfgsMinimizer.cs index 851d30ee..dfb8cced 100644 --- a/src/UnitTests/OptimizationTests/TestBfgsMinimizer.cs +++ b/src/UnitTests/OptimizationTests/TestBfgsMinimizer.cs @@ -12,7 +12,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests public void FindMinimum_Rosenbrock_Easy() { var obj = ObjectiveFunction.Gradient(RosenbrockFunction.Value, RosenbrockFunction.Gradient); - var solver = new BfgsMinimizer(1e-5, 1000); + var solver = new BfgsMinimizer(1e-5, 1e-5, 1000); var result = solver.FindMinimum(obj, new DenseVector(new[] { 1.2, 1.2 })); Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); @@ -23,7 +23,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests public void FindMinimum_Rosenbrock_Hard() { var obj = ObjectiveFunction.Gradient(RosenbrockFunction.Value, RosenbrockFunction.Gradient); - var solver = new BfgsMinimizer(1e-5, 1000); + var solver = new BfgsMinimizer(1e-5, 1e-5, 1000); var result = solver.FindMinimum(obj, new DenseVector(new[] { -1.2, 1.0 })); Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); @@ -34,7 +34,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests public void FindMinimum_Rosenbrock_Overton() { var obj = ObjectiveFunction.Gradient(RosenbrockFunction.Value, RosenbrockFunction.Gradient); - var solver = new BfgsMinimizer(1e-5, 1000); + var solver = new BfgsMinimizer(1e-5, 1e-5, 1000); var result = solver.FindMinimum(obj, new DenseVector(new[] { -0.9, -0.5 })); Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3)); diff --git a/src/UnitTests/OptimizationTests/TestConjugateGradientMinimizer.cs b/src/UnitTests/OptimizationTests/TestConjugateGradientMinimizer.cs index 083e56b4..bd1927e5 100644 --- a/src/UnitTests/OptimizationTests/TestConjugateGradientMinimizer.cs +++ b/src/UnitTests/OptimizationTests/TestConjugateGradientMinimizer.cs @@ -8,7 +8,6 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests [TestFixture] public class TestConjugateGradientMinimizer { - [Test] public void FindMinimum_Rosenbrock_Easy() { diff --git a/src/UnitTests/OptimizationTests/TestGoldenSectionMinimizer.cs b/src/UnitTests/OptimizationTests/TestGoldenSectionMinimizer.cs new file mode 100644 index 00000000..cd269406 --- /dev/null +++ b/src/UnitTests/OptimizationTests/TestGoldenSectionMinimizer.cs @@ -0,0 +1,32 @@ +using System; +using MathNet.Numerics.Optimization; +using NUnit.Framework; + +namespace MathNet.Numerics.UnitTests.OptimizationTests +{ + [TestFixture] + public class TestGoldenSectionMinimizer + { + [Test] + public void Test_Works() + { + var algorithm = new GoldenSectionMinimizer(1e-5, 1000); + var f1 = new Func(x => (x - 3)*(x - 3)); + var obj = new SimpleObjectiveFunction1D(f1); + var r1 = algorithm.FindMinimum(obj, -100, 100); + + Assert.That(Math.Abs(r1.MinimizingPoint - 3.0), Is.LessThan(1e-4)); + } + + [Test] + public void Test_ExpansionWorks() + { + var algorithm = new GoldenSectionMinimizer(1e-5, 1000); + var f1 = new Func(x => (x - 3) * (x - 3)); + var obj = new SimpleObjectiveFunction1D(f1); + var r1 = algorithm.FindMinimum(obj, -5, 5); + + Assert.That(Math.Abs(r1.MinimizingPoint - 3.0), Is.LessThan(1e-4)); + } + } +} \ No newline at end of file diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index 16a7a82f..608647a0 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -368,6 +368,7 @@ +