All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ngmf.util.cosu.luca.SCE Maven / Gradle / Ivy

There is a newer version: 0.8.1
Show newest version
package ngmf.util.cosu.luca;

import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.Vector;
import oms3.dsl.cosu.Step;

/**
 */
public class SCE {

    double[] initialParameterSet;    //INITIAL PARAMETER SET
    double[] lowerBound;    //LOWER BOUND ON PARAMETERS
    double[] upperBound;    // UPPER BOUND ON PARAMETERS
    int numOfParams;     // NUMBER OF PARAMETERS TO BE OPTIMIZED
    int initNumOfComplexes;    // NUMBER OF COMPLEXES IN THE INITIAL POPULATION
    int numOfPointsInComplex;    // NUMBER OF POINTS IN EACH COMPLEX
    int initTotalNumOfPoints;    //(initTotalNumOfPoints = initNumOfComplexes * numOfPointsInComplex

    //TOTAL NUMBER OF POINTS IN INITIAL POPULATION (NPT=NGS*NPG)
    int numOfPointsInSubComplex;    //NUMBER OF POINTS IN A SUB-COMPLEX
    int numOfEvolutionSteps;    //NUMBER OF EVOLUTION STEPS ALLOWED FOR EACH COMPLEX BEFORE
    //COMPLEX SHUFFLING
    int minNumOfComplexes;    //MINIMUM NUMBER OF COMPLEXES REQUIRED, IF THE NUMBER OF
    //COMPLEXES IS ALLOWED TO REDUCE AS THE OPTIMIZATION PROCEEDS
    //ISEED = INITIAL RANDOM SEED
    //INIFLG = FLAG ON WHETHER TO INCLUDE THE INITIAL POINT IN POPULATION
    // = 0, NOT INCLUDED
    //= 1, INCLUDED
    boolean includeInitialPOINT;
    //CONVERGENCE CHECK PARAMETERS
    //MAXN = MAX NO. OF TRIALS ALLOWED BEFORE OPTIMIZATION IS TERMINATED
    int maxNumOfTrials;
    // NUMBER OF SHUFFLING LOOPS IN WHICH THE CRITERION VALUE MUST
    //  CHANGE BY THE GIVEN PERCENTAGE BEFORE OPTIMIZATION IS TERMINATED
    int numOfShufflingLoops;
    //PERCENTAGE BY WHICH THE CRITERION VALUE MUST CHANGE IN
    // GIVEN NUMBER OF SHUFFLING LOOPS
    double percentage;
    // FLAG INDICATING WHETHER PARAMETER CONVERGENCE IS REACHED
    boolean paramConvergenceSATISFIED;

    //COORDINATES OF POINTS IN THE POPULATION
    double[][] pointsX;
    //FUNCTION VALUES OF X(.,.)
    double[] objFuncValueOfX;
    //COORDINATES OF A SINGLE POINT IN X
    double[] pointInX;
    //COORDINATES OF POINTS IN A COMPLEX
    double[][] pointsInComplex;
    //FUNCTION VALUES OF CX(.,.)
    double[] objFuncValuesOfComplex;
    //COORDINATES OF POINTS IN THE CURRENT SIMPLEX
    double[][] pointsInSimplex;
    //FUNCTION VALUES OF S(.,.)
    double[] objFuncValuesOfSimplex;
    //WORST POINT AT CURRENT SHUFFLING LOOP
    double[] worstPoint;
    //FUNCTION VALUE OF WORSTX(.)
    double objFuncValueOfWorstPoint;
    //STANDARD DEVIATION OF PARAMETERS IN THE POPULATION
    double[] stdDevOfPopulation;
    //NORMALIZED GEOMETRIC MEAN OF PARAMETER RANGES
    double normalizedGeometricMean;
    //INDICES LOCATING POSITION OF S(.,.) IN X(.,.)
    int[] indicesOfSimplex;
    //BOUND ON ITH VARIABLE BEING OPTIMIZED
    double[] bound;
    //NUMBER OF COMPLEXES IN CURRENT POPULATION
    int currentNumOfComplexes;
    //NUMBER OF COMPLEXES IN LAST POPULATION
    int lastNumOfComplexes;
    double[] bestCriterion;


    int totalNumOfPoints; // the number of points in current population
    double[] initialPoint; // initial point == initialParameterSet
    //
    private ExecutionHandle executionHandle;
    Step stepData;
    Step.Data data;
    int NLOOP = 0;
    int LOOP = 0;
    int IGS = 0;
    int icall = 0;
    //

    PrintStream out = System.out;

    public SCE(ExecutionHandle executionHandle, Step stepData, Step.Data data)  {

        this.executionHandle = executionHandle;
        this.stepData = stepData; // stepData contains data needed for running SCE
        this.data = data;

        // get values
        numOfParams = stepData.params().getCount();
        initNumOfComplexes = stepData.getInitComplexes();
        numOfPointsInComplex = stepData.getPointsPerComplex();
        numOfPointsInSubComplex = stepData.getPointsPerSubcomplex();
        numOfEvolutionSteps = stepData.getEvolutions();
        minNumOfComplexes = stepData.getMinComplexes();
        includeInitialPOINT = true;
        maxNumOfTrials = stepData.getMaxExec();
        numOfShufflingLoops = stepData.getShufflingLoops();
        percentage = stepData.getOfPercentage();
        upperBound = data.getUpperBound();
        lowerBound = data.getLowerBound();
        initialParameterSet = data.getParamValues();

//        System.out.println(maxNumOfTrials + " " + initNumOfComplexes + " " + numOfPointsInComplex + " " + numOfPointsInSubComplex + " " + numOfEvolutionSteps
//                + " " + minNumOfComplexes + " " + numOfShufflingLoops + " " + percentage);

        initTotalNumOfPoints = initNumOfComplexes * numOfPointsInComplex;

        // initialize arrays
        pointsX = new double[initTotalNumOfPoints][numOfParams];
        objFuncValueOfX = new double[initTotalNumOfPoints];
        pointInX = new double[numOfParams];

        pointsInComplex = new double[numOfPointsInComplex][numOfParams];
        objFuncValuesOfComplex = new double[numOfPointsInComplex];

        pointsInSimplex = new double[numOfPointsInSubComplex][numOfParams];
        objFuncValuesOfSimplex = new double[numOfPointsInSubComplex];
        worstPoint = new double[numOfParams];

        stdDevOfPopulation = new double[numOfParams];
        indicesOfSimplex = new int[numOfPointsInSubComplex];
        bound = new double[numOfParams];
        bestCriterion = new double[10];
        initialPoint = new double[numOfParams];
    }

    public void setOut(PrintStream out) {
        this.out = out;
    }

