committed by
Erik Ovegard
8 changed files with 163 additions and 1 deletions
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace MathNet.Numerics.Optimization |
|||
{ |
|||
class BFGS |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
using System; |
|||
using MathNet.Numerics.LinearAlgebra; |
|||
using MathNet.Numerics.Optimization.LineSearch; |
|||
|
|||
namespace MathNet.Numerics.Optimization |
|||
{ |
|||
public class ConjugateGradientMinimizer |
|||
{ |
|||
public double GradientTolerance { get; set; } |
|||
public int MaximumIterations { get; set; } |
|||
|
|||
public ConjugateGradientMinimizer(double gradientTolerance, int maximumIterations) |
|||
{ |
|||
this.GradientTolerance = gradientTolerance; |
|||
this.MaximumIterations = maximumIterations; |
|||
} |
|||
|
|||
public MinimizationResult FindMinimum(IObjectiveFunction objective, Vector<double> initialGuess) |
|||
{ |
|||
if (!objective.IsGradientSupported) |
|||
throw new Exception("Gradient not supported in objective function, but required for ConjugateGradient minimization."); |
|||
|
|||
objective.EvaluateAt(initialGuess); |
|||
var gradient = objective.Gradient; |
|||
ValidateGradient(gradient, initialGuess); |
|||
|
|||
// Check that we're not already done
|
|||
if (ExitCriteriaSatisfied(initialGuess, gradient)) |
|||
return new MinimizationResult(objective, 0, MinimizationResult.ExitCondition.AbsoluteGradient); |
|||
|
|||
// Set up line search algorithm
|
|||
var lineSearcher = new WeakWolfeLineSearch(1e-4, 0.1, 1e-4, 1000); |
|||
|
|||
// First step
|
|||
var steepestDirection = -gradient; |
|||
var searchDirection = steepestDirection; |
|||
var result = lineSearcher.FindConformingStep(objective, searchDirection, 1.0); |
|||
objective = result.FunctionInfoAtMinimum; |
|||
ValidateGradient(objective.Gradient, objective.Point); |
|||
|
|||
// Subsequent steps
|
|||
int iterations = 1; |
|||
while (!ExitCriteriaSatisfied(objective.Point, objective.Gradient) && iterations < MaximumIterations) |
|||
{ |
|||
var previousSteepestDirection = steepestDirection; |
|||
steepestDirection = -objective.Gradient; |
|||
var searchDirectionAdjuster = steepestDirection * (steepestDirection - previousSteepestDirection) / (previousSteepestDirection * previousSteepestDirection); |
|||
searchDirection = steepestDirection + searchDirectionAdjuster * previousSteepestDirection; |
|||
result = lineSearcher.FindConformingStep(objective, searchDirection, 1.0); |
|||
|
|||
objective = result.FunctionInfoAtMinimum; |
|||
iterations += 1; |
|||
} |
|||
|
|||
return new MinimizationResult(objective, iterations, MinimizationResult.ExitCondition.AbsoluteGradient); |
|||
} |
|||
|
|||
private bool ExitCriteriaSatisfied(Vector<double> candidatePoint, Vector<double> gradient) |
|||
{ |
|||
return gradient.Norm(2.0) < GradientTolerance; |
|||
} |
|||
|
|||
private void ValidateGradient(Vector<double> gradient, Vector<double> input) |
|||
{ |
|||
foreach (var x in gradient) |
|||
{ |
|||
if (Double.IsNaN(x) || Double.IsInfinity(x)) |
|||
throw new Exception("Non-finite gradient returned."); |
|||
} |
|||
} |
|||
|
|||
private void ValidateObjective(double objective, Vector<double> input) |
|||
{ |
|||
if (Double.IsNaN(objective) || Double.IsInfinity(objective)) |
|||
throw new Exception("Non-finite objective function returned."); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
namespace MathNet.Numerics.Optimization |
|||
{ |
|||
class GoldenSectionMinimizer |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace MathNet.Numerics.Optimization |
|||
{ |
|||
class StrongWolfeLineSearch |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace MathNet.Numerics.Optimization |
|||
{ |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
using NUnit.Framework; |
|||
|
|||
using MathNet.Numerics.Optimization; |
|||
|
|||
namespace MathNet.Numerics.UnitTests.OptimizationTests |
|||
{ |
|||
[TestFixture] |
|||
public class TestConjugateGradientMinimizer |
|||
{ |
|||
|
|||
[Test] |
|||
public void FindMinimum_Rosenbrock_Easy() |
|||
{ |
|||
var obj = new SimpleObjectiveFunction(RosenbrockFunction.Value, RosenbrockFunction.Gradient); |
|||
var solver = new ConjugateGradientMinimizer(1e-5, 100); |
|||
var result = solver.FindMinimum(obj, new MathNet.Numerics.LinearAlgebra.Double.DenseVector(new double[]{1.2,1.2})); |
|||
Assert.That(result.MinimizingPoint[0], Is.EqualTo(1.0)); |
|||
Assert.That(result.MinimizingPoint[1], Is.EqualTo(1.0)); |
|||
} |
|||
|
|||
[Test] |
|||
public void FindMinimum_Rosenbrock_Hard() |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue