Browse Source

Optimization: interface segregation: don't ask for function if only evaluation is needed

pull/497/head
Christoph Ruegg 9 years ago
parent
commit
2159e3c596
  1. 10
      src/Numerics/Optimization/BfgsBMinimizer.cs
  2. 6
      src/Numerics/Optimization/BfgsMinimizerBase.cs
  3. 4
      src/Numerics/Optimization/ConjugateGradientMinimizer.cs
  4. 6
      src/Numerics/Optimization/Exceptions.cs
  5. 5
      src/Numerics/Optimization/LineSearch/StrongWolfeLineSearch.cs
  6. 4
      src/Numerics/Optimization/LineSearch/WeakWolfeLineSearch.cs
  7. 16
      src/Numerics/Optimization/LineSearch/WolfeLineSearch.cs
  8. 18
      src/Numerics/Optimization/NelderMeadSimplex.cs
  9. 6
      src/Numerics/Optimization/NewtonMinimizer.cs
  10. 22
      src/Numerics/Optimization/ObjectiveFunctions/ForwardDifferenceGradientObjectiveFunction.cs
  11. 2
      src/Numerics/Optimization/ObjectiveFunctions/GradientHessianObjectiveFunction.cs
  12. 2
      src/Numerics/Optimization/ObjectiveFunctions/GradientObjectiveFunction.cs
  13. 2
      src/Numerics/Optimization/ObjectiveFunctions/HessianObjectiveFunction.cs
  14. 2
      src/Numerics/Optimization/ObjectiveFunctions/LazyObjectiveFunction.cs
  15. 2
      src/Numerics/Optimization/ObjectiveFunctions/ValueObjectiveFunction.cs

10
src/Numerics/Optimization/BfgsBMinimizer.cs

