/*-------------------------------------------------------------------------------------*/
/* 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 Evaluator_Control.cpp
\brief Control of the blackbox evaluations (implementation)
\author Sebastien Le Digabel
\date 2010-04-15
\see Evaluator_Control.hpp
*/
#include "Evaluator_Control.hpp"
#include "Multi_Obj_Quad_Model_Evaluator.hpp"
#include "Single_Obj_Quad_Model_Evaluator.hpp"
/*-----------------------------------*/
/* static members initialization */
/*-----------------------------------*/
bool NOMAD::Evaluator_Control::_force_quit = false;
/*---------------------------------------------------------*/
/* constructor */
/*---------------------------------------------------------*/
NOMAD::Evaluator_Control::Evaluator_Control
( const NOMAD::Parameters & p ,
NOMAD::Stats & stats ,
NOMAD::Evaluator * ev , // can be NULL
NOMAD::Cache * cache , // can be NULL
NOMAD::Cache * sgte_cache ) // can be NULL
: _p ( p ) ,
_ev ( ev ) ,
_cache ( cache ) ,
_sgte_cache ( sgte_cache ) ,
_model_eval_sort ( true ) ,
_del_ev ( false ) ,
_del_cache ( false ) ,
_del_sgte_cache ( false ) ,
#ifdef USE_MPI
_eval_in_progress ( NULL ) ,
_nb_in_progress ( 0 ) ,
_elop_tag ( 0 ) ,
_slaves_elop_tags ( NULL ) ,
_slave ( NULL ) ,
#endif
#ifdef USE_TGP
_last_TGP_model ( NULL ) ,
#endif
_stats ( stats ) ,
_last_stats_tag ( -1 ) ,
_last_stats_bbe ( -1 ) ,
_last_history_bbe ( -1 )
{
NOMAD::Evaluator_Control::_force_quit = false;
// Evaluator init:
if ( !_ev ) {
_ev = ( _p.get_index_obj().size() > 1 ) ? new NOMAD::Multi_Obj_Evaluator ( p ):
new NOMAD::Evaluator ( p );
_del_ev = true;
}
if ( NOMAD::Slave::is_master() ) {
#ifdef USE_MPI
int np = NOMAD::Slave::get_nb_processes();
_eval_in_progress = new NOMAD::Eval_Point * [np];
_slaves_elop_tags = new int [np];
for ( int i = 0 ; i < np ; ++i ) {
_eval_in_progress[i] = NULL;
_slaves_elop_tags[i] = -1;
}
_slave = new NOMAD::Slave ( _p , _ev );
#endif
const NOMAD::Display & out = _p.out();
// caches creation:
if ( !_cache ) {
_cache = new NOMAD::Cache ( out , NOMAD::TRUTH );
_del_cache = true;
}
if ( !_sgte_cache ) {
_sgte_cache = new NOMAD::Cache ( out , NOMAD::SGTE );
_del_sgte_cache = true;
}
// caches init (we only load cache file points with m blackbox outputs):
std::string file_name;
int m = p.get_bb_nb_outputs();
NOMAD::dd_type display_degree = out.get_gen_dd();
if ( !_p.get_cache_file().empty() ) {
file_name = _p.get_problem_dir() + _p.get_cache_file();
if ( !_cache->load ( file_name , &m , display_degree == NOMAD::FULL_DISPLAY )
&& display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
out << std::endl
<< "Warning (" << "Evaluator_Control.cpp" << ", " << __LINE__
<< "): could not load (or create) the cache file " << file_name
<< std::endl << std::endl;
}
if ( !_p.get_sgte_cache_file().empty() ) {
file_name = _p.get_problem_dir() + _p.get_sgte_cache_file();
if ( !_sgte_cache->load ( file_name , &m , display_degree==NOMAD::FULL_DISPLAY ) &&
display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY )
out << std::endl << "Warning (" << "Evaluator_Control.cpp" << ", " << __LINE__
<< "): could not load (or create) the surrogate cache file "
<< file_name << std::endl << std::endl;
}
#ifdef MODEL_STATS
if ( _p.has_model_search() ||
( _model_eval_sort &&
_p.get_model_eval_sort() != NOMAD::NO_MODEL ) ) {
out << std::endl
<< "MODEL_STATS is active. Displayed model stats are:"
<< std::endl
<< "mode ell nY wY cond";
if ( _p.has_constraints() )
out << " h mh eh";
out << " f mf ef" << std::endl
<< NOMAD::open_block()
<< "mode: model search (1) or model ordering (2)" << std::endl
<< "ell : mesh_index" << std::endl
<< "nY : cardinality of the interpolation set Y" << std::endl
<< "wY : width of Y" << std::endl
<< "cond: Y condition number" << std::endl;
if ( _p.has_constraints() )
out << "h : h value" << std::endl
<< "mh : model value for h" << std::endl
<< "eh : relative error(%)" << std::endl;
out << "f : f value" << std::endl
<< "mf : model value for f" << std::endl
<< "ef : relative error(%)" << std::endl
<< NOMAD::close_block() << std::endl;
}
#endif
}
}
/*---------------------------------------------------------*/
/* destructor */
/*---------------------------------------------------------*/
NOMAD::Evaluator_Control::~Evaluator_Control ( void )
{
if ( _del_ev )
delete _ev;
if ( _del_cache )
delete _cache;
if ( _del_sgte_cache )
delete _sgte_cache;
clear_eval_lop();
#ifdef USE_MPI
if ( _eval_in_progress ) {
int np = NOMAD::Slave::get_nb_processes();
for ( int i = 0 ; i < np ; ++i )
if ( _eval_in_progress[i] && !_eval_in_progress[i]->is_in_cache() )
delete _eval_in_progress[i];
delete [] _eval_in_progress;
}
if ( _slaves_elop_tags )
delete [] _slaves_elop_tags;
delete _slave;
#endif
}
/*---------------------------------------------------------*/
/* reset */
/*---------------------------------------------------------*/
void NOMAD::Evaluator_Control::reset ( void )
{
_last_stats_tag = _last_stats_bbe = -1;
#ifdef USE_TGP
_last_TGP_model = NULL;
#endif
}
/*---------------------------------------------------------*/
/* save the caches */
/*---------------------------------------------------------*/
bool NOMAD::Evaluator_Control::save_caches ( bool overwrite )
{
const NOMAD::Display & out = _p.out();
NOMAD::dd_type display_degree = out.get_gen_dd();
bool b1 = _cache->save ( overwrite , display_degree == NOMAD::FULL_DISPLAY );
bool b2 = _sgte_cache->save ( overwrite , display_degree == NOMAD::FULL_DISPLAY );
if ( !b1 && display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
out << std::endl << "Warning (" << "Evaluator_Control.cpp" << ", " << __LINE__
<< "): could not save the cache file "
<< _p.get_problem_dir() << _p.get_cache_file()
<< std::endl << std::endl;
if ( !b2 && display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
out << std::endl
<< "Warning (" << "Evaluator_Control.cpp" << ", " << __LINE__
<< "): could not save the surrogate cache file "
<< _p.get_problem_dir() << _p.get_sgte_cache_file()
<< std::endl << std::endl;
return b1 && b2;
}
/*---------------------------------------------------------*/
/* process an already evaluated Eval_Point (private) */
/*---------------------------------------------------------*/
void NOMAD::Evaluator_Control::process_eval_point
( const NOMAD::Eval_Point & x ,
NOMAD::Barrier & barrier ,
NOMAD::Pareto_Front * pareto_front ) const
{
// insertion of the Eval_Point in the barriers:
barrier.insert(x);
if ( x.get_eval_type() == NOMAD::TRUTH || _p.get_opt_only_sgte() ) {
// multi-objective:
if ( pareto_front ) {
// insertion of the Eval_Point in the Pareto front:
if ( x.is_feasible ( _p.get_h_min() ) &&
pareto_front->insert ( x ) &&
_p.get_user_calls_enabled() )
_ev->update_success ( _stats , x );
}
// single-objective: call virtual method Evaluator::update_success():
else if ( _p.get_user_calls_enabled() &&
barrier.get_one_eval_succ() == NOMAD::FULL_SUCCESS )
_ev->update_success ( _stats , x );
}
}
/*---------------------------------------------------------*/
/* update barrier b1 from points in barrier b2 and treat */
/* these points as evaluations (used in VNS search) */
/*---------------------------------------------------------*/
NOMAD::success_type NOMAD::Evaluator_Control::process_barrier_points
( NOMAD::Barrier & b1 ,
const NOMAD::Barrier & b2 ,
NOMAD::Pareto_Front * pareto_front ,
NOMAD::dd_type display_degree ,
NOMAD::search_type search ) const
{
b1.reset_success();
NOMAD::Eval_Point * modifiable_x;
NOMAD::success_type one_eval_succ;
bool opt_only_sgte = _p.get_opt_only_sgte();
const std::string & his_file = _p.get_history_file();
const NOMAD::Eval_Point * last_success = NULL;
const std::list
& all_inserted = b2.get_all_inserted();
std::list::const_iterator
it , end = all_inserted.end();
for ( it = all_inserted.begin() ; it != end ; ++it ) {
// insertion in barrier:
modifiable_x = &NOMAD::Cache::get_modifiable_point ( **it );
modifiable_x->set_direction ( NULL );
modifiable_x->set_mesh_index ( NULL );
modifiable_x->set_poll_center_type ( NOMAD::UNDEFINED_POLL_CENTER_TYPE );
modifiable_x->set_user_eval_priority ( NOMAD::Double() );
modifiable_x->set_rand_eval_priority ( NOMAD::Double() );
// process evaluation point:
process_eval_point ( **it , b1 , pareto_front );
one_eval_succ = b1.get_one_eval_succ();
if ( one_eval_succ != NOMAD::UNSUCCESSFUL && one_eval_succ >= b1.get_success() )
last_success = *it;
// update the history file:
if ( !his_file.empty() && ( opt_only_sgte ||
(*it)->get_eval_type() == NOMAD::TRUTH ) )
write_sol_or_his_file ( _p.get_problem_dir() + his_file , **it , false );
}
NOMAD::success_type success = b1.get_success();
// display and save only the last success:
if ( last_success )
display_eval_result ( *last_success ,
display_degree ,
search ,
success ,
success );
// barrier update:
b1.update_and_reset_success();
return success;
}
/*---------------------------------------------------------*/
/* count the output stats (STAT_SUM and STAT_AVG) */
/* (private) */
/*---------------------------------------------------------*/
void NOMAD::Evaluator_Control::count_output_stats ( const NOMAD::Eval_Point & x )
{
const NOMAD::Point & bbo = x.get_bb_outputs();
int i_sum = _p.get_index_stat_sum();
int i_avg = _p.get_index_stat_avg();
// STAT_SUM:
if ( i_sum >= 0 )
_stats.update_stat_sum ( bbo[i_sum] );
// STAT_AVG:
if ( i_avg >= 0 )
_stats.update_stat_avg ( bbo[i_avg] );
}
/*-------------------------------------------------------------------*/
/* file displays for parameter STATS_FILE */
/*-------------------------------------------------------------------*/
void NOMAD::Evaluator_Control::stats_file ( const std::string & file_name ,
const NOMAD::Eval_Point * x ,
bool feasible ,
const NOMAD::Point * multi_obj ) const
{
std::string fn = _p.get_problem_dir() + file_name;
std::ofstream fout ( fn.c_str() , std::ios::app );
if ( !fout.fail() ) {
fout.setf ( std::ios::fixed );
fout.precision ( NOMAD::DISPLAY_PRECISION_BB );
display_stats ( false , fout , _p.get_stats_file() , x , feasible , multi_obj );
}
else {
const NOMAD::Display & out = _p.out();
if ( out.get_gen_dd() != NOMAD::NO_DISPLAY && out.get_gen_dd() != NOMAD::MINIMAL_DISPLAY)
out << std::endl
<< "Warning (" << "Evaluator_Control.cpp" << ", " << __LINE__
<< "): could not save information in stats file \'"
<< file_name << "\'" << std::endl << std::endl;
}
fout.close();
}
/*-------------------------------------------------------------------*/
/* display stats during Mads::run() for minimal and normal display */
/*-------------------------------------------------------------------*/
void NOMAD::Evaluator_Control::display_stats
( bool header ,
const NOMAD::Display & out ,
const std::list & stats ,
const NOMAD::Eval_Point * x ,
bool feasible ,
const NOMAD::Point * multi_obj ) const
{
if ( stats.empty() ) {
#ifndef R_VERSION
out << std::endl;
#endif
return;
}
if ( header ) {
#ifndef R_VERSION
out << std::endl;
#endif
}
NOMAD::Double f;
const NOMAD::Point * sol = NULL;
const NOMAD::Point * bbo = NULL;
const NOMAD::Signature * signature = NULL;
int bbe = _stats.get_bb_eval();
int real_time = _stats.get_real_time();
int i;
// this integer is used for the default width display
// of the various stats on the number of evaluations:
int max_bbe = _p.get_max_bb_eval();
if ( _p.get_max_sgte_eval() > max_bbe )
max_bbe = _p.get_max_sgte_eval();
if ( _p.get_max_sim_bb_eval() > max_bbe )
max_bbe = _p.get_max_sim_bb_eval();
if ( _p.get_max_eval() > max_bbe )
max_bbe = _p.get_max_eval();
if ( x )
{
signature = x->get_signature();
f = (feasible) ? x->get_f() : NOMAD::INF;
sol = x;
bbo = &(x->get_bb_outputs());
_last_stats_tag = x->get_tag();
_last_stats_bbe = bbe;
}
std::string s1 , format;
std::list::const_iterator it , end = stats.end();
for ( it = stats.begin() ; it != end ; ++it ) {
if ( it->empty() ) {
#ifndef R_VERSION
out << "\t";
#endif
}
else {
if ( header ) {
#ifndef R_VERSION
s1 = *it;
NOMAD::Display::extract_display_format ( s1 , format );
out << s1;
#endif
}
else {
// get the stats type:
NOMAD::display_stats_type dst
= NOMAD::Display::get_display_stats_type ( *it );
// some stats types are disables in the multi-objective case:
if ( multi_obj &&
( dst == NOMAD::DS_SIM_BBE ||
dst == NOMAD::DS_BBE ||
dst == NOMAD::DS_SGTE ||
dst == NOMAD::DS_EVAL ||
dst == NOMAD::DS_TIME ||
dst == NOMAD::DS_STAT_SUM ||
dst == NOMAD::DS_STAT_AVG ) )
dst = NOMAD::DS_UNDEFINED;
// display the stats:
switch ( dst ) {
case NOMAD::DS_UNDEFINED:
s1 = *it;
NOMAD::Display::extract_display_format ( s1 , format );
out << s1;
break;
case NOMAD::DS_OBJ:
if ( multi_obj )
display_stats_point ( out , stats , it , multi_obj );
else {
#ifdef R_VERSION
{
std::ostringstream oss;
display_stats_real ( oss , f , format );
Rprintf ( "%s" , oss.str().c_str() );
}
#else
display_stats_real ( out , f , format );
#endif
format.clear();
}
break;
case NOMAD::DS_MESH_INDEX:
display_stats_int ( out ,
NOMAD::Mesh::get_mesh_index() ,
10*L_LIMITS ,
format );
format.clear();
break;
case NOMAD::DS_DELTA_M:
case NOMAD::DS_MESH_SIZE:
{
if ( signature ) {
NOMAD::Point delta_m;
signature->get_mesh().get_delta_m ( delta_m ,
NOMAD::Mesh::get_mesh_index() );
display_stats_point ( out , stats , it , &delta_m );
}
else
out << "-";
}
break;
case NOMAD::DS_DELTA_P:
case NOMAD::DS_POLL_SIZE:
{
if ( signature ) {
NOMAD::Point delta_p;
signature->get_mesh().get_delta_p ( delta_p ,
NOMAD::Mesh::get_mesh_index() );
display_stats_point ( out , stats , it , &delta_p );
}
else
out << "-";
}
break;
case NOMAD::DS_SIM_BBE:
display_stats_int ( out , _stats.get_sim_bb_eval() , max_bbe , format );
format.clear();
break;
case NOMAD::DS_BBE:
#ifdef R_VERSION
{
std::ostringstream oss;
display_stats_int ( oss , bbe , max_bbe , format );
Rprintf ( "\t%s " , oss.str().c_str() );
}
#else
{
display_stats_int ( out , bbe , max_bbe , format );
}
#endif
format.clear();
break;
case NOMAD::DS_SGTE:
display_stats_int ( out , _stats.get_sgte_eval() , max_bbe , format );
format.clear();
break;
case NOMAD::DS_EVAL:
display_stats_int ( out , _stats.get_eval() , max_bbe , format );
format.clear();
break;
case NOMAD::DS_TIME:
display_stats_int ( out , real_time , 3600 , format );
format.clear();
break;
case NOMAD::DS_STAT_SUM:
display_stats_real ( out , _stats.get_stat_sum() , format );
format.clear();
break;
case NOMAD::DS_STAT_AVG:
display_stats_real ( out , _stats.get_stat_avg() , format );
format.clear();
break;
case NOMAD::DS_BBO:
display_stats_point ( out , stats , it , bbo );
break;
case NOMAD::DS_SOL:
display_stats_point ( out , stats , it , sol , signature->get_input_type() );
break;
case NOMAD::DS_VAR:
++it;
NOMAD::atoi ( *it , i );
if ( sol )
if (format.empty())
display_stats_type ( out , (*sol)[i] , (signature->get_input_type())[i] );
else
display_stats_real ( out , (*sol)[i] , format );
else
out << "-";
format.clear();
break;
}
}
}
}
if ( !header )
#ifdef R_VERSION
Rprintf("\n");
#else
out << std::endl;
#endif
}
/*-----------------------------------------------------*/
/* display a number with type */
/*-----------------------------------------------------*/
void NOMAD::Evaluator_Control::display_stats_type
( const NOMAD::Display & out ,
const NOMAD::Double & d ,
const NOMAD::bb_input_type & bbType ) const
{
// Default based on bbType
std::string format2;
switch (bbType)
{
case NOMAD::CONTINUOUS:
format2 = "%0." + NOMAD::itos(DISPLAY_PRECISION_STD) + "g";
break;
case NOMAD::INTEGER || NOMAD::BINARY || NOMAD::CATEGORICAL:
format2 = "%i";
break;
default:
break;
}
d.display ( out , format2 );
}
/*-----------------------------------------------------*/
/* display a real with DISPLAY_STATS (or STATS_FILE) */
/*-----------------------------------------------------*/
void NOMAD::Evaluator_Control::display_stats_real
( const NOMAD::Display & out ,
const NOMAD::Double & d ,
const std::string & format ) const
{
if ( format.empty() )
{
std::string format2 = "%0." + NOMAD::itos(DISPLAY_PRECISION_STD) + "g";
d.display ( out , format2 );
}
else
d.display ( out , format );
}
/*---------------------------------------------------------*/
/* display an integer with DISPLAY_STATS (or STATS_FILE) */
/*---------------------------------------------------------*/
void NOMAD::Evaluator_Control::display_stats_int
( const NOMAD::Display & out ,
int i ,
int max_i ,
const std::string & format ) const
{
if ( format.empty() )
out.display_int_w ( i , max_i );
else {
NOMAD::Double d = i;
d.display ( out , format );
}
}
/*---------------------------------------------------------*/
/* display a point with DISPLAY_STATS (or STATS_FILE) */
/*---------------------------------------------------------*/
void NOMAD::Evaluator_Control::display_stats_point
( const NOMAD::Display & out ,
const std::list & display_stats ,
std::list::const_iterator & it ,
const NOMAD::Point * x ,
const std::vector & bbType ) const
{
if ( x )
{
unsigned int n = x->size() , bbn = static_cast(bbType.size());
if ( bbn!=0 && n != bbn )
throw NOMAD::Exception ( "Evaluator_Control.cpp" , __LINE__ ,
"Evaluator_Control::display_stats_point(): bbType and x have different size" );
// s1 is the string displayed befores and after
// one coordinate (it may include format):
std::string s1;
if ( it != display_stats.begin() )
{
s1 = *(--it);
++it;
}
// extract the display format from s1:
std::string format;
if ( !s1.empty() )
NOMAD::Display::extract_display_format ( s1 , format );
// s2 is the string displayed between two coordinates:
std::string s2;
++it;
if ( it != display_stats.end() )
s2 = *it;
else if ( s2.empty() )
--it;
for ( unsigned int i = 0 ; i < n ; ++i )
{
if ( !s1.empty() && i > 0 )
out << s1;
if (bbn!=0 && format.empty())
display_stats_type ( out , (*x)[i] , bbType[i]);
else
display_stats_real (out, (*x)[i] , format );
if ( !s1.empty() )
out << s1;
if ( !s2.empty() && i < n-1 && s2.find("(VNS)")==std::string::npos && s2.find("(PhaseOne)")==std::string::npos && s2.find("(LH)")==std::string::npos && s2.find("(ExtendedPoll)")==std::string::npos )
out << " " << s2;
out << " ";
}
if ( !s2.empty() && (s2.find("(VNS)")!=std::string::npos || s2.find("(PhaseOne)")!=std::string::npos || s2.find("(LH)")!=std::string::npos || s2.find("(ExtendedPoll)")!=std::string::npos))
out << s2;
}
}
/*------------------------------------------*/
/* save the solution file (SOLUTION_FILE) */
/*------------------------------------------*/
void NOMAD::Evaluator_Control::write_solution_file ( const NOMAD::Eval_Point & x,
bool display_bimv) const
{
const std::string & sol_file = _p.get_solution_file();
if ( !sol_file.empty() && ( x.is_feasible ( _p.get_h_min() ) || display_bimv ) )
write_sol_or_his_file ( _p.get_problem_dir() + sol_file , x , true , display_bimv );
}
/*----------------------------------------------*/
/* save the solution file (SOLUTION_FILE) */
/* or update the history file (HISTORY_FILE ) */
/* (private) */
/*----------------------------------------------*/
void NOMAD::Evaluator_Control::write_sol_or_his_file
( const std::string & file_name ,
const NOMAD::Eval_Point & x ,
bool is_sol ,
bool display_bimv ) const
{
// if is_sol == true: save the solution file
// else: update the history file
bool failed = false;
std::ofstream fout;
if ( is_sol )
fout.open ( file_name.c_str() );
else
fout.open ( file_name.c_str() , std::ios::app );
if ( !fout.fail() ) {
fout.setf ( std::ios::fixed );
fout.precision ( NOMAD::DISPLAY_PRECISION_BB );
// solution display:
if ( is_sol )
{
if ( _p.get_bb_input_include_seed() )
fout << _p.get_seed() << std::endl;
if ( _p.get_bb_input_include_tag() )
fout << x.get_tag() << std::endl;
x.Point::display ( fout , "\n" , -1 , -1 );
if (display_bimv)
fout << std::endl << "warning: best infeasible solution (min. violation)";
fout << std::endl;
}
// history display:
else {
x.Point::display ( fout , " " , -1 , -1 );
fout << " ";
x.get_bb_outputs().Point::display ( fout , " " , -1 , -1 );
fout << std::endl;
}
if ( fout.fail() )
failed = true;
}
else
failed = true;
fout.close();
if ( failed && _p.out().get_gen_dd() != NOMAD::NO_DISPLAY && _p.out().get_gen_dd() != NOMAD::MINIMAL_DISPLAY)
_p.out() << std::endl
<< "Warning (" << "Evaluator_Control.cpp" << ", " << __LINE__
<< "): could not "
<< ( is_sol ? "save the current solution" :
"update the history" )
<< " in \'"
<< file_name << "\'" << std::endl << std::endl;
}
/*---------------------------------------------------------*/
/* display evaluation result (private) */
/*---------------------------------------------------------*/
void NOMAD::Evaluator_Control::display_eval_result
( const NOMAD::Eval_Point & x ,
NOMAD::dd_type display_degree ,
NOMAD::search_type search ,
NOMAD::success_type one_eval_success ,
NOMAD::success_type success ) const
{
const NOMAD::Display & out = _p.out();
int cur_bbe;
// surrogate evaluation:
if ( x.get_eval_type() == NOMAD::SGTE )
{
if ( display_degree == NOMAD::FULL_DISPLAY )
{
out << std::endl << "point #" << x.get_tag() << " sgte eval: ";
if ( x.is_eval_ok() )
{
out << "h=";
if ( x.get_h().is_defined() )
out << x.get_h();
else
out << "inf (extr. barrier)";
out << " f=" << x.get_f();
}
else
out << "failed";
out << std::endl;
}
if ( !_p.get_opt_only_sgte() )
return;
cur_bbe = _sgte_cache->size();
}
else
cur_bbe = _cache->size();
const std::string & stats_file_name = _p.get_stats_file_name();
bool feas_x = x.is_feasible ( _p.get_h_min() );
// update the history file:
// (contains surrogate evaluations if opt_only_sgte==true)
const std::string & his_file = _p.get_history_file();
if ( !his_file.empty() && cur_bbe > _last_history_bbe )
{
write_sol_or_his_file ( _p.get_problem_dir() + his_file , x , false );
_last_history_bbe = cur_bbe;
}
// success displays:
if ( one_eval_success != NOMAD::UNSUCCESSFUL &&
one_eval_success >= success )
{
// save the current solution in file:
write_solution_file ( x );
bool ds_ok = ( cur_bbe > _last_stats_bbe ) &&
( _p.get_display_all_eval() ||
( one_eval_success == NOMAD::FULL_SUCCESS && feas_x ) );
// normal display and minimal:
if ( (display_degree == NOMAD::NORMAL_DISPLAY || display_degree == NOMAD::MINIMAL_DISPLAY )&& ds_ok )
display_stats ( false , out , _p.get_display_stats() , &x , feas_x , NULL );
// detailed display:
else if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl << search << " " << one_eval_success
<< " point " << x;
// stats file:
if ( ds_ok && !stats_file_name.empty() )
stats_file ( stats_file_name , &x , feas_x , NULL );
}
else
{
if ( display_degree == NOMAD::FULL_DISPLAY )
{
out << search << " " << one_eval_success
<< " point #" << x.get_tag();
if ( x.is_eval_ok() )
out << " [ h=" << x.get_h()
<< " f=" << x.get_f() << " ]" << std::endl;
else
out << ": evaluation failed" << std::endl;
}
if ( _p.get_display_all_eval() && cur_bbe > _last_stats_bbe )
{
if ( display_degree == NOMAD::NORMAL_DISPLAY || display_degree == NOMAD::MINIMAL_DISPLAY )
display_stats ( false , out , _p.get_display_stats() , &x , feas_x , NULL );
if ( !stats_file_name.empty() )
stats_file ( stats_file_name , &x , feas_x , NULL );
}
}
}
/*-------------------------------------------*/
/* search a point in the cache */
/*-------------------------------------------*/
/* . return true if the point is in cache */
/* . private method */
/*-------------------------------------------*/
bool NOMAD::Evaluator_Control::cache_check
( const NOMAD::Eval_Point *& x ,
NOMAD::Barrier & true_barrier ,
NOMAD::Barrier & sgte_barrier ,
NOMAD::Pareto_Front * pareto_front ,
bool & count_eval ,
const NOMAD::Double & h_max ,
NOMAD::dd_type display_degree ) const
{
NOMAD::eval_type x_eval_type = x->get_eval_type();
const NOMAD::Eval_Point * cache_x = NULL;
// first cache check:
if ( x->is_in_cache() )
cache_x = x;
// second cache check:
else
cache_x = ( ( x->get_eval_type() == NOMAD::TRUTH ) ?
_cache : _sgte_cache )->find ( *x );
// cache hit: transfer some data from x to cache_x:
if ( cache_x ) {
if ( x_eval_type != cache_x->get_eval_type() )
throw NOMAD::Exception ( "Evaluator_Control.cpp" , __LINE__ ,
"Evaluator_Control::cache_check(): eval and cache pts have different eval_type" );
if ( cache_x->is_eval_ok() ) {
NOMAD::Eval_Point * modifiable_cache_x
= &NOMAD::Cache::get_modifiable_point ( *cache_x );
// if wrong number of outputs, reset cache_x._bb_outputs:
{
int m = _p.get_bb_nb_outputs();
if ( cache_x->get_bb_outputs().size() != m )
modifiable_cache_x->set_bb_output ( NOMAD::Point ( m ) );
}
modifiable_cache_x->set_signature ( x->get_signature () );
modifiable_cache_x->set_direction ( x->get_direction () );
modifiable_cache_x->set_mesh_index ( x->get_mesh_index () );
// The point in cache is updated for the poll center to correspond to the new poll center of x (important for poll reduction)
modifiable_cache_x->set_poll_center ( x->get_poll_center () );
modifiable_cache_x->set_poll_center_type ( x->get_poll_center_type () );
modifiable_cache_x->set_user_eval_priority ( x->get_user_eval_priority() );
modifiable_cache_x->set_rand_eval_priority ( x->get_rand_eval_priority() );
#ifdef MODEL_STATS
modifiable_cache_x->set_model_data ( *x );
#endif
// set_f, set_h, and set_EB_ok:
_ev->compute_f ( *modifiable_cache_x );
_ev->compute_h ( *modifiable_cache_x );
}
}
// point in cache but evaluation is to be made again:
if ( cache_x && cache_x->is_eval_ok() &&
( !cache_x->get_f().is_defined() ||
( cache_x->is_EB_ok() &&
!cache_x->get_bb_outputs().is_complete() &&
cache_x->get_h().is_defined() &&
cache_x->get_h() < h_max ) ) ) {
x = cache_x;
cache_x = NULL;
}
// point in cache:
if ( cache_x ) {
_stats.add_cache_hit();
// displays:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
const NOMAD::Display & out = _p.out();
if ( cache_x->get_eval_type() == NOMAD::SGTE )
out << "surrogate ";
out << "cache hit: #" << x->get_tag()
<< " --> #" << cache_x->get_tag() << std::endl;
}
// process the Eval_Point taken in cache:
process_eval_point ( *cache_x ,
( cache_x->get_eval_type() == NOMAD::TRUTH ) ?
true_barrier : sgte_barrier ,
pareto_front );
// count the (simulated) bb eval ?
int index_cnt_eval = _p.get_index_cnt_eval();
if ( index_cnt_eval >= 0 && cache_x->get_bb_outputs()[index_cnt_eval] == 0.0 )
count_eval = false;
x = cache_x;
return true;
}
return false;
}
/*----------------------------------------------------*/
/* eval a point (private) */
/*----------------------------------------------------*/
void NOMAD::Evaluator_Control::eval_point ( NOMAD::Eval_Point & x ,
NOMAD::Barrier & true_barrier ,
NOMAD::Barrier & sgte_barrier ,
NOMAD::Pareto_Front * pareto_front ,
bool & count_eval ,
bool & stop ,
NOMAD::stop_type & stop_reason ,
const NOMAD::Double & h_max )
{
int max_bb_eval = _p.get_max_bb_eval();
int max_sgte_eval = _p.get_max_sgte_eval();
// blackbox or surrogate evaluations are allowed:
if ( ( x.get_eval_type() == NOMAD::TRUTH && max_bb_eval != 0 ) ||
( x.get_eval_type() == NOMAD::SGTE && max_sgte_eval != 0 ) )
{
NOMAD::Eval_Point * eval_x = &NOMAD::Cache::get_modifiable_point ( x );
// get the signature:
NOMAD::Signature * signature = x.get_signature();
if ( !signature )
throw NOMAD::Exception ( "Evaluator_Control.cpp" , __LINE__ ,
"Evaluator_Control::eval_point(): the point has no signature" );
// evaluation of the point:
// ------------------------
bool eval_ok = true;
{
// 1. scaling:
bool do_scaling = signature->get_scaling().is_defined();
if ( do_scaling )
eval_x->scale();
// 2.1. evaluation:
try {
eval_ok = _ev->eval_x ( *eval_x , h_max , count_eval );
}
catch ( ... ) {
eval_ok = false;
}
// 2.2. check the nan's:
if ( eval_ok && eval_x->check_nan() )
eval_ok = false;
// 3. unscaling:
if ( do_scaling )
eval_x->unscale();
}
if ( eval_ok ) {
eval_x->set_eval_status ( NOMAD::EVAL_OK );
// set_f, set_h and set_EB_ok:
_ev->compute_f ( *eval_x );
_ev->compute_h ( *eval_x );
}
else {
eval_x->set_eval_status ( NOMAD::EVAL_FAIL );
_stats.add_failed_eval();
}
// insertion in cache even if is_eval_ok == false:
if ( !x.is_in_cache() )
{
int size_before , size_after;
if ( x.get_eval_type() == NOMAD::SGTE ) {
size_before = _sgte_cache->size();
_sgte_cache->insert(x);
size_after = _sgte_cache->size();
}
else {
size_before = _cache->size();
_cache->insert(x);
size_after = _cache->size();
}
if ( size_after == size_before )
x.set_in_cache ( false );
}
// process the evaluated point:
if ( eval_ok && x.is_in_cache() )
process_eval_point ( *eval_x ,
( eval_x->get_eval_type() == NOMAD::TRUTH ) ?
true_barrier : sgte_barrier ,
pareto_front );
// count the bb evaluation:
if ( count_eval )
{
if ( x.get_eval_type() == NOMAD::SGTE )
_stats.add_sgte_eval();
else
{
// current mads bbe evaluation
_stats.add_bb_eval();
}
}
// count the output stats (STAT_SUM and STAT_AVG):
if ( _p.check_stat_sum() || _p.check_stat_avg() )
{
count_output_stats(x);
// check STAT_SUM_TARGET:
NOMAD::Double sum_target = _p.get_stat_sum_target();
if ( sum_target.is_defined() ) {
NOMAD::Double sum = _stats.get_stat_sum();
if ( !stop && sum.is_defined() && sum >= sum_target ) {
stop = true;
stop_reason = NOMAD::STAT_SUM_TARGET_REACHED;
}
}
}
}
// check the number of blackbox evaluations:
if ( !stop ) {
if ( max_bb_eval > 0 && _stats.get_bb_eval() >= max_bb_eval ) {
stop = true;
stop_reason = NOMAD::MAX_BB_EVAL_REACHED;
}
if ( max_sgte_eval > 0 && _stats.get_sgte_eval() >= max_sgte_eval ) {
stop = true;
stop_reason = NOMAD::MAX_SGTE_EVAL_REACHED;
}
}
}
/*-------------------------------------------*/
/* check stopping criteria (private) */
/*-------------------------------------------*/
void NOMAD::Evaluator_Control::check_stopping_criteria
( NOMAD::search_type search ,
bool count_eval ,
const NOMAD::Eval_Point & x ,
bool & stop ,
NOMAD::stop_type & stop_reason ) const
{
// check the time:
if ( !stop &&
_p.get_max_time() > 0 &&
_stats.get_real_time() >= _p.get_max_time() ) {
stop = true;
stop_reason = NOMAD::MAX_TIME_REACHED;
}
// count an evaluation or a simulated blackbox evaluation:
if ( x.get_eval_type() == NOMAD::TRUTH ) {
_stats.add_eval();
if ( count_eval && !x.get_current_run() )
_stats.add_sim_bb_eval();
}
// check the stopping condition MAX_EVAL:
if ( !stop &&
_p.get_max_eval() > 0 &&
_stats.get_eval() >= _p.get_max_eval() ) {
stop = true;
stop_reason = NOMAD::MAX_EVAL_REACHED;
}
// check the stopping condition MAX_SIM_BB_EVAL:
if ( !stop &&
_p.get_max_sim_bb_eval() > 0 &&
_stats.get_sim_bb_eval() >= _p.get_max_sim_bb_eval() ) {
stop = true;
stop_reason = NOMAD::MAX_SIM_BB_EVAL_REACHED;
}
// check the stopping conditions F_TARGET and FEAS_REACHED
// (for phase one: the evaluations must stop if all EB
// constraints are satisfied, but some PB constraints can
// be violated)
if ( !stop &&
x.is_eval_ok() &&
( _p.get_opt_only_sgte() ||
x.get_eval_type() == NOMAD::TRUTH ) ) {
bool feasible = x.is_feasible ( _p.get_h_min() );
// check FEAS_REACHED:
if ( feasible && _p.get_stop_if_feasible() ) {
stop = true;
stop_reason = NOMAD::FEAS_REACHED;
}
// check F_TARGET:
{
const NOMAD::Point & f_target = _p.get_f_target();
const std::list & index_obj = _p.get_index_obj();
std::list::const_iterator index_obj_end = index_obj.end();
bool check_f_target = f_target.is_defined();
int nb_to_check = (check_f_target) ?
f_target.nb_defined() : 0;
if ( check_f_target && ( feasible || search == NOMAD::LH_SEARCH_P1 ) ) {
const NOMAD::Point & bbo = x.get_bb_outputs();
bool chk = true;
int k = 0;
int cnt = 0;
for ( std::list::const_iterator it = index_obj.begin();
it != index_obj_end ; ++it , ++k ) {
if ( bbo[*it].is_defined() && f_target[k].is_defined() ) {
if ( f_target[k] < bbo[*it] ) {
chk = false;
break;
}
cnt++;
}
}
if ( chk && cnt == nb_to_check ) {
stop = true;
stop_reason = NOMAD::F_TARGET_REACHED;
}
}
}
}
}
/*-------------------------------------------------------*/
/* receive an evaluation result from a slave (private) */
/*-------------------------------------------------------*/
#ifdef USE_MPI
void NOMAD::Evaluator_Control::receive_eval_result
( NOMAD::search_type search ,
NOMAD::Eval_Point * x ,
NOMAD::Barrier & true_barrier ,
NOMAD::Barrier & sgte_barrier ,
NOMAD::Pareto_Front * pareto_front ,
int slave_rank ,
bool & stop ,
NOMAD::stop_type & stop_reason )
{
bool eval_ok , count_eval;
// receive the evaluation result:
_slave->receive_eval_result ( slave_rank , x , eval_ok , count_eval );
// process the evaluation:
if ( eval_ok ) {
// set_f, set_h and set_EB_ok:
_ev->compute_f ( *x );
_ev->compute_h ( *x );
// process the evaluated point:
process_eval_point ( *x ,
(x->get_eval_type()==NOMAD::TRUTH) ?
true_barrier : sgte_barrier ,
pareto_front );
}
else
_stats.add_failed_eval();
// insertion in cache even if !eval_ok:
if ( !x->is_in_cache() )
( ( x->get_eval_type() == NOMAD::SGTE ) ?
_sgte_cache : _cache)->insert ( *x );
// count the bb evaluation:
if ( count_eval ) {
if ( x->get_eval_type() == NOMAD::SGTE )
_stats.add_sgte_eval();
else
_stats.add_bb_eval();
}
// count the output stats (STAT_SUM and STAT_AVG):
if ( _p.check_stat_sum() || _p.check_stat_avg() ) {
count_output_stats ( *x );
// check STAT_SUM_TARGET:
NOMAD::Double sum_target = _p.get_stat_sum_target();
if ( sum_target.is_defined() ) {
NOMAD::Double sum = _stats.get_stat_sum();
if ( !stop && sum.is_defined() && sum >= sum_target ) {
stop = true;
stop_reason = NOMAD::STAT_SUM_TARGET_REACHED;
}
}
}
// check stopping criteria:
if ( !stop ) {
int max_bb_eval = _p.get_max_bb_eval();
int max_sgte_eval = _p.get_max_sgte_eval();
if ( max_bb_eval > 0 && _stats.get_bb_eval() >= max_bb_eval ) {
stop = true;
stop_reason = NOMAD::MAX_BB_EVAL_REACHED;
}
if ( max_sgte_eval > 0 && _stats.get_sgte_eval() >= max_sgte_eval ) {
stop = true;
stop_reason = NOMAD::MAX_SGTE_EVAL_REACHED;
}
}
check_stopping_criteria ( search , count_eval , *x , stop , stop_reason );
}
#endif
/*----------------------------------------------------*/
/* wait for evaluations in progress */
/*----------------------------------------------------*/
#ifdef USE_MPI
void NOMAD::Evaluator_Control::wait_for_evaluations
( NOMAD::search_type search ,
NOMAD::Barrier & true_barrier ,
NOMAD::Barrier & sgte_barrier ,
NOMAD::Pareto_Front * pareto_front ,
bool & stop ,
NOMAD::stop_type & stop_reason ,
NOMAD::success_type & success ,
std::list & evaluated_pts )
{
if ( _nb_in_progress == 0 )
return;
// display degree:
const NOMAD::Display & out = _p.out();
NOMAD::dd_type display_degree = out.get_display_degree ( search );
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< NOMAD::open_block ( "wait for evaluations" );
NOMAD::Barrier & barrier = ( _p.get_opt_only_sgte() ) ?
sgte_barrier : true_barrier;
char signal;
int source;
NOMAD::Eval_Point * eval_x;
NOMAD::success_type one_eval_success;
while ( _nb_in_progress > 0 ) {
source = NOMAD::Slave::receive_signal ( signal );
eval_x = _eval_in_progress[source];
if ( eval_x ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl << "receive eval point #" << eval_x->get_tag()
<< " from slave " << source << std::endl << std::endl;
receive_eval_result ( search ,
eval_x ,
true_barrier ,
sgte_barrier ,
pareto_front ,
source ,
stop ,
stop_reason );
// list of processed points:
if ( eval_x->is_in_cache() )
evaluated_pts.push_back ( eval_x );
// success:
one_eval_success = barrier.get_one_eval_succ();
success = barrier.get_success();
// asynchronous success count:
if ( success == NOMAD::FULL_SUCCESS &&
_elop_tag != _slaves_elop_tags[source] )
_stats.add_asynchronous_success();
// displays:
display_eval_result ( *eval_x ,
display_degree ,
search ,
one_eval_success ,
success );
if ( !_eval_in_progress[source]->is_in_cache() )
delete _eval_in_progress[source];
_eval_in_progress[source] = NULL;
_slaves_elop_tags[source] = -1;
--_nb_in_progress;
// force quit (by pressing ctrl-c):
if ( !stop && NOMAD::Evaluator_Control::_force_quit ) {
stop = true;
stop_reason = NOMAD::CTRL_C;
break;
}
if ( stop && ( stop_reason==NOMAD::ERROR ||
stop_reason==NOMAD::UNKNOWN_STOP_REASON ) )
break;
}
else
NOMAD::Slave::send_signal ( NOMAD::WAIT_SIGNAL , source );
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out.close_block();
}
#endif
/*----------------------------------------------------------------*/
/* check if the evaluation at this point is already in progress */
/* (private) */
/*----------------------------------------------------------------*/
#ifdef USE_MPI
bool NOMAD::Evaluator_Control::already_in_progress
( const NOMAD::Eval_Point & x ) const
{
if ( _eval_in_progress ) {
int x_tag = x.get_tag();
int np = NOMAD::Slave::get_nb_processes();
for ( int i = 0 ; i < np ; ++i )
if ( _eval_in_progress[i] &&
( _eval_in_progress[i]->get_tag() == x_tag ||
_eval_in_progress[i]->Point::operator == ( x ) ) )
return true;
}
return false;
}
#endif
/*----------------------------------------------------------------*/
/* eval_list_of_points, private version (parallel version) */
/*----------------------------------------------------------------*/
#ifdef USE_MPI
void NOMAD::Evaluator_Control::private_eval_list_of_points
( NOMAD::search_type search , // IN : search type
NOMAD::Barrier & true_barrier , // IN/OUT : the barrier
NOMAD::Barrier & sgte_barrier , // IN/OUT : the surrogate barrier
NOMAD::Pareto_Front * pareto_front , // IN/OUT : the Pareto front
// (can be NULL)
bool & stop , // IN/OUT : stopping criterion
NOMAD::stop_type & stop_reason , // OUT : stopping reason
const NOMAD::Eval_Point *& new_feas_inc , // OUT : new feasible incumbent
const NOMAD::Eval_Point *& new_infeas_inc , // OUT : new infeas. incumbent
NOMAD::success_type & success , // OUT : type of success
std::list
& evaluated_pts ) // OUT : list of processed pts
{
if ( stop || _eval_lop.empty() ) {
stop_reason = NOMAD::UNKNOWN_STOP_REASON;
++_elop_tag;
return;
}
evaluated_pts.clear();
// initial display:
const NOMAD::Display & out = _p.out();
NOMAD::dd_type display_degree = out.get_display_degree ( search );
if ( display_degree == NOMAD::FULL_DISPLAY ) {
std::ostringstream msg;
msg << "list of points evaluation (" << search << ")";
out << std::endl << NOMAD::open_block ( msg.str() );
}
// call the Evaluator (virtual) preprocessing of a list of points:
_ev->list_of_points_preprocessing ( _eval_lop );
const NOMAD::Eval_Point * old_feasible_incumbent = NULL;
const NOMAD::Eval_Point * old_infeasible_incumbent = NULL;
// active barrier:
NOMAD::Barrier & barrier = ( _p.get_opt_only_sgte() ) ?
sgte_barrier : true_barrier;
old_feasible_incumbent = barrier.get_best_feasible();
old_infeasible_incumbent = barrier.get_best_infeasible();
NOMAD::Double f0;
if ( _p.get_opportunistic_min_f_imprvmt().is_defined() &&
old_feasible_incumbent )
f0 = old_feasible_incumbent->get_f();
new_feas_inc = NULL;
new_infeas_inc = NULL;
stop = false;
success = NOMAD::UNSUCCESSFUL;
stop_reason = NOMAD::NO_STOP;
const NOMAD::Eval_Point * x;
NOMAD::check_failed_type check_failed_reason;
bool count_eval;
std::vector
to_be_evaluated;
NOMAD::success_type one_eval_success;
bool one_for_luck = false;
bool opp_stop = false;
int init_nb_eval = _stats.get_eval();
int nb_success = 0;
int k = 0;
int nb_points = static_cast ( _eval_lop.size() );
int max_bb_eval = _p.get_max_bb_eval();
// loop #1: search in cache:
// -------------------------
std::set::iterator
it = _eval_lop.begin() ,
end = _eval_lop.end();
while ( !stop && !opp_stop && it != end ) {
x = it->get_point();
x->set_current_run ( true );
// displays:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
// open the evaluation block:
{
std::ostringstream oss;
if ( x->get_eval_type() == NOMAD::SGTE )
oss << "surrogate ";
oss << "evaluation " << k+1 << "/" << nb_points;
out << std::endl << NOMAD::open_block ( oss.str() );
}
out << std::endl << "point #" << x->get_tag() << " ( ";
x->Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
out << " )" << std::endl;
if ( x->get_direction() )
out << "direction : " << *x->get_direction() << std::endl;
if ( x->get_mesh_index() )
out << "mesh index : " << *x->get_mesh_index() << std::endl;
}
// check if the evaluation at this point is already in progress:
if ( !already_in_progress ( *x ) ) {
// current point check (# of bb outputs, bounds, integer values, fixed-vars):
if ( x->check ( _p.get_bb_nb_outputs() , check_failed_reason ) ) {
count_eval = true;
// point in cache:
if ( cache_check ( x ,
true_barrier ,
sgte_barrier ,
pareto_front ,
count_eval ,
barrier.get_h_max() ,
display_degree ) ) {
// list of processed points:
evaluated_pts.push_back ( x );
// check stopping criteria:
check_stopping_criteria ( search , count_eval , *x , stop , stop_reason );
// success:
one_eval_success = barrier.get_one_eval_succ();
success = barrier.get_success();
// displays:
display_eval_result ( *x ,
display_degree ,
search ,
one_eval_success ,
success );
// stop the evaluations (opportunistic strategy) ?
if ( stop_evaluations ( *x ,
search ,
k ,
nb_points ,
stop ,
display_degree ,
one_eval_success ,
success ,
init_nb_eval ,
f0 ,
barrier ,
nb_success ,
one_for_luck ) ) {
_stats.add_interrupted_eval();
opp_stop = true; // will break loop #1
}
// close the evaluation block:
if ( display_degree == NOMAD::FULL_DISPLAY )
out.close_block();
}
// point not in cache (the point is saved for loop #2):
else {
// blackbox or surrogate evaluations are allowed:
if ( ( x->get_eval_type() == NOMAD::TRUTH && max_bb_eval != 0 ) ||
( x->get_eval_type() == NOMAD::SGTE && _p.get_max_sgte_eval() != 0 ) )
to_be_evaluated.push_back ( x );
// close the evaluation block:
if ( display_degree == NOMAD::FULL_DISPLAY )
out.close_block();
}
}
// points[k]->check() failed (close the evaluation block):
else if ( display_degree == NOMAD::FULL_DISPLAY ) {
std::ostringstream oss;
oss << "check failed (" << check_failed_reason << ")";
out.close_block ( oss.str() );
}
}
// evaluation already in progress (close the evaluation block):
else if ( display_degree == NOMAD::FULL_DISPLAY ) {
std::ostringstream oss;
oss << "evaluation of point #" << x->get_tag()
<< " already in progress";
out.close_block ( oss.str() );
}
++it;
++k;
// force quit (by pressing ctrl-c):
if ( !stop && NOMAD::Evaluator_Control::_force_quit ) {
stop = true;
stop_reason = NOMAD::CTRL_C;
}
} // end of loop #1
// --------------
// loop #2: evaluations:
// ---------------------
int nb_to_evaluate = static_cast ( to_be_evaluated.size() );
int nb_evaluated = 0;
int cur = 0;
int source;
char signal;
NOMAD::Eval_Point * eval_x;
while ( !stop && !opp_stop && nb_evaluated < nb_to_evaluate ) {
source = NOMAD::Slave::receive_signal ( signal );
// 2.1: send the RESULT signal, receive and process the evaluation result:
// -----------------------------------------------------------------------
eval_x = _eval_in_progress[source];
if ( eval_x ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl << "receive eval point #" << eval_x->get_tag()
<< " from slave " << source << std::endl << std::endl;
receive_eval_result ( search ,
eval_x ,
true_barrier ,
sgte_barrier ,
pareto_front ,
source ,
stop ,
stop_reason );
// list of processed points:
if ( eval_x->is_in_cache() )
evaluated_pts.push_back ( eval_x );
// success:
one_eval_success = barrier.get_one_eval_succ();
success = barrier.get_success();
// asynchronous success count:
if ( success == NOMAD::FULL_SUCCESS &&
_elop_tag != _slaves_elop_tags[source] )
_stats.add_asynchronous_success();
// displays:
display_eval_result ( *eval_x ,
display_degree ,
search ,
one_eval_success ,
success );
// stop the evaluations (opportunistic strategy) ?
if ( stop_evaluations ( *eval_x ,
search ,
nb_evaluated ,
nb_to_evaluate ,
stop ,
display_degree ,
one_eval_success ,
success ,
init_nb_eval ,
f0 ,
barrier ,
nb_success ,
one_for_luck ) ) {
_stats.add_interrupted_eval();
opp_stop = true; // will break loop #2
}
_eval_in_progress[source] = NULL;
_slaves_elop_tags[source] = -1;
--_nb_in_progress;
++nb_evaluated;
}
// 2.2: send the EVAL signal and launch a new evaluation:
// ------------------------------------------------------
else {
// do not launch a new evaluation if...
// there is no more points to be evaluated:
if ( cur == nb_to_evaluate )
NOMAD::Slave::send_signal ( NOMAD::WAIT_SIGNAL , source );
// or if bbe+_nb_in_progress >= max_bb_eval:
else if ( to_be_evaluated[cur]->get_eval_type() == NOMAD::TRUTH &&
max_bb_eval > 0 &&
_stats.get_bb_eval() + _nb_in_progress >= max_bb_eval ) {
stop = true;
stop_reason = NOMAD::MAX_BB_EVAL_REACHED;
NOMAD::Slave::send_signal ( NOMAD::WAIT_SIGNAL , source );
}
else {
// get the signature:
NOMAD::Signature * signature = to_be_evaluated[cur]->get_signature();
// there is no signature (error):
if ( !signature ) {
stop = true;
stop_reason = NOMAD::ERROR;
if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
out << std::endl
<< "Error in Evaluator_Control::private_eval_list_of_points():"
<< " the point #" << to_be_evaluated[cur]->get_tag()
<< " has no signature" << std::endl << std::endl;
NOMAD::Slave::send_signal ( NOMAD::WAIT_SIGNAL , source );
}
else {
NOMAD::Slave::send_signal ( NOMAD::EVAL_SIGNAL , source );
eval_x = &NOMAD::Cache::get_modifiable_point ( *to_be_evaluated[cur++] );
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< "send eval point #" << eval_x->get_tag()
<< " to slave " << source << std::endl;
// 1. scaling:
bool do_scaling = signature->get_scaling().is_defined();
if ( do_scaling )
eval_x->scale();
// 2. send the point:
_slave->send_eval_point ( eval_x , source , barrier.get_h_max() );
// 3. unscaling:
if ( do_scaling )
eval_x->unscale();
eval_x->set_eval_status ( NOMAD::EVAL_IN_PROGRESS );
_eval_in_progress[source] = eval_x;
_slaves_elop_tags[source] = _elop_tag;
++_nb_in_progress;
}
}
}
// force quit (by pressing ctrl-c):
if ( !stop && NOMAD::Evaluator_Control::_force_quit ) {
stop = true;
stop_reason = NOMAD::CTRL_C;
}
} // end of loop #2
// --------------
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< "number of evaluations in progress: " << _nb_in_progress
<< std::endl << std::endl;
// the algorithm is not asynchronous: we have
// to wait for all the evaluations in progress:
if ( !_p.get_asynchronous() )
wait_for_evaluations ( search ,
true_barrier ,
sgte_barrier ,
pareto_front ,
stop ,
stop_reason ,
success ,
evaluated_pts );
// barriers update:
if ( !stop ) {
true_barrier.update_and_reset_success();
sgte_barrier.update_and_reset_success();
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << NOMAD::close_block ( "end of evaluations" ) << std::endl;
// incumbents update:
const NOMAD::Eval_Point * bf = barrier.get_best_feasible ();
const NOMAD::Eval_Point * bi = barrier.get_best_infeasible();
if ( bf && bf != old_feasible_incumbent )
new_feas_inc = bf;
if ( bi && bi != old_infeasible_incumbent )
new_infeas_inc = bi;
// the list of eval. points is deleted (only points in the cache are kept):
clear_eval_lop();
// update the unique eval_lop() tag:
++_elop_tag;
} // end of eval_lop() parallel version
/*----------------------------------------------------------------*/
/* eval_list_of_points, private version (scalar version) */
/*----------------------------------------------------------------*/
#else
void NOMAD::Evaluator_Control::private_eval_list_of_points
( NOMAD::search_type search , // IN : search type
NOMAD::Barrier & true_barrier , // IN/OUT : the barrier
NOMAD::Barrier & sgte_barrier , // IN/OUT : the surrogate barrier
NOMAD::Pareto_Front * pareto_front , // IN/OUT : the Pareto front
// (can be NULL)
bool & stop , // IN/OUT : stopping criterion
NOMAD::stop_type & stop_reason , // OUT : stopping reason
const NOMAD::Eval_Point *& new_feas_inc , // OUT : new feasible incumbent
const NOMAD::Eval_Point *& new_infeas_inc , // OUT : new infeas. incumbent
NOMAD::success_type & success , // OUT : type of success
std::list
& evaluated_pts ) // OUT : list of processed pts
{
if ( stop || _eval_lop.empty() )
{
stop_reason = NOMAD::UNKNOWN_STOP_REASON;
return;
}
evaluated_pts.clear();
// initial display:
const NOMAD::Display & out = _p.out();
NOMAD::dd_type display_degree = out.get_display_degree ( search );
if ( display_degree == NOMAD::FULL_DISPLAY )
{
std::ostringstream oss;
oss << "list of points evaluation (" << search << ")";
out << std::endl << NOMAD::open_block ( oss.str() );
}
// call the Evaluator (virtual) preprocessing of a list of points:
_ev->list_of_points_preprocessing ( _eval_lop );
const NOMAD::Eval_Point * old_feasible_incumbent = NULL;
const NOMAD::Eval_Point * old_infeasible_incumbent = NULL;
// active barrier:
NOMAD::Barrier & barrier = ( _p.get_opt_only_sgte() ) ? sgte_barrier : true_barrier;
old_feasible_incumbent = barrier.get_best_feasible();
old_infeasible_incumbent = barrier.get_best_infeasible();
NOMAD::Double f0;
if ( _p.get_opportunistic_min_f_imprvmt().is_defined() &&
old_feasible_incumbent )
f0 = old_feasible_incumbent->get_f();
new_feas_inc = NULL;
new_infeas_inc = NULL;
stop = false;
success = NOMAD::UNSUCCESSFUL;
stop_reason = NOMAD::NO_STOP;
const NOMAD::Eval_Point * x;
NOMAD::check_failed_type check_failed_reason;
bool count_eval;
bool one_for_luck = false;
bool stop_evals = false;
int init_nb_eval = _stats.get_eval();
int nb_success = 0;
int k = 0;
int nb_points = get_nb_eval_points();
// main loop (on the list of points):
// ----------------------------------
std::set::iterator it = _eval_lop.begin() , end = _eval_lop.end();
while ( !stop_evals && !stop && it != end )
{
x = it->get_point();
x->set_current_run ( true );
// displays:
if ( display_degree == NOMAD::FULL_DISPLAY )
{
{
// open the evaluation block:
std::ostringstream oss;
if ( x->get_eval_type() == NOMAD::SGTE )
oss << "surrogate ";
oss << "evaluation " << k+1 << "/" << nb_points;
out << std::endl << NOMAD::open_block ( oss.str() );
}
out << std::endl << "point #" << x->get_tag() << " ( ";
x->Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
out << " )" << std::endl;
if ( x->get_direction() )
out << "direction : " << *x->get_direction() << std::endl;
if ( x->get_mesh_index() )
out << "mesh index : " << *x->get_mesh_index() << std::endl;
out << std::endl;
}
// current point check (# of bb outputs, bounds, integer values, fixed-vars):
if ( x->check ( _p.get_bb_nb_outputs() , check_failed_reason ) )
{
count_eval = true;
bool has_been_in_cache=cache_check ( x ,
true_barrier ,
sgte_barrier ,
pareto_front ,
count_eval ,
barrier.get_h_max() ,
display_degree );
// search in cache or eval the point:
if ( !has_been_in_cache )
{
eval_point ( NOMAD::Cache::get_modifiable_point ( *x ) ,
true_barrier ,
sgte_barrier ,
pareto_front ,
count_eval ,
stop ,
stop_reason ,
barrier.get_h_max() );
}
// check stopping criteria:
check_stopping_criteria ( search , count_eval , *x , stop , stop_reason );
// success:
NOMAD::success_type one_eval_success = barrier.get_one_eval_succ();
success = barrier.get_success();
// list of processed points:
if ( x->is_in_cache() )
evaluated_pts.push_back ( x );
else
{
// this situation may occur on very thin meshes:
// the point has not been found in the cache
// and it failed to be inserted.
one_eval_success = NOMAD::UNSUCCESSFUL;
}
// displays:
if ( ! has_been_in_cache || display_degree!=NOMAD::MINIMAL_DISPLAY)
display_eval_result ( *x, display_degree, search, one_eval_success, success );
// stop the evaluations (opportunistic strategy) ?
if ( stop_evaluations ( *x ,
search ,
k ,
nb_points ,
stop ,
display_degree ,
one_eval_success ,
success ,
init_nb_eval ,
f0 ,
barrier ,
nb_success ,
one_for_luck ) )
{
_stats.add_interrupted_eval();
stop_evals = true;
}
}
// points[k]->check() failed:
else if ( display_degree == NOMAD::FULL_DISPLAY )
out << "check failed (" << check_failed_reason << ")" << std::endl;
// close the evaluation block:
if ( display_degree == NOMAD::FULL_DISPLAY )
out << NOMAD::close_block();
++it;
++k;
// force quit (by pressing ctrl-c):
if ( !stop && NOMAD::Evaluator_Control::_force_quit )
{
stop = true;
stop_reason = NOMAD::CTRL_C;
}
} // end of main loop
// ----------------
// barriers update:
if ( !stop )
{
true_barrier.update_and_reset_success();
sgte_barrier.update_and_reset_success();
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl << NOMAD::close_block ( "end of evaluations" )
<< std::endl;
// incumbents update:
const NOMAD::Eval_Point * bf = barrier.get_best_feasible ();
const NOMAD::Eval_Point * bi = barrier.get_best_infeasible();
if ( bf && bf != old_feasible_incumbent )
new_feas_inc = bf;
if ( bi && bi != old_infeasible_incumbent )
new_infeas_inc = bi;
// the list of eval. points is deleted (only points in the cache are kept):
clear_eval_lop();
} // end of eval_lop() scalar version
#endif
/*-------------------------------------------------*/
/* reduce the list of evaluation points */
/*-------------------------------------------------*/
void NOMAD::Evaluator_Control::reduce_eval_lop ( int n )
{
int nb_eval_pts = get_nb_eval_points();
if ( n < 0 || n >= nb_eval_pts )
return;
const NOMAD::Eval_Point * x;
std::set::iterator it = _eval_lop.end();
--it;
while ( get_nb_eval_points() > n ) {
x = it->get_point();
if ( x && !x->is_in_cache() && x->get_eval_status() != NOMAD::EVAL_IN_PROGRESS )
delete x;
_eval_lop.erase ( it-- );
}
}
/*-------------------------------------------------*/
/* TGP model ordering (private) */
/*-------------------------------------------------*/
void NOMAD::Evaluator_Control::TGP_model_ordering ( NOMAD::dd_type display_degree ,
bool & modified_list )
{
modified_list = false;
if ( _p.get_opt_only_sgte() )
return;
#ifdef USE_TGP
// display:
const NOMAD::Display & out = _p.out();
// model stats:
NOMAD::Model_Stats model_stats;
NOMAD::Clock clock;
#ifdef TGP_DEBUG
out << std::endl << NOMAD::open_block ( "TGP model ordering") << std::endl;
#endif
const std::vector & bbot = _p.get_bb_output_type();
int i , j , n_XX = 0 , m = bbot.size();
// construct prediction set (XX):
// ------------------------------
std::vector XX;
NOMAD::Point lb_XX , ub_XX;
// save _eval_lop in XX and other_pts:
const NOMAD::Eval_Point * x;
std::list other_pts;
const NOMAD::Signature * signature = NULL;
int n = -1;
std::set::const_iterator it , end = _eval_lop.end();
for ( it = _eval_lop.begin() ; it != end ; ++it ) {
x = it->get_point();
if ( n < 0 ) {
signature = x->get_signature();
if ( !signature ) {
#ifdef TGP_DEBUG
out << NOMAD::close_block ( "failure (no signature)" ) << std::endl;
#endif
return;
}
n = signature->get_n();
lb_XX = ub_XX = NOMAD::Point(n);
}
if ( x->size () == n &&
x->get_m () == m &&
x->get_eval_type () == NOMAD::TRUTH &&
!x->get_bb_outputs().is_defined() ) {
XX.push_back ( &NOMAD::Cache::get_modifiable_point ( *x ) );
for ( i = 0 ; i < n ; ++i ) {
if ( !lb_XX[i].is_defined() || (*x)[i] < lb_XX[i] )
lb_XX[i] = (*x)[i];
if ( !ub_XX[i].is_defined() || (*x)[i] > ub_XX[i] )
ub_XX[i] = (*x)[i];
}
}
else
other_pts.push_back ( x );
}
n_XX = XX.size();
if ( n_XX <= 1 ) {
#ifdef TGP_DEBUG
out << NOMAD::close_block ( "failure (size(XX) <= 1)" ) << std::endl;
#endif
return;
}
// the TGP model:
NOMAD::TGP_Model * model;
// Reuse the last TGP model from the TGP model search:
if ( _last_TGP_model && _p.get_model_tgp_reuse_model() ) {
model = _last_TGP_model;
// individual predictions for XX points:
for ( i = 0 ; i < n_XX ; ++i )
if ( !model->predict ( *XX[i] , false ) ) // pred_outside_bnds = false
for ( j = 0 ; j < m ; ++j )
XX[i]->set_bb_output ( j , NOMAD::Double() );
}
// creation of a new TGP model:
else {
model = new NOMAD::TGP_Model ( n , bbot , out , _p.get_model_tgp_mode() );
NOMAD::Point center(n);
for ( i = 0 ; i < n ; ++i )
center[i] = ( lb_XX[i] + ub_XX[i] ) / 2.0;
// construct interpolation set (X):
// --------------------------------
if ( !model->set_X ( *_cache ,
¢er ,
_p.get_seed() ,
true ) ) { // remove_fv = true
if ( model->get_p() <= model->get_n() )
model_stats.add_not_enough_pts();
#ifdef TGP_DEBUG
out << NOMAD::close_block ( "failure: " + model->get_error_str() )
<< std::endl;
#endif
delete model;
return;
}
int p = model->get_p();
// display sets X and XX:
// ----------------------
#ifdef TGP_DEBUG
{
// max number of points displayed:
const int set_display_limit = 15; // set to -1 for no limit
// X:
model->display_X ( out , set_display_limit );
// XX:
out << NOMAD::open_block ( "prediction points (XX)");
for ( i = 0 ; i < n_XX ; ++i ) {
out << "#";
out.display_int_w ( i , n_XX );
out << " x=(";
XX[i]->NOMAD::Point::display ( out , " " , 15 , -1 );
out << " )" << std::endl;
}
std::ostringstream oss;
oss << "(size=" << n_XX << ")";
out << NOMAD::close_block ( oss.str() ) << std::endl;
}
#endif
// TGP model construction:
// -----------------------
#ifdef TGP_DEBUG
out << "TGP model construction ...";
out.flush();
#endif
if ( !model->compute ( XX ,
false , // compute_Ds2x = false
false , // compute_improv = false
false ) ) { // pred_outside_bnds = false
model_stats.add_construction_error();
#ifdef TGP_DEBUG
out << "... error: " << model->get_error_str() << std::endl
<< NOMAD::close_block() << std::endl;
#endif
// reset XX outputs:
for ( i = 0 ; i < n_XX ; ++i )
for ( j = 0 ; j < m ; ++j )
XX[i]->set_bb_output ( j , NOMAD::Double() );
delete model;
// check if ctrl-c has been pressed:
if ( NOMAD::TGP_Output_Model::get_force_quit() )
NOMAD::Evaluator_Control::_force_quit = true;
return;
}
#ifdef TGP_DEBUG
out << "... OK" << std::endl << std::endl;
#endif
// update model stats:
model_stats.add_construction_time ( clock.get_CPU_time() );
model_stats.update_nY ( p );
model_stats.update_ES_stats ( n_XX , n_XX );
model_stats.add_nb_truth();
model_stats.add_nb_TGP();
}
// open display block for model predictions:
#ifdef TGP_DEBUG
out << NOMAD::open_block ( "TGP predictions (XX+ZZ)");
#endif
// clear then fill _eval_lop again:
// --------------------------------
NOMAD::Double f_model , h_model;
const NOMAD::Double & h_min = _p.get_h_min();
NOMAD::hnorm_type h_norm = _p.get_h_norm();
bool snap_to_bounds = _p.get_snap_to_bounds();
modified_list = true;
_eval_lop.clear();
for ( i = 0 ; i < n_XX ; ++i ) {
// compute model h and f values:
model->eval_hf ( XX[i]->get_bb_outputs() ,
h_min ,
h_norm ,
h_model ,
f_model );
// display model predictions:
#ifdef TGP_DEBUG
out << "#";
out.display_int_w ( i , n_XX );
out << " x=(";
XX[i]->NOMAD::Point::display ( out , " " , 15 , -1 );
out << " ) m(x)=[";
XX[i]->get_bb_outputs().display ( out , " " , 15 , -1 );
out << " ]";
if ( h_model.is_defined() && f_model.is_defined() )
out << " hm=" << std::setw(15) << h_model
<< " fm=" << std::setw(15) << f_model;
else
out << " no model value";
out << std::endl;
#endif
// add the evaluation point:
add_eval_point ( XX[i] ,
display_degree ,
snap_to_bounds ,
NOMAD::Double() ,
NOMAD::Double() ,
f_model ,
h_model );
#ifdef MODEL_STATS
if ( XX[i] && f_model.is_defined() && h_model.is_defined() ) {
XX[i]->set_mod_use ( 2 ); // 2 for model ordering
XX[i]->set_Yw ( model->get_Yw () );
XX[i]->set_nY ( p );
XX[i]->set_mh ( h_model );
XX[i]->set_mf ( f_model );
}
#endif
}
#ifdef TGP_DEBUG
{
// close display block for model predictions:
std::ostringstream oss;
oss << "(size=" << n_XX << ")";
out << NOMAD::close_block ( oss.str() ) << std::endl;
// compute and display prediction errors:
out << NOMAD::open_block ( "prediction relative errors on X(%)" );
model->display_X_errors ( out );
out << NOMAD::close_block() << std::endl;
}
#endif
// other points that have been previously discarded and have no model values:
NOMAD::Eval_Point * y;
std::list::const_iterator it2 , end2 = other_pts.end();
for ( it2 = other_pts.begin() ; it2 != end2 ; ++it2 ) {
y = &NOMAD::Cache::get_modifiable_point (**it2);
add_eval_point ( y ,
display_degree ,
snap_to_bounds ,
NOMAD::Double() ,
NOMAD::Double() ,
NOMAD::Double() ,
NOMAD::Double() );
}
_stats.update_model_stats ( model_stats );
_model_ordering_stats.update ( model_stats );
if ( model != _last_TGP_model )
delete model;
#ifdef TGP_DEBUG
out << NOMAD::close_block() << std::endl;
#else
if ( display_degree == NOMAD::FULL_DISPLAY ) {
out << std::endl << "model ordering";
if ( !modified_list )
out << " (no modification)";
out << std::endl;
}
#endif
#endif
}
/*-------------------------------------------------*/
/* model_np1_quad_epsilon (private) */
/*-------------------------------------------------*/
void NOMAD::Evaluator_Control::quad_model_ordering ( NOMAD::dd_type display_degree ,
bool & modified_list )
{
const NOMAD::Display & out = _p.out();
#ifdef DEBUG
out << std::endl << NOMAD::open_block ( "model_np1_quad_epsilon") << std::endl;
#endif
// save _eval_lop in pts and other_pts:
// ------------------------------------
NOMAD::Point min , max , center , interpolation_radius;
const NOMAD::Eval_Point * y;
std::list pts , other_pts;
const NOMAD::Signature * signature = NULL;
const NOMAD::Double & radius_factor = _p.get_model_quad_radius_factor();
NOMAD::eval_type ev_type = NOMAD::TRUTH;
int i , n = -1;
std::set::const_iterator it , end = _eval_lop.end();
for ( it = _eval_lop.begin() ; it != end ; ++it )
{
y = it->get_point();
if ( n < 0 )
{
signature = y->get_signature();
if ( !signature )
{
#ifdef DEBUG
out << NOMAD::close_block ( "failure (no signature)" ) << std::endl;
#endif
modified_list = false;
return;
}
n = signature->get_n();
ev_type = y->get_eval_type();
min.resize ( n );
max.resize ( n );
center.resize ( n );
interpolation_radius.resize ( n );
}
if ( y->size() == n && y->get_eval_type() == ev_type ) {
pts.push_back(y);
for ( i = 0 ; i < n ; ++i ) {
if ( !min[i].is_defined() || (*y)[i] < min[i] )
min[i] = (*y)[i];
if ( !max[i].is_defined() || (*y)[i] > max[i] )
max[i] = (*y)[i];
}
}
else
other_pts.push_back ( y );
}
for ( i = 0 ; i < n ; ++i )
{
center [i] = ( min[i] + max[i] ) / 2.0;
interpolation_radius[i] = ( max[i] - min[i] ) * radius_factor / 2.0;
}
#ifdef DEBUG
out << NOMAD::open_block ( "points used to define interpolation radius")
<< "type of eval. : " << ev_type << std::endl
<< "number of points: " << pts.size() << std::endl
<< "min. coordinates: ( ";
min.display ( out , " " , 2 );
out << " )" << std::endl
<< "max. coordinates: ( ";
max.display ( out , " " , 2 );
out << " )" << std::endl
<< "center : ( ";
center.display ( out , " " , 2 );
out << " )" << std::endl
<< "interp. radius : ( ";
interpolation_radius.display ( out , " " , 2 );
out << " )" << std::endl
<< NOMAD::close_block() << std::endl;
#endif
// create model:
// -------------
NOMAD::Clock clock;
NOMAD::Model_Stats model_stats;
NOMAD::Quad_Model model ( out ,
_p.get_bb_output_type() ,
(ev_type==NOMAD::TRUTH) ? *_cache : *_sgte_cache ,
*signature );
int max_Y_size = _p.get_model_quad_max_Y_size();
int min_Y_size = _p.get_model_quad_min_Y_size();
bool use_WP = _p.get_model_quad_use_WP ();
// construct interpolation set Y:
model.construct_Y ( center ,
interpolation_radius ,
max_Y_size );
int nY = model.get_nY();
#ifdef DEBUG
out << "number of points in Y: " << nY
<< " (p=" << nY-1;
if ( nY < 2 ) out << ", not enough";
out << ")" << std::endl;
#endif
// not enough points:
if ( nY < 2 )
{
modified_list = false;
model_stats.add_not_enough_pts();
}
else
{
#ifdef DEBUG
out << std::endl;
model.display_Y ( out , "unscaled interpolation set Y" );
#endif
// define scaling:
model.define_scaling ( radius_factor );
#ifdef DEBUG
out << std::endl;
model.display_Y ( out , "scaled interpolation set Ys" );
#endif
// model error flag:
if ( model.get_error_flag() )
{
model_stats.add_construction_error();
modified_list = false;
}
else
{
// not enough points:
if ( nY < 2 || ( min_Y_size < 0 && nY <= model.get_nfree() ) )
{
model_stats.add_not_enough_pts();
modified_list = false;
}
// enough points and no error:
else
{
bool cautious = _p.get_model_eval_sort_cautious();
int nb_inside_radius = 0;
// check that there is at least two trial points inside the trust radius
// (cautious strategy):
nb_inside_radius = 0;
std::list::const_iterator it2 , end2 = pts.end();
if ( cautious )
{
for ( it2 = pts.begin() ; it2 != end2 ; ++it2 )
{
NOMAD::Point scaled_pt ( **it2 );
model.scale ( scaled_pt );
if ( model.is_within_trust_radius ( scaled_pt ) )
{
if ( ++nb_inside_radius == 2 )
break;
}
}
}
// not enough points inside trust radius:
if ( cautious && nb_inside_radius < 2 )
modified_list = false;
// at least two trial points are inside trust radius:
else
{
// construct model:
// ----------------
model.construct ( use_WP , NOMAD::SVD_EPS , NOMAD::SVD_MAX_MPN , max_Y_size );
model_stats.add_construction_time ( clock.get_CPU_time() );
model_stats.update_nY ( model.get_nY() );
// display model characteristics:
#ifdef DEBUG
out << std::endl;
model.display_model_coeffs ( out );
out << std::endl;
model.display_Y_error ( out );
#endif
// count model:
if ( ev_type == NOMAD::TRUTH )
model_stats.add_nb_truth();
else
model_stats.add_nb_sgte();
switch ( model.get_interpolation_type() )
{
case NOMAD::MFN:
model_stats.add_nb_MFN();
break;
case NOMAD::WP_REGRESSION:
model_stats.add_nb_WP_regression();
break;
case NOMAD::REGRESSION:
model_stats.add_nb_regression();
break;
default:
break;
}
// check model error flag:
const NOMAD::Double & cond = model.get_cond();
if ( model.get_error_flag() ||
!cond.is_defined() ||
cond > NOMAD::SVD_MAX_COND )
{
modified_list = false;
if ( model.get_error_flag() )
model_stats.add_construction_error();
else
model_stats.add_bad_cond();
}
else
{
// clear then fill _eval_lop again:
// --------------------------------
NOMAD::Double f_model , h_model;
NOMAD::Eval_Point * x;
bool snap_to_bounds = _p.get_snap_to_bounds();
modified_list = true;
_eval_lop.clear();
nb_inside_radius = 0;
#ifdef DEBUG
out << std::endl << NOMAD::open_block ( "original trial points" );
#endif
NOMAD::Quad_Model_Evaluator *quad_model_ev=new NOMAD::Quad_Model_Evaluator(_p , model);
for ( it2 = pts.begin() ; it2 != end2 ; ++it2 )
{
NOMAD::Point scaled_pt ( **it2 );
model.scale ( scaled_pt );
f_model.clear();
h_model.clear();
if ( !cautious || model.is_within_trust_radius ( scaled_pt ) )
{
int m = static_cast(_p.get_bb_output_type().size());
NOMAD::Eval_Point x_eval(scaled_pt,m);
for (int i = 0 ; i < x_eval.size() ; ++i )
x_eval[i] = scaled_pt[i].value() * 1000.0;
bool count_eval;
bool success=quad_model_ev->eval_x(x_eval,0.0,count_eval);
if (success)
{
_ev->compute_f(x_eval);
_ev->compute_h(x_eval);
f_model=x_eval.get_f();
h_model=x_eval.get_h();
}
++nb_inside_radius;
}
x = &NOMAD::Cache::get_modifiable_point (**it2);
#ifdef DEBUG
x->display_tag ( out );
out << ": ( ";
x->NOMAD::Point::display ( out , " " , 2 );
out << " ) scaled: (";
scaled_pt.NOMAD::Point::display ( out , " " , 2 );
out << ") ";
if ( h_model.is_defined() && f_model.is_defined() )
out << "hm=" << h_model << " fm=" << f_model;
else
out << "no model value";
out << std::endl;
#endif
// add the evaluation point:
add_eval_point ( x ,
display_degree ,
snap_to_bounds ,
NOMAD::Double() ,
NOMAD::Double() ,
f_model ,
h_model );
#ifdef MODEL_STATS
if ( x && f_model.is_defined() && h_model.is_defined() )
{
x->set_mod_use ( 2 ); // 2 for model ordering
x->set_cond ( model.get_cond() );
x->set_Yw ( model.get_Yw () );
x->set_nY ( model.get_nY () );
x->set_mh ( h_model );
x->set_mf ( f_model );
}
#endif
}
delete quad_model_ev;
// other points that have been previously discarded
// and have no model values:
end2 = other_pts.end();
for ( it2 = other_pts.begin() ; it2 != end2 ; ++it2 )
{
x = &NOMAD::Cache::get_modifiable_point (**it2);
#ifdef DEBUG
x->display_tag ( out );
out << ": ( ";
x->NOMAD::Point::display ( out , " " , 2 );
out << " ) no model value" << std::endl;
#endif
add_eval_point ( x ,
display_degree ,
snap_to_bounds ,
NOMAD::Double() ,
NOMAD::Double() ,
NOMAD::Double() ,
NOMAD::Double() );
}
#ifdef DEBUG
out.close_block();
#endif
}
}
model_stats.update_ES_stats ( nb_inside_radius , static_cast(pts.size()) );
}
}
}
_stats.update_model_stats ( model_stats );
_model_ordering_stats.update ( model_stats );
#ifdef DEBUG
out << NOMAD::close_block() << std::endl;
#else
if ( display_degree == NOMAD::FULL_DISPLAY )
{
out << std::endl << "model ordering";
if ( !modified_list )
out << " (no modification)";
out << std::endl;
}
#endif
}
/*----------------------------------------------------------------------------------*/
/* evaluation of a list of points (public version that calls the private version) */
/*----------------------------------------------------------------------------------*/
void NOMAD::Evaluator_Control::eval_list_of_points
( NOMAD::search_type search , // IN : search type
NOMAD::Barrier & true_barrier , // IN/OUT: truth barrier
NOMAD::Barrier & sgte_barrier , // IN/OUT: surrogate barrier
NOMAD::Pareto_Front * pareto_front , // IN/OUT: Pareto front
// (can be NULL)
bool & stop , // IN/OUT: stopping criterion
NOMAD::stop_type & stop_reason , // OUT : stopping reason
const NOMAD::Eval_Point *& new_feas_inc , // OUT : new feas. incumbent
const NOMAD::Eval_Point *& new_infeas_inc , // OUT : new infeas. incumb.
NOMAD::success_type & success , // OUT : type of success
std::list
* evaluated_pts ) // OUT : list of processed
// pts (can be NULL)
{
bool del_evaluated_pts = false;
if ( !evaluated_pts )
{
evaluated_pts = new std::list;
del_evaluated_pts = true;
}
bool sgte_eval_sort = _p.get_sgte_eval_sort() && _eval_lop.size() > 1;
bool opt_only_sgte = _p.get_opt_only_sgte ();
bool snap_to_bounds = _p.get_snap_to_bounds();
bool modified_list = false;
const NOMAD::Display & out = _p.out();
NOMAD::dd_type display_degree = out.get_display_degree ( search );
// reset the success type:
true_barrier.reset_success();
sgte_barrier.reset_success();
// define all points as surrogates:
if ( opt_only_sgte || sgte_eval_sort )
{
for ( std::set::iterator it = _eval_lop.begin() ;
it != _eval_lop.end() ; ++it )
NOMAD::Cache::get_modifiable_point(*it->get_point()).set_eval_type(NOMAD::SGTE);
}
// use the surrogates to sort the eval. points:
if ( !opt_only_sgte && sgte_eval_sort )
{
// evaluate the surrogate:
private_eval_list_of_points ( search ,
true_barrier ,
sgte_barrier ,
NULL , // Pareto front = NULL
stop ,
stop_reason ,
new_feas_inc ,
new_infeas_inc ,
success ,
*evaluated_pts );
if ( stop )
{
if ( del_evaluated_pts )
delete evaluated_pts;
return;
}
NOMAD::Eval_Point * x;
// construct a new list of trial points that will be
// ordered using surrogate values:
std::list::const_iterator
end = evaluated_pts->end() , it2;
for ( it2 = evaluated_pts->begin() ; it2 != end ; ++it2 ) {
// Eval_Point construction:
x = new NOMAD::Eval_Point;
x->set ( (*it2)->size() , _p.get_bb_nb_outputs() );
x->set_signature ( (*it2)->get_signature () );
x->set_direction ( (*it2)->get_direction () );
x->set_mesh_index ( (*it2)->get_mesh_index() );
x->Point::operator = ( **it2 );
modified_list = true;
// add the new point to the ordered list of trial points:
add_eval_point ( x ,
display_degree ,
snap_to_bounds ,
(*it2)->get_f() ,
(*it2)->get_h() ,
NOMAD::Double() ,
NOMAD::Double() );
}
}
if ( stop ) {
if ( del_evaluated_pts )
delete evaluated_pts;
return;
}
// model ordering:
// ---------------
if ( !modified_list && _model_eval_sort && _eval_lop.size() > 1 ) {
switch ( _p.get_model_eval_sort() ) {
case NOMAD::TGP_MODEL:
TGP_model_ordering ( display_degree , modified_list );
if ( NOMAD::Evaluator_Control::_force_quit ) {
stop = true;
stop_reason = NOMAD::CTRL_C;
}
break;
case NOMAD::QUADRATIC_MODEL:
quad_model_ordering ( display_degree , modified_list );
break;
case NOMAD::NO_MODEL:;
}
}
// this test is true if ctrl-c has been pressed:
if ( stop ) {
if ( del_evaluated_pts )
delete evaluated_pts;
return;
}
// display the re-ordered list of trial points:
if ( modified_list && display_degree == NOMAD::FULL_DISPLAY ) {
const NOMAD::Eval_Point * y;
std::ostringstream oss;
oss << "re-ordered list of " << _eval_lop.size()
<< " " << search << " trial points";
out << NOMAD::open_block ( oss.str() ) << std::endl;
std::set::const_iterator
end = _eval_lop.end() , it;
for ( it = _eval_lop.begin() ; it != end ; ++it ) {
y = it->get_point();
y->display_tag ( out );
out << ": ( ";
y->Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
out << " )";
if ( y->get_direction() )
out << " (dir " << y->get_direction()->get_index() << ")";
out << std::endl;
}
out.close_block();
}
// evaluate the list of points on the 'true' function:
private_eval_list_of_points ( search ,
true_barrier ,
sgte_barrier ,
pareto_front ,
stop ,
stop_reason ,
new_feas_inc ,
new_infeas_inc ,
success ,
*evaluated_pts );
#ifdef MODEL_STATS
display_model_stats ( *evaluated_pts );
#endif
if ( del_evaluated_pts )
delete evaluated_pts;
}
/*------------------------------------------------------------------------------------*/
/* ordering of a list of points based on surrogate (1st) or model (2nd) evaluations */
/*------------------------------------------------------------------------------------*/
void NOMAD::Evaluator_Control::ordering_lop ( NOMAD::search_type search , // IN : search type
bool & stop , // IN/OUT: stopping criterion
NOMAD::stop_type & stop_reason , // OUT : stopping reason
NOMAD::Barrier & true_barrier , // IN/OUT: truth barrier
NOMAD::Barrier & sgte_barrier // IN/OUT: surrogate barrier
)
{
std::list * evaluated_pts = new std::list;
bool sgte_eval_sort = _p.get_sgte_eval_sort() && _eval_lop.size() > 1;
bool opt_only_sgte = _p.get_opt_only_sgte ();
bool snap_to_bounds = _p.get_snap_to_bounds();
bool modified_list = false;
const NOMAD::Display & out = _p.out();
NOMAD::dd_type display_degree = out.get_display_degree ( search );
NOMAD::success_type success ;
const NOMAD::Eval_Point *new_feas_inc ;
const NOMAD::Eval_Point *new_infeas_inc;
// reset the success type:
true_barrier.reset_success();
sgte_barrier.reset_success();
// use the surrogates to sort the eval. points:
if ( !opt_only_sgte && sgte_eval_sort )
{
for ( std::set::iterator it = _eval_lop.begin() ; it != _eval_lop.end() ; ++it )
NOMAD::Cache::get_modifiable_point(*it->get_point()).set_eval_type(NOMAD::SGTE);
// evaluate the surrogate:
private_eval_list_of_points ( search ,
true_barrier ,
sgte_barrier ,
NULL , // Pareto front = NULL
stop ,
stop_reason ,
new_feas_inc ,
new_infeas_inc ,
success ,
*evaluated_pts );
if ( stop )
{
delete evaluated_pts;
return;
}
NOMAD::Eval_Point * x;
// construct a new list of trial points that will be
// ordered using surrogate values:
std::list::const_iterator
end = evaluated_pts->end() , it2;
for ( it2 = evaluated_pts->begin() ; it2 != end ; ++it2 )
{
// Eval_Point construction:
x = new NOMAD::Eval_Point;
x->set ( (*it2)->size() , _p.get_bb_nb_outputs() );
x->set_signature ( (*it2)->get_signature () );
x->set_direction ( (*it2)->get_direction () );
x->set_poll_center( (*it2)->get_poll_center () ); // Poll center is needed for further testing (not needed when evaluating points)
x->set_poll_center_type ( (*it2)->get_poll_center_type () );
x->set_mesh_index ( (*it2)->get_mesh_index() );
x->Point::operator = ( **it2 );
modified_list = true;
// add the new point to the ordered list of trial points:
add_eval_point ( x ,
display_degree ,
snap_to_bounds ,
(*it2)->get_f() ,
(*it2)->get_h() ,
NOMAD::Double() ,
NOMAD::Double() );
}
}
// model ordering:
// ---------------
if ( !modified_list && _model_eval_sort && _eval_lop.size() > 1 ) {
switch ( _p.get_model_eval_sort() ) {
case NOMAD::TGP_MODEL:
TGP_model_ordering ( display_degree , modified_list );
break;
case NOMAD::QUADRATIC_MODEL:
quad_model_ordering ( display_degree , modified_list );
break;
case NOMAD::NO_MODEL:;
}
}
if ( NOMAD::Evaluator_Control::_force_quit )
{
stop = true;
stop_reason = NOMAD::CTRL_C;
}
delete evaluated_pts;
}
/*--------------------------------------------------------------*/
/* return if a series of evaluations is opportunistic or not, */
/* depending on the search type (private) */
/*--------------------------------------------------------------*/
bool NOMAD::Evaluator_Control::is_opportunistic ( NOMAD::search_type t ) const
{
switch ( t ) {
case NOMAD::X0_EVAL:
return false;
case NOMAD::LH_SEARCH:
return _p.get_opportunistic_LH();
case NOMAD::CACHE_SEARCH:
return _p.get_opportunistic_cache_search();
default:
return _p.get_opportunistic_eval();
}
return false;
}
/*----------------------------------------------------------------*/
/* stop the evaluations ? */
/*----------------------------------------------------------------*/
/* . check the opportunistic strategy stopping criterion */
/* . private method */
/*----------------------------------------------------------------*/
bool NOMAD::Evaluator_Control::stop_evaluations
( const NOMAD::Eval_Point & x ,
NOMAD::search_type search ,
int k ,
int nb_points ,
bool stop ,
NOMAD::dd_type display_degree ,
NOMAD::success_type one_eval_success ,
NOMAD::success_type success ,
int init_nb_eval ,
const NOMAD::Double & f0 ,
const NOMAD::Barrier & barrier ,
int & nb_success ,
bool & one_for_luck ) const
{
// opportunistic evaluation ?
bool opportunistic = is_opportunistic ( search );
if ( k < nb_points - 1 ) {
if ( stop )
return true;
if ( opportunistic &&
( x.get_eval_type() == NOMAD::TRUTH || _p.get_opt_only_sgte() ) ) {
if ( one_for_luck && one_eval_success != NOMAD::FULL_SUCCESS ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
_p.out() << std::endl
<< "opportunistic termination of evaluations (lucky eval)"
<< std::endl;
return true;
}
if ( success == NOMAD::FULL_SUCCESS &&
check_opportunistic_criterion ( display_degree ,
one_eval_success ,
init_nb_eval ,
f0 ,
barrier ,
nb_success ,
one_for_luck ) )
return true;
}
}
return false;
}
/*-----------------------------------------------------------------*/
/* check the opportunistic strategy stopping criterion (private) */
/* return true to stop the evaluations */
/* return false to continue the evaluations */
/*-----------------------------------------------------------------*/
bool NOMAD::Evaluator_Control::check_opportunistic_criterion
( NOMAD::dd_type display_degree ,
NOMAD::success_type one_eval_success ,
int init_nb_eval ,
const NOMAD::Double & f0 ,
const NOMAD::Barrier & barrier ,
int & nb_success ,
bool & one_for_luck ) const
{
int min_nb_success = _p.get_opportunistic_min_nb_success();
int min_eval = _p.get_opportunistic_min_eval();
NOMAD::Double min_f_imprvmt = _p.get_opportunistic_min_f_imprvmt();
bool lucky_eval = _p.get_opportunistic_lucky_eval();
const NOMAD::Display & out = _p.out();
// min_nb_success:
if ( min_nb_success > 0 ) {
if ( one_eval_success == NOMAD::FULL_SUCCESS )
++nb_success;
if ( nb_success < min_nb_success ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< "opport. strategy (nb_success=" << nb_success
<< " < min_nb_success=" << min_nb_success
<< "): continue evaluations"
<< std::endl;
return false;
}
}
// min_eval:
if ( min_eval > 0 ) {
int eval = _stats.get_eval() - init_nb_eval;
if ( eval < min_eval ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< "opport. strategy (eval=" << eval
<< " < min_eval=" << min_eval
<< "): continue evaluations" << std::endl;
return false;
}
}
// min_f_imprvmt:
if ( min_f_imprvmt.is_defined() ) {
const NOMAD::Eval_Point * bf = barrier.get_best_feasible();
if ( f0.is_defined() && bf ) {
NOMAD::Double f = bf->get_f();
if ( f.is_defined() ) {
NOMAD::Double f_imprvmt = f0.rel_err(f) * 100.0;
if ( f_imprvmt < min_f_imprvmt ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< "opport. strategy (f_improvement="
<< f_imprvmt << " < min_f_imprvmt=" << min_f_imprvmt
<< "): continue evaluations" << std::endl;
return false;
}
}
}
}
// lucky_eval:
if ( lucky_eval && one_eval_success == NOMAD::FULL_SUCCESS ) {
one_for_luck = true;
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< "opport. strategy: one more evaluation for luck"
<< std::endl;
return false;
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl << "opport. strategy: stop evaluations"
<< std::endl;
return true;
}
/*---------------------------------------------------------------*/
/* display the list of evaluation points (_eval_lop) */
/*---------------------------------------------------------------*/
void NOMAD::Evaluator_Control::display_eval_lop ( NOMAD::search_type t ) const
{
const NOMAD::Display & out = _p.out();
int cnt = 0 , nb = static_cast(_eval_lop.size());
if ( nb == 0 ) {
out << std::endl << "no evaluation point" << std::endl;
return;
}
// open indented block:
std::ostringstream oss;
if ( t != NOMAD::UNDEFINED_SEARCH )
oss << t << " ";
oss << "evaluation point";
if ( nb > 1 )
oss << "s";
out << std::endl << NOMAD::open_block ( oss.str() ) << std::endl;
// display the points:
std::set::const_iterator it , end = _eval_lop.end();
for ( it = _eval_lop.begin() ; it != end ; ++it ) {
out << "point ";
out.display_int_w ( ++cnt , nb );
out << "/" << nb << ": ( ";
it->get_point()->Point::display ( out ,
" " ,
2 ,
NOMAD::Point::get_display_limit() );
out << " )" << std::endl;
}
// close indented block:
out.close_block();
}
/*--------------------------------------------------------------*/
/* add an Eval_Point to the list of points to be evaluated */
/*--------------------------------------------------------------*/
/* . x has to be a dynamic object */
/* . it may be deleted into the method and be NULL after that */
/* . the point is also snapped to bounds */
/* . periodic variables are checked */
/*--------------------------------------------------------------*/
void NOMAD::Evaluator_Control::add_eval_point( NOMAD::Eval_Point *& x ,
NOMAD::dd_type display_degree ,
bool snap_to_bounds ,
const NOMAD::Double & f_sgte ,
const NOMAD::Double & h_sgte ,
const NOMAD::Double & f_model ,
const NOMAD::Double & h_model )
{
if ( !x )
return;
const NOMAD::Display & out = _p.out();
// treat the periodic variables:
NOMAD::Direction * new_dir = NULL;
if ( _p.has_periodic_variables() &&
x->treat_periodic_variables ( new_dir ) ) {
if ( new_dir && new_dir->norm() == 0.0 ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "point #" << x->get_tag()
<< " is flushed (||dir||==0)"
<< std::endl;
delete x;
x = NULL;
delete new_dir;
return;
}
}
delete new_dir;
if ( snap_to_bounds && x->snap_to_bounds() ) {
if ( display_degree == NOMAD::FULL_DISPLAY ) {
out << std::endl << "point #" << x->get_tag() << " ";
if ( x->get_direction() && x->get_direction()->get_index() >= 0 )
out << "(dir " << x->get_direction()->get_index() << ") ";
out << "has been snapped to bounds" << std::endl;
}
if ( x->get_direction() && x->get_direction()->norm() == 0.0 ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "point #" << x->get_tag()
<< " is flushed (||dir||==0)"
<< std::endl;
delete x;
x = NULL;
return;
}
}
// creation of the Priority_Eval_Point:
NOMAD::Priority_Eval_Point pep ( x , _p.get_h_min() );
// ordering elements of Priority_Eval_Point's:
// -------------------------------------------
// 1. surrogate values for f and h:
pep.set_f_sgte ( f_sgte );
pep.set_h_sgte ( h_sgte );
// 2. model values for f and h:
pep.set_f_model ( f_model );
pep.set_h_model ( h_model );
if ( x->get_direction() )
{
// get the signature:
NOMAD::Signature * signature = x->get_signature();
if ( !signature )
throw NOMAD::Exception ( "Evaluator_Control.cpp" , __LINE__ ,
"Evaluator_Control::add_eval_point(): the point has no signature" );
// angle with last successful directions (feasible)
const NOMAD::Direction & feas_success_dir = signature->get_feas_success_dir();
if ( feas_success_dir.is_defined() &&
x->get_poll_center_type() == NOMAD::FEASIBLE )
pep.set_angle_success_dir ( feas_success_dir.get_angle ( *x->get_direction() ) );
// angle with last infeasible success direction:
const NOMAD::Direction & infeas_success_dir = signature->get_infeas_success_dir();
if ( infeas_success_dir.is_defined() &&
x->get_poll_center_type() == NOMAD::INFEASIBLE )
pep.set_angle_success_dir ( infeas_success_dir.get_angle ( *x->get_direction() ) );
}
// insertion of the point in _eval_lop:
// ------------------------------------
size_t size_before = _eval_lop.size();
_eval_lop.insert ( pep );
if ( _eval_lop.size() == size_before )
{
delete x;
x = NULL;
}
}
#ifdef MODEL_STATS
/*------------------------------------------------------------------*/
/* display stats on an evaluation for which a model has been used */
/*------------------------------------------------------------------*/
/* The displayed stats are: */
/* */
/* use (1:model_search, 2:model_ordering) */
/* mesh_index */
/* cardinality of Y */
/* width of Y */
/* Y condition number */
/* h value, model for h, relative error (if constraints) */
/* f value, model for f, relative error */
/* */
/*------------------------------------------------------------------*/
void NOMAD::Evaluator_Control::display_model_stats
( const std::list & evaluated_pts ) const
{
const NOMAD::Display & out = _p.out();
NOMAD::Double h , mh , eh , f , mf , ef;
std::list::const_iterator it , end = evaluated_pts.end();
for ( it = evaluated_pts.begin() ; it != end ; ++it ) {
if ( *it && (*it)->get_mod_use() >= 0 ) {
if ( _p.has_constraints() ) {
h = (*it)->get_h ();
mh = (*it)->get_mh();
}
else
h = mh = 0.0;
f = (*it)->get_f ();
mf = (*it)->get_mf();
if ( h.is_defined() && mh.is_defined() && f.is_defined() && mf.is_defined() ) {
ef = f.rel_err ( mf ) * 100.0;
out << (*it)->get_mod_use()
<< " " << std::setw(3) << NOMAD::Mesh::get_mesh_index()
<< " " << std::setw(4) << (*it)->get_nY()
<< " ";
(*it)->get_Yw ().display ( out , "%12.3g" ); out << " ";
(*it)->get_cond().display ( out , "%12.3g" ); out << " ";
if ( _p.has_constraints() ) {
eh = h.rel_err ( mh ) * 100.0;
h.display ( out , "%14.3g" ); out << " ";
mh.display ( out , "%14.3g" ); out << " ";
eh.display ( out , "%14.3g" ); out << " ";
}
f.display ( out , "%14.3g" ); out << " ";
mf.display ( out , "%14.3g" ); out << " ";
ef.display ( out , "%14.3g" );
out << std::endl;
}
(*it)->clear_model_data();
}
}
}
#endif