Browse Source

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

v3
Christoph Ruegg 10 years ago
parent
commit
2159e3c596
  1. 2
      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. 10
      src/Numerics/Optimization/LineSearch/WolfeLineSearch.cs
  8. 14
      src/Numerics/Optimization/NelderMeadSimplex.cs
  9. 6
      src/Numerics/Optimization/NewtonMinimizer.cs
  10. 22
      src/Numerics/Optimization/ObjectiveFunctions/ForwardDifferenceGradientObjectiveFunction.cs

2
src/Numerics/Optimization/BfgsBMinimizer.cs

@ -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; double projectedGradient;
bool atLowerBound = candidatePoint.Point[ii] - _lowerBound[ii] < VerySmall; bool atLowerBound = candidatePoint.Point[ii] - _lowerBound[ii] < VerySmall;

6
src/Numerics/Optimization/BfgsMinimizerBase.cs

@ -59,7 +59,7 @@ namespace MathNet.Numerics.Optimization
MaximumIterations = maximumIterations; 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); Vector<double> relGrad = new DenseVector(candidatePoint.Point.Count);
double relativeGradient = 0.0; double relativeGradient = 0.0;
@ -99,12 +99,12 @@ namespace MathNet.Numerics.Optimization
return MinimizationResult.ExitCondition.None; return MinimizationResult.ExitCondition.None;
} }
protected virtual double GetProjectedGradient(IObjectiveFunction candidatePoint, int ii) protected virtual double GetProjectedGradient(IObjectiveFunctionEvaluation candidatePoint, int ii)
{ {
return candidatePoint.Gradient[ii]; return candidatePoint.Gradient[ii];
} }
protected void ValidateGradientAndObjective(IObjectiveFunction eval) protected void ValidateGradientAndObjective(IObjectiveFunctionEvaluation eval)
{ {
foreach (var x in eval.Gradient) 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; return gradient.Norm(2.0) < GradientTolerance;
} }
void ValidateGradient(IObjectiveFunction objective) void ValidateGradient(IObjectiveFunctionEvaluation objective)
{ {
foreach (var x in objective.Gradient) 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)) if (Double.IsNaN(objective.Value) || Double.IsInfinity(objective.Value))
throw new EvaluationException("Non-finite objective function returned.", objective); 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 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) : base(message)
{ {
ObjectiveFunction = eval; ObjectiveFunction = eval;
} }
public EvaluationException(string message, IObjectiveFunction eval, Exception innerException) public EvaluationException(string message, IObjectiveFunctionEvaluation eval, Exception innerException)
: base(message, innerException) : base(message, innerException)
{ {
ObjectiveFunction = eval; ObjectiveFunction = eval;

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

@ -40,7 +40,10 @@ namespace MathNet.Numerics.Optimization.LineSearch
// Argument validation in base class // 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) 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; return stepDd < C2 * initialDd;
} }
protected override void ValidateValue(IObjectiveFunction eval) protected override void ValidateValue(IObjectiveFunctionEvaluation eval)
{ {
if (!IsFinite(eval.Value)) if (!IsFinite(eval.Value))
{ {
@ -78,7 +78,7 @@ namespace MathNet.Numerics.Optimization.LineSearch
throw new ArgumentException("objective function does not support gradient"); 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) foreach (double x in eval.Gradient)
{ {

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

@ -136,23 +136,21 @@ namespace MathNet.Numerics.Optimization.LineSearch
return new LineSearchResult(objective, ii, step, reasonForExit); return new LineSearchResult(objective, ii, step, reasonForExit);
} }
protected abstract MinimizationResult.ExitCondition WolfeExitCondition { get; } protected abstract MinimizationResult.ExitCondition WolfeExitCondition { get; }
protected abstract bool WolfeCondition(double stepDd, double initialDd); 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) protected virtual void ValidateInputArguments(IObjectiveFunctionEvaluation startingPoint, Vector<double> searchDirection, double initialStep, double upperBound)
{ {
} }
} }
} }

14
src/Numerics/Optimization/NelderMeadSimplex.cs

@ -32,9 +32,6 @@
using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MathNet.Numerics.Optimization namespace MathNet.Numerics.Optimization
{ {
@ -68,7 +65,7 @@ namespace MathNet.Numerics.Optimization
/// <returns>The minimum point</returns> /// <returns>The minimum point</returns>
public MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector<double> initialGuess) 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++) for (int i = 0; i < initialGuess.Count; i++)
{ {
initalPertubation[i] = initialGuess[i] == 0.0 ? 0.00025 : initialGuess[i] * 0.05; 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]; Vector<double>[] vertices = new Vector<double>[numDimensions + 1];
// define one point of the simplex as the given initial guesses // 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++) for (int i = 0; i < numDimensions; i++)
{ {
p0[i] = simplexConstants[i].Value; p0[i] = simplexConstants[i].Value;
@ -261,7 +258,7 @@ namespace MathNet.Numerics.Optimization
for (int i = 0; i < numDimensions; i++) for (int i = 0; i < numDimensions; i++)
{ {
double scale = simplexConstants[i].InitialPerturbation; 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; unitVector[i] = 1;
vertices[i + 1] = p0.Add(unitVector.Multiply(scale)); vertices[i + 1] = p0.Add(unitVector.Multiply(scale));
} }
@ -335,7 +332,7 @@ namespace MathNet.Numerics.Optimization
{ {
int numVertices = vertices.Length; int numVertices = vertices.Length;
// find the centroid of all points except the worst one // 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++) for (int i = 0; i < numVertices; i++)
{ {
if (i != errorProfile.HighestIndex) 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; return gradient.Norm(2.0) < GradientTolerance;
} }
static void ValidateGradient(IObjectiveFunction eval) static void ValidateGradient(IObjectiveFunctionEvaluation eval)
{ {
foreach (var x in eval.Gradient) 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)) if (Double.IsNaN(eval.Value) || Double.IsInfinity(eval.Value))
throw new EvaluationException("Non-finite objective function returned.", eval); 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) 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) if (!ValueEvaluated)
EvaluateValue(); EvaluateValue();
var tmp_point = Point.Clone(); var tmpPoint = Point.Clone();
var tmp_obj = InnerObjectiveFunction.CreateNew(); var tmpObj = InnerObjectiveFunction.CreateNew();
for (int ii = 0; ii < _gradient.Count; ++ii) for (int ii = 0; ii < _gradient.Count; ++ii)
{ {
var orig_point = tmp_point[ii]; var origPoint = tmpPoint[ii];
var rel_incr = orig_point * RelativeIncrement; var relIncr = origPoint * RelativeIncrement;
var h = Math.Max(rel_incr, MinimumIncrement); var h = Math.Max(relIncr, MinimumIncrement);
var mult = 1; var mult = 1;
if (orig_point + h > UpperBound[ii]) if (origPoint + h > UpperBound[ii])
mult = -1; mult = -1;
tmp_point[ii] = orig_point + mult*h; tmpPoint[ii] = origPoint + mult*h;
tmp_obj.EvaluateAt(tmp_point); tmpObj.EvaluateAt(tmpPoint);
double bumped_value = tmp_obj.Value; double bumpedValue = tmpObj.Value;
_gradient[ii] = (mult * bumped_value - mult * InnerObjectiveFunction.Value) / h; _gradient[ii] = (mult * bumpedValue - mult * InnerObjectiveFunction.Value) / h;
tmp_point[ii] = orig_point; tmpPoint[ii] = origPoint;
} }
GradientEvaluated = true; GradientEvaluated = true;
} }

Loading…
Cancel
Save