/*-------------------------------------------------------------------------------------*/
/* 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 Eval_Point.cpp
\brief Evaluation point (implementation)
\author Sebastien Le Digabel
\date 2010-04-14
\see Eval_Point.hpp
*/
#include "Cache_File_Point.hpp"
#include "Eval_Point.hpp"
#include "Slave.hpp"
/*-----------------------------------*/
/* static members initialization */
/*-----------------------------------*/
int NOMAD::Eval_Point::_current_tag = 0;
/*---------------------------------------------------------------------*/
/* constructor 1 */
/*---------------------------------------------------------------------*/
NOMAD::Eval_Point::Eval_Point ( void )
: _tag ( NOMAD::Eval_Point::_current_tag++ ) ,
_signature ( NULL ) ,
_in_cache ( false ) ,
_current_run ( false ) ,
_eval_type ( NOMAD::TRUTH ) ,
_direction ( NULL ) ,
_mesh_index ( NULL ) ,
_poll_center_type ( NOMAD::UNDEFINED_POLL_CENTER_TYPE ) ,
_eval_status ( NOMAD::UNDEFINED_STATUS ) ,
_EB_ok ( true )
{
#ifdef MODEL_STATS
_mod_use = -1;
_nY = -1;
#endif
}
/*---------------------------------------------------------------------*/
/* constructor 2 */
/*---------------------------------------------------------------------*/
NOMAD::Eval_Point::Eval_Point ( int n , int m )
: NOMAD::Point ( n ) ,
_tag ( NOMAD::Eval_Point::_current_tag++ ) ,
_signature ( NULL ) ,
_in_cache ( false ) ,
_current_run ( false ) ,
_eval_type ( NOMAD::TRUTH ) ,
_direction ( NULL ) ,
_mesh_index ( NULL ) ,
_poll_center_type ( NOMAD::UNDEFINED_POLL_CENTER_TYPE ) ,
_eval_status ( NOMAD::UNDEFINED_STATUS ) ,
_EB_ok ( true ) ,
_bb_outputs ( m )
{
#ifdef MODEL_STATS
_mod_use = -1;
_nY = -1;
#endif
}
/*---------------------------------------------------------------------*/
/* constructor 3 (used for model evalaution) */
/*---------------------------------------------------------------------*/
NOMAD::Eval_Point::Eval_Point ( const NOMAD::Point & x , int m )
: NOMAD::Point ( x ) ,
_direction ( NULL ) ,
_mesh_index ( NULL ) ,
_bb_outputs ( m )
{
#ifdef MODEL_STATS
_mod_use = -1;
_nY = -1;
#endif
}
/*---------------------------------------------------------------------*/
/* constructor 4 ( used in Cache::load() ) */
/*---------------------------------------------------------------------*/
NOMAD::Eval_Point::Eval_Point ( const NOMAD::Cache_File_Point & x , NOMAD::eval_type et )
: NOMAD::Point ( x.get_n() ) ,
_tag ( NOMAD::Eval_Point::_current_tag++ ) ,
_signature ( NULL ) ,
_in_cache ( false ) ,
_current_run ( false ) ,
_eval_type ( et ) ,
_direction ( NULL ) ,
_mesh_index ( NULL ) ,
_poll_center_type ( NOMAD::UNDEFINED_POLL_CENTER_TYPE ) ,
_EB_ok ( true ) ,
_bb_outputs ( x.get_bb_outputs() )
{
int n = size();
for ( int i = 0 ; i < n ; ++i )
(*this)[i] = x.get_coord(i);
switch ( x.get_eval_status() ) {
case 0:
_eval_status = NOMAD::EVAL_FAIL;
break;
case 1:
_eval_status = NOMAD::EVAL_OK;
break;
case 2:
_eval_status = NOMAD::EVAL_IN_PROGRESS;
break;
case 3:
_eval_status = NOMAD::UNDEFINED_STATUS;
break;
}
#ifdef MODEL_STATS
_mod_use = -1;
_nY = -1;
#endif
}
/*---------------------------------------------------------------------*/
/* copy constructor */
/*---------------------------------------------------------------------*/
NOMAD::Eval_Point::Eval_Point ( const Eval_Point & x )
: NOMAD::Point ( x.get_n() ) ,
_tag ( NOMAD::Eval_Point::_current_tag++ ) ,
_signature ( x._signature ) ,
_f ( x._f ) ,
_h ( x._h ) ,
_in_cache ( x._in_cache ) ,
_current_run ( x._current_run ) ,
_eval_type ( x._eval_type ) ,
_direction ( NULL ) ,
_mesh_index ( NULL ) ,
_poll_center_type ( x._poll_center_type ) ,
_eval_status ( x._eval_status ) ,
_EB_ok ( x._EB_ok ) ,
_bb_outputs ( x.get_bb_outputs() ) ,
_user_eval_priority ( x._user_eval_priority ) ,
_rand_eval_priority ( x._rand_eval_priority )
{
// point coordinates:
int n = size();
for ( int i = 0 ; i < n ; ++i )
(*this)[i] = x[i];
// _direction:
if ( x._direction )
_direction = new Direction ( *x._direction );
// _mesh_index:
if ( x._mesh_index ) {
_mesh_index = new int;
*_mesh_index = *x._mesh_index;
}
#ifdef MODEL_STATS
set_model_data ( x );
#endif
}
/*---------------------------------------------------------------------*/
/* destructor */
/*---------------------------------------------------------------------*/
NOMAD::Eval_Point::~Eval_Point ( void )
{
if (_mesh_index)
delete _mesh_index;
if (_direction)
delete _direction;
}
/*-------------------------------------------------------*/
/* SET methods used to complete a default construction */
/*-------------------------------------------------------*/
void NOMAD::Eval_Point::set ( int n , int m )
{
reset ( n );
_bb_outputs.reset ( m );
}
void NOMAD::Eval_Point::set ( const NOMAD::Point & x , int m )
{
NOMAD::Point::operator = ( x );
_bb_outputs.reset ( m );
}
/*-------------------------------------------------------*/
/* manually set the tag of a point */
/* (used in parallel version so that all points have */
/* still unique tags */
/*-------------------------------------------------------*/
void NOMAD::Eval_Point::set_tag ( int tag )
{
_tag = tag;
NOMAD::Eval_Point::_current_tag = tag+1;
}
/*---------------------------------------------------------------------*/
/* SET methods for _direction and _mesh_index */
/*---------------------------------------------------------------------*/
void NOMAD::Eval_Point::set_mesh_index ( const int * ell )
{
delete _mesh_index;
_mesh_index = NULL;
if ( ell ) {
_mesh_index = new int;
*_mesh_index = *ell;
}
}
void NOMAD::Eval_Point::set_direction ( const NOMAD::Direction * dir )
{
delete _direction;
_direction = ( dir ) ? new NOMAD::Direction ( *dir ) : NULL;
}
void NOMAD::Eval_Point::set_poll_center ( const NOMAD::Eval_Point * pc )
{
_poll_center=pc;
}
/*-------------------------------------------------------*/
/* set the signature */
/*-------------------------------------------------------*/
void NOMAD::Eval_Point::set_signature ( NOMAD::Signature * s )
{
if ( !s ) {
_signature = NULL;
return;
}
if ( !s->is_compatible(*this) )
throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
"x.Eval_Point::set_signature(s): x and s are incompatible" );
_signature = s;
}
/*------------------------------------------*/
/* get the signature */
/*------------------------------------------*/
NOMAD::Signature * NOMAD::Eval_Point::get_signature ( void ) const
{
#ifdef USE_MPI
if ( !NOMAD::Slave::is_master() )
throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
"Eval_Point::get_signature(): cannot be invoked by slave processes" );
#endif
return _signature;
}
/*-------------------------------------------------------*/
/* sizeof */
/*-------------------------------------------------------*/
int NOMAD::Eval_Point::size_of ( void ) const
{
return NOMAD::Point::size_of () +
_bb_outputs.size_of () +
_f.size_of () +
_h.size_of () +
_user_eval_priority.size_of() +
_rand_eval_priority.size_of() +
sizeof (_tag ) +
sizeof (NOMAD::Signature * ) +
sizeof (_current_run ) +
sizeof (_in_cache ) +
sizeof (_eval_type ) +
sizeof (_eval_status ) +
sizeof (_EB_ok ) +
sizeof (_mesh_index ) +
sizeof (_direction ) +
(( _mesh_index ) ? sizeof(*_mesh_index) : 0) +
((_direction ) ? _direction->size_of() : 0);
}
/*-------------------------------------------------------*/
/* scaling */
/*-------------------------------------------------------*/
void NOMAD::Eval_Point::scale ( void )
{
if ( !_signature )
throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
"x.Eval_Point::scale(): x has no signature" );
_signature->scale ( *this );
}
/*-------------------------------------------------------*/
/* unscaling */
/*-------------------------------------------------------*/
void NOMAD::Eval_Point::unscale ( void )
{
if ( !_signature )
throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
"x.Eval_Point::unscale(): x has no signature" );
_signature->unscale ( *this );
}
/*-------------------------------------------------------*/
/* snap to bounds */
/* returns true if the point has been modified */
/*-------------------------------------------------------*/
bool NOMAD::Eval_Point::snap_to_bounds ( void )
{
if ( !_signature )
throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
"x.Eval_Point::snap_to_bounds(): x has no signature" );
return _signature->snap_to_bounds ( *this , _direction );
}
/*-------------------------------------------------------*/
/* treat the periodic variables */
/* returns true if the point has been modified */
/*-------------------------------------------------------*/
bool NOMAD::Eval_Point::treat_periodic_variables ( NOMAD::Direction *& new_dir )
{
if (!_signature)
throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
"x.Eval_Point::treat_periodic_variables(): x has no signature" );
return _signature->treat_periodic_variables ( *this , _direction , new_dir );
}
/*--------------------------------------------------*/
/* Eval_Point::check */
/*--------------------------------------------------*/
bool NOMAD::Eval_Point::check ( int m , NOMAD::check_failed_type & cf ) const
{
if ( size() <= 0 || !_signature || m != _bb_outputs.size() ) {
std::string err = "Eval_Point::check() could not procede";
if ( !_signature )
err += " (no signature)";
else if ( m != _bb_outputs.size() )
err += " (wrong number of blackbox outputs)";
else
err += " (point size <= 0 !)";
throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ , err );
}
cf = NOMAD::CHECK_OK;
const std::vector
& input_types = _signature->get_input_types();
const NOMAD::Point & lb = _signature->get_lb();
const NOMAD::Point & ub = _signature->get_ub();
const NOMAD::Point & fv = _signature->get_fixed_variables();
int n = size();
NOMAD::bb_input_type iti;
for ( int i = 0 ; i < n ; ++i ) {
const NOMAD::Double xi = (*this)[i];
// undefined coordinates ?
if ( !xi.is_defined() )
throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
"Eval_Point::check() could not procede (undefined coordinates)" );
// check the bounds:
const NOMAD::Double & lbi = lb[i];
if ( lbi.is_defined() && xi < lbi ) {
cf = NOMAD::LB_FAIL;
return false;
}
const NOMAD::Double & ubi = ub[i];
if ( ubi.is_defined() && xi > ubi ) {
cf = NOMAD::UB_FAIL;
return false;
}
// check the integer/categorical/binary variables:
iti = input_types[i];
if ( iti == NOMAD::BINARY && !xi.is_binary() ) {
cf = NOMAD::BIN_FAIL;
return false;
}
if ( ( iti == NOMAD::INTEGER || iti == NOMAD::CATEGORICAL )
&& !xi.is_integer() ) {
cf = ( iti == NOMAD::INTEGER ) ? NOMAD::INT_FAIL : NOMAD::CAT_FAIL;
return false;
}
// check the fixed-variables:
const NOMAD::Double & fvi = fv[i];
if ( fvi.is_defined() && fvi != xi ) {
cf = NOMAD::FIX_VAR_FAIL;
return false;
}
}
return true;
}
/*--------------------------------------------------*/
/* display the tag */
/*--------------------------------------------------*/
void NOMAD::Eval_Point::display_tag ( const NOMAD::Display & out ) const
{
out << "#";
out.display_int_w ( _tag , NOMAD::Eval_Point::_current_tag );
}
/*--------------------------------------------------*/
/* display */
/*--------------------------------------------------*/
void NOMAD::Eval_Point::display ( const NOMAD::Display & out , bool in_block ) const
{
if ( in_block ) {
std::ostringstream oss;
oss << "#" << _tag;
out << NOMAD::open_block ( oss.str() )
<< "x = ( ";
NOMAD::Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
out << " )" << std::endl
<< "F(x) = [ ";
_bb_outputs.display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
out << " ]" << std::endl;
if ( _h.is_defined() )
out << "h = " << _h << std::endl;
if ( _f.is_defined() )
out << "f = " << _f << std::endl;
out.close_block();
}
else {
display_tag ( out );
out << " x=( ";
NOMAD::Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
out << " ) F(x)=[ ";
_bb_outputs.display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
out << " ]";
if ( _h.is_defined() )
out << " h=" << _h;
if ( _f.is_defined() )
out << " f=" << _f;
}
}
/*--------------------------------------------------------------*/
/* comparison operator '<': used to find and store the points */
/* in the filter */
/*--------------------------------------------------------------*/
bool NOMAD::Eval_Point::operator < ( const NOMAD::Eval_Point & x ) const
{
if ( this == &x || !is_eval_ok() || !_EB_ok )
return false;
double h = _h.value();
double f = _f.value();
double hx = x._h.value();
double fx = x._f.value();
if ( h < hx )
return ( f <= fx );
if ( h == hx )
return ( f < fx );
return false;
}
/*--------------------------------------------------------------*/
/* check if there are nan's in the blackbox outputs */
/*--------------------------------------------------------------*/
bool NOMAD::Eval_Point::check_nan ( void ) const
{
int m = _bb_outputs.size();
for ( int i = 0 ; i < m ; ++i ) {
if ( _bb_outputs[i].is_defined() ) {
#ifdef WINDOWS
if ( isnan ( _bb_outputs[i].value() ) )
return true;
#else
if ( std::isnan ( _bb_outputs[i].value() ) )
return true;
#endif
}
}
return false;
}
#ifdef MODEL_STATS
/*--------------------------------------------------------------*/
/* set model data when debugging models */
/*--------------------------------------------------------------*/
void NOMAD::Eval_Point::set_model_data ( const NOMAD::Eval_Point & x ) const
{
_mod_use = x._mod_use;
_nY = x._nY;
_cond = x._cond;
_Yw = x._Yw;
_mh = x._mh;
_mf = x._mf;
}
/*--------------------------------------------------------------*/
/* clear model data */
/*--------------------------------------------------------------*/
void NOMAD::Eval_Point::clear_model_data ( void ) const
{
_mod_use = -1;
_nY = -1;
_cond.clear();
_Yw.clear();
_mh.clear();
_mf.clear();
}
#endif