Browse Source

Added a converter from IObjectiveModel to IObjectiveFunction.

pull/614/head
diluculo 8 years ago
parent
commit
67db4f0501
  1. 64
      src/Numerics.Tests/OptimizationTests/NonLinearCurveFittingTests.cs
  2. 2
      src/Numerics/Optimization/IObjectiveModel.cs
  3. 24
      src/Numerics/Optimization/ObjectiveModel.cs
  4. 23
      src/Numerics/Optimization/ObjectiveModels/FittingObjectiveModel.cs

64
src/Numerics.Tests/OptimizationTests/NonLinearCurveFittingTests.cs

@ -386,6 +386,19 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
}
}
[Test]
public void Bfgs_FindMinimum_BoxBod_Unconstrained()
{
var obj = ObjectiveModel.FittingFunction(BoxBodModel, BoxBodPrime, BoxBodX, BoxBodY);
var solver = new BfgsMinimizer(1e-10, 1e-10, 1e-10, 100);
var result = solver.FindMinimum(obj, BoxBodStart2);
for (int i = 0; i < result.MinimizingPoint.Count; i++)
{
AssertHelpers.AlmostEqualRelative(BoxBodPbest[i], result.MinimizingPoint[i], 6);
}
}
// model : Thurber (https://www.itl.nist.gov/div898/strd/nls/data/thurber.shtml)
// f(x; b1 ... b7) = (b1 + b2*x + b3*x^2 + b4*x^3) / (1 + b5*x + b6*x^2 + b7*x^3)
// derivatives:
@ -456,7 +469,9 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
private Vector<double> ThurberPstd = new DenseVector(new double[] {
4.6647963344E+00, 3.9571156086E+01, 2.8698696102E+01, 5.5675370270E+00, 3.1333340687E-02,
1.4984928198E-02, 6.5842344623E-03 });
private Vector<double> ThurberInitialGuess = new DenseVector(new double[] { 1000.0, 1000.0, 400.0, 40.0, 0.7, 0.3, 0.03 });
private Vector<double> ThurberStart = new DenseVector(new double[] { 1000.0, 1000.0, 400.0, 40.0, 0.7, 0.3, 0.03 });
private Vector<double> ThurberLowerBound = new DenseVector(new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 });
private Vector<double> ThurberUpperBound = new DenseVector(new double[] { 1E6, 1E6, 1E6, 1E6, 1E6, 1E6, 1E6 });
private Vector<double> ThurberScales = new DenseVector(new double[7] { 1000, 1000, 400, 40, 0.7, 0.3, 0.03 });
[Test]
@ -464,7 +479,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
{
var obj = ObjectiveModel.FittingModel(ThurberModel, ThurberPrime, ThurberX, ThurberY);
var solver = new LevenbergMarquardtMinimizer();
var result = solver.FindMinimum(obj, ThurberInitialGuess);
var result = solver.FindMinimum(obj, ThurberStart);
for (int i = 0; i < result.BestFitParameters.Count; i++)
{
@ -478,7 +493,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
{
var obj = ObjectiveModel.FittingModel(ThurberModel, ThurberX, ThurberY, accuracyOrder: 6);
var solver = new LevenbergMarquardtMinimizer();
var result = solver.FindMinimum(obj, ThurberInitialGuess);
var result = solver.FindMinimum(obj, ThurberStart);
for (int i = 0; i < result.BestFitParameters.Count; i++)
{
@ -494,7 +509,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
scales: ThurberScales,
accuracyOrder: 6);
var solver = new TrustRegionDogLegMinimizer();
var result = solver.FindMinimum(obj, ThurberInitialGuess);
var result = solver.FindMinimum(obj, ThurberStart);
for (int i = 0; i < result.BestFitParameters.Count; i++)
{
@ -510,7 +525,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
scales: ThurberScales,
accuracyOrder: 6);
var solver = new TrustRegionNewtonCGMinimizer();
var result = solver.FindMinimum(obj, ThurberInitialGuess);
var result = solver.FindMinimum(obj, ThurberStart);
for (int i = 0; i < result.BestFitParameters.Count; i++)
{
@ -518,5 +533,44 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
AssertHelpers.AlmostEqualRelative(ThurberPstd[i], result.StandardErrors[i], 3);
}
}
[Test]
public void Bfgs_FindMinimum_Thurber_Unconstrained()
{
var obj = ObjectiveModel.FittingFunction(ThurberModel, ThurberX, ThurberY, accuracyOrder: 6);
var solver = new BfgsMinimizer(1e-10, 1e-10, 1e-10, 1000);
var result = solver.FindMinimum(obj, ThurberStart);
for (int i = 0; i < result.MinimizingPoint.Count; i++)
{
AssertHelpers.AlmostEqualRelative(ThurberPbest[i], result.MinimizingPoint[i], 6);
}
}
[Test]
public void BfgsB_FindMinimum_Thurber()
{
var obj = ObjectiveModel.FittingFunction(ThurberModel, ThurberX, ThurberY, accuracyOrder: 6);
var solver = new BfgsBMinimizer(1e-10, 1e-10, 1e-10, 1000);
var result = solver.FindMinimum(obj, ThurberLowerBound, ThurberUpperBound, ThurberStart);
for (int i = 0; i < result.MinimizingPoint.Count; i++)
{
AssertHelpers.AlmostEqualRelative(ThurberPbest[i], result.MinimizingPoint[i], 6);
}
}
[Test]
public void LBfgs_FindMinimum_Thurber()
{
var obj = ObjectiveModel.FittingFunction(ThurberModel, ThurberX, ThurberY, accuracyOrder: 6);
var solver = new LimitedMemoryBfgsMinimizer(1e-10, 1e-10, 1e-10, 1000);
var result = solver.FindMinimum(obj, ThurberStart);
for (int i = 0; i < result.MinimizingPoint.Count; i++)
{
AssertHelpers.AlmostEqualRelative(ThurberPbest[i], result.MinimizingPoint[i], 6);
}
}
}
}

