bool eval_x ( NOMAD::Eval_Point & x , const NOMAD::Double & h_max , bool & count_eval ) const { R_CheckUserInterrupt(); double *x0; int n = x.get_n(); int m = x.get_m(); x0 = (double *)malloc(sizeof(double)*n); for(int i=0;i<n;i++) { x0[i]=x[i].value(); } double *ret_value = eval_f(m, n, x0); for(int i=0;i<m;i++) x.set_bb_output ( i , ret_value[i] ); // objective value count_eval = true; // count a black-box evaluation free(x0); free(ret_value); return true; // the evaluation succeeded }
/*------------------------------------------------------------------*/ void NOMAD::Phase_One_Evaluator::compute_f(NOMAD::Eval_Point &x) const { if (x.get_bb_outputs().size() != _p.get_bb_nb_outputs()) { std::ostringstream err; err << "Phase_One_Evaluator::compute_f(x): " << "x has a wrong number of blackbox outputs (" << x.get_bb_outputs().size() << " != " << _p.get_bb_nb_outputs() << ")"; throw NOMAD::Exception("Phase_One_Evaluator.cpp" , __LINE__ , err.str()); } // objective value for MADS phase 1: the squared sum of all EB constraint violations // (each EB constraint has been previously transformed into OBJ values): const std::list<int> &index_obj = _p.get_index_obj(); const std::list<int>::const_iterator end = index_obj.end(); const NOMAD::Point &bbo = x.get_bb_outputs(); NOMAD::Double h_min = _p.get_h_min(); NOMAD::Double sum = 0.0; NOMAD::Double v; for (std::list<int>::const_iterator it = index_obj.begin() ; it != end ; ++it) { v = bbo[*it]; if (v > h_min) sum += v.pow2(); } x.set_f(sum); }
/*---------------------------------------------------------*/ NOMAD::success_type NOMAD::Barrier::insert_infeasible ( const NOMAD::Eval_Point & x ) { const NOMAD::Eval_Point * old_bi = get_best_infeasible(); // filter insertion: // ----------------- bool insert; filter_insertion ( x , insert ); // filter: // ------- if ( _p.get_barrier_type() == NOMAD::FILTER ) { const NOMAD::Eval_Point * bi = get_best_infeasible(); if ( !bi ) return NOMAD::UNSUCCESSFUL; if ( old_bi ) { if ( bi->get_h().value() < old_bi->get_h().value() ) return NOMAD::FULL_SUCCESS; if ( insert ) return NOMAD::PARTIAL_SUCCESS; return NOMAD::UNSUCCESSFUL; } return NOMAD::FULL_SUCCESS; } // progressive barrier: // -------------------- // with PEB constraints, we remember all points that we tried to insert: if ( _p.get_barrier_type() == NOMAD::PEB_P ) _peb_lop.push_back ( &x ); // first infeasible successes are considered as partial successes // (improving iterations) if ( !_ref ) return NOMAD::PARTIAL_SUCCESS; double hx = x.get_h().value(); double fx = x.get_f().value(); double hr = _ref->get_h().value(); double fr = _ref->get_f().value(); // failure: if ( hx > hr || ( hx == hr && fx >= fr ) ) return NOMAD::UNSUCCESSFUL; // partial success: if ( fx > fr ) return NOMAD::PARTIAL_SUCCESS; // full success: return NOMAD::FULL_SUCCESS; }
/*--------------------------------------------------------*/ void NOMAD::Evaluator::compute_f ( NOMAD::Eval_Point & x ) const { if ( x.get_bb_outputs().size() != _p.get_bb_nb_outputs() ) { std::ostringstream err; err << "Evaluator::compute_f(x): x has a wrong number of blackbox outputs (" << x.get_bb_outputs().size() << " != " << _p.get_bb_nb_outputs() << ")"; throw NOMAD::Exception ( "Evaluator.cpp" , __LINE__ , err.str() ); } x.set_f ( x.get_bb_outputs()[*(_p.get_index_obj().begin())] ); }
/*-----------------------------------------------------*/ bool NOMAD::Cache::erase ( const NOMAD::Eval_Point & x ) { // check the eval types: if ( x.get_eval_type() != _eval_type ) throw NOMAD::Cache::Cache_Error ( "Cache.cpp" , __LINE__ , "NOMAD::Cache:erase(x): x.eval_type != cache.eval_type" ); std::set<NOMAD::Cache_Point>::iterator it; NOMAD::cache_index_type cache_index; // search in cache: const NOMAD::Eval_Point * cache_x = find ( x , it , cache_index ); // the point has been found: if ( cache_x ) { // remove the point from the list of extern points: if ( cache_x->get_current_run() || x.get_current_run() ) { std::list<const NOMAD::Eval_Point*>::const_iterator end2 = _extern_pts.end(); std::list<const NOMAD::Eval_Point*>::iterator it2 = _extern_pts.begin(); while ( it2 != end2 ) { if ( *it2 == cache_x || *it2 == &x ) { _extern_pts.erase ( it2 ); break; } ++it2; } } // erase the point in cache if its address is different from &x: if ( cache_x != &x ) delete cache_x; // remove the point from the cache: _sizeof -= x.size_of(); switch ( cache_index ) { case NOMAD::CACHE_1: _cache1.erase ( it ); break; case NOMAD::CACHE_2: _cache2.erase ( it ); break; case NOMAD::CACHE_3: _cache3.erase ( it ); break; case NOMAD::UNDEFINED_CACHE: break; } return true; } return false; }
//----------------------------------------------------------------------------------------------- // evaluates the model //----------------------------------------------------------------------------------------------- bool LshNomadEvaluator::eval_x(NOMAD::Eval_Point &x, const NOMAD::Double &h_max, bool &count_eval) const { // generating a case from the evaluation point Case *c = generateCase(x); CaseQueue *cq = new CaseQueue(); cq->push_back(c); // sending the case off for evaluation p_optimizer->sendCasesToOptimizer(cq); ///p_optimizer->runCase(c); // extracting the objective x.set_bb_output(0, -c->objectiveValue()); // extracting the constraint values // the constraints in NOMAD must be on the form: c <= 0 for(int i = 0; i < c->numberOfConstraints(); ++i) { double val_input; double val = c->constraintValue(i); double max = p_optimizer->runner()->model()->constraints().at(i)->max(); double min = p_optimizer->runner()->model()->constraints().at(i)->min(); if(val > max) val_input = val - max; else if(val < min) val_input = min - val; else { double u_slack = max - val; double l_slack = val - min; val_input = (u_slack > l_slack) ? -u_slack : -l_slack; } x.set_bb_output(i+1, val_input); } // deleting the case from the heap delete c; delete cq; return true; }
/*---------------------------------------------------------*/ NOMAD::success_type NOMAD::Barrier::insert_feasible ( const NOMAD::Eval_Point & x ) { Double fx; Double fx_bf; if ( _p.get_robust_mads() ) { if ( x.get_smoothing_status() != NOMAD::SMOOTHING_OK ) return NOMAD::UNSUCCESSFUL; if ( _best_feasible ) fx_bf = _best_feasible->get_fsmooth(); else { _best_feasible = &x; return NOMAD::FULL_SUCCESS; } fx = x.get_fsmooth(); } else { if ( _best_feasible ) fx_bf = _best_feasible->get_f(); else { _best_feasible = &x; return NOMAD::FULL_SUCCESS; } fx= x.get_f(); } if ( !fx.is_defined() || ! fx_bf.is_defined() ) throw NOMAD::Exception ( __FILE__ , __LINE__ , "insert_feasible(): one point has no f value" ); if ( fx.value() < fx_bf.value() ) { _best_feasible = &x; return NOMAD::FULL_SUCCESS; } return NOMAD::UNSUCCESSFUL; }
/*------------------------------------------------*/ void NOMAD::Cache::insert ( const NOMAD::Eval_Point & x ) { // check the eval types: if ( x.get_eval_type() != _eval_type ) throw NOMAD::Cache::Cache_Error ( "Cache.cpp" , __LINE__ , "NOMAD::Cache:insert(x): x.eval_type != cache.eval_type" ); // insertion in _extern_pts: insert_extern_point ( x ); // insertion in _cache2: NOMAD::Cache_Point cp ( &x ); _cache2.insert ( cp ); x.set_in_cache ( true ); _sizeof += x.size_of(); }
/*---------------------------------------------------------*/ NOMAD::success_type NOMAD::Barrier::insert_feasible ( const NOMAD::Eval_Point & x ) { if ( !_best_feasible || ( x.get_f().value() < _best_feasible->get_f().value() ) ) { _best_feasible = &x; return NOMAD::FULL_SUCCESS; } return NOMAD::UNSUCCESSFUL; }
/*--------------------------------------------------------*/ void NOMAD::Evaluator::compute_h ( NOMAD::Eval_Point & x ) const { if ( x.get_bb_outputs().size() != _p.get_bb_nb_outputs() ) { std::ostringstream err; err << "Evaluator::compute_h(x): x has a wrong number of blackbox outputs (" << x.get_bb_outputs().size() << " != " << _p.get_bb_nb_outputs() << ")"; throw NOMAD::Exception ( "Evaluator.cpp" , __LINE__ , err.str() ); } int nbo = _p.get_bb_nb_outputs(); const std::vector<NOMAD::bb_output_type> & bbot = _p.get_bb_output_type(); const NOMAD::Point & bbo = x.get_bb_outputs(); NOMAD::Double h = 0.0 , bboi; x.set_EB_ok ( true ); for ( int i = 0 ; i < nbo ; ++i ) { bboi = bbo[i]; if ( bboi.is_defined() && (bbot[i] == NOMAD::EB || bbot[i] == NOMAD::PEB_E ) && bboi > _p.get_h_min() ) { h.clear(); x.set_h ( h ); x.set_EB_ok ( false ); return; } if ( bboi.is_defined() && ( bbot[i] == NOMAD::FILTER || bbot[i] == NOMAD::PB || bbot[i] == NOMAD::PEB_P ) ) { if ( bboi > _p.get_h_min() ) { switch ( _p.get_h_norm() ) { case NOMAD::L1: h += bboi; break; case NOMAD::L2: h += bboi * bboi; break; case NOMAD::LINF: if ( bboi > h ) h = bboi; break; } } } } if ( _p.get_h_norm() == NOMAD::L2 ) h = h.sqrt(); x.set_h ( h ); }
/*-----------------------------------------------------------------------*/ bool NOMAD::Evaluator::interrupt_evaluations ( const NOMAD::Eval_Point & x , const NOMAD::Double & h_max ) const { int nbo = _p.get_bb_nb_outputs(); const NOMAD::Point & bbo = x.get_bb_outputs(); const std::vector<NOMAD::bb_output_type> & bbot = _p.get_bb_output_type(); NOMAD::Double h = 0.0; bool check_h = h_max.is_defined(); for ( int i = 0 ; i < nbo ; ++i ) { if ( bbo[i].is_defined() && ( bbot[i] == NOMAD::EB || bbot[i] == NOMAD::PEB_E ) && bbo[i] > _p.get_h_min() ) return true; if ( check_h && bbo[i].is_defined() && (bbot[i] == NOMAD::FILTER || bbot[i] == NOMAD::PB || bbot[i] == NOMAD::PEB_P ) ) { if ( bbo[i] > _p.get_h_min() ) { switch ( _p.get_h_norm() ) { case NOMAD::L1: h += bbo[i]; break; case NOMAD::L2: h += bbo[i].pow2(); break; case NOMAD::LINF: if ( bbo[i] > h ) h = bbo[i]; break; } if ( _p.get_h_norm() == NOMAD::L2 ) { if ( h > h_max.pow2() ) return true; } else if ( h > h_max ) return true; } } } return false; }
/*---------------------------------------------------------*/ void NOMAD::Barrier::insert ( const NOMAD::Eval_Point & x ) { // we compare the eval types (_SGTE_ or _TRUTH_) of x and *this: if ( x.get_eval_type() != _eval_type ) throw Barrier::Insert_Error ( "Barrier.cpp" , __LINE__ , "insertion of an Eval_Point into the bad Barrier object" ); // basic check: if ( !x.is_eval_ok() ) { _one_eval_succ = NOMAD::UNSUCCESSFUL; return; } // pre-filter: if tag(x) is already in the pre-filter, // then return _UNSUCCESSFUL_: size_t size_before = _prefilter.size(); _prefilter.insert ( x.get_tag() ); if ( _prefilter.size() == size_before ) { _one_eval_succ = NOMAD::UNSUCCESSFUL; return; } // insertion in _all_inserted: _all_inserted.push_back ( &x ); // other checks: const NOMAD::Double & h = x.get_h(); if ( !x.is_EB_ok () || !x.get_f().is_defined () || !h.is_defined () || h.value() > _h_max.value() ) { _one_eval_succ = NOMAD::UNSUCCESSFUL; return; } // insert_feasible or insert_infeasible: _one_eval_succ = ( x.is_feasible ( _p.get_h_min() ) ) ? insert_feasible ( x ) : insert_infeasible(x); if ( _one_eval_succ > _success ) _success = _one_eval_succ; }
bool CMADSEvaluator::eval_x(NOMAD::Eval_Point &_x, const NOMAD::Double &_h_max, bool &_count_eval) const { int i,M=pOP->constraintsSize(); NOMAD::Point y(M+2); ArrayXd op,ep; op=CMADS::NOMADPoint2ArrayXd(_x); y[1]=(pOP->evaluate(op,ep))?0.:1.; y[0]=(pOP->isMinimization())?ep(0):-ep(0); for ( i=2; i<M+2; i++ ) { y[i]=1.-ep(i-1); } _x.set_bb_output(y); bool tohist=true; for ( i=1; tohist && i<M+2; i++ ) { if ( y[i]>0. ) tohist=false; } if ( tohist ) { pOP->writeHistory(op,ep(0)); } _count_eval=true; return true; }
/*---------------------------------------------------------------------*/ void NOMAD::Cache::insert_extern_point ( const NOMAD::Eval_Point & x ) const { if ( !x.get_current_run() ) _extern_pts.push_front ( &x ); }
/*-----------------------------------------------------------------*/ void NOMAD::Cache::update ( NOMAD::Eval_Point & cache_x , const NOMAD::Eval_Point & x ) const { const NOMAD::Point & bbo_x = x.get_bb_outputs(); if ( &cache_x == &x || !x.is_eval_ok() || !cache_x.is_in_cache() || bbo_x.empty() || cache_x != x ) return; // check the eval types: if ( x.get_eval_type () != _eval_type || cache_x.get_eval_type() != _eval_type ) throw NOMAD::Cache::Cache_Error ( "Cache.cpp" , __LINE__ , "NOMAD::Cache:update(): problem with the eval. types" ); const NOMAD::Point & bbo_cache_x = cache_x.get_bb_outputs(); int m = bbo_cache_x.size(); _sizeof -= cache_x.size_of(); // if the current point could not evaluate and x did, // or if the number of bb outputs is different, we set cache_x = x: if ( !cache_x.is_eval_ok() || m != bbo_x.size() ) { cache_x.set_eval_status ( NOMAD::EVAL_OK ); cache_x.set_bb_output ( bbo_x ); cache_x.set_signature ( x.get_signature () ); cache_x.set_direction ( x.get_direction () ); _sizeof += cache_x.size_of(); return; } // we complete _bb_outputs: int c1 = 0; int c2 = 0; for ( int i = 0 ; i < m ; ++i ) { if ( bbo_cache_x[i].is_defined() ) ++c1; if ( bbo_x[i].is_defined() ) ++c2; if ( !bbo_cache_x[i].is_defined() && bbo_x[i].is_defined() ) cache_x.set_bb_output ( i , bbo_x[i] ); } // the two points are 'eval_ok' and have comparable outputs: // we select the best as the one with the more defined bb_outputs: if ( c2 > c1 ) { cache_x.set_signature ( x.get_signature () ); cache_x.set_direction ( x.get_direction () ); } _sizeof += cache_x.size_of(); }
/*----------------------------------------------------*/ bool NOMAD::Cache::read_points_from_cache_file ( std::ifstream & fin , const int * p_nb_bb_outputs , bool display ) { try { NOMAD::Clock c; // the stream is placed at the first point (after the CACHE_FILE_ID tag): fin.seekg ( sizeof ( NOMAD::CACHE_FILE_ID ) , std::ios::beg ); NOMAD::Cache_File_Point cfp; NOMAD::Eval_Point * cur; const NOMAD::Eval_Point * cache_x; // main loop: while ( !fin.eof() ) { // reading of the Cache_File_Point: if ( !cfp.read ( fin ) ) { if ( fin.eof() ) break; return false; } // we ignore this cache file point if it has a different // number of blackbox outputs than *p_nb_bb_outputs: if ( p_nb_bb_outputs && cfp.get_m() != *p_nb_bb_outputs ) continue; // creation of the Eval_Point: cur = new NOMAD::Eval_Point ( cfp , _eval_type ); // we look if the current point is already in cache: cache_x = find ( *cur ); // the current point is already in cache: if ( cache_x ) { update ( get_modifiable_point ( *cache_x ) , *cur ); delete cur; } // point not in cache: insertion: else { // insertion in _extern_pts: insert_extern_point ( *cur ); // insertion in _cache1: NOMAD::Cache_Point cp ( cur ); _cache1.insert ( cp ); cur->set_in_cache ( true ); _sizeof += cur->size_of(); } } // end of main loop // display stats on the cache load: if ( display ) { _out << "number of points: " << static_cast<int>(_cache1.size()) << std::endl << "size : "; _out.display_size_of ( _sizeof ); _out << std::endl << "load time : " << c.get_real_time() << 's' << std::endl; } } catch ( ... ) { return false; } return true; }
/*---------------------------------------------------------------------*/ NOMAD::Cache_File_Point::Cache_File_Point(const NOMAD::Eval_Point &x) : _n(x.size()) , _m(0) , _m_def(0) , _coords(NULL) , _bbo_def(NULL) , _bbo_index(NULL) { int i; // eval_status: switch (x.get_eval_status()) { case NOMAD::EVAL_FAIL: _eval_status = 0; break; case NOMAD::EVAL_OK: _eval_status = 1; break; case NOMAD::EVAL_IN_PROGRESS: _eval_status = 2; break; case NOMAD::UNDEFINED_STATUS: _eval_status = 3; break; case NOMAD::EVAL_USER_REJECT: _eval_status = 3; break; } // inputs: if (_n > 0) { _coords = new double [_n]; for (i = 0 ; i < _n ; ++i) _coords[i] = x[i].value(); } else _n = 0; // outputs: const NOMAD::Point &bbo = x.get_bb_outputs(); _m = bbo.size(); if (_m > 0) { std::vector<double> vd; std::vector<int> vi; for (i = 0 ; i < _m ; ++i) if (bbo[i].is_defined()) { vd.push_back(bbo[i].value()); vi.push_back(i); } _m_def = static_cast<int>(vd.size()); if (_m_def > 0) { _bbo_def = new double [_m_def]; _bbo_index = new int [_m_def]; for (i = 0 ; i < _m_def ; ++i) { _bbo_def [i] = vd[i]; _bbo_index[i] = vi[i]; } } } else _m = 0; #ifdef MEMORY_DEBUG ++NOMAD::Cache_File_Point::_cardinality; if (NOMAD::Cache_File_Point::_cardinality > NOMAD::Cache_File_Point::_max_cardinality) ++NOMAD::Cache_File_Point::_max_cardinality; #endif }
//Function + Constraint Evaluation bool eval_x(NOMAD::Eval_Point &x, const NOMAD::Double &h_max, bool &count_eval) { char errstr[1024]; bool stop = false; int i, j, n = x.size(), status; double *xm, *fvals; mxLogical *sur; count_eval = true; //mexErrMsgTxt will kill MEX //Check for Ctrl-C if (utIsInterruptPending()) { utSetInterruptPending(false); /* clear Ctrl-C status */ mexPrintf("\nCtrl-C Detected. Exiting NOMAD...\n\n"); count_eval = false; raise(SIGINT); return false; } //Blackbox / Objective Evaluation fun->plhs[0] = NULL; xm = mxGetPr(fun->prhs[fun->xrhs]); for(i=0;i<n;i++) xm[i] = x[i].value(); //Add Surrogate if present and requested if(hasSur) { sur=mxGetLogicals(fun->prhs[fun->xrhs+1]); (x.get_eval_type()==NOMAD::SGTE)? *sur=true:*sur=false; } //Call MATLAB Objective try { status = mexCallMATLAB(1, fun->plhs, fun->nrhs, fun->prhs, fun->f); } //Note if these errors occur it is due to errors in MATLAB code, no way to recover? catch(exception &e) { sprintf(errstr,"Unrecoverable Error from Objective / Blackbox Callback:\n%sExiting NOMAD...\n\n",e.what()); mexWarnMsgTxt(errstr); //Force exit raise(SIGINT); return false; } catch(...) { mexWarnMsgTxt("Unrecoverable Error from Objective / Blackbox Callback, Exiting NOMAD...\n\n"); //Force exit raise(SIGINT); return false; } if(status) { mexWarnMsgTxt("Unrecoverable Error from Objective / Blackbox Callback, Exiting NOMAD...\n\n"); raise(SIGINT); return false; } #ifdef OPTI_VERSION //Check we got the correct number back if(mxGetM(fun->plhs[0]) != nobj) mexErrMsgTxt("Incorrect number of elements returned from the objective function"); //Set Objective (Or multi-objective) fvals = mxGetPr(fun->plhs[0]); for(i=0;i<nobj;i++) x.set_bb_output(i,fvals[i]); //Constraint Evaluation if(ncon) { //Add Surrogate if present and requested if(hasSur) { sur=mxGetLogicals(con->prhs[con->xrhs+1]); (x.get_eval_type()==NOMAD::SGTE)? *sur=true:*sur=false; } con->plhs[0] = NULL; xm = mxGetPr(con->prhs[con->xrhs]); for(i=0;i<n;i++) xm[i] = x[i].value(); //Call MATLAB Constraint try { status = mexCallMATLAB(1, con->plhs, con->nrhs, con->prhs, con->f); } catch(...) { mexWarnMsgTxt("Unrecoverable Error from Constraint Callback, Exiting NOMAD...\n\n"); //Force exit raise(SIGINT); return false; } if(status) { mexWarnMsgTxt("Unrecoverable Error from Constraint Callback, Exiting NOMAD...\n\n"); raise(SIGINT); return false; } //Check we got the correct number back if(mxGetM(con->plhs[0]) != ncon) mexErrMsgTxt("Incorrect number of elements returned from nonlinear constraint function"); //Set Constraints double *cons = mxGetPr(con->plhs[0]); for(i=0,j=nobj;i<ncon;i++,j++) x.set_bb_output(j,cons[i] - con->nlrhs[i]); //subtract nlrhs // Clean up LHS Ptr mxDestroyArray(con->plhs[0]); } #else //GERAD VERSION //Check we got the correct number of elements back if(mxGetNumberOfElements(fun->plhs[0]) > nobj+ncon) mexWarnMsgTxt("Black box returns more elements than required. Please provide a BB_OUTPUT_TYPE consistent with your black box function"); else if(mxGetNumberOfElements(fun->plhs[0]) < nobj+ncon) { mexErrMsgTxt("Insufficient outputs provided by the black box function. Exiting NOMAD...\n\n"); raise(SIGINT); return false; } //Assign bb output fvals = mxGetPr(fun->plhs[0]); for(i=0;i<(nobj+ncon);i++) x.set_bb_output(i,fvals[i]); #endif //Iteration Callback if(iterF->enabled) { iterF->plhs[0] = NULL; memcpy(mxGetData(iterF->prhs[1]), &citer, sizeof(int)); memcpy(mxGetPr(iterF->prhs[2]), fvals, sizeof(double)); memcpy(mxGetPr(iterF->prhs[3]), xm, n * sizeof(double)); try { status = mexCallMATLAB(1, iterF->plhs, 4, iterF->prhs, iterF->f); } catch (...) { mexWarnMsgTxt("Unrecoverable Error from Iteration Callback, Exiting NOMAD...\n\n"); //Force exit raise(SIGINT); return false; } if(status) { mexWarnMsgTxt("Unrecoverable Error from Iteration Callback, Exiting NOMAD...\n\n"); raise(SIGINT); return false; } //Collect return argument stop = *(bool*)mxGetData(iterF->plhs[0]); //Clean up Ptr mxDestroyArray(iterF->plhs[0]); } //Add Function Eval Counter citer++; // Clean up LHS Fun Ptr mxDestroyArray(fun->plhs[0]); //Check for iterfun stop if(stop) { mexPrintf("\nIterFun Called Stop. Exiting NOMAD...\n\n"); count_eval = false; raise(SIGINT); return false; } else return true; }
/*-------------------------------------------------------------------*/ bool NOMAD::Evaluator::eval_x ( NOMAD::Eval_Point & x , const NOMAD::Double & h_max , bool & count_eval ) const { count_eval = false; if ( _bb_exe.empty() || !x.is_complete() ) throw NOMAD::Exception ( "Evaluator.cpp" , __LINE__ , "Evaluator: no BB_EXE is defined (blackbox executable names)" ); bool sgte = x.get_eval_type() == NOMAD::SGTE; if ( sgte && _sgte_exe.empty() ) throw NOMAD::Exception ( "Evaluator.cpp" , __LINE__ , "Evaluator: no SGTE_EXE is defined (surrogate executable names)" ); int pid = NOMAD::get_pid(); int seed = _p.get_seed(); std::string tmp_dir = _p.get_tmp_dir(); std::ostringstream oss; oss << "." << seed; if ( pid != seed ) oss << "." << pid; oss << "." << x.get_tag() << "."; const std::string & sint = oss.str(); // for the parallel version: no need to include the process rank in the names // as the point tags are unique for all the processes: each process creates // its own points and uses Eval_Point::set_tag() // blackbox input file writing: // ---------------------------- std::string bb_input_file_name = tmp_dir + NOMAD::BLACKBOX_INPUT_FILE_PREFIX + sint + NOMAD::BLACKBOX_INPUT_FILE_EXT; std::string bb_output_file_name = tmp_dir + NOMAD::BLACKBOX_OUTPUT_FILE_PREFIX + sint + NOMAD::BLACKBOX_OUTPUT_FILE_EXT; std::ofstream fout ( bb_input_file_name.c_str() ); if ( fout.fail() ) { std::string err = "could not create file blackbox input file " + bb_input_file_name + ". \n \n #### Please check that write permission are granted for the working directory. #### "; throw NOMAD::Exception ( "Evaluator.cpp" , __LINE__ , err ); } // include seed: if ( _p.get_bb_input_include_seed() ) fout << seed << " "; // include tag: if ( _p.get_bb_input_include_tag() ) fout << x.get_tag() << " "; fout.setf ( std::ios::fixed ); fout.precision ( NOMAD::DISPLAY_PRECISION_BB ); x.Point::display ( fout , " " , -1 , -1 ); fout << std::endl; fout.close(); if ( fout.fail() ) return false; x.set_eval_status ( NOMAD::EVAL_IN_PROGRESS ); std::string cmd , bb_exe; std::ifstream fin; bool failed; NOMAD::Double d; int j , nbbok; int ibbo = 0; // system call to evaluate the blackbox: // ------------------------------------- size_t bn = _bb_exe.size(); for ( size_t k = 0 ; k < bn ; ++k ) { // executable name: bb_exe = ( sgte ) ? _sgte_exe[k] : _bb_exe[k]; // system command: cmd = bb_exe + " " + bb_input_file_name; // redirection ? if no, the blackbox has to create // the output file 'bb_output_file_name': if ( _p.get_bb_redirection() ) cmd += " > " + bb_output_file_name; #ifdef DEBUG #ifdef USE_MPI int rank; MPI_Comm_rank ( MPI_COMM_WORLD, &rank); _p.out() << "command(rank=" << rank << ") = \'" << cmd << "\'" << std::endl; #else _p.out() << "command=\'" << cmd << "\'" << std::endl; #endif #endif // the evaluation: { int signal = system ( cmd.c_str() ); // catch the ctrl-c signal: if ( signal == SIGINT ) raise ( SIGINT ); // other evaluation error: failed = ( signal != 0 ); count_eval = true; } // the evaluation failed (we stop the evaluations): if ( failed ) { x.set_eval_status ( NOMAD::EVAL_FAIL ); break; } // reading of the blackbox output file: // ------------------------------------ else { // bb-output file reading: fin.open ( bb_output_file_name.c_str() ); failed = false; bool is_defined = true; bool is_inf = false; // loop on the number of outputs for this blackbox: nbbok = _bb_nbo[k]; for ( j = 0 ; j < nbbok ; ++j ) { fin >> d; if ( !d.is_defined() ) { is_defined = false; break; } if ( fin.fail() ) { failed = true; break; } if ( d.value() >= NOMAD::INF ) { is_inf = true; break; } x.set_bb_output ( ibbo++ , d ); } fin.close(); // the evaluation failed: if ( failed || !is_defined || is_inf ) { x.set_eval_status ( NOMAD::EVAL_FAIL ); break; } // stop the evaluations if h > h_max or if a 'EB' constraint is violated: if ( k < _bb_exe.size() - 1 && interrupt_evaluations ( x , h_max ) ) break; } } if ( x.get_eval_status() == NOMAD::EVAL_IN_PROGRESS ) x.set_eval_status ( NOMAD::EVAL_OK ); // delete the blackbox input and output files: // ------------------------------------------- remove ( bb_input_file_name.c_str () ); remove ( bb_output_file_name.c_str() ); // check the CNT_EVAL output: // -------------------------- int index_cnt_eval = _p.get_index_cnt_eval(); if ( index_cnt_eval >= 0 && x.get_bb_outputs()[index_cnt_eval] == 0.0 ) count_eval = false; return x.is_eval_ok(); }
/*--------------------------------------------*/ bool NOMAD::TGP_Model::predict(NOMAD::Eval_Point &x , bool pred_outside_bnds) { if (!_error_str.empty()) return false; if (!_model_computed) { _error_str = "NOMAD::TGP_Model::compute() has not been called"; return false; } int i , i0 , ix , m = x.get_m() , nx = x.size(); // reset point outputs: x.set_eval_status(NOMAD::EVAL_FAIL); for (i = 0 ; i < m ; ++i) x.set_bb_output(i , NOMAD::Double()); // check dimensions: if (m != static_cast<int>(_bbot.size()) || (nx != _n0 && nx != _n)) { _error_str = "predict error: bad x dimensions"; return false; } double ZZ , * XX = new double[_n]; // set the coordinates and check the bounds: for (i = 0 ; i < _n ; ++i) { ix = (nx == _n0) ? _fv_index[i] : i; if (!pred_outside_bnds) { i0 = _fv_index[i]; if (x[ix] < _lb[i0] || x[ix] > _ub[i0]) { delete [] XX; return false; // this is not an error } } XX[i] = x[ix].value(); } // predictions (one for each output): for (i = 0 ; i < m ; ++i) if (_tgp_models[i]) { if (!_tgp_models[i]->predict(XX , _n , ZZ , _tgp_rect)) { std::ostringstream oss; oss << "predict error: problem with model #" << i; _error_str = oss.str(); break; } x.set_bb_output(i , ZZ); } delete [] XX; if (!_error_str.empty()) { x.set_eval_status(NOMAD::EVAL_FAIL); return false; } x.set_eval_status(NOMAD::EVAL_OK); return true; }
/*-------------------------------------------------------------*/ void NOMAD::Speculative_Search::search ( NOMAD::Mads & mads , int & nb_search_pts , bool & stop , NOMAD::stop_type & stop_reason , NOMAD::success_type & success , bool & count_search , const NOMAD::Eval_Point *& new_feas_inc , const NOMAD::Eval_Point *& new_infeas_inc ) { // new_feas_inc and new_infeas_inc are used as inputs, // so do not initialize them to NULL here nb_search_pts = 0; success = NOMAD::UNSUCCESSFUL; count_search = !stop; if ( stop ) return; const NOMAD::Display & out = _p.out(); NOMAD::dd_type display_degree = out.get_search_dd(); if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << NOMAD::SPEC_SEARCH; out << std::endl << NOMAD::open_block ( oss.str() ) << std::endl; } int lkm1; // l_{k-1} int lk; // l_k int n; NOMAD::Signature * signature; NOMAD::Point delta_m_k; NOMAD::Point delta_m_km1; NOMAD::Point factor; NOMAD::Point xkm1; NOMAD::Eval_Point * sk; const NOMAD::Eval_Point * x[2]; x[0] = new_feas_inc; x[1] = new_infeas_inc; // Evaluator_Control: NOMAD::Evaluator_Control & ev_control = mads.get_evaluator_control(); for ( int i = 0 ; i < 2 ; ++i ) { if ( x[i] && x[i]->get_mesh_index() ) { const NOMAD::Direction * dir = x[i]->get_direction(); if ( dir && ( dir->is_mads() || dir->get_type()==NOMAD::MODEL_SEARCH_DIR ) ) { // get the x_k's signature: signature = x[i]->get_signature(); if ( !signature ) throw NOMAD::Exception ( "Speculative_Search.cpp" , __LINE__ , "Speculative_Search::search(): could not get the signature" ); xkm1 = *x[i] - *dir; lk = lkm1 = *x[i]->get_mesh_index(); NOMAD::Mesh::update ( NOMAD::FULL_SUCCESS , lk ); n = signature->get_n(); delta_m_k = NOMAD::Point ( n ); delta_m_km1 = NOMAD::Point ( n ); factor = NOMAD::Point ( n ); signature->get_mesh().get_delta_m ( delta_m_k , lk ); signature->get_mesh().get_delta_m ( delta_m_km1 , lkm1 ); // multiplicative factor: takes into account the fact that // the direction contains \Delta^m_k: try { // factor = delta_m_k / delta_m_km1 : for ( int k = 0 ; k < n ; ++k ) { if ( delta_m_k[k].is_defined() && delta_m_km1[k].is_defined() && delta_m_k[k].value() != 0.0 && delta_m_km1[k].value() != 0.0 ) factor[k] = delta_m_k[k] / delta_m_km1[k]; else factor[k] = 0.0; } } catch ( NOMAD::Double::Invalid_Value & ) { if ( display_degree == NOMAD::FULL_DISPLAY ) out << "could not compute " << _type << " point: stop" << std::endl << NOMAD::close_block ( "end of speculative search" ); stop = true; stop_reason = NOMAD::MESH_PREC_REACHED; return; } if ( lkm1 <= 0 ) factor *= NOMAD::Mesh::get_mesh_update_basis(); // speculative search point: NOMAD::Direction new_dir ( n , 0.0 , dir->get_type() ); new_dir.Point::operator = ( factor * *dir ); sk = new NOMAD::Eval_Point; sk->set ( n , _p.get_bb_nb_outputs() ); sk->set_signature ( signature ); sk->set_direction ( &new_dir ); sk->set_mesh_index ( &lk ); sk->Point::operator = ( xkm1 + new_dir ); if ( display_degree == NOMAD::FULL_DISPLAY ) { out << "trial point #" << sk->get_tag() << ": ( "; sk->Point::display ( out ," " , 2 , NOMAD::Point::get_display_limit() ); out << " )" << std::endl; } // add the new point to the list of search trial points: ev_control.add_eval_point ( sk , display_degree , _p.get_snap_to_bounds() , NOMAD::Double() , NOMAD::Double() , NOMAD::Double() , NOMAD::Double() ); } } } nb_search_pts = ev_control.get_nb_eval_points(); // eval_list_of_points: // -------------------- new_feas_inc = new_infeas_inc = NULL; ev_control.eval_list_of_points ( _type , mads.get_true_barrier() , mads.get_sgte_barrier() , mads.get_pareto_front() , stop , stop_reason , new_feas_inc , new_infeas_inc , success ); if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << "end of speculative search (" << success << ")"; out << NOMAD::close_block ( oss.str() ) << std::endl; } }
/*--------------------------------------------------------*/ void NOMAD::Barrier::check_PEB_constraints ( const NOMAD::Eval_Point & x , bool display ) { const NOMAD::Double & h_min = _p.get_h_min(); const std::vector<NOMAD::bb_output_type> & bbot = _p.get_bb_output_type(); const NOMAD::Point & bbo = x.get_bb_outputs(); int nb = static_cast<int>(bbot.size()); std::list<int> ks; for ( int k = 0 ; k < nb ; ++k ) { if ( bbot[k] == NOMAD::PEB_P && bbo[k] <= h_min ) { if ( display ) _p.out() << std::endl << "change status of blackbox output " << k << " from progressive barrier constraint to extreme barrier constraint" << std::endl; ++_peb_changes; _p.change_PEB_constraint_status (k); ks.push_back(k); } } // at least one constraint changed status, so we have to update the filter // and remove all points that have their h value changed to infinity // (it can add new dominant points from the list _peb_lop): if ( !ks.empty() ) { std::list<int>::const_iterator it_k , end_k = ks.end() , begin_k = ks.begin(); // we inspect the filter points if some have to be removed; if so, // all filter candidates (stored in _peb_lop) will be re-inserted // into the filter: bool reset_filter = false; std::set<NOMAD::Filter_Point>::const_iterator end = _filter.end() , it; for ( it = _filter.begin() ; it != end ; ++it ) { const NOMAD::Point & bbo_cur = it->get_point()->get_bb_outputs(); for ( it_k = begin_k ; it_k != end_k ; ++it_k ) if ( bbo_cur[*it_k] > h_min ) { reset_filter = true; break; } if ( reset_filter ) break; } if ( reset_filter ) { if ( display ) _p.out() << std::endl << "PEB change of status: filter reset" << std::endl; ++_peb_filter_reset; _filter.clear(); bool insert; std::list<const NOMAD::Eval_Point *>::const_iterator end2 = _peb_lop.end (); std::list<const NOMAD::Eval_Point *>::iterator it2 = _peb_lop.begin(); while ( it2 != end2 ) { insert = true; const NOMAD::Point & bbo_cur = (*it2)->get_bb_outputs(); for ( it_k = begin_k ; it_k != end_k ; ++it_k ) if ( bbo_cur[*it_k] > h_min ) { insert = false; break; } // if insert==true: this point is potentially a new filter point: if ( insert ) { filter_insertion ( **it2 , insert ); ++it2; } // if insert==false: it means that the current filter point // has to be removed from filter and from _peb_lop, and // in addition, its h is put to INF: else { NOMAD::Cache::get_modifiable_point ( **it2 ).set_h ( NOMAD::Double() ); _peb_lop.erase(it2++); } } } } }
/*-----------------------------------------------------------*/ void NOMAD::LH_Search::search ( NOMAD::Mads & mads , int & nb_search_pts , bool & stop , NOMAD::stop_type & stop_reason , NOMAD::success_type & success , bool & count_search , const NOMAD::Eval_Point *& new_feas_inc , const NOMAD::Eval_Point *& new_infeas_inc ) { new_feas_inc = new_infeas_inc = NULL; nb_search_pts = 0; success = NOMAD::UNSUCCESSFUL; count_search = !stop; if ( stop ) return; // initial display: const NOMAD::Display & out = _p.out(); NOMAD::dd_type display_degree = out.get_search_dd(); if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << NOMAD::LH_SEARCH; out << std::endl << NOMAD::open_block ( oss.str() ) << std::endl; } // active barrier: const NOMAD::Barrier & barrier = mads.get_active_barrier(); // Evaluator_Control: NOMAD::Evaluator_Control & ev_control = mads.get_evaluator_control(); // current incumbents: const NOMAD::Eval_Point * feas_inc = barrier.get_best_feasible (); const NOMAD::Eval_Point * infeas_inc = barrier.get_best_infeasible(); // get a reference point and a signature: const NOMAD::Eval_Point * ref = (feas_inc) ? feas_inc : infeas_inc; NOMAD::Signature * signature = _p.get_signature(); // check the number of points: int p = _initial_search ? _p.get_LH_search_p0() : _p.get_LH_search_pi(); if ( p <= 0 ) { if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << "end of LH " << ( _initial_search ? "initial " : "") << "search (number of points <= 0)"; out << std::endl << NOMAD::close_block ( oss.str() ) << std::endl; } return; } // no reference point is available (we consider the standard signature): if ( !ref ) { // it is not sufficient with categorical variables: if ( signature->has_categorical() ) { if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << "end of LH " << ( _initial_search ? "initial " : "") << "search (no available reference point)"; out << std::endl << NOMAD::close_block ( oss.str() ) << std::endl; } return; } } else signature = ref->get_signature(); // Change Display stats style const std::list<std::string> old_ds = _p.get_display_stats(); std::list<std::string> ds = old_ds; ds.push_back ( " (LH)" ); _p.set_DISPLAY_STATS ( ds ); // check the parameters: _p.check ( false , // remove_history_file = false false , // remove_solution_file = false false ); // remove_stats_file = false int i; NOMAD::Eval_Point * x; int n = signature->get_n(); int m = _p.get_bb_nb_outputs(); int pm1 = p-1; // mesh size: NOMAD::Point delta_max = signature->get_mesh()->get_delta_max (); NOMAD::Double delta_i; NOMAD::Point delta; if ( !_initial_search ) signature->get_mesh()->get_delta ( delta ); // fixed variables: const NOMAD::Point & fixed_variables = signature->get_fixed_variables(); // bb input types: const std::vector<NOMAD::bb_input_type> & bbit = signature->get_input_types(); // bounds: const NOMAD::Point & lb = signature->get_lb(); const NOMAD::Point & ub = signature->get_ub(); // pts contains n points of dimension p: each of these points contains // p different values for each variable: NOMAD::Point ** pts = new NOMAD::Point * [n]; // creation of p search points: for ( int k = 0 ; k < p ; ++k ) { x = new NOMAD::Eval_Point ( n , m ); x->set_signature ( signature ); for ( i = 0 ; i < n ; ++i ) { if ( k==0 ) { if ( fixed_variables[i].is_defined() ) pts[i] = new NOMAD::Point ( p , fixed_variables[i] ); else if ( bbit[i] == NOMAD::CATEGORICAL ) { pts[i] = new NOMAD::Point ( p , (*ref)[i] ); } else { pts[i] = new NOMAD::Point ( p ); if ( !_initial_search ) delta_i = delta[i]; values_for_var_i ( p , delta_i , delta_max[i] , bbit [i] , lb [i] , ub [i] , *pts [i] ); } } (*x)[i] = (*pts[i])[k]; if ( k == pm1 ) delete pts[i]; } if ( display_degree == NOMAD::FULL_DISPLAY ) { out << "LH point #" << x->get_tag() << ": ( "; x->Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() ); out << " )" << std::endl; } // add the new point to the ordered list of search trial points: ev_control.add_eval_point ( x , display_degree , false , // snap_to_bounds = false NOMAD::Double() , NOMAD::Double() , NOMAD::Double() , NOMAD::Double() ); } delete [] pts; nb_search_pts = ev_control.get_nb_eval_points(); // eval_list_of_points: // -------------------- new_feas_inc = new_infeas_inc = NULL; ev_control.eval_list_of_points ( _type , mads.get_true_barrier() , mads.get_sgte_barrier() , mads.get_pareto_front() , stop , stop_reason , new_feas_inc , new_infeas_inc , success ); _p.get_display_stats(); // restore stats style _p.set_DISPLAY_STATS ( old_ds ); _p.check ( false , // remove_history_file = false false , // remove_solution_file = false false ); // remove_stats_file = false // final displays: if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << "end of LH search (" << success << ")"; out << std::endl << NOMAD::close_block ( oss.str() ) << std::endl; } }
/*-------------------------------------------------------------*/ void NOMAD::Multi_Obj_Evaluator::compute_f ( NOMAD::Eval_Point & x ) const { if ( _i1 < 0 || _i2 < 0 ) throw NOMAD::Exception ( "Multi_Obj_Evaluator.cpp" , __LINE__ , "Multi_Obj_Evaluator::compute_f(): no objective indexes defined" ); int obj_index [2]; obj_index[0] = _i1; obj_index[1] = _i2; const NOMAD::Point & bbo = x.get_bb_outputs(); // a reference is available: if ( _ref ) { NOMAD::multi_formulation_type mft = _p.get_multi_formulation(); if ( mft == NOMAD::UNDEFINED_FORMULATION ) throw NOMAD::Exception ( "Multi_Obj_Evaluator.cpp" , __LINE__ , "Multi_Obj_Evaluator::compute_f(): no formulation type is defined" ); // normalized formulation: if ( mft == NOMAD::NORMALIZED || mft == NOMAD::DIST_LINF ) { // f1 - r1: NOMAD::Double d = bbo[obj_index[0]] - (*_ref)[0]; // f2 - r2: NOMAD::Double f2mr2 = bbo[obj_index[1]] - (*_ref)[1]; // we take the max: if ( f2mr2 > d ) d = f2mr2; x.set_f ( d ); } // product formulation: else if ( mft == NOMAD::PRODUCT ) { NOMAD::Double prod = 1.0 , ri , fi; for ( int i = 0 ; i < 2 ; ++i ) { ri = (*_ref)[i]; fi = bbo[obj_index[i]]; if ( fi > ri ) { prod = 0.0; break; } prod = prod * (ri-fi).pow2(); } x.set_f ( -prod ); } // distance formulation: else { NOMAD::Double d; NOMAD::Double r1mf1 = (*_ref)[0] - bbo[obj_index[0]]; NOMAD::Double r2mf2 = (*_ref)[1] - bbo[obj_index[1]]; if ( r1mf1 >= 0.0 && r2mf2 >= 0.0 ) { d = r1mf1.pow2(); NOMAD::Double tmp = r2mf2.pow2(); if ( tmp < d ) d = tmp; d = -d; } else if ( r1mf1 <= 0.0 && r2mf2 <= 0.0 ) { // with L2 norm: if ( mft == NOMAD::DIST_L2 ) d = r1mf1.pow2() + r2mf2.pow2(); // with L1 norm: else d = (r1mf1.abs() + r2mf2.abs()).pow2(); // Linf norm: treated as NORMALIZED } else if ( r1mf1 > 0.0 ) d = r2mf2.pow2(); else d = r1mf1.pow2(); x.set_f ( d ); } } // no reference is available (use weights): else x.set_f ( _w1 * bbo[obj_index[0]] + _w2 * bbo[obj_index[1]] ); }