1 /*-------------------------------------------------------------------------------------*/
2 /* NOMAD - Nonlinear Optimization by Mesh Adaptive Direct search - version 3.7.2 */
3 /* */
4 /* Copyright (C) 2001-2015 Mark Abramson - the Boeing Company, Seattle */
5 /* Charles Audet - Ecole Polytechnique, Montreal */
6 /* Gilles Couture - Ecole Polytechnique, Montreal */
7 /* John Dennis - Rice University, Houston */
8 /* Sebastien Le Digabel - Ecole Polytechnique, Montreal */
9 /* Christophe Tribes - Ecole Polytechnique, Montreal */
10 /* */
11 /* funded in part by AFOSR and Exxon Mobil */
12 /* */
13 /* Author: Sebastien Le Digabel */
14 /* */
15 /* Contact information: */
16 /* Ecole Polytechnique de Montreal - GERAD */
17 /* C.P. 6079, Succ. Centre-ville, Montreal (Quebec) H3C 3A7 Canada */
18 /* e-mail: nomad@gerad.ca */
19 /* phone : 1-514-340-6053 #6928 */
20 /* fax : 1-514-340-5665 */
21 /* */
22 /* This program is free software: you can redistribute it and/or modify it under the */
23 /* terms of the GNU Lesser General Public License as published by the Free Software */
24 /* Foundation, either version 3 of the License, or (at your option) any later */
25 /* version. */
26 /* */
27 /* This program is distributed in the hope that it will be useful, but WITHOUT ANY */
28 /* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A */
29 /* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */
30 /* */
31 /* You should have received a copy of the GNU Lesser General Public License along */
32 /* with this program. If not, see <http://www.gnu.org/licenses/>. */
33 /* */
34 /* You can find information on the NOMAD software at www.gerad.ca/nomad */
35 /*-------------------------------------------------------------------------------------*/
36 /**
37 \file Eval_Point.cpp
38 \brief Evaluation point (implementation)
39 \author Sebastien Le Digabel
40 \date 2010-04-14
41 \see Eval_Point.hpp
42 */
43 #include "Cache_File_Point.hpp"
44 #include "Eval_Point.hpp"
45 #include "Slave.hpp"
46
47 /*-----------------------------------*/
48 /* static members initialization */
49 /*-----------------------------------*/
50 int NOMAD::Eval_Point::_current_tag = 0;
51 int NOMAD::Eval_Point::_current_bbe = 0;
52 int NOMAD::Eval_Point::_current_sgte_bbe = 0;
53 /*---------------------------------------------------------------------*/
54 /* constructor 1 */
55 /*---------------------------------------------------------------------*/
Eval_Point(void)56 NOMAD::Eval_Point::Eval_Point ( void )
57 : _tag ( NOMAD::Eval_Point::_current_tag++ ) ,
58 _signature ( NULL ) ,
59 _in_cache ( false ) ,
60 _current_run ( false ) ,
61 _eval_type ( NOMAD::TRUTH ) ,
62 _direction ( NULL ) ,
63 _poll_center_type ( NOMAD::UNDEFINED_POLL_CENTER_TYPE ) ,
64 _eval_status ( NOMAD::UNDEFINED_STATUS ) ,
65 _EB_ok ( true )
66 {
67 #ifdef MODEL_STATS
68 _mod_use = -1;
69 _nY = -1;
70 #endif
71 }
72
73 /*---------------------------------------------------------------------*/
74 /* constructor 2 */
75 /*---------------------------------------------------------------------*/
Eval_Point(int n,int m)76 NOMAD::Eval_Point::Eval_Point ( int n , int m )
77 : NOMAD::Point ( n ) ,
78 _tag ( NOMAD::Eval_Point::_current_tag++ ) ,
79 _signature ( NULL ) ,
80 _in_cache ( false ) ,
81 _current_run ( false ) ,
82 _eval_type ( NOMAD::TRUTH ) ,
83 _direction ( NULL ) ,
84 _poll_center_type ( NOMAD::UNDEFINED_POLL_CENTER_TYPE ) ,
85 _eval_status ( NOMAD::UNDEFINED_STATUS ) ,
86 _EB_ok ( true ) ,
87 _bb_outputs ( m )
88 {
89 #ifdef MODEL_STATS
90 _mod_use = -1;
91 _nY = -1;
92 #endif
93 }
94
95 /*---------------------------------------------------------------------*/
96 /* constructor 3 (used for model evalaution) */
97 /*---------------------------------------------------------------------*/
Eval_Point(const NOMAD::Point & x,int m)98 NOMAD::Eval_Point::Eval_Point ( const NOMAD::Point & x , int m )
99 : NOMAD::Point ( x ) ,
100 _direction ( NULL ) ,
101 _bb_outputs ( m )
102 {
103 #ifdef MODEL_STATS
104 _mod_use = -1;
105 _nY = -1;
106 #endif
107 }
108
109
110
111
112 /*---------------------------------------------------------------------*/
113 /* constructor 4 ( used in Cache::load() ) */
114 /*---------------------------------------------------------------------*/
Eval_Point(const NOMAD::Cache_File_Point & x,NOMAD::eval_type et)115 NOMAD::Eval_Point::Eval_Point ( const NOMAD::Cache_File_Point & x , NOMAD::eval_type et )
116 : NOMAD::Point ( x.get_n() ) ,
117 _tag ( NOMAD::Eval_Point::_current_tag++ ) ,
118 _signature ( NULL ) ,
119 _in_cache ( false ) ,
120 _current_run ( false ) ,
121 _eval_type ( et ) ,
122 _direction ( NULL ) ,
123 _poll_center_type ( NOMAD::UNDEFINED_POLL_CENTER_TYPE ) ,
124 _EB_ok ( true ) ,
125 _bb_outputs ( x.get_bb_outputs() )
126 {
127 int n = size();
128 for ( int i = 0 ; i < n ; ++i )
129 (*this)[i] = x.get_coord(i);
130
131 switch ( x.get_eval_status() ) {
132 case 0:
133 _eval_status = NOMAD::EVAL_FAIL;
134 break;
135 case 1:
136 _eval_status = NOMAD::EVAL_OK;
137 break;
138 case 2:
139 _eval_status = NOMAD::EVAL_IN_PROGRESS;
140 break;
141 case 3:
142 _eval_status = NOMAD::UNDEFINED_STATUS;
143 break;
144 }
145
146 #ifdef MODEL_STATS
147 _mod_use = -1;
148 _nY = -1;
149 #endif
150 }
151
152
153 /*---------------------------------------------------------------------*/
154 /* copy constructor */
155 /*---------------------------------------------------------------------*/
Eval_Point(const Eval_Point & x)156 NOMAD::Eval_Point::Eval_Point ( const Eval_Point & x )
157 : NOMAD::Point ( x.get_n() ) ,
158 _tag ( NOMAD::Eval_Point::_current_tag++ ) ,
159 _signature ( x._signature ) ,
160 _f ( x._f ) ,
161 _h ( x._h ) ,
162 _in_cache ( x._in_cache ) ,
163 _current_run ( x._current_run ) ,
164 _eval_type ( x._eval_type ) ,
165 _direction ( NULL ) ,
166 _poll_center_type ( x._poll_center_type ) ,
167 _eval_status ( x._eval_status ) ,
168 _EB_ok ( x._EB_ok ) ,
169 _bb_outputs ( x.get_bb_outputs() ) ,
170 _user_eval_priority ( x._user_eval_priority ) ,
171 _rand_eval_priority ( x._rand_eval_priority )
172 {
173 // point coordinates:
174 int n = size();
175 for ( int i = 0 ; i < n ; ++i )
176 (*this)[i] = x[i];
177
178 // _direction:
179 if ( x._direction )
180 _direction = new Direction ( *x._direction );
181
182 #ifdef MODEL_STATS
183 set_model_data ( x );
184 #endif
185 }
186
187 /*---------------------------------------------------------------------*/
188 /* destructor */
189 /*---------------------------------------------------------------------*/
~Eval_Point(void)190 NOMAD::Eval_Point::~Eval_Point ( void )
191 {
192 if ( _direction )
193 delete _direction;
194 }
195
196 /*-------------------------------------------------------*/
197 /* SET methods used to complete a default construction */
198 /*-------------------------------------------------------*/
set(int n,int m)199 void NOMAD::Eval_Point::set ( int n , int m )
200 {
201 reset ( n );
202 _bb_outputs.reset ( m );
203 }
204
set(const NOMAD::Point & x,int m)205 void NOMAD::Eval_Point::set ( const NOMAD::Point & x , int m )
206 {
207 NOMAD::Point::operator = ( x );
208 _bb_outputs.reset ( m );
209 }
210
211 /*-------------------------------------------------------*/
212 /* manually set the tag of a point */
213 /* (used in parallel version so that all points have */
214 /* still unique tags */
215 /*-------------------------------------------------------*/
set_tag(int tag)216 void NOMAD::Eval_Point::set_tag ( int tag )
217 {
218 _tag = tag;
219 NOMAD::Eval_Point::_current_tag = tag+1;
220 }
221
222 /*-------------------------------------------------------*/
223 /* increment counted black box evaluations */
224 /* All points have unique tags */
225 /*-------------------------------------------------------*/
increment_bbe(void)226 void NOMAD::Eval_Point::increment_bbe ( void )
227 {
228 NOMAD::Eval_Point::_current_bbe ++;
229 _bbe=_current_bbe;
230 }
231
232
233 /*-------------------------------------------------------*/
234 /* increment counted black box evaluations */
235 /* All points have unique tags */
236 /*-------------------------------------------------------*/
increment_sgte_bbe(void)237 void NOMAD::Eval_Point::increment_sgte_bbe ( void )
238 {
239 NOMAD::Eval_Point::_current_sgte_bbe ++;
240 _sgte_bbe=_current_sgte_bbe;
241 }
242
243
set_direction(const NOMAD::Direction * dir)244 void NOMAD::Eval_Point::set_direction ( const NOMAD::Direction * dir )
245 {
246 delete _direction;
247 _direction = ( dir ) ? new NOMAD::Direction ( *dir ) : NULL;
248 }
249
set_poll_center(const NOMAD::Eval_Point * pc)250 void NOMAD::Eval_Point::set_poll_center ( const NOMAD::Eval_Point * pc )
251 {
252 _poll_center=pc;
253 }
254
255 /*-------------------------------------------------------*/
256 /* set the signature */
257 /*-------------------------------------------------------*/
set_signature(NOMAD::Signature * s)258 void NOMAD::Eval_Point::set_signature ( NOMAD::Signature * s )
259 {
260 if ( !s ) {
261 _signature = NULL;
262 return;
263 }
264
265 if ( !s->is_compatible(*this) )
266 throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
267 "x.Eval_Point::set_signature(s): x and s are incompatible" );
268
269 _signature = s;
270 }
271
272 /*------------------------------------------*/
273 /* get the signature */
274 /*------------------------------------------*/
get_signature(void) const275 NOMAD::Signature * NOMAD::Eval_Point::get_signature ( void ) const
276 {
277 #ifdef USE_MPI
278 if ( !NOMAD::Slave::is_master() )
279 throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
280 "Eval_Point::get_signature(): cannot be invoked by slave processes" );
281 #endif
282 return _signature;
283 }
284
285 /*-------------------------------------------------------*/
286 /* sizeof */
287 /*-------------------------------------------------------*/
size_of(void) const288 int NOMAD::Eval_Point::size_of ( void ) const
289 {
290 return NOMAD::Point::size_of () +
291 _bb_outputs.size_of () +
292 _f.size_of () +
293 _h.size_of () +
294 _user_eval_priority.size_of() +
295 _rand_eval_priority.size_of() +
296 sizeof (_tag ) +
297 sizeof (NOMAD::Signature * ) +
298 sizeof (_current_run ) +
299 sizeof (_in_cache ) +
300 sizeof (_eval_type ) +
301 sizeof (_eval_status ) +
302 sizeof (_EB_ok ) +
303 sizeof (_direction ) +
304 ((_direction ) ? _direction->size_of() : 0);
305 }
306
307 /*-------------------------------------------------------*/
308 /* scaling */
309 /*-------------------------------------------------------*/
scale(void)310 void NOMAD::Eval_Point::scale ( void )
311 {
312 if ( !_signature )
313 throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
314 "x.Eval_Point::scale(): x has no signature" );
315 _signature->scale ( *this );
316 }
317
318 /*-------------------------------------------------------*/
319 /* unscaling */
320 /*-------------------------------------------------------*/
unscale(void)321 void NOMAD::Eval_Point::unscale ( void )
322 {
323 if ( !_signature )
324 throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
325 "x.Eval_Point::unscale(): x has no signature" );
326 _signature->unscale ( *this );
327 }
328
329 /*-------------------------------------------------------*/
330 /* snap to bounds */
331 /* returns true if the point has been modified */
332 /*-------------------------------------------------------*/
snap_to_bounds(void)333 bool NOMAD::Eval_Point::snap_to_bounds ( void )
334 {
335 if ( !_signature )
336 throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
337 "x.Eval_Point::snap_to_bounds(): x has no signature" );
338 return _signature->snap_to_bounds ( *this , _direction );
339 }
340
341 /*-------------------------------------------------------*/
342 /* treat the periodic variables */
343 /* returns true if the point has been modified */
344 /*-------------------------------------------------------*/
treat_periodic_variables(NOMAD::Direction * & new_dir)345 bool NOMAD::Eval_Point::treat_periodic_variables ( NOMAD::Direction *& new_dir )
346 {
347 if (!_signature)
348 throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
349 "x.Eval_Point::treat_periodic_variables(): x has no signature" );
350
351 return _signature->treat_periodic_variables ( *this , _direction , new_dir );
352 }
353
354 /*--------------------------------------------------*/
355 /* Eval_Point::check */
356 /*--------------------------------------------------*/
check(int m,NOMAD::check_failed_type & cf) const357 bool NOMAD::Eval_Point::check ( int m , NOMAD::check_failed_type & cf ) const
358 {
359 if ( size() <= 0 || !_signature || m != _bb_outputs.size() ) {
360 std::string err = "Eval_Point::check() could not procede";
361 if ( !_signature )
362 err += " (no signature)";
363 else if ( m != _bb_outputs.size() )
364 err += " (wrong number of blackbox outputs)";
365 else
366 err += " (point size <= 0 !)";
367 throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ , err );
368 }
369
370 cf = NOMAD::CHECK_OK;
371
372 const std::vector<NOMAD::bb_input_type>
373 & input_types = _signature->get_input_types();
374 const NOMAD::Point & lb = _signature->get_lb();
375 const NOMAD::Point & ub = _signature->get_ub();
376 const NOMAD::Point & fv = _signature->get_fixed_variables();
377 int n = size();
378 NOMAD::bb_input_type iti;
379
380 for ( int i = 0 ; i < n ; ++i )
381 {
382
383 const NOMAD::Double xi = (*this)[i];
384
385 // undefined coordinates ?
386 if ( !xi.is_defined() )
387 throw NOMAD::Exception ( "Eval_Point.cpp" , __LINE__ ,
388 "Eval_Point::check() could not procede (undefined coordinates)" );
389
390 // check the bounds:
391 const NOMAD::Double & lbi = lb[i];
392 if ( lbi.is_defined() && xi < lbi )
393 {
394 cf = NOMAD::LB_FAIL;
395 return false;
396 }
397
398 const NOMAD::Double & ubi = ub[i];
399 if ( ubi.is_defined() && xi > ubi )
400 {
401 cf = NOMAD::UB_FAIL;
402 return false;
403 }
404
405 // check the integer/categorical/binary variables:
406 iti = input_types[i];
407 if ( iti == NOMAD::BINARY && !xi.is_binary() ) {
408 cf = NOMAD::BIN_FAIL;
409 return false;
410 }
411 if ( ( iti == NOMAD::INTEGER || iti == NOMAD::CATEGORICAL )
412 && !xi.is_integer() ) {
413 cf = ( iti == NOMAD::INTEGER ) ? NOMAD::INT_FAIL : NOMAD::CAT_FAIL;
414 return false;
415 }
416
417 // check the fixed-variables:
418 const NOMAD::Double & fvi = fv[i];
419 if ( fvi.is_defined() && fvi != xi ) {
420 cf = NOMAD::FIX_VAR_FAIL;
421 return false;
422 }
423 }
424 return true;
425 }
426
427 /*--------------------------------------------------*/
428 /* display the tag */
429 /*--------------------------------------------------*/
display_tag(const NOMAD::Display & out) const430 void NOMAD::Eval_Point::display_tag ( const NOMAD::Display & out ) const
431 {
432 out << "#";
433 out.display_int_w ( _tag , NOMAD::Eval_Point::_current_tag );
434 }
435
436 /*--------------------------------------------------*/
437 /* display */
438 /*--------------------------------------------------*/
display_eval(const NOMAD::Display & out,bool in_block) const439 void NOMAD::Eval_Point::display_eval( const NOMAD::Display & out , bool in_block ) const
440 {
441 if ( in_block ) {
442
443 std::ostringstream oss;
444 oss << "#" << _tag;
445 out << NOMAD::open_block ( oss.str() )
446 << "x = ( ";
447 NOMAD::Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
448 out << " )" << std::endl
449 << "F(x) = [ ";
450 _bb_outputs.display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
451 out << " ]" << std::endl;
452 if ( _h.is_defined() )
453 out << "h = " << _h << std::endl;
454 if ( _f.is_defined() )
455 out << "f = " << _f << std::endl;
456 out.close_block();
457 }
458 else {
459 display_tag ( out );
460 out << " x=( ";
461 NOMAD::Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
462 out << " ) F(x)=[ ";
463 _bb_outputs.display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
464 out << " ]";
465 if ( _h.is_defined() )
466 out << " h=" << _h;
467 if ( _f.is_defined() )
468 out << " f=" << _f;
469 }
470 }
471
472 /*--------------------------------------------------------------*/
473 /* comparison operator '<': used to find and store the points */
474 /* in the filter */
475 /*--------------------------------------------------------------*/
operator <(const NOMAD::Eval_Point & x) const476 bool NOMAD::Eval_Point::operator < ( const NOMAD::Eval_Point & x ) const
477 {
478 if ( this == &x || !is_eval_ok() || !_EB_ok )
479 return false;
480
481 double h = _h.value();
482 double f = _f.value();
483 double hx = x._h.value();
484 double fx = x._f.value();
485
486 if ( h < hx )
487 return ( f <= fx );
488
489 if ( h == hx )
490 return ( f < fx );
491
492 return false;
493 }
494
495 /*--------------------------------------------------------------*/
496 /* check if there are nan's in the blackbox outputs */
497 /*--------------------------------------------------------------*/
check_nan(void) const498 bool NOMAD::Eval_Point::check_nan ( void ) const
499 {
500 int m = _bb_outputs.size();
501 for ( int i = 0 ; i < m ; ++i ) {
502 if ( _bb_outputs[i].is_defined() ) {
503 #ifdef WINDOWS
504 if ( isnan ( _bb_outputs[i].value() ) )
505 return true;
506 #else
507 if ( std::isnan ( _bb_outputs[i].value() ) )
508 return true;
509 #endif
510 }
511 }
512 return false;
513 }
514
515 #ifdef MODEL_STATS
516
517 /*--------------------------------------------------------------*/
518 /* set model data when debugging models */
519 /*--------------------------------------------------------------*/
set_model_data(const NOMAD::Eval_Point & x) const520 void NOMAD::Eval_Point::set_model_data ( const NOMAD::Eval_Point & x ) const
521 {
522 _mod_use = x._mod_use;
523 _nY = x._nY;
524 _cond = x._cond;
525 _Yw = x._Yw;
526 _mh = x._mh;
527 _mf = x._mf;
528 }
529
530 /*--------------------------------------------------------------*/
531 /* clear model data */
532 /*--------------------------------------------------------------*/
clear_model_data(void) const533 void NOMAD::Eval_Point::clear_model_data ( void ) const
534 {
535 _mod_use = -1;
536 _nY = -1;
537 _cond.clear();
538 _Yw.clear();
539 _mh.clear();
540 _mf.clear();
541 }
542
543 #endif
544