/*-------------------------------------------------------------------------------------*/ /* NOMAD - Nonlinear Optimization by Mesh Adaptive Direct search - version 3.6.1 */ /* */ /* Copyright (C) 2001-2012 Mark Abramson - the Boeing Company, Seattle */ /* Charles Audet - Ecole Polytechnique, Montreal */ /* Gilles Couture - Ecole Polytechnique, Montreal */ /* John Dennis - Rice University, Houston */ /* Sebastien Le Digabel - Ecole Polytechnique, Montreal */ /* Christophe Tribes - Ecole Polytechnique, Montreal */ /* */ /* funded in part by AFOSR and Exxon Mobil */ /* */ /* Author: Sebastien Le Digabel */ /* */ /* Contact information: */ /* Ecole Polytechnique de Montreal - GERAD */ /* C.P. 6079, Succ. Centre-ville, Montreal (Quebec) H3C 3A7 Canada */ /* e-mail: nomad@gerad.ca */ /* phone : 1-514-340-6053 #6928 */ /* fax : 1-514-340-5665 */ /* */ /* This program is free software: you can redistribute it and/or modify it under the */ /* terms of the GNU Lesser General Public License as published by the Free Software */ /* Foundation, either version 3 of the License, or (at your option) any later */ /* version. */ /* */ /* This program is distributed in the hope that it will be useful, but WITHOUT ANY */ /* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A */ /* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License along */ /* with this program. If not, see . */ /* */ /* You can find information on the NOMAD software at www.gerad.ca/nomad */ /*-------------------------------------------------------------------------------------*/ /** \file Extended_Poll.cpp \brief Extended poll for categorical variables (implementation) \author Sebastien Le Digabel \date 2010-04-14 \see Extended_Poll.hpp */ #include "Extended_Poll.hpp" /*----------------------------------------------------------------*/ /* destructor */ /*----------------------------------------------------------------*/ NOMAD::Extended_Poll::~Extended_Poll ( void ) { std::set::const_iterator it , end = _signatures.end(); for ( it = _signatures.begin() ; it != end ; ++it ) delete (*it).get_signature(); poll_reset(); } /*----------------------------------------------------------------*/ /* reset */ /*----------------------------------------------------------------*/ void NOMAD::Extended_Poll::reset ( void ) { // successful directions: std::set::const_iterator it , end = _signatures.end(); for ( it = _signatures.begin() ; it != end ; ++it ) { (*it).get_signature()->reset_feas_success_dir(); (*it).get_signature()->reset_infeas_success_dir(); } // poll_reset: poll_reset(); } /*----------------------------------------------------------------*/ /* poll reset: before the extended poll is launched */ /*----------------------------------------------------------------*/ void NOMAD::Extended_Poll::poll_reset ( void ) { _poll_signatures.clear(); std::list::const_iterator end = _extended_points.end(); for ( std::list::iterator it = _extended_points.begin() ; it != end ; ++it ) if ( !(*it)->is_in_cache() ) delete *it; _extended_points.clear(); } /*----------------------------------------------------------------*/ /* get, check and register the extended point and its signature */ /* created by the user in construct_extended_points() */ /*----------------------------------------------------------------*/ void NOMAD::Extended_Poll::add_extended_poll_point ( NOMAD::Point & ep , NOMAD::Signature & s ) { // new signature: // -------------- NOMAD::Signature * new_s = new NOMAD::Signature (s); // . 's' can be standard, but its copy 'new_s' is not // . a standard signature will never be inserted into _signatures, // since standard signatures are handled and deleted by the Parameters class { // signature already registered ? NOMAD::Signature_Element se ( new_s ); std::set::const_iterator it = _signatures.find ( se ); // signature already registered: if ( it != _signatures.end() ) { // success directions eventually included in new_s are not considered // since new_s is the copy of s, which is user provided delete new_s; new_s = it->get_signature(); } // new signature to register: else _signatures.insert ( se ); _poll_signatures.insert ( NOMAD::Signature_Element ( new_s ) ); } // new eval point: // --------------- int ell = NOMAD::Mesh::get_mesh_index(); NOMAD::Eval_Point * pt = new NOMAD::Eval_Point; pt->set ( ep , _p.get_bb_nb_outputs() ); pt->set_signature ( new_s ); pt->set_mesh_index ( &ell ); _extended_points.push_back ( pt ); } /*----------------------------------------------------------------*/ /* check the extended poll trigger */ /*----------------------------------------------------------------*/ /* . return true if the extended poll has to be performed */ /* . private method */ /*----------------------------------------------------------------*/ bool NOMAD::Extended_Poll::check_trigger ( const NOMAD::Eval_Point * old_bf , const NOMAD::Eval_Point * old_bi , const NOMAD::Eval_Point * y ) const { if ( !y->is_in_cache() || !y->is_eval_ok() || !y->get_f().is_defined() || !y->get_h().is_defined() ) return false; // y is feasible: // -------------- if ( y->is_feasible ( _p.get_h_min() ) ) { if ( !old_bf ) return true; return check_trigger_on_f ( old_bf->get_f() , y->get_f() ); } // y is infeasible: // ---------------- if ( !old_bf && !old_bi ) return true; if ( !old_bf ) return ( y->get_h() < old_bi->get_h() ); if ( !old_bi ) return check_trigger_on_f ( old_bf->get_f() , y->get_f() ); if ( y->get_h() >= old_bi->get_h() ) return false; // y is infeasible, and old best feasible and best infeasible solutions are // available: the extended poll will be performed if the y point in the // (h,f) space is below the line joining [ h(old_bf) , f(old_bf)+trigger ] // to [ h(old_bi) , f(old_bi)+trigger ] : const NOMAD::Double & hA = old_bf->get_h(); NOMAD::Double fA = old_bf->get_f(); const NOMAD::Double & hB = old_bi->get_h(); NOMAD::Double fB = old_bi->get_f(); const NOMAD::Double & hy = y->get_h(); const NOMAD::Double & fy = y->get_f(); const NOMAD::Double & ept = _p.get_extended_poll_trigger(); if ( _p.get_relative_ept() && fA != 0.0 && fB != 0.0 && fy != 0.0 ) { fA = fA + fA.abs() * ept; fB = fB + fB.abs() * ept; } else { fA = fA + ept; fB = fB + ept; } // line joining [h(A),f(A)] to [h(B),f(B)]: f=a*h+b : NOMAD::Double a = (fA-fB) / (hA-hB); NOMAD::Double b = fA - a * hA; return fy < a*hy + b; } /*-------------------------------------------------------------------*/ /* check only the f values for the extended poll trigger (private) */ /*-------------------------------------------------------------------*/ bool NOMAD::Extended_Poll::check_trigger_on_f ( const NOMAD::Double & old_f , const NOMAD::Double & new_f ) const { if ( new_f <= old_f ) return true; // relative comparison (both values are != 0): if ( _p.get_relative_ept() && old_f != 0.0 && new_f != 0.0 ) return ( new_f < old_f + old_f.abs() * _p.get_extended_poll_trigger() ); // absolute comparison: return ( new_f < old_f + _p.get_extended_poll_trigger() ); } /*----------------------------------------------------------------*/ /* descent from the extended poll center (private) */ /*----------------------------------------------------------------*/ void NOMAD::Extended_Poll::descent ( const NOMAD::Eval_Point * y , Mads & mads , int & nb_ext_poll_pts , bool & stop , NOMAD::stop_type & stop_reason , NOMAD::success_type & success , const NOMAD::Eval_Point *& new_feas_inc , const NOMAD::Eval_Point *& new_infeas_inc ) { int mesh_index = NOMAD::Mesh::get_mesh_index(); NOMAD::Stats & stats = mads.get_stats(); bool has_sgte = _p.has_sgte(); bool opt_only_sgte = _p.get_opt_only_sgte(); const NOMAD::Display & out = _p.out(); NOMAD::dd_type display_degree = out.get_poll_dd(); // displays: if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << NOMAD::EXTENDED_POLL << " descent"; if ( has_sgte ) oss << " (on surrogates)"; out << std::endl << NOMAD::open_block ( oss.str() ) << std::endl; out << " iteration = " << stats.get_iterations() << std::endl << " blackbox eval. = " << stats.get_bb_eval() << std::endl; if ( has_sgte ) out << " sgte eval. = " << stats.get_sgte_eval() << std::endl; out << " mesh index = " << mesh_index << std::endl << "ext. poll center = ( "; y->Point::display ( out , " " , 5 , _p.get_point_display_limit() ); out << " ) f=" << y->get_f() << " h=" << y->get_h() << std::endl << std::endl; } // get the signature: NOMAD::Signature * signature = y->get_signature(); // create the descent parameters: NOMAD::Parameters descent_p ( signature , _p.out() ); set_descent_parameters ( y , stats , descent_p ); // Evaluator_Control object: NOMAD::Evaluator_Control & ev_control = mads.get_evaluator_control(); // descent: run MADS: // ------------------ NOMAD::Mads EP_mads ( descent_p , ev_control.get_evaluator () , NULL , &ev_control.get_cache () , &ev_control.get_sgte_cache() ); #ifdef DEBUG out << std::endl << NOMAD::open_block ( "MADS run (ext. poll)" ) << std::endl; #endif NOMAD::Mads::set_flag_reset_barriers ( true ); NOMAD::Mads::set_flag_reset_mesh ( false ); NOMAD::stop_type st = EP_mads.run(); NOMAD::Mads::set_flag_reset_mesh ( true ); #ifdef DEBUG out << std::endl << NOMAD::close_block ( "end of run (ext. poll)" ) << std::endl; #endif // restore mesh index: NOMAD::Mesh::set_mesh_index ( mesh_index ); // update stats: const NOMAD::Stats & EP_stats = EP_mads.get_stats(); stats.update ( EP_stats , true ); // for_search = true stats.add_ext_poll_bb_eval ( EP_stats.get_bb_eval() ); stats.add_ext_poll_descent (); // check MADS stopping criteria: if ( st == NOMAD::CTRL_C || st == NOMAD::ERROR || st == NOMAD::UNKNOWN_STOP_REASON || st == NOMAD::FEAS_REACHED || st == NOMAD::MAX_CACHE_MEMORY_REACHED || st == NOMAD::STAT_SUM_TARGET_REACHED || st == NOMAD::MAX_SGTE_EVAL_REACHED || st == NOMAD::F_TARGET_REACHED || st == NOMAD::MAX_SIM_BB_EVAL_REACHED || st == NOMAD::MAX_TIME_REACHED || st == NOMAD::MAX_BB_EVAL_REACHED ) { stop_reason = st; stop = true; } // Pareto front: NOMAD::Pareto_Front * pareto_front = mads.get_pareto_front(); // the barriers: NOMAD::Barrier & true_barrier = mads.get_true_barrier(); NOMAD::Barrier & sgte_barrier = mads.get_sgte_barrier(); // surrogate evaluations: perform at most one true evaluation: if ( has_sgte && !opt_only_sgte ) { if ( !stop ) { // remember old best surrogates incumbents: const NOMAD::Eval_Point * old_sgte_bf = sgte_barrier.get_best_feasible (); const NOMAD::Eval_Point * old_sgte_bi = sgte_barrier.get_best_infeasible(); // update the surrogate barrier // (no need to invoke Evaluator_Control::process_barrier_points() here // since only surrogate evaluations have been made): sgte_barrier.insert ( EP_mads.get_sgte_barrier() ); NOMAD::success_type sgte_succ = sgte_barrier.get_success(); sgte_barrier.update_and_reset_success(); // we generate only a true trial point if the // surrogates improved the surrogate barrier: if ( sgte_succ != NOMAD::UNSUCCESSFUL ) { // choose the best surrogate point(s) where to evaluate the true function: const NOMAD::Eval_Point * sgte_bf = sgte_barrier.get_best_feasible (); const NOMAD::Eval_Point * sgte_bi = sgte_barrier.get_best_infeasible(); std::list candidates; if ( sgte_bf && ( !y->is_feasible(_p.get_h_min()) || sgte_bf != old_sgte_bf ) ) candidates.push_back ( sgte_bf ); if ( sgte_bi && sgte_bi != old_sgte_bi ) candidates.push_back ( sgte_bi ); // generate the new trial points: NOMAD::Eval_Point * sk; std::list::const_iterator it , end = candidates.end(); for ( it = candidates.begin() ; it != end ; ++it ) { // display: if ( display_degree == NOMAD::FULL_DISPLAY ) out << std::endl << "ext. poll surrogate candidate: " << **it << std::endl; sk = new NOMAD::Eval_Point; sk->set ( signature->get_n() , _p.get_bb_nb_outputs() ); sk->set_signature ( signature ); sk->set_mesh_index ( &mesh_index ); sk->Point::operator = ( **it ); // add the new point to the list of trial points: ev_control.add_eval_point ( sk , display_degree , _p.get_snap_to_bounds() , NOMAD::Double() , NOMAD::Double() , NOMAD::Double() , NOMAD::Double() ); } // eval_list_of_points: // -------------------- success = NOMAD::UNSUCCESSFUL; new_feas_inc = new_infeas_inc = NULL; ev_control.eval_list_of_points ( NOMAD::EXTENDED_POLL , true_barrier , sgte_barrier , pareto_front , stop , stop_reason , new_feas_inc , new_infeas_inc , success ); // number of search points (0 or 1 or 2): nb_ext_poll_pts += static_cast ( candidates.size() ); } } } // true evaluations (or surrogate evaluations if opt_only_sgte==true): else { const NOMAD::Barrier & active_barrier = mads.get_active_barrier(); // for the update of new_feas_inc and new_infeas_inc (1/2): const NOMAD::Eval_Point * old_feasible_incumbent = active_barrier.get_best_feasible(); const NOMAD::Eval_Point * old_infeasible_incumbent = active_barrier.get_best_infeasible(); // update barriers and process extended poll points: NOMAD::success_type sgte_succ = ev_control.process_barrier_points ( sgte_barrier , EP_mads.get_sgte_barrier() , pareto_front , display_degree , NOMAD::EXTENDED_POLL ); NOMAD::success_type true_succ = ev_control.process_barrier_points ( true_barrier , EP_mads.get_true_barrier() , pareto_front , display_degree , NOMAD::EXTENDED_POLL ); // update of new_feas_inc and new_infeas_inc (2/2): const NOMAD::Eval_Point * bf = active_barrier.get_best_feasible (); const NOMAD::Eval_Point * bi = active_barrier.get_best_infeasible(); if ( bf && bf != old_feasible_incumbent ) new_feas_inc = bf; if ( bi && bi != old_infeasible_incumbent ) new_infeas_inc = bi; // number of extended poll points and success: if ( opt_only_sgte ) { nb_ext_poll_pts += EP_mads.get_stats().get_sgte_eval(); success = sgte_succ; } else { nb_ext_poll_pts += EP_mads.get_stats().get_eval(); success = true_succ; } } // final display: if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << "end of " << NOMAD::EXTENDED_POLL << " descent (" << success << ")"; out << std::endl << NOMAD::close_block ( oss.str() ) << std::endl; } } /*----------------------------------------------------------------*/ /* create the descent parameters (private) */ /*----------------------------------------------------------------*/ void NOMAD::Extended_Poll::set_descent_parameters ( const NOMAD::Eval_Point * y , const NOMAD::Stats & stats , NOMAD::Parameters & descent_p ) const { // extended poll center signature // (will be the temporary standard signature): NOMAD::Signature * epc_signature = y->get_signature(); if ( !epc_signature ) throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , "Extended_Poll::set_descent_parameters(): ext. poll center has no signature" ); // we set all the parameters: descent_p.set_DIMENSION ( epc_signature->get_n() ); descent_p.set_BB_INPUT_TYPE ( epc_signature->get_input_types() ); descent_p.set_LOWER_BOUND ( epc_signature->get_lb() ); descent_p.set_UPPER_BOUND ( epc_signature->get_ub() ); descent_p.set_FIXED_VARIABLE ( epc_signature->get_fixed_variables() ); descent_p.set_PERIODIC_VARIABLE ( epc_signature->get_periodic_variables() ); descent_p.set_VARIABLE_GROUP ( epc_signature->get_var_groups() ); descent_p.set_BB_OUTPUT_TYPE ( _p.get_bb_output_type() ); descent_p.set_DIRECTION_TYPE ( _p.get_direction_types() ); { const std::list & bb_exe = _p.get_bb_exe(); descent_p.set_BB_EXE ( bb_exe ); std::list::const_iterator it , end = bb_exe.end(); for ( it = bb_exe.begin() ; it != end ; ++it ) descent_p.set_SGTE_EXE ( *it , _p.get_sgte_exe ( *it ) ); } descent_p.set_PROBLEM_DIR ( _p.get_problem_dir() ); descent_p.set_TMP_DIR ( _p.get_tmp_dir() ); descent_p.set_SGTE_COST ( _p.get_sgte_cost() ); descent_p.set_SGTE_EVAL_SORT ( _p.get_sgte_eval_sort() ); descent_p.set_X0 ( *y ); bool has_sgte = _p.has_sgte(); if ( has_sgte ) { descent_p.reset_f_target(); descent_p.set_HAS_SGTE ( true ); descent_p.set_OPT_ONLY_SGTE ( true ); descent_p.set_STOP_IF_FEASIBLE ( false ); descent_p.set_MODEL_SEARCH ( false ); descent_p.set_MODEL_EVAL_SORT ( NOMAD::NO_MODEL ); } else { descent_p.set_F_TARGET ( _p.get_f_target() ); descent_p.set_STOP_IF_FEASIBLE ( _p.get_stop_if_feasible() ); descent_p.set_MODEL_EVAL_SORT ( _p.get_model_eval_sort()); descent_p.set_MODEL_SEARCH (_p.has_model_search()); } descent_p.set_DIRECTION_TYPE ( _p.get_direction_types() ); descent_p.set_SEC_POLL_DIR_TYPE ( _p.get_sec_poll_dir_types() ); descent_p.set_HALTON_SEED ( _p.get_halton_seed() ); descent_p.set_SEED ( _p.get_seed() ); descent_p.set_LH_SEARCH ( 0 , 0 ); int bbe = stats.get_bb_eval(); int sgte_eval = stats.get_sgte_eval(); { int p_max_bbe = _p.get_max_bb_eval(); if ( p_max_bbe > 0 ) descent_p.set_MAX_BB_EVAL ( p_max_bbe - bbe ); int p_max_sgte_eval = _p.get_max_sgte_eval(); if ( p_max_sgte_eval > 0 ) descent_p.set_MAX_SGTE_EVAL ( p_max_sgte_eval - sgte_eval ); int p_max_eval = _p.get_max_eval(); if ( p_max_eval > 0 ) descent_p.set_MAX_EVAL ( p_max_eval - stats.get_eval() ); int p_max_sbe = _p.get_max_sim_bb_eval(); if ( p_max_sbe > 0 ) descent_p.set_MAX_SIM_BB_EVAL ( p_max_sbe - stats.get_sim_bb_eval() ); int p_max_time = _p.get_max_time(); if ( p_max_time > 0 ) descent_p.set_MAX_TIME ( p_max_time - stats.get_real_time() ); NOMAD::Double p_sst = _p.get_stat_sum_target(); if ( p_sst.is_defined() ) descent_p.set_STAT_SUM_TARGET ( p_sst - stats.get_stat_sum() ); } descent_p.set_OPPORTUNISTIC_EVAL ( _p.get_opportunistic_eval() ); descent_p.set_BB_INPUT_INCLUDE_SEED ( _p.get_bb_input_include_seed() ); descent_p.set_BB_INPUT_INCLUDE_TAG ( _p.get_bb_input_include_tag() ); descent_p.set_BB_REDIRECTION ( _p.get_bb_redirection() ); descent_p.set_EXTENDED_POLL_ENABLED ( false ); descent_p.set_USER_CALLS_ENABLED ( false ); descent_p.set_H_MAX_0 ( _p.get_h_max_0() ); descent_p.set_H_MIN ( _p.get_h_min() ); descent_p.set_H_NORM ( _p.get_h_norm() ); descent_p.set_RHO ( _p.get_rho() ); descent_p.set_SNAP_TO_BOUNDS ( _p.get_snap_to_bounds() ); descent_p.set_MAX_CACHE_MEMORY ( _p.get_max_cache_memory() ); descent_p.set_SPECULATIVE_SEARCH ( _p.get_speculative_search() ); descent_p.set_OPPORTUNISTIC_LUCKY_EVAL ( _p.get_opportunistic_lucky_eval() ); descent_p.set_OPPORTUNISTIC_MIN_EVAL ( _p.get_opportunistic_min_eval() ); descent_p.set_OPPORTUNISTIC_MIN_F_IMPRVMT ( _p.get_opportunistic_min_f_imprvmt() ); descent_p.set_OPPORTUNISTIC_MIN_NB_SUCCESS ( _p.get_opportunistic_min_nb_success() ); descent_p.set_CACHE_FILE ( _p.get_cache_file() ); descent_p.set_SGTE_CACHE_FILE ( _p.get_sgte_cache_file() ); descent_p.set_CACHE_SAVE_PERIOD ( _p.get_cache_save_period() ); descent_p.set_ADD_SEED_TO_FILE_NAMES ( _p.get_add_seed_to_file_names() ); descent_p.set_DISPLAY_ALL_EVAL(_p.get_display_all_eval()); if ( _p.out().get_poll_dd() == NOMAD::FULL_DISPLAY ) descent_p.set_DISPLAY_DEGREE ( NOMAD::NORMAL_DISPLAY ); else if (_p.out().get_poll_dd() == NOMAD::NORMAL_DISPLAY ) descent_p.set_DISPLAY_DEGREE ( NOMAD::MINIMAL_DISPLAY ); else descent_p.set_DISPLAY_DEGREE ( _p.out().get_poll_dd()); if ( has_sgte ) descent_p.set_DISPLAY_STATS ( NOMAD::itos(sgte_eval) + "+SGTE OBJ (ExtendedPoll---surrogate)" ); else { std::list ds = _p.get_display_stats(); std::list::iterator it = ds.begin(); std::list::const_iterator end = ds.end(); std::string s_bbe = NOMAD::itos(bbe) + "+"; while ( it != end ) { if (*it == "BBE") ds.insert ( it , s_bbe ); ++it; } ds.push_back ( " (ExtendedPoll)" ); descent_p.set_DISPLAY_STATS ( ds ); } // STATS_FILE: if ( has_sgte ) descent_p.set_STATS_FILE ( _p.get_stats_file_name() , NOMAD::itos(sgte_eval) + "+SGTE OBJ (ExtendedPoll---surrogate)" ); else { std::list sf = _p.get_stats_file(); std::list::iterator it = sf.begin(); std::list::const_iterator end = sf.end(); std::string s_bbe = NOMAD::itos(bbe) + "+"; while ( it != end ) { if ( *it == "BBE" ) sf.insert ( it , s_bbe ); ++it; } sf.push_back ( " (ExtendedPoll)" ); descent_p.set_STATS_FILE ( _p.get_stats_file_name() , sf ); } // Mesh: { const Mesh & mesh = epc_signature->get_mesh(); descent_p.set_MIN_MESH_SIZE ( mesh.get_min_mesh_size() ); descent_p.set_MIN_POLL_SIZE ( mesh.get_min_poll_size() ); int ell = NOMAD::Mesh::get_mesh_index(); descent_p.set_INITIAL_MESH_INDEX ( ell ); descent_p.set_MAX_MESH_INDEX ( ell ); descent_p.set_INITIAL_MESH_SIZE ( mesh.get_initial_mesh_size() , false ); } // check the parameters: try { descent_p.check ( false , // remove_history_file = false false , // remove_solution_file = false false ); // remove_stats_file = false } catch ( NOMAD::Exception & e ) { std::ostringstream err; err << "-- " << e.what(); throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , err.str() ); } } /*----------------------------------------------------------------*/ /* evaluation of an extended poll point (private) */ /*----------------------------------------------------------------*/ const NOMAD::Eval_Point * NOMAD::Extended_Poll::eval_epp ( NOMAD::Eval_Point * y , Mads & mads , bool & stop , NOMAD::stop_type & stop_reason , NOMAD::success_type & success , const NOMAD::Eval_Point *& new_feas_inc , const NOMAD::Eval_Point *& new_infeas_inc ) const { NOMAD::Evaluator_Control & ev_control = mads.get_evaluator_control(); const NOMAD::Display & out = _p.out(); NOMAD::dd_type display_degree = out.get_poll_dd(); // initial display: if ( display_degree == NOMAD::FULL_DISPLAY ) { out << std::endl << NOMAD::open_block ( "extended poll point eval" ) << std::endl << "extended poll point = ( "; y->Point::display ( out , " " , 5 , _p.get_point_display_limit() ); out << " )" << std::endl; } // add the eval point to the evaluator control: ev_control.add_eval_point ( y , display_degree , _p.get_snap_to_bounds() , NOMAD::Double() , NOMAD::Double() , NOMAD::Double() , NOMAD::Double() ); // get the stats: NOMAD::Stats & stats = mads.get_stats(); int old_bbe = stats.get_bb_eval(); // eval list of points: new_feas_inc = new_infeas_inc = NULL; std::list evaluated_pts; ev_control.eval_list_of_points ( NOMAD::EXTENDED_POLL , mads.get_true_barrier() , mads.get_sgte_barrier() , mads.get_pareto_front() , stop , stop_reason , new_feas_inc , new_infeas_inc , success , &evaluated_pts ); // update the number of extended poll blackbox evaluations: stats.add_ext_poll_bb_eval ( stats.get_bb_eval() - old_bbe ); // final display: if ( display_degree == NOMAD::FULL_DISPLAY ) out << std::endl << NOMAD::close_block() << std::endl; // return the evaluated point: return ( evaluated_pts.size() != 1 ) ? NULL : *evaluated_pts.begin(); } /*-----------------------------------------*/ /* run the extended poll */ /*-----------------------------------------*/ void NOMAD::Extended_Poll::run ( Mads & mads , int & nb_ext_poll_pts , bool & stop , NOMAD::stop_type & stop_reason , NOMAD::success_type & success , const NOMAD::Eval_Point *& new_feas_inc , const NOMAD::Eval_Point *& new_infeas_inc ) { nb_ext_poll_pts = 0; success = NOMAD::UNSUCCESSFUL; new_feas_inc = new_infeas_inc = NULL; if ( stop || _extended_points.empty() ) return; const NOMAD::Display & out = _p.out(); NOMAD::dd_type display_degree = out.get_poll_dd(); NOMAD::Eval_Point * cur; // phase 1: evaluate the extended poll points in order to sort them // -------- (based on the surrogates or on the true function): if ( _extended_points.size() > 1 ) { bool has_sgte = _p.has_sgte(); bool old_sgte_eval_sort = _p.get_sgte_eval_sort(); // phase 1 initial display: if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << "extended poll pts sorting"; if ( has_sgte ) oss << " (on surrogates)"; out << std::endl << NOMAD::open_block ( oss.str() ) << std::endl; } if ( has_sgte ) { _p.set_SGTE_EVAL_SORT ( false ); // this ensures that only surrogate _p.force_check_flag(); // evaluations are performed } NOMAD::Evaluator_Control & ev_control = mads.get_evaluator_control(); // loop on the extended poll points: std::list::const_iterator end = _extended_points.end(); for ( std::list::iterator it = _extended_points.begin() ; it != end ; ++it ) { cur = *it; if ( has_sgte ) cur->set_eval_type ( NOMAD::SGTE ); ev_control.add_eval_point ( cur , display_degree , _p.get_snap_to_bounds() , NOMAD::Double() , NOMAD::Double() , NOMAD::Double() , NOMAD::Double() ); } _extended_points.clear(); // get the stats: NOMAD::Stats & stats = mads.get_stats(); int old_bbe = stats.get_bb_eval(); // number of eval points: nb_ext_poll_pts = ev_control.get_nb_eval_points(); // eval list of points: new_feas_inc = new_infeas_inc = NULL; std::list evaluated_pts; ev_control.eval_list_of_points ( NOMAD::EXTENDED_POLL , mads.get_true_barrier() , mads.get_sgte_barrier() , mads.get_pareto_front() , stop , stop_reason , new_feas_inc , new_infeas_inc , success , &evaluated_pts ); if ( has_sgte ) { if ( !_p.get_opt_only_sgte() ) { success = NOMAD::UNSUCCESSFUL; new_feas_inc = new_infeas_inc = NULL; } _p.set_SGTE_EVAL_SORT ( old_sgte_eval_sort ); _p.force_check_flag(); } // update the number of extended poll blackbox evaluations: stats.add_ext_poll_bb_eval ( stats.get_bb_eval() - old_bbe ); // sort the evaluated extended poll points: if ( success != NOMAD::FULL_SUCCESS ) sort_epp ( evaluated_pts ); // the extended poll is terminated in case of success: if ( stop || success == NOMAD::FULL_SUCCESS || new_feas_inc || new_infeas_inc ) { if ( display_degree == NOMAD::FULL_DISPLAY ) out << std::endl << NOMAD::close_block ( "end of ext poll pts sorting (success)" ) << std::endl; return; } // phase 1 final display: if ( display_degree == NOMAD::FULL_DISPLAY ) { std::ostringstream oss; oss << "end of ext poll pts sorting"; if ( has_sgte ) oss << " (on surrogates)"; out << std::endl << NOMAD::close_block ( oss.str() ) << std::endl; } } // end of phase 1 // -------------- /*--------------------------------------------------------------*/ // phase 2: execute the extended poll for each extended point: // -------- { const NOMAD::Eval_Point * old_bf = mads.get_best_feasible(); const NOMAD::Eval_Point * old_bi = mads.get_best_infeasible(); const NOMAD::Eval_Point * y; while ( !_extended_points.empty() ) { cur = *_extended_points.begin(); // the point has already been evaluated during // the extended poll points sorting: if ( cur->is_in_cache() && cur->get_eval_type() == NOMAD::TRUTH ) y = cur; // the point has to be evaluated: else { y = eval_epp ( cur , mads , stop , stop_reason , success , new_feas_inc , new_infeas_inc ); ++nb_ext_poll_pts; // the extended poll is terminated in case of success: if ( !y || stop || success == NOMAD::FULL_SUCCESS || new_feas_inc || new_infeas_inc ) break; } _extended_points.pop_front(); // perform the extended poll descent ? if ( display_degree == NOMAD::FULL_DISPLAY ) { out << std::endl << "extended poll center: ( "; y->Point::display ( out , " " , 5 , _p.get_point_display_limit() ); out << " )" << std::endl << std::endl << "perform extended poll descent ..."; } if ( check_trigger ( old_bf , old_bi , y ) ) { if ( display_degree == NOMAD::FULL_DISPLAY ) out << "... yes" << std::endl; descent ( y , mads , nb_ext_poll_pts , stop , stop_reason , success , new_feas_inc , new_infeas_inc ); // the extended poll is terminated in case of success: if ( stop || success == NOMAD::FULL_SUCCESS || new_feas_inc || new_infeas_inc ) break; } else if ( display_degree == NOMAD::FULL_DISPLAY ) out << "... no" << std::endl; } } // end of phase 2 // -------------- // clean the extended points that have not been considered: std::list::const_iterator end = _extended_points.end(); for ( std::list::iterator it = _extended_points.begin() ; it != end ; ++it ) if ( !(*it)->is_in_cache() ) delete *it; _extended_points.clear(); } /*----------------------------------------------------------------*/ /* sort the extended poll points after they have been evaluated */ /* (private) */ /*----------------------------------------------------------------*/ void NOMAD::Extended_Poll::sort_epp ( const std::list & evaluated_pts ) { const NOMAD::Display & out = _p.out(); NOMAD::dd_type display_degree = out.get_poll_dd(); const NOMAD::Double & h_min = _p.get_h_min(); std::set sorted_pts; // 1. loop on the evaluated points: std::list::const_iterator it1 , end1 = evaluated_pts.end(); for ( it1 = evaluated_pts.begin() ; it1 != end1 ; ++it1 ) { // creation of a Priority_Eval_Point: NOMAD::Priority_Eval_Point pep ( *it1 , h_min ); // surrogate values for f and h: if ( (*it1)->get_eval_type() == NOMAD::SGTE ) { pep.set_f_sgte ( (*it1)->get_f() ); pep.set_h_sgte ( (*it1)->get_h() ); } // insertion in the sorted list of points: sorted_pts.insert ( pep ); } // 2. loop on the sorted points: if ( display_degree == NOMAD::FULL_DISPLAY ) out << std::endl << NOMAD::open_block ( "sorted ext poll pts" ) << std::endl; const NOMAD::Eval_Point * cur; NOMAD::Eval_Point * y; int i = 0 , nb_pts = static_cast ( sorted_pts.size() ); std::set::const_iterator it2 , end2 = sorted_pts.end(); for ( it2 = sorted_pts.begin() ; it2 != end2 ; ++it2 ) { // we copy y=cur an create a new Eval_Point because cur can be a surrogate // point already in the surrogate cache cur = (*it2).get_point(); y = new NOMAD::Eval_Point; y->set ( cur->size() , _p.get_bb_nb_outputs() ); y->set_signature ( cur->get_signature () ); y->set_direction ( cur->get_direction () ); y->set_mesh_index ( cur->get_mesh_index() ); y->Point::operator = ( *cur ); // display: if ( display_degree == NOMAD::FULL_DISPLAY ) { out << "point #"; out.display_int_w ( ++i , nb_pts ); out << "/" << nb_pts << " : ( "; y->Point::display ( out , " " , 5 , _p.get_point_display_limit() ); out << " )" << std::endl; } // insertion in _extended_points: _extended_points.push_back ( y ); } if ( display_degree == NOMAD::FULL_DISPLAY ) out << std::endl << NOMAD::close_block() << std::endl; } /*--------------------------------------------------------------------*/ /* set the neighbors executable name for the default implementation */ /*--------------------------------------------------------------------*/ bool NOMAD::Extended_Poll::set_neighbors_exe ( std::string & error_str ) { error_str.clear(); _neighbors_exe = _p.get_neighbors_exe(); if ( _neighbors_exe.empty() ) { error_str = "categorical variables: parameter NEIGHBORS_EXE is undefined"; return false; } const std::string problem_dir = _p.get_problem_dir(); std::list neighbors_exe_words; NOMAD::get_words ( _neighbors_exe , neighbors_exe_words ); // _neighbors_exe is composed of several words (it is a command): if ( neighbors_exe_words.size() > 1 ) { _neighbors_exe.clear(); std::list::const_iterator it = neighbors_exe_words.begin() , end = neighbors_exe_words.end(); while (true) { if ( (*it)[0] != '$' ) { _neighbors_exe += "\"" + problem_dir; _neighbors_exe += *it + "\""; } else _neighbors_exe += it->substr ( 1 , it->size()-1 ); ++it; if ( it == end ) break; _neighbors_exe += " "; } } // _neighbors_exe is just composed of one name (it is an executable): else { if ( _neighbors_exe[0] != '$' ) _neighbors_exe = problem_dir + _neighbors_exe; else _neighbors_exe = _neighbors_exe.substr ( 1 , _neighbors_exe.size()-1 ); if ( !NOMAD::check_exe_file ( _neighbors_exe ) ) { error_str = "categorical variables: \'" + _neighbors_exe + "\' is not a valid executable file"; return false; } if ( _neighbors_exe[0] != '$' ) _neighbors_exe = "\"" + _neighbors_exe + "\""; } return true; } /*----------------------------------------------------------------------*/ /* construct the extended poll points: this is the default version of */ /* this virtual function: it calls the executable defined by the */ /* NEIGHBORS_EXE parameter */ /*----------------------------------------------------------------------*/ void NOMAD::Extended_Poll::construct_extended_points ( const NOMAD::Eval_Point & xk ) { if ( _neighbors_exe.empty() ) throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , "NOMAD::Extended_Poll::construct_extended_points(): no NEIGHBORS_EXE executable (batch mode) or no subclass implementation of the method (library mode)" ); if ( !xk.is_complete() ) throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , "NOMAD::Extended_Poll::construct_extended_points(): bad extended poll center"); NOMAD::Signature * signature = _p.get_signature(); if ( !signature ) throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , "NOMAD::Extended_Poll::construct_extended_points(): no signature" ); std::string tmp_dir = _p.get_tmp_dir(); std::ostringstream oss; oss << "." << _p.get_seed() << "." << xk.get_tag() << ".neighbors."; const std::string & sint = oss.str(); // input file writing: // ------------------- std::string input_file_name = tmp_dir + NOMAD::BLACKBOX_INPUT_FILE_PREFIX + sint + NOMAD::BLACKBOX_INPUT_FILE_EXT; std::string output_file_name = tmp_dir + NOMAD::BLACKBOX_OUTPUT_FILE_PREFIX + sint + NOMAD::BLACKBOX_OUTPUT_FILE_EXT; std::ofstream fout ( input_file_name.c_str() ); if ( fout.fail() ) { remove ( input_file_name.c_str () ); std::string err = "could not open file neighbors input file " + input_file_name; throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , err ); } fout.setf ( std::ios::fixed ); fout.precision ( NOMAD::DISPLAY_PRECISION_BB ); xk.Point::display ( fout , " " , -1 , -1 ); fout << std::endl; fout.close(); if ( fout.fail() ) { remove ( input_file_name.c_str () ); std::string err = "could not write file neighbors input file " + input_file_name; throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , err ); } // system call to get the neighbors: // --------------------------------- std::string cmd = _neighbors_exe + " " + input_file_name + " > " + 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 call: if ( ( system ( cmd.c_str() ) ) != 0 ) { remove ( input_file_name.c_str () ); remove ( output_file_name.c_str() ); std::string err = "error with command " + cmd; throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , err ); } // reading of the output file: // --------------------------- std::ifstream fin ( output_file_name.c_str() ); if ( fin.fail() ) { remove ( input_file_name.c_str () ); remove ( output_file_name.c_str() ); std::string err = "could not open neighbors output file " + output_file_name; throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , err ); } int n = xk.size(); while ( true ) { NOMAD::Point y(n); try { fin >> y; } catch ( NOMAD::Point::Bad_Input & ) { if ( y.is_defined() ) { remove ( input_file_name.c_str () ); remove ( output_file_name.c_str() ); std::string err = "error with neighbor in file " + output_file_name; throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , err ); } break; } if ( !y.is_complete() ) { remove ( input_file_name.c_str () ); remove ( output_file_name.c_str() ); std::string err = "error with neighbor in file " + output_file_name; throw NOMAD::Exception ( "Extended_Poll.cpp" , __LINE__ , err ); } add_extended_poll_point ( y , *signature ); } fin.close(); // delete the input and output files: // ---------------------------------- remove ( input_file_name.c_str () ); remove ( output_file_name.c_str() ); }