Browse Source

Optimization: first pass code style fix

unified_optimization
Christoph Ruegg 12 years ago
parent
commit
c111019d38
  1. 31
      src/Numerics/Optimization/BaseEvaluation.cs
  2. 3
      src/Numerics/Optimization/Exceptions.cs
  3. 7
      src/Numerics/Optimization/IEvaluation.cs
  4. 9
      src/Numerics/Optimization/IUnconstrainedMinimizer.cs
  5. 13
      src/Numerics/Optimization/Implementation/LineSearchOutput.cs
  6. 14
      src/Numerics/Optimization/Implementation/NullEvaluation.cs
  7. 67
      src/Numerics/Optimization/Implementation/ObjectiveChecker.cs
  8. 119
      src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs
  9. 14
      src/Numerics/Optimization/MinimizationOutput.cs
  10. 15
      src/Numerics/Optimization/MinimizationWithLineSearchOutput.cs
  11. 78
      src/Numerics/Optimization/NewtonMinimizer.cs
  12. 6
      src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs

31
src/Numerics/Optimization/BaseEvaluation.cs

@ -1,9 +1,4 @@
using System; using MathNet.Numerics.LinearAlgebra;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Optimization namespace MathNet.Numerics.Optimization
{ {
@ -19,23 +14,23 @@ namespace MathNet.Numerics.Optimization
public bool GradientSupported { get; private set; } public bool GradientSupported { get; private set; }
public bool HessianSupported { get; private set; } public bool HessianSupported { get; private set; }
protected BaseEvaluation(bool gradient_supported, bool hessian_supported) protected BaseEvaluation(bool gradientSupported, bool hessianSupported)
{ {
Status = EvaluationStatus.None; Status = EvaluationStatus.None;
this.GradientSupported = gradient_supported; GradientSupported = gradientSupported;
this.HessianSupported = hessian_supported; HessianSupported = hessianSupported;
} }
public Vector<double> Point public Vector<double> Point
{ {
get get
{ {
return this.PointRaw; return PointRaw;
} }
set set
{ {
this.PointRaw = value; PointRaw = value;
this.Status = EvaluationStatus.None; Status = EvaluationStatus.None;
} }
} }
@ -45,7 +40,7 @@ namespace MathNet.Numerics.Optimization
{ {
if (!Status.HasFlag(EvaluationStatus.Value)) if (!Status.HasFlag(EvaluationStatus.Value))
{ {
setValue(); SetValue();
Status |= EvaluationStatus.Value; Status |= EvaluationStatus.Value;
} }
return ValueRaw; return ValueRaw;
@ -57,7 +52,7 @@ namespace MathNet.Numerics.Optimization
{ {
if (!Status.HasFlag(EvaluationStatus.Gradient)) if (!Status.HasFlag(EvaluationStatus.Gradient))
{ {
setGradient(); SetGradient();
Status |= EvaluationStatus.Gradient; Status |= EvaluationStatus.Gradient;
} }
return GradientRaw; return GradientRaw;
@ -69,16 +64,16 @@ namespace MathNet.Numerics.Optimization
{ {
if (!Status.HasFlag(EvaluationStatus.Hessian)) if (!Status.HasFlag(EvaluationStatus.Hessian))
{ {
setHessian(); SetHessian();
Status |= EvaluationStatus.Hessian; Status |= EvaluationStatus.Hessian;
} }
return HessianRaw; return HessianRaw;
} }
} }
protected abstract void setValue(); protected abstract void SetValue();
protected abstract void setGradient(); protected abstract void SetGradient();
protected abstract void setHessian(); protected abstract void SetHessian();
public abstract IEvaluation CreateNew(); public abstract IEvaluation CreateNew();
} }
} }

3
src/Numerics/Optimization/Exceptions.cs

