diff --git a/src/Numerics/Optimization/NelderMeadSimplex.cs b/src/Numerics/Optimization/NelderMeadSimplex.cs
index c9dbb636..68551786 100644
--- a/src/Numerics/Optimization/NelderMeadSimplex.cs
+++ b/src/Numerics/Optimization/NelderMeadSimplex.cs
@@ -43,7 +43,7 @@ namespace MathNet.Numerics.Optimization
///
public sealed class NelderMeadSimplex
{
- private static readonly double JITTER = 1e-10d; // a small value used to protect against floating point noise
+ static readonly double JITTER = 1e-10d; // a small value used to protect against floating point noise
public double ConvergenceTolerance { get; set; }
public int MaximumIterations { get; set; }
@@ -63,13 +63,38 @@ namespace MathNet.Numerics.Optimization
/// The intial guess
/// The minimum point
public MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector initialGuess)
+ {
+ return FindMinimum(objectiveFunction, initialGuess, ConvergenceTolerance, MaximumIterations);
+ }
+
+ ///
+ /// Finds the minimum of the objective function with an intial pertubation
+ ///
+ /// The objective function, no gradient or hessian needed
+ /// The intial guess
+ /// The inital pertubation
+ /// The minimum point
+ public MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector initialGuess, Vector initalPertubation)
+ {
+ return FindMinimum(objectiveFunction, initialGuess, initalPertubation, ConvergenceTolerance, MaximumIterations);
+ }
+
+ ///
+ /// Finds the minimum of the objective function without an intial pertubation, the default values used
+ /// by fminsearch() in Matlab are used instead
+ /// http://se.mathworks.com/help/matlab/math/optimizing-nonlinear-functions.html#bsgpq6p-11
+ ///
+ /// The objective function, no gradient or hessian needed
+ /// The intial guess
+ /// The minimum point
+ public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector initialGuess, double convergenceTolerance, int maximumIterations)
{
var initalPertubation = new LinearAlgebra.Double.DenseVector(initialGuess.Count);
for (int i = 0; i < initialGuess.Count; i++)
{
initalPertubation[i] = initialGuess[i] == 0.0 ? 0.00025 : initialGuess[i] * 0.05;
}
- return FindMinimum(objectiveFunction, initialGuess, initalPertubation);
+ return FindMinimum(objectiveFunction, initialGuess, initalPertubation, convergenceTolerance, maximumIterations);
}
///
@@ -79,7 +104,7 @@ namespace MathNet.Numerics.Optimization
/// The intial guess
/// The inital pertubation
/// The minimum point
- public MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector initialGuess, Vector initalPertubation)
+ public static MinimizationResult FindMinimum(IObjectiveFunction objectiveFunction, Vector initialGuess, Vector initalPertubation, double convergenceTolerance, int maximumIterations)
{
// confirm that we are in a position to commence
if (objectiveFunction == null)
@@ -111,7 +136,7 @@ namespace MathNet.Numerics.Optimization
errorProfile = EvaluateSimplex(errorValues);
// see if the range in point heights is small enough to exit
- if (HasConverged(ConvergenceTolerance, errorProfile, errorValues))
+ if (HasConverged(convergenceTolerance, errorProfile, errorValues))
{
exitCondition = ExitCondition.Converged;
break;
@@ -143,9 +168,9 @@ namespace MathNet.Numerics.Optimization
}
}
// check to see if we have exceeded our alloted number of evaluations
- if (evaluationCount >= MaximumIterations)
+ if (evaluationCount >= maximumIterations)
{
- throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", MaximumIterations));
+ throw new MaximumIterationsException(String.Format("Maximum iterations ({0}) reached.", maximumIterations));
}
}
var regressionResult = new MinimizationResult(objectiveFunction, evaluationCount, exitCondition);
@@ -159,7 +184,7 @@ namespace MathNet.Numerics.Optimization
///
///
///
- private static double[] InitializeErrorValues(Vector[] vertices, IObjectiveFunction objectiveFunction)
+ static double[] InitializeErrorValues(Vector[] vertices, IObjectiveFunction objectiveFunction)
{
double[] errorValues = new double[vertices.Length];
for (int i = 0; i < vertices.Length; i++)
@@ -178,7 +203,7 @@ namespace MathNet.Numerics.Optimization
///
///
///
- private static bool HasConverged(double convergenceTolerance, ErrorProfile errorProfile, double[] errorValues)
+ static bool HasConverged(double convergenceTolerance, ErrorProfile errorProfile, double[] errorValues)
{
double range = 2 * Math.Abs(errorValues[errorProfile.HighestIndex] - errorValues[errorProfile.LowestIndex]) /
(Math.Abs(errorValues[errorProfile.HighestIndex]) + Math.Abs(errorValues[errorProfile.LowestIndex]) + JITTER);
@@ -198,7 +223,7 @@ namespace MathNet.Numerics.Optimization
///
///
///
- private static ErrorProfile EvaluateSimplex(double[] errorValues)
+ static ErrorProfile EvaluateSimplex(double[] errorValues)
{
ErrorProfile errorProfile = new ErrorProfile();
if (errorValues[0] > errorValues[1])
@@ -239,7 +264,7 @@ namespace MathNet.Numerics.Optimization
///
///
///
- private static Vector[] InitializeVertices(SimplexConstant[] simplexConstants)
+ static Vector[] InitializeVertices(SimplexConstant[] simplexConstants)
{
int numDimensions = simplexConstants.Length;
Vector[] vertices = new Vector[numDimensions + 1];
@@ -273,7 +298,7 @@ namespace MathNet.Numerics.Optimization
///
///
///
- private static double TryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector[] vertices,
+ static double TryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector[] vertices,
double[] errorValues, IObjectiveFunction objectiveFunction)
{
// find the centroid through which we will reflect
@@ -306,7 +331,7 @@ namespace MathNet.Numerics.Optimization
///
///
///
- private static void ShrinkSimplex(ErrorProfile errorProfile, Vector[] vertices, double[] errorValues,
+ static void ShrinkSimplex(ErrorProfile errorProfile, Vector[] vertices, double[] errorValues,
IObjectiveFunction objectiveFunction)
{
Vector lowestVertex = vertices[errorProfile.LowestIndex];
@@ -327,7 +352,7 @@ namespace MathNet.Numerics.Optimization
///
///
///
- private static Vector ComputeCentroid(Vector[] vertices, ErrorProfile errorProfile)
+ static Vector ComputeCentroid(Vector[] vertices, ErrorProfile errorProfile)
{
int numVertices = vertices.Length;
// find the centroid of all points except the worst one
@@ -342,32 +367,21 @@ namespace MathNet.Numerics.Optimization
return centroid.Multiply(1.0d / (numVertices - 1));
}
- private sealed class SimplexConstant
+ sealed class SimplexConstant
{
- private double _value;
- private double _initialPerturbation;
-
public SimplexConstant(double value, double initialPerturbation)
{
- _value = value;
- _initialPerturbation = initialPerturbation;
+ Value = value;
+ InitialPerturbation = initialPerturbation;
}
///
/// The value of the constant
///
- public double Value
- {
- get { return _value; }
- set { _value = value; }
- }
+ public double Value { get; }
// The size of the initial perturbation
- public double InitialPerturbation
- {
- get { return _initialPerturbation; }
- set { _initialPerturbation = value; }
- }
+ public double InitialPerturbation { get; }
public static SimplexConstant[] CreateSimplexConstantsFromVectors(Vector initialGuess, Vector initialPertubation)
{
@@ -380,29 +394,11 @@ namespace MathNet.Numerics.Optimization
}
}
- private sealed class ErrorProfile
+ sealed class ErrorProfile
{
- private int _highestIndex;
- private int _nextHighestIndex;
- private int _lowestIndex;
-
- public int HighestIndex
- {
- get { return _highestIndex; }
- set { _highestIndex = value; }
- }
-
- public int NextHighestIndex
- {
- get { return _nextHighestIndex; }
- set { _nextHighestIndex = value; }
- }
-
- public int LowestIndex
- {
- get { return _lowestIndex; }
- set { _lowestIndex = value; }
- }
+ public int HighestIndex { get; set; }
+ public int NextHighestIndex { get; set; }
+ public int LowestIndex { get; set; }
}
}
}
diff --git a/src/UnitTests/OptimizationTests/NelderMeadSimplexTests.cs b/src/UnitTests/OptimizationTests/NelderMeadSimplexTests.cs
index 3d0f0c75..54fc124a 100644
--- a/src/UnitTests/OptimizationTests/NelderMeadSimplexTests.cs
+++ b/src/UnitTests/OptimizationTests/NelderMeadSimplexTests.cs
@@ -111,9 +111,8 @@ namespace MathNet.Numerics.UnitTests.OptimizationTests
public void Mgh_Tests(TestFunctions.TestCase test_case)
{
var obj = new MghObjectiveFunction(test_case.Function, true, true);
- var solver = new NelderMeadSimplex(1e-8, 1000);
- var result = solver.FindMinimum(obj, test_case.InitialGuess);
+ var result = NelderMeadSimplex.FindMinimum(obj, test_case.InitialGuess, 1e-8, 1000);
if (test_case.MinimizingPoint != null)
{