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);
            }
示例#2
0
 /// <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);
        }
示例#4
0
        /// <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);
        }
示例#5
0
        /// <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);
    }
示例#7
0
        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;
        }