@ -158,9 +158,9 @@ namespace MathNet.Numerics.Optimization
protected override Vector<double> CalculateSearchDirection(ref Matrix<double> pseudoHessian,
out double maxLineSearchStep,
out double startingStepSize,
IObjectiveFunction previousPoint,
IObjectiveFunction candidatePoint,
out double startingStepSize,
IObjectiveFunction previousPoint,
IObjectiveFunction candidatePoint,
Vector<double> step)
{
Vector<double> lineSearchDirection;
@ -170,7 +170,7 @@ namespace MathNet.Numerics.Optimization
if (sy > 0.0) // only do update if it will create a positive definite matrix
{
double sts = step * step;
var Hs = pseudoHessian * step;
var sHs = step * pseudoHessian * step;
pseudoHessian = pseudoHessian + y.OuterProduct(y) * (1.0 / sy) - Hs.OuterProduct(Hs) * (1.0 / sHs);
@ -285,7 +285,7 @@ namespace MathNet.Numerics.Optimization
}
}
protected override double GetProjectedGradient(IObjectiveFunction candidatePoint, int ii)
protected override double GetProjectedGradient(IObjectiveFunctionEvaluation candidatePoint, int ii)
{
double projectedGradient;
bool atLowerBound = candidatePoint.Point[ii] - _lowerBound[ii] < VerySmall;

6
src/Numerics/Optimization/BfgsMinimizerBase.cs

@ -59,7 +59,7 @@ namespace MathNet.Numerics.Optimization
MaximumIterations = maximumIterations;
}
protected MinimizationResult.ExitCondition ExitCriteriaSatisfied(IObjectiveFunction candidatePoint, IObjectiveFunction lastPoint, int iterations)
protected MinimizationResult.ExitCondition ExitCriteriaSatisfied(IObjectiveFunctionEvaluation candidatePoint, IObjectiveFunctionEvaluation lastPoint, int iterations)
{
Vector<double> relGrad = new DenseVector(candidatePoint.Point.Count);
double relativeGradient = 0.0;
@ -99,12 +99,12 @@ namespace MathNet.Numerics.Optimization
return MinimizationResult.ExitCondition.None;
}
protected virtual double GetProjectedGradient(IObjectiveFunction candidatePoint, int ii)
protected virtual double GetProjectedGradient(IObjectiveFunctionEvaluation candidatePoint, int ii)
{
return candidatePoint.Gradient[ii];
}
protected void ValidateGradientAndObjective(IObjectiveFunction eval)
protected void ValidateGradientAndObjective(IObjectiveFunctionEvaluation eval)
{
foreach (var x in eval.Gradient)
{

4
src/Numerics/Optimization/ConjugateGradientMinimizer.cs

@ -127,7 +127,7 @@ namespace MathNet.Numerics.Optimization
return gradient.Norm(2.0) < GradientTolerance;
}
void ValidateGradient(IObjectiveFunction objective)
void ValidateGradient(IObjectiveFunctionEvaluation objective)
{
foreach (var x in objective.Gradient)
{
@ -136,7 +136,7 @@ namespace MathNet.Numerics.Optimization
}
}
void ValidateObjective(IObjectiveFunction objective)
void ValidateObjective(IObjectiveFunctionEvaluation objective)
{
if (Double.IsNaN(objective.Value) || Double.IsInfinity(objective.Value))
throw new EvaluationException("Non-finite objective function returned.", objective);

6
src/Numerics/Optimization/Exceptions.cs

@ -49,15 +49,15 @@ namespace MathNet.Numerics.Optimization
public class EvaluationException : OptimizationException
{
public IObjectiveFunction ObjectiveFunction { get; private set; }
public IObjectiveFunctionEvaluation ObjectiveFunction { get; private set; }
public EvaluationException(string message, IObjectiveFunction eval)
public EvaluationException(string message, IObjectiveFunctionEvaluation eval)
: base(message)
{
ObjectiveFunction = eval;
}
public EvaluationException(string message, IObjectiveFunction eval, Exception innerException)
public EvaluationException(string message, IObjectiveFunctionEvaluation eval, Exception innerException)
: base(message, innerException)
{
ObjectiveFunction = eval;

5
src/Numerics/Optimization/LineSearch/StrongWolfeLineSearch.cs

@ -40,7 +40,10 @@ namespace MathNet.Numerics.Optimization.LineSearch
// Argument validation in base class
}
protected override MinimizationResult.ExitCondition WolfeExitCondition { get { return MinimizationResult.ExitCondition.StrongWolfeCriteria; } }
protected override MinimizationResult.ExitCondition WolfeExitCondition
{
get { return MinimizationResult.ExitCondition.StrongWolfeCriteria; }
}
protected override bool WolfeCondition(double stepDd, double initialDd)
{

4
src/Numerics/Optimization/LineSearch/WeakWolfeLineSearch.cs

@ -64,7 +64,7 @@ namespace MathNet.Numerics.Optimization.LineSearch
return stepDd < C2 * initialDd;
}
protected override void ValidateValue(IObjectiveFunction eval)
protected override void ValidateValue(IObjectiveFunctionEvaluation eval)
{
if (!IsFinite(eval.Value))
{
@ -78,7 +78,7 @@ namespace MathNet.Numerics.Optimization.LineSearch
throw new ArgumentException("objective function does not support gradient");
}
protected override void ValidateGradient(IObjectiveFunction eval)
protected override void ValidateGradient(IObjectiveFunctionEvaluation eval)
{
foreach (double x in eval.Gradient)
{

16
src/Numerics/Optimization/LineSearch/WolfeLineSearch.cs

@ -87,8 +87,8 @@ namespace MathNet.Numerics.Optimization.LineSearch
for (ii = 0; ii < MaximumIterations; ++ii)
{
objective.EvaluateAt(startingPoint.Point + searchDirection * step);
ValidateGradient(objective);
ValidateValue(objective);
ValidateGradient(objective);
ValidateValue(objective);
double stepDd = searchDirection * objective.Gradient;
@ -104,7 +104,7 @@ namespace MathNet.Numerics.Optimization.LineSearch
}
else
{
reasonForExit = WolfeExitCondition;
reasonForExit = WolfeExitCondition;
break;
}
@ -136,23 +136,21 @@ namespace MathNet.Numerics.Optimization.LineSearch
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 ValidateGradient(IObjectiveFunctionEvaluation objective)
{
}
protected virtual void ValidateValue(IObjectiveFunction objective)
protected virtual void ValidateValue(IObjectiveFunctionEvaluation objective)
{
}
protected virtual void ValidateInputArguments(IObjectiveFunctionEvaluation startingPoint, Vector<double> searchDirection, double initialStep, double upperBound)
{
}
}
}

18
src/Numerics/Optimization/NelderMeadSimplex.cs

@ -32,15 +32,12 @@
using MathNet.Numerics.LinearAlgebra;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MathNet.Numerics.Optimization
{
/// <summary>
/// Class implementing the Nelder-Mead simplex algorithm, used to find a minima when no gradient is available.
/// Called fminsearch() in Matlab. A description of the algorithm can be found at
/// Class implementing the Nelder-Mead simplex algorithm, used to find a minima when no gradient is available.
/// Called fminsearch() in Matlab. A description of the algorithm can be found at
/// http://se.mathworks.com/help/matlab/math/optimizing-nonlinear-functions.html#bsgpq6p-11
/// or
/// https://en.wikipedia.org/wiki/Nelder%E2%80%93Mead_method
@ -68,7 +65,7 @@ namespace MathNet.Numerics.Optimization
/// <returns>The minimum point</returns>
public MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector<double> initialGuess)
{
var initalPertubation = new MathNet.Numerics.LinearAlgebra.Double.DenseVector(initialGuess.Count);
var initalPertubation = new LinearAlgebra.Double.DenseVector(initialGuess.Count);
for (int i = 0; i < initialGuess.Count; i++)
{
initalPertubation[i] = initialGuess[i] == 0.0 ? 0.00025 : initialGuess[i] * 0.05;
@ -249,7 +246,7 @@ namespace MathNet.Numerics.Optimization
Vector<double>[] vertices = new Vector<double>[numDimensions + 1];
// define one point of the simplex as the given initial guesses
var p0 = new MathNet.Numerics.LinearAlgebra.Double.DenseVector(numDimensions);
var p0 = new LinearAlgebra.Double.DenseVector(numDimensions);
for (int i = 0; i < numDimensions; i++)
{
p0[i] = simplexConstants[i].Value;
@ -261,7 +258,7 @@ namespace MathNet.Numerics.Optimization
for (int i = 0; i < numDimensions; i++)
{
double scale = simplexConstants[i].InitialPerturbation;
Vector<double> unitVector = new MathNet.Numerics.LinearAlgebra.Double.DenseVector(numDimensions);
Vector<double> unitVector = new LinearAlgebra.Double.DenseVector(numDimensions);
unitVector[i] = 1;
vertices[i + 1] = p0.Add(unitVector.Multiply(scale));
}
@ -335,7 +332,7 @@ namespace MathNet.Numerics.Optimization
{
int numVertices = vertices.Length;
// find the centroid of all points except the worst one
Vector<double> centroid = new MathNet.Numerics.LinearAlgebra.Double.DenseVector(numVertices - 1);
Vector<double> centroid = new LinearAlgebra.Double.DenseVector(numVertices - 1);
for (int i = 0; i < numVertices; i++)
{
if (i != errorProfile.HighestIndex)
@ -409,7 +406,4 @@ namespace MathNet.Numerics.Optimization
}
}
}
}

6
src/Numerics/Optimization/NewtonMinimizer.cs

@ -126,7 +126,7 @@ namespace MathNet.Numerics.Optimization
return gradient.Norm(2.0) < GradientTolerance;
}
static void ValidateGradient(IObjectiveFunction eval)
static void ValidateGradient(IObjectiveFunctionEvaluation eval)
{
foreach (var x in eval.Gradient)
{
@ -137,13 +137,13 @@ namespace MathNet.Numerics.Optimization
}
}
private void ValidateObjective(IObjectiveFunction eval)
private void ValidateObjective(IObjectiveFunctionEvaluation eval)
{
if (Double.IsNaN(eval.Value) || Double.IsInfinity(eval.Value))
throw new EvaluationException("Non-finite objective function returned.", eval);
}
private void ValidateHessian(IObjectiveFunction eval)
private void ValidateHessian(IObjectiveFunctionEvaluation eval)
{
for (int ii = 0; ii < eval.Hessian.RowCount; ++ii)
{

22
src/Numerics/Optimization/ObjectiveFunctions/ForwardDifferenceGradientObjectiveFunction.cs

@ -76,23 +76,23 @@ namespace MathNet.Numerics.Optimization.ObjectiveFunctions
if (!ValueEvaluated)
EvaluateValue();
var tmp_point = Point.Clone();
var tmp_obj = InnerObjectiveFunction.CreateNew();
var tmpPoint = Point.Clone();
var tmpObj = InnerObjectiveFunction.CreateNew();
for (int ii = 0; ii < _gradient.Count; ++ii)
{
var orig_point = tmp_point[ii];
var rel_incr = orig_point * RelativeIncrement;
var h = Math.Max(rel_incr, MinimumIncrement);
var origPoint = tmpPoint[ii];
var relIncr = origPoint * RelativeIncrement;
var h = Math.Max(relIncr, MinimumIncrement);
var mult = 1;
if (orig_point + h > UpperBound[ii])
if (origPoint + h > UpperBound[ii])
mult = -1;
tmp_point[ii] = orig_point + mult*h;
tmp_obj.EvaluateAt(tmp_point);
double bumped_value = tmp_obj.Value;
_gradient[ii] = (mult * bumped_value - mult * InnerObjectiveFunction.Value) / h;
tmpPoint[ii] = origPoint + mult*h;
tmpObj.EvaluateAt(tmpPoint);
double bumpedValue = tmpObj.Value;
_gradient[ii] = (mult * bumpedValue - mult * InnerObjectiveFunction.Value) / h;
tmp_point[ii] = orig_point;
tmpPoint[ii] = origPoint;
}
GradientEvaluated = true;
}

2
src/Numerics/Optimization/ObjectiveFunctions/GradientHessianObjectiveFunction.cs

@ -84,4 +84,4 @@ namespace MathNet.Numerics.Optimization.ObjectiveFunctions
public Vector<double> Gradient { get; private set; }
public Matrix<double> Hessian { get; private set; }
}
}
}

2
src/Numerics/Optimization/ObjectiveFunctions/GradientObjectiveFunction.cs

@ -86,4 +86,4 @@ namespace MathNet.Numerics.Optimization.ObjectiveFunctions
get { throw new NotSupportedException(); }
}
}
}
}

2
src/Numerics/Optimization/ObjectiveFunctions/HessianObjectiveFunction.cs

@ -86,4 +86,4 @@ namespace MathNet.Numerics.Optimization.ObjectiveFunctions
get { throw new NotSupportedException(); }
}
}
}
}

2
src/Numerics/Optimization/ObjectiveFunctions/LazyObjectiveFunction.cs

@ -139,4 +139,4 @@ namespace MathNet.Numerics.Optimization.ObjectiveFunctions
}
}
}
}
}

2
src/Numerics/Optimization/ObjectiveFunctions/ValueObjectiveFunction.cs

@ -86,4 +86,4 @@ namespace MathNet.Numerics.Optimization.ObjectiveFunctions
get { throw new NotSupportedException(); }
}
}
}
}

Loading…
Cancel
Save