committed by
GitHub
26 changed files with 2335 additions and 50 deletions
@ -0,0 +1,100 @@ |
|||||
|
using System; |
||||
|
using MathNet.Numerics.LinearAlgebra.Double; |
||||
|
using MathNet.Numerics.Optimization; |
||||
|
using NUnit.Framework; |
||||
|
using MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions; |
||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests |
||||
|
{ |
||||
|
[TestFixture] |
||||
|
public class ConjugateGradientMinimizerTests |
||||
|
{ |
||||
|
[Test] |
||||
|
public void FindMinimum_Rosenbrock_Easy() |
||||
|
{ |
||||
|
var obj = ObjectiveFunction.Gradient(RosenbrockFunction.Value, RosenbrockFunction.Gradient); |
||||
|
var solver = new ConjugateGradientMinimizer(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)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void FindMinimum_Rosenbrock_Hard() |
||||
|
{ |
||||
|
var obj = ObjectiveFunction.Gradient(RosenbrockFunction.Value, RosenbrockFunction.Gradient); |
||||
|
var solver = new ConjugateGradientMinimizer(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)); |
||||
|
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
||||
|
} |
||||
|
|
||||
|
private class MghTestCaseEnumerator : IEnumerable<ITestCaseData> |
||||
|
{ |
||||
|
private static readonly string[] _ignore_list = |
||||
|
{ |
||||
|
"Beale fun (MGH #5) unbounded", |
||||
|
"Meyer fun (MGH #10) unbounded", |
||||
|
"Powell singular fun (MGH #13) unbounded", |
||||
|
"Rosenbrock fun (MGH #1) hard start", |
||||
|
"Rosenbrock fun (MGH #1) Overton start", |
||||
|
}; |
||||
|
|
||||
|
private static bool in_ignore_list(string test_name) |
||||
|
{ |
||||
|
return _ignore_list.Contains(test_name); |
||||
|
} |
||||
|
|
||||
|
public IEnumerator<ITestCaseData> 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 ConjugateGradientMinimizer(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."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using NUnit.Framework; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests |
||||
|
{ |
||||
|
internal static class TestCaseDataExtensions |
||||
|
{ |
||||
|
public static TestCaseData IgnoreIf(this TestCaseData input, bool do_ignore, string reason) |
||||
|
{ |
||||
|
if (do_ignore) |
||||
|
return input.Ignore(reason); |
||||
|
else |
||||
|
return input; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,33 +0,0 @@ |
|||||
using System; |
|
||||
using MathNet.Numerics.LinearAlgebra.Double; |
|
||||
using MathNet.Numerics.Optimization; |
|
||||
using NUnit.Framework; |
|
||||
|
|
||||
namespace MathNet.Numerics.UnitTests.OptimizationTests |
|
||||
{ |
|
||||
[TestFixture] |
|
||||
public class TestConjugateGradientMinimizer |
|
||||
{ |
|
||||
[Test] |
|
||||
public void FindMinimum_Rosenbrock_Easy() |
|
||||
{ |
|
||||
var obj = ObjectiveFunction.Gradient(RosenbrockFunction.Value, RosenbrockFunction.Gradient); |
|
||||
var solver = new ConjugateGradientMinimizer(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)); |
|
||||
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
|
||||
} |
|
||||
|
|
||||
[Test] |
|
||||
public void FindMinimum_Rosenbrock_Hard() |
|
||||
{ |
|
||||
var obj = ObjectiveFunction.Gradient(RosenbrockFunction.Value, RosenbrockFunction.Gradient); |
|
||||
var solver = new ConjugateGradientMinimizer(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)); |
|
||||
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,54 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
using MathNet.Numerics.Optimization; |
||||
|
using MathNet.Numerics.Optimization.ObjectiveFunctions; |
||||
|
using MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions; |
||||
|
using MathNet.Numerics.LinearAlgebra.Double; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests |
||||
|
{ |
||||
|
public class MghObjectiveFunction : LazyObjectiveFunctionBase |
||||
|
{ |
||||
|
private ITestFunction TestFunction; |
||||
|
|
||||
|
public MghObjectiveFunction(ITestFunction testFunction, bool use_gradient, bool use_hessian) |
||||
|
: base(use_gradient, use_hessian) |
||||
|
{ |
||||
|
this.TestFunction = testFunction; |
||||
|
} |
||||
|
|
||||
|
public override IObjectiveFunction CreateNew() |
||||
|
{ |
||||
|
return new MghObjectiveFunction(this.TestFunction, this.IsGradientSupported, this.IsHessianSupported); |
||||
|
} |
||||
|
|
||||
|
protected override void EvaluateValue() |
||||
|
{ |
||||
|
this.Value = this.TestFunction.SsqValue(this.Point); |
||||
|
} |
||||
|
|
||||
|
protected override void EvaluateGradient() |
||||
|
{ |
||||
|
if (this.IsGradientSupported) |
||||
|
{ |
||||
|
if (this._gradientValue == null) |
||||
|
this.Gradient = new DenseVector(this.TestFunction.ParameterDimension); |
||||
|
this.TestFunction.SsqGradientByRef(this.Point, _gradientValue); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected override void EvaluateHessian() |
||||
|
{ |
||||
|
if (this.IsHessianSupported) |
||||
|
{ |
||||
|
if (this._hessianValue == null) |
||||
|
this.Hessian = new DenseMatrix(this.TestFunction.ParameterDimension, this.TestFunction.ParameterDimension); |
||||
|
this.TestFunction.SsqHessianByRef(this.Point, _hessianValue); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,309 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions; |
||||
|
using NUnit.Framework; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
using System.Collections; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests |
||||
|
{ |
||||
|
[TestFixture] |
||||
|
public class TestFunctionTests |
||||
|
{ |
||||
|
private static IEnumerable<TestFunctions.TestCase> MghCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return Enumerable.Empty<TestFunctions.TestCase>() |
||||
|
.Concat(RosenbrockFunction2.TestCases) |
||||
|
.Concat(BealeFunction.TestCases) |
||||
|
.Concat(HelicalValleyFunction.TestCases) |
||||
|
.Concat(MeyerFunction.TestCases) |
||||
|
.Concat(PowellSingularFunction.TestCases) |
||||
|
.Concat(WoodFunction.TestCases) |
||||
|
.Concat(BrownAndDennisFunction.TestCases); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private class MghCaseEnumerator : IEnumerable<TestCaseData> |
||||
|
{ |
||||
|
public string CategoryName { get; protected set; } |
||||
|
|
||||
|
public MghCaseEnumerator(string category_name) |
||||
|
{ |
||||
|
this.CategoryName = category_name; |
||||
|
} |
||||
|
|
||||
|
public virtual IEnumerator<TestCaseData> GetEnumerator() |
||||
|
{ |
||||
|
return MghCases |
||||
|
.Select(x => |
||||
|
new TestCaseData(x) |
||||
|
.SetName($"{x.FullName} {this.CategoryName}") |
||||
|
).GetEnumerator(); |
||||
|
} |
||||
|
|
||||
|
IEnumerator IEnumerable.GetEnumerator() |
||||
|
{ |
||||
|
return this.GetEnumerator(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
public void Smoke_Construction() |
||||
|
{ |
||||
|
var c = new TestCase() |
||||
|
{ |
||||
|
InitialGuess = new double[] { 1, 2, 3 }, |
||||
|
MinimizingPoint = new double[] { 1, 1, 1 }, |
||||
|
MinimalValue = 0 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private class ValueAtMinimumSource : MghCaseEnumerator |
||||
|
{ |
||||
|
public ValueAtMinimumSource() : base("ValueAtMinimum") { } |
||||
|
|
||||
|
public override IEnumerator<TestCaseData> GetEnumerator() |
||||
|
{ |
||||
|
return MghCases |
||||
|
.Where(x => x.MinimizingPoint != null) |
||||
|
.Select(x => |
||||
|
new TestCaseData(x) |
||||
|
.SetName($"{x.FullName} {this.CategoryName}") |
||||
|
) |
||||
|
.GetEnumerator(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
[TestCaseSource(typeof(ValueAtMinimumSource))] |
||||
|
public void ValueAtMinimum(TestFunctions.TestCase test_case) |
||||
|
{ |
||||
|
if (test_case.MinimizingPoint != null) |
||||
|
{ |
||||
|
var value_at_minimum = test_case.Function.SsqValue(test_case.MinimizingPoint); |
||||
|
Assert.That( |
||||
|
Math.Abs(value_at_minimum - test_case.MinimalValue) < 1e-3, |
||||
|
$"Function value at minimum not as expected." |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private class GradientAtStartSource : MghCaseEnumerator |
||||
|
{ |
||||
|
public GradientAtStartSource() : base("GradientAtStart") { } |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
[TestCaseSource(typeof(GradientAtStartSource))] |
||||
|
public void GradientAtStart(TestFunctions.TestCase test_case) |
||||
|
{ |
||||
|
var a_grad = test_case.Function.SsqGradient(test_case.InitialGuess); |
||||
|
var fd_grad = Vector<double>.Build.Dense(test_case.Function.ParameterDimension, 0.0); |
||||
|
|
||||
|
for (int ii = 0; ii < test_case.Function.ParameterDimension; ++ii) |
||||
|
{ |
||||
|
var h = 1e-6; |
||||
|
|
||||
|
var bump_up = test_case.InitialGuess.Clone(); |
||||
|
bump_up[ii] += h; |
||||
|
var bump_down = test_case.InitialGuess.Clone(); |
||||
|
bump_down[ii] -= h; |
||||
|
|
||||
|
var up_val = test_case.Function.SsqValue(bump_up); |
||||
|
var down_val = test_case.Function.SsqValue(bump_down); |
||||
|
|
||||
|
fd_grad[ii] = 0.5 * (up_val - down_val) / h; |
||||
|
} |
||||
|
|
||||
|
for (int ii = 0; ii < test_case.Function.ParameterDimension; ++ii) |
||||
|
{ |
||||
|
var val1 = a_grad[ii]; |
||||
|
var val2 = fd_grad[ii]; |
||||
|
var min_abs_val = Math.Min(Math.Abs(val1), Math.Abs(val2)); |
||||
|
if (min_abs_val <= 1) |
||||
|
Assert.That(Math.Abs(val1 - val2) < 1e-3, $"Problem with gradient value at start point."); |
||||
|
else |
||||
|
Assert.That(Math.Abs(val1 - val2) / min_abs_val < 1e-3, $"Problem with gradient value at start point."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private class HessianAtStartSource : MghCaseEnumerator |
||||
|
{ |
||||
|
public HessianAtStartSource() : base("HessianAtStart") { } |
||||
|
|
||||
|
public override IEnumerator<TestCaseData> GetEnumerator() |
||||
|
{ |
||||
|
return MghCases |
||||
|
.Where(x => x.MinimizingPoint != null) |
||||
|
.Select(x => |
||||
|
new TestCaseData(x) |
||||
|
.SetName($"{x.FullName} {this.CategoryName}") |
||||
|
) |
||||
|
.GetEnumerator(); |
||||
|
} |
||||
|
} |
||||
|
[Test] |
||||
|
[TestCaseSource(typeof(HessianAtStartSource))] |
||||
|
public void HessianAtStart(TestFunctions.TestCase test_case) |
||||
|
{ |
||||
|
var a_hess = test_case.Function.SsqHessian(test_case.InitialGuess); |
||||
|
var fd_hess = Matrix<double>.Build.Dense(test_case.Function.ParameterDimension, test_case.Function.ParameterDimension); |
||||
|
for (int ii = 0; ii < test_case.Function.ParameterDimension; ++ii) |
||||
|
{ |
||||
|
for (int jj = 0; jj < test_case.Function.ParameterDimension; ++jj) |
||||
|
{ |
||||
|
var h1 = 1e-3 * Math.Max(1.0, Math.Abs(test_case.InitialGuess[ii])); |
||||
|
var h2 = 1e-3 * Math.Max(1.0, Math.Abs(test_case.InitialGuess[jj])); |
||||
|
|
||||
|
var bump_uu = test_case.InitialGuess.Clone(); |
||||
|
bump_uu[ii] += h1; |
||||
|
bump_uu[jj] += h2; |
||||
|
|
||||
|
var bump_dd = test_case.InitialGuess.Clone(); |
||||
|
bump_dd[ii] -= h1; |
||||
|
bump_dd[jj] -= h2; |
||||
|
|
||||
|
var bump_ud = test_case.InitialGuess.Clone(); |
||||
|
bump_ud[ii] += h1; |
||||
|
bump_ud[jj] -= h2; |
||||
|
|
||||
|
var bump_du = test_case.InitialGuess.Clone(); |
||||
|
bump_du[ii] -= h1; |
||||
|
bump_du[jj] += h2; |
||||
|
|
||||
|
var val_uu = test_case.Function.SsqValue(bump_uu); |
||||
|
var val_dd = test_case.Function.SsqValue(bump_dd); |
||||
|
var val_ud = test_case.Function.SsqValue(bump_ud); |
||||
|
var val_du = test_case.Function.SsqValue(bump_du); |
||||
|
|
||||
|
fd_hess[ii, jj] = (val_uu - val_ud + val_dd - val_du) / (4 * h1 * h2); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (int ii = 0; ii < test_case.Function.ParameterDimension; ++ii) |
||||
|
{ |
||||
|
for (int jj = 0; jj < test_case.Function.ParameterDimension; ++jj) |
||||
|
{ |
||||
|
var val1 = fd_hess[ii, jj]; |
||||
|
var val2 = a_hess[ii, jj]; |
||||
|
|
||||
|
var abs_min = Math.Min(Math.Abs(val1), Math.Abs(val2)); |
||||
|
if (abs_min <= 1) |
||||
|
{ |
||||
|
Assert.That(Math.Abs(val1 - val2) < 1e-3, $"Problem with hessian at start point."); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Assert.That(Math.Abs(val1 - val2) / abs_min < 0.05, $"Problem with hessian at start point."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private class ItemGradientAtStartSource : MghCaseEnumerator |
||||
|
{ |
||||
|
public ItemGradientAtStartSource() : base("ItemGradientAtStart") { } |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
[TestCaseSource(typeof(ItemGradientAtStartSource))] |
||||
|
public void ItemGradientAtStart(TestFunctions.TestCase test_case) |
||||
|
{ |
||||
|
for (var item_index = 0; item_index < test_case.Function.ItemDimension; ++item_index) |
||||
|
{ |
||||
|
|
||||
|
var a_grad = test_case.Function.ItemGradient(test_case.InitialGuess, item_index); |
||||
|
var h = 1e-4; |
||||
|
var fd_grad = Vector<double>.Build.Dense(test_case.Function.ParameterDimension, 0.0); |
||||
|
|
||||
|
for (int ii = 0; ii < test_case.Function.ParameterDimension; ++ii) |
||||
|
{ |
||||
|
var bump_up = test_case.InitialGuess.Clone(); |
||||
|
bump_up[ii] += h; |
||||
|
var bump_down = test_case.InitialGuess.Clone(); |
||||
|
bump_down[ii] -= h; |
||||
|
|
||||
|
var up_val = test_case.Function.ItemValue(bump_up, item_index); |
||||
|
var down_val = test_case.Function.ItemValue(bump_down, item_index); |
||||
|
|
||||
|
fd_grad[ii] = 0.5 * (up_val - down_val) / h; |
||||
|
} |
||||
|
|
||||
|
for (int ii = 0; ii < test_case.Function.ParameterDimension; ++ii) |
||||
|
{ |
||||
|
Assert.That(Math.Abs(fd_grad[ii] - a_grad[ii]) < 1e-3, $"Failed for parameter {ii}"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private class ItemHessianAtStartSource : MghCaseEnumerator |
||||
|
{ |
||||
|
public ItemHessianAtStartSource() : base("ItemHessianAtStart") { } |
||||
|
} |
||||
|
|
||||
|
[Test] |
||||
|
[TestCaseSource(typeof(ItemHessianAtStartSource))] |
||||
|
public void ItemHessianAtStart(TestFunctions.TestCase test_case) |
||||
|
{ |
||||
|
for (var item_index = 0; item_index < test_case.Function.ItemDimension; ++item_index) |
||||
|
{ |
||||
|
var a_hess = test_case.Function.ItemHessian(test_case.InitialGuess, item_index); |
||||
|
var h = 1e-4; |
||||
|
var fd_hess = Matrix<double>.Build.Dense(test_case.Function.ParameterDimension, test_case.Function.ParameterDimension); |
||||
|
for (int ii = 0; ii < test_case.Function.ParameterDimension; ++ii) |
||||
|
{ |
||||
|
for (int jj = 0; jj < test_case.Function.ParameterDimension; ++jj) |
||||
|
{ |
||||
|
var bump_uu = test_case.InitialGuess.Clone(); |
||||
|
bump_uu[ii] += h; |
||||
|
bump_uu[jj] += h; |
||||
|
|
||||
|
var bump_dd = test_case.InitialGuess.Clone(); |
||||
|
bump_dd[ii] -= h; |
||||
|
bump_dd[jj] -= h; |
||||
|
|
||||
|
var bump_ud = test_case.InitialGuess.Clone(); |
||||
|
bump_ud[ii] += h; |
||||
|
bump_ud[jj] -= h; |
||||
|
|
||||
|
var bump_du = test_case.InitialGuess.Clone(); |
||||
|
bump_du[ii] -= h; |
||||
|
bump_du[jj] += h; |
||||
|
|
||||
|
var val_uu = test_case.Function.ItemValue(bump_uu, item_index); |
||||
|
var val_dd = test_case.Function.ItemValue(bump_dd, item_index); |
||||
|
var val_ud = test_case.Function.ItemValue(bump_ud, item_index); |
||||
|
var val_du = test_case.Function.ItemValue(bump_du, item_index); |
||||
|
|
||||
|
fd_hess[ii, jj] = (val_uu - val_ud + val_dd - val_du) / (4 * h * h); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (int ii = 0; ii < test_case.Function.ParameterDimension; ++ii) |
||||
|
{ |
||||
|
for (int jj = 0; jj < test_case.Function.ParameterDimension; ++jj) |
||||
|
{ |
||||
|
var val1 = fd_hess[ii, jj]; |
||||
|
var val2 = a_hess[ii, jj]; |
||||
|
|
||||
|
var abs_min = Math.Min(Math.Abs(val1), Math.Abs(val2)); |
||||
|
if (abs_min <= 1) |
||||
|
{ |
||||
|
Assert.That(Math.Abs(val1 - val2) < 1e-3, $"Problem with hessian at start point."); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Assert.That(Math.Abs(val1 - val2) / abs_min < 0.05, $"Problem with hessian at start point."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,125 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public abstract class BaseTestFunction : ITestFunction |
||||
|
{ |
||||
|
public abstract string Description { get; } |
||||
|
public abstract int ParameterDimension { get; } |
||||
|
public abstract int ItemDimension { get; } |
||||
|
|
||||
|
public abstract double ItemValue(Vector<double> x, int itemIndex); |
||||
|
public abstract void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output); |
||||
|
public abstract void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output); |
||||
|
|
||||
|
public virtual Vector<double> ItemGradient(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
var output = new LinearAlgebra.Double.DenseVector(this.ParameterDimension); |
||||
|
this.ItemGradientByRef(x, itemIndex, output); |
||||
|
return output; |
||||
|
} |
||||
|
|
||||
|
public virtual Matrix<double> ItemHessian(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
var output = new LinearAlgebra.Double.DenseMatrix(this.ParameterDimension, this.ParameterDimension); |
||||
|
this.ItemHessianByRef(x, itemIndex, output); |
||||
|
return output; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public virtual void JacobianbyRef(Vector<double> x, Matrix<double> output) |
||||
|
{ |
||||
|
for (int ii = 0; ii < this.ItemDimension; ++ii) |
||||
|
{ |
||||
|
var grad = this.ItemGradient(x, ii); |
||||
|
output.SetRow(ii, grad); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public virtual Matrix<double> Jacobian(Vector<double> x) |
||||
|
{ |
||||
|
var output = new LinearAlgebra.Double.DenseMatrix(this.ItemDimension, this.ParameterDimension); |
||||
|
this.JacobianbyRef(x, output); |
||||
|
return output; |
||||
|
} |
||||
|
|
||||
|
public virtual void SsqGradientByRef(Vector<double> x, Vector<double> output) |
||||
|
{ |
||||
|
if (output.Count != this.ParameterDimension) |
||||
|
throw new ArgumentException($"Output vector must match parameter dimension of function; expected {this.ParameterDimension}, got {output.Count}."); |
||||
|
|
||||
|
for (int jj = 0; jj < this.ParameterDimension; ++jj) |
||||
|
output[jj] = 0.0; |
||||
|
var tmp_grad = new LinearAlgebra.Double.DenseVector(this.ParameterDimension); |
||||
|
double tmp_value = 0.0; |
||||
|
|
||||
|
for (int ii = 0; ii < this.ItemDimension; ++ii) |
||||
|
{ |
||||
|
tmp_value = this.ItemValue(x, ii); |
||||
|
this.ItemGradientByRef(x, ii, tmp_grad); |
||||
|
for (int jj = 0; jj < this.ParameterDimension; ++jj) |
||||
|
output[jj] += 2 * tmp_value * tmp_grad[jj]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public virtual Vector<double> SsqGradient(Vector<double> x) |
||||
|
{ |
||||
|
var output = new LinearAlgebra.Double.DenseVector(this.ParameterDimension); |
||||
|
this.SsqGradientByRef(x, output); |
||||
|
return output; |
||||
|
} |
||||
|
|
||||
|
public virtual void SsqHessianByRef(Vector<double> x, Matrix<double> output) |
||||
|
{ |
||||
|
if (output.RowCount != this.ParameterDimension || output.ColumnCount != this.ParameterDimension) |
||||
|
throw new ArgumentException($"Output matrix must match parameter dimension of function; expected {this.ParameterDimension}x{this.ParameterDimension}, got {output.RowCount}x{output.ColumnCount}."); |
||||
|
|
||||
|
for (int ii = 0; ii < this.ParameterDimension; ++ii) |
||||
|
for (int jj = 0; jj < this.ParameterDimension; ++jj) |
||||
|
output[ii,jj] = 0.0; |
||||
|
|
||||
|
var tmp_grad = new LinearAlgebra.Double.DenseVector(this.ParameterDimension); |
||||
|
var tmp_hess = new LinearAlgebra.Double.DenseMatrix(this.ParameterDimension, this.ParameterDimension); |
||||
|
double tmp_value = 0.0; |
||||
|
|
||||
|
for (int ii = 0; ii < this.ItemDimension; ++ii) |
||||
|
{ |
||||
|
tmp_value = this.ItemValue(x, ii); |
||||
|
this.ItemGradientByRef(x, ii, tmp_grad); |
||||
|
this.ItemHessianByRef(x, ii, tmp_hess); |
||||
|
for (int jj = 0; jj < this.ParameterDimension; ++jj) |
||||
|
{ |
||||
|
for (int kk = 0; kk < this.ParameterDimension; ++kk) |
||||
|
{ |
||||
|
var increment = 2 * (tmp_value * tmp_hess[jj, kk] + tmp_grad[jj] * tmp_grad[kk]); |
||||
|
output[jj, kk] += increment; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public virtual Matrix<double> SsqHessian(Vector<double> x) |
||||
|
{ |
||||
|
var output = new LinearAlgebra.Double.DenseMatrix(this.ParameterDimension, this.ParameterDimension); |
||||
|
this.SsqHessianByRef(x, output); |
||||
|
return output; |
||||
|
} |
||||
|
|
||||
|
public virtual double SsqValue(Vector<double> x) |
||||
|
{ |
||||
|
double ssq = 0.0; |
||||
|
for (int ii = 0; ii < this.ItemDimension; ++ii) |
||||
|
{ |
||||
|
var tmp = this.ItemValue(x, ii); |
||||
|
ssq += tmp * tmp; |
||||
|
} |
||||
|
return ssq; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,97 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class BealeFunction : BaseTestFunction |
||||
|
{ |
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new BealeFunction(), |
||||
|
InitialGuess = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 3, 0.5 }, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new BealeFunction(), |
||||
|
InitialGuess = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 3, 0.5 }, |
||||
|
LowerBound = new double[] { -1000, -1000}, |
||||
|
UpperBound = new double[] { 1000, 1000}, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new BealeFunction(), |
||||
|
InitialGuess = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 3, 0.5 }, |
||||
|
LowerBound = new double[] { 0.6, 0.5 }, |
||||
|
UpperBound = new double[] { 10, 100 }, |
||||
|
CaseName = "tight bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public BealeFunction() { } |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "Beale fun (MGH #5)"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 3; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
int ii = itemIndex + 1; |
||||
|
output[0] = -1 + Math.Pow(x[1], ii); |
||||
|
output[1] = ii * x[0] * Math.Pow(x[1], ii - 1); |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
int ii = itemIndex + 1; |
||||
|
output[0, 0] = 0; |
||||
|
output[0, 1] = ii * Math.Pow(x[1], ii - 1); |
||||
|
output[1, 0] = ii * Math.Pow(x[1], ii - 1); |
||||
|
output[1, 1] = (ii - 1) * ii * x[0] * Math.Pow(x[1], ii - 2); |
||||
|
} |
||||
|
|
||||
|
private static readonly double[] y = { 1.5, 2.25, 2.625}; |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
int ii = itemIndex + 1; |
||||
|
return y[itemIndex] - x[0] * (1 - Math.Pow(x[1], ii)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,114 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class BrownAndDennisFunction : BaseTestFunction |
||||
|
{ |
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new BrownAndDennisFunction(20), |
||||
|
InitialGuess = new double[] { 25, 5, -5, -1 }, |
||||
|
MinimalValue = 85822.2, |
||||
|
MinimizingPoint = null, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new BrownAndDennisFunction(20), |
||||
|
InitialGuess = new double[] { 25, 5, -5, -1 }, |
||||
|
MinimalValue = 85822.2, |
||||
|
MinimizingPoint = null, |
||||
|
LowerBound = new double[] { -1000, -1000, -1000, -1000 }, |
||||
|
UpperBound = new double[] {1000, 1000, 1000, 1000 }, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new BrownAndDennisFunction(20), |
||||
|
InitialGuess = new double[] { 25, 5, -5, -1 }, |
||||
|
MinimalValue = 0.88860479e5, |
||||
|
MinimizingPoint = null, |
||||
|
LowerBound = new double[] { -10, 0, -100, -20 }, |
||||
|
UpperBound = new double[] { 100, 15, 0, 0.2 }, |
||||
|
CaseName = "tight bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private readonly int _items; |
||||
|
|
||||
|
public BrownAndDennisFunction(int items) |
||||
|
{ |
||||
|
if (items < 4) |
||||
|
throw new ArgumentException("items must be >= 4"); |
||||
|
_items = items; |
||||
|
} |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "Brown & Dennis fun (MGH #16)"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _items; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 4; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
var ii = itemIndex + 1; |
||||
|
var t = ii / 5.0; |
||||
|
output[0] = 2 * (x[0] + t * x[1] - Math.Exp(t)); |
||||
|
output[1] = (2*ii/25.0) * (5 * x[0] + ii * x[1] - 5 * Math.Exp(t)); |
||||
|
output[2] = 2 * (x[2] + x[3] * Math.Sin(t) - Math.Cos(t)); |
||||
|
output[3] = 2 * Math.Sin(t) * (x[2] + Math.Sin(t) * x[3] - Math.Cos(t)); |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
for (int ii = 0; ii < 4; ++ii) |
||||
|
for (int jj = 0; jj < 4; ++jj) |
||||
|
output[ii, jj] = 0; |
||||
|
var i = itemIndex + 1; |
||||
|
var t = i / 5.0; |
||||
|
output[0, 0] = 2; |
||||
|
output[0, 1] = 2 * t; |
||||
|
output[1, 0] = 2 * t; |
||||
|
output[1, 1] = 2 * t * t; |
||||
|
output[2, 2] = 2; |
||||
|
output[2, 3] = 2 * Math.Sin(t); |
||||
|
output[3, 2] = 2 * Math.Sin(t); |
||||
|
output[3, 3] = 2 * Math.Pow(Math.Sin(t), 2); |
||||
|
} |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
var ii = itemIndex + 1; |
||||
|
var t = ii / 5.0; |
||||
|
return Math.Pow(x[0] + t * x[1] - Math.Exp(t), 2.0) + Math.Pow(x[2] + x[3] * Math.Sin(t) - Math.Cos(t), 2); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,131 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class BrownBadlyScaledFunction : BaseTestFunction |
||||
|
{ |
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new BrownBadlyScaledFunction(), |
||||
|
InitialGuess = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 1e6, 2e-6 }, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new BrownBadlyScaledFunction(), |
||||
|
InitialGuess = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 1e6, 2e-6 }, |
||||
|
LowerBound = new double[] { -1e8, -1e8 }, |
||||
|
UpperBound = new double[] { 1e8, 1e8 }, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new BrownBadlyScaledFunction(), |
||||
|
InitialGuess = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0.784e3, |
||||
|
MinimizingPoint = new double[] { 1e6, 2e-6 }, |
||||
|
LowerBound = new double[] { 0, 3e-5 }, |
||||
|
UpperBound = new double[] { 1e6, 100 }, |
||||
|
CaseName = "tight bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public BrownBadlyScaledFunction() { } |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "Brown badly scaled fun (MGH #4)"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 3; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
output[0] = 1; |
||||
|
output[1] = 0; |
||||
|
break; |
||||
|
case 1: |
||||
|
output[0] = 0; |
||||
|
output[1] = 1; |
||||
|
break; |
||||
|
case 2: |
||||
|
output[0] = x[1]; |
||||
|
output[1] = x[0]; |
||||
|
break; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 2"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
case 1: |
||||
|
output[0, 0] = 0; |
||||
|
output[0, 1] = 0; |
||||
|
output[1, 0] = 0; |
||||
|
output[1, 1] = 0; |
||||
|
break; |
||||
|
case 2: |
||||
|
output[0, 0] = 0; |
||||
|
output[0, 1] = 1; |
||||
|
output[1, 0] = 1; |
||||
|
output[1, 1] = 0; |
||||
|
break; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 2"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
return x[0] - 1e6; |
||||
|
case 1: |
||||
|
return x[1] - 2e-6; |
||||
|
case 2: |
||||
|
return x[0] * x[1] - 2; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 2"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,98 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
using DenseVector = MathNet.Numerics.LinearAlgebra.Double.DenseVector; |
||||
|
using DenseMatrix = MathNet.Numerics.LinearAlgebra.Double.DenseMatrix; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class FreudensteinAndRothFunction : BaseTestFunction |
||||
|
{ |
||||
|
|
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new FreudensteinAndRothFunction(), |
||||
|
InitialGuess = new double[] { 0.5, -2 }, |
||||
|
MinimizingPoint = new double[] { 5, 4 }, |
||||
|
MinimalValue = 0, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new FreudensteinAndRothFunction(), |
||||
|
InitialGuess = new double[] { 0.5, -2 }, |
||||
|
MinimizingPoint = new double[] {5, 4}, |
||||
|
MinimalValue = 0, |
||||
|
LowerBound = new double[] { -1000, -1000 }, |
||||
|
UpperBound = new double[] { 1000, 1000}, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override string Description { get { return "Freudenstein & Roth fun (MGH #2)"; } } |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
if (itemIndex == 0) |
||||
|
return -13 + x[0] + ((5 - x[1]) * x[1] - 2) * x[1]; |
||||
|
else |
||||
|
return -29 + x[0] + ((x[1] + 1) * x[1] - 14) * x[1]; |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
if (itemIndex == 0) |
||||
|
{ |
||||
|
output[0] = 1; |
||||
|
output[1] = -2 + (5 - 2 * x[1]) * x[1] + (5 - x[1]) * x[1]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
output[0] = 1; |
||||
|
output[1] = -14 + x[1] * (1 + x[1]) + x[1] * (1 + 2 * x[1]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
if (itemIndex == 0) |
||||
|
{ |
||||
|
output[0, 0] = 0; |
||||
|
output[0, 1] = 0; |
||||
|
output[1, 0] = 0; |
||||
|
output[1, 1] = 10 - 6 * x[1]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
output[0, 0] = 0; |
||||
|
output[0, 1] = 0; |
||||
|
output[1, 0] = 0; |
||||
|
output[1, 1] = 2 + 6 * x[1]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,178 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class HelicalValleyFunction : BaseTestFunction |
||||
|
{ |
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new HelicalValleyFunction(), |
||||
|
InitialGuess = new double[] { -1, 0, 0 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 1, 0, 0 }, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new HelicalValleyFunction(), |
||||
|
InitialGuess = new double[] { -1, 0, 0 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 1, 0, 0 }, |
||||
|
LowerBound = new double[] { -1000, -1000, -1000 }, |
||||
|
UpperBound = new double[] { 1000, 1000, 1000 }, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new HelicalValleyFunction(), |
||||
|
InitialGuess = new double[] { -1, 0, 0 }, |
||||
|
MinimalValue = 0.99042212, |
||||
|
LowerBound = new double[] { -100, -1, -1 }, |
||||
|
UpperBound = new double[] { 0.8, 1, 1 }, |
||||
|
CaseName = "tight bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "Helical valley fun (MGH #7)"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 3; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 3; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
output[0] = -100 * theta10(x[0], x[1]); |
||||
|
output[1] = -100 * theta01(x[0], x[1]); |
||||
|
output[2] = 10; |
||||
|
break; |
||||
|
case 1: |
||||
|
output[0] = (10 * x[0]) / Math.Sqrt(x[0]*x[0] + x[1]*x[1]); |
||||
|
output[1] = (10 * x[1]) / Math.Sqrt(x[0]*x[0] + x[1]*x[1]); |
||||
|
output[2] = 0; |
||||
|
break; |
||||
|
case 2: |
||||
|
output[0] = 0; |
||||
|
output[1] = 0; |
||||
|
output[2] = 1; |
||||
|
break; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 2"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
output[0, 0] = -100 * theta20(x[0], x[1]); |
||||
|
output[0, 1] = -100 * theta11(x[0], x[1]); |
||||
|
output[0, 2] = 0; |
||||
|
output[1, 0] = -100 * theta11(x[0], x[1]); |
||||
|
output[1, 1] = -100 * theta02(x[0], x[1]); |
||||
|
output[1, 2] = 0; |
||||
|
output[2, 0] = 0; |
||||
|
output[2, 1] = 0; |
||||
|
output[2, 2] = 0; |
||||
|
break; |
||||
|
case 1: |
||||
|
output[0, 0] = (10 * x[1]*x[1]) / Math.Pow(x[0]*x[0] + x[1]*x[1],1.5); |
||||
|
output[0, 1] = (-10 * x[0] * x[1]) / Math.Pow(x[0]*x[0] + x[1]*x[1],1.5); |
||||
|
output[0, 2] = 0; |
||||
|
output[1, 0] = (-10 * x[0] * x[1]) / Math.Pow(x[0] * x[0] + x[1] * x[1], 1.5); |
||||
|
output[1, 1] = (10 * x[0]*x[0]) / Math.Pow(x[0] * x[0] + x[1] * x[1], 1.5); |
||||
|
output[1, 2] = 0; |
||||
|
output[2, 0] = 0; |
||||
|
output[2, 1] = 0; |
||||
|
output[2, 2] = 0; |
||||
|
break; |
||||
|
case 2: |
||||
|
for (int ii = 0; ii < 2; ++ii) |
||||
|
for (int jj = 0; jj < 2; ++jj) |
||||
|
output[ii, jj] = 0; |
||||
|
break; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 2"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static double theta(double x1, double x2) |
||||
|
{ |
||||
|
if (x1 >= 0) |
||||
|
return 0.5 * Math.Atan(x2 / x1) / Math.PI; |
||||
|
else |
||||
|
return 0.5 * Math.Atan(x2 / x1) / Math.PI + 0.5; |
||||
|
} |
||||
|
|
||||
|
private static double theta10(double x1, double x2) |
||||
|
{ |
||||
|
return -(x2 / (2 * Math.PI * Math.Pow(x1,2) + 2 * Math.PI * Math.Pow(x2,2))); |
||||
|
} |
||||
|
|
||||
|
private static double theta01(double x1, double x2) |
||||
|
{ |
||||
|
return x1 / (2 * Math.PI * x1*x1 + 2 * Math.PI * x2*x2); |
||||
|
} |
||||
|
|
||||
|
private static double theta20(double x1,double x2) |
||||
|
{ |
||||
|
return (x1 * x2) / (Math.PI * Math.Pow(x1 * x1 + x2 * x2, 2)); |
||||
|
} |
||||
|
|
||||
|
private static double theta11(double x1, double x2) |
||||
|
{ |
||||
|
return (-x1 * x1 + x2 * x2) / (2 * Math.PI * Math.Pow(x1 * x1 + x2 * x2, 2)); |
||||
|
} |
||||
|
|
||||
|
private static double theta02(double x1, double x2) |
||||
|
{ |
||||
|
return -((x1 * x2) / (Math.PI * Math.Pow(x1*x1 + x2*x2, 2))); |
||||
|
} |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
return 10 * (x[2] - 10 * theta(x[0], x[1])); |
||||
|
case 1: |
||||
|
return 10 * (Math.Sqrt(x[0] * x[0] + x[1] * x[1]) - 1); |
||||
|
case 2: |
||||
|
return x[2]; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 2"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
using DenseVector = MathNet.Numerics.LinearAlgebra.Double.DenseVector; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class TestCase |
||||
|
{ |
||||
|
public string CaseName; |
||||
|
public ITestFunction Function; |
||||
|
public DenseVector InitialGuess; |
||||
|
public DenseVector LowerBound; |
||||
|
public DenseVector UpperBound; |
||||
|
public double MinimalValue; |
||||
|
public DenseVector MinimizingPoint; |
||||
|
|
||||
|
public bool IsBounded |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return this.LowerBound != null && this.UpperBound != null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public bool IsUnbounded |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return this.IsUnboundedOverride ?? this.LowerBound == null || this.UpperBound == null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public bool? IsUnboundedOverride; |
||||
|
|
||||
|
public string FullName |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return $"{this.Function.Description} {this.CaseName}"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public interface ITestFunction |
||||
|
{ |
||||
|
string Description { get; } |
||||
|
int ParameterDimension { get; } |
||||
|
int ItemDimension { get; } |
||||
|
|
||||
|
double ItemValue(Vector<double> x, int itemIndex); |
||||
|
Vector<double> ItemGradient(Vector<double> x, int itemIndex); |
||||
|
void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output); |
||||
|
Matrix<double> ItemHessian(Vector<double> x, int itemIndex); |
||||
|
void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output); |
||||
|
|
||||
|
Matrix<double> Jacobian(Vector<double> x); |
||||
|
void JacobianbyRef(Vector<double> x, Matrix<double> output); |
||||
|
|
||||
|
double SsqValue(Vector<double> x); |
||||
|
Vector<double> SsqGradient(Vector<double> x); |
||||
|
void SsqGradientByRef(Vector<double> x, Vector<double> output); |
||||
|
Matrix<double> SsqHessian(Vector<double> x); |
||||
|
void SsqHessianByRef(Vector<double> x, Matrix<double> output); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,102 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class JennrichAndSampsonFunction : BaseTestFunction |
||||
|
{ |
||||
|
private readonly int _m; |
||||
|
|
||||
|
public JennrichAndSampsonFunction(int itemDimension) |
||||
|
{ |
||||
|
if (itemDimension < 2) |
||||
|
throw new ArgumentException("itemDimension must be at least 2."); |
||||
|
_m = itemDimension; |
||||
|
} |
||||
|
|
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new JennrichAndSampsonFunction(10), |
||||
|
InitialGuess = new double[] { 0.3, 0.4 }, |
||||
|
MinimalValue = 124.362, |
||||
|
MinimizingPoint = new double[] { 0.2578, 0.2578 }, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
//yield return new TestCase()
|
||||
|
//{
|
||||
|
// Function = new JennrichAndSampsonFunction(10),
|
||||
|
// LowerBound = new double[] { 0.6, 0.5 },
|
||||
|
// UpperBound = new double[] { 10, 50 },
|
||||
|
// StartPoint = new double[] { 1.0, 1.0 },
|
||||
|
// MinimizingInput = null,
|
||||
|
// MinimizingValue = 0,
|
||||
|
// CaseName = "tight bounds"
|
||||
|
//};
|
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new JennrichAndSampsonFunction(10), |
||||
|
LowerBound = new double[] { -50, -50 }, |
||||
|
UpperBound = new double[] { 50, 50 }, |
||||
|
InitialGuess = new double[] { 0.3, 0.4 }, |
||||
|
MinimizingPoint = null, |
||||
|
MinimalValue = 0, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return $"Jennrich & Sampson fun (MGH #6) (n={this.ItemDimension})"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _m; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
int ii = itemIndex + 1; |
||||
|
output[0] = -(Math.Exp(ii * x[0]) * ii); |
||||
|
output[1] = -(Math.Exp(ii * x[1]) * ii); |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
int ii = itemIndex + 1; |
||||
|
output[0, 0] = -(Math.Exp(ii * x[0]) * ii*ii); |
||||
|
output[0, 1] = 0; |
||||
|
output[1, 0] = 0; |
||||
|
output[1, 1] = -(Math.Exp(ii * x[1]) * ii*ii); |
||||
|
} |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
int ii = itemIndex + 1; |
||||
|
return 2 + 2 * ii - (Math.Exp(ii * x[0]) + Math.Exp(ii * x[1])); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,99 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class MeyerFunction : BaseTestFunction |
||||
|
{ |
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new MeyerFunction(), |
||||
|
InitialGuess = new double[] { 0.02, 4000, 250 }, |
||||
|
MinimalValue = 87.9458, |
||||
|
MinimizingPoint = null, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new MeyerFunction(), |
||||
|
InitialGuess = new double[] { 0.02, 4000, 250 }, |
||||
|
MinimalValue = 87.9458, |
||||
|
MinimizingPoint = null, |
||||
|
LowerBound = new double[] { -1e6, -1e6, -1e6 }, |
||||
|
UpperBound = new double[] { 1e6, 1e6, 1e6 }, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public MeyerFunction() { } |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "Meyer fun (MGH #10)"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 16; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 3; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
int ii = itemIndex + 1; |
||||
|
output[0] = Math.Exp(x[1] / (45.0 + 5 * ii + x[2])); |
||||
|
output[1] = (Math.Exp(x[1] / (45.0 + 5 * ii + x[2])) * x[0]) / (45 + 5 * ii + x[2]); |
||||
|
output[2] = -(Math.Exp(x[1] / (45.0 + 5 * ii + x[2])) * x[0] * x[1]) / Math.Pow(45 + 5 * ii + x[2], 2); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
var ii = itemIndex + 1; |
||||
|
|
||||
|
var t0 = (45.0 + 5 * ii + x[2]); |
||||
|
var t1 = Math.Exp(x[1] / t0); |
||||
|
|
||||
|
output[0, 0] = 0; |
||||
|
output[0, 1] = t1 / t0; |
||||
|
output[0, 2] = -t1 * x[1] / Math.Pow(t0, 2); |
||||
|
output[1, 0] = t1 / t0; |
||||
|
output[1, 1] = t1 * x[0] / Math.Pow(t0, 2); |
||||
|
output[1, 2] = -t1 * x[0] * (t0 + x[1]) / Math.Pow(t0, 3); |
||||
|
output[2, 0] = -t1 * x[1] / Math.Pow(t0, 2); |
||||
|
output[2, 1] = -t1 * x[0] * (t0 + x[1]) / Math.Pow(t0, 3); |
||||
|
output[2, 2] = t1 * x[0] * x[1] * (2*t0 + x[1]) / Math.Pow(t0, 4); |
||||
|
} |
||||
|
|
||||
|
private static readonly double[] y = { 34780, 28610, 23650, 19630, 16370, 13720, 11540, 9744, 8261, 7030, 6005, 5147, 4427, 3820, 3307, 2872 }; |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
var ii = itemIndex + 1; |
||||
|
var t = 45.0 + 5 * ii; |
||||
|
return x[0] * Math.Exp(x[1] / (t + x[2])) - y[itemIndex]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,111 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
using MathNet.Numerics.LinearAlgebra.Double; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class PowellBadlyScaledFunction : BaseTestFunction |
||||
|
{ |
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new PowellBadlyScaledFunction(), |
||||
|
InitialGuess = new double[] { 0, 1 }, |
||||
|
MinimizingPoint = new double[] { 1.098e-5, 9.106 }, |
||||
|
MinimalValue = 0, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new PowellBadlyScaledFunction(), |
||||
|
InitialGuess = new double[] { 0, 1 }, |
||||
|
MinimizingPoint = new double[] { 1.098e-5, 9.106 }, |
||||
|
MinimalValue = 0, |
||||
|
LowerBound = new double[] { -1000, -1000 }, |
||||
|
UpperBound = new double[] { 1000, 1000 }, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new PowellBadlyScaledFunction(), |
||||
|
LowerBound = new double[] { 0, 1 }, |
||||
|
UpperBound = new double[] { 1, 9 }, |
||||
|
InitialGuess = new double[] { 0, 1 }, |
||||
|
MinimalValue = 0.15125900e-9, |
||||
|
CaseName = "tight bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "Powell badly scaled fun (MGH #3)"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
if (itemIndex == 0) |
||||
|
{ |
||||
|
output[0] = 10000 * x[1]; |
||||
|
output[1] = 10000 * x[0]; |
||||
|
} |
||||
|
else if (itemIndex == 1) |
||||
|
{ |
||||
|
output[0] = -Math.Exp(-x[0]); |
||||
|
output[1] = -Math.Exp(-x[1]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
if (itemIndex == 0) |
||||
|
{ |
||||
|
output[0, 0] = 0; |
||||
|
output[0, 1] = 10000; |
||||
|
output[1, 0] = 10000; |
||||
|
output[1, 1] = 0; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
output[0, 0] = Math.Exp(-x[0]); |
||||
|
output[0, 1] = 0; |
||||
|
output[1, 0] = 0; |
||||
|
output[1,1] = Math.Exp(-x[1]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
if (itemIndex == 0) |
||||
|
return 10000.0 * x[0] * x[1] - 1; |
||||
|
else |
||||
|
return Math.Exp(-x[0]) + Math.Exp(-x[1]) - 1.0001; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,141 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class PowellSingularFunction : BaseTestFunction |
||||
|
{ |
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new PowellSingularFunction(), |
||||
|
InitialGuess = new double[] { 3, -1, 0, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] {0,0,0,0}, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new PowellSingularFunction(), |
||||
|
InitialGuess = new double[] { 3, -1, 0, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 0, 0, 0, 0 }, |
||||
|
LowerBound = new double[] {-1000, -1000, -1000, -1000}, |
||||
|
UpperBound = new double[] { 1000, 1000, 1000, 1000 }, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public PowellSingularFunction() { } |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "Powell singular fun (MGH #13)"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 4; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 4; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
output[0] = 1; |
||||
|
output[1] = 10; |
||||
|
output[2] = 0; |
||||
|
output[3] = 0; |
||||
|
break; |
||||
|
case 1: |
||||
|
output[0] = 0; |
||||
|
output[1] = 0; |
||||
|
output[2] = Math.Sqrt(5); |
||||
|
output[3] = -Math.Sqrt(5); |
||||
|
break; |
||||
|
case 2: |
||||
|
output[0] = 0; |
||||
|
output[1] = 2*(x[1]-2*x[2]); |
||||
|
output[2] = -4*x[1] + 8*x[2]; |
||||
|
output[3] = 0; |
||||
|
break; |
||||
|
case 3: |
||||
|
output[0] = 2*Math.Sqrt(10)*(x[0] - x[3]); |
||||
|
output[1] = 0; |
||||
|
output[2] = 0; |
||||
|
output[3] = -2*Math.Sqrt(10)*(x[0] - x[3]); |
||||
|
break; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 3"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
for (int ii = 0; ii < 4; ++ii) |
||||
|
for (int jj = 0; jj < 4; ++jj) |
||||
|
output[ii, jj] = 0; |
||||
|
switch(itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
case 1: |
||||
|
break; |
||||
|
case 2: |
||||
|
output[1, 1] = 2; |
||||
|
output[1, 2] = -4; |
||||
|
output[2, 1] = -4; |
||||
|
output[2, 2] = 8; |
||||
|
break; |
||||
|
case 3: |
||||
|
output[0, 0] = 2 * Math.Sqrt(10); |
||||
|
output[0, 3] = -2 * Math.Sqrt(10); |
||||
|
output[3, 0] = -2 * Math.Sqrt(10); |
||||
|
output[3, 3] = 2 * Math.Sqrt(10); |
||||
|
break; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 3"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
return x[0] + 10 * x[1]; |
||||
|
case 1: |
||||
|
return Math.Sqrt(5) * (x[2] - x[3]); |
||||
|
case 2: |
||||
|
return Math.Pow(x[1] - 2 * x[2], 2); |
||||
|
case 3: |
||||
|
return Math.Sqrt(10.0) * Math.Pow(x[0] - x[3], 2); |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 3"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,156 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class RosenbrockFunction2 : BaseTestFunction |
||||
|
{ |
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new RosenbrockFunction2(), |
||||
|
InitialGuess = new double[] { -1.2, 1 }, |
||||
|
MinimizingPoint = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
LowerBound = new double[] { -1000, -1000 }, |
||||
|
UpperBound = new double[] { 1000, 1000 }, |
||||
|
CaseName = "hard start", |
||||
|
IsUnboundedOverride = true |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new RosenbrockFunction2(), |
||||
|
InitialGuess = new double[] { 1.2, 1.2 }, |
||||
|
MinimizingPoint = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
LowerBound = new double[] { -5, -5 }, |
||||
|
UpperBound = new double[] { 5, 5 }, |
||||
|
CaseName = "easy start" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new RosenbrockFunction2(), |
||||
|
InitialGuess = new double[] { -0.9, -0.5 }, |
||||
|
MinimizingPoint = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
LowerBound = new double[] { -5, -5 }, |
||||
|
UpperBound = new double[] { 5, 5 }, |
||||
|
CaseName = "Overton start", |
||||
|
IsUnboundedOverride = true |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new RosenbrockFunction2(), |
||||
|
InitialGuess = new double[] { 1.2, 1.2 }, |
||||
|
MinimizingPoint = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
LowerBound = new double[] { 1, -5 }, |
||||
|
UpperBound = new double[] { 5, 5 }, |
||||
|
CaseName = "easy one active bound" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new RosenbrockFunction2(), |
||||
|
InitialGuess = new double[] { 1.2, 1.2 }, |
||||
|
MinimizingPoint = new double[] { 1, 1 }, |
||||
|
MinimalValue = 0, |
||||
|
LowerBound = new double[] { 1, 1 }, |
||||
|
UpperBound = new double[] { 5, 5 }, |
||||
|
CaseName = "easy two active bounds" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new RosenbrockFunction2(), |
||||
|
InitialGuess = new double[] { 2.5, 2.5 }, |
||||
|
MinimizingPoint = new double[] { 2, 4 }, |
||||
|
MinimalValue = 1, |
||||
|
LowerBound = new double[] { 2, 2 }, |
||||
|
UpperBound = new double[] { 5, 5 }, |
||||
|
CaseName = "min on lower bound, not local" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new RosenbrockFunction2(), |
||||
|
InitialGuess = new double[] { -0.9, -0.5 }, |
||||
|
MinimizingPoint = new double[] { 0.5, 0.25 }, |
||||
|
MinimalValue = 0.25, |
||||
|
LowerBound = new double[] { -2, -2 }, |
||||
|
UpperBound = new double[] { 0.5, 0.5 }, |
||||
|
CaseName = "min on upper bound, not local" |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
||||
|
public RosenbrockFunction2() { } |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "Rosenbrock fun (MGH #1)"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 2; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
if (itemIndex == 0) |
||||
|
{ |
||||
|
output[0] = -20 * x[0]; |
||||
|
output[1] = 10; |
||||
|
} else |
||||
|
{ |
||||
|
output[0] = -1; |
||||
|
output[1] = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
if (itemIndex == 0) |
||||
|
{ |
||||
|
output[0, 0] = -20; |
||||
|
output[0, 1] = 0; |
||||
|
output[1, 0] = 0; |
||||
|
output[1, 1] = 0; |
||||
|
} else |
||||
|
{ |
||||
|
output[0, 0] = 0; |
||||
|
output[0, 1] = 0; |
||||
|
output[1, 0] = 0; |
||||
|
output[1, 1] = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
if (itemIndex == 0) |
||||
|
return 10 * (x[1] - x[0] * x[0]); |
||||
|
else |
||||
|
return 1 - x[0]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,164 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using MathNet.Numerics.LinearAlgebra; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.OptimizationTests.TestFunctions |
||||
|
{ |
||||
|
public class WoodFunction : BaseTestFunction |
||||
|
{ |
||||
|
public static IEnumerable<TestCase> TestCases |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new WoodFunction(), |
||||
|
InitialGuess = new double[] { -3, -1, -3, -1 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 1, 1, 1, 1 }, |
||||
|
CaseName = "unbounded" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new WoodFunction(), |
||||
|
InitialGuess = new double[] { -3, -1, -3, -1 }, |
||||
|
MinimalValue = 0, |
||||
|
MinimizingPoint = new double[] { 1, 1, 1, 1 }, |
||||
|
LowerBound = new double[] { -1000, -1000, -1000, -1000 }, |
||||
|
UpperBound = new double[] { 1000, 1000, 1000, 1000 }, |
||||
|
CaseName = "loose bounds" |
||||
|
}; |
||||
|
yield return new TestCase() |
||||
|
{ |
||||
|
Function = new WoodFunction(), |
||||
|
InitialGuess = new double[] { -3, -1, -3, -1 }, |
||||
|
MinimalValue = 1.5567008, |
||||
|
MinimizingPoint = null, |
||||
|
LowerBound = new double[] { -100, -100, -100, -100 }, |
||||
|
UpperBound = new double[] { 0, 10, 100, 100 }, |
||||
|
CaseName = "tight bounds" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public WoodFunction() { } |
||||
|
|
||||
|
public override string Description |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "Wood fun (MGH #14)"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ItemDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 6; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override int ParameterDimension |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 4; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemGradientByRef(Vector<double> x, int itemIndex, Vector<double> output) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
output[0] = -20 * x[0]; |
||||
|
output[1] = 10; |
||||
|
output[2] = 0; |
||||
|
output[3] = 0; |
||||
|
break; |
||||
|
case 1: |
||||
|
output[0] = -1; |
||||
|
output[1] = 0; |
||||
|
output[2] = 0; |
||||
|
output[3] = 0; |
||||
|
break; |
||||
|
case 2: |
||||
|
output[0] = 0; |
||||
|
output[1] = 0; |
||||
|
output[2] = -6 * Math.Sqrt(10) * x[2]; |
||||
|
output[3] = 3 * Math.Sqrt(10); |
||||
|
break; |
||||
|
case 3: |
||||
|
output[0] = 0; |
||||
|
output[1] = 0; |
||||
|
output[2] = -1; |
||||
|
output[3] = 0; |
||||
|
break; |
||||
|
case 4: |
||||
|
output[0] = 0; |
||||
|
output[1] = Math.Sqrt(10); |
||||
|
output[2] = 0; |
||||
|
output[3] = Math.Sqrt(10); |
||||
|
break; |
||||
|
case 5: |
||||
|
output[0] = 0; |
||||
|
output[1] = 1.0 / Math.Sqrt(10); |
||||
|
output[2] = 0; |
||||
|
output[3] = -1.0 / Math.Sqrt(10); |
||||
|
break; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 5"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void ItemHessianByRef(Vector<double> x, int itemIndex, Matrix<double> output) |
||||
|
{ |
||||
|
for (int ii = 0; ii < 4; ++ii) |
||||
|
for (int jj = 0; jj < 4; ++jj) |
||||
|
output[ii, jj] = 0; |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
output[0, 0] = -20; |
||||
|
break; |
||||
|
case 1: |
||||
|
break; |
||||
|
case 2: |
||||
|
output[2, 2] = -6 * Math.Sqrt(10); |
||||
|
break; |
||||
|
case 3: |
||||
|
case 4: |
||||
|
case 5: |
||||
|
break; |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 5"); |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override double ItemValue(Vector<double> x, int itemIndex) |
||||
|
{ |
||||
|
switch (itemIndex) |
||||
|
{ |
||||
|
case 0: |
||||
|
return 10 * (x[1] - x[0] * x[0]); |
||||
|
case 1: |
||||
|
return 1 - x[0]; |
||||
|
case 2: |
||||
|
return Math.Sqrt(90) * (x[3] - x[2] * x[2]); |
||||
|
case 3: |
||||
|
return 1 - x[2]; |
||||
|
case 4: |
||||
|
return Math.Sqrt(10) * (x[1] + x[3] - 2); |
||||
|
case 5: |
||||
|
return (x[1] - x[3]) / Math.Sqrt(10); |
||||
|
default: |
||||
|
throw new ArgumentException("itemIndex must be <= 5"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue