committed by
Erik Ovegard
7 changed files with 162 additions and 196 deletions
@ -0,0 +1,131 @@ |
|||
using MathNet.Numerics.LinearAlgebra; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace MathNet.Numerics.Optimization.LineSearch |
|||
{ |
|||
public abstract class WolfeLineSearch |
|||
{ |
|||
protected double C1 { get; } |
|||
protected double C2 { get; } |
|||
protected double ParameterTolerance { get; } |
|||
protected int MaximumIterations { get; } |
|||
|
|||
public WolfeLineSearch(double c1, double c2, double parameterTolerance, int maxIterations = 10) |
|||
{ |
|||
if (c1 <= 0) |
|||
throw new ArgumentException(string.Format("c1 {0} should be greater than 0", c1)); |
|||
if (c2 <= c1) |
|||
throw new ArgumentException(string.Format("c1 {0} should be less than c2 {1}", c1, c2)); |
|||
if (c2 >= 1) |
|||
throw new ArgumentException(string.Format("c2 {0} should be less than 1", c2)); |
|||
|
|||
C1 = c1; |
|||
C2 = c2; |
|||
ParameterTolerance = parameterTolerance; |
|||
MaximumIterations = maxIterations; |
|||
} |
|||
|
|||
/// <summary>Implemented following http://www.math.washington.edu/~burke/crs/408/lectures/L9-weak-Wolfe.pdf</summary>
|
|||
/// <param name="startingPoint">The objective function being optimized, evaluated at the starting point of the search</param>
|
|||
/// <param name="searchDirection">Search direction</param>
|
|||
/// <param name="initialStep">Initial size of the step in the search direction</param>
|
|||
public LineSearchResult FindConformingStep(IObjectiveFunctionEvaluation startingPoint, Vector<double> searchDirection, double initialStep) |
|||
{ |
|||
return FindConformingStep(startingPoint, searchDirection, initialStep, double.PositiveInfinity); |
|||
} |
|||
|
|||
/// <summary></summary>
|
|||
/// <param name="startingPoint">The objective function being optimized, evaluated at the starting point of the search</param>
|
|||
/// <param name="searchDirection">Search direction</param>
|
|||
/// <param name="initialStep">Initial size of the step in the search direction</param>
|
|||
/// <param name="upperBound">The upper bound</param>
|
|||
public LineSearchResult FindConformingStep(IObjectiveFunctionEvaluation startingPoint, Vector<double> searchDirection, double initialStep, double upperBound) |
|||
{ |
|||
ValidateInputArguments(startingPoint, searchDirection, initialStep, upperBound); |
|||
|
|||
double lowerBound = 0.0; |
|||
double step = initialStep; |
|||
|
|||
double initialValue = startingPoint.Value; |
|||
Vector<double> initialGradient = startingPoint.Gradient; |
|||
|
|||
double initialDd = searchDirection * initialGradient; |
|||
|
|||
IObjectiveFunction objective = startingPoint.CreateNew(); |
|||
int ii; |
|||
MinimizationResult.ExitCondition reasonForExit = MinimizationResult.ExitCondition.None; |
|||
for (ii = 0; ii < MaximumIterations; ++ii) |
|||
{ |
|||
objective.EvaluateAt(startingPoint.Point + searchDirection * step); |
|||
ValidateGradient(objective); // Differ! (added)
|
|||
ValidateValue(objective); // Differ! (added)
|
|||
|
|||
double stepDd = searchDirection * objective.Gradient; |
|||
|
|||
if (objective.Value > initialValue + C1 * step * initialDd) |
|||
{ |
|||
upperBound = step; |
|||
step = 0.5 * (lowerBound + upperBound); |
|||
} |
|||
else if (WolfeCondition(stepDd,initialDd)) // Differ, weak Wolfe
|
|||
{ |
|||
lowerBound = step; |
|||
step = double.IsPositiveInfinity(upperBound) ? 2 * lowerBound : 0.5 * (lowerBound + upperBound); |
|||
} |
|||
else |
|||
{ |
|||
reasonForExit = WolfeExitCondition; |
|||
break; |
|||
} |
|||
|
|||
if (!double.IsInfinity(upperBound)) |
|||
{ |
|||
double maxRelChange = 0.0; |
|||
for (int jj = 0; jj < objective.Point.Count; ++jj) |
|||
{ |
|||
double tmp = Math.Abs(searchDirection[jj] * (upperBound - lowerBound)) / Math.Max(Math.Abs(objective.Point[jj]), 1.0); |
|||
maxRelChange = Math.Max(maxRelChange, tmp); |
|||
} |
|||
if (maxRelChange < ParameterTolerance) |
|||
{ |
|||
reasonForExit = MinimizationResult.ExitCondition.LackOfProgress; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (ii == MaximumIterations && Double.IsPositiveInfinity(upperBound)) |
|||
{ |
|||
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached. Function appears to be unbounded in search direction.", MaximumIterations)); |
|||
} |
|||
|
|||
if (ii == MaximumIterations) |
|||
{ |
|||
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", MaximumIterations)); |
|||
} |
|||
|
|||
return new LineSearchResult(objective, ii, step, reasonForExit); |
|||
} |
|||
protected abstract MinimizationResult.ExitCondition WolfeExitCondition { get; } |
|||
|
|||
protected abstract bool WolfeCondition(double stepDd, double initialDd); |
|||
|
|||
protected virtual void ValidateGradient(IObjectiveFunction objective) |
|||
{ |
|||
} |
|||
protected virtual void ValidateValue(IObjectiveFunction objective) |
|||
{ |
|||
} |
|||
|
|||
protected virtual void ValidateInputArguments(IObjectiveFunctionEvaluation startingPoint, Vector<double> searchDirection, double initialStep, double upperBound) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
} |
|||
Loading…
Reference in new issue