//RegressionResult
        double runCalculation(SimplexConstant[] consts)
        {
            ObjectiveFunctionDelegate objFunc = new ObjectiveFunctionDelegate(minimizeAngle);
            RegressionResult          result  = NelderMeadSimplex.Regress(consts, tolerance, maxEvals, objFunc);

            return(result.Constants[0]);
        }
Пример #2
0
        /// <summary>
        /// Test a scaling operation of the high point, and replace it if it is an improvement
        /// </summary>
        /// <param name="scaleFactor"></param>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        /// <returns></returns>
        private static double _tryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector[] vertices,
                                                 double[] errorValues, ObjectiveFunctionDelegate objectiveFunction)
        {
            // find the centroid through which we will reflect
            Vector centroid = _computeCentroid(vertices, errorProfile);

            // define the vector from the centroid to the high point
            Vector centroidToHighPoint = vertices[errorProfile.HighestIndex].Subtract(centroid);

            // scale and position the vector to determine the new trial point
            Vector newPoint = centroidToHighPoint.Multiply(scaleFactor).Add(centroid);

            //TODO: should see if this is a good point by constraints, otherwise throw it out

            // evaluate the new point
            double newErrorValue = objectiveFunction(newPoint.Components);

            // if it's better, replace the old high point
            if (newErrorValue < errorValues[errorProfile.HighestIndex])
            {
                vertices[errorProfile.HighestIndex]    = newPoint;
                errorValues[errorProfile.HighestIndex] = newErrorValue;
            }

            return(newErrorValue);
        }
Пример #3
0
        public HybridACOGA(int numberOfVariables, OptimizationType opType, GA <int> .ObjectiveFunctionDelegate objectFunction, double[,] distance) : base(numberOfVariables, opType, objectFunction)
        {
            getObjectiveValue    = objectFunction;
            numberOfCity         = numberOfVariables;
            FromToDistanceMatrix = distance;
            // Allocate memory for pheromone matrix and heuristic value matrix
            // Heuristic values in the matrix are computed and assigned via
            // the specified function delegate
            pheromone            = new double[numberOfCity, numberOfCity];
            indicesOfAnts        = new int[populationSize];
            solutions            = new int[populationSize][];
            soFarTheBestSoluiton = new int[numberOfCity];
            for (int r = 0; r < numberOfCity; r++)
            {
                for (int c = 0; c < numberOfCity; c++)
                {
                    pheromone[r, c] = 0.01;
                }
            }
            for (int r = 0; r < numberOfCity; r++)
            {
                for (int c = 0; c < numberOfCity; c++)
                {
                    AverageDistance += FromToDistanceMatrix[r, c];
                }
            }
            AverageDistance = AverageDistance / (numberOfCity * numberOfCity);

            heuristicValues = new double[numberOfCity, numberOfCity];
            for (int r = 0; r < numberOfCity; r++)
            {
                for (int c = 0; c < numberOfCity; c++)
                {
                    heuristicValues[r, c] = DistanceInverseHeuristic(r, c);
                }
            }
            for (int i = 0; i < populationSize; i++)
            {
                indicesOfAnts[i] = i;
                solutions[i]     = new int[numberOfCity];
                for (int j = 0; j < numberOfCity; j++)
                {
                    solutions[i][j] = j;
                }
                KnuthShuffle(solutions[i]);
            }

            // Allocate memory for the arries used in ACO, whose length is
            // depend on the number of variables. In contrast, those arraies
            // with length depending on the number of ants are allocated in
            // reset function.
            probabilities   = new double[numberOfCity];
            candidateSet    = new int[numberOfCity];
            ObjectiveValues = new double[populationSize];
            // Set drop amount multiplier; which is the avarage length
            //dropMultiplier = dropPheromone * dropMultiplier / getObjectiveValue(objectiveValues);
        }
Пример #4
0
 /// <summary>
 /// Evaluate the objective function at each vertex to create a corresponding
 /// list of error values for each vertex
 /// </summary>
 private static double[] InitializeErrorValues(Vector <double>[] vertices, ObjectiveFunctionDelegate objectiveFunction)
 {
     double[] errorValues = new double[vertices.Length];
     for (int i = 0; i < vertices.Length; i++)
     {
         errorValues[i] = objectiveFunction(vertices[i].ToArray());
     }
     return(errorValues);
 }
Пример #5
0
 /// <summary>
 /// Evaluate the objective function at each vertex to create a corresponding
 /// list of error values for each vertex
 /// </summary>
 /// <param name="vertices"></param>
 /// <returns></returns>
 private static double[] _initializeErrorValues(Vector[] vertices, ObjectiveFunctionDelegate objectiveFunction)
 {
     double[] errorValues = new double[vertices.Length];
     for (int i = 0; i < vertices.Length; i++)
     {
         errorValues[i] = objectiveFunction(vertices[i].Components);
     }
     return(errorValues);
 }
Пример #6
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);
 }
Пример #7
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);
 }
Пример #8
0
 /// <summary>
 ///  To employ a GA solver, user must provide the number of variables, the optimization type, and a function delegate
 ///  that compute and return the objective value for a given solution.
 /// </summary>
 /// <param name="numberOfVariables"> Number of variables of the problem</param>
 /// <param name="opType"> The optimization problem type </param>
 /// <param name="objectFunction"> The function delegate that computer the objective value for a given solution </param>
 public GA(int numberOfVariables, OptimizationType opType, GA <T> .ObjectiveFunctionDelegate objectFunction)
 {
     numberOfGenes    = numberOfVariables;
     optimizationType = opType;
     if (objectFunction == null)
     {
         throw new Exception("You must prepare an objective function.");
     }
     GetObjectiveValueFunction = objectFunction;
 }
Пример #9
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);
        }
Пример #10
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);
        }
Пример #11
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);
        }
Пример #12
0
        /// <summary>
        /// Contract the simplex uniformly around the lowest point
        /// </summary>
        private static void ShrinkSimplex(ErrorProfile errorProfile, Vector <double>[] vertices, double[] errorValues,
                                          ObjectiveFunctionDelegate objectiveFunction)
        {
            Vector <double> lowestVertex = vertices[errorProfile.LowestIndex];

            for (int i = 0; i < vertices.Length; i++)
            {
                if (i != errorProfile.LowestIndex)
                {
                    vertices[i]    = (vertices[i].Add(lowestVertex)).Multiply(0.5);
                    errorValues[i] = objectiveFunction(vertices[i].ToArray());
                }
            }
        }
Пример #13
0
        /// <summary>
        /// Contract the simplex uniformly around the lowest point
        /// </summary>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        private static void _shrinkSimplex(ErrorProfile errorProfile, Vector[] vertices, double[] errorValues,
                                           ObjectiveFunctionDelegate objectiveFunction, double[] tt, double[] Y)
        {
            Vector lowestVertex = vertices[errorProfile.LowestIndex];

            for (int i = 0; i < vertices.Length; i++)
            {
                if (i != errorProfile.LowestIndex)
                {
                    vertices[i]    = (vertices[i].Add(lowestVertex)).Multiply(0.5);
                    errorValues[i] = objectiveFunction(vertices[i].Components, tt, Y);
                }
            }
        }
Пример #14
0
    // 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);
    }
Пример #15
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);
        }
Пример #16
0
        public void Initialize(ObjectiveFunctionDelegate _ofd, int _total, double[] _scale, bool[] _fixt)
        {
            ofd      = _ofd;
            total    = _total;
            accepted = 0;
            dim      = _scale.Length;
            Scale    = _scale;

            searchRadius = 1.0 / Scale.Length;

            this.IntializeScale(searchRadius, _fixt);

            // uniform on [0,1]
            uRand.Alpha = 0.0;
            uRand.Beta  = 1.0;

            // standard gaussian parameters
            zRand.Mu    = 0;
            zRand.Sigma = 1;

            Temperature = 1;
        }
Пример #17
0
        /// <summary>
        /// Test a scaling operation of the high point, and replace it if it is an improvement
        /// </summary>
        private static double TryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector <double>[] vertices,
                                                double[] errorValues, ObjectiveFunctionDelegate objectiveFunction)
        {
            // find the centroid through which we will reflect
            Vector centroid = ComputeCentroid(vertices, errorProfile);

            // define the vector from the centroid to the high point
            Vector centroidToHighPoint = (Vector)vertices[errorProfile.HighestIndex].Subtract(centroid);

            // scale and position the vector to determine the new trial point
            Vector newPoint = (Vector)centroidToHighPoint.Multiply(scaleFactor).Add(centroid);

            // evaluate the new point
            double newErrorValue = objectiveFunction(newPoint.ToArray());

            // if it's better, replace the old high point
            if (newErrorValue < errorValues[errorProfile.HighestIndex])
            {
                vertices[errorProfile.HighestIndex]    = newPoint;
                errorValues[errorProfile.HighestIndex] = newErrorValue;
            }

            return(newErrorValue);
        }
