|
|
|
@ -33,7 +33,7 @@ using MathNet.Numerics.Optimization.LineSearch; |
|
|
|
|
|
|
|
namespace MathNet.Numerics.Optimization |
|
|
|
{ |
|
|
|
public class ConjugateGradientMinimizer |
|
|
|
public class ConjugateGradientMinimizer : IUnconstrainedMinimizer |
|
|
|
{ |
|
|
|
public double GradientTolerance { get; set; } |
|
|
|
public int MaximumIterations { get; set; } |
|
|
|
@ -45,17 +45,26 @@ namespace MathNet.Numerics.Optimization |
|
|
|
} |
|
|
|
|
|
|
|
public MinimizationResult FindMinimum(IObjectiveFunction objective, Vector<double> initialGuess) |
|
|
|
{ |
|
|
|
return Minimum(objective, initialGuess, GradientTolerance, MaximumIterations); |
|
|
|
} |
|
|
|
|
|
|
|
public static MinimizationResult Minimum(IObjectiveFunction objective, Vector<double> initialGuess, double gradientTolerance=1e-8, int maxIterations=1000) |
|
|
|
{ |
|
|
|
if (!objective.IsGradientSupported) |
|
|
|
{ |
|
|
|
throw new IncompatibleObjectiveException("Gradient not supported in objective function, but required for ConjugateGradient minimization."); |
|
|
|
} |
|
|
|
|
|
|
|
objective.EvaluateAt(initialGuess); |
|
|
|
var gradient = objective.Gradient; |
|
|
|
ValidateGradient(objective); |
|
|
|
|
|
|
|
// Check that we're not already done
|
|
|
|
if (ExitCriteriaSatisfied(initialGuess, gradient)) |
|
|
|
if (gradient.Norm(2.0) < gradientTolerance) |
|
|
|
{ |
|
|
|
return new MinimizationResult(objective, 0, ExitCondition.AbsoluteGradient); |
|
|
|
} |
|
|
|
|
|
|
|
// Set up line search algorithm
|
|
|
|
var lineSearcher = new WeakWolfeLineSearch(1e-4, 0.1, 1e-4, 1000); |
|
|
|
@ -63,7 +72,7 @@ namespace MathNet.Numerics.Optimization |
|
|
|
// First step
|
|
|
|
var steepestDirection = -gradient; |
|
|
|
var searchDirection = steepestDirection; |
|
|
|
double initialStepSize = 100 * GradientTolerance / (gradient * gradient); |
|
|
|
double initialStepSize = 100 * gradientTolerance / (gradient * gradient); |
|
|
|
|
|
|
|
LineSearchResult result; |
|
|
|
try |
|
|
|
@ -85,7 +94,7 @@ namespace MathNet.Numerics.Optimization |
|
|
|
int totalLineSearchSteps = result.Iterations; |
|
|
|
int iterationsWithNontrivialLineSearch = result.Iterations > 0 ? 0 : 1; |
|
|
|
int steepestDescentResets = 0; |
|
|
|
while (!ExitCriteriaSatisfied(objective.Point, objective.Gradient) && iterations < MaximumIterations) |
|
|
|
while (objective.Gradient.Norm(2.0) >= gradientTolerance && iterations < maxIterations) |
|
|
|
{ |
|
|
|
var previousSteepestDirection = steepestDirection; |
|
|
|
steepestDirection = -objective.Gradient; |
|
|
|
@ -113,32 +122,31 @@ namespace MathNet.Numerics.Optimization |
|
|
|
iterations += 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (iterations == MaximumIterations) |
|
|
|
if (iterations == maxIterations) |
|
|
|
{ |
|
|
|
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", MaximumIterations)); |
|
|
|
throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", maxIterations)); |
|
|
|
} |
|
|
|
|
|
|
|
return new MinimizationWithLineSearchResult(objective, iterations, ExitCondition.AbsoluteGradient, totalLineSearchSteps, iterationsWithNontrivialLineSearch); |
|
|
|
} |
|
|
|
|
|
|
|
bool ExitCriteriaSatisfied(Vector<double> candidatePoint, Vector<double> gradient) |
|
|
|
{ |
|
|
|
return gradient.Norm(2.0) < GradientTolerance; |
|
|
|
} |
|
|
|
|
|
|
|
void ValidateGradient(IObjectiveFunctionEvaluation objective) |
|
|
|
static void ValidateGradient(IObjectiveFunctionEvaluation objective) |
|
|
|
{ |
|
|
|
foreach (var x in objective.Gradient) |
|
|
|
{ |
|
|
|
if (Double.IsNaN(x) || Double.IsInfinity(x)) |
|
|
|
{ |
|
|
|
throw new EvaluationException("Non-finite gradient returned.", objective); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void ValidateObjective(IObjectiveFunctionEvaluation objective) |
|
|
|
static void ValidateObjective(IObjectiveFunctionEvaluation objective) |
|
|
|
{ |
|
|
|
if (Double.IsNaN(objective.Value) || Double.IsInfinity(objective.Value)) |
|
|
|
{ |
|
|
|
throw new EvaluationException("Non-finite objective function returned.", objective); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|