diff --git a/src/Numerics/Optimization/BaseObjectiveFunction.cs b/src/Numerics/Optimization/BaseObjectiveFunction.cs index b41d2dbc..e85b5e7d 100644 --- a/src/Numerics/Optimization/BaseObjectiveFunction.cs +++ b/src/Numerics/Optimization/BaseObjectiveFunction.cs @@ -11,14 +11,14 @@ namespace MathNet.Numerics.Optimization protected Vector GradientRaw { get; set; } protected Matrix HessianRaw { get; set; } - public bool GradientSupported { get; private set; } - public bool HessianSupported { get; private set; } + public bool IsGradientSupported { get; private set; } + public bool IsHessianSupported { get; private set; } protected BaseObjectiveFunction(bool gradientSupported, bool hessianSupported) { Status = EvaluationStatus.None; - GradientSupported = gradientSupported; - HessianSupported = hessianSupported; + IsGradientSupported = gradientSupported; + IsHessianSupported = hessianSupported; } public Vector Point @@ -34,6 +34,12 @@ namespace MathNet.Numerics.Optimization } } + public void EvaluateAt(Vector point) + { + PointRaw = point; + Status = EvaluationStatus.None; + } + public double Value { get @@ -71,9 +77,10 @@ namespace MathNet.Numerics.Optimization } } + public abstract IObjectiveFunction Fork(); + protected abstract void SetValue(); protected abstract void SetGradient(); protected abstract void SetHessian(); - public abstract IObjectiveFunction CreateNew(); } } diff --git a/src/Numerics/Optimization/IObjectiveFunction.cs b/src/Numerics/Optimization/IObjectiveFunction.cs index 65c58230..bc335ded 100644 --- a/src/Numerics/Optimization/IObjectiveFunction.cs +++ b/src/Numerics/Optimization/IObjectiveFunction.cs @@ -4,18 +4,26 @@ using MathNet.Numerics.LinearAlgebra; namespace MathNet.Numerics.Optimization { [Flags] - public enum EvaluationStatus { None = 0, Value = 1, Gradient = 2, Hessian = 4 } + public enum EvaluationStatus + { + None = 0, + Value = 1, + Gradient = 2, + Hessian = 4 + } public interface IObjectiveFunction { - Vector Point { get; set; } - IObjectiveFunction CreateNew(); + void EvaluateAt(Vector point); + IObjectiveFunction Fork(); - // Used by algorithm - bool GradientSupported { get; } - bool HessianSupported { get; } + Vector Point { get; } double Value { get; } + + bool IsGradientSupported { get; } Vector Gradient { get; } + + bool IsHessianSupported { get; } Matrix Hessian { get; } } } diff --git a/src/Numerics/Optimization/Implementation/CheckedObjectiveFunction.cs b/src/Numerics/Optimization/Implementation/CheckedObjectiveFunction.cs index 2cd5db1f..04159fc7 100644 --- a/src/Numerics/Optimization/Implementation/CheckedObjectiveFunction.cs +++ b/src/Numerics/Optimization/Implementation/CheckedObjectiveFunction.cs @@ -25,7 +25,11 @@ namespace MathNet.Numerics.Optimization.Implementation public Vector Point { get { return InnerObjectiveFunction.Point; } - set { InnerObjectiveFunction.Point = value; } + } + + public void EvaluateAt(Vector point) + { + InnerObjectiveFunction.EvaluateAt(point); } public double Value @@ -97,19 +101,19 @@ namespace MathNet.Numerics.Optimization.Implementation } } - public IObjectiveFunction CreateNew() + public IObjectiveFunction Fork() { return new CheckedObjectiveFunction(InnerObjectiveFunction, ValueChecker, GradientChecker, HessianChecker); } - public bool GradientSupported + public bool IsGradientSupported { - get { return InnerObjectiveFunction.GradientSupported; } + get { return InnerObjectiveFunction.IsGradientSupported; } } - public bool HessianSupported + public bool IsHessianSupported { - get { return InnerObjectiveFunction.HessianSupported; } + get { return InnerObjectiveFunction.IsHessianSupported; } } } } diff --git a/src/Numerics/Optimization/Implementation/NullObjectiveFunction.cs b/src/Numerics/Optimization/Implementation/NullObjectiveFunction.cs index 159da526..a279a620 100644 --- a/src/Numerics/Optimization/Implementation/NullObjectiveFunction.cs +++ b/src/Numerics/Optimization/Implementation/NullObjectiveFunction.cs @@ -10,6 +10,7 @@ namespace MathNet.Numerics.Optimization.Implementation { Point = point; } + protected override void SetValue() { throw new NotImplementedException(); @@ -25,7 +26,7 @@ namespace MathNet.Numerics.Optimization.Implementation throw new NotImplementedException(); } - public override IObjectiveFunction CreateNew() + public override IObjectiveFunction Fork() { throw new NotImplementedException(); } diff --git a/src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs b/src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs index 6003ba20..8d291ab1 100644 --- a/src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs +++ b/src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs @@ -36,11 +36,11 @@ namespace MathNet.Numerics.Optimization.Implementation double initialDd = searchDirection * initialGradient; int ii; - IObjectiveFunction candidateEval = objective.CreateNew(); + IObjectiveFunction candidateEval = objective.Fork(); MinimizationOutput.ExitCondition reasonForExit = MinimizationOutput.ExitCondition.None; for (ii = 0; ii < _maximumIterations; ++ii) { - candidateEval.Point = startingPoint.Point + searchDirection * step; + candidateEval.EvaluateAt(startingPoint.Point + searchDirection * step); double stepDd = searchDirection * candidateEval.Gradient; diff --git a/src/Numerics/Optimization/NewtonMinimizer.cs b/src/Numerics/Optimization/NewtonMinimizer.cs index 2654c477..69cb7193 100644 --- a/src/Numerics/Optimization/NewtonMinimizer.cs +++ b/src/Numerics/Optimization/NewtonMinimizer.cs @@ -20,17 +20,17 @@ namespace MathNet.Numerics.Optimization public MinimizationOutput FindMinimum(IObjectiveFunction objective, Vector initialGuess) { - if (!objective.GradientSupported) + if (!objective.IsGradientSupported) throw new IncompatibleObjectiveException("Gradient not supported in objective function, but required for Newton minimization."); - if (!objective.HessianSupported) + if (!objective.IsHessianSupported) 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); - IObjectiveFunction initialEval = objective.CreateNew(); - initialEval.Point = initialGuess; + IObjectiveFunction initialEval = objective.Fork(); + initialEval.EvaluateAt(initialGuess); // Check that we're not already done if (ExitCriteriaSatisfied(initialGuess, initialEval.Gradient)) @@ -73,7 +73,7 @@ namespace MathNet.Numerics.Optimization } else { - candidatePoint.Point = candidatePoint.Point + searchDirection; + candidatePoint.EvaluateAt(candidatePoint.Point + searchDirection); } tmpLineSearch = false; diff --git a/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs b/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs index d7f910d7..d6d45d4f 100644 --- a/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs +++ b/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs @@ -25,7 +25,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests HessianRaw = RosenbrockFunction.Hessian(Point); } - public override IObjectiveFunction CreateNew() + public override IObjectiveFunction Fork() { return new RosenbrockObjectiveFunction(); }