예제 #1
0
  /**
   * Runs the optimization process until a termination criteria is satisfied
   *
   * @param x0 initial point
   * @return <CODE>-1</CODE> if the maximum number of iteration is exceeded <br>
   *     <CODE>+1</CODE> if the required accuracy is reached
   * @exception Exception
   * @exception OptimizerException
   */
  public int run(Point x0) throws OptimizerException, Exception {
    boolean restart = false;
    int retFla = 0;
    int i, j, nue;
    int w = 0;
    int b = 0;
    double ssf = 1;
    int dimF = getDimensionF();
    Point[] xkP1 = new Point[dimXP1]; // xkP1 = x(k+1)
    for (i = 0; i < dimXP1; i++) xkP1[i] = new Point(dimX, 0, dimF);
    Point xN = new Point(dimX, 0, dimF);
    Point xNN = new Point(dimX, 0, dimF);
    double[] xC = new double[dimX];
    double[] xTemp = new double[dimX];

    String[] com = new String[11];
    com[1] = "Establish initial simplex (1).";
    com[2] = "Reflection (2).";
    com[4] = "Expansion (4).";
    com[5] = "Partial outside contraction (5).";
    com[6] = "Partial inside contraction (6).";
    com[7] = "Total contraction to best known point (7).";
    com[10] = "Invoke simplex reconstruction (10).";

    final String comBesNowPoi = "Best known point in total contraction (7).";
    final String comNewSte = "New step.";
    final String comBasPoi = "Base point for optimality check.";

    double[] dNew = new double[dimX]; // new movement direction of changed point
    double[] dOld = new double[dimX]; // old movement direction of changed point
    double dNewL2; // L2norm of dNew
    int stepOld = 0; // number of last step section
    double cosMov = -1; // inner product of the last two directions
    boolean insideContraction = false; // flag whether we have just a inside contraction
    // beyond us
    int step = 0; // number of step
    boolean tryRes;
    boolean iterate = true;
    int nexAllRes = konvge; // number of main iteration when next restart might
    // be enabled

    // Perturber for check of the optimaltity condition
    Perturber per = new Perturber(this);

    LinAlg.initialize(xC, 0);

    // optimization loop
    do {
      switch (step) {
        case 0: // Initalization
          for (i = 0; i < dimX; i++) // starting point
          x[0].setX(i, getX0(i));
          step = 1;
          break;
        case 1: // Etablish the initial simplex
          for (i = 1; i < dimXP1; i++) {
            for (j = 0;
                j < dimX;
                j++) { // getX is used on x[0] since x[0] may be reassigned after a failed
                       // optimality check
              if (i == j + 1) x[i].setX(j, x[0].getX(j) + ssf * getDx(j, x[0].getX(j)));
              else x[i].setX(j, x[0].getX(j));
            }
          }
          // get the objective function values for the initial simplex
          if (restart) {
            i = 1; // first point is already known from step 10
            restart = false;
          } else i = 0;

          for (; i < dimXP1; i++) {
            x[i].setComment(com[1]);
            x[i] = getF(x[i]);
            report(x[i], SUBITERATION);
            if (i == 0) report(x[i], MAINITERATION);
            checkObjectiveFunctionValue(x[i]);
          }
          step = 2;
          break;
        case 2: // determine worst and best point for the normal reflection
          w = getWorst();
          b = getBest();
          xC = getXCenter(w);
          xN.setComment(com[2]);
          xN.setX(reflect(xC, x[w].getX()));
          xN = getF(xN);
          report(xN, SUBITERATION);
          stepOld = step;
          step = (xN.getF(0) < x[b].getF(0)) ? 4 : 3;
          break;
        case 3: // compare trial with other vertices
          nue = dimXP1 - rank(xN.getF(0)); // if nue is 0, we got the worst point

          if (nue == 0) // we got even a worser point than we had
          step = 6;
          else if (nue == 1) // we got a worse point but not that worse as the last was
          step = 5;
          else // we got a good point
          {
            xkP1[w] = (Point) xN.clone();
            step = 8;
          }
          break;
        case 4: // Expansion (try if further expansion of point is successfull)
          xNN.setComment(com[4]);
          xNN.setX(LinAlg.subtract(LinAlg.multiply(2., xN.getX()), xC));
          xNN = getF(xNN);
          report(xNN, SUBITERATION);

          if (xNN.getF(0) < x[b].getF(0)) xkP1[w] = (Point) xNN.clone(); // expansion was successful
          else xkP1[w] = (Point) xN.clone();
          stepOld = step;
          step = 8;
          break;
        case 5: // Partial outside contraction
          xNN.setComment(com[5]);
          xNN.setX(LinAlg.multiply(0.5, LinAlg.add(xC, xN.getX())));
          xNN = getF(xNN);
          report(xNN, SUBITERATION);
          if (xNN.getF(0) <= xN.getF(0)) {
            xkP1[w] = (Point) xNN.clone();
            stepOld = step;
            step = 8;
          } else step = 7;
          break;
        case 6: // Partial inside contraction
          xNN.setComment(com[6]);
          xNN.setX(LinAlg.multiply(0.5, LinAlg.add(xC, x[w].getX())));
          xNN = getF(xNN);
          report(xNN, SUBITERATION);

          /* the inequality (fNN >= fX[w]) is changed so that we
             get a total contraction
             if some vertices are in a null space.
             Nelder Mead have in their paper (1965) the strict
             inequality (fNN > fX[w])    02/16/99 wm
          */
          if (xNN.getF(0) >= x[w].getF(0)) step = 7;
          else {
            xkP1[w] = (Point) xNN.clone();
            stepOld = step;
            step = 8;
            insideContraction = true;
          }
          break;
        case 7: // Total contraction to best point
          // construct new simplex
          xkP1[b] = (Point) x[b].clone();
          xkP1[b].setComment(comBesNowPoi);
          report(xkP1[b], SUBITERATION);
          report(xkP1[b], MAINITERATION);

          xTemp = x[b].getX();

          for (i = 0; i < dimXP1; i++) {
            if (i != b) {
              xkP1[i].setComment(com[7]);
              xkP1[i].setX(LinAlg.multiply(0.5, LinAlg.add(xTemp, x[i].getX())));
              xkP1[i] = getF(xkP1[i]);
              report(xkP1[i], SUBITERATION);
              report(xkP1[i], MAINITERATION);
              checkObjectiveFunctionValue(xkP1[i]);
            }
          }
          insideContraction = true;
          step = 9;
          break;
        case 8: // normal iteration loop
          for (i = 0; i < dimXP1; i++) {
            if (i != w) xkP1[i] = (Point) x[i].clone();
            else {
              xkP1[w].setComment(com[stepOld]);
              report(xkP1[w], MAINITERATION);
              checkObjectiveFunctionValue(xkP1[w]);
            }
          }
          step = 9;
          break;
        case 9: // Termination criterion
          // increase k <- k+1
          // Note: 9 is only entered from 7 or 8

          // determine movement direction of simplex
          if (modStoCri) {
            System.arraycopy(dNew, 0, dOld, 0, dimX);
            // new (current) search direction
            double[][] temp1 = new double[dimXP1][dimX];
            double[][] temp2 = new double[dimXP1][dimX];
            for (i = 0; i < dimXP1; i++) {
              temp1[i] = xkP1[i].getX();
              temp2[i] = x[i].getX();
            }
            dNew = LinAlg.subtract(LinAlg.getCenter(temp1), LinAlg.getCenter(temp2));
            dNewL2 = LinAlg.twoNorm(dNew);
            if (dNewL2 > Double.MIN_VALUE) dNew = LinAlg.multiply(1 / dNewL2, dNew);
            cosMov = LinAlg.innerProduct(dOld, dNew);
          }

          ///////////////////////////////////////////////////////////
          // update points
          for (i = 0; i < dimXP1; i++) x[i] = (Point) xkP1[i].clone();

          if (checkMaxIteration()) {
            retFla = -1;
            iterate = false;
            break;
          }

          // check for restart
          if (modStoCri)
            tryRes =
                (insideContraction
                    && (cosMov <= 0)
                    && (nexAllRes <= getMainIterationNumber())
                    && restartCriterion());
          else tryRes = (nexAllRes <= getMainIterationNumber()) && restartCriterion();

          if (tryRes) {
            // try a restart
            step = 10;
            nexAllRes = getMainIterationNumber() + konvge + 1;
          } else {
            // do a usual iteration loop
            if (writeStepNumber()) {
              // get the best point
              b = getBest();
              x[b].setComment(comNewSte);
              x[b] = increaseStepNumber(x[b]);
              report(x[b], MAINITERATION);
              report(x[b], SUBITERATION);
            }
            step = 2;
          }
          // reset contraction flag
          insideContraction = false;
          break;
        case 10: // restart test (note that w points to the new vertex)
          ssf = cFactor; // factor for step size
          b = getBest();
          x[b].setComment(comBasPoi);
          report(x[b], SUBITERATION);
          per.perturb(x[b], ssf);
          if (per.gotOptimum()) { // we are at the minimum
            retFla = 1;
            reportMinimum();
            iterate = false;
          } else {
            restart = true; // to prevent a recalculation of the 0-th pt.
            x[0] = per.getOptimalPoint();
            x[0].setComment(com[10]);
            report(x[0], MAINITERATION);
            if (writeStepNumber()) {
              x[0].setComment(comNewSte);
              x[0] = increaseStepNumber(x[0]);
              report(x[0], MAINITERATION);
            }
            step = 1;
          }
          break;
      }
    } while (iterate);
    return retFla;
  }