/*-------------------------------------------------------------------------------------*/
/* 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 TGP_Model_Search.cpp
\brief TGP Model search (implementation)
\author Sebastien Le Digabel
\date 2011-02-17
\see TGP_Model_Search.hpp
*/
#ifndef USE_TGP
int TGP_MODEL_SEARCH_DUMMY; // avoids that TGP_Model_Search.o has no symbols with ranlib
#else
#include "TGP_Model_Search.hpp"
/*-----------------------------------*/
/* reset (virtual) */
/*-----------------------------------*/
void NOMAD::TGP_Model_Search::reset ( void )
{
if ( _model )
delete _model;
_model = NULL;
}
/*--------------------------------------------------------*/
/* delete a list of points: one version for points, and */
/* one version for evaluation points (static, private) */
/*--------------------------------------------------------*/
void NOMAD::TGP_Model_Search::clear_pts ( std::vector & pts )
{
size_t k , n = pts.size();
for ( k = 0 ; k < n ; ++k )
delete pts[k];
pts.clear();
}
void NOMAD::TGP_Model_Search::clear_pts ( std::vector & pts )
{
size_t k , n = pts.size();
for ( k = 0 ; k < n ; ++k )
delete pts[k];
pts.clear();
}
/*------------------------------------------------------------------*/
/* the search */
/*------------------------------------------------------------------*/
/* Search parameters: */
/* ------------------ */
/* */
/* . MODEL_SEARCH: flag to activate the model search (MS) */
/* (here its value is NOMAD::TGP_MODEL) */
/* */
/* . MODEL_SEARCH_OPTIMISTIC: if true, the direction from the */
/* model center to the trial point */
/* is computed and prossibly used */
/* in the speculative search */
/* default=yes */
/* */
/* . MODEL_SEARCH_PROJ_TO_MESH: project or not to mesh */
/* default=yes */
/* */
/* . MODEL_SEARCH_MAX_TRIAL_PTS: limit on the number of trial */
/* points for one search */
/* default=10 */
/* */
/* . MODEL_TGP_MODE: TGP mode (FAST or PRECISE) */
/* default=FAST */
/* */
/*------------------------------------------------------------------*/
void NOMAD::TGP_Model_Search::search ( NOMAD::Mads & mads ,
int & nb_search_pts ,
bool & stop ,
NOMAD::stop_type & stop_reason ,
NOMAD::success_type & success ,
bool & count_search ,
const NOMAD::Eval_Point *& new_feas_inc ,
const NOMAD::Eval_Point *& new_infeas_inc )
{
new_feas_inc = new_infeas_inc = NULL;
nb_search_pts = 0;
success = NOMAD::UNSUCCESSFUL;
count_search = false;
_one_search_stats.reset();
const NOMAD::Display & out = _p.out();
NOMAD::dd_type display_degree = out.get_search_dd();
int display_lim = 15;
if ( stop ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "TGP_Model_Search::search(): not performed (stop flag is active)"
<< std::endl;
return;
}
// active cache (we accept only true function evaluations):
const NOMAD::Cache & cache = mads.get_cache();
if ( cache.get_eval_type() != NOMAD::TRUTH ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "TGP_Model_Search::search(): not performed on surrogates"
<< std::endl;
return;
}
// check that there is one objective exactly:
const std::list & index_obj_list = _p.get_index_obj();
if ( index_obj_list.empty() ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "TGP_Model_Search::search(): not performed with no objective function"
<< std::endl;
return;
}
if ( index_obj_list.size() > 1 ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "TGP_Model_Search::search(): not performed with biobjective"
<< std::endl;
return;
}
// active barrier:
const NOMAD::Barrier & barrier = mads.get_true_barrier();
// get the incumbent:
const NOMAD::Eval_Point * incumbent = barrier.get_best_feasible();
if ( !incumbent )
incumbent = barrier.get_best_infeasible();
if ( !incumbent ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "TGP_Model_Search::search(): no incumbent"
<< std::endl;
return;
}
// get and check the signature, and compute the dimension:
NOMAD::Signature * signature = incumbent->get_signature();
if ( !signature ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "TGP_Model_Search::search(): no signature"
<< std::endl;
return;
}
int n = signature->get_n();
if ( n != incumbent->size() ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "TGP_Model_Search::search(): incompatible signature"
<< std::endl;
return;
}
// initial displays:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
std::ostringstream oss;
oss << NOMAD::MODEL_SEARCH << " #"
<< _all_searches_stats.get_MS_nb_searches();
out << std::endl << NOMAD::open_block ( oss.str() ) << std::endl;
}
// from this point the search is counted:
count_search = true;
_one_search_stats.add_MS_nb_searches();
// mesh:
int mesh_index = NOMAD::Mesh::get_mesh_index();
NOMAD::Point delta_m;
signature->get_mesh().get_delta_m ( delta_m , mesh_index );
// initial displays:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
#ifdef TGP_DEBUG
out << "seed : "
<< _p.get_seed() << std::endl;
#endif
out << "number of cache points: " << cache.size() << std::endl
<< "mesh index : " << mesh_index << std::endl
<< "mesh size parameter : ( " << delta_m << " )" << std::endl
<< "incumbent : ( ";
incumbent->NOMAD::Point::display
( out , " " , 2 , NOMAD::Point::get_display_limit() );
out << " )" << std::endl;
}
// construct the model:
NOMAD::Stats & stats = mads.get_stats();
bool compute_Ds2x;
std::vector XX;
std::string error_str;
if ( !model_construction ( cache ,
*incumbent ,
delta_m ,
out ,
display_degree ,
display_lim ,
stats ,
compute_Ds2x ,
XX ,
stop ,
stop_reason ,
error_str ) ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << NOMAD::close_block ( "failure: " + error_str )
<< std::endl;
return;
}
// trial_pts = oracle_pts + Ds2x_pts + improv_pts
//
// oracle_pts: given by the model optimization
// Ds2x_pts : XX points with the largest expected reduction in predictive variance
// improv_pts: XX points with the largest expected improvement for the objective
int max_pts = _p.get_model_search_max_trial_pts();
/*-----------------------*/
/* oracle points (1/3) */
/*-----------------------*/
std::vector oracle_pts;
if ( !create_oracle_pts ( cache ,
*incumbent ,
delta_m ,
out ,
display_degree ,
display_lim ,
XX ,
oracle_pts ,
stop ,
stop_reason ) && stop ) {
// delete XX and oracle_pts:
NOMAD::TGP_Model_Search::clear_pts ( XX );
NOMAD::TGP_Model_Search::clear_pts ( oracle_pts );
// quit:
if ( display_degree == NOMAD::FULL_DISPLAY )
out << NOMAD::close_block ( "algorithm stop" )
<< std::endl;
return;
}
/*---------------------*/
/* Ds2x points (2/3) */
/*---------------------*/
std::vector Ds2x_pts;
if ( compute_Ds2x )
create_Ds2x_pts ( XX , out , display_degree , display_lim , Ds2x_pts );
/*-----------------------*/
/* improv points (3/3) */
/*-----------------------*/
std::vector improv_pts;
create_improv_pts ( XX ,
*incumbent ,
max_pts ,
out ,
display_degree ,
display_lim ,
improv_pts );
// create the complete list of trial points:
// -----------------------------------------
std::vector trial_pts;
create_trial_pts ( oracle_pts ,
Ds2x_pts ,
improv_pts ,
*incumbent ,
max_pts ,
out ,
display_degree ,
trial_pts );
// evaluator control:
NOMAD::Evaluator_Control & ev_control = mads.get_evaluator_control();
// add the trial points to the evaluator control for evaluation:
int i , nop = trial_pts.size();
for ( i = 0 ; i < nop ; ++i )
register_point ( *trial_pts[i] ,
*signature ,
*incumbent ,
mesh_index ,
display_degree ,
ev_control );
// display the evaluator control list of points:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
out << std::endl << NOMAD::open_block ( "list of trial points" );
const std::set & lop = ev_control.get_eval_lop();
std::set::const_iterator it , end = lop.end();
nop = lop.size();
for ( it = lop.begin() , i = 0 ; it != end ; ++it , ++i ) {
out << "#";
out.display_int_w ( i , nop );
out << " x=( ";
it->get_point()->NOMAD::Point::display ( out , " " , 15 , -1 );
out << " )" << std::endl;
}
out.close_block();
}
// delete XX and the trial points
// (do not delete Ds2x_pts and improv_pts because
// they are XX points, contrary to oracle_pts):
NOMAD::TGP_Model_Search::clear_pts ( XX );
NOMAD::TGP_Model_Search::clear_pts ( oracle_pts );
nb_search_pts = ev_control.get_nb_eval_points();
if ( nb_search_pts == 0 ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl << "no trial point" << std::endl;
}
else {
_one_search_stats.update_MS_max_search_pts ( nb_search_pts );
// evaluate the trial points:
// --------------------------
int bbe = stats.get_bb_eval();
int sgte_eval = stats.get_sgte_eval ();
int cache_hits = stats.get_cache_hits();
new_feas_inc = new_infeas_inc = NULL;
ev_control.disable_model_eval_sort();
std::list * evaluated_pts = NULL;
if ( display_degree == NOMAD::FULL_DISPLAY )
evaluated_pts = new std::list;
ev_control.eval_list_of_points ( _type ,
mads.get_true_barrier() ,
mads.get_sgte_barrier() ,
mads.get_pareto_front() ,
stop ,
stop_reason ,
new_feas_inc ,
new_infeas_inc ,
success ,
evaluated_pts );
// display the prediction error for the evaluated points:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
display_eval_pred_errors ( *evaluated_pts , out );
delete evaluated_pts;
}
ev_control.enable_model_eval_sort();
// update stats:
_one_search_stats.add_MS_bb_eval ( stats.get_bb_eval () - bbe );
_one_search_stats.add_MS_sgte_eval ( stats.get_sgte_eval () - sgte_eval );
_one_search_stats.add_MS_cache_hits ( stats.get_cache_hits() - cache_hits );
if ( success == NOMAD::FULL_SUCCESS )
_one_search_stats.add_MS_success();
_one_search_stats.add_MS_pts ( nb_search_pts );
}
// update stats objects:
stats.update_model_stats ( _one_search_stats );
_all_searches_stats.update ( _one_search_stats );
// final display:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
std::ostringstream oss;
oss << "end of " << NOMAD::MODEL_SEARCH << " (" << success << ")";
out << std::endl << NOMAD::close_block ( oss.str() ) << std::endl;
}
}
/*---------------------------------------------------------------*/
/* create XX a list of prediction points (private) */
/*---------------------------------------------------------------*/
void NOMAD::TGP_Model_Search::set_XX
( const NOMAD::Cache & cache ,
int n ,
int m ,
const NOMAD::Point & incumbent ,
const NOMAD::Point & delta_m ,
std::vector & XX ) const
{
// . we begin with 1999 points, filter them to remove points
// that appear more than once or in the cache.
// . then we prune the list to 499 points.
// . we do not begin directly with 500 points because it
// gives more flexibility with the projection.
// . we terminate by adding the incumbent.
// --> we obtain a list of at most 500 prediction points.
int j , i = 0 , n_XX = 1999; // 2000-1
bool proj_to_mesh = _p.get_model_search_proj_to_mesh();
bool remove_pt;
// XX is made of n_XX-1 LH points inside the model bounds
// (and the incumbent will be added at the end):
NOMAD::LH_Search::LH_points ( n, m, n_XX, _model->get_lb(), _model->get_ub(), XX );
while ( i < n_XX ) {
remove_pt = false;
// project to the mesh:
if ( proj_to_mesh )
XX[i]->project_to_mesh ( incumbent , delta_m , _p.get_lb() , _p.get_ub() );
// remove if point is in cache:
if ( cache.find ( *XX[i] ) )
remove_pt = true;
// check if this point is already in XX
// (may occur only if the point has been projected):
if ( proj_to_mesh && !remove_pt ) {
if ( incumbent == (*XX[i]) )
remove_pt = true;
else
for ( j = 0 ; j < i ; ++j )
if ( XX[j]->NOMAD::Point::operator == ( *XX[i] ) ) {
remove_pt = true;
break;
}
}
// remove the point:
if ( remove_pt ) {
delete XX[i];
--n_XX;
if ( i != n_XX )
XX[i] = XX[n_XX];
XX.resize ( n_XX );
}
else
++i;
}
// reduce to 500-1 points (we eliminate randomly):
while ( n_XX >= 500 ) {
i = rand()%n_XX;
delete XX[i];
--n_XX;
if ( i != n_XX )
XX[i] = XX[n_XX];
XX.resize(n_XX);
}
// add the incumbent as the last point of XX:
XX.push_back ( new NOMAD::Eval_Point ( n , m ) );
XX[n_XX]->NOMAD::Point::operator = ( incumbent );
}
/*---------------------------------------------------------------------*/
/* create the complete list of trial points (oracle + Ds2x + improv) */
/* (private) */
/*---------------------------------------------------------------------*/
void NOMAD::TGP_Model_Search::create_trial_pts
( const std::vector & oracle_pts , // IN
const std::vector & Ds2x_pts , // IN
const std::vector & improv_pts , // IN
const NOMAD::Point & incumbent , // IN
int max_pts , // IN
const NOMAD::Display & out , // IN
NOMAD::dd_type display_degree , // IN
std::vector & trial_pts ) const // OUT
{
bool found;
size_t i , j ,
n1 = oracle_pts.size() ,
n2 = Ds2x_pts.size () ,
n3 = improv_pts.size();
std::vector l2 , l3;
// 1. remove duplicates:
// ---------------------
//
// . oracle_pts are not XX points
// . Ds2x_pts and improv_pts are XX points
// . there is no duplicate in each list separately
//
for ( i = 0 ; i < n2 ; ++i ) {
found = false;
if ( *Ds2x_pts[i] == incumbent )
found = true;
else {
for ( j = 0 ; j < n1 ; ++j )
if ( *Ds2x_pts[i] == *oracle_pts[j] ) {
found = true;
break;
}
}
if ( !found )
l2.push_back ( Ds2x_pts[i] );
}
n2 = l2.size();
for ( i = 0 ; i < n3 ; ++i ) {
found = false;
if ( *improv_pts[i] == incumbent )
found = true;
else {
for ( j = 0 ; j < n1 ; ++j )
if ( *improv_pts[i] == *oracle_pts[j] ) {
found = true;
break;
}
}
if ( !found ) {
for ( j = 0 ; j < n2 ; ++j )
if ( improv_pts[i] == l2[j] ) {
found = true;
break;
}
}
if ( !found )
l3.push_back ( improv_pts[i] );
}
n3 = l3.size();
// 2. construct the list of trial points:
// ------------------------------------
trial_pts.clear();
int nb_pts = static_cast ( n1 + n2 + n3 );
// no need to reduce the number of trial points:
if ( max_pts <= 0 || nb_pts <= max_pts ) {
// 1. oracle points:
for ( i = 0 ; i < n1 ; ++i )
trial_pts.push_back ( oracle_pts[i] );
// 2, improv points:
for ( i = 0 ; i < n3 ; ++i )
trial_pts.push_back ( l3[i] );
// 3. Ds2x points:
for ( i = 0 ; i < n2 ; ++i )
trial_pts.push_back ( l2[i] );
}
// reduce the list to max_pts points:
else {
nb_pts = 0;
size_t i1 = 0 , i2 = 0 , i3 = 0;
while ( true ) {
// one point from the oracle points:
if ( i1 < n1 ) {
trial_pts.push_back ( oracle_pts[i1++] );
++nb_pts;
if ( nb_pts == max_pts )
break;
}
// two from the improv points:
for ( i = 0 ; i < 2 ; ++i ) {
if ( i3 < n3 ) {
trial_pts.push_back ( l3[i3++] );
++nb_pts;
if ( nb_pts == max_pts )
break;
}
}
if ( nb_pts == max_pts )
break;
// one from the Ds2x points:
if ( i2 < n2 ) {
trial_pts.push_back ( l2[i2++] );
++nb_pts;
if ( nb_pts == max_pts )
break;
}
}
}
// 3. display the list of trial points:
// ------------------------------------
// if ( display_degree == NOMAD::FULL_DISPLAY ) {
// out.open_block ( "list of trial points (debug)" );
// n1 = trial_pts.size();
// for ( i = 0 ; i < n1 ; ++i ) {
// out << "#";
// out.display_int_w ( i , n1 );
// out << " x=( " << *trial_pts[i] << " )" << std::endl;
// }
// out.close_block();
// }
}
/*---------------------------------------------------------*/
/* create the list of improv points (private) */
/*---------------------------------------------------------*/
void NOMAD::TGP_Model_Search::create_improv_pts
( const std::vector & XX , // IN
const NOMAD::Point & incumbent , // IN
int max_pts , // IN
const NOMAD::Display & out , // IN
NOMAD::dd_type display_degree , // IN
int display_lim , // IN
std::vector & improv_pts ) const // OUT
{
if ( display_degree == NOMAD::FULL_DISPLAY )
out << NOMAD::open_block ( "improv points construction" )
<< std::endl;
// reset improv points:
improv_pts.clear();
// display improv points directly from the NOMAD::TGP_Model object:
#ifdef TGP_DEBUG
out << NOMAD::open_block ( "expected improvement of the objective (improv)" );
_model->display_improv ( out , display_lim );
out << NOMAD::close_block() << std::endl;
#endif
std::list pts_indexes;
_model->get_improv_points ( pts_indexes );
if ( pts_indexes.empty() ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< NOMAD::close_block ( "no improv candidate" )
<< std::endl;
return;
}
std::list::const_iterator it , end = pts_indexes.end();
// with constraints, the list is re-sorted in order to put the
// predicred feasible points first:
if ( _p.has_constraints() ) {
std::list feas_pts , infeas_pts;
NOMAD::Double h , f;
const NOMAD::Double & h_min = _p.get_h_min();
for ( it = pts_indexes.begin() ; it != end ; ++it ) {
if ( predict ( *XX[*it] , h , f ) && h <= h_min )
feas_pts.push_back ( *it );
else
infeas_pts.push_back ( *it );
}
pts_indexes.clear();
end = feas_pts.end();
for ( it = feas_pts.begin() ; it != end ; ++it )
pts_indexes.push_back ( *it );
end = infeas_pts.end();
for ( it = infeas_pts.begin() ; it != end ; ++it )
pts_indexes.push_back ( *it );
end = pts_indexes.end();
}
// compute max_index just for the display:
int i , j , max_index = -1 , ni = -1;
if ( display_degree == NOMAD::FULL_DISPLAY ) {
ni = pts_indexes.size();
if ( max_pts > 0 && ni > max_pts )
ni = max_pts;
for ( it = pts_indexes.begin() ; it != end ; ++it ) {
if ( *it > max_index )
max_index = *it;
}
}
// add the points to improv_pts:
bool rejected;
i = j = 0;
for ( it = pts_indexes.begin() ; it != end ; ++it ) {
// we check the max number of points:
rejected = ( max_pts > 0 && max_pts == i );
// we reject the point if it is the incumbent:
if ( !rejected && incumbent == *XX[*it] )
rejected = true;
// we add the point:
if ( !rejected ) {
improv_pts.push_back ( XX[*it] );
++i;
}
// display:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
if ( display_lim <= 0 || j < display_lim ) {
if ( rejected )
out << "rejected candidate ";
else {
out << "improv candidate #";
out.display_int_w ( i-1 , ni );
}
out << " (XX point #";
out.display_int_w ( *it , max_index );
out << "): x=( ";
XX[*it]->NOMAD::Point::display ( out , " " , 6 , -1 );
out << " )";
if ( rejected ) {
if ( max_pts > 0 && max_pts == i )
out << " (max number of points)";
else
out << " (candidate==incumbent)";
}
else
out << " improv=" << _model->get_improv(*it);
out << std::endl;
}
if ( display_lim > 0 && j == display_lim )
out << "..." << std::endl;
++j;
}
// if no display, stop the loop if there is already too many points:
else if ( max_pts > 0 && max_pts == i )
break;
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< NOMAD::close_block ( "end of improv points construction" )
<< std::endl;
}
/*------------------------------------------------------------*/
/* create the list of Ds2x points, the points that maximize */
/* the expected reduction in predictive variance */
/* (private) */
/*------------------------------------------------------------*/
void NOMAD::TGP_Model_Search::create_Ds2x_pts
( const std::vector & XX , // IN
const NOMAD::Display & out , // IN
NOMAD::dd_type display_degree , // IN
int display_lim , // IN
std::vector & Ds2x_pts ) const // OUT
{
if ( display_degree == NOMAD::FULL_DISPLAY )
out << NOMAD::open_block ( "Ds2x points construction" )
<< std::endl;
// reset Ds2x points:
Ds2x_pts.clear();
// display Ds2x points directly from the NOMAD::TGP_Model object:
#ifdef TGP_DEBUG
out << NOMAD::open_block ( "expected reduction in predictive variance (Ds2x)" );
_model->display_Ds2x ( out , display_lim );
out << NOMAD::close_block() << std::endl;
#endif
std::set pts_indexes;
_model->get_Ds2x_points ( pts_indexes );
if ( pts_indexes.empty() ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< NOMAD::close_block ( "no Ds2x candidate" )
<< std::endl;
return;
}
std::set::const_iterator it , end = pts_indexes.end();
int i , max_index = -1 , m = _p.get_bb_nb_outputs() , n_XX = XX.size();
if ( display_degree == NOMAD::FULL_DISPLAY ) {
for ( it = pts_indexes.begin() ; it != end ; ++it ) {
if ( *it > max_index )
max_index = *it;
}
}
for ( it = pts_indexes.begin() , i = 0 ; it != end ; ++it , ++i ) {
Ds2x_pts.push_back ( XX[*it] );
if ( display_degree == NOMAD::FULL_DISPLAY ) {
out << "Ds2x candidate #";
out.display_int_w ( i , m );
out << " (XX point #";
out.display_int_w ( *it , max_index );
out << "): x=( ";
XX[*it]->NOMAD::Point::display ( out , " " , 6 , -1 );
out << " )";
if ( *it == n_XX - 1 )
out << " (rejected: candidate==incumbent)";
out << std::endl;
}
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< NOMAD::close_block ( "end of Ds2x points construction" )
<< std::endl;
}
/*-------------------------------------------------------------------*/
/* create a list of oracle points, given by the model optimization */
/* (private) */
/*-------------------------------------------------------------------*/
bool NOMAD::TGP_Model_Search::create_oracle_pts
( const NOMAD::Cache & cache ,
const NOMAD::Point & incumbent ,
const NOMAD::Point & delta_m ,
const NOMAD::Display & out ,
NOMAD::dd_type display_degree ,
int display_lim ,
const std::vector & XX ,
std::vector & oracle_pts ,
bool & stop ,
NOMAD::stop_type & stop_reason )
{
if ( display_degree == NOMAD::FULL_DISPLAY )
out << NOMAD::open_block ( "oracle points construction" )
<< std::endl;
// reset oracle points:
NOMAD::TGP_Model_Search::clear_pts ( oracle_pts );
int i , n_XX = XX.size();
// starting points selection:
const NOMAD::Eval_Point * x0s[3];
x0s[0] = x0s[1] = x0s[2] = NULL;
// open display block for model predictions:
#ifdef TGP_DEBUG
out << NOMAD::open_block ( "TGP predictions (XX+ZZ)");
int i0 = ( display_lim > 0 ) ? n_XX - display_lim : 0;
if ( i0 > 0 )
out << "..." << std::endl;
#endif
NOMAD::Double f_model , h_model;
const NOMAD::Double & h_min = _p.get_h_min();
NOMAD::hnorm_type h_norm = _p.get_h_norm();
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 );
if ( h_model.is_defined() && f_model.is_defined() ) {
XX[i]->set_f ( f_model );
XX[i]->set_h ( h_model );
// feasible point:
if ( XX[i]->is_feasible ( h_min ) ) {
if ( !x0s[0] || f_model < x0s[0]->get_f() )
x0s[0] = XX[i];
}
// infeasible point:
else {
if ( !x0s[1] || h_model < x0s[1]->get_h() )
x0s[1] = XX[i];
if ( !x0s[2] || f_model < x0s[2]->get_f() )
x0s[2] = XX[i];
}
}
// display model predictions:
#ifdef TGP_DEBUG
if ( i >= i0 ) {
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=" << h_model << " fm=" << f_model;
else
out << " no model value";
out << std::endl;
}
#endif
#ifdef MODEL_STATS
if ( XX[i] && f_model.is_defined() && h_model.is_defined() ) {
XX[i]->set_mod_use ( 1 ); // 1 for model search
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
if ( !x0s[0] && !x0s[1] && !x0s[2] ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< NOMAD::close_block ( "oracle points error: no model starting point" )
<< std::endl;
return false;
}
// display starting points:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
out << std::endl
<< NOMAD::open_block ( "model starting points" );
for ( i = 0 ; i < 3 ; ++i ) {
out << "#" << i << ": ";
if ( !x0s[i] )
out << "NULL" << std::endl;
else {
out << " x=(";
x0s[i]->NOMAD::Point::display ( out , " " , 15 , -1 );
out << " ) m(x)=[";
x0s[i]->get_bb_outputs().display ( out , " " , 15 , -1 );
out << " ]"
<< " hm=" << std::setw(15) << x0s[i]->get_h()
<< " fm=" << std::setw(15) << x0s[i]->get_f()
<< std::endl;
}
}
out << NOMAD::close_block() << std::endl;
}
// optimize model:
// ---------------
NOMAD::Point * xf = NULL , * xi = NULL;
NOMAD::Clock clock;
bool optimization_ok = optimize_model ( x0s ,
out ,
display_degree ,
xf ,
xi ,
stop ,
stop_reason );
_one_search_stats.add_optimization_time ( clock.get_CPU_time() );
if ( stop || !optimization_ok || ( xf == NULL && xi == NULL ) ) {
std::string error_str;
if ( xf == NULL && xi == NULL )
error_str = "no model optimization solution";
else {
if ( xf ) delete xf;
if ( xi ) delete xi;
error_str = ( stop ) ? "algorithm stop" : "model optimization error";
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< NOMAD::close_block ( "oracle points error: " + error_str )
<< std::endl;
return false;
}
// project and check xf and xi:
if ( xf && !check_oracle_point ( cache ,
incumbent ,
delta_m ,
out ,
display_degree ,
*xf ) ) {
delete xf;
xf = NULL;
}
if ( xi && !check_oracle_point ( cache ,
incumbent ,
delta_m ,
out ,
display_degree ,
*xi ) ) {
delete xi;
xi = NULL;
}
// add xf and xi in the list of oracle points:
if ( xf )
oracle_pts.push_back ( xf );
if ( xi ) {
// check that xi != xf:
if ( xf && *xf == *xi ) {
delete xi;
xi = NULL;
}
if ( xi )
oracle_pts.push_back ( xi );
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< NOMAD::close_block ( "end of oracle points construction" )
<< std::endl;
return true;
}
/*------------------------------------------------------*/
/* project and accept or reject an oracle trial point */
/* (private) */
/*------------------------------------------------------*/
bool NOMAD::TGP_Model_Search::check_oracle_point
( const NOMAD::Cache & cache ,
const NOMAD::Point & incumbent ,
const NOMAD::Point & delta_m ,
const NOMAD::Display & out ,
NOMAD::dd_type display_degree ,
NOMAD::Point & x )
{
bool proj_to_mesh = _p.get_model_search_proj_to_mesh();
if ( display_degree == NOMAD::FULL_DISPLAY ) {
out << std::endl << "oracle candidate";
if ( proj_to_mesh )
out << " (before projection)";
out << ": ( " << x << " )" << std::endl;
}
// projection to mesh:
if ( proj_to_mesh ) {
x.project_to_mesh ( incumbent , delta_m , _p.get_lb() , _p.get_ub() );
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "oracle candidate (after projection) : ( "
<< x << " )" << std::endl;
}
// compare x and incumbent coordinates:
if ( x == incumbent ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "oracle candidate rejected (candidate==incumbent)" << std::endl;
return false;
}
// two evaluations points are created in order to:
// 1. check if the candidate is in cache
// 2. have a prediction at x and at the incumbent:
int n = x.size() , m = _p.get_bb_nb_outputs();
NOMAD::Eval_Point * tk = new NOMAD::Eval_Point ( n , m ); // trial point
tk->Point::operator = ( x );
// check if the point is in cache:
if ( cache.find ( *tk ) ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "oracle candidate rejected (found in cache)" << std::endl;
delete tk;
return false;
}
NOMAD::Eval_Point * ic = new NOMAD::Eval_Point ( n , m ); // incumbent copy
ic->Point::operator = ( incumbent );
// model predictions (in order to accept or reject the trial point):
bool pred_error = !_model->predict ( *ic , true ) || // pred_outside_bnds = true
!_model->predict ( *tk , true ); // pred_outside_bnds = true
const NOMAD::Double & h_min = _p.get_h_min();
NOMAD::hnorm_type h_norm = _p.get_h_norm();
NOMAD::Double h0 , f0; // model values of f and h at the center
NOMAD::Double h1 , f1; // model values of f and h at the trial point
if ( !pred_error )
_model->eval_hf ( tk->get_bb_outputs() , h_min , h_norm , h1 , f1 );
delete tk;
if ( pred_error || !h1.is_defined() || !f1.is_defined() ) {
if ( display_degree == NOMAD::FULL_DISPLAY ) {
if ( pred_error )
out << "prediction error: oracle candidate rejected";
else
out << "no model value (EB constraint violated?): oracle candidate rejected";
out << std::endl;
}
delete ic;
return false;
}
// accept or reject the trial point:
bool accept_point = false;
_model->eval_hf ( ic->get_bb_outputs(), h_min, h_norm, h0, f0 );
if ( !h0.is_defined() || !f0.is_defined() )
accept_point = true;
delete ic;
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl
<< "incumbent prediction : h0=" << h0 << " f0=" << f0 << std::endl
<< "trial point prediction: h1=" << h1 << " f1=" << f1 << std::endl;
if ( !accept_point )
accept_point = (f1 < f0) || (h1 < h0);
if ( !accept_point ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "oracle candidate rejected" << std::endl;
_one_search_stats.add_MS_rejected();
return false;
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "oracle candidate accepted" << std::endl;
return true;
}
/*--------------------------------------------------------*/
/* insert a trial point in the evaluator control object */
/* (private) */
/*--------------------------------------------------------*/
void NOMAD::TGP_Model_Search::register_point
( NOMAD::Point x ,
NOMAD::Signature & signature ,
const NOMAD::Point & incumbent ,
int mesh_index ,
NOMAD::dd_type display_degree ,
NOMAD::Evaluator_Control & ev_control ) const
{
int n = x.size();
NOMAD::Eval_Point * tk = new NOMAD::Eval_Point ( n , _p.get_bb_nb_outputs() );
// if the search is optimistic, a direction is computed (this
// will be used in case of success in the speculative search):
if ( _p.get_model_search_optimistic() ) {
NOMAD::Direction dir ( n , 0.0 , NOMAD::MODEL_SEARCH_DIR );
dir.Point::operator = ( x - incumbent );
tk->set_direction ( &dir );
}
tk->set_signature ( &signature );
tk->set_mesh_index ( &mesh_index );
tk->Point::operator = ( x );
// add the new point to the list of search trial points:
ev_control.add_eval_point ( tk ,
display_degree ,
_p.get_snap_to_bounds() ,
NOMAD::Double() ,
NOMAD::Double() ,
NOMAD::Double() ,
NOMAD::Double() );
#ifdef MODEL_STATS
if ( tk ) {
NOMAD::Double h1 , f1;
if ( _model->predict ( *tk , true ) ) // pred_outside_bnds = true
_model->eval_hf ( tk->get_bb_outputs() ,
_p.get_h_min() ,
_p.get_h_norm() ,
h1 ,
f1 );
if ( h1.is_defined() && f1.is_defined() ) {
tk->set_mod_use ( 1 ); // 1 for model search
tk->set_Yw ( _model->get_Yw() );
tk->set_nY ( model.get_p () );
tk->set_mh ( h1 );
tk->set_mf ( f1 );
}
}
#endif
}
/*---------------------------------------------------------------*/
/* model construction (private) */
/*---------------------------------------------------------------*/
bool NOMAD::TGP_Model_Search::model_construction
( const NOMAD::Cache & cache ,
const NOMAD::Point & incumbent ,
const NOMAD::Point & delta_m ,
const NOMAD::Display & out ,
NOMAD::dd_type display_degree ,
int display_lim ,
NOMAD::Stats & stats ,
bool & compute_Ds2x ,
std::vector & XX ,
bool & stop ,
NOMAD::stop_type & stop_reason ,
std::string & error_str )
{
int i , n_XX , n = incumbent.size();
compute_Ds2x = false;
// reset XX:
{
n_XX = XX.size();
for ( i = 0 ; i < n_XX ; ++i )
delete XX[i];
XX.clear();
n_XX = 0;
}
error_str.clear();
if ( stop )
return false;
NOMAD::Clock clock;
// TGP model creation:
if ( _model )
delete _model;
NOMAD::TGP_mode_type tgp_mode = _p.get_model_tgp_mode();
_model = new NOMAD::TGP_Model ( n ,
_p.get_bb_output_type() ,
out ,
tgp_mode );
// construct interpolation set (X):
// --------------------------------
if ( !_model->set_X ( cache ,
&incumbent ,
_p.get_seed() ,
true ) ) { // remove_fv = true
if ( _model->get_nep_flag() )
_one_search_stats.add_not_enough_pts();
stats.update_model_stats ( _one_search_stats );
_all_searches_stats.update ( _one_search_stats );
error_str = _model->get_error_str();
delete _model;
_model = NULL;
return false;
}
// create the list of prediction points (XX)
// (they are used to get starting points
// and to get IMPROV and DS2X stats):
// -----------------------------------
set_XX ( cache ,
n ,
_p.get_bb_output_type().size() ,
incumbent ,
delta_m ,
XX );
n_XX = XX.size();
// display sets X and XX:
// ----------------------
#ifdef TGP_DEBUG
// X:
_model->display_X ( out , display_lim );
// XX (only the 10 last points are displayed):
out << NOMAD::open_block ( "prediction points (XX)");
int i0 = ( display_lim > 0 ) ? n_XX - display_lim : 0;
if ( i0 > 0 )
out << "..." << std::endl;
else if ( i0 < 0 )
i0 = 0;
for ( i = i0 ; 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
// model construction:
// -------------------
int p = _model->get_p(); // number of points in X
if ( display_degree == NOMAD::FULL_DISPLAY ) {
out << "TGP model construction (p="
<< p << ") ...";
out.flush();
}
// decide compute_Ds2x flag:
compute_Ds2x = true;
if ( tgp_mode == NOMAD::TGP_PRECISE && n_XX > 100 )
compute_Ds2x = false;
if ( !_model->compute ( XX ,
compute_Ds2x ,
true , // compute_improv = true
false ) ) { // pred_outside_bnds = false
_one_search_stats.add_construction_error();
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "... error" << std::endl;
// delete XX points:
for ( i = 0 ; i < n_XX ; ++i )
delete XX[i];
XX.clear();
n_XX = 0;
stats.update_model_stats ( _one_search_stats );
_all_searches_stats.update ( _one_search_stats );
error_str = _model->get_error_str();
delete _model;
_model = NULL;
// check if ctrl-c has been pressed:
if ( NOMAD::TGP_Output_Model::get_force_quit() ) {
stop = true;
stop_reason = NOMAD::CTRL_C;
}
return false;
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << "... OK" << std::endl << std::endl;
// update model stats:
_one_search_stats.add_construction_time ( clock.get_CPU_time() );
_one_search_stats.update_nY ( p );
_one_search_stats.add_nb_truth();
_one_search_stats.add_nb_TGP();
return true;
}
/*---------------------------------------------------------------*/
/* optimize a model (private) */
/*---------------------------------------------------------------*/
bool NOMAD::TGP_Model_Search::optimize_model
( const NOMAD::Eval_Point * x0s[3] ,
const NOMAD::Display & out ,
NOMAD::dd_type display_degree ,
NOMAD::Point *& xf ,
NOMAD::Point *& xi ,
bool & stop ,
NOMAD::stop_type & stop_reason )
{
// reset xf and xi:
if ( xf ) delete xf; xf = NULL;
if ( xi ) delete xi; xi = NULL;
if ( !_model ) {
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl << "model optimization error (no model)"
<< std::endl;
return false;
}
std::string error_str;
bool error = false;
int i , n = _model->get_n0();
// model bounds:
const NOMAD::Point & lb = _model->get_lb();
const NOMAD::Point & ub = _model->get_ub();
// initial displays:
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl << NOMAD::open_block ( "model optimization" );
// parameters creation:
NOMAD::Parameters model_param ( out );
// random seed:
model_param.set_SEED ( _p.get_seed() + 10 * _all_searches_stats.get_MS_nb_searches() );
// number of variables:
model_param.set_DIMENSION ( n );
// blackbox outputs:
model_param.set_BB_OUTPUT_TYPE ( _p.get_bb_output_type() );
// blackbox inputs:
model_param.set_BB_INPUT_TYPE ( _p.get_bb_input_type() );
// barrier parameters:
model_param.set_H_MIN ( _p.get_h_min () );
model_param.set_H_NORM ( _p.get_h_norm() );
// starting points:
for ( i = 0 ; i < 3 ; ++i )
if ( x0s[i] )
model_param.set_X0 ( *x0s[i] );
// fixed variables:
for ( i = 0 ; i < n ; ++i )
if ( lb[i] == ub[i] || _p.variable_is_fixed(i) )
model_param.set_FIXED_VARIABLE(i);
// no model search and no model ordering:
model_param.set_MODEL_SEARCH ( false );
model_param.set_MODEL_EVAL_SORT ( false );
// display:
model_param.set_DISPLAY_DEGREE ( NOMAD::NO_DISPLAY );
if ( display_degree == NOMAD::FULL_DISPLAY ) {
model_param.set_DISPLAY_DEGREE ( NOMAD::NORMAL_DISPLAY );
// model_param.set_DISPLAY_DEGREE ( NOMAD::FULL_DISPLAY );
if ( n <= 5 )
model_param.set_DISPLAY_STATS ( "bbe mesh_index ( %14.12gsol ) %14.12gobj" );
else if ( n <= 10 )
model_param.set_DISPLAY_STATS ( "bbe mesh_index ( sol ) obj" );
else
model_param.set_DISPLAY_STATS ( "bbe obj" );
}
// mesh:
int mesh_index = NOMAD::Mesh::get_mesh_index();
int min_mesh_index = NOMAD::Mesh::get_min_mesh_index();
int max_mesh_index = NOMAD::Mesh::get_max_mesh_index();
int max_halton_index = NOMAD::Mesh::get_max_halton_index();
NOMAD::Mesh::init ( 4.0 , 1 , -1 , 0 );
// searches:
// model_param.set_LH_SEARCH ( 1000 , 100 );
// model_param.set_OPPORTUNISTIC_LH ( true );
// model_param.set_VNS_SEARCH ( true );
// maximum number of evaluations (2000 or 10000):
model_param.set_MAX_BB_EVAL
( ( _p.get_model_tgp_mode() == NOMAD::TGP_PRECISE ) ? 10000 : 2000 );
// min mesh size:
// model_param.set_MAX_MESH_INDEX ( 30 );
// model_param.set_MIN_MESH_SIZE ( NOMAD::Double ( 1e-8 ) , false );
model_param.set_SNAP_TO_BOUNDS ( true );
// model_param.set_SNAP_TO_BOUNDS ( false );
// disable user calls:
model_param.set_USER_CALLS_ENABLED ( false );
// set flags:
bool flag_check_bimads , flag_reset_mesh , flag_reset_barriers , flag_p1_active;
NOMAD::Mads::get_flags ( flag_check_bimads ,
flag_reset_mesh ,
flag_reset_barriers ,
flag_p1_active );
NOMAD::Mads::set_flag_check_bimads ( true );
NOMAD::Mads::set_flag_reset_mesh ( true );
NOMAD::Mads::set_flag_reset_barriers ( true );
NOMAD::Mads::set_flag_p1_active ( false );
// bounds:
model_param.set_LOWER_BOUND ( lb );
model_param.set_UPPER_BOUND ( ub );
try {
// parameters validation:
model_param.check();
// out << "TGP PARAMETERS:" << std::endl << model_param << std::endl;
// model evaluator creation:
NOMAD::TGP_Model_Evaluator ev ( model_param , *_model );
// algorithm creation and execution:
NOMAD::Mads mads ( model_param , &ev );
NOMAD::stop_type st = mads.run();
// check the stopping criterion:
if ( st == NOMAD::CTRL_C || st == NOMAD::MAX_CACHE_MEMORY_REACHED ) {
std::ostringstream oss;
oss << "model optimization: " << st;
error_str = oss.str();
error = true;
stop = true;
stop_reason = st;
}
else if ( st == NOMAD::MAX_BB_EVAL_REACHED )
_one_search_stats.add_MS_max_bbe();
// update the stats on the number of model evaluations:
_one_search_stats.update_MS_model_opt ( mads.get_stats().get_bb_eval() );
// get the solution(s):
const NOMAD::Eval_Point * best_feas = mads.get_best_feasible ();
const NOMAD::Eval_Point * best_infeas = mads.get_best_infeasible();
if ( best_feas )
xf = new NOMAD::Point ( *best_feas );
if ( best_infeas )
xi = new NOMAD::Point ( *best_infeas );
if ( !xf && !xi ) {
error = true;
error_str = "optimization error: no solution";
}
}
catch ( std::exception & e ) {
error = true;
error_str = std::string ( "optimization error: " ) + e.what();
}
// reset flags:
NOMAD::Mads::set_flag_check_bimads ( flag_check_bimads );
NOMAD::Mads::set_flag_reset_mesh ( flag_reset_mesh );
NOMAD::Mads::set_flag_reset_barriers ( flag_reset_barriers );
NOMAD::Mads::set_flag_p1_active ( flag_p1_active );
// reset mesh to what it was before:
NOMAD::Mesh::init ( _p.get_mesh_update_basis().value() ,
_p.get_mesh_coarsening_exponent() ,
_p.get_mesh_refining_exponent() ,
_p.get_initial_mesh_index() );
NOMAD::Mesh::set_max_halton_index ( max_halton_index );
NOMAD::Mesh::set_mesh_index ( min_mesh_index );
NOMAD::Mesh::set_mesh_index ( max_mesh_index );
NOMAD::Mesh::set_mesh_index ( mesh_index );
// close display block:
if ( display_degree == NOMAD::FULL_DISPLAY ) {
if ( error )
out.close_block ( error_str );
else
out.close_block();
}
return !error;
}
/*---------------------------------------------------------*/
/* display the prediction error for the evaluated points */
/* (private) */
/*---------------------------------------------------------*/
bool NOMAD::TGP_Model_Search::predict ( const NOMAD::Point & x ,
NOMAD::Double & h ,
NOMAD::Double & f ) const
{
h.clear();
f.clear();
if ( !_model )
return false;
NOMAD::Eval_Point y ( x.size() , _p.get_bb_nb_outputs() );
y.NOMAD::Point::operator = ( x );
if ( _model->predict ( y , true ) ) // pred_outside_bnds = true
_model->eval_hf ( y.get_bb_outputs() , _p.get_h_min() , _p.get_h_norm() , h , f );
return ( h.is_defined() && f.is_defined() );
}
/*---------------------------------------------------------*/
/* display the prediction error for the evaluated points */
/* (private) */
/*---------------------------------------------------------*/
void NOMAD::TGP_Model_Search::display_eval_pred_errors
( const std::list & evaluated_pts ,
const NOMAD::Display & out )
{
if ( !_model )
return;
int i , j = 0;
int nb_pts = evaluated_pts.size() ,
n = _model->get_n0() ,
m = _p.get_bb_nb_outputs();
const NOMAD::Double & h_min = _p.get_h_min();
NOMAD::hnorm_type h_norm = _p.get_h_norm();
NOMAD::Double h , f , hm , fm , err;
NOMAD::Eval_Point x ( n , m );
out << std::endl << NOMAD::open_block ( "evaluated points" );
std::list::const_iterator it , end = evaluated_pts.end();
for ( it = evaluated_pts.begin() ; it != end ; ++it ) {
if ( !(*it) )
continue;
h = (*it)->get_h();
f = (*it)->get_f();
for ( i = 0 ; i < n ; ++i )
x[i] = (**it)[i];
_model->predict ( x , true ); // pred_outside_bnds = true
_model->eval_hf ( x.get_bb_outputs(), h_min , h_norm , hm , fm );
out << "#";
out.display_int_w ( j++ , nb_pts );
out << " x=(";
if ( n < 5 )
(*it)->NOMAD::Point::display ( out , " " , 6 , -1 );
else
(*it)->NOMAD::Point::display ( out , " " , -1 , 20 );
out << ")";
if ( _p.has_constraints() ) {
err = (h.is_defined() && hm.is_defined()) ? h.rel_err(hm) * 100.0 : 100.0;
out << " [h=";
h.display ( out , "%11.3g" );
out << " hm=";
hm.display ( out , "%11.3g" );
out << " err_h=";
err.display ( out , "%.2f" );
out << "%]";
}
err = (f.is_defined() && fm.is_defined()) ? f.rel_err(fm) * 100.0 : 100.0;
out << " [f=";
f.display ( out , "%11.3g" );
out << " fm=";
fm.display ( out , "%11.3g" );
out << " err_f=";
err.display ( out , "%.2f" );
out << "%]" << std::endl;
}
out.close_block();
}
#endif