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