    public void run() throws Exception {
        currentNumOfComplexes = initNumOfComplexes;
        totalNumOfPoints = initTotalNumOfPoints;
        double objFuncValue;

        for (int j = 0; j < numOfParams; j++) {
            bound[j] = upperBound[j] - lowerBound[j];
            initialPoint[j] = initialParameterSet[j];
        }

        objFuncValue = execute(initialPoint); // write initialPoint in the 'newPARAMS' file, executes runMMS and SRobjfun()

        out.println("\n Initial OF value : " + objFuncValue);
        out.print(" Initial Parameterset : ");
        for (int j = 0; j < initialParameterSet.length; j++) {
            out.print(" " + initialParameterSet[j]);
        }
        out.println();

        if (maxNumOfTrials <= 1) {
            out.println("Due to max model execution of 1, no optimization was done. " +
                    "The only thing that was done is the calculation of objective function for initial values.");
            return; // done with this method
        }

        out.println(" SCE generating data points ....");
        if (includeInitialPOINT) {
//            out.println("Initial point will be included");
            for (int j = 0; j < numOfParams; j++) {
                pointsX[0][j] = initialParameterSet[j];
            }
            objFuncValueOfX[0] = objFuncValue;
        } else {
//            out.println("Initial point won't be included");
            for (int j = 0; j < numOfParams; j++) {
                pointsX[0][j] = lowerBound[j] + bound[j] * Math.random();
                pointInX[j] = pointsX[0][j];
            }
            // write pointInX in the 'newPARAMS' file, executes runMMS and SRobjfun()
            objFuncValue = execute(pointInX);
            objFuncValueOfX[0] = objFuncValue;
        }

        data.setObjFuncValueOfBestPoint(objFuncValueOfX[0]);
        int outputType = 1;
        if (icall < maxNumOfTrials) {
            for (int i = 1; i < totalNumOfPoints; i++) {
                for (int j = 0; j < numOfParams; j++) {
                    pointsX[i][j] = lowerBound[j] + bound[j] * Math.random();
                    pointInX[j] = pointsX[i][j];
                }

                objFuncValueOfX[i] = execute(pointInX);
                //ICALL++;
                if (icall >= maxNumOfTrials) {
                    totalNumOfPoints = i + 1;
                    pointsX = copy(pointsX, totalNumOfPoints);
                    objFuncValueOfX = copy(objFuncValueOfX, totalNumOfPoints);
                    break;
                }
            }
//            out.println("size of pointsX = " + totalNumOfPoints + " (max size is " + pointsX.length + ")" +
//                    ", max size of objFuncValueOfX = " + objFuncValueOfX.length);

            sort_duan(pointsX, objFuncValueOfX);

            // set the best point and its objective function value
            data.setBestParamData(pointsX[0], objFuncValueOfX[0]);
            for (int j = 0; j < numOfParams; j++) {
                worstPoint[j] = pointsX[totalNumOfPoints - 1][j];
            }
            objFuncValueOfWorstPoint = objFuncValueOfX[totalNumOfPoints - 1];

            parstt();
//            double distribution = normdistForBestPoint();
            out.print("\n Results of the initial SCE research:");
//            out.println("NLOOP: " + NLOOP);
//            out.println("ICALL: " + icall);
//            out.println("Number of complexes in current population: " + currentNumOfComplexes);
//            out.println("Function value of best point: " + data.getObjFuncValueOfBestPoint());
//            out.println("Function value of worst point: " + objFuncValueOfWorstPoint);
//            out.println("DIST for best point (DIST(0)): " + distribution);
//            out.println("Best point at current shuffling loop");
            for (int j = 0; j < numOfParams; j++) {
                out.print(" " + pointsX[0][j]); // display the best point
            }
            out.println();
            if (icall >= maxNumOfTrials) {
                outputType = 1;
            } else if (paramConvergenceSATISFIED) {
                outputType = 3;
            } else {
                outputType = mainLoop();
            }
        }

        /*************************************************************************
         * Creating a parameter file that contains the best point. This is not done
         * in the original SCE code.
         **************************************************************************/
        // get the best point
        double[] bestPoint = data.getBestParamDataArray();
        data.setParamValues(bestPoint); // set the best point in stepData
        executionHandle.writeParameterFile(data);

        String output = "";
        out.println("\n **************************************************");
        if (outputType == 1) {
            output = " Optimization terminated, limit " +
                    "on the maximum number of trials, " + maxNumOfTrials + ", was exceeded.\n" +
                    " Search was stopped at sub-complex " + (LOOP + 1) + " of complex " + (IGS + 1) +
                    " in shuffling loop. " + NLOOP;// + "\n" +
        } else if (outputType == 2) {
//            double percentage2 = percentage * 100;
            output = " Optimization terminated, OF value " +
                    "has not changed " + percentage + "% in " + numOfShufflingLoops +
                    " shuffling loops.";
        } else if (outputType == 3) {
            double normalizedGeometricMean2 = normalizedGeometricMean * 100;
            output = " Optimization terminated, population has " +
                    "converged into " + normalizedGeometricMean2 + "% of the feasible space.";
        } else if (outputType == 4) {
            output = " SCE was stopped.";
        }

        out.println(output);
        out.println(" **************************************************");
        out.print(" Final parameter estimates:");
        for (int j = 0; j < numOfParams; j++) {
            out.print(" " + bestPoint[j]);
            initialParameterSet[j] = bestPoint[j];
        }
        out.println();
        out.println(" Final OF value: " + data.getObjFuncValueOfBestPoint());
    }

    //  MAIN LOOP
    private int mainLoop() throws Exception {
        out.println(" SCE shuffling ....");
        int outputType = 1; // different output will be displayed depending on the value of ouputTYpe
        while (true) {
            NLOOP++;
            for (IGS = 0; IGS < currentNumOfComplexes; IGS++) {
                for (int k1 = 0; k1 < numOfPointsInComplex; k1++) {
                    int k2 = k1 * currentNumOfComplexes + IGS;
                    for (int j = 0; j < numOfParams; j++) {
                        pointsInComplex[k1][j] = pointsX[k2][j];
                    }
                    objFuncValuesOfComplex[k1] = objFuncValueOfX[k2];
                }
                for (LOOP = 0; LOOP < numOfEvolutionSteps; LOOP++) {
                    if (numOfPointsInSubComplex == numOfPointsInComplex) {
                        for (int k = 0; k < numOfPointsInSubComplex; k++) {
                            indicesOfSimplex[k] = k;
                        }
                    } else {
                        //  k = 0 instead of k = 1 because the line above (indicesOfSimplex[0] = ....)
                        // is removed.
                        for (int k = 0; k < numOfPointsInSubComplex; k++) {
                            boolean again = true;
                            int lpos = -1;
                            while (again) {
                                again = false;
                                lpos = (int) (numOfPointsInComplex + 0.5 -
                                        Math.sqrt(Math.pow((numOfPointsInComplex + 0.5), 2) -
                                        numOfPointsInComplex * (numOfPointsInComplex + 1) * Math.random()));
                                // check if any element from indicesOfSimplex[0] to indicesOfSimplex[k-1]
                                // is equal to LPOS. If not, get out of the for loop, finish the while(AGAIN) loop,
                                // and set LPOS as a value of indicesOfSimplex[k]
                                for (int k1 = 0; k1 < k; k1++) {
                                    if (lpos == indicesOfSimplex[k1]) {
                                        again = true;
                                        break;
                                    }
                                }
                            }
                            indicesOfSimplex[k] = lpos;
                        }
                        // sort the indiciesOfSimplex array in increasing order
                        Arrays.sort(indicesOfSimplex);
                    }

                    for (int k = 0; k < numOfPointsInSubComplex; k++) {
                        for (int j = 0; j < numOfParams; j++) {
                            pointsInSimplex[k][j] = pointsInComplex[indicesOfSimplex[k]][j];
                        }
                        objFuncValuesOfSimplex[k] = objFuncValuesOfComplex[indicesOfSimplex[k]];
                    }
                    cce();
                    for (int k = 0; k < numOfPointsInSubComplex; k++) {
                        for (int j = 0; j < numOfParams; j++) {
                            pointsInComplex[indicesOfSimplex[k]][j] = pointsInSimplex[k][j];
                        }
                        objFuncValuesOfComplex[indicesOfSimplex[k]] = objFuncValuesOfSimplex[k];
                    }
                    sort_duan(pointsInComplex, objFuncValuesOfComplex);
                    if (icall >= maxNumOfTrials) {
                        break;
                    }
                } // end of loop with LOOP
                for (int k1 = 0; k1 < numOfPointsInComplex; k1++) {
                    int k2 = k1 * currentNumOfComplexes + IGS;
                    for (int j = 0; j < numOfParams; j++) {
                        pointsX[k2][j] = pointsInComplex[k1][j];
                    }
                    objFuncValueOfX[k2] = objFuncValuesOfComplex[k1];
                }
                if (icall >= maxNumOfTrials) {
                    break;
                }
            } // end of for loop with IGS

            sort_duan(pointsX, objFuncValueOfX);
            // set the best point and its objective function value
            data.setBestParamData(pointsX[0], objFuncValueOfX[0]);
            for (int j = 0; j < numOfParams; j++) {
                worstPoint[j] = pointsX[totalNumOfPoints - 1][j];
            }
            objFuncValueOfWorstPoint = objFuncValueOfX[totalNumOfPoints - 1];

            parstt();
//            double distribution = normdistForBestPoint();
//            out.println("loop " + NLOOP + "  ICALL = " + icall);
//            out.println("Number of complexes in a current population: " + currentNumOfComplexes);
//            out.println("Objective Function value of best point: " + data.getObjFuncValueOfBestPoint());
//            out.println("Objective Function value of worst point: " + objFuncValueOfWorstPoint);
//            out.println("Normal Distribution of best point: " + distribution);
//            out.println();
            
            if (icall >= maxNumOfTrials) {
                outputType = 1;
                break;
            }

            int lastIndex = bestCriterion.length - 1; // currently this value is 9

            bestCriterion[lastIndex] = data.getObjFuncValueOfBestPoint();
            if (NLOOP > numOfShufflingLoops) // ### Is this right?
            {
                // This condition is needed. If NLOOP < vectorOfBestCriterion.length,
                // then there are some elements that are not set yet in vectorOfBestCriterion.
                if (NLOOP >= bestCriterion.length) {
                    int idx = lastIndex - numOfShufflingLoops;
                    if (idx < 0) //#### For now, tempIndex is set to 0 if tempIndex < 0. This line should be changed.
                    {
                        idx = 0;
                    }
                    double denomi = Math.abs(bestCriterion[idx] + bestCriterion[lastIndex]) / 2;
                    double timeou = Math.abs(bestCriterion[idx] - bestCriterion[lastIndex]) / denomi;
//                    out.println("\n$$$$$$$$$$$$ NLOOP = " + NLOOP + "\tnumOfShufflingLoops = " + numOfShufflingLoops +
//                            "\tvectorOfBestCriterion length = " + bestCriterion.length + "\tPercentage is calculated: " + timeou);
                    if (timeou < percentage) {
                        outputType = 2;
                        break;
                    }
                }
            }
            for (int l = 0; l < lastIndex; l++) {
                bestCriterion[l] = bestCriterion[l + 1];  // ######## Does this work????
            }
            if (paramConvergenceSATISFIED) {
                outputType = 3;
                break;
            }
            if (currentNumOfComplexes > minNumOfComplexes) {
                lastNumOfComplexes = currentNumOfComplexes;
                currentNumOfComplexes -= 1;
                totalNumOfPoints = currentNumOfComplexes * numOfPointsInComplex;
                comp();
            }
        }
        return outputType;
    }

    //#########################################################################
    //##  Other functions
    //########################################################################
    double execute(double[] array) throws Exception {
        data.setParamValues(array);
        executionHandle.execute(data);
        icall++;
        double of = stepData.calculateObjectiveFunctionValue(executionHandle);
         double distribution = normdistForBestPoint();
//          out.println("loop " + NLOOP + "  ICALL = " + icall);
//            out.println("Number of complexes in a current population: " + currentNumOfComplexes);
//            out.println("Objective Function value of best point: " + data.getObjFuncValueOfBestPoint());
//            out.println("Objective Function value of worst point: " + objFuncValueOfWorstPoint);
//            out.println("Normal Distribution of best point: " + distribution);

        out.print(" %r   " + icall + ": " + of + " [" + data.getObjFuncValueOfBestPoint() + "/" + objFuncValueOfWorstPoint+"]" + " c:" + currentNumOfComplexes + " d:" + distribution);
        return of;
    }

    void sort_duan(double[][] x, double[] y) {
        Vector indices = new Vector();
        for (int i = 0; i < x.length; i++) {
            indices.add(new Integer(i));
        }
        if (!stepData.maximizeObjectiveFunctionValue()) {
            Sorter sorter = new Sorter(y, Sorter.ASCENDING);
            Collections.sort(indices, sorter);
            Arrays.sort(y);
        } else {
            Sorter sorter = new Sorter(y, Sorter.DESCENDING);
            Collections.sort(indices, sorter);
            // sort y[] in ascending order
            Arrays.sort(y);
            // reverse the order of y to be in descending order
            double[] new_y = new double[y.length];
            for (int i = 0; i < y.length; i++) {
                new_y[i] = y[y.length - 1 - i];
            }
            for (int i = 0; i < y.length; i++) {
                y[i] = new_y[i];
            }
        }
        double[][] new_x = new double[x.length][x[0].length];
        for (int i = 0; i < new_x.length; i++) {
            new_x[i] = x[indices.get(i).intValue()];
        }
        for (int i = 0; i < x.length; i++) {
            x[i] = new_x[i];
        }
    }

    void parstt() {
        double[] xMax = new double[numOfParams];
        double[] xMin = new double[numOfParams];
        double[] xMean = new double[numOfParams];
        double delta = Math.pow(10, -20);
//        double delta = 10E-20;
        double peps = Math.pow(10, -3); // minimum standard deviation
//        double peps = 10E-3;              // minimum standard deviation
        double gSum = 0;
        for (int k = 0; k < numOfParams; k++) {
            xMax[k] = Double.MIN_VALUE;
            xMin[k] = Double.MAX_VALUE;
            double xSum1 = 0;
            double xSum2 = 0;
            for (int i = 0; i < totalNumOfPoints; i++) {
                xMax[k] = Math.max(pointsX[i][k], xMax[k]);
                xMin[k] = Math.min(pointsX[i][k], xMin[k]);
                xSum1 = xSum1 + pointsX[i][k];
                xSum2 = xSum2 + pointsX[i][k] * pointsX[i][k];
            }
            xMean[k] = xSum1 / (double) totalNumOfPoints;
            stdDevOfPopulation[k] = xSum2 / (double) totalNumOfPoints - xMean[k] * xMean[k];
            if (stdDevOfPopulation[k] <= delta) {
                stdDevOfPopulation[k] = delta;
            }
            stdDevOfPopulation[k] = Math.sqrt(stdDevOfPopulation[k]) / bound[k];
            gSum += Math.log(delta + (xMax[k] - xMin[k]) / bound[k]);
        }
        normalizedGeometricMean = Math.pow(Math.E, gSum / (double) numOfParams);
        paramConvergenceSATISFIED = false;
        if (normalizedGeometricMean <= peps) {
            paramConvergenceSATISFIED = true;
        }
    }

    /*  This method returns the normal distance of the best point. This method
     *  is used instead of normdist() because normdist() determins the normal
     *  distances for all points, which is not needed. */
    double normdistForBestPoint() {
        double normalDistance = 0;
        for (int i = 0; i < numOfParams; i++) {
            normalDistance += Math.abs(pointsX[0][i] - initialPoint[i]) / bound[i];
        }
        normalDistance = normalDistance / numOfParams;
        return normalDistance;
    }

    void comp() {
        double[][] tempPoints = new double[totalNumOfPoints][numOfParams];
        double[] tempObjFuncValues = new double[totalNumOfPoints];

        // copy selected elements in pointsX and objFuncValueOfX to tempPoints and tempObjFuncValues
        for (int igs = 0; igs < currentNumOfComplexes; igs++) {
            for (int ipg = 0; ipg < numOfPointsInComplex; ipg++) {
                int k1 = ipg * lastNumOfComplexes + igs;
                int k2 = ipg * currentNumOfComplexes + igs;
                for (int i = 0; i < numOfParams; i++) {
                    tempPoints[k2][i] = pointsX[k1][i];
                }
                tempObjFuncValues[k2] = objFuncValueOfX[k1];
            }
        }
        // reinitialize pointsX and objFuncValueOfX with a correct size
        pointsX = new double[totalNumOfPoints][numOfParams];
        objFuncValueOfX = new double[totalNumOfPoints];
        // copy elements of tempPointx and tempObjFuncValues back to pointsX and objFuncValueOfX
        for (int j = 0; j < totalNumOfPoints; j++) {
            for (int i = 0; i < numOfParams; i++) {
                pointsX[j][i] = tempPoints[j][i];
            }
            objFuncValueOfX[j] = tempObjFuncValues[j];
        }
    }

    void cce() throws Exception {
        double[] worstPointSimplex = new double[numOfParams]; // WO(.)
        double[] centroid = new double[numOfParams]; //CE(.)
        double[] newPoint = new double[numOfParams]; //SNEW(.)
        double[] vector = new double[numOfParams]; //STEP(.)
        double worstObjFuncValue; //FW

        for (int j = 0; j < numOfParams; j++) {
            // pointsInSimplex[] is sorted based on the objective functions values,
            // so the element in the last index is the worst point.
            worstPointSimplex[j] = pointsInSimplex[numOfPointsInSubComplex - 1][j];
            centroid[j] = 0;
            // exclude the last point (worst point) in this loop
            for (int i = 0; i < (numOfPointsInSubComplex - 1); i++) {
                centroid[j] += pointsInSimplex[i][j];
            }
            centroid[j] = centroid[j] / ((double) (numOfPointsInSubComplex - 1));
            vector[j] = centroid[j] - worstPointSimplex[j];
        }
        worstObjFuncValue = objFuncValuesOfSimplex[numOfPointsInSubComplex - 1];
        for (int j = 0; j < numOfParams; j++) {
            newPoint[j] = worstPointSimplex[j] + 2 * vector[j];
        }
        boolean outOfBOUND = false;
        for (int j = 0; j < numOfParams; j++) {
            if ((newPoint[j] > upperBound[j]) || (newPoint[j] < lowerBound[j])) {
                outOfBOUND = true;
                break;
            }
        }
        if (outOfBOUND) {
            getNewPointAtRandom(newPoint);
        }
        double newObjFuncValue = execute(newPoint);

        if ((stepData.maximizeObjectiveFunctionValue() && newObjFuncValue <= worstObjFuncValue) ||
                (!stepData.maximizeObjectiveFunctionValue() && newObjFuncValue >= worstObjFuncValue)) {
            if (icall >= maxNumOfTrials) {
                return; //ICALL;
            }
            for (int j = 0; j < numOfParams; j++) {
                newPoint[j] = worstPointSimplex[j] + 0.5 * vector[j];
            }
            newObjFuncValue = execute(newPoint);
            if ((stepData.maximizeObjectiveFunctionValue() && newObjFuncValue < worstObjFuncValue) ||
                    (!stepData.maximizeObjectiveFunctionValue() && newObjFuncValue > worstObjFuncValue)) {
                if (icall >= maxNumOfTrials) {
                    return;
                }
                getNewPointAtRandom(newPoint);
                newObjFuncValue = execute(newPoint);

            }// end of the 2nd if ((newObjFuncValue > worstObjFuncValue) ... )
        } // end of the 1st if ((newObjFuncValue > worstObjFuncValue) ... )

        for (int j = 0; j < numOfParams; j++) {
            pointsInSimplex[numOfPointsInSubComplex - 1][j] = newPoint[j];
        }
        objFuncValuesOfSimplex[numOfPointsInSubComplex - 1] = newObjFuncValue;
    }

