forked from tsai/mathnet-numerics
committed by
Erik Ovegard
3 changed files with 166 additions and 3 deletions
@ -1,6 +1,70 @@ |
|||
namespace MathNet.Numerics.Optimization |
|||
using System; |
|||
|
|||
namespace MathNet.Numerics.Optimization |
|||
{ |
|||
class GoldenSectionMinimizer |
|||
public class GoldenSectionMinimizer |
|||
{ |
|||
public double XTolerance { get; set; } |
|||
public int MaximumIterations { get; set; } |
|||
|
|||
public GoldenSectionMinimizer(double xTolerance=1e-5, int maxIterations=1000) |
|||
{ |
|||
XTolerance = xTolerance; |
|||
MaximumIterations = maxIterations; |
|||
} |
|||
|
|||
public MinimizationResult FindMinimum(IObjectiveFunction1D objective, double lowerBound, double upperBound) |
|||
{ |
|||
double middlePointX = lowerBound + (upperBound - lowerBound) / (1 + Constants.GoldenRatio); |
|||
IEvaluation1D lower = objective.Evaluate(lowerBound); |
|||
IEvaluation1D middle = objective.Evaluate(middlePointX); |
|||
IEvaluation1D upper = objective.Evaluate(upperBound); |
|||
|
|||
ValueChecker(lower.Value, lowerBound); |
|||
ValueChecker(middle.Value, middlePointX); |
|||
ValueChecker(upper.Value, upperBound); |
|||
|
|||
if (upperBound <= lowerBound) |
|||
throw new OptimizationException("Lower bound must be lower than upper bound."); |
|||
|
|||
if (upper.Value < middle.Value || lower.Value < middle.Value) |
|||
throw new OptimizationException("Lower and upper bounds do not necessarily bound a minimum."); |
|||
|
|||
int iterations = 0; |
|||
while (Math.Abs(upper.Point - lower.Point) > XTolerance && iterations < MaximumIterations) |
|||
{ |
|||
double testX = lower.Point + (upper.Point - middle.Point); |
|||
var test = objective.Evaluate(testX); |
|||
ValueChecker(test.Value, testX); |
|||
|
|||
if (test.Value > middle.Value) |
|||
{ |
|||
if (test.Point < middle.Point) |
|||
lower = test; |
|||
else |
|||
upper = test; |
|||
} |
|||
else |
|||
{ |
|||
if (test.Point < middle.Point) |
|||
upper = middle; |
|||
else |
|||
lower = middle; |
|||
} |
|||
|
|||
iterations += 1; |
|||
} |
|||
|
|||
if (iterations == MaximumIterations) |
|||
throw new MaximumIterationsException("Max iterations reached."); |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private void ValueChecker(double value, double point) |
|||
{ |
|||
if (Double.IsNaN(value) || Double.IsInfinity(value)) |
|||
throw new Exception("Objective function returned non-finite value."); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,98 @@ |
|||
using System; |
|||
|
|||
namespace MathNet.Numerics.Optimization |
|||
{ |
|||
public interface IEvaluation1D |
|||
{ |
|||
double Point { get; } |
|||
double Value { get; } |
|||
double Derivative { get; } |
|||
double SecondDerivative { get; } |
|||
} |
|||
|
|||
public interface IObjectiveFunction1D |
|||
{ |
|||
bool DerivativeSupported { get; } |
|||
bool SecondDerivativeSupported { get; } |
|||
IEvaluation1D Evaluate(double point); |
|||
} |
|||
|
|||
public class CachedEvaluation1D : IEvaluation1D |
|||
{ |
|||
private double? _value; |
|||
private double? _derivative; |
|||
private double? _secondDerivative; |
|||
private readonly SimpleObjectiveFunction1D _objectiveObject; |
|||
private readonly double _point; |
|||
|
|||
public CachedEvaluation1D(SimpleObjectiveFunction1D f, double point) |
|||
{ |
|||
_objectiveObject = f; |
|||
_point = point; |
|||
} |
|||
private double SetValue() |
|||
{ |
|||
_value = _objectiveObject.Objective(_point); |
|||
return _value.Value; |
|||
} |
|||
private double SetDerivative() |
|||
{ |
|||
_derivative = _objectiveObject.Derivative(_point); |
|||
return _derivative.Value; |
|||
} |
|||
private double SetSecondDerivative() |
|||
{ |
|||
_secondDerivative = _objectiveObject.SecondDerivative(_point); |
|||
return _secondDerivative.Value; |
|||
} |
|||
|
|||
public double Point { get { return _point; } } |
|||
public double Value { get { return _value ?? SetValue(); } } |
|||
public double Derivative { get { return _derivative ?? SetDerivative(); } } |
|||
public double SecondDerivative { get { return _secondDerivative ?? SetSecondDerivative(); } } |
|||
|
|||
} |
|||
|
|||
public class SimpleObjectiveFunction1D : IObjectiveFunction1D |
|||
{ |
|||
public Func<double, double> Objective { get; private set; } |
|||
public Func<double, double> Derivative { get; private set; } |
|||
public Func<double, double> SecondDerivative { get; private set; } |
|||
|
|||
public SimpleObjectiveFunction1D(Func<double, double> objective) |
|||
{ |
|||
Objective = objective; |
|||
Derivative = null; |
|||
SecondDerivative = null; |
|||
} |
|||
|
|||
public SimpleObjectiveFunction1D(Func<double, double> objective, Func<double, double> derivative) |
|||
{ |
|||
Objective = objective; |
|||
Derivative = derivative; |
|||
SecondDerivative = null; |
|||
} |
|||
|
|||
public SimpleObjectiveFunction1D(Func<double, double> objective, Func<double, double> derivative, Func<double,double> secondDerivative) |
|||
{ |
|||
Objective = objective; |
|||
Derivative = derivative; |
|||
SecondDerivative = secondDerivative; |
|||
} |
|||
|
|||
public bool DerivativeSupported |
|||
{ |
|||
get { return Derivative != null; } |
|||
} |
|||
|
|||
public bool SecondDerivativeSupported |
|||
{ |
|||
get { return SecondDerivative != null; } |
|||
} |
|||
|
|||
public IEvaluation1D Evaluate(double point) |
|||
{ |
|||
return new CachedEvaluation1D(this, point); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue