Browse Source

Optimization: ExitCondition is no longer nested in MinimizationResult

v3
Christoph Ruegg 9 years ago
parent
commit
a1372e624f
  1. 1
      src/Numerics/Numerics.csproj
  2. 8
      src/Numerics/Optimization/BfgsBMinimizer.cs
  3. 10
      src/Numerics/Optimization/BfgsMinimizer.cs
  4. 18
      src/Numerics/Optimization/BfgsMinimizerBase.cs
  5. 4
      src/Numerics/Optimization/ConjugateGradientMinimizer.cs
  6. 43
      src/Numerics/Optimization/ExitCondition.cs
  7. 2
      src/Numerics/Optimization/GoldenSectionMinimizer.cs
  8. 4
      src/Numerics/Optimization/LineSearch/StrongWolfeLineSearch.cs
  9. 8
      src/Numerics/Optimization/LineSearch/WeakWolfeLineSearch.cs
  10. 6
      src/Numerics/Optimization/LineSearch/WolfeLineSearch.cs
  11. 13
      src/Numerics/Optimization/MinimizationResult.cs
  12. 4
      src/Numerics/Optimization/MinimizationResult1D.cs
  13. 6
      src/Numerics/Optimization/NelderMeadSimplex.cs
  14. 4
      src/Numerics/Optimization/NewtonMinimizer.cs

1
src/Numerics/Numerics.csproj

@ -116,6 +116,7 @@
<Compile Include="OdeSolvers\AdamsBashforth.cs" />
<Compile Include="OdeSolvers\RungeKutta.cs" />
<Compile Include="Optimization\BfgsMinimizerBase.cs" />
<Compile Include="Optimization\ExitCondition.cs" />
<Compile Include="Optimization\LineSearch\WolfeLineSearch.cs" />
<Compile Include="Optimization\NelderMeadSimplex.cs" />
<Compile Include="Optimization\ObjectiveFunctions\ForwardDifferenceGradientObjectiveFunction.cs" />

8
src/Numerics/Optimization/BfgsBMinimizer.cs

