Browse Source

Optimization: NewtonMinimizer: allow static usage

v3
Christoph Ruegg 9 years ago
parent
commit
9f48af911c
  1. 4
      src/Numerics/Optimization/NelderMeadSimplex.cs
  2. 30
      src/Numerics/Optimization/NewtonMinimizer.cs
  3. 3
      src/UnitTests/OptimizationTests/NewtonMinimizerTests.cs

4
src/Numerics/Optimization/NelderMeadSimplex.cs

@ -87,7 +87,7 @@ namespace MathNet.Numerics.Optimization
/// <param name="objectiveFunction">The objective function, no gradient or hessian needed</param> /// <param name="objectiveFunction">The objective function, no gradient or hessian needed</param>
/// <param name="initialGuess">The intial guess</param> /// <param name="initialGuess">The intial guess</param>
/// <returns>The minimum point</returns> /// <returns>The minimum point</returns>
public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector<double> initialGuess, double convergenceTolerance, int maximumIterations) public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector<double> initialGuess, double convergenceTolerance, int maximumIterations=1000)
{ {
var initalPertubation = new LinearAlgebra.Double.DenseVector(initialGuess.Count); var initalPertubation = new LinearAlgebra.Double.DenseVector(initialGuess.Count);
for (int i = 0; i < initialGuess.Count; i++) for (int i = 0; i < initialGuess.Count; i++)
@ -104,7 +104,7 @@ namespace MathNet.Numerics.Optimization
/// <param name="initialGuess">The intial guess</param> /// <param name="initialGuess">The intial guess</param>
/// <param name="initalPertubation">The inital pertubation</param> /// <param name="initalPertubation">The inital pertubation</param>
/// <returns>The minimum point</returns> /// <returns>The minimum point</returns>
public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector<double> initialGuess, Vector<double> initalPertubation, double convergenceTolerance, int maximumIterations) public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector<double> initialGuess, Vector<double> initalPertubation, double convergenceTolerance, int maximumIterations=1000)
{ {
// confirm that we are in a position to commence // confirm that we are in a position to commence
if (objectiveFunction == null) if (objectiveFunction == null)

30
src/Numerics/Optimization/NewtonMinimizer.cs

@ -33,7 +33,7 @@ using MathNet.Numerics.Optimization.LineSearch;
namespace MathNet.Numerics.Optimization namespace MathNet.Numerics.Optimization
{ {
public class NewtonMinimizer public sealed class NewtonMinimizer
{ {
public double GradientTolerance { get; set; } public double GradientTolerance { get; set; }
public int MaximumIterations { get; set; } public int MaximumIterations { get; set; }
@ -47,6 +47,11 @@ namespace MathNet.Numerics.Optimization
} }
public MinimizationResult FindMinimum(IObjectiveFunction objective, Vector<double> initialGuess) public MinimizationResult FindMinimum(IObjectiveFunction objective, Vector<double> initialGuess)
{
return FindMinimum(objective, initialGuess, GradientTolerance, MaximumIterations, UseLineSearch);
}
public static MinimizationResult FindMinimum(IObjectiveFunction objective, Vector<double> initialGuess, double gradientTolerance, int maxIterations=1000, bool useLineSearch = false)
{ {
if (!objective.IsGradientSupported) if (!objective.IsGradientSupported)
{ {
@ -61,7 +66,7 @@ namespace MathNet.Numerics.Optimization
// Check that we're not already done // Check that we're not already done
objective.EvaluateAt(initialGuess); objective.EvaluateAt(initialGuess);
ValidateGradient(objective); ValidateGradient(objective);
if (ExitCriteriaSatisfied(objective.Gradient)) if (objective.Gradient.Norm(2.0) < gradientTolerance)
{ {
return new MinimizationResult(objective, 0, ExitCondition.AbsoluteGradient); return new MinimizationResult(objective, 0, ExitCondition.AbsoluteGradient);
} }
@ -74,7 +79,7 @@ namespace MathNet.Numerics.Optimization
int totalLineSearchSteps = 0; int totalLineSearchSteps = 0;
int iterationsWithNontrivialLineSearch = 0; int iterationsWithNontrivialLineSearch = 0;
bool tmpLineSearch = false; bool tmpLineSearch = false;
while (!ExitCriteriaSatisfied(objective.Gradient) && iterations < MaximumIterations) while (objective.Gradient.Norm(2.0) >= gradientTolerance && iterations < maxIterations)
{ {
ValidateHessian(objective); ValidateHessian(objective);
@ -85,7 +90,7 @@ namespace MathNet.Numerics.Optimization
tmpLineSearch = true; tmpLineSearch = true;
} }
if (UseLineSearch || tmpLineSearch) if (useLineSearch || tmpLineSearch)
{ {
LineSearchResult result; LineSearchResult result;
try try
@ -112,19 +117,14 @@ namespace MathNet.Numerics.Optimization
iterations += 1; iterations += 1;
} }
if (iterations == MaximumIterations) if (iterations == maxIterations)
{ {
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", MaximumIterations)); throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", maxIterations));
} }
return new MinimizationWithLineSearchResult(objective, iterations, ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch); return new MinimizationWithLineSearchResult(objective, iterations, ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
} }
bool ExitCriteriaSatisfied(Vector<double> gradient)
{
return gradient.Norm(2.0) < GradientTolerance;
}
static void ValidateGradient(IObjectiveFunctionEvaluation eval) static void ValidateGradient(IObjectiveFunctionEvaluation eval)
{ {
foreach (var x in eval.Gradient) foreach (var x in eval.Gradient)
@ -136,13 +136,7 @@ namespace MathNet.Numerics.Optimization
} }
} }
private void ValidateObjective(IObjectiveFunctionEvaluation eval) static void ValidateHessian(IObjectiveFunctionEvaluation eval)
{
if (Double.IsNaN(eval.Value) || Double.IsInfinity(eval.Value))
throw new EvaluationException("Non-finite objective function returned.", eval);
}
private void ValidateHessian(IObjectiveFunctionEvaluation eval)
{ {
for (int ii = 0; ii < eval.Hessian.RowCount; ++ii) for (int ii = 0; ii < eval.Hessian.RowCount; ++ii)
{ {

3
src/UnitTests/OptimizationTests/NewtonMinimizerTests.cs

@ -198,9 +198,8 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
public void Mgh_Tests(TestFunctions.TestCase test_case) public void Mgh_Tests(TestFunctions.TestCase test_case)
{ {
var obj = new MghObjectiveFunction(test_case.Function, true, true); var obj = new MghObjectiveFunction(test_case.Function, true, true);
var solver = new NewtonMinimizer(1e-8, 1000, useLineSearch: false);
var result = solver.FindMinimum(obj, test_case.InitialGuess); var result = NewtonMinimizer.FindMinimum(obj, test_case.InitialGuess, 1e-8, 1000, useLineSearch: false);
if (test_case.MinimizingPoint != null) if (test_case.MinimizingPoint != null)
{ {

Loading…
Cancel
Save