/*-------------------------------------------------------------------------------------*/
/* 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 Phase_One_Search.cpp
\brief NOMAD::Search subclass for the phase one (implementation)
\author Sebastien Le Digabel
\date 2010-04-09
\see Phase_One_Search.hpp
*/
#include "Phase_One_Search.hpp"
/*-------------------------------------------------------------*/
/* phase one search */
/* (try to satisfy EB constraints) */
/*-------------------------------------------------------------*/
void NOMAD::Phase_One_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;
stop = false;
count_search = true;
const NOMAD::Display & out = _p.out();
NOMAD::dd_type display_degree = out.get_search_dd();
// initial display:
if ( display_degree == NOMAD::FULL_DISPLAY )
{
std::ostringstream oss;
oss << NOMAD::P1_SEARCH;
out << std::endl << NOMAD::open_block ( oss.str() ) << std::endl;
}
// stats:
NOMAD::Stats & stats = mads.get_stats();
// counters:
int old_bbe = stats.get_bb_eval();
int old_it = stats.get_iterations();
// Evaluator_Control:
NOMAD::Evaluator_Control & ev_control = mads.get_evaluator_control();
// save and modify parameters:
std::string old_display_degree;
_p.out().get_display_degree ( old_display_degree );
const std::list old_ds = _p.get_display_stats();
NOMAD::Double old_VNS_trigger = _p.get_VNS_trigger();
const std::string old_stats_file_name = _p.get_stats_file_name();
const std::string old_sol_file = _p.get_solution_file();
const std::list old_stats_file = _p.get_stats_file();
const NOMAD::Point old_f_target = _p.get_f_target();
NOMAD::Double old_lct = _p.get_L_curve_target();
bool old_sif = _p.get_stop_if_feasible();
const std::vector old_bbot = _p.get_bb_output_type();
std::vector p1_bbot = old_bbot;
if ( display_degree == NOMAD::NORMAL_DISPLAY) // Normal display -> minimal display for Phase one
_p.set_DISPLAY_DEGREE( NOMAD::MINIMAL_DISPLAY);
else if (display_degree == NOMAD::FULL_DISPLAY)
_p.set_DISPLAY_DEGREE( NOMAD::FULL_DISPLAY);// Full display -> full display for Phase one
int m = static_cast ( old_bbot.size() );
int cnt = 0;
for ( int i = 0 ; i < m ; ++i ) {
if ( old_bbot[i] == NOMAD::EB ) {
p1_bbot[i] = NOMAD::OBJ;
++cnt;
}
else if ( old_bbot[i] == NOMAD::OBJ )
p1_bbot[i] = NOMAD::UNDEFINED_BBO;
}
if ( cnt == 0 ) {
stop = true;
stop_reason = NOMAD::P1_FAIL;
return;
}
_p.set_F_TARGET ( NOMAD::Point ( cnt , 0.0 ) );
_p.set_L_CURVE_TARGET ( NOMAD::Double() );
_p.set_STOP_IF_FEASIBLE ( false );
_p.set_VNS_SEARCH ( false );
_p.set_BB_OUTPUT_TYPE ( p1_bbot );
_p.set_SOLUTION_FILE ( "" );
_p.reset_stats_file();
// DISPLAY_STATS and STATS_FILE
{
std::list ds = old_ds;
std::list sf = old_stats_file;
ds.push_back ( " (PhaseOne)" );
_p.set_DISPLAY_STATS ( ds );
sf.push_back ( " (PhaseOne)" );
_p.set_STATS_FILE ( old_stats_file_name , sf );
}
_p.check ( false , // remove_history_file = false
true , // remove_solution_file = true
false ); // remove_stats_file = false
// modify evaluator:
NOMAD::Evaluator * old_ev = ev_control.get_evaluator();
NOMAD::Phase_One_Evaluator * p1ev = new NOMAD::Phase_One_Evaluator ( _p , *old_ev );
ev_control.set_evaluator ( p1ev );
// disable the Pareto front:
NOMAD::Pareto_Front * old_pareto_front = mads.get_pareto_front();
mads.set_pareto_front ( NULL );
int old_eval = stats.get_eval();
// run MADS with modified parameters:
// ----------------------------------
// C. Tribes march 2013 ---- these flags are mads static and must be put back to their original value after running mads (see below)
// get 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 );
// set flags:
NOMAD::Mads::set_flag_check_bimads ( false );
NOMAD::Mads::set_flag_reset_mesh ( false );
NOMAD::Mads::set_flag_p1_active ( true );
NOMAD::Mads::set_flag_reset_barriers ( true );
// run:
stop_reason = mads.run();
// reset stopping condition:
if ( stop_reason == NOMAD::F_TARGET_REACHED ) {
// stop if feasible:
if ( old_sif ) {
stop = true;
stop_reason = NOMAD::FEAS_REACHED;
}
// continue:
else {
stop = false;
stop_reason = NOMAD::NO_STOP;
}
}
else
stop = true;
// reset flags to there previous state :
// C. Tribes march 2013 ---- these flags are mads static and must be put back to their original value after running mads
NOMAD::Mads::set_flag_check_bimads ( flag_check_bimads );
NOMAD::Mads::set_flag_reset_mesh ( flag_reset_mesh );
NOMAD::Mads::set_flag_p1_active ( flag_p1_active );
NOMAD::Mads::set_flag_reset_barriers ( flag_reset_barriers );
// NOMAD::Mads::set_flag_check_bimads ( true );
// NOMAD::Mads::set_flag_reset_mesh ( true );
// NOMAD::Mads::set_flag_p1_active ( false );
// number of search points:
nb_search_pts = stats.get_eval() - old_eval;
// restore evaluator:
ev_control.set_evaluator ( old_ev );
delete p1ev;
// restore the Pareto front:
mads.set_pareto_front ( old_pareto_front );
// restore parameters:
_p.set_VNS_SEARCH ( old_VNS_trigger );
_p.set_F_TARGET ( old_f_target );
_p.set_L_CURVE_TARGET ( old_lct );
_p.set_BB_OUTPUT_TYPE ( old_bbot );
_p.set_DISPLAY_DEGREE ( old_display_degree );
_p.set_SOLUTION_FILE ( old_sol_file );
_p.reset_stats_file();
_p.set_STATS_FILE ( old_stats_file_name , old_stats_file );
_p.set_DISPLAY_STATS (old_ds);
_p.check ( false , // remove_history_file = false
true , // remove_solution_file = true
false ); // remove_stats_file = true
// reset mesh index:
NOMAD::Mesh::set_mesh_index ( _p.get_initial_mesh_index() );
// counters:
stats.add_p1_iterations ( stats.get_iterations() - old_it );
stats.add_p1_bbe ( stats.get_bb_eval () - old_bbe );
// for the update of new_feas_inc and new_infeas_inc (1/2):
const NOMAD::Barrier & active_barrier = mads.get_active_barrier();
const NOMAD::Eval_Point * old_feasible_incumbent = NULL;
const NOMAD::Eval_Point * old_infeasible_incumbent = NULL;
old_feasible_incumbent = active_barrier.get_best_feasible();
old_infeasible_incumbent = active_barrier.get_best_infeasible();
// update the barriers and compute the true values
// of f and h for all evaluated points:
NOMAD::Barrier & true_barrier = mads.get_true_barrier();
NOMAD::Barrier & sgte_barrier = mads.get_sgte_barrier();
true_barrier.reset();
sgte_barrier.reset();
// scan the active cache:
const NOMAD::Cache & active_cache = mads.get_cache();
if ( active_cache.empty() ) {
stop = true;
stop_reason = NOMAD::P1_FAIL;
return;
}
const NOMAD::Eval_Point * cur = active_cache.begin();
while ( cur ) {
if ( cur->get_current_run() && cur->is_eval_ok() ) {
NOMAD::Eval_Point * modifiable_x = &NOMAD::Cache::get_modifiable_point ( *cur );
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() );
old_ev->compute_f ( *modifiable_x );
old_ev->compute_h ( *modifiable_x );
// insertion in barrier:
(( cur->get_eval_type() == NOMAD::TRUTH ) ?
true_barrier : sgte_barrier).insert (*cur);
}
cur = active_cache.next();
}
success = active_barrier.get_success();
if ( !stop && success == NOMAD::UNSUCCESSFUL ) {
stop = true;
stop_reason = NOMAD::P1_FAIL;
return;
}
true_barrier.update_and_reset_success();
sgte_barrier.update_and_reset_success();
// update of new_feas_inc and new_infeas_inc (2/2):
const NOMAD::Eval_Point * bf = active_barrier.get_best_feasible ();
const NOMAD::Eval_Point * bi = active_barrier.get_best_infeasible();
if ( bf && bf != old_feasible_incumbent )
new_feas_inc = bf;
if ( bi && bi != old_infeasible_incumbent )
new_infeas_inc = bi;
// final displays:
if ( bf )
{
// solution file:
ev_control.write_solution_file ( *bf );
// stats_file:
const std::string & stats_file_name = _p.get_stats_file_name();
if ( !stats_file_name.empty() && display_degree > NOMAD::NO_DISPLAY)
ev_control.stats_file ( stats_file_name , bf , true , NULL );
// display_stats
if (display_degree > NOMAD::NO_DISPLAY)
ev_control.display_stats(false, out, old_ds , bf , true , NULL );
}
if ( display_degree == NOMAD::FULL_DISPLAY )
out << std::endl << NOMAD::close_block ( "end of phase one" );
}