    /* a new point is assigned to newPoint based on stdDevOfPopulation[],
     *  gasdev(), bound[], and etc.*/
    void getNewPointAtRandom(double[] newPoint) {
        for (int j = 0; j < numOfParams; j++) {
            int nnn = 0;
            do {
                double R = gasdev();
                newPoint[j] = pointsInSimplex[0][j] + stdDevOfPopulation[j] * R * bound[j];
                nnn++;
                if (nnn == 1001) {
                    out.println("SCE: getNewPointAtRandom(): Having hard time generating a new point in a feasible region");
                }
                if (nnn > 1000) {
                    newPoint[j] = lowerBound[j] + Math.abs(R) * (0.5 * bound[j]);
                    if (nnn % 100 == 1) {
                        out.print("Attempt " + nnn + ": new point = " + newPoint[j] +
                                ", lower bound = " + lowerBound[j] + ", upper bound = " + upperBound[j]);
                    }
                    if ((newPoint[j] > upperBound[j]) || (newPoint[j] < lowerBound[j])) {
                        out.println(" ---> out of bound");
                    } else {
                        out.println(" ---> in bound!!");
                    }
                }
            } while ((newPoint[j] > upperBound[j]) || (newPoint[j] < lowerBound[j]));
        }
    }
    //
    boolean calculateGASDEV = true; // if true, gasdev() returns gasdevValue1
    double gasdevValue1; // one of the two values generated in gasdev()
    double gasdevValue2; // one of the two values generated in gasdev()

    /* returns a normally distributed deviate with zero mean and unit variance,
     *  using random number generator, as the source of uniform deviates.
     */
    double gasdev() {
        double R, v1, v2;
        if (calculateGASDEV) {
            // if we don't have an extra deviate handy
            do {
                // pick two uniform numbers in the square extending from -1 to +1
                // in each direction
                v1 = 2 * Math.random() - 1;
                v2 = 2 * Math.random() - 1;
                // check if v1 and v2 are in the unit circle
                R = v1 * v1 + v2 * v2;
            } while (R >= 1); // if v1 and v2 are not in the unit circle

            // make the Box-Muller transformation to get two normal deviates
            double fac = Math.sqrt((-1) * ((2 * Math.log(R)) / R));
            gasdevValue2 = v1 * fac; // one of the two normal deviates. gasdevValue2 is returned
            // next time this function is called
            gasdevValue1 = v2 * fac; // the other normal deviate, which will be returned at this time
            calculateGASDEV = false;
            return gasdevValue1;
        } else {
            calculateGASDEV = true;
            return gasdevValue2;
        }
    }

    /* returns an array of the specified size, containing the elements of index
     *  from 0 to size - 1 in source. */
    double[] copy(double[] source, int size) {
        double[] newArray = new double[size];
        for (int i = 0; i < size; i++) {
            newArray[i] = source[i];
        }
        return newArray;
    }

    /* returns an 2D array[rowSize][length of columns of source], containing
     *  the elements from source[0][] to source[size-1][]. */
    double[][] copy(double[][] source, int rowSize) {
        double[][] newArray = new double[rowSize][source[0].length];
        for (int i = 0; i < rowSize; i++) {
            for (int j = 0; j < newArray[0].length; j++) {
                newArray[i][j] = source[i][j];
            }
        }
        return newArray;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy