diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj
index a478aab5..370d2a0d 100644
--- a/src/Numerics/Numerics.csproj
+++ b/src/Numerics/Numerics.csproj
@@ -122,8 +122,6 @@
-
-
diff --git a/src/Numerics/Optimization/BaseEvaluation.cs b/src/Numerics/Optimization/BaseEvaluation.cs
index fa19f5e8..c1a703bc 100644
--- a/src/Numerics/Optimization/BaseEvaluation.cs
+++ b/src/Numerics/Optimization/BaseEvaluation.cs
@@ -9,15 +9,34 @@ namespace MathNet.Numerics.Optimization
{
public abstract class BaseEvaluation : IEvaluation
{
- public EvaluationStatus Status { get; set; }
- public Vector Point { get; set; }
- public double ValueRaw { get; set; }
- public Vector GradientRaw { get; set; }
- public Matrix HessianRaw { get; set; }
-
- protected BaseEvaluation()
+ public EvaluationStatus Status { get; protected set; }
+
+ protected Vector PointRaw { get; set; }
+ protected double ValueRaw { get; set; }
+ protected Vector GradientRaw { get; set; }
+ protected Matrix HessianRaw { get; set; }
+
+ public bool GradientSupported { get; private set; }
+ public bool HessianSupported { get; private set; }
+
+ protected BaseEvaluation(bool gradient_supported, bool hessian_supported)
{
Status = EvaluationStatus.None;
+ this.GradientSupported = gradient_supported;
+ this.HessianSupported = hessian_supported;
+ }
+
+ public Vector Point
+ {
+ get
+ {
+ return this.PointRaw;
+ }
+ set
+ {
+ this.PointRaw = value;
+ this.Status = EvaluationStatus.None;
+ }
}
public double Value
@@ -57,14 +76,9 @@ namespace MathNet.Numerics.Optimization
}
}
- public void Reset(Vector new_point)
- {
- this.Point = new_point;
- this.Status = EvaluationStatus.None;
- }
-
protected abstract void setValue();
protected abstract void setGradient();
protected abstract void setHessian();
+ public abstract IEvaluation CreateNew();
}
}
diff --git a/src/Numerics/Optimization/BaseObjectiveFunction.cs b/src/Numerics/Optimization/BaseObjectiveFunction.cs
deleted file mode 100644
index 5cd5f68f..00000000
--- a/src/Numerics/Optimization/BaseObjectiveFunction.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace MathNet.Numerics.Optimization
-{
- public class BaseObjectiveFunction : IObjectiveFunction where T : IEvaluation
- {
- public BaseObjectiveFunction(bool gradient_supported, bool hessian_supported)
- {
- _gradient_supported = gradient_supported;
- _hessian_supported = hessian_supported;
- }
-
- private bool _gradient_supported;
- private bool _hessian_supported;
-
- public bool GradientSupported
- {
- get { return _gradient_supported; }
- }
-
- public bool HessianSupported
- {
- get { return _hessian_supported; }
- }
-
- public void Evaluate(LinearAlgebra.Vector point, IEvaluation output)
- {
- output.Reset(point);
- }
-
- public virtual IEvaluation CreateEvaluationObject()
- {
- return default(T);
- }
- }
-}
diff --git a/src/Numerics/Optimization/IEvaluation.cs b/src/Numerics/Optimization/IEvaluation.cs
index 9150d5fd..9ee1a83a 100644
--- a/src/Numerics/Optimization/IEvaluation.cs
+++ b/src/Numerics/Optimization/IEvaluation.cs
@@ -12,17 +12,14 @@ namespace MathNet.Numerics.Optimization
public interface IEvaluation
{
Vector Point { get; set; }
- EvaluationStatus Status { get; set; }
+ IEvaluation CreateNew();
// Used by algorithm
+ bool GradientSupported { get; }
+ bool HessianSupported { get; }
+ EvaluationStatus Status { get; }
double Value { get; }
Vector Gradient { get; }
Matrix Hessian { get; }
-
- // Used by ObjectiveFunction
- void Reset(Vector new_point);
- double ValueRaw { get; set; }
- Vector GradientRaw { get; set; }
- Matrix HessianRaw { get; set; }
}
}
diff --git a/src/Numerics/Optimization/IObjectiveFunction.cs b/src/Numerics/Optimization/IObjectiveFunction.cs
deleted file mode 100644
index cd553ac2..00000000
--- a/src/Numerics/Optimization/IObjectiveFunction.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using MathNet.Numerics.LinearAlgebra;
-
-namespace MathNet.Numerics.Optimization
-{
- public interface IObjectiveFunction
- {
- bool GradientSupported { get; }
- bool HessianSupported { get; }
-
- IEvaluation CreateEvaluationObject();
- void Evaluate(Vector point, IEvaluation output);
- }
-}
diff --git a/src/Numerics/Optimization/IUnconstrainedMinimizer.cs b/src/Numerics/Optimization/IUnconstrainedMinimizer.cs
index d7200b01..37ac4928 100644
--- a/src/Numerics/Optimization/IUnconstrainedMinimizer.cs
+++ b/src/Numerics/Optimization/IUnconstrainedMinimizer.cs
@@ -8,7 +8,7 @@ namespace MathNet.Numerics.Optimization
{
public interface IUnconstrainedMinimizer
{
- MinimizationOutput FindMinimum(IObjectiveFunction objective, Vector initial_guess);
+ MinimizationOutput FindMinimum(IEvaluation objective, Vector initial_guess);
}
}
diff --git a/src/Numerics/Optimization/Implementation/NullEvaluation.cs b/src/Numerics/Optimization/Implementation/NullEvaluation.cs
index fcc31c4b..521419f3 100644
--- a/src/Numerics/Optimization/Implementation/NullEvaluation.cs
+++ b/src/Numerics/Optimization/Implementation/NullEvaluation.cs
@@ -10,7 +10,7 @@ namespace MathNet.Numerics.Optimization.Implementation
public class NullEvaluation : BaseEvaluation
{
public NullEvaluation(Vector point)
- : base()
+ : base(false, false)
{
this.Point = point;
}
@@ -28,5 +28,10 @@ namespace MathNet.Numerics.Optimization.Implementation
{
throw new NotImplementedException();
}
+
+ public override IEvaluation CreateNew()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/src/Numerics/Optimization/Implementation/ObjectiveChecker.cs b/src/Numerics/Optimization/Implementation/ObjectiveChecker.cs
index 3aa0d052..af6ef93d 100644
--- a/src/Numerics/Optimization/Implementation/ObjectiveChecker.cs
+++ b/src/Numerics/Optimization/Implementation/ObjectiveChecker.cs
@@ -8,16 +8,21 @@ namespace MathNet.Numerics.Optimization.Implementation
{
public class CheckedEvaluation : IEvaluation
{
- private ObjectiveChecker Checker;
public IEvaluation InnerEvaluation { get; private set; }
private bool ValueChecked;
private bool GradientChecked;
private bool HessianChecked;
+ public Action ValueChecker { get; private set; }
+ public Action GradientChecker { get; private set; }
+ public Action HessianChecker { get; private set; }
- public CheckedEvaluation(ObjectiveChecker checker, IEvaluation evaluation)
+
+ public CheckedEvaluation(IEvaluation objective, Action value_checker, Action gradient_checker, Action hessian_checker)
{
- this.Checker = checker;
- this.InnerEvaluation = evaluation;
+ this.InnerEvaluation = objective;
+ this.ValueChecker = value_checker;
+ this.GradientChecker = gradient_checker;
+ this.HessianChecker = hessian_checker;
}
public Vector Point
@@ -32,34 +37,6 @@ namespace MathNet.Numerics.Optimization.Implementation
{
return this.InnerEvaluation.Status;
}
- set
- {
- this.InnerEvaluation.Status = value;
- }
- }
-
- public double ValueRaw
- {
- get
- {
- return this.InnerEvaluation.Value;
- }
- set
- {
- this.InnerEvaluation.ValueRaw = value;
- }
- }
-
- public Vector GradientRaw
- {
- get { return this.InnerEvaluation.GradientRaw; }
- set { this.InnerEvaluation.GradientRaw = value; }
- }
-
- public Matrix HessianRaw
- {
- get { return this.InnerEvaluation.HessianRaw; }
- set { this.InnerEvaluation.HessianRaw = value; }
}
public double Value
@@ -78,7 +55,7 @@ namespace MathNet.Numerics.Optimization.Implementation
{
throw new EvaluationException("Objective function evaluation failed.", this.InnerEvaluation, e);
}
- this.Checker.ValueChecker(this.InnerEvaluation);
+ this.ValueChecker(this.InnerEvaluation);
this.ValueChecked = true;
}
return this.InnerEvaluation.Value;
@@ -101,7 +78,7 @@ namespace MathNet.Numerics.Optimization.Implementation
{
throw new EvaluationException("Objective gradient evaluation failed.", this.InnerEvaluation, e);
}
- this.Checker.GradientChecker(this.InnerEvaluation);
+ this.GradientChecker(this.InnerEvaluation);
this.GradientChecked = true;
}
return this.InnerEvaluation.Gradient;
@@ -124,60 +101,26 @@ namespace MathNet.Numerics.Optimization.Implementation
{
throw new EvaluationException("Objective hessian evaluation failed.", this.InnerEvaluation, e);
}
- this.Checker.HessianChecker(InnerEvaluation);
+ this.HessianChecker(InnerEvaluation);
this.HessianChecked = true;
}
return this.InnerEvaluation.Hessian;
}
}
- public void Reset(Vector new_point)
+ public IEvaluation CreateNew()
{
- this.InnerEvaluation.Reset(new_point);
- }
- }
-
- public class ObjectiveChecker : IObjectiveFunction
- {
- public IObjectiveFunction InnerObjective { get; private set; }
- public Action ValueChecker { get; private set; }
- public Action GradientChecker { get; private set; }
- public Action HessianChecker { get; private set; }
-
- public ObjectiveChecker(IObjectiveFunction objective, Action value_checker, Action gradient_checker, Action hessian_checker)
- {
- this.InnerObjective = objective;
- this.ValueChecker = value_checker;
- this.GradientChecker = gradient_checker;
- this.HessianChecker = hessian_checker;
+ return new CheckedEvaluation(this.InnerEvaluation, this.ValueChecker, this.GradientChecker, this.HessianChecker);
}
public bool GradientSupported
{
- get { return this.InnerObjective.GradientSupported; }
+ get { return this.InnerEvaluation.GradientSupported; }
}
public bool HessianSupported
{
- get { return this.InnerObjective.HessianSupported; }
- }
-
- public void Evaluate(Vector point, IEvaluation output)
- {
- try
- {
- this.InnerObjective.Evaluate(point, output);
- }
- catch (Exception e)
- {
- throw new EvaluationException("Objective evaluation failed.", new NullEvaluation(point), e);
- }
- }
-
-
- public IEvaluation CreateEvaluationObject()
- {
- return this.InnerObjective.CreateEvaluationObject();
+ get { return this.InnerEvaluation.HessianSupported; }
}
}
}
diff --git a/src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs b/src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs
index 605c424b..5a6642b5 100644
--- a/src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs
+++ b/src/Numerics/Optimization/Implementation/WeakWolfeLineSearch.cs
@@ -23,11 +23,11 @@ namespace MathNet.Numerics.Optimization.Implementation
}
// Implemented following http://www.math.washington.edu/~burke/crs/408/lectures/L9-weak-Wolfe.pdf
- public LineSearchOutput FindConformingStep(IObjectiveFunction objective, IEvaluation starting_point, Vector search_direction, double initial_step)
+ public LineSearchOutput FindConformingStep(IEvaluation objective, IEvaluation starting_point, Vector search_direction, double initial_step)
{
- if (!(objective is ObjectiveChecker))
- objective = new ObjectiveChecker(objective, this.ValidateValue, this.ValidateGradient, null);
+ if (!(objective is CheckedEvaluation))
+ objective = new CheckedEvaluation(objective, this.ValidateValue, this.ValidateGradient, null);
double lower_bound = 0.0;
double upper_bound = Double.PositiveInfinity;
@@ -39,11 +39,11 @@ namespace MathNet.Numerics.Optimization.Implementation
double initial_dd = search_direction * initial_gradient;
int ii;
- IEvaluation candidate_eval = objective.CreateEvaluationObject();
+ IEvaluation candidate_eval = objective.CreateNew();
MinimizationOutput.ExitCondition reason_for_exit = MinimizationOutput.ExitCondition.None;
for (ii = 0; ii < this.MaximumIterations; ++ii)
{
- objective.Evaluate(starting_point.Point + search_direction * step, candidate_eval);
+ candidate_eval.Point = starting_point.Point + search_direction * step;
double step_dd = search_direction * candidate_eval.Gradient;
diff --git a/src/Numerics/Optimization/NewtonMinimizer.cs b/src/Numerics/Optimization/NewtonMinimizer.cs
index 810c859f..5f17d738 100644
--- a/src/Numerics/Optimization/NewtonMinimizer.cs
+++ b/src/Numerics/Optimization/NewtonMinimizer.cs
@@ -21,7 +21,7 @@ namespace MathNet.Numerics.Optimization
this.UseLineSearch = use_line_search;
}
- public MinimizationOutput FindMinimum(IObjectiveFunction objective, Vector initial_guess)
+ public MinimizationOutput FindMinimum(IEvaluation objective, Vector initial_guess)
{
if (!objective.GradientSupported)
throw new IncompatibleObjectiveException("Gradient not supported in objective function, but required for Newton minimization.");
@@ -29,11 +29,11 @@ namespace MathNet.Numerics.Optimization
if (!objective.HessianSupported)
throw new IncompatibleObjectiveException("Hessian not supported in objective function, but required for Newton minimization.");
- if (!(objective is ObjectiveChecker))
- objective = new ObjectiveChecker(objective, this.ValidateObjective, this.ValidateGradient, this.ValidateHessian);
+ if (!(objective is CheckedEvaluation))
+ objective = new CheckedEvaluation(objective, this.ValidateObjective, this.ValidateGradient, this.ValidateHessian);
- IEvaluation initial_eval = objective.CreateEvaluationObject();
- objective.Evaluate(initial_guess, initial_eval);
+ IEvaluation initial_eval = objective.CreateNew();
+ initial_eval.Point = initial_guess;
// Check that we're not already done
if (this.ExitCriteriaSatisfied(initial_guess, initial_eval.Gradient))
@@ -81,7 +81,7 @@ namespace MathNet.Numerics.Optimization
}
else
{
- objective.Evaluate(candidate_point.Point + search_direction, candidate_point);
+ candidate_point.Point = candidate_point.Point + search_direction;
}
tmp_line_search = false;
diff --git a/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs b/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs
index fd6b6779..2fbca71e 100644
--- a/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs
+++ b/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs
@@ -11,9 +11,9 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
{
public class RosenbrockEvaluation : BaseEvaluation
{
- public const bool SupportsGradient = true;
- public const bool SupportsHessian = true;
-
+ public RosenbrockEvaluation()
+ : base(true, true) { }
+
protected override void setValue()
{
this.ValueRaw = RosenbrockFunction.Value(this.Point);
@@ -28,6 +28,11 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
{
this.HessianRaw = RosenbrockFunction.Hessian(this.Point);
}
+
+ public override IEvaluation CreateNew()
+ {
+ return new RosenbrockEvaluation();
+ }
}
[TestFixture]
@@ -37,7 +42,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
[Test]
public void FindMinimum_Rosenbrock_Easy()
{
- var obj = new BaseObjectiveFunction(RosenbrockEvaluation.SupportsGradient, RosenbrockEvaluation.SupportsHessian);
+ var obj = new RosenbrockEvaluation();
var solver = new NewtonMinimizer(1e-5, 1000);
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { 1.2, 1.2 }));
@@ -49,7 +54,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
[Test]
public void FindMinimum_Rosenbrock_Hard()
{
- var obj = new BaseObjectiveFunction(RosenbrockEvaluation.SupportsGradient, RosenbrockEvaluation.SupportsHessian);
+ var obj = new RosenbrockEvaluation();
var solver = new NewtonMinimizer(1e-5, 1000);
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -1.2, 1.0 }));
@@ -60,7 +65,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
[Test]
public void FindMinimum_Rosenbrock_Overton()
{
- var obj = new BaseObjectiveFunction(RosenbrockEvaluation.SupportsGradient, RosenbrockEvaluation.SupportsHessian);
+ var obj = new RosenbrockEvaluation();
var solver = new NewtonMinimizer(1e-5, 1000);
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -0.9, -0.5 }));
@@ -71,7 +76,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
[Test]
public void FindMinimum_Linesearch_Rosenbrock_Easy()
{
- var obj = new BaseObjectiveFunction(RosenbrockEvaluation.SupportsGradient, RosenbrockEvaluation.SupportsHessian);
+ var obj = new RosenbrockEvaluation();
var solver = new NewtonMinimizer(1e-5, 1000, true);
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { 1.2, 1.2 }));
@@ -82,7 +87,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
[Test]
public void FindMinimum_Linesearch_Rosenbrock_Hard()
{
- var obj = new BaseObjectiveFunction(RosenbrockEvaluation.SupportsGradient, RosenbrockEvaluation.SupportsHessian);
+ var obj = new RosenbrockEvaluation();
var solver = new NewtonMinimizer(1e-5, 1000, true);
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -1.2, 1.0 }));
@@ -93,7 +98,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
[Test]
public void FindMinimum_Linesearch_Rosenbrock_Overton()
{
- var obj = new BaseObjectiveFunction(RosenbrockEvaluation.SupportsGradient, RosenbrockEvaluation.SupportsHessian);
+ var obj = new RosenbrockEvaluation();
var solver = new NewtonMinimizer(1e-5, 1000, true);
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[] { -0.9, -0.5 }));