@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MathNet.Numerics.Optimization namespace MathNet.Numerics.Optimization
{ {

7
src/Numerics/Optimization/IEvaluation.cs

@ -1,8 +1,5 @@
using MathNet.Numerics.LinearAlgebra; using System;
using System; using MathNet.Numerics.LinearAlgebra;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MathNet.Numerics.Optimization namespace MathNet.Numerics.Optimization
{ {

9
src/Numerics/Optimization/IUnconstrainedMinimizer.cs

@ -1,14 +1,9 @@
using System; using MathNet.Numerics.LinearAlgebra;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Optimization namespace MathNet.Numerics.Optimization
{ {
public interface IUnconstrainedMinimizer public interface IUnconstrainedMinimizer
{ {
MinimizationOutput FindMinimum(IEvaluation objective, Vector<double> initial_guess); MinimizationOutput FindMinimum(IEvaluation objective, Vector<double> initialGuess);
} }
} }

13
src/Numerics/Optimization/Implementation/LineSearchOutput.cs

@ -1,18 +1,13 @@
using System; namespace MathNet.Numerics.Optimization.Implementation
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MathNet.Numerics.Optimization.Implementation
{ {
public class LineSearchOutput : MinimizationOutput public class LineSearchOutput : MinimizationOutput
{ {
public double FinalStep { get; private set; } public double FinalStep { get; private set; }
public LineSearchOutput(IEvaluation function_info, int iterations, double final_step, ExitCondition reason_for_exit) public LineSearchOutput(IEvaluation functionInfo, int iterations, double finalStep, ExitCondition reasonForExit)
: base(function_info, iterations, reason_for_exit) : base(functionInfo, iterations, reasonForExit)
{ {
this.FinalStep = final_step; FinalStep = finalStep;
} }
} }
} }

14
src/Numerics/Optimization/Implementation/NullEvaluation.cs

@ -1,30 +1,26 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Optimization.Implementation namespace MathNet.Numerics.Optimization.Implementation
{ {
public class NullEvaluation : BaseEvaluation public class NullEvaluation : BaseEvaluation
{ {
public NullEvaluation(Vector<double> point) public NullEvaluation(Vector<double> point)
: base(false, false) : base(false, false)
{ {
this.Point = point; Point = point;
} }
protected override void setValue() protected override void SetValue()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
protected override void setGradient() protected override void SetGradient()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
protected override void setHessian() protected override void SetHessian()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

67
src/Numerics/Optimization/Implementation/ObjectiveChecker.cs

@ -1,34 +1,31 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Optimization.Implementation namespace MathNet.Numerics.Optimization.Implementation
{ {
public class CheckedEvaluation : IEvaluation public class CheckedEvaluation : IEvaluation
{ {
private bool _valueChecked;
private bool _gradientChecked;
private bool _hessianChecked;
public IEvaluation InnerEvaluation { get; private set; } public IEvaluation InnerEvaluation { get; private set; }
private bool ValueChecked;
private bool GradientChecked;
private bool HessianChecked;
public Action<IEvaluation> ValueChecker { get; private set; } public Action<IEvaluation> ValueChecker { get; private set; }
public Action<IEvaluation> GradientChecker { get; private set; } public Action<IEvaluation> GradientChecker { get; private set; }
public Action<IEvaluation> HessianChecker { get; private set; } public Action<IEvaluation> HessianChecker { get; private set; }
public CheckedEvaluation(IEvaluation objective, Action<IEvaluation> valueChecker, Action<IEvaluation> gradientChecker, Action<IEvaluation> hessianChecker)
public CheckedEvaluation(IEvaluation objective, Action<IEvaluation> value_checker, Action<IEvaluation> gradient_checker, Action<IEvaluation> hessian_checker)
{ {
this.InnerEvaluation = objective; InnerEvaluation = objective;
this.ValueChecker = value_checker; ValueChecker = valueChecker;
this.GradientChecker = gradient_checker; GradientChecker = gradientChecker;
this.HessianChecker = hessian_checker; HessianChecker = hessianChecker;
} }
public Vector<double> Point public Vector<double> Point
{ {
get { return this.InnerEvaluation.Point; } get { return InnerEvaluation.Point; }
set { this.InnerEvaluation.Point = value; } set { InnerEvaluation.Point = value; }
} }
public double Value public double Value
@ -36,21 +33,21 @@ namespace MathNet.Numerics.Optimization.Implementation
get get
{ {
if (!this.ValueChecked) if (!_valueChecked)
{ {
double tmp; double tmp;
try try
{ {
tmp = this.InnerEvaluation.Value; tmp = InnerEvaluation.Value;
} }
catch (Exception e) catch (Exception e)
{ {
throw new EvaluationException("Objective function evaluation failed.", this.InnerEvaluation, e); throw new EvaluationException("Objective function evaluation failed.", InnerEvaluation, e);
} }
this.ValueChecker(this.InnerEvaluation); ValueChecker(InnerEvaluation);
this.ValueChecked = true; _valueChecked = true;
} }
return this.InnerEvaluation.Value; return InnerEvaluation.Value;
} }
} }
@ -59,21 +56,21 @@ namespace MathNet.Numerics.Optimization.Implementation
get get
{ {
if (!this.GradientChecked) if (!_gradientChecked)
{ {
Vector<double> tmp; Vector<double> tmp;
try try
{ {
tmp = this.InnerEvaluation.Gradient; tmp = InnerEvaluation.Gradient;
} }
catch (Exception e) catch (Exception e)
{ {
throw new EvaluationException("Objective gradient evaluation failed.", this.InnerEvaluation, e); throw new EvaluationException("Objective gradient evaluation failed.", InnerEvaluation, e);
} }
this.GradientChecker(this.InnerEvaluation); GradientChecker(InnerEvaluation);
this.GradientChecked = true; _gradientChecked = true;
} }
return this.InnerEvaluation.Gradient; return InnerEvaluation.Gradient;
} }
} }
@ -82,37 +79,37 @@ namespace MathNet.Numerics.Optimization.Implementation
get get
{ {
if (!this.HessianChecked) if (!_hessianChecked)
{ {
Matrix<double> tmp; Matrix<double> tmp;
try try
{ {
tmp = this.InnerEvaluation.Hessian; tmp = InnerEvaluation.Hessian;
} }
catch (Exception e) catch (Exception e)
{ {
throw new EvaluationException("Objective hessian evaluation failed.", this.InnerEvaluation, e); throw new EvaluationException("Objective hessian evaluation failed.", InnerEvaluation, e);
} }
this.HessianChecker(InnerEvaluation); HessianChecker(InnerEvaluation);
this.HessianChecked = true; _hessianChecked = true;
} }
return this.InnerEvaluation.Hessian; return InnerEvaluation.Hessian;
} }
} }
public IEvaluation CreateNew() public IEvaluation CreateNew()
{ {
return new CheckedEvaluation(this.InnerEvaluation, this.ValueChecker, this.GradientChecker, this.HessianChecker); return new CheckedEvaluation(InnerEvaluation, ValueChecker, GradientChecker, HessianChecker);
} }
public bool GradientSupported public bool GradientSupported
{ {
get { return this.InnerEvaluation.GradientSupported; } get { return InnerEvaluation.GradientSupported; }
} }
public bool HessianSupported public bool HessianSupported
{ {
get { return this.InnerEvaluation.HessianSupported; } get { return InnerEvaluation.HessianSupported; }
} }
} }
} }

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

@ -1,117 +1,122 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Optimization.Implementation namespace MathNet.Numerics.Optimization.Implementation
{ {
public class WeakWolfeLineSearch public class WeakWolfeLineSearch
{ {
public double C1 { get; set; } readonly double _c1;
public double C2 { get; set; } readonly double _c2;
public double ParameterTolerance { get; set; } readonly double _parameterTolerance;
public int MaximumIterations { get; set; } readonly int _maximumIterations;
public WeakWolfeLineSearch(double c1, double c2, double parameter_tolerance, int max_iterations = 10) public WeakWolfeLineSearch(double c1, double c2, double parameterTolerance, int maxIterations = 10)
{ {
this.C1 = c1; _c1 = c1;
this.C2 = c2; _c2 = c2;
this.ParameterTolerance = parameter_tolerance; _parameterTolerance = parameterTolerance;
this.MaximumIterations = max_iterations; _maximumIterations = maxIterations;
} }
// Implemented following http://www.math.washington.edu/~burke/crs/408/lectures/L9-weak-Wolfe.pdf // Implemented following http://www.math.washington.edu/~burke/crs/408/lectures/L9-weak-Wolfe.pdf
public LineSearchOutput FindConformingStep(IEvaluation objective, IEvaluation starting_point, Vector<double> search_direction, double initial_step) public LineSearchOutput FindConformingStep(IEvaluation objective, IEvaluation startingPoint, Vector<double> searchDirection, double initialStep)
{ {
if (!(objective is CheckedEvaluation)) if (!(objective is CheckedEvaluation))
objective = new CheckedEvaluation(objective, this.ValidateValue, this.ValidateGradient, null); {
objective = new CheckedEvaluation(objective, ValidateValue, ValidateGradient, null);
}
double lower_bound = 0.0; double lowerBound = 0.0;
double upper_bound = Double.PositiveInfinity; double upperBound = Double.PositiveInfinity;
double step = initial_step; double step = initialStep;
double initial_value = starting_point.Value; double initialValue = startingPoint.Value;
Vector<double> initial_gradient = starting_point.Gradient; Vector<double> initialGradient = startingPoint.Gradient;
double initial_dd = search_direction * initial_gradient; double initialDd = searchDirection * initialGradient;
int ii; int ii;
IEvaluation candidate_eval = objective.CreateNew(); IEvaluation candidateEval = objective.CreateNew();
MinimizationOutput.ExitCondition reason_for_exit = MinimizationOutput.ExitCondition.None; MinimizationOutput.ExitCondition reasonForExit = MinimizationOutput.ExitCondition.None;
for (ii = 0; ii < this.MaximumIterations; ++ii) for (ii = 0; ii < _maximumIterations; ++ii)
{ {
candidate_eval.Point = starting_point.Point + search_direction * step; candidateEval.Point = startingPoint.Point + searchDirection * step;
double step_dd = search_direction * candidate_eval.Gradient; double stepDd = searchDirection * candidateEval.Gradient;
if (candidate_eval.Value > initial_value + this.C1 * step * initial_dd) if (candidateEval.Value > initialValue + _c1 * step * initialDd)
{ {
upper_bound = step; upperBound = step;
step = 0.5 * (lower_bound + upper_bound); step = 0.5 * (lowerBound + upperBound);
} }
else if (step_dd < this.C2 * initial_dd) else if (stepDd < _c2 * initialDd)
{ {
lower_bound = step; lowerBound = step;
step = Double.IsPositiveInfinity(upper_bound) ? 2 * lower_bound : 0.5 * (lower_bound + upper_bound); step = Double.IsPositiveInfinity(upperBound) ? 2 * lowerBound : 0.5 * (lowerBound + upperBound);
} }
else else
{ {
reason_for_exit = MinimizationOutput.ExitCondition.WeakWolfeCriteria; reasonForExit = MinimizationOutput.ExitCondition.WeakWolfeCriteria;
break; break;
} }
if (!Double.IsInfinity(upper_bound)) if (!Double.IsInfinity(upperBound))
{ {
double max_rel_change = 0.0; double maxRelChange = 0.0;
for (int jj = 0; jj < candidate_eval.Point.Count; ++jj) for (int jj = 0; jj < candidateEval.Point.Count; ++jj)
{ {
double tmp = Math.Abs(search_direction[jj] * (upper_bound - lower_bound)) / Math.Max(Math.Abs(candidate_eval.Point[jj]), 1.0); double tmp = Math.Abs(searchDirection[jj] * (upperBound - lowerBound)) / Math.Max(Math.Abs(candidateEval.Point[jj]), 1.0);
max_rel_change = Math.Max(max_rel_change, tmp); maxRelChange = Math.Max(maxRelChange, tmp);
} }
if (max_rel_change < this.ParameterTolerance) if (maxRelChange < _parameterTolerance)
{ {
reason_for_exit = MinimizationOutput.ExitCondition.LackOfProgress; reasonForExit = MinimizationOutput.ExitCondition.LackOfProgress;
break; break;
} }
} }
} }
if (ii == this.MaximumIterations && Double.IsPositiveInfinity(upper_bound)) if (ii == _maximumIterations && Double.IsPositiveInfinity(upperBound))
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached. Function appears to be unbounded in search direction.", this.MaximumIterations)); {
else if (ii == this.MaximumIterations) throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached. Function appears to be unbounded in search direction.", _maximumIterations));
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", this.MaximumIterations)); }
else
return new LineSearchOutput(candidate_eval, ii, step, reason_for_exit); if (ii == _maximumIterations)
{
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", _maximumIterations));
}
return new LineSearchOutput(candidateEval, ii, step, reasonForExit);
} }
private bool Conforms(IEvaluation starting_point, Vector<double> search_direction, double step, IEvaluation ending_point) bool Conforms(IEvaluation startingPoint, Vector<double> searchDirection, double step, IEvaluation endingPoint)
{ {
bool sufficientDecrease = endingPoint.Value <= startingPoint.Value + _c1 * step * (startingPoint.Gradient * searchDirection);
bool notTooSteep = endingPoint.Gradient * searchDirection >= _c2 * startingPoint.Gradient * searchDirection;
bool sufficient_decrease = ending_point.Value <= starting_point.Value + this.C1 * step * (starting_point.Gradient * search_direction); return step > 0 && sufficientDecrease && notTooSteep;
bool not_too_steep = ending_point.Gradient * search_direction >= this.C2 * starting_point.Gradient * search_direction;
return step > 0 && sufficient_decrease && not_too_steep;
} }
private void ValidateValue(IEvaluation eval) void ValidateValue(IEvaluation eval)
{ {
if (!this.IsFinite(eval.Value)) if (!IsFinite(eval.Value))
{
throw new EvaluationException(String.Format("Non-finite value returned by objective function: {0}", eval.Value), eval); throw new EvaluationException(String.Format("Non-finite value returned by objective function: {0}", eval.Value), eval);
}
} }
private void ValidateGradient(IEvaluation eval) void ValidateGradient(IEvaluation eval)
{ {
foreach (double x in eval.Gradient) foreach (double x in eval.Gradient)
if (!this.IsFinite(x)) {
if (!IsFinite(x))
{ {
throw new EvaluationException(String.Format("Non-finite value returned by gradient: {0}", x), eval); throw new EvaluationException(String.Format("Non-finite value returned by gradient: {0}", x), eval);
} }
}
} }
private bool IsFinite(double x) bool IsFinite(double x)
{ {
return !(Double.IsNaN(x) || Double.IsInfinity(x)); return !(Double.IsNaN(x) || Double.IsInfinity(x));
} }

14
src/Numerics/Optimization/MinimizationOutput.cs

@ -1,8 +1,4 @@
using System; using MathNet.Numerics.LinearAlgebra;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.LinearAlgebra;
namespace MathNet.Numerics.Optimization namespace MathNet.Numerics.Optimization
{ {
@ -15,11 +11,11 @@ namespace MathNet.Numerics.Optimization
public int Iterations { get; private set; } public int Iterations { get; private set; }
public ExitCondition ReasonForExit { get; private set; } public ExitCondition ReasonForExit { get; private set; }
public MinimizationOutput(IEvaluation function_info, int iterations, ExitCondition reason_for_exit) public MinimizationOutput(IEvaluation functionInfo, int iterations, ExitCondition reasonForExit)
{ {
this.FunctionInfoAtMinimum = function_info; FunctionInfoAtMinimum = functionInfo;
this.Iterations = iterations; Iterations = iterations;
this.ReasonForExit = reason_for_exit; ReasonForExit = reasonForExit;
} }
} }
} }

15
src/Numerics/Optimization/MinimizationWithLineSearchOutput.cs

@ -1,20 +1,15 @@
using System; namespace MathNet.Numerics.Optimization
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MathNet.Numerics.Optimization
{ {
public class MinimizationWithLineSearchOutput : MinimizationOutput public class MinimizationWithLineSearchOutput : MinimizationOutput
{ {
public int TotalLineSearchIterations { get; private set; } public int TotalLineSearchIterations { get; private set; }
public int IterationsWithNonTrivialLineSearch { get; private set; } public int IterationsWithNonTrivialLineSearch { get; private set; }
public MinimizationWithLineSearchOutput(IEvaluation function_info, int iterations, ExitCondition reason_for_exit, int total_line_search_iterations, int iterations_with_non_trivial_line_search) public MinimizationWithLineSearchOutput(IEvaluation functionInfo, int iterations, ExitCondition reasonForExit, int totalLineSearchIterations, int iterationsWithNonTrivialLineSearch)
: base(function_info, iterations, reason_for_exit) : base(functionInfo, iterations, reasonForExit)
{ {
this.TotalLineSearchIterations = total_line_search_iterations; TotalLineSearchIterations = totalLineSearchIterations;
this.IterationsWithNonTrivialLineSearch = iterations_with_non_trivial_line_search; IterationsWithNonTrivialLineSearch = iterationsWithNonTrivialLineSearch;
} }
} }
} }

78
src/Numerics/Optimization/NewtonMinimizer.cs

@ -1,10 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra;
using LU = MathNet.Numerics.LinearAlgebra.Factorization.LU<double>;
using MathNet.Numerics.Optimization.Implementation; using MathNet.Numerics.Optimization.Implementation;
using LU = MathNet.Numerics.LinearAlgebra.Factorization.LU<double>;
namespace MathNet.Numerics.Optimization namespace MathNet.Numerics.Optimization
{ {
@ -14,14 +11,14 @@ namespace MathNet.Numerics.Optimization
public int MaximumIterations { get; set; } public int MaximumIterations { get; set; }
public bool UseLineSearch { get; set; } public bool UseLineSearch { get; set; }
public NewtonMinimizer(double gradient_tolerance, int maximum_iterations, bool use_line_search = false) public NewtonMinimizer(double gradientTolerance, int maximumIterations, bool useLineSearch = false)
{ {
this.GradientTolerance = gradient_tolerance; GradientTolerance = gradientTolerance;
this.MaximumIterations = maximum_iterations; MaximumIterations = maximumIterations;
this.UseLineSearch = use_line_search; UseLineSearch = useLineSearch;
} }
public MinimizationOutput FindMinimum(IEvaluation objective, Vector<double> initial_guess) public MinimizationOutput FindMinimum(IEvaluation objective, Vector<double> initialGuess)
{ {
if (!objective.GradientSupported) if (!objective.GradientSupported)
throw new IncompatibleObjectiveException("Gradient not supported in objective function, but required for Newton minimization."); throw new IncompatibleObjectiveException("Gradient not supported in objective function, but required for Newton minimization.");
@ -30,74 +27,69 @@ namespace MathNet.Numerics.Optimization
throw new IncompatibleObjectiveException("Hessian not supported in objective function, but required for Newton minimization."); throw new IncompatibleObjectiveException("Hessian not supported in objective function, but required for Newton minimization.");
if (!(objective is CheckedEvaluation)) if (!(objective is CheckedEvaluation))
objective = new CheckedEvaluation(objective, this.ValidateObjective, this.ValidateGradient, this.ValidateHessian); objective = new CheckedEvaluation(objective, ValidateObjective, ValidateGradient, ValidateHessian);
IEvaluation initial_eval = objective.CreateNew(); IEvaluation initialEval = objective.CreateNew();
initial_eval.Point = initial_guess; initialEval.Point = initialGuess;
// Check that we're not already done // Check that we're not already done
if (this.ExitCriteriaSatisfied(initial_guess, initial_eval.Gradient)) if (ExitCriteriaSatisfied(initialGuess, initialEval.Gradient))
return new MinimizationOutput(initial_eval, 0, MinimizationOutput.ExitCondition.AbsoluteGradient); return new MinimizationOutput(initialEval, 0, MinimizationOutput.ExitCondition.AbsoluteGradient);
// Set up line search algorithm // Set up line search algorithm
var line_searcher = new WeakWolfeLineSearch(1e-4, 0.9, 1e-4, max_iterations: 1000); var lineSearcher = new WeakWolfeLineSearch(1e-4, 0.9, 1e-4, maxIterations: 1000);
// Declare state variables // Declare state variables
IEvaluation candidate_point = initial_eval; IEvaluation candidatePoint = initialEval;
Vector<double> search_direction;
LineSearchOutput result;
// Subsequent steps // Subsequent steps
int iterations = 0; int iterations = 0;
int total_line_search_steps = 0; int totalLineSearchSteps = 0;
int iterations_with_nontrivial_line_search = 0; int iterationsWithNontrivialLineSearch = 0;
int steepest_descent_resets = 0; bool tmpLineSearch = false;
bool tmp_line_search = false; while (!ExitCriteriaSatisfied(candidatePoint.Point, candidatePoint.Gradient) && iterations < MaximumIterations)
while (!this.ExitCriteriaSatisfied(candidate_point.Point, candidate_point.Gradient) && iterations < this.MaximumIterations)
{ {
var searchDirection = candidatePoint.Hessian.LU().Solve(-candidatePoint.Gradient);
search_direction = candidate_point.Hessian.LU().Solve(-candidate_point.Gradient); if (searchDirection * candidatePoint.Gradient >= 0)
if (search_direction * candidate_point.Gradient >= 0)
{ {
search_direction = -candidate_point.Gradient; searchDirection = -candidatePoint.Gradient;
steepest_descent_resets += 1; tmpLineSearch = true;
tmp_line_search = true;
} }
if (this.UseLineSearch || tmp_line_search) if (UseLineSearch || tmpLineSearch)
{ {
LineSearchOutput result;
try try
{ {
result = line_searcher.FindConformingStep(objective, candidate_point, search_direction, 1.0); result = lineSearcher.FindConformingStep(objective, candidatePoint, searchDirection, 1.0);
} }
catch (Exception e) catch (Exception e)
{ {
throw new InnerOptimizationException("Line search failed.", e); throw new InnerOptimizationException("Line search failed.", e);
} }
iterations_with_nontrivial_line_search += result.Iterations > 0 ? 1 : 0; iterationsWithNontrivialLineSearch += result.Iterations > 0 ? 1 : 0;
total_line_search_steps += result.Iterations; totalLineSearchSteps += result.Iterations;
candidate_point = result.FunctionInfoAtMinimum; candidatePoint = result.FunctionInfoAtMinimum;
} }
else else
{ {
candidate_point.Point = candidate_point.Point + search_direction; candidatePoint.Point = candidatePoint.Point + searchDirection;
} }
tmp_line_search = false; tmpLineSearch = false;
iterations += 1; iterations += 1;
} }
if (iterations == this.MaximumIterations) if (iterations == MaximumIterations)
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", this.MaximumIterations)); throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", MaximumIterations));
return new MinimizationWithLineSearchOutput(candidate_point, iterations, MinimizationOutput.ExitCondition.AbsoluteGradient, total_line_search_steps, iterations_with_nontrivial_line_search); return new MinimizationWithLineSearchOutput(candidatePoint, iterations, MinimizationOutput.ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch);
} }
private bool ExitCriteriaSatisfied(Vector<double> candidate_point, Vector<double> gradient) private bool ExitCriteriaSatisfied(Vector<double> candidatePoint, Vector<double> gradient)
{ {
return gradient.Norm(2.0) < this.GradientTolerance; return gradient.Norm(2.0) < GradientTolerance;
} }
private void ValidateGradient(IEvaluation eval) private void ValidateGradient(IEvaluation eval)

6
src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs

@ -14,17 +14,17 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
public RosenbrockEvaluation() public RosenbrockEvaluation()
: base(true, true) { } : base(true, true) { }
protected override void setValue() protected override void SetValue()
{ {
this.ValueRaw = RosenbrockFunction.Value(this.Point); this.ValueRaw = RosenbrockFunction.Value(this.Point);
} }
protected override void setGradient() protected override void SetGradient()
{ {
this.GradientRaw = RosenbrockFunction.Gradient(this.Point); this.GradientRaw = RosenbrockFunction.Gradient(this.Point);
} }
protected override void setHessian() protected override void SetHessian()
{ {
this.HessianRaw = RosenbrockFunction.Hessian(this.Point); this.HessianRaw = RosenbrockFunction.Hessian(this.Point);
} }

Loading…
Cancel
Save