From 7139108a19a5b77656c4c67a861288d3eaeb157b Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Fri, 15 May 2015 10:47:00 +0200 Subject: [PATCH] Optimization: InplaceObjectiveFunction --- src/Numerics/Numerics.csproj | 1 + .../Optimization/BaseObjectiveFunction.cs | 10 +-- .../InplaceObjectiveFunction.cs | 62 +++++++++++++++++++ .../OptimizationTests/TestNewtonMinimizer.cs | 26 +++++++- 4 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 src/Numerics/Optimization/ObjectiveFunctions/InplaceObjectiveFunction.cs 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 }));