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