Browse Source

Optimization: simplification: validate directly instead of through adapter

pull/489/head
Christoph Ruegg 11 years ago
committed by Erik Ovegard
parent
commit
2fcf9c91ee
  1. 4
      src/Numerics/Optimization/Implementation/CheckedObjectiveFunction.cs
  2. 12
      src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs
  3. 28
      src/Numerics/Optimization/NewtonMinimizer.cs

4
src/Numerics/Optimization/Implementation/CheckedObjectiveFunction.cs

@ -30,13 +30,15 @@ namespace MathNet.Numerics.Optimization.Implementation
public void EvaluateAt(Vector<double> point)
{
InnerObjectiveFunction.EvaluateAt(point);
_valueChecked = false;
_gradientChecked = false;
_hessianChecked = false;
}
public double Value
{
get
{
if (!_valueChecked)
{
double tmp;

12
src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs

@ -22,10 +22,6 @@ namespace MathNet.Numerics.Optimization.Implementation
public LineSearchOutput FindConformingStep(IObjectiveFunctionEvaluation startingPoint, Vector<double> searchDirection, double initialStep)
{
var objective = startingPoint.Fork();
if (!(objective is CheckedObjectiveFunction))
{
objective = new CheckedObjectiveFunction(objective, ValidateValue, ValidateGradient, null);
}
double lowerBound = 0.0;
double upperBound = Double.PositiveInfinity;
@ -42,6 +38,8 @@ namespace MathNet.Numerics.Optimization.Implementation
for (ii = 0; ii < _maximumIterations; ++ii)
{
objective.EvaluateAt(initialPoint + searchDirection * step);
ValidateGradient(objective);
ValidateValue(objective);
double stepDd = searchDirection * objective.Gradient;
@ -98,7 +96,7 @@ namespace MathNet.Numerics.Optimization.Implementation
return step > 0 && sufficientDecrease && notTooSteep;
}
void ValidateValue(IObjectiveFunction eval)
static void ValidateValue(IObjectiveFunction eval)
{
if (!IsFinite(eval.Value))
{
@ -106,7 +104,7 @@ namespace MathNet.Numerics.Optimization.Implementation
}
}
void ValidateGradient(IObjectiveFunction eval)
static void ValidateGradient(IObjectiveFunction eval)
{
foreach (double x in eval.Gradient)
{
@ -117,7 +115,7 @@ namespace MathNet.Numerics.Optimization.Implementation
}
}
bool IsFinite(double x)
static bool IsFinite(double x)
{
return !(Double.IsNaN(x) || Double.IsInfinity(x));
}

28
src/Numerics/Optimization/NewtonMinimizer.cs

@ -30,13 +30,9 @@ namespace MathNet.Numerics.Optimization
throw new IncompatibleObjectiveException("Hessian not supported in objective function, but required for Newton minimization.");
}
if (!(objective is CheckedObjectiveFunction))
{
objective = new CheckedObjectiveFunction(objective, ValidateObjective, ValidateGradient, ValidateHessian);
}
// Check that we're not already done
objective.EvaluateAt(initialGuess);
ValidateGradient(objective);
if (ExitCriteriaSatisfied(objective.Gradient))
{
return new MinimizationOutput(objective, 0, MinimizationOutput.ExitCondition.AbsoluteGradient);
@ -52,6 +48,8 @@ namespace MathNet.Numerics.Optimization
bool tmpLineSearch = false;
while (!ExitCriteriaSatisfied(objective.Gradient) && iterations < MaximumIterations)
{
ValidateHessian(objective);
var searchDirection = objective.Hessian.LU().Solve(-objective.Gradient);
if (searchDirection * objective.Gradient >= 0)
{
@ -70,6 +68,7 @@ namespace MathNet.Numerics.Optimization
{
throw new InnerOptimizationException("Line search failed.", e);
}
iterationsWithNontrivialLineSearch += result.Iterations > 0 ? 1 : 0;
totalLineSearchSteps += result.Iterations;
objective = result.FunctionInfoAtMinimum;
@ -79,8 +78,9 @@ namespace MathNet.Numerics.Optimization
objective.EvaluateAt(objective.Point + searchDirection);
}
tmpLineSearch = false;
ValidateGradient(objective);
tmpLineSearch = false;
iterations += 1;
}
@ -92,34 +92,32 @@ namespace MathNet.Numerics.Optimization
return new MinimizationWithLineSearchOutput(objective, iterations, MinimizationOutput.ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
}
private bool ExitCriteriaSatisfied(Vector<double> gradient)
bool ExitCriteriaSatisfied(Vector<double> gradient)
{
return gradient.Norm(2.0) < GradientTolerance;
}
private void ValidateGradient(IObjectiveFunction eval)
static void ValidateGradient(IObjectiveFunction eval)
{
foreach (var x in eval.Gradient)
{
if (Double.IsNaN(x) || Double.IsInfinity(x))
{
throw new EvaluationException("Non-finite gradient returned.", eval);
}
}
}
private void ValidateObjective(IObjectiveFunction eval)
{
if (Double.IsNaN(eval.Value) || Double.IsInfinity(eval.Value))
throw new EvaluationException("Non-finite objective function returned.", eval);
}
private void ValidateHessian(IObjectiveFunction eval)
static void ValidateHessian(IObjectiveFunction eval)
{
for (int ii = 0; ii < eval.Hessian.RowCount; ++ii)
{
for (int jj = 0; jj < eval.Hessian.ColumnCount; ++jj)
{
if (Double.IsNaN(eval.Hessian[ii, jj]) || Double.IsInfinity(eval.Hessian[ii, jj]))
{
throw new EvaluationException("Non-finite Hessian returned.", eval);
}
}
}
}

Loading…
Cancel
Save