Пример #18
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);
        }
Пример #19
0
        private const double JITTER = 1e-10d; // a small value used to protect against floating point noise

        #endregion Fields

        #region Methods

        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");

            if (simplexConstants == null)
                throw new InvalidOperationException("SimplexConstants must be initialized");

            // create the initial simplex
            int numDimensions = simplexConstants.Length;
            int numVertices = numDimensions + 1;
            Vector[] 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
                    double expansionPointValue = _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;
                }
            }
            var regressionResult = new RegressionResult(terminationReason,
                                                        vertices[errorProfile.LowestIndex].Components,
                                                        errorValues[errorProfile.LowestIndex], evaluationCount);
            return regressionResult;
        }
Пример #20
0
 /// <summary>
 /// Evaluate the objective function at each vertex to create a corresponding
 /// list of error values for each vertex
 /// </summary>
 /// <param name="vertices"></param>
 /// <param name="objectiveFunction"></param>
 /// <returns></returns>        
 private static double[] _initializeErrorValues(Vector[] vertices, ObjectiveFunctionDelegate objectiveFunction)
 {
     var errorValues = new double[vertices.Length];
     for (int i = 0; i < vertices.Length; i++)
     {
         errorValues[i] = objectiveFunction(vertices[i].Components);
     }
     return errorValues;
 }
Пример #21
0
        public double FindFit(double[] _pmin, double[] _start, double _delta, double _tolerance, int _maxIterations, ObjectiveFunctionDelegate _objectiveFn)
        {
            // initialise simplex
            Mov(s[0], _start);
            for (int i = 1; i < NB_POINTS; i++)
            {
                Mov(s[i], _start);
                s[i][i - 1] += _delta;
            }

            // evaluate function at each point on simplex
            for (int i = 0; i < NB_POINTS; i++)
            {
                f[i] = _objectiveFn(s[i]);
            }

            double[] o = new double[DIM];       // Centroid
            double[] r = new double[DIM];       // Reflection
            double[] c = new double[DIM];       // Contraction
            double[] e = new double[DIM];       // Expansion

            int lo = 0, hi, nh;

            for (m_lastIterationsCount = 0; m_lastIterationsCount < _maxIterations; m_lastIterationsCount++)
            {
                // find lowest, highest and next highest
                lo = hi = nh = 0;
                for (int i = 1; i < NB_POINTS; i++)
                {
                    if (f[i] < f[lo])
                    {
                        lo = i;
                    }
                    if (f[i] > f[hi])
                    {
                        nh = hi;
                        hi = i;
                    }
                    else if (f[i] > f[nh])
                    {
                        nh = i;
                    }
                }

                // stop if we've reached the required tolerance level
                double a = Math.Abs(f[lo]);
                double b = Math.Abs(f[hi]);
                if (2.0 * Math.Abs(a - b) < (a + b) * _tolerance)
                {
                    break;
                }

                // compute centroid (excluding the worst point)
                Set(o, 0.0f);
                for (int i = 0; i < NB_POINTS; i++)
                {
                    if (i == hi)
                    {
                        continue;
                    }
                    Add(o, s[i]);
                }

                for (int i = 0; i < DIM; i++)
                {
                    o[i] /= DIM;
                }

                // reflection
                for (int i = 0; i < DIM; i++)
                {
                    r[i] = o[i] + reflect * (o[i] - s[hi][i]);
                }

                double fr = _objectiveFn(r);
                if (fr < f[nh])
                {
                    if (fr < f[lo])
                    {
                        // expansion
                        for (int i = 0; i < DIM; i++)
                        {
                            e[i] = o[i] + expand * (o[i] - s[hi][i]);
                        }

                        double fe = _objectiveFn(e);
                        if (fe < fr)
                        {
                            Mov(s[hi], e);
                            f[hi] = fe;
                            continue;
                        }
                    }

                    Mov(s[hi], r);
                    f[hi] = fr;
                    continue;
                }

                // contraction
                for (int i = 0; i < DIM; i++)
                {
                    c[i] = o[i] - contract * (o[i] - s[hi][i]);
                }

                double fc = _objectiveFn(c);
                if (fc < f[hi])
                {
                    Mov(s[hi], c);
                    f[hi] = fc;
                    continue;
                }

                // reduction
                for (int k = 0; k < NB_POINTS; k++)
                {
                    if (k == lo)
                    {
                        continue;
                    }
                    for (int i = 0; i < DIM; i++)
                    {
                        s[k][i] = s[lo][i] + shrink * (s[k][i] - s[lo][i]);
                    }
                    f[k] = _objectiveFn(s[k]);
                }
            }

            // return best point and its value
            Mov(_pmin, s[lo]);
            return(f[lo]);
        }
 /// <summary>
 /// Evaluate the objective function at each vertex to create a corresponding
 /// list of error values for each vertex
 /// </summary>
 /// <param name="vertices"></param>
 /// <returns></returns>
 private static double[] _initializeErrorValues(Vector[] vertices, ObjectiveFunctionDelegate objectiveFunction)
 {
     double[] errorValues = new double[vertices.Length];
     for (int i = 0; i < vertices.Length; i++)
     {
         errorValues[i] = objectiveFunction(vertices[i].Components);
     #if DEBUG
         Console.Write(i + ":" + vertices[i]+"==");
     #endif
     }
     return errorValues;
 }
 /// <summary>
 /// Contract the simplex uniformly around the lowest point
 /// </summary>
 /// <param name="errorProfile"></param>
 /// <param name="vertices"></param>
 /// <param name="errorValues"></param>
 private static void _shrinkSimplex(ErrorProfile errorProfile, Vector[] vertices, double[] errorValues, 
     ObjectiveFunctionDelegate objectiveFunction)
 {
     Vector lowestVertex = vertices[errorProfile.LowestIndex];
     for (int i = 0; i < vertices.Length; i++)
     {
         if (i != errorProfile.LowestIndex)
         {
             vertices[i] = (vertices[i].Add(lowestVertex)).Multiply(0.5);
             errorValues[i] = objectiveFunction(vertices[i].Components);
         }
     }
 }
