From 0eef7f093beb070b963b0a6157aff3336bf7b547 Mon Sep 17 00:00:00 2001 From: Scott Stephens Date: Sat, 24 Sep 2016 15:02:22 -0500 Subject: [PATCH] Optimization: Add MGH tests to Nelder-Mead algo --- .../NelderMeadSimplexTests.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/UnitTests/OptimizationTests/NelderMeadSimplexTests.cs b/src/UnitTests/OptimizationTests/NelderMeadSimplexTests.cs index 64ba24db..b01bfc32 100644 --- a/src/UnitTests/OptimizationTests/NelderMeadSimplexTests.cs +++ b/src/UnitTests/OptimizationTests/NelderMeadSimplexTests.cs @@ -30,8 +30,12 @@ using MathNet.Numerics.LinearAlgebra.Double; using MathNet.Numerics.Optimization; +using MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions; using NUnit.Framework; using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; namespace MathNet.Numerics.UnitTests.OptimizationTests { @@ -65,5 +69,64 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests 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)); } + + private class MghTestCaseEnumerator : IEnumerable + { + private static readonly string[] _ignore_list = + { + "Meyer fun (MGH #10) unbounded", + }; + + private static bool in_ignore_list(string test_name) + { + return _ignore_list.Contains(test_name); + } + + public IEnumerator GetEnumerator() + { + return + RosenbrockFunction2.TestCases + .Concat(BealeFunction.TestCases) + .Concat(HelicalValleyFunction.TestCases) + .Concat(MeyerFunction.TestCases) + .Concat(PowellSingularFunction.TestCases) + .Concat(WoodFunction.TestCases) + .Concat(BrownAndDennisFunction.TestCases) + .Where(x => x.IsUnbounded) + .Select(x => new TestCaseData(x) + .SetName(x.FullName) + .IgnoreIf(in_ignore_list(x.FullName), "Algo error, not implementation error") + ) + .GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } + + [Test] + [TestCaseSource(typeof(MghTestCaseEnumerator))] + public void Mgh_Tests(TestFunctions.TestCase test_case) + { + var obj = new MghObjectiveFunction(test_case.Function, true, true); + var solver = new NelderMeadSimplex(1e-8, 1000); + + var result = solver.FindMinimum(obj, test_case.InitialGuess); + + if (test_case.MinimizingPoint != null) + { + Assert.That((result.MinimizingPoint - test_case.MinimizingPoint).L2Norm(), Is.LessThan(1e-3)); + } + + var val1 = result.FunctionInfoAtMinimum.Value; + var val2 = test_case.MinimalValue; + var abs_min = Math.Min(Math.Abs(val1), Math.Abs(val2)); + var abs_err = Math.Abs(val1 - val2); + var rel_err = abs_err / abs_min; + var success = (abs_min <= 1 && abs_err < 1e-3) || (abs_min > 1 && rel_err < 1e-3); + Assert.That(success, "Minimal function value is not as expected."); + } } }