/*-----------------------------------------------------*/ 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; }
/*------------------------------------------------*/ 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(); }
/*---------------------------------------------------------*/ 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; }
//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; }
/*-----------------------------------------------------------------*/ 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::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(); }