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 ML_multi_DownhillSimplex::amoeba(mat_ratep_type& p, v_ratep_type& y, const double ftol, ptr_eval_func funk, int& nfunk ) { const double TINY=1.0e-10; int i, ihi, ilo, inhi, j; double rtol, ysave, ytry; int mpts = p.size(); int ndim = p[0].size(); v_ratep_type psum(ndim); get_psum(p, psum); for (;;) { ilo = 0; ihi = y[0] > y[1] ? (inhi = 1, 0) : (inhi = 0, 1); for (i = 0; i < mpts; ++i) { if (y[i] <= y[ilo]) ilo = i; if (y[i] > y[ihi]) { inhi = ihi; ihi = i; } else if (y[i] > y[inhi] && i != ihi) inhi = i; } rtol = 2.0 * std::abs(y[ihi] - y[ilo]) / (std::abs(y[ihi]) + std::abs(y[ilo]) + TINY); if (rtol < ftol) { SWAP(y[0], y[ilo]); for (i = 0; i < ndim; ++i) SWAP(p[0][i], p[ilo][i]); break; } if (nfunk >= get_NMAX()) { if (CONFIG_DIE_ON_NMAX_EXCEEDED) { std::cerr << "amoeba: NMAX " << get_NMAX() << " exceeded " << nfunk << std::endl; assert(false); } // otherwise, put the lowest at vertex 0 and return to try again SWAP(y[0], y[ilo]); for (i = 0; i < ndim; ++i) SWAP(p[0][i], p[ilo][i]); break; } nfunk += 2; ytry = amotry(p, y, psum, funk, ihi, -1.0); if (ytry <= y[ilo]) ytry = amotry(p, y, psum, funk, ihi, 2.0); else if (ytry >= y[inhi]) { ysave = y[ihi]; ytry = amotry(p, y, psum, funk, ihi, 0.5); if (ytry >= ysave) { for (i = 0; i < mpts; ++i) { if (i != ilo) { for (j = 0; j < ndim; ++j) p[i][j] = psum[j] = 0.5*(p[i][j] + p[ilo][j]); if (DEBUG_BOUNDS_TRACE) bounds_trace(p[i], "amoeba"); y[i] = (this->*funk)(psum); } } nfunk += ndim; get_psum(p, psum); } } else --nfunk; if (DEBUG_AMOEBA) { if (! DEBUG_MONITOR_X10 || (nfunk % 10) == 0) { std::cout << "amoeba(): nfunk=" << nfunk; std::cout << " y[ilo]=" << y[ilo]; std::cout << " y[ihi]=" << y[ihi]; std::cout << std::endl; } } } }