Browse Source

Very minimally tested ConjugateGradient minimizer is complete.

unified_optimization
Scott Stephens 14 years ago
committed by Christoph Ruegg
parent
commit
edbab552eb
  1. 26
      src/Numerics/Optimization/ConjugateGradientMinimizer.cs
  2. 24
      src/UnitTests/OptimizationTests/TestConjugateGradientMinimizer.cs
  3. 4
      src/UnitTests/UnitTests.csproj

26
src/Numerics/Optimization/ConjugateGradientMinimizer.cs

@ -34,25 +34,41 @@ namespace MathNet.Numerics.Optimization
// First step
var steepestDirection = -gradient;
var searchDirection = steepestDirection;
var result = lineSearcher.FindConformingStep(objective, searchDirection, 1.0);
double initialStepSize = 100 * GradientTolerance / (gradient * gradient);
var result = lineSearcher.FindConformingStep(objective, searchDirection, initialStepSize);
objective = result.FunctionInfoAtMinimum;
ValidateGradient(objective.Gradient, objective.Point);
double stepSize = (objective.Point - initialGuess).Norm(2.0);
// Subsequent steps
int iterations = 1;
int totalLineSearchSteps = result.Iterations;
int noLineSearchIterations = result.Iterations > 0 ? 0 : 1;
int steepestDescentResets = 0;
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);
var searchDirectionAdjuster = Math.Max(0, steepestDirection*(steepestDirection - previousSteepestDirection)/(previousSteepestDirection*previousSteepestDirection));
searchDirection = steepestDirection + searchDirectionAdjuster * searchDirection;
if (searchDirection * objective.Gradient >= 0)
{
searchDirection = steepestDirection;
steepestDescentResets += 1;
}
result = lineSearcher.FindConformingStep(objective, searchDirection, stepSize);
noLineSearchIterations += result.Iterations == 0 ? 1 : 0;
totalLineSearchSteps += result.Iterations;
stepSize = (result.FunctionInfoAtMinimum.Point - objective.Point).Norm(2.0);
objective = result.FunctionInfoAtMinimum;
iterations += 1;
}
return new MinimizationResult(objective, iterations, MinimizationResult.ExitCondition.AbsoluteGradient);
return new MinimizationWithLineSearchResult(objective, iterations, MinimizationResult.ExitCondition.AbsoluteGradient, totalLineSearchSteps, noLineSearchIterations);
}
private bool ExitCriteriaSatisfied(Vector<double> candidatePoint, Vector<double> gradient)

24
src/UnitTests/OptimizationTests/TestConjugateGradientMinimizer.cs

@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.Optimization;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.OptimizationTests
{
@ -16,17 +12,23 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
[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));
var obj = ObjectiveFunction.Gradient(RosenbrockFunction.Value, RosenbrockFunction.Gradient);
var solver = new ConjugateGradientMinimizer(1e-5, 1000);
var result = solver.FindMinimum(obj, new DenseVector(new[]{1.2,1.2}));
Assert.That(Math.Abs(result.MinimizingPoint[0]-1.0), Is.LessThan(1e-3));
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3));
}
[Test]
public void FindMinimum_Rosenbrock_Hard()
{
var obj = ObjectiveFunction.Gradient(RosenbrockFunction.Value, RosenbrockFunction.Gradient);
var solver = new ConjugateGradientMinimizer(1e-5, 1000);
var result = solver.FindMinimum(obj, new DenseVector(new[] { -1.2, 1.0 }));
Assert.That(Math.Abs(result.MinimizingPoint[0] - 1.0), Is.LessThan(1e-3));
Assert.That(Math.Abs(result.MinimizingPoint[1] - 1.0), Is.LessThan(1e-3));
}
}
}

4
src/UnitTests/UnitTests.csproj

@ -349,10 +349,6 @@
<Compile Include="Random\SystemRandomSourceTests.cs" />
<Compile Include="OptimizationTests\BfgsTest.cs" />
<Compile Include="RootFindingTests\BisectionTest.cs" />
<Compile Include="MatrixHelpers.cs" />
<Compile Include="NumberTheoryTests\GcdRelatedTest.cs" />
<Compile Include="NumberTheoryTests\GcdRelatedTestBigInteger.cs" />
<Compile Include="NumberTheoryTests\IntegerTheoryTest.cs" />
<Compile Include="OptimizationTests\RosenbrockFunction.cs" />
<Compile Include="OptimizationTests\TestConjugateGradientMinimizer.cs" />
<Compile Include="PermutationTest.cs" />

Loading…
Cancel
Save