diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj
index af581d56..2370e819 100644
--- a/src/Numerics/Numerics.csproj
+++ b/src/Numerics/Numerics.csproj
@@ -104,6 +104,7 @@
+
diff --git a/src/Numerics/Optimization/BaseObjectiveFunction.cs b/src/Numerics/Optimization/BaseObjectiveFunction.cs
index 3e1fbd2d..ed7f1331 100644
--- a/src/Numerics/Optimization/BaseObjectiveFunction.cs
+++ b/src/Numerics/Optimization/BaseObjectiveFunction.cs
@@ -33,15 +33,7 @@ namespace MathNet.Numerics.Optimization
public Vector Point
{
- get
- {
- return PointRaw;
- }
- set
- {
- PointRaw = value;
- Status = EvaluationStatus.None;
- }
+ get { return PointRaw; }
}
public void EvaluateAt(Vector point)
diff --git a/src/Numerics/Optimization/ObjectiveFunctions/InplaceObjectiveFunction.cs b/src/Numerics/Optimization/ObjectiveFunctions/InplaceObjectiveFunction.cs
new file mode 100644
index 00000000..d2554dfb
--- /dev/null
+++ b/src/Numerics/Optimization/ObjectiveFunctions/InplaceObjectiveFunction.cs
@@ -0,0 +1,62 @@
+using MathNet.Numerics.LinearAlgebra;
+
+namespace MathNet.Numerics.Optimization.ObjectiveFunctions
+{
+ public abstract class InplaceObjectiveFunction : IObjectiveFunction
+ {
+ Vector _point;
+ double _functionValue;
+ Vector _gradientValue;
+ Matrix _hessianValue;
+
+ protected InplaceObjectiveFunction(bool isGradientSupported, bool isHessianSupported)
+ {
+ IsGradientSupported = isGradientSupported;
+ IsHessianSupported = isHessianSupported;
+ }
+
+ public abstract IObjectiveFunction CreateNew();
+
+ public virtual IObjectiveFunction Fork()
+ {
+ // no need to deep-clone values since they are replaced on evaluation
+ InplaceObjectiveFunction objective = (InplaceObjectiveFunction)CreateNew();
+ objective._point = _point == null ? null : _point.Clone();
+ objective._functionValue = _functionValue;
+ objective._gradientValue = _gradientValue == null ? null : _gradientValue.Clone();
+ objective._hessianValue = _hessianValue == null ? null : _hessianValue.Clone();
+ return objective;
+ }
+
+ public bool IsGradientSupported { get; private set; }
+ public bool IsHessianSupported { get; private set; }
+
+ public void EvaluateAt(Vector point)
+ {
+ _point = point;
+ EvaluateAt(_point, ref _functionValue, ref _gradientValue, ref _hessianValue);
+ }
+
+ protected abstract void EvaluateAt(Vector point, ref double value, ref Vector gradient, ref Matrix hessian);
+
+ public Vector Point
+ {
+ get { return _point; }
+ }
+
+ public double Value
+ {
+ get { return _functionValue; }
+ }
+
+ public Vector Gradient
+ {
+ get { return _gradientValue; }
+ }
+
+ public Matrix Hessian
+ {
+ get { return _hessianValue; }
+ }
+ }
+}
diff --git a/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs b/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs
index ad8bb32f..85912a65 100644
--- a/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs
+++ b/src/UnitTests/OptimizationTests/TestNewtonMinimizer.cs
@@ -1,14 +1,15 @@
using System;
+using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.Optimization;
+using MathNet.Numerics.Optimization.ObjectiveFunctions;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.OptimizationTests
{
public class RosenbrockObjectiveFunction : BaseObjectiveFunction
{
- public RosenbrockObjectiveFunction()
- : base(true, true) { }
+ public RosenbrockObjectiveFunction() : base(true, true) { }
protected override void SetValue()
{
@@ -31,6 +32,25 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
}
}
+ public class InplaceRosenbrockObjectiveFunction : InplaceObjectiveFunction
+ {
+ public InplaceRosenbrockObjectiveFunction() : base(true, true) { }
+
+ public override IObjectiveFunction CreateNew()
+ {
+ return new InplaceRosenbrockObjectiveFunction();
+ }
+
+ protected override void EvaluateAt(Vector point, ref double value, ref Vector gradient, ref Matrix hessian)
+ {
+ // here we could directly overwrite the existing matrices instead.
+ // note: values must then be initialized manually here first, if null.
+ value = RosenbrockFunction.Value(point);
+ gradient = RosenbrockFunction.Gradient(point);
+ hessian = RosenbrockFunction.Hessian(point);
+ }
+ }
+
[TestFixture]
public class TestNewtonMinimizer
{
@@ -70,7 +90,7 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
[Test]
public void FindMinimum_Linesearch_Rosenbrock_Easy()
{
- var obj = new RosenbrockObjectiveFunction();
+ var obj = new InplaceRosenbrockObjectiveFunction();
var solver = new NewtonMinimizer(1e-5, 1000, true);
var result = solver.FindMinimum(obj, new DenseVector(new[] { 1.2, 1.2 }));