Пример #24
0
        private const double JITTER = 1e-10d; // a small value used to protect against floating point noise

        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);
        }
Пример #25
0
 /// <summary>
 /// Evaluate the objective function at each vertex to create a corresponding
 /// list of error values for each vertex
 /// </summary>
 private static double[] InitializeErrorValues(Vector<double>[] vertices, ObjectiveFunctionDelegate objectiveFunction)
 {
     double[] errorValues = new double[vertices.Length];
     for (int i = 0; i < vertices.Length; i++)
     {
         errorValues[i] = objectiveFunction(vertices[i].ToArray());
     }
     return errorValues;
 }
        private static readonly double JITTER = 1e-10d; // a small value used to protect against floating point noise

        #endregion Fields

        #region Methods

        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");

            if (simplexConstants == null)
                throw new InvalidOperationException("SimplexConstants must be initialized");
            #if DEBUG   //this is the coniditional compilation symbols in the project property >>build section
            Console.Write("inside nelder mead regression:");
            #endif
            // create the initial simplex
            int numDimensions = simplexConstants.Length;
            int numVertices = numDimensions + 1;
            #if DEBUG
            Console.Write("numVertices: {0}", numVertices );
            #endif
            Vector[] vertices = _initializeVertices(simplexConstants);
            double[] errorValues = new double[numVertices];

            int evaluationCount = 0;
            TerminationReason terminationReason = TerminationReason.Unspecified;
            ErrorProfile errorProfile;

            errorValues = _initializeErrorValues(vertices, objectiveFunction);
            #if DEBUG || LOG_MODE
            Console.WriteLine("\n=====Start the Nelder-Mead Algorithm for Optimization..........");
            #endif
            // iterate until we converge, or complete our permitted number of iterations
            while (true)
            {
            #if LOG_MODE
                if (evaluationCount % 100 == 0)
                {
                    Console.Write("......"+evaluationCount+ "/"+maxEvaluations );
                }
            #endif
               errorProfile = _evaluateSimplex(errorValues);

                // see if the range in point heights is small enough to exit
                if (_hasConverged(convergenceTolerance, errorProfile, errorValues))
                {
                    terminationReason = TerminationReason.Converged;
                    break;
                }
            #if DEBUG
                Console.WriteLine("not converged");
            #endif
                // attempt a reflection of the simplex
                double reflectionPointValue = _tryToScaleSimplex(-1.0, ref errorProfile, vertices, errorValues, objectiveFunction);
                ++evaluationCount;
            #if DEBUG
                Console.WriteLine("Got a reflection point");
            #endif
                if (reflectionPointValue <= errorValues[errorProfile.LowestIndex])
                {
                    // it's better than the best point, so attempt an expansion of the simplex
                    double expansionPointValue = _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;
                }
            }
            #if LOG_MODE
            Console.WriteLine("Done!!");
            #endif
            RegressionResult regressionResult = new RegressionResult(terminationReason,
                                vertices[errorProfile.LowestIndex].Components, errorValues[errorProfile.LowestIndex], evaluationCount);
            return regressionResult;
        }
Пример #27
0
        /// <summary>
        /// Test a scaling operation of the high point, and replace it if it is an improvement
        /// </summary>
        private static double TryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector<double>[] vertices, 
                                          double[] errorValues, ObjectiveFunctionDelegate objectiveFunction)
        {
            // find the centroid through which we will reflect
            Vector centroid = ComputeCentroid(vertices, errorProfile);

            // define the vector from the centroid to the high point
            Vector centroidToHighPoint = (Vector) vertices[errorProfile.HighestIndex].Subtract(centroid);

            // scale and position the vector to determine the new trial point
            Vector newPoint = (Vector) centroidToHighPoint.Multiply(scaleFactor).Add(centroid);

            // evaluate the new point
            double newErrorValue = objectiveFunction(newPoint.ToArray());

            // if it's better, replace the old high point
            if (newErrorValue < errorValues[errorProfile.HighestIndex])
            {
                vertices[errorProfile.HighestIndex] = newPoint;
                errorValues[errorProfile.HighestIndex] = newErrorValue;
            }

            return newErrorValue;
        }
        /// <summary>
        /// Test a scaling operation of the high point, and replace it if it is an improvement
        /// </summary>
        /// <param name="scaleFactor"></param>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        /// <returns></returns>
        private static double _tryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector[] vertices, 
            double[] errorValues, ObjectiveFunctionDelegate objectiveFunction)
        {
            // find the centroid through which we will reflect
            Vector centroid = _computeCentroid(vertices, errorProfile);
            #if DEBUG
            Console.WriteLine("centroid:" + centroid.ToString());
            #endif
            // define the vector from the centroid to the high point
            Vector centroidToHighPoint = vertices[errorProfile.HighestIndex].Subtract(centroid);

            // scale and position the vector to determine the new trial point
            Vector newPoint = centroidToHighPoint.Multiply(scaleFactor).Add(centroid);

            // evaluate the new point
            double newErrorValue = objectiveFunction(newPoint.Components);

            // if it's better, replace the old high point
            if (newErrorValue < errorValues[errorProfile.HighestIndex])
            {
                vertices[errorProfile.HighestIndex] = newPoint;
                errorValues[errorProfile.HighestIndex] = newErrorValue;
            }

            return newErrorValue;
        }