@ -74,8 +74,8 @@ namespace MathNet.Numerics.Optimization
ValidateGradientAndObjective(objective);
// Check that we're not already done
MinimizationResult.ExitCondition currentExitCondition = ExitCriteriaSatisfied(objective, null, 0);
if (currentExitCondition != MinimizationResult.ExitCondition.None)
ExitCondition currentExitCondition = ExitCriteriaSatisfied(objective, null, 0);
if (currentExitCondition != ExitCondition.None)
return new MinimizationResult(objective, 0, currentExitCondition);
// Set up line search algorithm
@ -149,13 +149,13 @@ namespace MathNet.Numerics.Optimization
int iterations = DoBfgsUpdate(ref currentExitCondition, lineSearcher, ref pseudoHessian, ref lineSearchDirection, ref previousPoint, ref lineSearchResult, ref candidatePoint, ref step, ref totalLineSearchSteps, ref iterationsWithNontrivialLineSearch);
if (iterations == MaximumIterations && currentExitCondition == MinimizationResult.ExitCondition.None)
if (iterations == MaximumIterations && currentExitCondition == ExitCondition.None)
throw new MaximumIterationsException(string.Format("Maximum iterations ({0}) reached.", MaximumIterations));
return new MinimizationWithLineSearchResult(candidatePoint, iterations, currentExitCondition, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
}
protected override Vector<double> CalculateSearchDirection(ref Matrix<double> pseudoHessian,
protected override Vector<double> CalculateSearchDirection(ref Matrix<double> pseudoHessian,
out double maxLineSearchStep,
out double startingStepSize,
IObjectiveFunction previousPoint,

10
src/Numerics/Optimization/BfgsMinimizer.cs

@ -65,8 +65,8 @@ namespace MathNet.Numerics.Optimization
ValidateGradientAndObjective(objective);
// Check that we're not already done
MinimizationResult.ExitCondition currentExitCondition = ExitCriteriaSatisfied(objective, null, 0);
if (currentExitCondition != MinimizationResult.ExitCondition.None)
ExitCondition currentExitCondition = ExitCriteriaSatisfied(objective, null, 0);
if (currentExitCondition != ExitCondition.None)
return new MinimizationResult(objective, 0, currentExitCondition);
// Set up line search algorithm
@ -106,17 +106,17 @@ namespace MathNet.Numerics.Optimization
int iterationsWithNontrivialLineSearch = lineSearchResult.Iterations > 0 ? 0 : 1;
iterations = DoBfgsUpdate(ref currentExitCondition, lineSearcher, ref inversePseudoHessian, ref lineSearchDirection, ref previousPoint, ref lineSearchResult, ref candidate, ref step, ref totalLineSearchSteps, ref iterationsWithNontrivialLineSearch);
if (iterations == MaximumIterations && currentExitCondition == MinimizationResult.ExitCondition.None)
if (iterations == MaximumIterations && currentExitCondition == ExitCondition.None)
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", MaximumIterations));
return new MinimizationWithLineSearchResult(candidate, iterations, MinimizationResult.ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
return new MinimizationWithLineSearchResult(candidate, iterations, ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
}
protected override Vector<double> CalculateSearchDirection(ref Matrix<double> inversePseudoHessian,
out double maxLineSearchStep,
out double startingStepSize,
IObjectiveFunction previousPoint,
IObjectiveFunction candidate,
IObjectiveFunction candidate,
Vector<double> step)
{
startingStepSize = 1.0;

18
src/Numerics/Optimization/BfgsMinimizerBase.cs

@ -58,7 +58,7 @@ namespace MathNet.Numerics.Optimization
MaximumIterations = maximumIterations;
}
protected MinimizationResult.ExitCondition ExitCriteriaSatisfied(IObjectiveFunctionEvaluation candidatePoint, IObjectiveFunctionEvaluation lastPoint, int iterations)
protected ExitCondition ExitCriteriaSatisfied(IObjectiveFunctionEvaluation candidatePoint, IObjectiveFunctionEvaluation lastPoint, int iterations)
{
Vector<double> relGrad = new DenseVector(candidatePoint.Point.Count);
double relativeGradient = 0.0;
@ -67,13 +67,13 @@ namespace MathNet.Numerics.Optimization
{
double projectedGradient = GetProjectedGradient(candidatePoint, ii);
double tmp = projectedGradient *
double tmp = projectedGradient *
Math.Max(Math.Abs(candidatePoint.Point[ii]), 1.0) / normalizer;
relativeGradient = Math.Max(relativeGradient, Math.Abs(tmp));
}
if (relativeGradient < GradientTolerance)
{
return MinimizationResult.ExitCondition.RelativeGradient;
return ExitCondition.RelativeGradient;
}
if (lastPoint != null)
@ -81,21 +81,21 @@ namespace MathNet.Numerics.Optimization
double mostProgress = 0.0;
for (int ii = 0; ii < candidatePoint.Point.Count; ++ii)
{
var tmp = Math.Abs(candidatePoint.Point[ii] - lastPoint.Point[ii]) /
var tmp = Math.Abs(candidatePoint.Point[ii] - lastPoint.Point[ii]) /
Math.Max(Math.Abs(lastPoint.Point[ii]), 1.0);
mostProgress = Math.Max(mostProgress, tmp);
}
if (mostProgress < ParameterTolerance)
{
return MinimizationResult.ExitCondition.LackOfProgress;
return ExitCondition.LackOfProgress;
}
double functionChange = candidatePoint.Value - lastPoint.Value;
if (iterations > 500 && functionChange < 0 && Math.Abs(functionChange) < FunctionProgressTolerance)
return MinimizationResult.ExitCondition.LackOfProgress;
return ExitCondition.LackOfProgress;
}
return MinimizationResult.ExitCondition.None;
return ExitCondition.None;
}
protected virtual double GetProjectedGradient(IObjectiveFunctionEvaluation candidatePoint, int ii)
@ -114,7 +114,7 @@ namespace MathNet.Numerics.Optimization
throw new EvaluationException("Non-finite objective function returned.", eval);
}
protected int DoBfgsUpdate(ref MinimizationResult.ExitCondition currentExitCondition, WolfeLineSearch lineSearcher, ref Matrix<double> inversePseudoHessian, ref Vector<double> lineSearchDirection, ref IObjectiveFunction previousPoint, ref LineSearchResult lineSearchResult, ref IObjectiveFunction candidate, ref Vector<double> step, ref int totalLineSearchSteps, ref int iterationsWithNontrivialLineSearch)
protected int DoBfgsUpdate(ref ExitCondition currentExitCondition, WolfeLineSearch lineSearcher, ref Matrix<double> inversePseudoHessian, ref Vector<double> lineSearchDirection, ref IObjectiveFunction previousPoint, ref LineSearchResult lineSearchResult, ref IObjectiveFunction candidate, ref Vector<double> step, ref int totalLineSearchSteps, ref int iterationsWithNontrivialLineSearch)
{
int iterations;
for (iterations = 1; iterations < MaximumIterations; ++iterations)
@ -140,7 +140,7 @@ namespace MathNet.Numerics.Optimization
candidate = lineSearchResult.FunctionInfoAtMinimum;
currentExitCondition = ExitCriteriaSatisfied(candidate, previousPoint, iterations);
if (currentExitCondition != MinimizationResult.ExitCondition.None)
if (currentExitCondition != ExitCondition.None)
break;
}

4
src/Numerics/Optimization/ConjugateGradientMinimizer.cs

@ -55,7 +55,7 @@ namespace MathNet.Numerics.Optimization
// Check that we're not already done
if (ExitCriteriaSatisfied(initialGuess, gradient))
return new MinimizationResult(objective, 0, MinimizationResult.ExitCondition.AbsoluteGradient);
return new MinimizationResult(objective, 0, ExitCondition.AbsoluteGradient);
// Set up line search algorithm
var lineSearcher = new WeakWolfeLineSearch(1e-4, 0.1, 1e-4, 1000);
@ -118,7 +118,7 @@ namespace MathNet.Numerics.Optimization
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", MaximumIterations));
}
return new MinimizationWithLineSearchResult(objective, iterations, MinimizationResult.ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
return new MinimizationWithLineSearchResult(objective, iterations, ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
}
bool ExitCriteriaSatisfied(Vector<double> candidatePoint, Vector<double> gradient)

43
src/Numerics/Optimization/ExitCondition.cs

@ -0,0 +1,43 @@
// <copyright file="ExitCondition.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2017 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.Optimization
{
public enum ExitCondition
{
None,
RelativeGradient,
LackOfProgress,
AbsoluteGradient,
WeakWolfeCriteria,
BoundTolerance,
StrongWolfeCriteria,
Converged
}
}

2
src/Numerics/Optimization/GoldenSectionMinimizer.cs

@ -124,7 +124,7 @@ namespace MathNet.Numerics.Optimization
if (iterations == MaximumIterations)
throw new MaximumIterationsException("Max iterations reached.");
return new MinimizationResult1D(middle, iterations, MinimizationResult.ExitCondition.BoundTolerance);
return new MinimizationResult1D(middle, iterations, ExitCondition.BoundTolerance);
}
void ValueChecker(double value, double point)

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

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

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

