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