2
src/Numerics/Optimization/IObjectiveModel.cs

@ -66,5 +66,7 @@ namespace MathNet.Numerics.Optimization
/// <summary>Create a new independent copy of this objective function, evaluated at the same point.</summary>
IObjectiveModel Fork();
IObjectiveFunction ToObjectiveFunction();
}
}

24
src/Numerics/Optimization/ObjectiveModel.cs

@ -36,5 +36,29 @@ namespace MathNet.Numerics.Optimization
objective.SetParameters(lowerBound, upperBound, scales, isFixed);
return objective;
}
/// <summary>
/// Fitting function with a user supplied jacobian for nonlinear least squares regression by the line search algorithm.
/// </summary>
public static IObjectiveFunction FittingFunction(Func<Vector<double>, double, double> function, Func<Vector<double>, double, Vector<double>> derivatives,
Vector<double> observedX, Vector<double> observedY, Vector<double> weight = null)
{
var objective = new FittingObjectiveModel(function, derivatives);
objective.SetObserved(observedX, observedY, weight);
return objective.ToObjectiveFunction();
}
/// <summary>
/// Fitting function for nonlinear least squares regression by the line search algorithm.
/// The numerical jacobian with accuracy order is used.
/// </summary>
public static IObjectiveFunction FittingFunction(Func<Vector<double>, double, double> function,
Vector<double> observedX, Vector<double> observedY, Vector<double> weight = null,
int accuracyOrder = 2)
{
var objective = new FittingObjectiveModel(function, null, accuracyOrder: accuracyOrder);
objective.SetObserved(observedX, observedY, weight);
return objective.ToObjectiveFunction();
}
}
}

23
src/Numerics/Optimization/ObjectiveModels/FittingObjectiveModel.cs

@ -1,4 +1,5 @@
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.Optimization.ObjectiveFunctions;
using System;
using System.Collections.Generic;
using System.Linq;
@ -172,7 +173,27 @@ namespace MathNet.Numerics.Optimization.ObjectiveModels
public IObjectiveModel CreateNew()
{
return new FittingObjectiveModel(userFunction, userDerivatives);
return new FittingObjectiveModel(userFunction, userDerivatives, AccuracyOrder);
}
public IObjectiveFunction ToObjectiveFunction()
{
Tuple<double, Vector<double>, Matrix<double>> function(Vector<double> point)
{
EvaluateFunction(point);
EvaluateJacobian(point);
return new Tuple<double, Vector<double>, Matrix<double>>(Residue, -Gradient, Hessian);
}
LowerBound = null;
UpperBound = null;
Scales = null;
IsFixed = null;
IsBounded = false;
var objective = new GradientHessianObjectiveFunction(function);
return objective;
}
/// <summary>

Loading…
Cancel
Save