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