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 Mads.cpp
38 \brief MADS algorithm (implementation)
39 \author Sebastien Le Digabel
40 \date 2010-04-20
41 \see Mads.hpp
42 */
43 #include "Mads.hpp"
44
45 /*-----------------------------------*/
46 /* static members initialization */
47 /*-----------------------------------*/
48 bool NOMAD::Mads::_force_quit = false;
49 bool NOMAD::Mads::_flag_check_bimads = true;
50 bool NOMAD::Mads::_flag_reset_mesh = true;
51 bool NOMAD::Mads::_flag_reset_barriers = true;
52 bool NOMAD::Mads::_flag_p1_active = false;
53
54
55 /*---------------------------------------------------------*/
56 /* force quit (static, called by pressing ctrl-c) */
57 /*---------------------------------------------------------*/
force_quit(int signalValue)58 void NOMAD::Mads::force_quit ( int signalValue )
59 {
60 NOMAD::Mads::_force_quit = true;
61 NOMAD::Evaluator_Control::force_quit();
62 NOMAD::Evaluator::force_quit();
63
64 #ifdef USE_TGP
65 NOMAD::TGP_Output_Model::force_quit();
66 #endif
67 }
68
69 /*---------------------------------------------------------*/
70 /* access to the flags (static) */
71 /*---------------------------------------------------------*/
get_flags(bool & flag_check_bimads,bool & flag_reset_mesh,bool & flag_reset_barriers,bool & flag_p1_active)72 void NOMAD::Mads::get_flags ( bool & flag_check_bimads ,
73 bool & flag_reset_mesh ,
74 bool & flag_reset_barriers ,
75 bool & flag_p1_active )
76 {
77 flag_check_bimads = _flag_check_bimads;
78 flag_reset_mesh = _flag_reset_mesh;
79 flag_reset_barriers = _flag_reset_barriers;
80 flag_p1_active = _flag_p1_active;
81 }
82
83 /*---------------------------------------------------------*/
84 /* initializations */
85 /*---------------------------------------------------------*/
86 /* . only to be invoked by constructors */
87 /* . private method */
88 /*---------------------------------------------------------*/
init(void)89 void NOMAD::Mads::init ( void )
90 {
91
92 NOMAD::Mads::_force_quit = false;
93
94 if ( !NOMAD::Slave::is_master() )
95 return;
96
97 // Mads::force_quit() will be called if ctrl-c is pressed:
98 signal ( SIGINT , NOMAD::Mads::force_quit );
99 #ifndef WINDOWS
100 signal ( SIGPIPE , NOMAD::Mads::force_quit ); // (ctrl-c during a "| more")
101 #endif
102 #ifdef USE_MPI
103 signal ( SIGTERM , NOMAD::Mads::force_quit );
104 #endif
105
106 // model searches initialization:
107 if ( _p.has_model_search() ) {
108 #ifdef USE_TGP
109 if ( _p.get_model_search(1) == NOMAD::TGP_MODEL )
110 _model_search1 = new TGP_Model_Search ( _p );
111 #endif
112 if ( _p.get_model_search(1) == NOMAD::QUADRATIC_MODEL )
113 _model_search1 = new Quad_Model_Search ( _p );
114 #ifdef USE_TGP
115 if ( _p.get_model_search(2) == NOMAD::TGP_MODEL )
116 _model_search2 = new TGP_Model_Search ( _p );
117 #endif
118 if ( _p.get_model_search(2) == NOMAD::QUADRATIC_MODEL )
119 _model_search2 = new Quad_Model_Search ( _p );
120 }
121
122 #ifdef USE_TGP
123 _ev_control.set_last_TGP_model ( NULL );
124 #endif
125
126 // VNS search initialization:
127 if ( _p.get_VNS_search() )
128 _VNS_search = new VNS_Search ( _p );
129
130 // cache search initialization:
131 if ( _p.get_cache_search() )
132 _cache_search = new Cache_Search ( _p );
133
134 // Orthogonal mesh initialization
135 _mesh->reset();
136
137
138 }
139
140 /*---------------------------------------------------------*/
141 /* destructor */
142 /*---------------------------------------------------------*/
~Mads(void)143 NOMAD::Mads::~Mads ( void )
144 {
145 delete _pareto_front;
146 delete _model_search1;
147 delete _model_search2;
148 delete _VNS_search;
149 delete _cache_search;
150 delete _L_curve;
151
152 if ( _extended_poll && !_user_ext_poll)
153 delete _extended_poll;
154 }
155
156 /*-------------------------------------------------------------*/
157 /* reset */
158 /*-------------------------------------------------------------*/
159 /* default values for parameters: keep_barriers = false */
160 /* keep_stats = false */
161 /*-------------------------------------------------------------*/
reset(bool keep_barriers,bool keep_stats)162 void NOMAD::Mads::reset ( bool keep_barriers , bool keep_stats )
163 {
164 // evaluator control:
165 #ifdef USE_TGP
166 _ev_control.set_last_TGP_model ( NULL );
167 #endif
168
169 // user search:
170 _user_search = NULL;
171
172 // model search #1:
173 if ( _p.get_model_search(1) != NOMAD::NO_MODEL )
174 {
175 if ( _model_search1 )
176 _model_search1->reset();
177 else {
178 if ( _p.get_model_search(1) == NOMAD::TGP_MODEL )
179 {
180 #ifdef USE_TGP
181 _model_search1 = new TGP_Model_Search ( _p ) ;
182 #endif
183 }
184 else
185 _model_search1 = new Quad_Model_Search ( _p );
186 }
187 }
188 else
189 {
190 delete _model_search1;
191 _model_search1 = NULL;
192 }
193
194 // model search #2:
195 if ( _p.get_model_search(2) != NOMAD::NO_MODEL )
196 {
197 if ( _model_search2 )
198 _model_search2->reset();
199 else
200 {
201 if ( _p.get_model_search(2) == NOMAD::TGP_MODEL )
202 {
203 #ifdef USE_TGP
204 _model_search2 = new TGP_Model_Search ( _p ) ;
205 #endif
206 }
207 else
208 _model_search2 = new Quad_Model_Search ( _p );
209 }
210 }
211 else
212 {
213 delete _model_search2;
214 _model_search2 = NULL;
215 }
216
217 // VNS search:
218 if ( _p.get_VNS_search() )
219 {
220 if ( _VNS_search )
221 _VNS_search->reset();
222 else
223 _VNS_search = new VNS_Search ( _p );
224 }
225 else {
226 delete _VNS_search;
227 _VNS_search = NULL;
228 }
229
230 // cache search:
231 if ( _p.get_cache_search() )
232 {
233 if ( _cache_search )
234 _cache_search->reset();
235 else
236 _cache_search = new Cache_Search ( _p );
237 }
238 else
239 {
240 delete _cache_search;
241 _cache_search = NULL;
242 }
243
244 // barriers:
245 _flag_reset_barriers = !keep_barriers;
246 if ( _flag_reset_barriers )
247 {
248 _true_barrier.reset();
249 _sgte_barrier.reset();
250 }
251
252 // stats:
253 if ( !keep_stats )
254 _stats.reset();
255
256
257 _mesh->reset();
258
259 }
260
261
262 /* algorithm execution (single-objective) */
263 /*---------------------------------------------------------*/
run(void)264 NOMAD::stop_type NOMAD::Mads::run ( void )
265 {
266 const NOMAD::Display & out = _p.out();
267 NOMAD::dd_type display_degree = out.get_gen_dd();
268 NOMAD::stop_type stop_reason = NOMAD::UNKNOWN_STOP_REASON;
269
270 #ifdef USE_MPI
271
272 if ( NOMAD::Slave::get_nb_processes() < 2 )
273 {
274 out << NOMAD::open_block("ERROR:") << "Incorrect command to run with MPI." << std::endl
275 << "Usage: mpirun -np p exeName" << std::endl ;
276 out << NOMAD::close_block();
277 return stop_reason;
278 }
279
280
281 // init the slaves:
282 bool stop_slaves_here = false;
283
284 if ( NOMAD::Slave::is_master() )
285 {
286 if ( !NOMAD::Slave::are_running() )
287 {
288 NOMAD::Slave::init_slaves ( out );
289 stop_slaves_here = true;
290 }
291 }
292 else
293 {
294 NOMAD::Slave s ( _p , _ev_control.get_evaluator() );
295 s.run();
296 return stop_reason;
297 }
298
299 #endif
300
301 try
302 {
303
304 // check an extended poll if there are categorical
305 // variables and disable extended poll otherwise:
306 if ( _p.get_signature()->has_categorical() )
307 {
308
309 if ( _user_ext_poll && !_extended_poll )
310 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
311 "categorical variables: user extended poll object is NULL" );
312
313 if ( _p.get_extended_poll_enabled() && !_user_ext_poll )
314 {
315 if (!_extended_poll)
316 _extended_poll = new NOMAD::Extended_Poll ( _p ); // extended poll created only once with the signatures of _p
317
318 std::string error_str;
319 if ( !_extended_poll->set_neighbors_exe ( error_str ) )
320 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ , error_str );
321 }
322 }
323 else if ( _extended_poll )
324 {
325 if ( !_user_ext_poll )
326 delete _extended_poll;
327 _extended_poll = NULL;
328 }
329
330 // check if Mads::run() has been called for multi-objective:
331 if ( NOMAD::Mads::_flag_check_bimads && _p.get_nb_obj() > 1 )
332 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
333 "Mads::run() called for multi-objective instead of Mads::multi_run()" );
334
335 #ifndef R_VERSION
336 if ( display_degree == NOMAD::NORMAL_DISPLAY || display_degree == NOMAD::FULL_DISPLAY )
337 out << std::endl << NOMAD::open_block ( "MADS run" );
338
339 if ( display_degree == NOMAD::NORMAL_DISPLAY ) {
340 _ev_control.display_stats ( true ,
341 out ,
342 _p.get_display_stats() ,
343 NULL ,
344 false ,
345 NULL );
346 out << std::endl << std::endl;
347 }
348 #endif
349
350 // barriers init:
351 if ( _flag_reset_barriers )
352 {
353 _true_barrier.reset();
354 _sgte_barrier.reset();
355 }
356
357 // evaluator control init:
358 _ev_control.reset();
359
360 // reset the extended poll:
361 if ( _extended_poll && _p.get_extended_poll_enabled() )
362 _extended_poll->reset();
363
364 // mesh init/reset:
365 if ( _flag_reset_mesh )
366 _mesh->reset();
367
368 NOMAD::success_type success , last_success;
369 int nb_search_pts;
370 bool count_search;
371 bool stop = false;
372 const NOMAD::Eval_Point * new_feas_inc = NULL;
373 const NOMAD::Eval_Point * new_infeas_inc = NULL;
374
375 stop_reason = NOMAD::NO_STOP;
376
377 // x0 eval:
378 eval_x0 ( stop , stop_reason );
379
380 // phase one: if no feasible starting point:
381 bool phase_one_done = false;
382 if (stop &&
383 stop_reason == NOMAD::X0_FAIL &&
384 _p.has_EB_constraints() &&
385 ( _stats.get_eval() > 0 || ( _p.get_opt_only_sgte() && _stats.get_sgte_eval() > 0 ) ) )
386 {
387
388 phase_one_done = true;
389 Phase_One_Search p1s ( _p );
390 p1s.search ( *this ,
391 nb_search_pts ,
392 stop ,
393 stop_reason ,
394 success ,
395 count_search ,
396 new_feas_inc ,
397 new_infeas_inc );
398
399 _mesh->reset();
400
401 }
402
403 // initial Latin-Hypercube (LH) search:
404 if ( !stop && !phase_one_done && _p.get_LH_search_p0() > 0 )
405 {
406
407 LH_Search lh ( _p , true , _flag_p1_active );
408 int nb_search_pts;
409
410 lh.search ( *this ,
411 nb_search_pts ,
412 stop ,
413 stop_reason ,
414 success ,
415 count_search ,
416 new_feas_inc ,
417 new_infeas_inc );
418
419 if ( success == NOMAD::FULL_SUCCESS )
420 _stats.add_LH_success();
421
422 if ( count_search )
423 _stats.add_nb_LH_searches();
424
425 _stats.add_LH_pts ( nb_search_pts );
426 }
427
428 // no iterations allowed:
429 if ( !stop && _p.get_max_iterations() == 0 )
430 {
431 stop = true;
432 stop_reason = NOMAD::MAX_ITER_REACHED;
433 }
434
435 // L_curve initialization:
436 delete _L_curve;
437 _L_curve = NULL;
438 const NOMAD::Double L_curve_target = _p.get_L_curve_target();
439 if ( L_curve_target.is_defined() )
440 {
441 _L_curve = new NOMAD::L_Curve ( L_curve_target );
442 const NOMAD::Eval_Point * best_feasible = get_best_feasible();
443 if ( best_feasible )
444 _L_curve->insert ( _stats.get_bb_eval() , best_feasible->get_f() );
445 }
446
447 int max_cfi = _p.get_max_consecutive_failed_iterations();
448 int nb_cfi = 0;
449
450 success = last_success = NOMAD::UNSUCCESSFUL;
451
452 // MADS iterations:
453 while ( !stop )
454 {
455
456 iteration ( stop ,
457 stop_reason ,
458 success ,
459 new_feas_inc ,
460 new_infeas_inc );
461
462 if ( success == NOMAD::UNSUCCESSFUL && last_success == NOMAD::UNSUCCESSFUL )
463 ++nb_cfi;
464 else
465 nb_cfi = (success == NOMAD::UNSUCCESSFUL) ? 1 : 0;
466
467 last_success = success;
468
469 // check the consecutive number of failed iterations:
470 if ( max_cfi > 0 && nb_cfi > max_cfi )
471 {
472 stop = true;
473 stop_reason = NOMAD::MAX_CONS_FAILED_ITER;
474 }
475
476 }
477
478 // parallel version:
479 #ifdef USE_MPI
480
481 // asynchronous mode: wait for the evaluations in progress:
482 if ( _p.get_asynchronous() )
483 {
484 std::list<const NOMAD::Eval_Point *> evaluated_pts;
485 _ev_control.wait_for_evaluations ( NOMAD::ASYNCHRONOUS ,
486 _true_barrier ,
487 _sgte_barrier ,
488 _pareto_front ,
489 stop ,
490 stop_reason ,
491 success ,
492 evaluated_pts );
493 }
494
495 // update stats:
496 _stats.set_MPI_data_size ( NOMAD::Slave::get_data_sent() +
497 NOMAD::Slave::get_data_rcvd() );
498
499 #endif
500
501 // final cache save (overwrite=true):
502 _ev_control.save_caches ( true );
503
504 // final displays:
505 const NOMAD::Eval_Point * bf = get_best_feasible();
506 bool write_stats = bf &&
507 ( bf->get_tag() != _ev_control.get_last_stats_tag() ||
508 _stats.get_bb_eval() != _ev_control.get_last_stats_bbe() );
509
510 const std::string & stats_file_name = _p.get_stats_file_name();
511
512 if ( !stats_file_name.empty() )
513 {
514 if ( write_stats && !_p.get_display_all_eval() )
515 {
516 _ev_control.stats_file ( stats_file_name , bf , true , NULL );
517 }
518 if ( !bf && display_degree > NOMAD::MINIMAL_DISPLAY )
519 {
520 std::ofstream fout ( (_p.get_problem_dir() + stats_file_name).c_str() );
521 if ( fout.fail() )
522 {
523 out << std::endl
524 << "Warning (" << "Mads.cpp" << ", " << __LINE__
525 << "): could not save information in stats file \'"
526 << stats_file_name << "\'" << std::endl << std::endl;
527 }
528 else
529 fout << "no feasible solution has been found after "
530 << _stats.get_bb_eval() << " evaluations"
531 << std::endl;
532 fout.close();
533 }
534
535 }
536
537 if ( display_degree > NOMAD::MINIMAL_DISPLAY)
538 {
539
540 // final stats:
541 if ( display_degree == NOMAD::NORMAL_DISPLAY && bf && write_stats && !_p.get_display_all_eval() )
542 _ev_control.display_stats ( false,
543 out,
544 _p.get_display_stats() ,
545 bf ,
546 true ,
547 NULL );
548 #ifndef R_VERSION
549 std::ostringstream msg;
550 msg << "end of run (" << stop_reason << ")";
551 out << std::endl << NOMAD::close_block ( msg.str() );
552 #endif
553 }
554
555 // mono-objective final displays:
556 if ( _p.get_nb_obj() == 1 )
557 {
558
559 if ( display_degree == NOMAD::FULL_DISPLAY )
560 out << std::endl << NOMAD::open_block ( "NOMAD final display" );
561
562 #ifndef R_VERSION
563 display();
564 #endif
565
566
567
568 if ( display_degree == NOMAD::FULL_DISPLAY )
569 out.close_block();
570 }
571
572 } // end of the try block
573
574 catch ( std::exception & e )
575 {
576
577 #ifdef USE_MPI
578 if ( NOMAD::Slave::are_running() )
579 NOMAD::Slave::stop_slaves ( out );
580 #endif
581
582 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ , e.what() );
583 }
584
585 // stop the slaves:
586 #ifdef USE_MPI
587 if ( NOMAD::Slave::are_running() && stop_slaves_here )
588 NOMAD::Slave::stop_slaves ( out );
589 #endif
590
591 return stop_reason;
592 }
593
594 /*----------------------------------------------------------------------*/
595 /* launch a single optimization for multi-objective optimization */
596 /*----------------------------------------------------------------------*/
597 /* . the display_degree is given as a parameter since it corresponds */
598 /* to the original iterative display degree before all degrees have */
599 /* been set to zero */
600 /* . private method */
601 /*----------------------------------------------------------------------*/
multi_launch_single_opt(NOMAD::dd_type display_degree,int mads_runs,int overall_bbe,NOMAD::Multi_Obj_Evaluator & ev,int & stagnation_cnt,NOMAD::Stats & multi_stats,bool & stop,NOMAD::stop_type & stop_reason)602 void NOMAD::Mads::multi_launch_single_opt
603 ( NOMAD::dd_type display_degree ,
604 int mads_runs ,
605 int overall_bbe ,
606 NOMAD::Multi_Obj_Evaluator & ev ,
607 int & stagnation_cnt ,
608 NOMAD::Stats & multi_stats ,
609 bool & stop ,
610 NOMAD::stop_type & stop_reason )
611 {
612 // max number of bb evaluations for one MADS run:
613 int max_bbe = _p.get_max_bb_eval();
614
615 // size of the Pareto front before the MADS run:
616 int tmp = _pareto_front->size();
617
618 // current MADS run:
619 int cur_mads_run = multi_stats.get_mads_runs();
620
621 // displays:
622 const NOMAD::Display & out = _p.out();
623
624 if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
625 {
626 out << "MADS run " << std::setw(2) << cur_mads_run + 1;
627 if ( mads_runs > 0 )
628 out << "/" << mads_runs;
629 out << " ...";
630 }
631
632 // run single-objective MADS (it also updates the Pareto front):
633 NOMAD::Mads::set_flag_check_bimads ( false );
634 NOMAD::stop_type single_run_stop_reason = run();
635 NOMAD::Mads::set_flag_check_bimads ( true );
636
637 if ( single_run_stop_reason == NOMAD::CTRL_C ||
638 single_run_stop_reason == NOMAD::ERROR ||
639 single_run_stop_reason == NOMAD::UNKNOWN_STOP_REASON ||
640 single_run_stop_reason == NOMAD::X0_FAIL ||
641 single_run_stop_reason == NOMAD::F_TARGET_REACHED ||
642 single_run_stop_reason == NOMAD::P1_FAIL )
643 {
644 stop = true;
645 stop_reason = single_run_stop_reason;
646 }
647
648 // update MULTI-MADS stats from MADS stats:
649 multi_stats.update ( _stats , false ); // for_search = false
650 multi_stats.add_mads_run();
651
652 int nb_new_pts = _pareto_front->size() - tmp;
653 int global_bbe = multi_stats.get_bb_eval();
654
655 // displays:
656 if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
657 {
658
659 // display basic stats on the terminated run:
660 out << "... OK [bb eval=" << std::setw(3) << _stats.get_bb_eval()
661 << "] [overall bb eval=" << std::setw(5) << global_bbe
662 << "] [# dominant pts=" << std::setw(4) << _pareto_front->size()
663 << "] [# new pts=" << std::setw(4) << nb_new_pts << "]";
664
665 // display f1, f2, and f:
666 const NOMAD::Eval_Point * bf = get_best_feasible();
667 if ( bf )
668 {
669
670 const NOMAD::Point & bbo = bf->get_bb_outputs();
671
672 out << " [f1=" << bbo[ev.get_i1()]
673 << " f2=" << bbo[ev.get_i2()];
674 if ( display_degree == NOMAD::FULL_DISPLAY )
675 out << " f=" << bf->get_f();
676 out << "]";
677 }
678 out << std::endl;
679 }
680
681 if ( _stats.get_bb_eval() == 0 && nb_new_pts == 0 )
682 ++stagnation_cnt;
683 else
684 stagnation_cnt = 0;
685
686 // stop ?
687 if ( !stop )
688 {
689
690 // test the number of MADS runs:
691 if ( mads_runs > 0 )
692 {
693 if ( multi_stats.get_mads_runs() >= mads_runs )
694 {
695 stop = true;
696 stop_reason = NOMAD::MULTI_NB_MADS_RUNS_REACHED;
697 }
698 }
699
700 // test if no new Pareto point has been generated for 50*n MADS runs:
701 else
702 {
703 if ( stagnation_cnt > 50 * _p.get_nb_free_variables() )
704 {
705 stop = true;
706 stop_reason = NOMAD::MULTI_STAGNATION;
707 }
708 }
709 }
710
711 if ( overall_bbe >= 0 && global_bbe >= overall_bbe )
712 {
713 stop = true;
714 stop_reason = NOMAD::MULTI_MAX_BB_REACHED;
715 }
716
717 bool user_calls_enabled = _p.get_user_calls_enabled();
718
719 if ( !stop )
720 {
721
722 // ell is the mesh index on which the last run terminated:
723 // int ell = NOMAD::Mesh::get_mesh_index();
724
725 // reset MADS:
726 reset();
727
728 // this strategy deciding the initial mesh size
729 // was used with versions < 3.4
730 // if ( cur_mads_run > 1 )
731 // _p.set_INITIAL_MESH_INDEX ( (ell > 5) ? 5 : ell );
732
733 // modify MAX_BB_EVAL for single runs (in order to have
734 // less than overall_bbe blackbox evaluations):
735 if ( overall_bbe >= 0 && global_bbe + max_bbe > overall_bbe )
736 _p.set_MAX_BB_EVAL ( overall_bbe - global_bbe );
737 }
738
739 // set the number of MADS runs for the general Stats object:
740 _stats.set_mads_runs ( multi_stats.get_mads_runs() );
741
742 // call the user-defined function Multi_Obj_Evaluator::update_mads_run():
743 if ( user_calls_enabled )
744 ev.update_mads_run ( _stats ,
745 _ev_control ,
746 _true_barrier ,
747 _sgte_barrier ,
748 *_pareto_front );
749 }
750
751 /*--------------------------------------------------------------------------*/
752 /* compute and set the minimal poll size for multi-objective optimization */
753 /* (private) */
754 /*--------------------------------------------------------------------------*/
multi_set_min_poll_size(const NOMAD::Point & lb,const NOMAD::Point & ub,const NOMAD::Point & Delta_0,NOMAD::Double delta_j)755 void NOMAD::Mads::multi_set_min_poll_size ( const NOMAD::Point & lb ,
756 const NOMAD::Point & ub ,
757 const NOMAD::Point & Delta_0 ,
758 NOMAD::Double delta_j )
759 {
760
761 delta_j /= sqrt ( _mesh->get_update_basis() );
762
763 int n = Delta_0.size();
764 NOMAD::Point Delta_min (n);
765
766 for ( int i = 0 ; i < n ; ++i )
767 {
768
769 // set a relative value:
770 if ( lb[i].is_defined() && ub[i].is_defined() )
771 Delta_min[i] = delta_j * ( ub[i] - lb[i] );
772
773 // set an absolute value:
774 else
775 Delta_min[i] = delta_j;
776
777 // compare to Delta_0:
778 if ( Delta_min[i] > Delta_0[i] )
779 Delta_min[i] = Delta_0[i];
780 }
781
782 _p.set_MIN_POLL_SIZE ( Delta_min );
783 }
784
785 /*---------------------------------------------------------*/
786 /* algorithm execution (multi) */
787 /*---------------------------------------------------------*/
multi_run(void)788 NOMAD::stop_type NOMAD::Mads::multi_run ( void )
789 {
790 const NOMAD::Display & out = _p.out();
791 NOMAD::dd_type display_degree = out.get_gen_dd();
792 NOMAD::stop_type stop_reason = NOMAD::UNKNOWN_STOP_REASON;
793
794 // init the slaves:
795
796 #ifdef USE_MPI
797
798 if ( NOMAD::Slave::get_nb_processes() < 2 )
799 {
800 out << NOMAD::open_block("ERROR:") << "Incorrect command to run with MPI." << std::endl
801 << "Usage: mpirun -np p exeName" << std::endl ;
802 out << NOMAD::close_block();
803 return stop_reason;
804 }
805
806 bool stop_slaves_here = false;
807
808 if ( NOMAD::Slave::is_master() )
809 {
810 if ( !NOMAD::Slave::are_running() )
811 {
812 NOMAD::Slave::init_slaves ( out );
813 stop_slaves_here = true;
814 }
815 }
816 else
817 {
818 NOMAD::Slave s ( _p , _ev_control.get_evaluator() );
819 s.run();
820 return stop_reason;
821 }
822
823 #endif
824
825 try {
826
827 // objective indexes:
828 NOMAD::Multi_Obj_Evaluator::set_obj_indexes ( _p.get_index_obj() );
829
830 // bounds:
831 const NOMAD::Point & lb = _p.get_lb();
832 const NOMAD::Point & ub = _p.get_ub();
833
834 // MULTI-MADS stopping criteria:
835 int mads_runs = _p.get_multi_nb_mads_runs(); // max number of MADS runs
836 int overall_bbe = _p.get_multi_overall_bb_eval(); // max number of total bb eval.
837 bool use_delta_crit = _p.get_multi_use_delta_crit(); // use the delta term. crit.
838 int stagnation_cnt = 0;
839
840 if ( mads_runs == 0 )
841 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
842 "Mads::multi_run(): parameter MULTI_NB_MADS_RUNS is not positive" );
843
844 if ( _p.get_nb_obj() != 2 )
845 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
846 "Mads::multi_run(): NOMAD current version handles a maximum of two objectives" );
847
848 // remember cache save period:
849 int old_csp = _p.get_cache_save_period();
850
851 // remember L_CURVE_TARGET:
852 NOMAD::Double old_lct = _p.get_L_curve_target();
853
854 // remember solution file:
855 std::string old_sol_file = _p.get_solution_file();
856
857 // remember the original LH search parameters:
858 int lh_p0 = _p.get_LH_search_p0();
859 int lh_pi = _p.get_LH_search_pi();
860
861 // remember the original minimal poll size:
862 const NOMAD::Point original_min_poll_size = _p.get_min_poll_size();
863
864 // remember display degrees:
865 NOMAD::dd_type iter_dd = out.get_iter_dd();
866 std::string old_dd;
867 out.get_display_degree ( old_dd );
868
869 // save list of starting points:
870 std::string x0_cache_file = _p.get_x0_cache_file();
871 std::vector<NOMAD::Point *> x0s;
872 {
873 const std::vector<NOMAD::Point *> & x0s_tmp = _p.get_x0s();
874 size_t nx0 = x0s_tmp.size() , k;
875 for ( k = 0 ; k < nx0 ; ++k )
876 x0s.push_back ( new Point ( *x0s_tmp[k] ) );
877 }
878
879 NOMAD::Point Delta_0 = _mesh->get_initial_poll_size ();
880
881
882 if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
883 out << std::endl << NOMAD::open_block ( "multi-MADS run" ) << std::endl;
884
885 bool stop = false;
886 stop_reason = NOMAD::NO_STOP;
887
888 // MULTI-MADS stats:
889 NOMAD::Stats multi_stats ( _stats );
890
891 // access to the evaluator (downcast to a Multi_Obj_Evaluator):
892 NOMAD::Multi_Obj_Evaluator * ev =
893 static_cast<NOMAD::Multi_Obj_Evaluator*> ( _ev_control.get_evaluator() );
894 if ( !ev->is_multi_obj() )
895 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
896 "Mads::multi_run(): associated Evaluator object is not a Multi_Obj_Evaluator" );
897
898 // parameters modifications:
899 // -------------------------
900
901 // STATS_FILE:
902 const std::string old_stats_file_name = _p.get_stats_file_name();
903 const std::list<std::string> old_stats_file = _p.get_stats_file();
904 _p.reset_stats_file();
905
906 // MAX_BB_EVAL:
907 int max_bbe = _p.get_max_bb_eval();
908 if ( overall_bbe >= 0 && ( max_bbe < 0 || overall_bbe < max_bbe ) )
909 _p.set_MAX_BB_EVAL ( overall_bbe );
910
911 // disable display:
912 _p.set_DISPLAY_DEGREE ( NOMAD::NO_DISPLAY );
913
914 // disable solution file:
915 _p.set_SOLUTION_FILE ( "" );
916
917 // disable CACHE_SAVE_PERIOD:
918 _p.set_CACHE_SAVE_PERIOD ( -1 );
919
920 // disable L_CURVE_TARGET:
921 _p.set_L_CURVE_TARGET ( NOMAD::Double() );
922
923 // LH_SEARCH and MAX_BB_EVAL adjustment:
924 if ( lh_p0 > 0 )
925 {
926 _p.set_LH_SEARCH ( lh_p0 , 0 );
927 if ( max_bbe >= 0 )
928 {
929 int bbe = max_bbe + lh_p0;
930 if ( overall_bbe >= 0 && bbe > overall_bbe )
931 bbe = overall_bbe;
932 _p.set_MAX_BB_EVAL ( bbe );
933 }
934 }
935
936 // parameters validation:
937 _p.check ( true , // remove_history_file = true
938 true , // remove_solution_file = true
939 true ); // remove_stats_file = true
940
941 // Pareto front initialization:
942 delete _pareto_front;
943 _pareto_front = new NOMAD::Pareto_Front;
944
945 // Problem has categorical variables ? (Si why this flag is needed below)
946 bool hasCategoricalVar=_p.get_signature()->has_categorical();
947
948 // initial optimizations ( minimize f1(x) or f2(x) ):
949 // --------------------------------------------------
950 const NOMAD::Eval_Point * best_f2;
951 int i;
952
953 for ( i = 0 ; i < 2 ; ++i )
954 {
955
956 if ( stop )
957 break;
958
959 // minimize f2:
960 if ( i == 1 )
961 {
962
963 // new starting point:
964 best_f2 = _pareto_front->get_best_f2();
965 if ( best_f2 )
966 {
967 _p.set_EXTERN_SIGNATURE ( best_f2->get_signature() );
968 _p.reset_X0();
969 _p.set_X0 ( *best_f2 );
970 }
971
972 // LH_SEARCH:
973 if ( lh_pi > 0 )
974 _p.set_LH_SEARCH ( lh_pi , 0 );
975 else if ( lh_p0 > 0 )
976 _p.set_LH_SEARCH ( 0 , 0 );
977
978 // MAX_BB_EVAL:
979 if ( max_bbe >= 0 )
980 {
981 int bbe = max_bbe + ( (lh_pi > 0 ) ? lh_pi : 0 );
982 if ( overall_bbe >= 0 )
983 {
984 if ( bbe > overall_bbe )
985 bbe = overall_bbe;
986 int global_bbe = multi_stats.get_bb_eval();
987 if ( global_bbe + bbe > overall_bbe )
988 bbe = overall_bbe - global_bbe;
989 }
990 _p.set_MAX_BB_EVAL ( bbe );
991 }
992
993 if ( _p.to_be_checked() )
994 _p.check ( false , // remove_history_file = false
995 true , // remove_solution_file = true
996 true ); // remove_stats_file = true
997
998 _mesh=_p.get_signature()->get_mesh();
999
1000 }
1001
1002 // set weights/reference:
1003 ev->set_weights ( 1-i , i );
1004 ev->set_ref ( NULL );
1005
1006 // launch the single optimization:
1007 multi_launch_single_opt ( iter_dd ,
1008 mads_runs ,
1009 overall_bbe ,
1010 *ev ,
1011 stagnation_cnt ,
1012 multi_stats ,
1013 stop ,
1014 stop_reason );
1015 }
1016
1017 const NOMAD::Point * ref;
1018 const NOMAD::Pareto_Point * xj;
1019 NOMAD::Double delta_j;
1020
1021 // the LH search is disabled:
1022 _p.set_LH_SEARCH ( 0 , 0 );
1023
1024 // MAX_BB_EVAL reset:
1025 if ( max_bbe > 0 && ( lh_p0 > 0 || lh_pi > 0 ) )
1026 {
1027 int bbe = max_bbe;
1028 if ( overall_bbe >= 0 )
1029 {
1030 if ( bbe > overall_bbe )
1031 bbe = overall_bbe;
1032
1033 int global_bbe = multi_stats.get_bb_eval();
1034 if ( global_bbe + bbe > overall_bbe )
1035 bbe = overall_bbe - global_bbe;
1036 }
1037 _p.set_MAX_BB_EVAL ( bbe );
1038 }
1039
1040 // MULTI-MADS main loop:
1041 // ---------------------
1042 const NOMAD::Eval_Point * x0_tmp;
1043
1044 while ( !stop )
1045 {
1046
1047 // get the reference point from the Pareto front:
1048 ref = _pareto_front->get_ref ( xj , delta_j );
1049
1050 if ( !xj )
1051 {
1052 stop = true;
1053 stop_reason = NOMAD::MULTI_NO_PARETO_PTS;
1054 break;
1055 }
1056
1057 // use delta as stopping criterion:
1058 if ( use_delta_crit )
1059 {
1060 if ( delta_j.is_defined() && delta_j > 0.0 )
1061 multi_set_min_poll_size ( lb , ub , Delta_0 , delta_j );
1062 else
1063 _p.set_MIN_POLL_SIZE ( original_min_poll_size );
1064 }
1065
1066 // new starting point:
1067 x0_tmp = xj->get_element();
1068 _p.set_EXTERN_SIGNATURE ( x0_tmp->get_signature() );
1069 _p.reset_X0();
1070 _p.set_X0 ( *x0_tmp );
1071
1072 _p.check ( false , // remove_history_file = false
1073 true , // remove_solution_file = true
1074 true ); // remove_stats_file = true
1075
1076 // a reference point has been found: optimization
1077 // with reference-based function:
1078 if ( ref )
1079 {
1080
1081 // set reference:
1082 ev->set_ref ( ref );
1083
1084 // launch the single optimization:
1085 multi_launch_single_opt ( iter_dd ,
1086 mads_runs ,
1087 overall_bbe ,
1088 *ev ,
1089 stagnation_cnt ,
1090 multi_stats ,
1091 stop ,
1092 stop_reason );
1093
1094 delete ref;
1095 ev->set_ref ( NULL );
1096 }
1097
1098 // no reference available: two optimizations ( f1(x) and f2(x) ):
1099 else
1100 {
1101
1102 // for the stagnation check:
1103 const NOMAD::Eval_Point * pp_before;
1104 int stagnation_cnt_before , overall_bbe_before;
1105 bool check_1 = false;
1106
1107 // loop on f1 and f2:
1108 for ( i = 0 ; i < 2 ; ++i )
1109 {
1110
1111 if ( stop )
1112 break;
1113
1114 // minimize f2:
1115 if ( i == 1 )
1116 {
1117
1118 // new starting point:
1119 best_f2 = _pareto_front->get_best_f2();
1120 if ( best_f2 )
1121 {
1122 _p.set_EXTERN_SIGNATURE ( best_f2->get_signature() );
1123 _p.reset_X0();
1124 _p.set_X0 ( *best_f2 );
1125 }
1126 else
1127 _p.set_X0 ( *x0_tmp );
1128
1129 _p.check ( false , // remove_history_file = false
1130 true , // remove_solution_file = true
1131 true ); // remove_stats_file = true
1132 }
1133
1134 // set weights/reference:
1135 ev->set_weights ( 1-i , i );
1136 ev->set_ref ( NULL );
1137
1138 stagnation_cnt_before = stagnation_cnt;
1139 overall_bbe_before = overall_bbe;
1140 pp_before = ( _pareto_front->size() == 1 ) ?
1141 _pareto_front->begin() : NULL;
1142
1143 // launch the single optimization:
1144 multi_launch_single_opt ( iter_dd ,
1145 mads_runs ,
1146 overall_bbe ,
1147 *ev ,
1148 stagnation_cnt ,
1149 multi_stats ,
1150 stop ,
1151 stop_reason );
1152
1153 // stagnation check:
1154 if ( stagnation_cnt > stagnation_cnt_before &&
1155 overall_bbe == overall_bbe_before &&
1156 _pareto_front->size() == 1 &&
1157 _pareto_front->begin() == pp_before )
1158 {
1159
1160 if ( i == 0 )
1161 check_1 = true;
1162 else if ( check_1 )
1163 {
1164 stop = true;
1165 stop_reason = NOMAD::MULTI_STAGNATION;
1166 }
1167 }
1168 }
1169 }
1170
1171 } // end of MULTI-MADS main loop
1172 // ---------------------------
1173
1174
1175 // parameters re-initialization and final displays:
1176 if ( ! hasCategoricalVar ) // Dimension may change when categorical variables are present. This may pose problem for the check. Hence we add a test -> when categorical variables are present, the parameters are not set back to their initial state at the end of the multi-objective optimization.
1177 {
1178 _p.reset_X0();
1179 size_t nx0 = x0s.size();
1180 if ( nx0 > 0 )
1181 {
1182 for ( size_t k = 0 ; k < nx0 ; ++k )
1183 {
1184 _p.set_X0 ( *x0s[k] );
1185 delete x0s[k];
1186 }
1187 }
1188 else if ( !x0_cache_file.empty() )
1189 _p.set_X0 ( x0_cache_file );
1190
1191 if ( use_delta_crit )
1192 _p.set_MIN_POLL_SIZE ( original_min_poll_size );
1193
1194 }
1195 _p.set_MAX_BB_EVAL ( max_bbe );
1196 _p.set_DISPLAY_DEGREE ( old_dd );
1197 _p.set_STATS_FILE ( old_stats_file_name , old_stats_file );
1198 _p.set_SOLUTION_FILE ( old_sol_file );
1199 _p.set_LH_SEARCH ( lh_p0 , lh_pi );
1200 _p.set_CACHE_SAVE_PERIOD ( old_csp );
1201 _p.set_L_CURVE_TARGET ( old_lct );
1202
1203
1204 _p.check ( false , // remove_history_file = false
1205 true , // remove_solution_file = true
1206 true ); // remove_stats_file = true
1207
1208 // reset MADS stats from MULTI-MADS stats:
1209 _stats = multi_stats;
1210
1211 // final cache save (overwrite=true):
1212 _ev_control.save_caches ( true );
1213
1214 #ifndef R_VERSION
1215 if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
1216 {
1217 std::ostringstream msg;
1218 msg << "end of run (" << stop_reason << ")";
1219 out << std::endl << NOMAD::close_block ( msg.str() ) << std::endl;
1220 }
1221 #endif
1222
1223
1224 // multi-objective final displays:
1225 if ( _p.get_nb_obj() > 1 )
1226 {
1227
1228 if ( display_degree == NOMAD::FULL_DISPLAY )
1229 out.open_block ( "NOMAD final display" );
1230
1231 display();
1232
1233 if ( display_degree == NOMAD::FULL_DISPLAY )
1234 out.close_block();
1235 }
1236
1237 } // end of the try block
1238
1239 catch ( std::exception & e )
1240 {
1241
1242 #ifdef USE_MPI
1243 if ( NOMAD::Slave::are_running() )
1244 NOMAD::Slave::stop_slaves ( out );
1245 #endif
1246
1247 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ , e.what() );
1248 }
1249
1250 // stop the slaves:
1251 #ifdef USE_MPI
1252 if ( NOMAD::Slave::are_running() && stop_slaves_here )
1253 NOMAD::Slave::stop_slaves ( out );
1254 #endif
1255
1256 return stop_reason;
1257 }
1258
1259 /*---------------------------------------------------------*/
1260 /* one MADS iteration (private) */
1261 /*---------------------------------------------------------*/
iteration(bool & stop,NOMAD::stop_type & stop_reason,NOMAD::success_type & success,const NOMAD::Eval_Point * & new_feas_inc,const NOMAD::Eval_Point * & new_infeas_inc)1262 void NOMAD::Mads::iteration ( bool & stop ,
1263 NOMAD::stop_type & stop_reason ,
1264 NOMAD::success_type & success ,
1265 const NOMAD::Eval_Point *& new_feas_inc ,
1266 const NOMAD::Eval_Point *& new_infeas_inc )
1267 {
1268
1269 bool forbid_poll_size_stop = false;
1270
1271 // force quit (by pressing ctrl-c):
1272 if ( !stop && NOMAD::Mads::_force_quit )
1273 {
1274 stop = true;
1275 stop_reason = NOMAD::CTRL_C;
1276 return;
1277 }
1278
1279 // poll center selection:
1280 ( ( _p.get_opt_only_sgte() ) ?
1281 _sgte_barrier : _true_barrier ).select_poll_center ( success );
1282
1283 // displays:
1284 const NOMAD::Display & out = _p.out();
1285 if ( out.get_iter_dd() == NOMAD::FULL_DISPLAY )
1286 out << std::endl
1287 << NOMAD::open_block ( "MADS iteration "
1288 + NOMAD::itos ( _stats.get_iterations() ) )
1289 << std::endl;
1290 display_iteration_begin();
1291
1292 // SEARCH:
1293 // -------
1294 search ( stop , stop_reason , success , new_feas_inc , new_infeas_inc );
1295
1296 // POLL:
1297 // -----
1298 if ( success != NOMAD::FULL_SUCCESS )
1299 poll ( stop ,
1300 stop_reason ,
1301 success ,
1302 new_feas_inc ,
1303 new_infeas_inc ,
1304 forbid_poll_size_stop );
1305
1306 // UPDATES:
1307 // --------
1308
1309 NOMAD::Point old_r=_mesh->get_mesh_indices();
1310
1311 if ( !stop )
1312 {
1313 // OrthogonalMesh update using success status and direction of success (when present)
1314 if ( new_feas_inc )
1315 {
1316 _mesh=new_feas_inc->get_signature()->get_mesh();
1317 _mesh->update ( success, new_feas_inc->get_direction() );
1318 }
1319 else if ( new_infeas_inc )
1320 {
1321 _mesh=new_infeas_inc->get_signature()->get_mesh();
1322 _mesh->update ( success, new_infeas_inc->get_direction());
1323 }
1324 else
1325 _mesh->update ( success );
1326
1327
1328 _mesh->check_min_mesh_sizes( stop , stop_reason );
1329
1330 // if the Delta_k^p stopping criterion is met with integer variables,
1331 // the last set of directions must have a minimal coordinate of 1;
1332 // otherwise the stopping criterion is disabled at this iteration:
1333 if ( forbid_poll_size_stop && stop && stop_reason == NOMAD::DELTA_P_MIN_REACHED )
1334 {
1335 stop = false;
1336 stop_reason = NOMAD::NO_STOP;
1337 }
1338
1339 // display:
1340 if ( _p.out().get_iter_dd() == NOMAD::FULL_DISPLAY )
1341 {
1342 _p.out() << std::endl << NOMAD::open_block ( "Orthogonal mesh update" )
1343 << "previous mesh indices: ( " << old_r << " )" << std::endl
1344 << "new mesh indices : ( " << _mesh->get_mesh_indices() << " )" << std::endl
1345 << NOMAD::close_block() << std::endl;
1346 }
1347
1348 // periodic cache save (overwrite=false):
1349 if ( _p.get_cache_save_period() > 0 &&
1350 _stats.get_iterations()%_p.get_cache_save_period() ==
1351 _p.get_cache_save_period() - 1 )
1352 _ev_control.save_caches ( false );
1353 }
1354
1355 // number of iterations:
1356 _stats.add_iteration();
1357 if ( !stop &&
1358 _p.get_max_iterations() > 0 &&
1359 _stats.get_iterations() >= _p.get_max_iterations() )
1360 {
1361 stop = true;
1362 stop_reason = NOMAD::MAX_ITER_REACHED;
1363 }
1364
1365 // max cache memory:
1366 if ( !stop &&
1367 _p.get_max_cache_memory() > 0.0 &&
1368 _ev_control.get_cache().size_of() > 1048576*_p.get_max_cache_memory() )
1369 {
1370 stop = true;
1371 stop_reason = NOMAD::MAX_CACHE_MEMORY_REACHED;
1372 }
1373
1374 // L_CURVE_TARGET stopping criterion:
1375 if ( _L_curve && !stop )
1376 {
1377 int bbe = _stats.get_bb_eval();
1378 if ( success == NOMAD::FULL_SUCCESS )
1379 {
1380 if ( new_feas_inc )
1381 _L_curve->insert ( bbe , new_feas_inc->get_f() );
1382 }
1383 else if ( success == NOMAD::UNSUCCESSFUL && _L_curve->check_stop ( bbe ) )
1384 {
1385 stop = true;
1386 stop_reason = NOMAD::L_CURVE_TARGET_REACHED;
1387 }
1388 }
1389
1390 // call the user-defined function Evaluator::update_iteration():
1391 if ( _p.get_user_calls_enabled() )
1392 {
1393 bool stop_before = stop;
1394
1395 NOMAD::Pareto_Front * pf = ( ( _pareto_front ) ? _pareto_front:(new NOMAD::Pareto_Front) );
1396
1397 _ev_control.get_evaluator()->update_iteration ( success ,
1398 _stats ,
1399 _ev_control ,
1400 _true_barrier ,
1401 _sgte_barrier ,
1402 *pf ,
1403 stop );
1404
1405 if ( ! _pareto_front )
1406 delete pf;
1407
1408
1409 if ( !stop_before && stop )
1410 stop_reason = NOMAD::USER_STOPPED;
1411 }
1412
1413 // if the algorithms stops, we set the mesh index to the value
1414 // it had before the mesh update:
1415 if ( stop )
1416 {
1417 _mesh->set_mesh_indices( old_r );
1418 }
1419
1420 // displays at the end of an iteration:
1421 display_iteration_end ( stop ,
1422 stop_reason ,
1423 success ,
1424 new_feas_inc ,
1425 new_infeas_inc );
1426
1427
1428
1429 // displays:
1430 if ( out.get_iter_dd() == NOMAD::FULL_DISPLAY )
1431 out << std::endl
1432 << NOMAD::close_block ( "end of iteration "
1433 + NOMAD::itos ( _stats.get_iterations()-1 ) );
1434 }
1435
1436 /*---------------------------------------------------------*/
1437 /* the poll (private) */
1438 /*---------------------------------------------------------*/
poll(bool & stop,NOMAD::stop_type & stop_reason,NOMAD::success_type & success,const NOMAD::Eval_Point * & new_feas_inc,const NOMAD::Eval_Point * & new_infeas_inc,bool & forbid_poll_size_stop)1439 void NOMAD::Mads::poll ( bool & stop ,
1440 NOMAD::stop_type & stop_reason ,
1441 NOMAD::success_type & success ,
1442 const NOMAD::Eval_Point *& new_feas_inc ,
1443 const NOMAD::Eval_Point *& new_infeas_inc ,
1444 bool & forbid_poll_size_stop )
1445 {
1446 forbid_poll_size_stop = false;
1447
1448 if ( stop )
1449 return;
1450
1451 const NOMAD::Display & out = _p.out();
1452 NOMAD::dd_type display_degree = out.get_poll_dd();
1453
1454 success = NOMAD::UNSUCCESSFUL;
1455 new_feas_inc = NULL;
1456 new_infeas_inc = NULL;
1457
1458 if ( display_degree == NOMAD::FULL_DISPLAY )
1459 out << std::endl << NOMAD::open_block ( "MADS poll" ) << std::endl;
1460
1461
1462 const NOMAD::Eval_Point * x;
1463 size_t offset = 0;
1464
1465 std::vector<NOMAD::Signature *> signatures;
1466
1467 const NOMAD::Barrier & barrier = get_active_barrier();
1468 std::list<NOMAD::Direction>::const_iterator it , end;
1469
1470
1471 // poll centers:
1472 const NOMAD::Eval_Point * poll_centers[2] , * poll_center;
1473 poll_centers[0] = barrier.get_poll_center();
1474 poll_centers[1] = (_p.use_sec_poll_center()) ?
1475 barrier.get_sec_poll_center() : NULL;
1476
1477 if ( !poll_centers[0] && !poll_centers[1] )
1478 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
1479 "Mads::poll(): could not get a poll center" );
1480
1481
1482 // Keep original directions + reduction in reducedPollDirs
1483 std::list<NOMAD::Direction> *dirs=new std::list<NOMAD::Direction>[2];
1484 std::list<NOMAD::Direction> *reducedPollDirs=new std::list<NOMAD::Direction>[2];
1485 std::list<NOMAD::Direction>::iterator itDir;
1486
1487
1488 // loop on the two poll centers for creation of evaluation point
1489 // -----------------------------
1490 NOMAD::poll_type i_pc = NOMAD::PRIMARY;
1491 poll_center = poll_centers[NOMAD::PRIMARY];
1492
1493 bool reducePollToNDir=false;
1494
1495 while ( true )
1496 {
1497 if ( poll_center )
1498 {
1499 // add the poll center signature
1500 signatures.push_back(poll_center->get_signature());
1501
1502 // Creation of the poll directions
1503 set_poll_directions ( dirs[i_pc] , i_pc , offset , *poll_center , stop , stop_reason );
1504
1505 // Reduction is applied only to achieve ortho n+1
1506 reducePollToNDir=dirs_have_orthomads_np1(dirs[i_pc]);
1507
1508 // creation of the poll trial points in the evaluator control:
1509 if (reducePollToNDir)
1510 {
1511
1512 // Keep poll directions unchanged (store directions even those that will be snaped to bounds)
1513 reducedPollDirs[i_pc].assign(dirs[i_pc].begin(),dirs[i_pc].end());
1514
1515 _ev_control_for_sorting.clear_eval_lop();
1516
1517
1518 // Sort the directions only if mesh is not finest
1519 if ( ! _mesh->is_finest() )
1520 {
1521
1522 // 1st sorting of points based on feas. or infeas. success direction. IMPORTANT removes out of bounds -> this justifies to proceede in two steps
1523 set_poll_trial_points(dirs[i_pc],offset,*poll_center,stop,stop_reason,true);
1524 if (stop)
1525 {
1526 delete[] dirs;
1527 delete[] reducedPollDirs;
1528 return;
1529 }
1530
1531 #ifdef USE_MPI
1532 // asynchronous mode: wait for truth evaluations in progress:
1533 if ( _p.get_asynchronous() )
1534 {
1535 std::list<const NOMAD::Eval_Point *> eval_pts;
1536 _ev_control.wait_for_evaluations ( NOMAD::ASYNCHRONOUS ,
1537 _true_barrier ,
1538 _sgte_barrier ,
1539 _pareto_front ,
1540 stop ,
1541 stop_reason ,
1542 success ,
1543 eval_pts );
1544 }
1545 #endif
1546
1547 // 2nd sorting of points based on model and surrogate if available
1548 _ev_control_for_sorting.ordering_lop( NOMAD::POLL,stop,stop_reason,_true_barrier,_sgte_barrier );
1549 if (stop)
1550 {
1551 delete[] dirs;
1552 delete[] reducedPollDirs;
1553 return;
1554 }
1555 }
1556
1557
1558
1559 // reduce the number of poll direction using dir indices from ev_control_for_sorting and original poll directions (reducedPollDirs)
1560 bool hasBeenReduced=set_reduced_poll_to_n_directions(reducedPollDirs[i_pc],*poll_center);
1561
1562
1563 // if hasBeenReduced than reassign dirs for setting poll trial points (reduced)
1564 // else original dirs are considered
1565 if (hasBeenReduced)
1566 dirs[i_pc].assign(reducedPollDirs[i_pc].begin(),reducedPollDirs[i_pc].end());
1567
1568 }
1569
1570 set_poll_trial_points(dirs[i_pc],offset,*poll_center,stop,stop_reason,false);
1571 offset = dirs[i_pc].size();
1572
1573 if (!reducePollToNDir)
1574 {
1575 // 2nd sorting of points based on model and surrogate if available
1576 _ev_control.ordering_lop( NOMAD::POLL,stop,stop_reason,_true_barrier,_sgte_barrier );
1577 }
1578
1579
1580 }
1581
1582 if (stop)
1583 {
1584 delete[] dirs;
1585 delete[] reducedPollDirs;
1586 return;
1587 }
1588
1589 // loop increment:
1590 if ( i_pc == NOMAD::PRIMARY)
1591 {
1592 i_pc = NOMAD::SECONDARY;
1593 poll_center = poll_centers[NOMAD::SECONDARY];
1594 }
1595 else
1596 break;
1597 }
1598
1599
1600 // display the re-ordered list of poll trial points:
1601 if ( display_degree == NOMAD::FULL_DISPLAY && !stop )
1602 {
1603 const std::set<NOMAD::Priority_Eval_Point> & poll_pts = _ev_control.get_eval_lop();
1604 if (!reducePollToNDir)
1605 out << std::endl << NOMAD::open_block ( "re-ordered list of "
1606 + NOMAD::itos ( poll_pts.size() )
1607 + " poll trial points." );
1608 else
1609 out << std::endl << NOMAD::open_block ( "re-ordered and reduced (dynamic directions may be added after evaluations) list of "
1610 + NOMAD::itos ( poll_pts.size() )
1611 + " poll trial points" );
1612
1613 std::set<NOMAD::Priority_Eval_Point>::const_iterator end2 = poll_pts.end() , it2;
1614 for ( it2 = poll_pts.begin() ; it2 != end2 ; ++it2 )
1615 {
1616 x = it2->get_point();
1617 x->display_tag ( out );
1618 out << " : ( ";
1619 x->Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
1620 out << " )";
1621 if ( x->get_direction() )
1622 out << " (dir " << x->get_direction()->get_index() << ")";
1623 out << std::endl;
1624 }
1625 out.close_block();
1626 }
1627
1628
1629 _stats.add_poll_pts ( _ev_control.get_nb_eval_points() );
1630
1631 // the directions are checked to satisfy a minimum
1632 // poll size with integer variables:
1633 check_directions ( forbid_poll_size_stop );
1634
1635 // eval_list_of_points (poll):
1636 // ---------------------------
1637 std::list<const NOMAD::Eval_Point *> *evaluated_pts=new std::list<const NOMAD::Eval_Point *>;
1638 _ev_control.eval_list_of_points ( NOMAD::POLL ,
1639 _true_barrier ,
1640 _sgte_barrier ,
1641 _pareto_front ,
1642 stop ,
1643 stop_reason ,
1644 new_feas_inc ,
1645 new_infeas_inc ,
1646 success ,
1647 evaluated_pts );
1648
1649
1650 // If ortho mads n+1, complete poll with additional evaluations obtained dynamically
1651 if (!stop && success !=NOMAD::FULL_SUCCESS && _p.has_dynamic_direction())
1652 {
1653 _ev_control.reset();
1654
1655 // loop again on the two poll centers to obtain dynamic direction
1656 // ---------------------------------------------------------------------------
1657 i_pc = NOMAD::PRIMARY;
1658 poll_center = poll_centers[NOMAD::PRIMARY];
1659 offset=0;
1660 while ( true )
1661 {
1662 if ( poll_center && NOMAD::Mads::dirs_have_orthomads_np1(reducedPollDirs[i_pc]))
1663 {
1664 std::list<NOMAD::Direction> dyn_dirs;
1665
1666 #ifdef USE_MPI
1667 // asynchronous mode: wait for the evaluations in progress:
1668 if ( _p.get_asynchronous() )
1669 {
1670 _ev_control.wait_for_evaluations ( NOMAD::ASYNCHRONOUS ,
1671 _true_barrier ,
1672 _sgte_barrier ,
1673 _pareto_front ,
1674 stop ,
1675 stop_reason ,
1676 success ,
1677 *evaluated_pts );
1678 }
1679 #endif
1680
1681 bool hasNewDynDir=get_dynamic_directions (reducedPollDirs[i_pc],
1682 dyn_dirs,
1683 *poll_center);
1684
1685
1686 // Set new poll points obtained dynamically
1687 if (hasNewDynDir)
1688 {
1689 set_poll_trial_points(dyn_dirs,
1690 offset,
1691 *poll_center,
1692 stop,
1693 stop_reason,
1694 false);
1695
1696 if (stop)
1697 {
1698 delete evaluated_pts;
1699 delete[] dirs;
1700 delete[] reducedPollDirs;
1701 return;
1702 }
1703 }
1704 offset = dyn_dirs.size();
1705 }
1706 // loop increment:
1707 if ( i_pc == NOMAD::PRIMARY )
1708 {
1709 i_pc = NOMAD::SECONDARY;
1710 poll_center = poll_centers[NOMAD::SECONDARY];
1711 }
1712 else
1713 break;
1714 }
1715
1716 if ( display_degree == NOMAD::FULL_DISPLAY )
1717 {
1718 const std::set<NOMAD::Priority_Eval_Point> & poll_pts = _ev_control.get_eval_lop();
1719 out << std::endl << NOMAD::open_block ( "re-ordered and complete (dynamic directions added) list of "
1720 + NOMAD::itos ( poll_pts.size() )
1721 + " poll trial points" );
1722
1723 std::set<NOMAD::Priority_Eval_Point>::const_iterator end2 = poll_pts.end() , it2;
1724 for ( it2 = poll_pts.begin() ; it2 != end2 ; ++it2 ) {
1725 x = it2->get_point();
1726 x->display_tag ( out );
1727 out << " : ( ";
1728 x->Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
1729 out << " )";
1730 if ( x->get_direction() )
1731 out << " (dir " << x->get_direction()->get_index() << ")";
1732 out << std::endl;
1733 }
1734 out.close_block();
1735 }
1736
1737
1738
1739
1740 // Eval additional point(s) :
1741 // ---------------------------
1742 _ev_control.eval_list_of_points ( NOMAD::POLL ,
1743 _true_barrier ,
1744 _sgte_barrier ,
1745 _pareto_front ,
1746 stop ,
1747 stop_reason ,
1748 new_feas_inc ,
1749 new_infeas_inc ,
1750 success );
1751
1752 if (success==NOMAD::FULL_SUCCESS)
1753 _stats.add_nb_success_dyn_dir();
1754
1755 }
1756
1757 delete evaluated_pts;
1758 delete[] dirs;
1759 delete[] reducedPollDirs;
1760
1761
1762 // extended poll for categorical variables:
1763 // ----------------------------------------
1764 if ( !stop &&
1765 _extended_poll &&
1766 success != NOMAD::FULL_SUCCESS &&
1767 _p.get_extended_poll_enabled() ) {
1768
1769 // display:
1770 if ( display_degree == NOMAD::FULL_DISPLAY )
1771 out << std::endl << NOMAD::open_block ( "MADS extended poll" ) << std::endl;
1772
1773 #ifdef USE_MPI
1774 // asynchronous mode: wait for the evaluations in progress:
1775 if ( _p.get_asynchronous() ) {
1776 std::list<const NOMAD::Eval_Point *> evaluated_pts;
1777 _ev_control.wait_for_evaluations ( NOMAD::ASYNCHRONOUS ,
1778 _true_barrier ,
1779 _sgte_barrier ,
1780 _pareto_front ,
1781 stop ,
1782 stop_reason ,
1783 success ,
1784 evaluated_pts );
1785 }
1786 #endif
1787
1788 // reset the extended poll object:
1789 _extended_poll->poll_reset();
1790
1791 // call the user defined method changing the categorical variables
1792 // (this creates the list of extended poll points):
1793 _extended_poll->construct_extended_points ( *barrier.get_poll_center() );
1794
1795 // add the signatures in use to the list of poll signatures:
1796 {
1797 const std::set<NOMAD::Signature_Element> &
1798 tmp = _extended_poll->get_poll_signatures();
1799 std::set<NOMAD::Signature_Element>::const_iterator it , end = tmp.end();
1800 for ( it = tmp.begin() ; it != end ; ++it )
1801 signatures.push_back ( it->get_signature() );
1802 }
1803
1804 // execute the extended poll:
1805 int nb_ext_poll_pts;
1806 _extended_poll->run ( *this ,
1807 nb_ext_poll_pts ,
1808 stop ,
1809 stop_reason ,
1810 success ,
1811 new_feas_inc ,
1812 new_infeas_inc );
1813
1814 // stats updates:
1815 _stats.add_ext_poll_pts ( nb_ext_poll_pts );
1816 if ( success == NOMAD::FULL_SUCCESS )
1817 _stats.add_ext_poll_succ();
1818 _stats.add_nb_ext_polls();
1819
1820 // display:
1821 if ( display_degree == NOMAD::FULL_DISPLAY )
1822 out << std::endl << NOMAD::close_block ( "end of extended poll" ) << std::endl;
1823 }
1824
1825 // stats updates:
1826 if ( success == NOMAD::FULL_SUCCESS )
1827 _stats.add_poll_success();
1828
1829 _stats.add_nb_poll_searches();
1830
1831 // success directions (feasible and infeasible):
1832 update_success_directions ( new_feas_inc , true );
1833 update_success_directions ( new_infeas_inc , false );
1834
1835 #ifdef DEBUG
1836 if ( !new_feas_inc && !new_infeas_inc )
1837 out << "No new feasible or infeasible incumbent" << std::endl << std::endl;
1838 #endif
1839
1840 // check the PEB constraints: if we have a new best infeasible
1841 // incumbent from another infeasible incumbent
1842 // ( active_barrier.check_PEB_constraints() ):
1843 if ( _p.get_barrier_type() == NOMAD::PEB_P && new_infeas_inc &&
1844 new_infeas_inc->get_poll_center_type() == NOMAD::INFEASIBLE )
1845 ( ( _p.get_opt_only_sgte() ) ? _sgte_barrier : _true_barrier ).check_PEB_constraints( *new_infeas_inc , display_degree==NOMAD::FULL_DISPLAY );
1846
1847 // final display:
1848 if ( display_degree == NOMAD::FULL_DISPLAY )
1849 out << NOMAD::close_block ( "end of poll" );
1850 }
1851
1852 /*---------------------------------------------------------*/
1853 /* Reduction to n directions for each direction group */
1854 /* of a poll center. (private) */
1855 /* return false if not enough directions provided/returned */
1856 /*---------------------------------------------------------*/
1857 // A direction group corresponds to a variable group having directions.
1858 // A variable group of categorical variables does not possess directions.
set_reduced_poll_to_n_directions(std::list<NOMAD::Direction> & dirs,const NOMAD::Eval_Point & poll_center)1859 bool NOMAD::Mads::set_reduced_poll_to_n_directions(std::list<NOMAD::Direction> & dirs,
1860 const NOMAD::Eval_Point & poll_center)
1861 {
1862 NOMAD::Signature * cur_signature = poll_center.get_signature();
1863 size_t n = cur_signature->get_n()-cur_signature->get_nb_fixed_variables() ;
1864
1865 // No direction for categorical variables
1866 size_t n_cat = cur_signature->get_n_categorical();
1867
1868 // Verify that enough directions for reduction are provided
1869 if ( dirs.size()<n-n_cat )
1870 return false;
1871
1872 // Maximum number of direction groups
1873 std::list<NOMAD::Direction>::iterator itDirs;
1874 size_t maxDirGroupIndex=0;
1875 size_t dgi;
1876 for (itDirs=dirs.begin();itDirs!=dirs.end() ; ++itDirs)
1877 {
1878 dgi=(*itDirs).get_dir_group_index();
1879 if (dgi>maxDirGroupIndex) maxDirGroupIndex=dgi;
1880 }
1881
1882 std::list<NOMAD::Direction> TmpDirs(dirs);
1883 dirs.clear();
1884
1885
1886 // Loop on each direction group
1887 for (dgi=0;dgi<=maxDirGroupIndex;++dgi)
1888 {
1889
1890 // Get all poll directions with a given direction group index + Get a vector of unique indices for those directions
1891 std::vector<NOMAD::Direction> pollDirs;
1892 std::vector<int> pollDirIndices;
1893 bool containsOrthoMads=false;
1894 for (itDirs=TmpDirs.begin();itDirs!=TmpDirs.end() ; ++itDirs)
1895 {
1896 if ( static_cast<size_t>((*itDirs).get_dir_group_index()) == dgi )
1897 {
1898 pollDirs.push_back(*itDirs);
1899 pollDirIndices.push_back((*itDirs).get_index());
1900 if (!containsOrthoMads)
1901 containsOrthoMads=NOMAD::dir_is_orthomads((*itDirs).get_type());
1902 }
1903 }
1904
1905
1906 std::list<NOMAD::Direction> sortedDirs;
1907 std::list<NOMAD::Direction>::iterator itSortedDirs;
1908 // Sort the directions only if mesh is not finest
1909 if ( !_mesh->is_finest() )
1910 {
1911
1912 const std::set<NOMAD::Priority_Eval_Point> & LOP=_ev_control_for_sorting.get_eval_lop();
1913
1914 if ( LOP.size()==0 )
1915 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
1916 "Mads::set_reduced_poll_to_n_directions(): the _ev_control_for_sorting does not have a list of evaluation points." );
1917
1918
1919 // Get all directions from ev_control ordered lop (list of evaluation points) with a given direction group index and given poll center
1920 // Get a set of unique indices of those directions
1921 std::list<int> sortedDirIndices;
1922 std::set<int> indices;
1923 std::list<int>::iterator itSortedDirIndices;
1924 std::set<NOMAD::Priority_Eval_Point>::const_iterator citLOP;
1925 for (citLOP=LOP.begin();citLOP!=LOP.end();++citLOP)
1926 {
1927 const NOMAD::Eval_Point *eval_point=(*citLOP).get_point();
1928 if ( static_cast<size_t>(eval_point->get_direction()->get_dir_group_index()) == dgi &&
1929 *(eval_point->get_poll_center())==poll_center)
1930 {
1931 int index=eval_point->get_direction()->get_index();
1932 if ( indices.size() == 0 || indices.find(index) == indices.end() ) // if the index is already in indices no need to add it in sortedDirIndices to avoid duplicate.
1933 sortedDirIndices.push_back(index);
1934 indices.insert(index); // If the index is already in the set IT IS NOT INSERTED --> set of unique sort integers
1935
1936 }
1937
1938 }
1939
1940 if ( sortedDirIndices.size()==0 )
1941 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
1942 "Mads::set_reduced_poll_to_n_directions(): no directions with proper group index available from _ev_control_for_sorting!" );
1943
1944 // A direction from _ev_control may have been suppressed if it does not satisfy bound constraint and is not snapped to bounds
1945 // --> complete sorted direction with remaining directions in poll dirs
1946 //
1947 // 2 - Add poll directions (from tmpDirs) in the same order as sorted direction indices (from ev_control)
1948 std::vector<int>::iterator itPollDirIndices;
1949 std::vector<NOMAD::Direction>::iterator itPollDirs=pollDirs.begin();
1950 size_t pos;
1951 for ( itSortedDirIndices = sortedDirIndices.begin() ; itSortedDirIndices != sortedDirIndices.end() ; ++itSortedDirIndices)
1952 {
1953 itPollDirIndices=find(pollDirIndices.begin(),pollDirIndices.end(),*itSortedDirIndices);
1954 if ( itPollDirIndices!=pollDirIndices.end() )
1955 {
1956 pos=distance(pollDirIndices.begin(),itPollDirIndices);
1957 itPollDirs=pollDirs.begin();
1958 std::advance(itPollDirs,pos);
1959 sortedDirs.push_back(*itPollDirs);
1960 }
1961 }
1962 // 3 - complete with remaining pollDirs directions
1963 if ( sortedDirs.size() != pollDirs.size() )
1964 {
1965 itPollDirs=pollDirs.begin();
1966 for ( itPollDirIndices = pollDirIndices.begin() ; itPollDirIndices != pollDirIndices.end() ; ++itPollDirIndices,++itPollDirs)
1967 {
1968 itSortedDirIndices=find(sortedDirIndices.begin(),sortedDirIndices.end(),*itPollDirIndices);
1969 if ( itSortedDirIndices == sortedDirIndices.end() )
1970 // Handle the case where poll direction not in sorted directions --> put it at the end
1971 sortedDirs.push_back(*itPollDirs);
1972 }
1973 }
1974
1975 }
1976 else
1977 sortedDirs.assign(pollDirs.begin(),pollDirs.end());
1978
1979 // Make a spanning set of directions (this is slightly different Ortho n+1 paper but still we have the garantee that Dk grows asymptotically dense because D^o_k has not been sorted if mesh_index_is_max)
1980 // Sequentially add sorted directions that increase the rank in two situations:
1981 // - If mesh is not finest -> consider all directions for adding -> n directions
1982 // - If mesh is finest but some ORTHO MADS directions are present -> only consider ortho mads dir for adding -> n directions
1983 // - Else, all directions are considered -> more than n directions
1984 // See paper Ortho n+1 paper for details
1985
1986
1987 size_t currentRank=get_rank_from_dirs(dirs);
1988 for (itSortedDirs=sortedDirs.begin();itSortedDirs!=sortedDirs.end();++itSortedDirs)
1989 {
1990 dirs.push_back(*itSortedDirs);
1991 if ( !_mesh->is_finest() || ( _mesh->is_finest() && containsOrthoMads))
1992 {
1993 size_t rank=get_rank_from_dirs(dirs);
1994 if (rank>currentRank && rank<=n-n_cat && NOMAD::dir_is_orthomads((*itSortedDirs).get_type()))
1995 currentRank++;
1996 else
1997 dirs.pop_back();
1998 }
1999 }
2000
2001
2002 }
2003 const NOMAD::Display & out = _p.out();
2004 NOMAD::dd_type display_degree = out.get_poll_dd();
2005 if ( dirs.size()!=n-n_cat )
2006 {
2007 if (display_degree == NOMAD::FULL_DISPLAY )
2008 {
2009 out << std::endl << NOMAD::open_block ( "The number of reduced directions is lower than n-n_categorical: ");
2010 out << dirs.size() << ". No reduction is performed." << std::endl;
2011 out << NOMAD::close_block();
2012 }
2013 return false;
2014 }
2015 return true;
2016 }
2017
2018 /*----------------------------------------------------------------*/
2019 /* Get the rank from a list of directions (private) */
2020 /*----------------------------------------------------------------*/
get_rank_from_dirs(const std::list<NOMAD::Direction> & dirs)2021 int NOMAD::Mads::get_rank_from_dirs(const std::list<NOMAD::Direction> & dirs)
2022 {
2023 if (dirs.size()==0)
2024 return 0;
2025
2026 std::list<NOMAD::Direction>::const_iterator it=dirs.begin();
2027 size_t m=(*it).size();
2028 size_t n=dirs.size();
2029
2030 double ** M = new double *[m];
2031 for (size_t i=0 ; i<m ; ++i )
2032 {
2033 it=dirs.begin();
2034 M[i] = new double[n];
2035 for (size_t j = 0 ; j < n ; ++j )
2036 {
2037 M[i][j] = (*it)[static_cast<int>(i)].value() ;
2038 ++it;
2039 }
2040 }
2041
2042 int rank=NOMAD::get_rank(M,m,n);
2043
2044 for (size_t i = 0 ; i < m ; ++i )
2045 {
2046 delete[] M[i];
2047 }
2048 delete[] M;
2049 return rank;
2050
2051 }
2052
2053 /*---------------------------------------------------------------------------------------*/
2054 /* compute a prospect point by optimizing quadratic models of obj(s) and constraints */
2055 /* (private) */
2056 /*---------------------------------------------------------------------------------------*/
optimize_quad_model(const NOMAD::Eval_Point & poll_center,const std::list<NOMAD::Direction> & dirs,NOMAD::Point & prospect_point)2057 bool NOMAD::Mads::optimize_quad_model ( const NOMAD::Eval_Point & poll_center ,
2058 const std::list<NOMAD::Direction> & dirs ,
2059 NOMAD::Point & prospect_point )
2060 {
2061 const NOMAD::Display & out = _p.out();
2062
2063 // surrogate or truth model evaluations:
2064 NOMAD::eval_type ev_type =
2065 ( _p.get_opt_only_sgte() ) ? NOMAD::SGTE : NOMAD::TRUTH;
2066
2067 // active cache:
2068 const NOMAD::Cache & cache = get_cache();
2069
2070 NOMAD::Point delta,Delta;
2071 NOMAD::Signature * signature=poll_center.get_signature();
2072 _mesh->get_delta ( delta );
2073 _mesh->get_Delta ( Delta );
2074
2075 // compute the interpolation radius: points in Y must be at
2076 // a max distance of ms_radius_factor times Delta^k:
2077 NOMAD::Point interpolation_radius = Delta;
2078 interpolation_radius *= _p.get_model_quad_radius_factor();
2079
2080
2081 // Epsilon for quad model hypercube scaling
2082 NOMAD::Double epsilon = _p.get_model_np1_quad_epsilon();
2083
2084 #ifdef DEBUG
2085 out << std::endl << NOMAD::open_block ( "Quadratic model for (n+1)th prospect point") << std::endl
2086 << "model construction for " << ev_type << std::endl
2087 << "nbr of cache pts: " << cache.size() << std::endl
2088 << "mesh indices : ( " << _mesh->get_mesh_indices () << " )" << std::endl
2089 << "poll center : ( " << poll_center << " )" << std::endl
2090 << "poll size : ( " << Delta << " )" << std::endl
2091 << "interpol. radius: ( " << interpolation_radius << " )" << std::endl
2092 << "epsilon hypercube: ( " << epsilon << " )" << std::endl;;
2093 #endif
2094
2095
2096 // creation of the model for all bb outputs:
2097 std::vector<NOMAD::bb_output_type> bbot = _p.get_bb_output_type();
2098 NOMAD::Quad_Model model ( out , bbot , cache , *signature );
2099 NOMAD::Model_Stats tmp_stats;
2100 NOMAD::Clock clock;
2101
2102 // flag to detect model or optimization errors:
2103 bool error = true;
2104
2105 // construct interpolation set Y:
2106 int min_Y_size = _p.get_model_quad_min_Y_size();
2107 int max_Y_size = _p.get_model_quad_max_Y_size();
2108
2109 model.construct_Y ( poll_center , interpolation_radius , max_Y_size );
2110
2111 int nY = model.get_nY();
2112
2113 #ifdef DEBUG
2114 out << std::endl << "number of points in Y: " << nY;
2115 if ( nY < 2 || ( min_Y_size < 0 && nY <= model.get_nfree() ) )
2116 out << " (not enough)";
2117 out << std::endl;
2118 #endif
2119
2120 if ( nY < 2 || ( min_Y_size < 0 && nY <= model.get_nfree() ) )
2121 tmp_stats.add_not_enough_pts();
2122 else
2123 {
2124 #ifdef DEBUG
2125 out << std::endl;
2126 model.display_Y ( out , "unscaled interpolation set Y" );
2127 #endif
2128
2129 // define scaling with rotation: obtain an hypercube [0,1]^n formed by truncated directions
2130 model.define_scaling_by_directions ( dirs, delta ,epsilon);
2131
2132 #ifdef DEBUG
2133 out << std::endl;
2134 model.display_Y ( out , "scaled interpolation set Ys" );
2135 #endif
2136
2137 // error check:
2138 if ( model.get_error_flag() )
2139 tmp_stats.add_construction_error();
2140
2141 // no model error:
2142 else {
2143
2144 // construct model:
2145 model.construct ( _p.get_model_quad_use_WP() , NOMAD::SVD_EPS , NOMAD::SVD_MAX_MPN , max_Y_size );
2146 tmp_stats.add_construction_time ( clock.get_CPU_time() );
2147 tmp_stats.update_nY ( model.get_nY() );
2148
2149 // display model characteristics:
2150 #ifdef DEBUG
2151 out << std::endl;
2152 model.display_model_coeffs ( out );
2153 out << std::endl;
2154 model.display_Y_error ( out );
2155 #endif
2156
2157
2158 // count model:
2159 if ( ev_type == NOMAD::TRUTH )
2160 tmp_stats.add_nb_truth();
2161 else
2162 tmp_stats.add_nb_sgte();
2163
2164 switch ( model.get_interpolation_type() )
2165 {
2166 case NOMAD::MFN:
2167 tmp_stats.add_nb_MFN();
2168 break;
2169 case NOMAD::WP_REGRESSION:
2170 tmp_stats.add_nb_WP_regression();
2171 break;
2172 case NOMAD::REGRESSION:
2173 tmp_stats.add_nb_regression();
2174 break;
2175 default:
2176 break;
2177 }
2178
2179 // check model error flag:
2180 const NOMAD::Double & cond = model.get_cond();
2181 if ( model.get_error_flag() ||
2182 !cond.is_defined() ||
2183 cond > NOMAD::SVD_MAX_COND )
2184 {
2185 if ( model.get_error_flag() )
2186 tmp_stats.add_construction_error();
2187 else
2188 tmp_stats.add_bad_cond();
2189 }
2190 else
2191 {
2192 int n = model.get_n();
2193 std::string error_str;
2194 int i;
2195
2196 // initial displays:
2197 if ( _p.get_display_degree() == NOMAD::FULL_DISPLAY )
2198 {
2199 std::ostringstream oss;
2200 oss << "Quad model optimization for prospect point";
2201 out << std::endl << NOMAD::open_block ( oss.str() );
2202 }
2203
2204 // parameters creation:
2205 NOMAD::Parameters model_param ( out );
2206
2207 // number of variables:
2208 model_param.set_DIMENSION ( n );
2209
2210 // blackbox outputs:
2211 model_param.set_BB_OUTPUT_TYPE ( bbot );
2212
2213 // barrier parameters:
2214 model_param.set_H_MIN ( _p.get_h_min () );
2215 model_param.set_H_NORM ( _p.get_h_norm() );
2216
2217 // starting points:
2218 model_param.set_X0 ( NOMAD::Point ( n , 500.0 ) );
2219
2220 // fixed variables:
2221 for ( i = 0 ; i < n ; ++i )
2222 if ( model.variable_is_fixed(i) || _p.variable_is_fixed(i) )
2223 model_param.set_FIXED_VARIABLE(i);
2224
2225 // no model search and no model ordering:
2226 model_param.set_MODEL_SEARCH ( false );
2227 model_param.set_MODEL_EVAL_SORT ( false );
2228 model_param.set_DIRECTION_TYPE (NOMAD::ORTHO_2N); // use 2N for model search rather than the default Ortho n+1
2229
2230 // display:
2231 model_param.set_DISPLAY_DEGREE ( NOMAD::NO_DISPLAY );
2232
2233 // mesh: use isotropic mesh
2234 model_param.set_ANISOTROPIC_MESH ( false );
2235 model_param.set_MESH_UPDATE_BASIS ( 4.0 );
2236 model_param.set_MESH_COARSENING_EXPONENT ( 1 );
2237 model_param.set_MESH_REFINING_EXPONENT ( -1 );
2238 model_param.set_INITIAL_MESH_INDEX ( 0 );
2239 model_param.set_INITIAL_MESH_SIZE ( NOMAD::Point ( n , 100.0 ) );
2240
2241 // maximum number of evaluations:
2242 model_param.set_MAX_BB_EVAL ( 50000 );
2243
2244 model_param.set_SNAP_TO_BOUNDS ( true );
2245
2246 // disable user calls:
2247 model_param.set_USER_CALLS_ENABLED ( false );
2248
2249 // set flags:
2250 bool flag_check_bimads , flag_reset_mesh , flag_reset_barriers , flag_p1_active;
2251 NOMAD::Mads::get_flags ( flag_check_bimads ,
2252 flag_reset_mesh ,
2253 flag_reset_barriers ,
2254 flag_p1_active );
2255
2256 NOMAD::Mads::set_flag_check_bimads (false );
2257 NOMAD::Mads::set_flag_reset_mesh ( true );
2258 NOMAD::Mads::set_flag_reset_barriers ( true );
2259 NOMAD::Mads::set_flag_p1_active ( false );
2260
2261 // bounds to optimize away from n first direction
2262 // Bound are consistent with model evaluator: x in [0;1000] for optimziation -> x in [-1;1] for model evaluation
2263 NOMAD::Point lb ( n , 0.0 );
2264 NOMAD::Point ub ( n , 1000.0 );
2265 model_param.set_LOWER_BOUND ( lb );
2266 model_param.set_UPPER_BOUND ( ub );
2267
2268 try
2269 {
2270
2271 // parameters validation:
2272 model_param.check();
2273
2274 // model evaluator creation:
2275 NOMAD::Evaluator *ev;
2276 if (model_param.get_nb_obj()==2)
2277 ev =new NOMAD::Multi_Obj_Quad_Model_Evaluator( model_param , model );
2278 else
2279 ev=new NOMAD::Single_Obj_Quad_Model_Evaluator( model_param , model );
2280
2281 // algorithm creation and execution:
2282 NOMAD::Mads mads ( model_param , ev );
2283
2284 NOMAD::Phase_One_Evaluator * p1ev=NULL;
2285 if ( model_param.get_nb_obj() >= 2 && ! flag_check_bimads )
2286 {
2287 p1ev = new NOMAD::Phase_One_Evaluator ( model_param , *ev );
2288 mads.get_evaluator_control().set_evaluator ( p1ev );
2289 }
2290 NOMAD::stop_type st = mads.run();
2291
2292
2293 delete ev;
2294 if (p1ev)
2295 delete p1ev;
2296
2297 // reset flags:
2298 NOMAD::Mads::set_flag_check_bimads ( flag_check_bimads );
2299 NOMAD::Mads::set_flag_reset_mesh ( flag_reset_mesh );
2300 NOMAD::Mads::set_flag_reset_barriers ( flag_reset_barriers );
2301 NOMAD::Mads::set_flag_p1_active ( flag_p1_active );
2302
2303 // check the stopping criterion:
2304 if ( st == NOMAD::CTRL_C || st == NOMAD::MAX_CACHE_MEMORY_REACHED ) {
2305 std::ostringstream oss;
2306 oss << "quad model optimization for prospect point: " << st;
2307 error_str = oss.str();
2308 error = true;
2309 }
2310
2311 // display solution:
2312 if ( _p.get_display_degree() == NOMAD::FULL_DISPLAY )
2313 {
2314 NOMAD::Display out_tmp = out;
2315 out_tmp.set_degrees ( NOMAD::NORMAL_DISPLAY );
2316 out_tmp.open_block("Optimization results");
2317 mads.display ( out_tmp );
2318 }
2319
2320 // get the solution(s):
2321 const NOMAD::Eval_Point * best_feas = mads.get_best_feasible ();
2322 const NOMAD::Eval_Point * best_infeas = mads.get_best_infeasible();
2323
2324
2325 if ( best_infeas )
2326 {
2327 prospect_point = *best_infeas;
2328 prospect_point *= 0.001;
2329 model.unscale ( prospect_point );
2330
2331 if ( _p.get_display_degree() == NOMAD::FULL_DISPLAY )
2332 {
2333 out << "best infeasible point before unscaling: ( ";
2334 prospect_point.NOMAD::Point::display ( out );
2335 out << " )" << std::endl;
2336 }
2337
2338
2339 }
2340 else if ( _p.get_display_degree() == NOMAD::FULL_DISPLAY )
2341 out << "no infeasible solution" << std::endl;
2342
2343
2344 if ( best_feas )
2345 {
2346 prospect_point = *best_feas;
2347 prospect_point *= 0.001;
2348 model.unscale ( prospect_point );
2349 if ( _p.get_display_degree() == NOMAD::FULL_DISPLAY )
2350 {
2351 out << "best feasible point after unscaling : ( ";
2352 prospect_point.NOMAD::Point::display ( out );
2353 out << " )" << std::endl;
2354 }
2355
2356 }
2357 else if ( _p.get_display_degree() == NOMAD::FULL_DISPLAY )
2358 out << "no feasible solution" << std::endl;
2359
2360
2361 if ( !prospect_point.is_defined() )
2362 {
2363 error = true;
2364 error_str = "optimization error: no solution";
2365 }
2366 else
2367 error=false;
2368 }
2369 catch ( std::exception & e )
2370 {
2371 error = true;
2372 error_str = std::string ( "optimization error: " ) + e.what();
2373 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ , error_str );
2374 }
2375 }
2376 }
2377 }
2378
2379 // update the stats:
2380 _stats.update_model_stats ( tmp_stats );
2381
2382 if ( _p.get_display_degree() == NOMAD::FULL_DISPLAY )
2383 {
2384 out << std::endl << "Prospect point. from quad. model: ";
2385 if ( !error)
2386 out << "( " << prospect_point << " )" << std::endl;
2387 else
2388 out << "failure" << std::endl;
2389
2390 out << NOMAD::close_block() << std::endl;
2391 }
2392
2393 #ifdef DEBUG
2394 out << NOMAD::close_block() << std::endl;
2395 #endif
2396
2397 return !error;
2398 }
2399
2400
2401 /*----------------------------------------------------------------*/
2402 /* set the poll directions based on signatures (private) */
2403 /*----------------------------------------------------------------*/
set_poll_directions(std::list<NOMAD::Direction> & dirs,NOMAD::poll_type i_pc,size_t offset,const NOMAD::Eval_Point & poll_center,bool & stop,NOMAD::stop_type & stop_reason)2404 void NOMAD::Mads::set_poll_directions ( std::list<NOMAD::Direction> & dirs ,
2405 NOMAD::poll_type i_pc ,
2406 size_t offset ,
2407 const NOMAD::Eval_Point & poll_center ,
2408 bool & stop ,
2409 NOMAD::stop_type & stop_reason )
2410 {
2411 const NOMAD::Display & out = _p.out();
2412 NOMAD::dd_type display_degree = out.get_poll_dd();
2413
2414 std::list<NOMAD::Direction>::const_iterator it , end;
2415
2416 if ( display_degree == NOMAD::FULL_DISPLAY )
2417 {
2418 if ( i_pc == NOMAD::SECONDARY )
2419 out << "secondary ";
2420 out << "poll center: ( ";
2421 poll_center.Point::display ( out, " ", 2, NOMAD::Point::get_display_limit() );
2422 out << " )" << std::endl;
2423 }
2424
2425 // get the poll center's signature:
2426 NOMAD::Signature * cur_signature = poll_center.get_signature();
2427
2428 if ( !cur_signature )
2429 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
2430 "Mads::poll(): could not get the poll center's signature" );
2431
2432 int n = cur_signature->get_n();
2433
2434 if ( n != poll_center.size() )
2435 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
2436 "Mads::poll(): the poll center has an incompatible signature" );
2437
2438 // get directions from the signature:
2439 cur_signature->get_directions ( dirs ,
2440 i_pc ,
2441 poll_center );
2442
2443
2444
2445 size_t k = 0;
2446 for ( it = dirs.begin() ; it != dirs.end() ; ++it, ++k )
2447 it->set_index ( static_cast<int>(offset + k) );
2448
2449
2450
2451 if ( !stop && dirs.empty() )
2452 {
2453 if ( display_degree == NOMAD::FULL_DISPLAY )
2454 out << "Mads::poll(): could not get directions: stop"
2455 << std::endl << NOMAD::close_block() << std::endl;
2456 stop = true;
2457 stop_reason = NOMAD::MESH_PREC_REACHED;
2458 return;
2459
2460 }
2461
2462
2463 // displays:
2464 if ( display_degree == NOMAD::FULL_DISPLAY )
2465 {
2466 end = dirs.end();
2467
2468 int nb_dirs = static_cast<int>(dirs.size());
2469
2470 out << std::endl
2471 << NOMAD::open_block ( "poll directions (include mesh size parameter)" );
2472 for ( it = dirs.begin() ; it != end ; ++it )
2473 {
2474 out << "dir ";
2475 out.display_int_w ( (*it).get_index() , nb_dirs );
2476 out << " : " << *it << std::endl;
2477 }
2478 out.close_block();
2479 }
2480 }
2481
2482
2483 /*----------------------------------------------------------------------------------*/
2484 /* check if a set of directions includes one Ortho-MADS N+1 direction (private) */
2485 /* (true if at least one direction in the set is of type Ortho-MADS N+1) */
2486 /*----------------------------------------------------------------------------------*/
dirs_have_orthomads_np1(const std::list<NOMAD::Direction> & dirs)2487 bool NOMAD::Mads::dirs_have_orthomads_np1( const std::list<NOMAD::Direction> & dirs)
2488 {
2489 std::list<NOMAD::Direction>::const_iterator it , end = dirs.end();
2490 for ( it = dirs.begin() ; it != end ; ++it )
2491 if ( (*it).get_type()==NOMAD::ORTHO_NP1_QUAD ||
2492 (*it).get_type()==NOMAD::ORTHO_NP1_NEG)
2493 return true;
2494 return false;
2495 }
2496
2497
2498 /*-------------------------------------------------------------------------*/
2499 /* check if a dir needs to be obtained from model optimization (private) */
2500 /* (true if all directions in the set are of type Ortho-MADS N+1 QUAD) */
2501 /*-------------------------------------------------------------------------*/
dir_from_model_opt(const std::list<NOMAD::Direction> & dirs)2502 bool NOMAD::Mads::dir_from_model_opt( const std::list<NOMAD::Direction> & dirs)
2503 {
2504 std::list<NOMAD::Direction>::const_iterator it , end = dirs.end();
2505 for ( it = dirs.begin() ; it != end ; ++it )
2506 if ( (*it).get_type()!=NOMAD::ORTHO_NP1_QUAD )
2507 return false;
2508 return true;
2509 }
2510
2511
2512
2513 /*----------------------------------------------------------------*/
2514 /* set the poll trial points based on poll directions (private) */
2515 /*----------------------------------------------------------------*/
set_poll_trial_points(std::list<NOMAD::Direction> & dirs,size_t offset,const NOMAD::Eval_Point & poll_center,bool & stop,NOMAD::stop_type & stop_reason,bool sorting)2516 void NOMAD::Mads::set_poll_trial_points (std::list<NOMAD::Direction> &dirs,
2517 size_t offset,
2518 const NOMAD::Eval_Point & poll_center,
2519 bool & stop,
2520 NOMAD::stop_type &stop_reason,
2521 bool sorting)
2522 {
2523 NOMAD::Signature * cur_signature=poll_center.get_signature();
2524 NOMAD::poll_center_type pc_type=( poll_center.is_feasible ( _p.get_h_min() ) ) ? NOMAD::FEASIBLE : NOMAD::INFEASIBLE;
2525
2526 int n = cur_signature->get_n();
2527 int m = _p.get_bb_nb_outputs();
2528 const std::vector<NOMAD::bb_input_type> & bbit = _p.get_bb_input_type();
2529
2530 std::list<NOMAD::Direction>::const_iterator it;
2531
2532 const NOMAD::Direction * dir;
2533 NOMAD::Eval_Point * pt;
2534
2535 const NOMAD::Display & out = _p.out();
2536 NOMAD::dd_type display_degree = out.get_poll_dd();
2537
2538 int k=0;
2539 for ( it = dirs.begin() ; it != dirs.end() ; ++it )
2540 {
2541 dir = &(*it);
2542 pt = new NOMAD::Eval_Point ( n , m );
2543
2544 // pt = poll_center + dir: with a particular case for binary variables
2545 // equal to 1 with dir=1: the variables are set to 0 (1+1=0 in binary):
2546 for (int i = 0 ; i < n ; ++i )
2547 (*pt)[i] = ( bbit[i]==NOMAD::BINARY && (*dir)[i]==1.0 && (poll_center)[i]==1.0 ) ? 0.0 : (*pt)[i] = (poll_center)[i] + (*dir)[i];
2548
2549
2550 if ( pt->Point::operator == ( poll_center ) )
2551 delete pt;
2552 else
2553 {
2554 pt->set_signature ( cur_signature );
2555 pt->set_direction ( dir );
2556 pt->set_poll_center_type ( pc_type );
2557 pt->set_poll_center ( &poll_center );
2558
2559 // random direction?
2560 if ( NOMAD::dir_is_random ( dir->get_type() ) )
2561 {
2562 int nb_dirs = static_cast<int>(dirs.size());
2563 NOMAD::Random_Pickup rp ( nb_dirs );
2564 pt->set_rand_eval_priority ( rp.pickup() );
2565 }
2566
2567 if (!sorting)
2568 _ev_control.add_eval_point ( pt ,
2569 display_degree ,
2570 _p.get_snap_to_bounds() ,
2571 NOMAD::Double() ,
2572 NOMAD::Double() ,
2573 NOMAD::Double() ,
2574 NOMAD::Double() );
2575 else
2576 {
2577 _ev_control_for_sorting.add_eval_point ( pt ,
2578 display_degree ,
2579 _p.get_snap_to_bounds() ,
2580 NOMAD::Double() ,
2581 NOMAD::Double() ,
2582 NOMAD::Double() ,
2583 NOMAD::Double() );
2584 }
2585
2586 ++k;
2587 }
2588 }
2589
2590 if ( k==0 )
2591 {
2592 if ( display_degree == NOMAD::FULL_DISPLAY )
2593 out << "Mads::poll(): could not generate poll trial points: stop"
2594 << std::endl << NOMAD::close_block() << std::endl;
2595 stop = true;
2596 stop_reason = NOMAD::MESH_PREC_REACHED;
2597 }
2598
2599
2600 return;
2601 }
2602
2603
2604 /*-------------------------------------------------------------*/
2605 /* compute the poll directions dynamically (private) */
2606 /*-------------------------------------------------------------*/
get_dynamic_directions(const std::list<NOMAD::Direction> & dirs,std::list<NOMAD::Direction> & newDirs,const NOMAD::Eval_Point & poll_center)2607 bool NOMAD::Mads::get_dynamic_directions (const std::list<NOMAD::Direction> & dirs,
2608 std::list<NOMAD::Direction> & newDirs,
2609 const NOMAD::Eval_Point & poll_center )
2610 {
2611
2612 const NOMAD::Signature * cur_signature=poll_center.get_signature();
2613 size_t n = cur_signature->get_n()-cur_signature->get_nb_fixed_variables();
2614 size_t n_cat = cur_signature->get_n_categorical();
2615
2616 const NOMAD::Display & out = _p.out();
2617 NOMAD::dd_type display_degree = out.get_poll_dd();
2618
2619 // Dynamic completion only if sufficient directions provided: (n-n_cat)->(n-n_cat)+1
2620 if ( dirs.size() < n-n_cat )
2621 return false;
2622
2623
2624 // Get the maximum number of direction groups
2625 std::list<NOMAD::Direction>::const_iterator itDir;
2626 int maxDirGroupIndex=0;
2627 int dgi;
2628 for (itDir=dirs.begin();itDir!=dirs.end() ; ++itDir)
2629 {
2630 dgi=(*itDir).get_dir_group_index();
2631 if (dgi>maxDirGroupIndex)
2632 maxDirGroupIndex=dgi;
2633 }
2634
2635 // Loop on each direction group to obtain a new direction
2636 for (dgi=0;dgi<=maxDirGroupIndex;++dgi)
2637 {
2638 int maxIndex=0;
2639
2640 // 1 - Search directions having the same direction group index
2641 std::list<NOMAD::Direction> rDirs;
2642 std::list<NOMAD::Double>::iterator it_fv;
2643 for (itDir=dirs.begin();itDir!=dirs.end() ; ++itDir)
2644 {
2645 if ((*itDir).get_index()>maxIndex)
2646 maxIndex=(*itDir).get_index();
2647 if ((*itDir).get_dir_group_index()==dgi)
2648 rDirs.push_back(*itDir);
2649 }
2650
2651 // 2 - add a dynamic direction from a quad model optimization or sum of direction negatives
2652 NOMAD::Direction dyn_dir=get_single_dynamic_direction(rDirs,poll_center);
2653 if ( dyn_dir.get_type()==NOMAD::DYN_ADDED )
2654 {
2655 dyn_dir.set_index(maxIndex+1);
2656 newDirs.push_back(dyn_dir);
2657 }
2658 }
2659
2660 if ( display_degree == NOMAD::FULL_DISPLAY )
2661 {
2662 out << std::endl;
2663 if ( newDirs.size()!= 0 )
2664 out << NOMAD::open_block ( "Added (n+1)th poll direction(s) (include mesh size parameter)" );
2665 else
2666 out << NOMAD::open_block ( "Cannot generate a (n+1)th poll direction" );
2667
2668 for ( itDir = newDirs.begin() ; itDir != newDirs.end() ; ++itDir )
2669 {
2670 out << "dir ";
2671 out.display_int_w ( (*itDir).get_index() , static_cast<int>(newDirs.size()) );
2672 out << " : " << *itDir << std::endl;
2673 }
2674 out.close_block();
2675 out << std::endl;
2676
2677 }
2678
2679 if ( newDirs.size()==0 )
2680 return false;
2681
2682
2683 return true;
2684 }
2685
2686
2687
2688 /*------------------------------------------------------------------------------*/
2689 /* get a single dynamic direction from incomplete poll */
2690 /* directions by optimization of a quad model or sum of negative (private) */
2691 /*------------------------------------------------------------------------------*/
2692 /* The new direction calculation is described in paper from */
2693 /* Audet, Ianni, Le Digabel and Tribes : Reducing the number of */
2694 /* function evaluations in Mesh Adaptive Direct Search Algorithms*/
2695 /*----------------------------------------------------------------*/
get_single_dynamic_direction(const std::list<NOMAD::Direction> & dirs,const NOMAD::Eval_Point & poll_center)2696 NOMAD::Direction NOMAD::Mads::get_single_dynamic_direction (const std::list<NOMAD::Direction> & dirs,
2697 const NOMAD::Eval_Point & poll_center)
2698 {
2699 const NOMAD::Signature * cur_signature=poll_center.get_signature();
2700 int n=cur_signature->get_n();
2701
2702 NOMAD::Direction Vb1( n , 0.0 ,NOMAD::UNDEFINED_DIRECTION);
2703
2704
2705 std::vector<NOMAD::Double> alpha;
2706 NOMAD::Double f_pc=(poll_center.is_feasible(_p.get_h_min())) ? poll_center.get_f():poll_center.get_h();
2707 NOMAD::Double lambda=0;
2708 std::list<NOMAD::Direction>::const_iterator itDir;
2709
2710 // -sum(d^i)
2711 for (itDir=dirs.begin();itDir!=dirs.end();++itDir)
2712 {
2713 for (int i=0; i<n; i++)
2714 {
2715 Vb1[i]-=(*itDir)[i].value();
2716 }
2717 }
2718
2719 // New direction
2720 int dirGroupIndex=(*dirs.begin()).get_dir_group_index();
2721 NOMAD::Direction V( n , 0.0 ,NOMAD::DYN_ADDED,dirGroupIndex);
2722
2723 // New direction obtained by quad model optimization or negative sum of directions
2724 NOMAD::Point prospect_point;
2725 bool success=false;
2726 if (dir_from_model_opt(dirs))
2727 success=optimize_quad_model(poll_center,dirs,prospect_point);
2728 for (int i=0; i<n; i++)
2729 {
2730 if (success)
2731 V[i]=prospect_point[i].value()-poll_center[i].value();
2732 else
2733 V[i]=Vb1[i]; // use -sum(d^i) if model optimization unsucessfull or no dynamic direction requested
2734 }
2735
2736 // Update the new directions depending on the input_types
2737 const std::vector<NOMAD::bb_input_type> & input_types=cur_signature->get_input_types();
2738
2739 NOMAD::Point delta,Delta;
2740 _mesh->get_delta ( delta );
2741 _mesh->get_Delta ( Delta );
2742 bool isZero=true;
2743 for (int i=0; i<n; ++i)
2744 {
2745 NOMAD::Double v=V[i].value(),vb1=Vb1[i].value(),dm=delta[i].value(),dp=Delta[i].value();
2746
2747 // Continous variables ---> rounding towards mesh node.
2748 if (input_types[i]==NOMAD::CONTINUOUS)
2749 {
2750 if ((vb1/dm).round()>=(v/dm).round())
2751 V[i] = (v/dm).ceil()*dm;
2752 else
2753 V[i] = (v/dm).floor()*dm;
2754 }
2755 // Integer variables:
2756 else if ( input_types[i] == NOMAD::INTEGER )
2757 {
2758 if ( v >= dp/3.0 )
2759 V[i] = v.ceil();
2760 else if ( v <= -dp/3.0 )
2761 V[i] = v.floor();
2762 else
2763 V[i] = v.round();
2764 }
2765 // binary variables:
2766 else if ( input_types[i] == NOMAD::BINARY )
2767 {
2768 if ( v != 0.0 ) V[i] = 1.0;
2769 }
2770 // categorical variables: set direction=0:
2771 else if ( input_types[i] == NOMAD::CATEGORICAL )
2772 V[i] = 0.0;
2773
2774 if (V[i]!=0)
2775 isZero=false;
2776 }
2777
2778 if (isZero)
2779 {
2780 NOMAD::Direction Vzero( n , 0.0 ,NOMAD::UNDEFINED_DIRECTION);
2781 return Vzero;
2782 }
2783 else
2784 return V;
2785 }
2786
2787
2788 /*----------------------------------------------------------------*/
2789 /* check the directions after the poll step (private) */
2790 /*----------------------------------------------------------------*/
2791 /* ensures that the last set of poll directions is small enough */
2792 /* with integer variables */
2793 /*----------------------------------------------------------------*/
check_directions(bool & forbid_poll_size_stop)2794 void NOMAD::Mads::check_directions ( bool & forbid_poll_size_stop )
2795 {
2796 if ( !_p.get_min_poll_size_defined() )
2797 {
2798
2799 NOMAD::Double v , min;
2800 const NOMAD::Point * dir;
2801 int i , n;
2802
2803 const NOMAD::Signature * signature;
2804
2805 const std::set<NOMAD::Priority_Eval_Point> & poll_pts = _ev_control.get_eval_lop();
2806 std::set<NOMAD::Priority_Eval_Point>::const_iterator end = poll_pts.end() , it;
2807 for ( it = poll_pts.begin() ; it != end ; ++it )
2808 {
2809
2810 signature = it->get_point()->get_signature();
2811
2812 if ( signature )
2813 {
2814
2815 dir = it->get_point()->get_direction();
2816
2817 if ( dir )
2818 {
2819
2820 n = dir->size();
2821
2822 if ( n == signature->get_n() )
2823 {
2824
2825 const std::vector<NOMAD::bb_input_type> & bbit
2826 = signature->get_input_types();
2827
2828 for ( i = 0 ; i < n ; ++i )
2829 {
2830 if ( bbit[i] == NOMAD::INTEGER )
2831 {
2832 v = (*dir)[i].abs();
2833 if ( v.is_defined() && v > 0.0 && ( !min.is_defined() || v < min ) )
2834 min = v;
2835 }
2836 }
2837 }
2838 }
2839 }
2840 }
2841
2842 if ( min.is_defined() && min > 1.0 )
2843 forbid_poll_size_stop = true;
2844 }
2845 }
2846
2847 /*---------------------------------------------------------*/
2848 /* update of the success directions, after the poll */
2849 /* (private) */
2850 /*---------------------------------------------------------*/
update_success_directions(const NOMAD::Eval_Point * new_inc,bool feasible) const2851 void NOMAD::Mads::update_success_directions ( const NOMAD::Eval_Point * new_inc ,
2852 bool feasible ) const
2853 {
2854 if ( new_inc && new_inc->get_direction() )
2855 {
2856
2857 const NOMAD::Direction * dir = new_inc->get_direction();
2858 NOMAD::Signature * signature = new_inc->get_signature();
2859
2860
2861 if ( !signature )
2862 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ ,
2863 "Mads::update_success_directions(): new incumbent has no signature" );
2864
2865 if ( feasible )
2866 new_inc->get_signature()->set_feas_success_dir ( *dir );
2867 else
2868 new_inc->get_signature()->set_infeas_success_dir ( *dir );
2869
2870 }
2871 }
2872
2873
2874 /*---------------------------------------------------------*/
2875 /* the search (private) */
2876 /*---------------------------------------------------------*/
search(bool & stop,NOMAD::stop_type & stop_reason,NOMAD::success_type & success,const NOMAD::Eval_Point * & new_feas_inc,const NOMAD::Eval_Point * & new_infeas_inc)2877 void NOMAD::Mads::search ( bool & stop ,
2878 NOMAD::stop_type & stop_reason ,
2879 NOMAD::success_type & success ,
2880 const NOMAD::Eval_Point *& new_feas_inc ,
2881 const NOMAD::Eval_Point *& new_infeas_inc )
2882 {
2883 int nb_search_pts;
2884 bool count_search;
2885 int mads_iteration = _stats.get_iterations();
2886 const NOMAD::Display & out = _p.out();
2887 NOMAD::dd_type display_degree = out.get_search_dd();
2888 NOMAD::success_type last_it_success = success;
2889 success = NOMAD::UNSUCCESSFUL;
2890
2891 // first display:
2892 if ( display_degree == NOMAD::FULL_DISPLAY )
2893 out << std::endl << NOMAD::open_block ( "MADS search" );
2894
2895 // 1. speculative search:
2896 if ( _p.get_speculative_search() )
2897 {
2898 if ( new_feas_inc || new_infeas_inc )
2899 {
2900 Speculative_Search ss ( _p );
2901
2902 ss.search ( *this ,
2903 nb_search_pts ,
2904 stop ,
2905 stop_reason ,
2906 success ,
2907 count_search ,
2908 new_feas_inc ,
2909 new_infeas_inc );
2910
2911 if ( success == NOMAD::FULL_SUCCESS )
2912 _stats.add_spec_success();
2913 if ( count_search )
2914 _stats.add_nb_spec_searches();
2915 _stats.add_spec_pts ( nb_search_pts );
2916 }
2917 }
2918
2919 // 2. user search:
2920 if ( success != NOMAD::FULL_SUCCESS && _user_search )
2921 {
2922
2923 // initial user search display:
2924 if ( display_degree == NOMAD::FULL_DISPLAY )
2925 {
2926 std::ostringstream oss;
2927 oss << NOMAD::USER_SEARCH;
2928 out << std::endl << NOMAD::open_block ( oss.str() ) << std::endl;
2929 }
2930
2931 // the search:
2932 _user_search->search ( *this ,
2933 nb_search_pts ,
2934 stop ,
2935 stop_reason ,
2936 success ,
2937 count_search ,
2938 new_feas_inc ,
2939 new_infeas_inc );
2940
2941 // update stats:
2942 if ( success == NOMAD::FULL_SUCCESS )
2943 _stats.add_usr_srch_success();
2944 if ( count_search )
2945 _stats.add_nb_usr_searches();
2946 _stats.add_usr_srch_pts ( nb_search_pts );
2947
2948 // final user search display:
2949 if ( display_degree == NOMAD::FULL_DISPLAY )
2950 {
2951 std::ostringstream oss;
2952 oss << "end of " << NOMAD::USER_SEARCH << " (" << success << ")";
2953 out << std::endl << NOMAD::close_block ( oss.str() ) << std::endl;
2954 }
2955 }
2956
2957 // 3. cache search:
2958 if ( success != NOMAD::FULL_SUCCESS && _p.get_cache_search() )
2959 {
2960
2961 // the search:
2962 _cache_search->search ( *this ,
2963 nb_search_pts ,
2964 stop ,
2965 stop_reason ,
2966 success ,
2967 count_search ,
2968 new_feas_inc ,
2969 new_infeas_inc );
2970
2971 // update stats:
2972 if ( success == NOMAD::FULL_SUCCESS )
2973 _stats.add_CS_success();
2974 if ( count_search )
2975 _stats.add_nb_cache_searches();
2976 _stats.add_CS_pts ( nb_search_pts );
2977 }
2978
2979 // 4. Model Searches (stats are updated inside the searches):
2980 if ( success != NOMAD::FULL_SUCCESS && _p.has_model_search() )
2981 {
2982
2983 #ifdef USE_MPI
2984 // asynchronous mode: wait for the evaluations in progress:
2985 if ( _p.get_asynchronous() )
2986 {
2987 std::list<const NOMAD::Eval_Point *> evaluated_pts;
2988 _ev_control.wait_for_evaluations ( NOMAD::ASYNCHRONOUS ,
2989 _true_barrier ,
2990 _sgte_barrier ,
2991 _pareto_front ,
2992 stop ,
2993 stop_reason ,
2994 success ,
2995 evaluated_pts );
2996 }
2997 #endif
2998
2999 // model search #1:
3000 _model_search1->search ( *this ,
3001 nb_search_pts ,
3002 stop ,
3003 stop_reason ,
3004 success ,
3005 count_search ,
3006 new_feas_inc ,
3007 new_infeas_inc );
3008
3009 // save the TGP model for the model ordering:
3010 if ( _p.get_model_search(1) == NOMAD::TGP_MODEL )
3011 {
3012 #ifdef USE_TGP
3013 _ev_control.set_last_TGP_model
3014 ( static_cast<NOMAD::TGP_Model_Search *>(_model_search1)->get_model() );
3015 #endif
3016 }
3017 // model search #2:
3018 if ( success != NOMAD::FULL_SUCCESS && _model_search2 )
3019 {
3020
3021 #ifdef USE_MPI
3022 // asynchronous mode: wait for the evaluations in progress:
3023 if ( _p.get_asynchronous() )
3024 {
3025 std::list<const NOMAD::Eval_Point *> evaluated_pts;
3026 _ev_control.wait_for_evaluations ( NOMAD::ASYNCHRONOUS ,
3027 _true_barrier ,
3028 _sgte_barrier ,
3029 _pareto_front ,
3030 stop ,
3031 stop_reason ,
3032 success ,
3033 evaluated_pts );
3034 }
3035 #endif
3036 _model_search2->search ( *this ,
3037 nb_search_pts ,
3038 stop ,
3039 stop_reason ,
3040 success ,
3041 count_search ,
3042 new_feas_inc ,
3043 new_infeas_inc );
3044
3045 // save the TGP model for the model ordering:
3046 if ( _p.get_model_search(2) == NOMAD::TGP_MODEL )
3047 {
3048 #ifdef USE_TGP
3049 _ev_control.set_last_TGP_model
3050 ( static_cast<NOMAD::TGP_Model_Search *>(_model_search2)->get_model() );
3051 #endif
3052 }
3053 }
3054 }
3055
3056 // 5. VNS search:
3057 if ( _p.get_VNS_search() &&
3058 success != NOMAD::FULL_SUCCESS &&
3059 last_it_success == NOMAD::UNSUCCESSFUL &&
3060 _mesh->is_finer_than_initial() &&
3061 _stats.get_iterations() > 0 )
3062 {
3063
3064 // check the VNS_trigger criterion:
3065 int bbe = _stats.get_bb_eval();
3066 if ( bbe==0 ||
3067 _stats.get_VNS_bb_eval() / static_cast<float>(bbe) < _p.get_VNS_trigger() )
3068 {
3069
3070 #ifdef USE_MPI
3071 // asynchronous mode: wait for the evaluations in progress:
3072 if ( _p.get_asynchronous() )
3073 {
3074 std::list<const NOMAD::Eval_Point *> evaluated_pts;
3075 _ev_control.wait_for_evaluations ( NOMAD::ASYNCHRONOUS ,
3076 _true_barrier ,
3077 _sgte_barrier ,
3078 _pareto_front ,
3079 stop ,
3080 stop_reason ,
3081 success ,
3082 evaluated_pts );
3083 }
3084 #endif
3085
3086 _VNS_search->search ( *this ,
3087 nb_search_pts ,
3088 stop ,
3089 stop_reason ,
3090 success ,
3091 count_search ,
3092 new_feas_inc ,
3093 new_infeas_inc );
3094
3095 if ( success == NOMAD::FULL_SUCCESS )
3096 _stats.add_VNS_success();
3097
3098 if ( count_search )
3099 _stats.add_nb_VNS_searches();
3100
3101 _stats.add_VNS_pts ( nb_search_pts );
3102 }
3103 }
3104
3105 // 6. Latin-Hypercube (LH) search:
3106 if ( success != NOMAD::FULL_SUCCESS && _p.get_LH_search_pi() > 0 )
3107 {
3108
3109 // for the first iteration: do not perform the
3110 // search if there was an initial LH search:
3111 if ( mads_iteration > 0 || _p.get_LH_search_p0() <= 0 ) {
3112
3113 LH_Search lh ( _p , false , _flag_p1_active );
3114
3115 lh.search ( *this ,
3116 nb_search_pts ,
3117 stop ,
3118 stop_reason ,
3119 success ,
3120 count_search ,
3121 new_feas_inc ,
3122 new_infeas_inc );
3123
3124 if ( success == NOMAD::FULL_SUCCESS )
3125 _stats.add_LH_success();
3126
3127 if ( count_search )
3128 _stats.add_nb_LH_searches();
3129
3130 _stats.add_LH_pts ( nb_search_pts );
3131 }
3132 }
3133
3134 if ( display_degree == NOMAD::FULL_DISPLAY )
3135 out << NOMAD::close_block ( "end of search" );
3136 }
3137
3138 /*---------------------------------------------------------*/
3139 /* x0 eval (private) */
3140 /*---------------------------------------------------------*/
eval_x0(bool & stop,NOMAD::stop_type & stop_reason)3141 void NOMAD::Mads::eval_x0 ( bool & stop ,
3142 NOMAD::stop_type & stop_reason )
3143 {
3144 const std::vector<NOMAD::Point *> & x0s = _p.get_x0s();
3145 const std::string & x0_cache_file = _p.get_x0_cache_file();
3146 if ( x0s.empty() && x0_cache_file.empty() )
3147 return;
3148
3149 const NOMAD::Display & out = _p.out();
3150 NOMAD::dd_type display_degree = out.get_gen_dd();
3151
3152 if ( display_degree == NOMAD::FULL_DISPLAY )
3153 out << std::endl << NOMAD::open_block ( "starting point evaluation" );
3154
3155 NOMAD::Eval_Point * pt;
3156 size_t k;
3157 int m = _p.get_bb_nb_outputs();
3158 int n = _p.get_dimension();
3159 std::ostringstream err;
3160
3161 // x0s from vector Parameters::_x0s:
3162 // ---------------------------------
3163 size_t x0s_size = x0s.size();
3164 for ( k = 0 ; k < x0s_size ; ++k )
3165 {
3166
3167 // the current starting point has to be in dimension n:
3168 if ( x0s[k]->size() != n )
3169 {
3170 err << "starting point ( " << *x0s[k] << " ) is not of dimension " << n;
3171 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ , err.str() );
3172 }
3173
3174 // creation of the Eval_Point:
3175 pt = new NOMAD::Eval_Point;
3176 pt->set ( *x0s[k] , m );
3177 pt->set_signature ( _p.get_signature() );
3178
3179 _ev_control.add_eval_point ( pt ,
3180 display_degree ,
3181 false ,
3182 NOMAD::Double() ,
3183 NOMAD::Double() ,
3184 NOMAD::Double() ,
3185 NOMAD::Double() );
3186 }
3187
3188 // x0 from a cache file:
3189 // ---------------------
3190 if ( !x0_cache_file.empty() )
3191 {
3192
3193 NOMAD::Cache & cache = _ev_control.get_cache();
3194 const NOMAD::Eval_Point * x;
3195
3196 // another cache file (this file won't be modified):
3197 if ( x0_cache_file != _p.get_cache_file() )
3198 {
3199
3200 NOMAD::Cache x0_cache ( out , ( _p.get_opt_only_sgte() ) ? NOMAD::SGTE : NOMAD::TRUTH );
3201 std::string file_name = _p.get_problem_dir() + x0_cache_file;
3202
3203 if ( !x0_cache.load ( file_name , NULL , display_degree==NOMAD::FULL_DISPLAY ) )
3204 {
3205 err << "could not load (or create) the cache file " << file_name;
3206 throw NOMAD::Exception ( "Mads.cpp" , __LINE__ , err.str() );
3207 }
3208
3209 // we copy all the temporary cache points
3210 // into the list of points to be evaluated:
3211 x = x0_cache.begin();
3212 while ( x )
3213 {
3214
3215 pt = new NOMAD::Eval_Point;
3216 pt->set ( *x , m );
3217
3218 if ( x->get_signature() )
3219 pt->set_signature ( x->get_signature() );
3220 else if ( x->size() == n )
3221 pt->set_signature ( _p.get_signature() );
3222
3223 if ( pt->get_signature() )
3224 _ev_control.add_eval_point ( pt ,
3225 display_degree ,
3226 false ,
3227 NOMAD::Double() ,
3228 NOMAD::Double() ,
3229 NOMAD::Double() ,
3230 NOMAD::Double() );
3231 else
3232 {
3233 if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
3234 out << std::endl << "Warning (" << "Mads.cpp" << ", " << __LINE__
3235 << "): could not use the starting point " << *pt
3236 << " (no signature)" << std::endl << std::endl;
3237 delete pt;
3238 }
3239
3240 x = x0_cache.next();
3241 }
3242
3243 // insertion of this temporary cache in the algorithm's cache:
3244 cache.insert ( x0_cache );
3245 }
3246
3247 // x0 cache file and the algorithm's cache file are the same:
3248 else {
3249
3250 x = cache.begin();
3251 while ( x ) {
3252 pt = &NOMAD::Cache::get_modifiable_point ( *x );
3253
3254 if ( x->get_signature() )
3255 pt->set_signature ( x->get_signature() );
3256 else if ( x->size() == n )
3257 pt->set_signature ( _p.get_signature() );
3258
3259 if ( pt->get_signature() )
3260 _ev_control.add_eval_point ( pt ,
3261 display_degree ,
3262 false ,
3263 NOMAD::Double() ,
3264 NOMAD::Double() ,
3265 NOMAD::Double() ,
3266 NOMAD::Double() );
3267 else {
3268 if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
3269 out << std::endl << "Warning (" << "Mads.cpp" << ", " << __LINE__
3270 << "): could not use the starting point " << *pt
3271 << "(no signature)" << std::endl;
3272 }
3273 x = cache.next();
3274 }
3275 }
3276 }
3277
3278 // display of all starting points:
3279 if ( display_degree == NOMAD::FULL_DISPLAY ) {
3280
3281 const std::set<NOMAD::Priority_Eval_Point> & pts = _ev_control.get_eval_lop();
3282
3283 // one starting point:
3284 if ( pts.size() == 1 ) {
3285 out << std::endl << "x0 eval point: ( ";
3286 pts.begin()->get_point()->Point::display ( out ,
3287 " " ,
3288 2 ,
3289 NOMAD::Point::get_display_limit() );
3290 out << " )" << std::endl;
3291 }
3292
3293 // several starting points:
3294 else
3295 _ev_control.display_eval_lop ( NOMAD::X0_EVAL );
3296 }
3297
3298 NOMAD::success_type success;
3299 const NOMAD::Eval_Point * new_feas_inc = NULL;
3300 const NOMAD::Eval_Point * new_infeas_inc = NULL;
3301
3302 // eval_list_of_points (x0):
3303 // -------------------------
3304 _ev_control.eval_list_of_points ( NOMAD::X0_EVAL ,
3305 _true_barrier ,
3306 _sgte_barrier ,
3307 _pareto_front ,
3308 stop ,
3309 stop_reason ,
3310 new_feas_inc ,
3311 new_infeas_inc ,
3312 success );
3313 if ( !stop &&
3314 ( success == NOMAD::UNSUCCESSFUL ||
3315 (!new_feas_inc && !new_infeas_inc ) ||
3316 ( _p.get_barrier_type() == NOMAD::EB &&
3317 !get_active_barrier().get_best_feasible() ) ) ) {
3318 stop = true;
3319 stop_reason = NOMAD::X0_FAIL;
3320 }
3321
3322
3323 // displays:
3324 display_iteration_end ( stop ,
3325 stop_reason ,
3326 success ,
3327 new_feas_inc ,
3328 new_infeas_inc );
3329
3330 // stop the algorithm if no iterations are allowed:
3331 if ( !stop && _p.get_max_iterations() == 0 )
3332 {
3333 stop = true;
3334 stop_reason = NOMAD::MAX_ITER_REACHED;
3335 }
3336
3337 if ( display_degree == NOMAD::FULL_DISPLAY )
3338 out << std::endl << NOMAD::close_block ( "end of starting point evaluation" );
3339 }
3340
3341 /*---------------------------------------------------------*/
3342 /* display the Pareto front */
3343 /*---------------------------------------------------------*/
display_pareto_front(void) const3344 void NOMAD::Mads::display_pareto_front ( void ) const
3345 {
3346 if ( !_pareto_front )
3347 return;
3348
3349 const std::string & stats_file_name = _p.get_stats_file_name();
3350 const NOMAD::Display & out = _p.out();
3351 NOMAD::dd_type display_degree = out.get_gen_dd();
3352
3353 // loop on the Pareto points:
3354 if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
3355 out << std::endl << NOMAD::open_block ( "Pareto front" ) << std::endl;
3356
3357 const NOMAD::Eval_Point * cur = _pareto_front->begin();
3358 while ( cur )
3359 {
3360
3361 if ( cur->is_eval_ok() && cur->is_feasible ( _p.get_h_min() ) )
3362 {
3363
3364 const std::list<int> & index_obj = _p.get_index_obj();
3365 std::list<int>::const_iterator it , end = index_obj.end();
3366 const NOMAD::Point & bbo = cur->get_bb_outputs();
3367 int i = 0;
3368 NOMAD::Point multi_obj ( static_cast<int>(index_obj.size()) );
3369
3370 for ( it = index_obj.begin() ; it != end ; ++it )
3371 multi_obj[i++] = bbo[*it];
3372
3373 if ( !stats_file_name.empty() )
3374 _ev_control.stats_file ( stats_file_name , cur , true , &multi_obj );
3375
3376 if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY && !_p.get_display_stats().empty() )
3377 _ev_control.display_stats ( false ,
3378 out ,
3379 _p.get_display_stats() ,
3380 cur ,
3381 true ,
3382 &multi_obj );
3383 }
3384 cur = _pareto_front->next();
3385 }
3386
3387 if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
3388 out << NOMAD::close_block();
3389
3390 // other stats:
3391 if ( display_degree == NOMAD::FULL_DISPLAY )
3392 {
3393
3394 out << std::endl << "number of pts : " << _pareto_front->size() << std::endl;
3395
3396 NOMAD::Double delta , surf;
3397 _pareto_front->get_delta_surf ( delta , surf ,
3398 _p.get_multi_f_bounds() ); // f1_min, f1_max,
3399 // f2_min, f2_max
3400 out << "delta_j : " << delta << std::endl
3401 << "surf : ";
3402 if ( surf.is_defined() )
3403 out << 100*surf << "%" << std::endl;
3404 else
3405 out << NOMAD::Double()
3406 << " (define valid MULTI_F_BOUNDS values to access this output)"
3407 << std::endl;
3408 }
3409 else if ( display_degree != NOMAD::NO_DISPLAY && display_degree != NOMAD::MINIMAL_DISPLAY)
3410 out << std::endl << "number of Pareto points: " << _pareto_front->size()
3411 << std::endl;
3412 }
3413
3414 /*---------------------------------------------------------*/
3415 /* MADS display */
3416 /*---------------------------------------------------------*/
display(const NOMAD::Display & out) const3417 void NOMAD::Mads::display ( const NOMAD::Display & out ) const
3418 {
3419 NOMAD::dd_type display_degree = out.get_gen_dd();
3420
3421 if ( !NOMAD::Slave::is_master() )
3422 return;
3423
3424 // 0. no display:
3425 // --------------
3426 if ( display_degree == NOMAD::NO_DISPLAY || display_degree == NOMAD::MINIMAL_DISPLAY)
3427 {
3428
3429 // there may be a pareto front to write as a stats file:
3430 if ( _pareto_front &&
3431 !_pareto_front->empty() &&
3432 !_p.get_stats_file_name().empty() )
3433 display_pareto_front();
3434
3435 return;
3436 }
3437
3438 // incumbents:
3439 const NOMAD::Eval_Point * bf = get_best_feasible();
3440 const NOMAD::Eval_Point * bi = get_best_infeasible();
3441 const NOMAD::Eval_Point *bimv = get_best_infeasible_min_viol();
3442
3443 // save the solution file:
3444 if ( bf )
3445 _ev_control.write_solution_file ( *bf , false);
3446 else if (bimv)
3447 _ev_control.write_solution_file ( *bimv , true );
3448
3449
3450
3451 // 1. detailed display:
3452 // --------------------
3453 if ( display_degree == NOMAD::FULL_DISPLAY )
3454 {
3455
3456 // cache:
3457 out << std::endl
3458 << NOMAD::open_block ( "cache" )
3459 << ( _p.get_opt_only_sgte() ? _ev_control.get_sgte_cache() : _ev_control.get_cache() )
3460 << NOMAD::close_block();
3461
3462 // constraints:
3463 if ( _p.has_constraints() )
3464 out << std::endl
3465 << NOMAD::open_block ( "constraints handling") << std::endl
3466 << get_active_barrier()
3467 << NOMAD::close_block();
3468
3469 // Pareto front:
3470 if ( _pareto_front )
3471 {
3472 if ( _pareto_front->empty() )
3473 out << std::endl << "Pareto front empty" << std::endl;
3474 else
3475 display_pareto_front();
3476 }
3477
3478 // stats:
3479 out << std::endl
3480 << NOMAD::open_block ( "stats" )
3481 << _stats
3482 << NOMAD::close_block();
3483
3484 // model stats:
3485 #ifdef DEBUG
3486 display_model_stats ( out );
3487 #endif
3488
3489 // miscellaneous:
3490 if ( !_pareto_front )
3491 {
3492 out << std::endl
3493 << NOMAD::open_block ( "miscellaneous" )
3494 << "mesh indices : min= ("
3495 << _mesh->get_min_mesh_indices() << " ), max = ("
3496 << _mesh->get_max_mesh_indices() << " ), last= ( "
3497 << _mesh->get_mesh_indices() << " ) " << std::endl;
3498
3499 if ( bimv )
3500 {
3501 out << "best infeasible solution (min. violation): ( ";
3502 bimv->Point::display ( out , " " , -1 , -1 );
3503 out << " ) h=" << bimv->get_h()
3504 << " f=" << bimv->get_f() << std::endl;
3505 }
3506
3507 out << "best feasible solution : ";
3508
3509 if ( bf )
3510 {
3511 out << "( ";
3512 bf->Point::display ( out , " " , -1 , -1 );
3513 out << " ) h=" << bf->get_h()
3514 << " f=" << bf->get_f() << std::endl;
3515 }
3516 else
3517 out << "no feasible solution has been found" << std::endl;
3518
3519
3520 out.close_block();
3521 }
3522 }
3523
3524 // 2. normal display:
3525 // ------------------
3526 else
3527 {
3528
3529 // blackbox evaluations:
3530 out << std::endl
3531 << "blackbox evaluations : " << _stats.get_bb_eval() << std::endl;
3532
3533 // output stats:
3534 if ( _stats.get_stat_sum().is_defined() )
3535 out << "stat sum : " << _stats.get_stat_sum() << std::endl;
3536 if ( _stats.get_stat_avg().is_defined() )
3537 out << "stat avg : " << _stats.get_stat_avg() << std::endl;
3538
3539 // Pareto front (multi-objective optimization):
3540 if ( _pareto_front )
3541 {
3542 out << "number of MADS runs : " << _stats.get_mads_runs() << std::endl;
3543 if ( _pareto_front->empty() )
3544 out << "Pareto front : empty" << std::endl;
3545 else
3546 display_pareto_front();
3547 }
3548
3549 // single-objective optimization (display of best solutions):
3550 else
3551 {
3552
3553 if ( !bf && !bi )
3554 out << "no solution" << std::endl;
3555 else
3556 {
3557 if ( bimv )
3558 {
3559 out << "best infeasible solution (min. violation): ( ";
3560 bimv->Point::display ( out , " " , -1 , -1 );
3561 out << " ) h=" << bimv->get_h()
3562 << " f=" << bimv->get_f() << std::endl;
3563 }
3564
3565 out << "best feasible solution : ";
3566
3567 if ( bf )
3568 {
3569 out << "( ";
3570 bf->Point::display ( out , " " , -1 , -1 );
3571 out << " ) h=" << bf->get_h()
3572 << " f=" << bf->get_f() << std::endl;
3573 }
3574 else
3575 out << "no feasible solution has been found" << std::endl;
3576
3577 }
3578 }
3579 out.close_block();
3580 }
3581 }
3582
3583 /*---------------------------------------------------------*/
3584 /* display model stats */
3585 /*---------------------------------------------------------*/
display_model_stats(const NOMAD::Display & out) const3586 void NOMAD::Mads::display_model_stats ( const NOMAD::Display & out ) const
3587 {
3588 if ( _model_search1 )
3589 out << std::endl << NOMAD::open_block ( "model search #1 stats" )
3590 << *_model_search1 << NOMAD::close_block();
3591 if ( _model_search2 )
3592 out << std::endl << NOMAD::open_block ( "model search #2 stats" )
3593 << *_model_search2 << NOMAD::close_block();
3594 if ( _p.get_model_eval_sort() != NOMAD::NO_MODEL ) {
3595 out << std::endl << NOMAD::open_block ( "model ordering stats" );
3596 _ev_control.display_model_ordering_stats ( out );
3597 out << NOMAD::close_block();
3598 }
3599 }
3600
3601 /*---------------------------------------------------------*/
3602 /* display mesh and poll sizes for a given signature and */
3603 /* the current mesh index (private) */
3604 /*---------------------------------------------------------*/
display_deltas(const NOMAD::Signature & s) const3605 void NOMAD::Mads::display_deltas ( const NOMAD::Signature & s ) const
3606 {
3607
3608 NOMAD::Point delta,Delta;
3609
3610 _mesh->get_delta(delta);
3611 _mesh->get_Delta(Delta);
3612 if (delta.is_defined() && Delta.is_defined())
3613 _p.out() << "mesh size : ( " << delta << " )" << std::endl
3614 << "poll size : ( " << Delta << " )" << std::endl
3615 << "mesh indices : ( " << _mesh->get_mesh_indices() << " )" << std::endl;
3616
3617 }
3618
3619 /*-------------------------------------------------------*/
3620 /* displays at the beginning of an iteration (private) */
3621 /*-------------------------------------------------------*/
display_iteration_begin(void) const3622 void NOMAD::Mads::display_iteration_begin ( void ) const
3623 {
3624 const NOMAD::Display & out = _p.out();
3625 if ( out.get_iter_dd() != NOMAD::FULL_DISPLAY )
3626 return;
3627
3628 // incumbents:
3629 const NOMAD::Eval_Point * bf = get_best_feasible();
3630 const NOMAD::Eval_Point * bi = get_best_infeasible();
3631 const NOMAD::Signature * s1 = NULL;
3632
3633 out << "blackbox evaluations : " << _stats.get_bb_eval() << std::endl;
3634 #ifdef USE_MPI
3635 if ( _p.get_asynchronous() )
3636 out << "eval. in progress : " << _ev_control.get_nb_eval_in_progress()
3637 << std::endl;
3638 #endif
3639 out << "best feas. solution : ";
3640 if ( bf ) {
3641 out << "( ";
3642 bf->Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
3643 out << " ) h=" << bf->get_h()
3644 << " f=" << bf->get_f()
3645 << std::endl;
3646 }
3647 else
3648 out << "none" << std::endl;
3649 out << "best infeas. solution: ";
3650 if ( bi ) {
3651 out << "( ";
3652 bi->Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
3653 out << " ) h=" << bi->get_h()
3654 << " f=" << bi->get_f()
3655 << std::endl;
3656 }
3657 else
3658 out << "none" << std::endl;
3659
3660 out << "poll center : ";
3661 const NOMAD::Eval_Point * poll_center = get_active_barrier().get_poll_center();
3662 if ( poll_center ) {
3663 out << "( ";
3664 poll_center->Point::display ( out , " " , 2 , NOMAD::Point::get_display_limit() );
3665 out << " )" << std::endl;
3666
3667 s1 = poll_center->get_signature();
3668 if (s1)
3669 display_deltas ( *s1 );
3670 }
3671 else
3672 out << "none" << std::endl;
3673
3674 const NOMAD::Eval_Point * sec_poll_center
3675 = get_active_barrier().get_sec_poll_center();
3676
3677 if ( sec_poll_center ) {
3678 out << "sec. poll center : ( ";
3679 sec_poll_center->Point::display ( out ,
3680 " " ,
3681 2 ,
3682 NOMAD::Point::get_display_limit() );
3683 out << " )" << std::endl;
3684 const NOMAD::Signature * s2 = sec_poll_center->get_signature();
3685 if ( s2 && (!s1 || s1 != s2) )
3686 display_deltas ( *s2 );
3687 }
3688 out << "h_max : "
3689 << get_active_barrier().get_h_max() << std::endl;
3690 }
3691
3692 /*---------------------------------------------------------*/
3693 /* displays at the end of an iteration (private) */
3694 /*---------------------------------------------------------*/
display_iteration_end(bool stop,NOMAD::stop_type stop_reason,NOMAD::success_type success,const NOMAD::Eval_Point * new_feas_inc,const NOMAD::Eval_Point * new_infeas_inc) const3695 void NOMAD::Mads::display_iteration_end
3696 ( bool stop ,
3697 NOMAD::stop_type stop_reason ,
3698 NOMAD::success_type success ,
3699 const NOMAD::Eval_Point * new_feas_inc ,
3700 const NOMAD::Eval_Point * new_infeas_inc ) const
3701 {
3702 const NOMAD::Display & out = _p.out();
3703
3704 if ( out.get_iter_dd() != NOMAD::FULL_DISPLAY )
3705 return;
3706
3707 out << std::endl
3708 << "terminate MADS : ";
3709 out.display_yes_or_no ( stop );
3710 out << std::endl;
3711 if ( stop ) {
3712 out << "termination cause : " << stop_reason;
3713 if ( stop_reason==NOMAD::X0_FAIL &&
3714 !_flag_p1_active &&
3715 _p.has_EB_constraints() )
3716 out << " (phase one will be performed)";
3717 out << std::endl;
3718 }
3719 out << "iteration status : " << success << std::endl;
3720 out << "new feas. incumbent : ";
3721 if ( new_feas_inc )
3722 out << *new_feas_inc;
3723 else
3724 out << "none" << std::endl;
3725 out << "new infeas. incumbent: ";
3726 if ( new_infeas_inc )
3727 out << *new_infeas_inc;
3728 else
3729 out << "none" << std::endl;
3730 }
3731