@ -38,9 +38,9 @@ namespace MathNet.Numerics.Optimization.LineSearch
/// i) Armijo Rule: f(x_k + alpha_k p_k) &lt;= f(x_k) + c1 alpha_k p_k^T g(x_k)
/// ii) Curvature Condition: p_k^T g(x_k + alpha_k p_k) &gt;= c2 p_k^T g(x_k)
/// where g(x) is the gradient of f(x), 0 &lt; c1 &lt; c2 &lt; 1.
///
///
/// Implementation is based on http://www.math.washington.edu/~burke/crs/408/lectures/L9-weak-Wolfe.pdf
///
///
/// references:
/// http://en.wikipedia.org/wiki/Wolfe_conditions
/// http://www.math.washington.edu/~burke/crs/408/lectures/L9-weak-Wolfe.pdf
@ -53,9 +53,9 @@ namespace MathNet.Numerics.Optimization.LineSearch
// Validation in base class
}
protected override MinimizationResult.ExitCondition WolfeExitCondition
protected override ExitCondition WolfeExitCondition
{
get { return MinimizationResult.ExitCondition.WeakWolfeCriteria; }
get { return ExitCondition.WeakWolfeCriteria; }
}
protected override bool WolfeCondition(double stepDd, double initialDd)

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

@ -82,7 +82,7 @@ namespace MathNet.Numerics.Optimization.LineSearch
IObjectiveFunction objective = startingPoint.CreateNew();
int ii;
MinimizationResult.ExitCondition reasonForExit = MinimizationResult.ExitCondition.None;
ExitCondition reasonForExit = ExitCondition.None;
for (ii = 0; ii < MaximumIterations; ++ii)
{
objective.EvaluateAt(startingPoint.Point + searchDirection * step);
@ -117,7 +117,7 @@ namespace MathNet.Numerics.Optimization.LineSearch
}
if (maxRelChange < ParameterTolerance)
{
reasonForExit = MinimizationResult.ExitCondition.LackOfProgress;
reasonForExit = ExitCondition.LackOfProgress;
break;
}
}
@ -136,7 +136,7 @@ namespace MathNet.Numerics.Optimization.LineSearch
return new LineSearchResult(objective, ii, step, reasonForExit);
}
protected abstract MinimizationResult.ExitCondition WolfeExitCondition { get; }
protected abstract ExitCondition WolfeExitCondition { get; }
protected abstract bool WolfeCondition(double stepDd, double initialDd);

