void NonGradient::optimize_vertex_positions(PatchData &pd, 
                                            MsqError &err)
{
  MSQ_FUNCTION_TIMER( "NonGradient::optimize_vertex_positions" );
  int numRow = getDimension();
  int numCol = numRow+1;  
  std::vector<double> height(numCol); 

  for(int col = 0; col < numCol; col++)
  {
    height[col] =  evaluate(&simplex[col*numRow], pd, err);//  eval patch stuff
  }
  if(mNonGradDebug > 0)
  {
    printSimplex( simplex, height );
  }

  // standardization
  TerminationCriterion* term_crit=get_inner_termination_criterion();
  int maxNumEval = getMaxNumEval();
  double threshold = getThreshold();
//  double ftol = getTolerance();
  int ilo = 0;  //height[ilo]<=...
  int inhi = 0; //...<=height[inhi]<=
  int ihi = 0;  //<=height[ihi] 
//  double rtol = 2.*ftol;
  double ysave;
  double ytry;
  bool afterEvaluation = false;
  std::vector<double> rowSum(numRow);
  getRowSum( numRow, numCol, simplex, rowSum);
  while( !( term_crit->terminate() ) )
  {

    if(mNonGradDebug > 0)
    {
      printSimplex( simplex, height );
    }
    //std::cout << "rtol " << rtol << " ftol " << ftol << " MesquiteIter " << term_crit->get_iteration_count() << " Done " << term_crit->terminate() << std::endl;

    if( afterEvaluation )   
    {
      // reflect highPt through opposite face
      // height[0] may vanish
/*
      if( !testRowSum( numRow, numCol, &simplex[0], &rowSum[0]) )
      {
        // Before uncommenting here and ... 
        //MSQ_SETERR(err)("Internal check sum test A failed", MsqError::INTERNAL_ERROR);
        //MSQ_ERRRTN(err);
      }
*/
      ytry=amotry(simplex,height,&rowSum[0],ihi,-1.0, pd, err);
/*
      if( !testRowSum( numRow, numCol, &simplex[0], &rowSum[0]) )
      {
         // ... here, determine a maxVal majorizing the previous as well as the current simplex.
         //MSQ_SETERR(err)("Internal check sum test B failed", MsqError::INTERNAL_ERROR);
         //MSQ_ERRRTN(err);
      }   
*/
  
/*
      if( height[0] == 0.)
      {
         MSQ_SETERR(err)("(B) Zero objective function value", MsqError::INTERNAL_ERROR);
         exit(-1);
      }
*/
      if (ytry <= height[ilo])   
      {
        ytry=amotry(simplex,height,&rowSum[0],ihi,-2.0,pd,err);
        if( mNonGradDebug >= 3 ) 
        {      
         std::cout << "Reflect and Expand from highPt " << ytry << std::endl;
        }      
        //MSQ_PRINT(3)("Reflect and Expand from highPt : %e\n",ytry);
      }
      else 
      {
        if (ytry >= height[inhi]) 
        {
          ysave=height[ihi]; // Contract along highPt
          ytry=amotry(simplex,height,&rowSum[0],ihi,0.5,pd,err);
          if (ytry >= ysave)
          { // contract all directions toward lowPt
            for (int col=0;col<numCol;col++)
            {
              if (col != ilo)
              {
                for (int row=0;row<numRow;row++)
                {
                  rowSum[row]=0.5*(simplex[row+col*numRow]+simplex[row+ilo*numRow]);
                  simplex[row+col*numRow]=rowSum[row];
                }
                height[col] = evaluate(&rowSum[0], pd, err); 
                if( mNonGradDebug >= 3 ) 
                {      
                  std::cout << "Contract all directions toward lowPt value( " << col << " ) = " << height[col] << " ilo = " << ilo << std::endl;
                }      
                //MSQ_PRINT(3)("Contract all directions toward lowPt value( %d ) = %e    ilo = %d\n", col, height[col], ilo);
              }
            }
          }
        }   
      } // ytri > h(ilo) 
    } // after evaluation
    ilo=1; // conditional operator or inline if 
    ihi = height[0] > height[1] ? (inhi=1,0) : (inhi=0,1);
    for (int col=0;col<numCol;col++)
    {
      if (height[col] <= height[ilo])
      {
        ilo=col;  // ilo := argmin height
      }
      if (height[col] > height[ihi])
      {
        inhi=ihi;
        ihi=col;
      } 
      else  // height[ihi] >= height[col]
        if (col != ihi && height[col] > height[inhi] ) inhi=col;
    }
//    rtol=2.0*fabs( height[ihi]-height[ilo] )/
//         ( fabs(height[ihi])+fabs(height[ilo])+threshold );
    afterEvaluation = true;
  } //  while not converged 

  // Always set to current best mesh.
  { 
    if( ilo != 0 )
    {
      double yTemp = height[0];
      height[0] = height[ilo]; // height dimension numCol
      height[ilo] = yTemp;
      for (int row=1;row<numRow;row++)
      { 
          yTemp = simplex[row];
          simplex[row] = simplex[row+ilo*numRow];
          simplex[row+ilo*numRow] = yTemp;
      }
    }
  }
  if( pd.num_free_vertices() > 1 )
  {
    MSQ_SETERR(err)("Only one free vertex per patch implemented", MsqError::NOT_IMPLEMENTED);
  }

  Vector3D newPoint( &simplex[0] ); 
  size_t vertexIndex = 0; // fix c.f. freeVertexIndex
  pd.set_vertex_coordinates( newPoint, vertexIndex, err ); 
  pd.snap_vertex_to_domain( vertexIndex, err );
  if( term_crit->terminate() )
  {
    if( mNonGradDebug >= 1 ) 
    {      
         std::cout << "Optimization Termination OptStatus: Max Iter Exceeded" << std::endl;
    }      
    //MSQ_PRINT(1)("Optimization Termination OptStatus: Max Iter Exceeded\n"); 
  }
}
Exemple #2
0
void multiDS(int n, double *x, double cc, double ce, double lmin,
             double lstart, int maxiter)
{
   int i, imin, replaced, iter = 0;
   double **xs, **xr, **xe, **xc, *fs, *fr, *fe, *fc, fsmin, frmin,
      femin, fcmin, ssize;
   FILE *fp;
   void initSimplex(int, double *, double **, double);
   void printSimplex(int, int, double **, double *);
   void findBest(int, double **, double *, int *, double *);
   void copySimplex(int, double **, double **, double *, double *);
   double simplexSize(int, double **);
   void vecAdd(int, double *, double *, double *, double);
   double dmin(int, double *);
   void mpi_assign(int);
   void mpi_distribute(int, double *);

   /* Initial size of simplex */
   ssize = lstart;

   /* Check validity of input parameters */
   if(cc <= 0.0 || cc >= 1.0) {
      printf("multiDS: contraction coefficient must be in (0,1)\n");
      exit(0);
   }

   if(ce <= 1.0) {
      printf("multiDS: expandion coefficient must be > 1\n");
      exit(0);
   }

   if(ssize < lmin) {
      printf("multiDS: starting simplex size is < minimum\n");
      printf("         give lstart > lmin\n");
      exit(0);
   }

   printf("Parameters for search:\n");
   printf("   Contraction factor     = %e\n", cc);
   printf("   Expansion   factor     = %e\n", ce);
   printf("   Starting simplex size  = %e\n", ssize);
   printf("   Minimum  simplex size  = %e\n", lmin);
   printf("   Maximum number of iter = %d\n", maxiter);

   /* Allocate memory */
   xs = (double **) calloc((n + 1), sizeof(double *));
   xr = (double **) calloc((n + 1), sizeof(double *));
   xe = (double **) calloc((n + 1), sizeof(double *));
   xc = (double **) calloc((n + 1), sizeof(double *));
   fs = (double *) calloc(n + 1, sizeof(double));
   fr = (double *) calloc(n + 1, sizeof(double));
   fe = (double *) calloc(n + 1, sizeof(double));
   fc = (double *) calloc(n + 1, sizeof(double));
   for(i = 0; i < n + 1; i++) {
      xs[i] = (double *) calloc(n, sizeof(double));
      xr[i] = (double *) calloc(n, sizeof(double));
      xe[i] = (double *) calloc(n, sizeof(double));
      xc[i] = (double *) calloc(n, sizeof(double));
   }


   /* Initialize the simplex */
   initSimplex(n, x, xs, ssize);

   /* Assign evaluations to different proc */
   mpi_assign(n);

   /* Calculate initial function values */
   /* Zeroth vertex is starting vertex, cost = 1. No need to calculate again
    * since it is already done in multiDS_driver.c */
   fs[0] = cost0;

   for(i = 1; i < n + 1; i++) {
      if(proc[i] == myproc)
         fs[i] = objFun(n, xs[i]);
   }

   /* Distribute cost functions */
   mpi_distribute(n, fs);

   printf("Initial simplex and function values:\n");
   printSimplex(0, n, xs, fs);

   /* Find best vertex and put in first position */
   findBest(n, xs, fs, &imin, &fsmin);

   if(myproc == 0)
      fp = fopen("cost.dat", "w");

   /* Main iteration loop */
   while(ssize > lmin && iter < maxiter) {
      printf("Iteration = %d\n\n", iter + 1);

      replaced = 0;
      while(!replaced && ssize > lmin) { /* inner repeat loop */

         /* rotation step */
         printf("   Rotation:\n");
         for(i = 1; i <= n; i++) {
            vecAdd(n, xs[0], xs[i], xr[i], 1.0);
            if(proc[i] == myproc)
               fr[i] = objFun(n, xr[i]);
         }
         mpi_distribute(n, fr);
         printSimplex(1, n, xr, fr);

         frmin = dmin(n, fr);
         replaced = (frmin < fs[0]) ? 1 : 0;
         if(replaced) {
            /* expansion step */
            printf("   Expansion:\n");
            for(i = 1; i <= n; i++) {
               vecAdd(n, xs[0], xs[i], xe[i], ce);
               if(proc[i] == myproc)
                  fe[i] = objFun(n, xe[i]);
            }
            mpi_distribute(n, fe);
            printSimplex(1, n, xe, fe);

            femin = dmin(n, fe);
            if(femin < frmin)
               copySimplex(n, xe, xs, fe, fs); //accept expansion
            else
               copySimplex(n, xr, xs, fr, fs); //accept rotation
         }
         else {
            /* contraction step */
            printf("   Contraction step:\n");
            for(i = 1; i <= n; i++) {
               vecAdd(n, xs[0], xs[i], xc[i], -cc);
               if(proc[i] == myproc)
                  fc[i] = objFun(n, xc[i]);
            }
            mpi_distribute(n, fc);
            printSimplex(1, n, xc, fc);

            fcmin = dmin(n, fc);
            replaced = (fcmin < fs[0]) ? 1 : 0;
            copySimplex(n, xc, xs, fc, fs); //accept contraction
         }

         /* Length of smallest edge in simplex */
         ssize = simplexSize(n, xs);

      }                         /* End of inner repeat loop */

      ++iter;

      /* Find best vertex and put in first position */
      findBest(n, xs, fs, &imin, &fsmin);

      printf("\n");
      printf("Minimum length of simplex = %12.4e\n", ssize);
      printf("Minimum function value    = %12.4e\n", fs[0]);
      printf("-------------------------------------------------\n");
      if(myproc == 0) {
         fprintf(fp, "%5d %20.10e %20.10e %5d\n", iter, fs[0], ssize, imin);
         fflush(fp);
      }
   }                            /* End of main iteration loop */
   if(myproc == 0)
      fclose(fp);

   /* Copy best vertex for output */
   for(i = 0; i < n; i++)
      x[i] = xs[0][i];

   /* Best vertex found */
   printf("Best vertex:\n");
   for(i = 0; i < n; i++)
      printf("%e ", x[i]);
   printf("\n");


   /* Free memory */
   for(i = 0; i < n + 1; i++) {
      free(xs[i]);
      free(xr[i]);
      free(xe[i]);
      free(xc[i]);
   }
   free(xs);
   free(xr);
   free(xe);
   free(xc);
   free(fs);
   free(fr);
   free(fe);
   free(fc);
}