Example #1
0
        /** Initialise the simplex and evaluate it. Returns null on failure. */
        private List <double[]> makeSimplex(double[] initialParams, double[] initialParamVariations, Random random)
        {
            var simp = Java.NewDoubleArray2(numVertices, numParams + 1 + numExtraArrayElements);

            /* simpTable.put(Thread.currentThread(), simp); */

            if (initialParams != null)
            {
                for (int i = 0; i < numParams; i++)
                {
                    if (double.IsNaN(initialParams[i]))
                    {
                        Array.Copy(initialParams, 0, simp[0], 0, Math.Min(initialParams.Length, numParams));
                    }
                }
            }
            evaluate(simp[0]);
            if (double.IsNaN(value(simp[0])))
            {
                findValidInitalParams(simp[0], initialParamVariations, random);
            }
            if (double.IsNaN(value(simp[0])))
            {
                return(null);
            }
            if (initializeSimplex(simp, initialParamVariations, random))
            {
                return(simp);
            }
            else
            {
                return(null);
            }
        }
Example #2
0
        /** Get the full simplex of the current thread. This may be useful if the target function
         *  wants to modify the simplex */
        /* public List<double[]> getSimplex() {
         * return simpTable.get(Thread.currentThread());
         * } */

        /** One minimization run (including reinitializations of the simplex until the result is stable) */
        private void minimizeOnce(double[] initialParams, double[] initialParamVariations, int seed)
        {
            Random random = new Random(seed);
            var    simp   = makeSimplex(initialParams, initialParamVariations, random);

            if (simp == null)
            {
                status = wasInitialized ? REINITIALIZATION_FAILURE : INITIALIZATION_FAILURE;
                return;
            }
            wasInitialized = true;
            if (startTime == 0)
            {
                startTime = Java.SystemCurrentTimeMillis();
            }
            //if (io.binroot.regression.IJ.debugMode) showSimplex(simp, seed+" Initialized:");
            int    bestVertexNumber = minimize(simp);       // first minimization
            double bestValueSoFar   = value(simp[bestVertexNumber]);
            //reinitialize until converged or error/aborted (don't care about reinitialization failure in other thread)
            bool reinitialisationFailure = false;

            while (status == SUCCESS || status == REINITIALIZATION_FAILURE)
            {
                double[] paramVariations =
                    makeNewParamVariations(simp, bestVertexNumber, initialParams, initialParamVariations);
                if (!reInitializeSimplex(simp, bestVertexNumber, paramVariations, random))
                {
                    reinitialisationFailure = true;
                    break;
                }
                //if (io.binroot.regression.IJ.debugMode) showSimplex(simp, seed+" Reinitialized:");
                bestVertexNumber = minimize(simp);          // minimize with reinitialized simplex
                if (belowErrorLimit(value(simp[bestVertexNumber]), bestValueSoFar, 2.0))
                {
                    break;
                }
                bestValueSoFar = value(simp[bestVertexNumber]);
            }
            if (reinitialisationFailure)
            {
                status = REINITIALIZATION_FAILURE;
            }
            else if (status == SUCCESS || status == REINITIALIZATION_FAILURE) //i.e. not aborted, not max iterations exceeded
            {
                numCompletedMinimizations++;                                  // it was a complete minimization
            }
            //if (io.binroot.regression.IJ.debugMode) showSimplex(simp, seed+" Final:");
            if (resultsVector != null)
            {
                lock (resultsVector) {
                    resultsVector.Add(simp[bestVertexNumber]);
                }
            }
            else
            {
                result = simp[bestVertexNumber];
            }
        }
Example #3
0
 /** Get the value of the minimum, i.e. the value associated with the resulting parameters
  *  as obtained by getParams(). May return NaN in case the minimize call has returned
  *  an INITIALIZATION_FAILURE status or that abort() has been called at the very
  *  beginning of the minimization.
  *  Do not call this method before minimization. */
 public double getFunctionValue()
 {
     if (result == null)
     {
         result = new double[numParams + 1];
         Java.DoubleArrayFill(result, double.NaN);
     }
     return(value(result));
 }
Example #4
0
 /** Get the result, i.e., the set of parameter values (i.e., variable values)
  *  from the best corner of the simplex. Note that the array returned may have more
  *  elements than numParams; ignore the rest.
  *  May return an array with only NaN values in case the minimize call has returned
  *  an INITIALIZATION_FAILURE status or that abort() has been called at the very
  *  beginning of the minimization.
  *  Do not call this method before minimization. */
 public double[] getParams()
 {
     if (result == null)
     {
         result = new double[numParams + 1 + numExtraArrayElements];
         Java.DoubleArrayFill(result, double.NaN);
     }
     return(result);
 }
Example #5
0
        /** Get center of all vertices except one to exclude
         *  (may be -1 to exclude none)
         *  Does not care about function values (i.e., last array elements) */
        private void getCenter(List <double[]> simp, int excludeVertex, double[] center)
        {
            Java.DoubleArrayFill(center, 0.0);
            int nV = 0;

            for (int v = 0; v < numVertices; v++)
            {
                if (v != excludeVertex)
                {
                    for (int i = 0; i < numParams; i++)
                    {
                        center[i] += simp[v][i];
                    }
                    nV++;
                }
            }
            double norm = 1.0 / nV;

            for (int i = 0; i < numParams; i++)
            {
                center[i] *= norm;
            }
        }
Example #6
0
        /** Minimizes the target function by variation of the simplex.
         *  Note that one call to this function never does more than 0.4*maxIter iterations.
         *  @return index of the best value in simp
         */
        private int minimize(List <double[]> simp)
        {
            int[]    worstNextBestArray = new int[3];                                        // used to pass these indices from 'order' function
            double[] center             = new double[numParams + 1 + numExtraArrayElements]; // center of all vertices except worst
            double[] reflected          = new double[numParams + 1 + numExtraArrayElements]; // the 1st new vertex to try
            double[] secondTry          = new double[numParams + 1 + numExtraArrayElements]; // expanded or contracted vertex

            order(simp, worstNextBestArray);
            int worst     = worstNextBestArray[WORST];
            int nextWorst = worstNextBestArray[NEXT_WORST];
            int best      = worstNextBestArray[BEST];
            //showSimplex(simp, "before minimization, value="+value(simp[best]));

            //String operation="ini";
            int thisNumIter = 0;

            while (true)
            {
                totalNumIter++;                                 // global count over all threads
                thisNumIter++;                                  // local count for this minimize call
                                                                // THE MINIMIZAION ALGORITHM IS HERE
                {
                    getCenter(simp, worst, center);             // centroid of vertices except worst
                                                                // Reflect worst vertex through centriod of not-worst
                    getVertexAndEvaluate(center, simp[worst], -C_REFLECTION, reflected);
                    if (value(reflected) <= value(simp[best]))  // if it's better than the best...
                                                                // try expanding it
                    {
                        getVertexAndEvaluate(center, simp[worst], -C_EXPANSION, secondTry);
                        if (value(secondTry) <= value(reflected))
                        {
                            copyVertex(secondTry, simp[worst]);  // if expanded is better than reflected, keep it
                                                                 //operation="expa";
                            goto iteration;
                        }
                    }
                    if (value(reflected) < value(simp[nextWorst]))
                    {
                        copyVertex(reflected, simp[worst]);     // keep reflected if better than 2nd worst
                                                                //operation="refl";
                        goto iteration;
                    }
                    else if (value(reflected) < value(simp[worst]))
                    {
                        // try outer contraction
                        getVertexAndEvaluate(center, simp[worst], -C_CONTRACTION, secondTry);
                        if (value(secondTry) <= value(reflected))
                        {
                            copyVertex(secondTry, simp[worst]); // keep outer contraction
                                                                //operation="outC";
                            goto iteration;
                        }
                    }
                    else if (value(reflected) > value(simp[worst]) || double.IsNaN(value(reflected)))
                    {
                        // else inner contraction
                        getVertexAndEvaluate(center, simp[worst], C_CONTRACTION, secondTry);
                        if (value(secondTry) < value(simp[worst]))
                        {
                            copyVertex(secondTry, simp[worst]);     // keep contracted if better than 2nd worst
                                                                    //operation="innC";
                            goto iteration;
                        }
                    }
                    // if everything else has failed, contract simplex in on best
                    shrinkSimplexAndEvaluate(simp, best);
                    //operation="shri";
                    goto iteration;
                } // iteration:
iteration:

                bool checkParamResolution =    // if new 'worst' is not close to 'best', don't check any further
                                            paramResolutions != null && belowResolutionLimit(simp[worst], simp[best]);
                order(simp, worstNextBestArray);
                worst     = worstNextBestArray[WORST];
                nextWorst = worstNextBestArray[NEXT_WORST];
                best      = worstNextBestArray[BEST];

                if (checkParamResolution)
                {
                    if (belowResolutionLimit(simp, best))       // check whether all parameters are within the resolution limit
                    {
                        break;
                    }
                }
                if (belowErrorLimit(value(simp[best]), value(simp[worst]), 4.0)) // make sure we are at the minimum:
                {
                    getCenter(simp, -1, secondTry);                              // check center of the simplex
                    evaluate(secondTry);
                    if (value(secondTry) < value(simp[best]))
                    {
                        copyVertex(secondTry, simp[best]);      // better than best: keep
                    }
                }
                if (belowErrorLimit(value(simp[best]), value(simp[worst]), 4.0)) // no large spread of values
                {
                    break;                                                       // looks like we are at the minimum
                }
                if (totalNumIter > maxIter || thisNumIter > 4 * (maxIter / 10))
                {
                    status = MAX_ITERATIONS_EXCEEDED;
                }
                if (status != SUCCESS)
                {
                    break;
                }
                if ((ijStatusString != null || checkEscape) && totalNumIter > nextIterationForStatus)
                {
                    long time = Java.SystemCurrentTimeMillis();
                    nextIterationForStatus = totalNumIter + (int)(totalNumIter * 500L / (time - startTime + 1)); //next display 0.5 sec later
                }
            }
            //showSimplex(simp, "after "+totalNumIter+" iterations: value="+value(simp[best]));
            return(best);
        }