13
src/Numerics/Optimization/MinimizationResult.cs

@ -33,19 +33,6 @@ namespace MathNet.Numerics.Optimization
{
public class MinimizationResult
{
public enum ExitCondition
{
None,
RelativeGradient,
LackOfProgress,
AbsoluteGradient,
WeakWolfeCriteria,
BoundTolerance,
StrongWolfeCriteria,
LackOfFunctionImprovement,
Converged
}
public Vector<double> MinimizingPoint { get { return FunctionInfoAtMinimum.Point; } }
public IObjectiveFunction FunctionInfoAtMinimum { get; private set; }
public int Iterations { get; private set; }

4
src/Numerics/Optimization/MinimizationResult1D.cs

@ -34,9 +34,9 @@ namespace MathNet.Numerics.Optimization
public double MinimizingPoint { get { return FunctionInfoAtMinimum.Point; } }
public IEvaluation1D FunctionInfoAtMinimum { get; private set; }
public int Iterations { get; private set; }
public MinimizationResult.ExitCondition ReasonForExit { get; private set; }
public ExitCondition ReasonForExit { get; private set; }
public MinimizationResult1D(IEvaluation1D functionInfo, int iterations, MinimizationResult.ExitCondition reasonForExit)
public MinimizationResult1D(IEvaluation1D functionInfo, int iterations, ExitCondition reasonForExit)
{
FunctionInfoAtMinimum = functionInfo;
Iterations = iterations;

6
src/Numerics/Optimization/NelderMeadSimplex.cs

@ -100,7 +100,7 @@ namespace MathNet.Numerics.Optimization
double[] errorValues = new double[numVertices];
int evaluationCount = 0;
MinimizationResult.ExitCondition exitCondition = MinimizationResult.ExitCondition.None;
ExitCondition exitCondition = ExitCondition.None;
ErrorProfile errorProfile;
errorValues = InitializeErrorValues(vertices, objectiveFunction);
@ -113,7 +113,7 @@ namespace MathNet.Numerics.Optimization
// see if the range in point heights is small enough to exit
if (HasConverged(ConvergenceTolerance, errorProfile, errorValues))
{
exitCondition = MinimizationResult.ExitCondition.Converged;
exitCondition = ExitCondition.Converged;
break;
}
@ -135,7 +135,7 @@ namespace MathNet.Numerics.Optimization
++evaluationCount;
if (contractionPointValue >= currentWorst)
{
// that would be even worse, so let's try to contract uniformly towards the low point;
// that would be even worse, so let's try to contract uniformly towards the low point;
// don't bother to update the error profile, we'll do it at the start of the
// next iteration
ShrinkSimplex(errorProfile, vertices, errorValues, objectiveFunction);

4
src/Numerics/Optimization/NewtonMinimizer.cs

@ -63,7 +63,7 @@ namespace MathNet.Numerics.Optimization
ValidateGradient(objective);
if (ExitCriteriaSatisfied(objective.Gradient))
{
return new MinimizationResult(objective, 0, MinimizationResult.ExitCondition.AbsoluteGradient);
return new MinimizationResult(objective, 0, ExitCondition.AbsoluteGradient);
}
// Set up line search algorithm
@ -117,7 +117,7 @@ namespace MathNet.Numerics.Optimization
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", MaximumIterations));
}
return new MinimizationWithLineSearchResult(objective, iterations, MinimizationResult.ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
return new MinimizationWithLineSearchResult(objective, iterations, ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
}
bool ExitCriteriaSatisfied(Vector<double> gradient)

Loading…
Cancel
Save