Пример #29
0
//public System.IO.StreamWriter	log = new System.IO.FileInfo( "log.txt" ).CreateText();


        public double   FindFit(double[] _pmin, double[] _start, double _delta, double _tolerance, int _maxIterations, ObjectiveFunctionDelegate _objectiveFn)
        {
            // initialise simplex
            Mov(s[0], _start);
            for (int i = 1; i < NB_POINTS; i++)
            {
                Mov(s[i], _start);
                s[i][i - 1] += _delta;
            }

            // evaluate function at each point on simplex
//log.WriteLine( "Init" );
            for (int i = 0; i < NB_POINTS; i++)
            {
                f[i] = _objectiveFn(s[i]);
//log.WriteLine( "f[{0}] = {1}", i, f[i] );
            }
//			if ( f[0] < _tolerance ) {
//				// Already at a minimum!
//				Mov( _pmin, _start );
//				return f[0];
//			}

            double[] o = new double[DIM];                       // Centroid
            double[] r = new double[DIM];                       // Reflection
            double[] c = new double[DIM];                       // Contraction
            double[] e = new double[DIM];                       // Expansion

            int lo = 0, hi, nh;

            for (m_lastIterationsCount = 0; m_lastIterationsCount < _maxIterations; m_lastIterationsCount++)
            {
//log.WriteLine();
//log.WriteLine( "===================================" );
//log.WriteLine(  "Iteration #" + m_lastIterationsCount );

                // find lowest, highest and next highest
                lo = hi = nh = 0;
                for (int i = 1; i < NB_POINTS; i++)
                {
                    if (f[i] < f[lo])
                    {
                        lo = i;
                    }
                    if (f[i] > f[hi])
                    {
                        nh = hi;
                        hi = i;
                    }
                    else if (f[i] > f[nh])
                    {
                        nh = i;
                    }

//log.WriteLine( "f[{0}] = {1}", i, f[i] );
                }

                // stop if we've reached the required tolerance level
                double a = Mathf.Abs(f[lo]);
                double b = Mathf.Abs(f[hi]);
                if (2.0 * Mathf.Abs(a - b) < (a + b) * _tolerance)              // || a + b == 0.0 )
                {
                    break;
                }

                // compute centroid (excluding the worst point)
                Set(o, 0.0f);
                for (int i = 0; i < NB_POINTS; i++)
                {
                    if (i == hi)
                    {
                        continue;
                    }
                    Add(o, s[i]);
                }

                for (int i = 0; i < DIM; i++)
                {
                    o[i] /= DIM;
                }

//log.WriteLine( "centroid = {{ {0}, {1}, {2} }}", o[0], o[1], o[2] );

                // reflection
                for (int i = 0; i < DIM; i++)
                {
                    r[i] = o[i] + reflect * (o[i] - s[hi][i]);
                }

                double fr = _objectiveFn(r);

//log.WriteLine( "reflection = {{ {0}, {1}, {2} }}", r[0], r[1], r[2] );
//log.WriteLine( "reflection error = " + fr );

                if (fr < f[nh])
                {
                    if (fr < f[lo])
                    {
                        // expansion
                        for (int i = 0; i < DIM; i++)
                        {
                            e[i] = o[i] + expand * (o[i] - s[hi][i]);
                        }

                        double fe = _objectiveFn(e);

//log.WriteLine( "expansion = {{ {0}, {1}, {2} }}", e[0], e[1], e[2] );
//log.WriteLine( "expansion error = " + fe );

                        if (fe < fr)
                        {
                            Mov(s[hi], e);
                            f[hi] = fe;
//log.WriteLine( "CHOSE EXPANSION" );
                            continue;
                        }
                    }

                    Mov(s[hi], r);
                    f[hi] = fr;
//log.WriteLine( "CHOSE REFLECTION" );
                    continue;
                }

                // contraction
                for (int i = 0; i < DIM; i++)
                {
                    c[i] = o[i] - contract * (o[i] - s[hi][i]);
                }

                double fc = _objectiveFn(c);

//log.WriteLine( "contraction = {{ {0}, {1}, {2} }}", c[0], c[1], c[2] );
//log.WriteLine( "contraction error = " + fc );

                if (fc < f[hi])
                {
                    Mov(s[hi], c);
                    f[hi] = fc;
//log.WriteLine( "CHOSE CONTRACTION" );
                    continue;
                }

                // reduction
                for (int k = 0; k < NB_POINTS; k++)
                {
                    if (k == lo)
                    {
                        continue;
                    }
                    for (int i = 0; i < DIM; i++)
                    {
                        s[k][i] = s[lo][i] + shrink * (s[k][i] - s[lo][i]);
                    }
                    f[k] = _objectiveFn(s[k]);
                }
//log.WriteLine( "CHOSE REDUCTION" );
            }

            // return best point and its value
            Mov(_pmin, s[lo]);

// log.WriteLine();
// log.WriteLine();
// log.WriteLine( "===================================" );
// log.WriteLine( "Exiting after " + m_lastIterationsCount + " iterations" );
// log.WriteLine( "Result = {{ {0}, {1}, {2} }}", _pmin[0], _pmin[1], _pmin[2] );
// log.WriteLine( "Error = " + f[lo] );

            return(f[lo]);
        }