public static SimplexConstant[] CreateSimplexConstantsFromVectors(Vector <double> initialGuess, Vector <double> initialPertubation) { var constants = new SimplexConstant[initialGuess.Count]; for (int i = 0; i < constants.Length; i++) { constants[i] = new SimplexConstant(initialGuess[i], initialPertubation[i]); } return(constants); }
/// <summary> /// Test to see if we can fit a parabola /// </summary> public static void SimplexTest1() { Console.WriteLine("Starting SimplexTest1"); SimplexConstant[] constants = new SimplexConstant[] { new SimplexConstant(3, 1), new SimplexConstant(5, 1) }; double tolerance = 1e-6; int maxEvals = 1000; ObjectiveFunctionDelegate objFunction = new ObjectiveFunctionDelegate(_objFunction1); RegressionResult result = NelderMeadSimplex.Regress(constants, tolerance, maxEvals, objFunction); _printResult(result); }
private SimplexConstant[] simplexConstantFrom(double[] values) { var constants = new SimplexConstant[values.Count()]; for (int i = 0; i < values.Count(); i++) { constants[i] = new SimplexConstant(Math.Log10(values[i]), 1); } return(constants); }
/// <summary> /// Test on the Rosenbrock function /// </summary> public static void SimplexTest2() { Console.WriteLine("\n\nStarting SimplexTest2"); // we are regressing for frequency, amplitude, and phase offset SimplexConstant[] constants = new SimplexConstant[] { new SimplexConstant(-1.2, .1), new SimplexConstant(1, .1)}; double tolerance = 1e-10; int maxEvals = 1000; ObjectiveFunctionDelegate objFunction = new ObjectiveFunctionDelegate(_objFunction2); RegressionResult result = NelderMeadSimplex.Regress(constants, tolerance, maxEvals, objFunction); _printResult(result); }
/// <summary> /// Test to see if we can fit a parabola /// </summary> private static void _simplexTest1() { Console.WriteLine("Starting SimplexTest1"); SimplexConstant[] nss = new SimplexConstant[] { new SimplexConstant(0, 1), new SimplexConstant(0, 1), new SimplexConstant(0, 1), new SimplexConstant(0, 1), new SimplexConstant(1, 1), new SimplexConstant(1, 1) }; double[] tt = { 5.0, 10.0, 15.0, 20.0, 25.0 }; double[] Y = { 0.001770949, 0.008396027, 0.013860686, 0.019379306, 0.023731833 }; double tolerance = 1e-6; int maxEvals = 1000; ObjectiveFunctionDelegate objFunction = new ObjectiveFunctionDelegate(_objFunction1); RegressionResult result = NelderMeadSimplex.Regress(nss, tt, Y, tolerance, maxEvals, objFunction); _printResult(result); }
// Run cost minimization Vector3 IDecisionManager.getNextDesiredPoint() { // What are the variables to minimize (position) SimplexConstant[] constants = new SimplexConstant[] { new SimplexConstant(this.sensorModule.gps.position.x, 1), new SimplexConstant(this.sensorModule.gps.position.y, 1), new SimplexConstant(this.sensorModule.gps.position.z, 1) }; double tolerance = 1e-30; int maxEvals = 10000; // What's the objective function ObjectiveFunctionDelegate objFunction = new ObjectiveFunctionDelegate(_objFunction1); RegressionResult result = NelderMeadSimplex.Regress(constants, tolerance, maxEvals, objFunction); Vector3 r = new Vector3((float)result.Constants[0], (float)result.Constants[1], (float)result.Constants[2]); // Debug.Log (result.TerminationReason.ToString ()); return(r); }
public void Minimize() { SetCoefficients(); Console.WriteLine("Starting minimization..."); SimplexConstant[] constants = new SimplexConstant[Coefficients.Length]; for (int i = 0; i < Coefficients.Length; i++) { constants[i] = new SimplexConstant(Coefficients[i], Math.Abs(Coefficients[i]) / 2); } double tolerance = 1e-6; int maxEvals = 1000; ObjectiveFunctionDelegate objFunction = new ObjectiveFunctionDelegate(SpiderObjectiveFunction); RegressionResult result = NelderMeadSimplex.Regress(constants, tolerance, maxEvals, objFunction); Coefficients = result.Constants; PrintCoefficients(Coefficients); }
/// <summary> /// Finds the minimum of the objective function with an initial perturbation /// </summary> /// <param name="objectiveFunction">The objective function, no gradient or hessian needed</param> /// <param name="initialGuess">The initial guess</param> /// <param name="initalPertubation">The initial perturbation</param> /// <returns>The minimum point</returns> public static MinimizationResult Minimum(IObjectiveFunction objectiveFunction, Vector <double> initialGuess, Vector <double> initalPertubation, double convergenceTolerance = 1e-8, int maximumIterations = 1000) { // confirm that we are in a position to commence if (objectiveFunction == null) { throw new ArgumentNullException(nameof(objectiveFunction), "ObjectiveFunction must be set to a valid ObjectiveFunctionDelegate"); } if (initialGuess == null) { throw new ArgumentNullException(nameof(initialGuess), "initialGuess must be initialized"); } if (initalPertubation == null) { throw new ArgumentNullException(nameof(initalPertubation), "initalPertubation must be initialized, if unknown use overloaded version of FindMinimum()"); } SimplexConstant[] simplexConstants = SimplexConstant.CreateSimplexConstantsFromVectors(initialGuess, initalPertubation); // create the initial simplex int numDimensions = simplexConstants.Length; int numVertices = numDimensions + 1; Vector <double>[] vertices = InitializeVertices(simplexConstants); int evaluationCount = 0; ExitCondition exitCondition; ErrorProfile errorProfile; double[] errorValues = InitializeErrorValues(vertices, objectiveFunction); int numTimesHasConverged = 0; // iterate until we converge, or complete our permitted number of iterations while (true) { errorProfile = EvaluateSimplex(errorValues); // see if the range in point heights is small enough to exit // to handle the case when the function is symmetrical and extra iteration is performed if (HasConverged(convergenceTolerance, errorProfile, errorValues)) { numTimesHasConverged++; } else { numTimesHasConverged = 0; } if (numTimesHasConverged == 2) { exitCondition = ExitCondition.Converged; break; } // attempt a reflection of the simplex double reflectionPointValue = TryToScaleSimplex(-1.0, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; if (reflectionPointValue <= errorValues[errorProfile.LowestIndex]) { // it's better than the best point, so attempt an expansion of the simplex TryToScaleSimplex(2.0, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; } else if (reflectionPointValue >= errorValues[errorProfile.NextHighestIndex]) { // it would be worse than the second best point, so attempt a contraction to look // for an intermediate point double currentWorst = errorValues[errorProfile.HighestIndex]; double contractionPointValue = TryToScaleSimplex(0.5, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; if (contractionPointValue >= currentWorst) { // that would be even worse, so let's try to contract uniformly towards the low point; // don't bother to update the error profile, we'll do it at the start of the // next iteration ShrinkSimplex(errorProfile, vertices, errorValues, objectiveFunction); evaluationCount += numVertices; // that required one function evaluation for each vertex; keep track } } // check to see if we have exceeded our alloted number of evaluations if (evaluationCount >= maximumIterations) { throw new MaximumIterationsException(FormattableString.Invariant($"Maximum iterations ({maximumIterations}) reached.")); } } objectiveFunction.EvaluateAt(vertices[errorProfile.LowestIndex]); var regressionResult = new MinimizationResult(objectiveFunction, evaluationCount, exitCondition); return(regressionResult); }
public static RegressionResult Regress(SimplexConstant[] simplexConstants, double convergenceTolerance, int maxEvaluations, ObjectiveFunctionDelegate objectiveFunction) { // confirm that we are in a position to commence if (objectiveFunction == null) throw new InvalidOperationException("ObjectiveFunction must be set to a valid ObjectiveFunctionDelegate"); // Not L10N if (simplexConstants == null) throw new InvalidOperationException("SimplexConstants must be initialized"); // Not L10N // create the initial simplex int numDimensions = simplexConstants.Length; int numVertices = numDimensions + 1; Vector<double>[] vertices = InitializeVertices(simplexConstants); int evaluationCount = 0; TerminationReason terminationReason; ErrorProfile errorProfile; double[] errorValues = InitializeErrorValues(vertices, objectiveFunction); // iterate until we converge, or complete our permitted number of iterations while (true) { errorProfile = EvaluateSimplex(errorValues); // see if the range in point heights is small enough to exit if (HasConverged(convergenceTolerance, errorProfile, errorValues)) { terminationReason = TerminationReason.Converged; break; } // attempt a reflection of the simplex double reflectionPointValue = TryToScaleSimplex(-1.0, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; if (reflectionPointValue <= errorValues[errorProfile.LowestIndex]) { // it's better than the best point, so attempt an expansion of the simplex TryToScaleSimplex(2.0, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; } else if (reflectionPointValue >= errorValues[errorProfile.NextHighestIndex]) { // it would be worse than the second best point, so attempt a contraction to look // for an intermediate point double currentWorst = errorValues[errorProfile.HighestIndex]; double contractionPointValue = TryToScaleSimplex(0.5, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; if (contractionPointValue >= currentWorst) { // that would be even worse, so let's try to contract uniformly towards the low point; // don't bother to update the error profile, we'll do it at the start of the // next iteration ShrinkSimplex(errorProfile, vertices, errorValues, objectiveFunction); evaluationCount += numVertices; // that required one function evaluation for each vertex; keep track } } // check to see if we have exceeded our alloted number of evaluations if (evaluationCount >= maxEvaluations) { terminationReason = TerminationReason.MaxFunctionEvaluations; break; } } RegressionResult regressionResult = new RegressionResult(terminationReason, vertices[errorProfile.LowestIndex].ToArray(), errorValues[errorProfile.LowestIndex], evaluationCount); return regressionResult; }
/// <summary> /// Construct an initial simplex, given starting guesses for the constants, and /// initial step sizes for each dimension /// </summary> private static Vector<double>[] InitializeVertices(SimplexConstant[] simplexConstants) { int numDimensions = simplexConstants.Length; Vector<double>[] vertices = new Vector<double>[numDimensions + 1]; // define one point of the simplex as the given initial guesses Vector<double> p0 = new DenseVector(numDimensions); for (int i = 0; i < numDimensions; i++) { p0[i] = simplexConstants[i].Value; } // now fill in the vertices, creating the additional points as: // P(i) = P(0) + Scale(i) * UnitVector(i) vertices[0] = p0; for (int i = 0; i < numDimensions; i++) { double scale = simplexConstants[i].InitialPerturbation; Vector unitVector = new DenseVector(numDimensions); unitVector[i] = 1; vertices[i + 1] = p0.Add(unitVector.Multiply(scale)); } return vertices; }