forked from tsai/mathnet-numerics
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