1 #include "Master_Slaves.hpp"
2 using namespace std;
3 using namespace NOMAD;
4 
5 /*--------------------------*/
6 /*  tags and signal values  */
7 /*--------------------------*/
8 const int  Master_Slaves::TAG_SIGNAL       = 100;
9 const int  Master_Slaves::TAG_I1           = 101;
10 const int  Master_Slaves::TAG_R1           = 102;
11 const int  Master_Slaves::TAG_CSTOP        = 103;
12 const int  Master_Slaves::TAG_D1           = 105;
13 const int  Master_Slaves::TAG_I2           = 106;
14 char       Master_Slaves::STOP_SIGNAL      = 'S';
15 char       Master_Slaves::OPTI_RES_SIGNAL  = 'O';
16 char       Master_Slaves::OPTI_DATA_SIGNAL = 'D';
17 
18 /*--------------------------------*/
19 /*  start the master (process 0)  */
20 /*--------------------------------*/
start(void) const21 void Master_Slaves::start ( void ) const {
22 
23     if ( _rank != 0 )
24         return;
25 
26     MPI_Status status;
27     int        source;
28     char       signal;
29     int        n                   = _p.get_dimension();
30     int        nb_stops            = 0;
31     int        pollster_mesh_index = 0;
32     bool       stop_algo           = false;
33     double   * best_feasible       = NULL;
34 
35     // the first best infeasible point is initialized with x0:
36     double      * best_infeasible = new double [n+2];
37     const Point * x0              = (_p.get_x0s())[0];
38     for ( int i = 0 ; i < n ; ++i )
39         best_infeasible[i] = (*x0)[i].value();
40     best_infeasible[n  ] = INF;
41     best_infeasible[n+1] = INF;
42 
43     /*-------------*/
44     /*  main loop  */
45     /*-------------*/
46     while ( nb_stops != _np-2 ) {
47 
48         MPI_Recv ( &signal , 1 , MPI_CHAR , MPI_ANY_SOURCE ,
49                   Master_Slaves::TAG_SIGNAL , MPI_COMM_WORLD , &status );
50 
51         source = status.MPI_SOURCE;
52 
53         // stop signal:
54         // ------------
55         if ( signal == Master_Slaves::STOP_SIGNAL ) {
56             if ( _debug ) {
57                 _p.out() << "MASTER: STOP SIGNAL FROM RANK " << source;
58                 if ( source == 1 )
59                     _p.out() << " (POLLSTER)";
60                 _p.out() << endl;
61             }
62             ++nb_stops;
63         }
64 
65         // optimization data signal:
66         // -------------------------
67         else if ( signal == Master_Slaves::OPTI_DATA_SIGNAL ) {
68             if ( _debug ) {
69                 _p.out() << "MASTER: receive optimization data request from slave "
70                 << source;
71                 if ( source == 1 )
72                     _p.out() << " (POLLSTER)";
73                 _p.out() << endl;
74             }
75 
76             send_optimization_data ( pollster_mesh_index ,
77                                     stop_algo           ,
78                                     best_feasible       ,
79                                     best_infeasible     ,
80                                     source                );
81         }
82 
83         // optimization result signal:
84         // ---------------------------
85         else if ( signal == Master_Slaves::OPTI_RES_SIGNAL ) {
86             if ( _debug ) {
87                 _p.out() << "MASTER: receive optimization result from slave "
88                 << source;
89                 if ( source == 1 )
90                     _p.out() << " (POLLSTER)";
91                 _p.out() << endl;
92             }
93 
94             // pollster:
95             if ( source == 1 )
96                 receive_optimization_result ( pollster_mesh_index ,
97                                              stop_algo           ,
98                                              best_feasible       ,
99                                              best_infeasible     ,
100                                              source                );
101 
102             // other slaves:
103             else {
104                 int  tmp1;
105                 bool tmp2;
106                 receive_optimization_result ( tmp1            ,
107                                              tmp2            ,
108                                              best_feasible   ,
109                                              best_infeasible ,
110                                              source            );
111             }
112         }
113     }
114 
115     if ( best_feasible )
116         delete [] best_feasible;
117     if ( best_infeasible )
118         delete [] best_infeasible;
119 }
120 
121 /*------------------------------------------*/
122 /*  stop the master (processes 1 to _np-2)  */
123 /*------------------------------------------*/
stop(void) const124 void Master_Slaves::stop ( void ) const {
125     if ( _rank == 0 || _rank == _np-1 )
126         return;
127 
128     MPI_Send ( &Master_Slaves::STOP_SIGNAL , 1 , MPI_CHAR ,
129               0 , Master_Slaves::TAG_SIGNAL , MPI_COMM_WORLD );
130 }
131 
132 /*----------------------------------------*/
133 /*                MADS run                */
134 /*----------------------------------------*/
mads_run(Cache & cache)135 void Master_Slaves::mads_run ( Cache & cache ) {
136 
137     const Eval_Point * best_feasible   = NULL;
138     const Eval_Point * best_infeasible = NULL;
139     Double             old_f           = INF;
140     bool               stop_algo       = false;
141     int                run_index       = 0;
142     int                mesh_index      = 0;
143     double             default_eps     = Double::get_epsilon();
144     int                n               = _p.get_dimension();
145     int              * free_vars       = new int [_ns];
146     Point              x0 ( n ) , delta_0 , delta_min;
147 
148     /*---------------------*/
149     /*      main loop      */
150     /*---------------------*/
151     while ( !stop_algo ) {
152 
153         best_feasible   = NULL;
154         best_infeasible = NULL;
155 
156         // Seed:
157         _p.set_SEED ( 99 * _rank + 20 * run_index );
158 
159         // first run:
160         if ( run_index == 0 ) {
161 
162             // max number of evaluations for regular slaves:
163             if ( _rank != 1 )
164                 _p.set_MAX_BB_EVAL ( _bbe );
165 
166             // display:
167             // p.set_DISPLAY_STATS ( "process #" + itos(_rank) + " BBE OBJ" );
168             // p.set_DISPLAY_DEGREE ( FULL_DISPLAY );
169             _p.set_DISPLAY_DEGREE ( NO_DISPLAY );
170         }
171 
172         // force the parameters check:
173         _p.force_check_flag();
174 
175         /*------------------*/
176         /*  pollster slave  */
177         /*------------------*/
178         if ( _rank == 1 ) {
179 
180             stop_type stop_reason = UNKNOWN_STOP_REASON;
181 
182             _p.check();   // must do check to get a valid signature
183             _p.get_signature()->get_mesh()->set_mesh_indices( NOMAD::Point( n,mesh_index ) );
184             delta_0=_p.get_signature()->get_mesh()->get_delta ( );
185 
186 
187 
188             // we set a very small epsilon in order to accept
189             // very small initial mesh sizes:
190             Double::set_epsilon ( 1e-16 );
191 
192             if ( !check_delta ( delta_0 ) )
193                 stop_algo = true;
194 
195             else {
196 
197                 // first run:
198                 if ( run_index == 0 ) {
199 
200                     // directions:
201                     {
202                         bool use_orthomads = _p.has_orthomads_directions();
203                         _p.reset_directions   ( );
204                         _p.set_DIRECTION_TYPE ( (use_orthomads) ? ORTHO_1 : LT_1 );
205                     }
206 
207                     // cache search:
208                     _p.set_CACHE_SEARCH               ( true  );
209                     _p.set_OPPORTUNISTIC_CACHE_SEARCH ( false );
210                 }
211 
212                 // other runs:
213                 else {
214 
215                     // stop_algo may be set to 'false' here:
216                     receive_optimization_data ( stop_algo , x0 , old_f );
217 
218                     // starting point:
219                     _p.reset_X0();
220                     _p.set_X0 ( x0 );
221                 }
222 
223                 if ( !stop_algo ) {
224 
225                     // check the parameters:
226                     _p.check();
227 
228                     _p.get_signature()->get_mesh()->set_min_mesh_sizes( delta_0 );
229 
230                     if ( mesh_index <= 0 )
231                         _p.get_signature()->get_mesh()->set_limit_mesh_index ( mesh_index );
232                     else
233                         _p.get_signature()->get_mesh()->set_limit_mesh_index ( 0 );
234 
235 
236                     Double::set_epsilon ( default_eps );
237 
238                     Mads mads ( _p , &_ev , NULL , &cache , NULL );
239                     stop_reason     = mads.run();
240                     best_feasible   = mads.get_best_feasible();
241                     best_infeasible = mads.get_best_infeasible();
242 
243                     bool success = false;
244 
245                     if ( best_feasible ) {
246 
247                         success = (best_feasible->get_f() < old_f);
248 
249                         if ( _debug )
250                             _p.out() << "POLLSTER: ELL="
251                             << mesh_index << " BBE="
252                             << mads.get_stats().get_bb_eval()
253                             << " OLD_F=" << old_f << " NEW_F="
254                             << best_feasible->get_f()
255                             << " SUCCESS=" << success << endl;
256                     }
257 
258                     // pollster mesh update:
259                     if ( success )
260                         ++mesh_index;
261                     else
262                         --mesh_index;
263 
264                 }
265             }
266 
267             send_optimization_result ( mesh_index      ,
268                                       stop_algo       ,
269                                       best_feasible   ,
270                                       best_infeasible ,
271                                       stop_reason       );
272         }
273 
274         /*------------------*/
275         /*  regular slaves  */
276         /*------------------*/
277         else {
278 
279             int i , j , pollster_mesh_index;
280 
281             receive_optimization_data ( stop_algo           ,
282                                        x0                  ,
283                                        old_f               ,
284                                        pollster_mesh_index ,
285                                        free_vars             );
286 
287             if ( _debug ) {
288                 _p.out() << "SLAVE #" << _rank
289                 << ": OPTIM. DATA: [STOP=" << stop_algo
290                 << "] [POLLSTER_MESH_INDEX=" << pollster_mesh_index
291                 << "] [X0=" << x0 << " ] [f(X0)="
292                 << old_f << "] [FREE VARS= ";
293                 for ( i = 0 ; i < _ns ; ++i )
294                     _p.out() << free_vars[i] << " ";
295                 _p.out() << " ]" << endl;
296             }
297 
298             if ( !stop_algo ) {
299 
300                 // starting point:
301                 _p.reset_X0();
302                 _p.set_X0 ( x0 );
303 
304                 // mesh of the regular slave:
305                 int ell_0 = 0;
306                 if ( pollster_mesh_index > ell_0 )
307                     ell_0 = pollster_mesh_index;
308 
309                 _p.check();  // Must do check to access signature
310                 _p.get_signature()->get_mesh()->set_mesh_indices( NOMAD::Point( n,ell_0 ) );
311                 delta_0=_p.get_signature()->get_mesh()->get_delta();
312 
313                 _p.get_signature()->get_mesh()->set_mesh_indices( NOMAD::Point( n ,pollster_mesh_index ) );
314                 delta_min=_p.get_signature()->get_mesh()->get_delta();
315 
316 
317 
318                 Double::set_epsilon ( 1e-16 );
319                 if ( !check_delta ( delta_0 ) || !check_delta ( delta_min ) )
320                     stop_algo = true;
321 
322                 else {
323 
324                     // free variables:
325                     {
326                         _p.reset_fixed_variables();
327                         bool fix_var;
328                         for ( i = 0 ; i < n ; ++i ) {
329                             fix_var = true;
330                             for ( j = 0 ; j < _ns ; ++j )
331                                 if ( free_vars[j] == i ) {
332                                     fix_var = false;
333                                     break;
334                                 }
335                             if ( fix_var )
336                                 _p.set_FIXED_VARIABLE ( i );
337                         }
338                     }
339 
340                     // check the parameters:
341                     _p.check();
342 
343                     // modify mesh termination criterions
344                     _p.get_signature()->get_mesh()->set_mesh_indices( NOMAD::Point( n,ell_0 ) );
345 
346                     if ( pollster_mesh_index <=0 )
347                         _p.get_signature()->get_mesh()->set_limit_mesh_index( pollster_mesh_index );
348                     else
349                         _p.get_signature()->get_mesh()->set_limit_mesh_index( 0 );
350 
351                     _p.get_signature()->get_mesh()->set_min_mesh_sizes( delta_min );
352                     _p.get_signature()->get_mesh()->set_delta_0 ( delta_0 );
353 
354 
355 
356                     Double::set_epsilon ( default_eps );
357 
358                     // MADS run:
359                     Mads mads ( _p , &_ev , NULL , &cache , NULL );
360                     mads.run();
361                     best_feasible   = mads.get_best_feasible();
362                     best_infeasible = mads.get_best_infeasible();
363 
364                     if ( _debug && best_feasible ) {
365                         _p.out() << "RANK #" << _rank << ": POLLSTER_ELL="
366                         << pollster_mesh_index << " VARS = [";
367                         for ( i = 0 ; i < _ns ; ++i )
368                             _p.out() << free_vars[i] << " ";
369                         _p.out() << " ] BBE=" << mads.get_stats().get_bb_eval()
370                         << " OLD_F=" << old_f << " NEW_F="
371                         << best_feasible->get_f()
372                         << " SUCCESS="
373                         << (best_feasible->get_f() < old_f)
374                         << endl;
375                     }
376                 }
377             }
378 
379             {
380                 int       tmp1 = -1;
381                 bool      tmp2 = false;
382                 stop_type tmp3 = UNKNOWN_STOP_REASON;
383                 send_optimization_result ( tmp1            ,
384                                           tmp2            ,
385                                           best_feasible   ,
386                                           best_infeasible ,
387                                           tmp3              );
388             }
389         }
390 
391         // loop increment:
392         ++run_index;
393     }
394 
395     delete [] free_vars;
396 }
397 
398 /*----------------------------------------------------*/
399 /*  receive an optimization result from the pollster  */
400 /*  POLLSTER --> MASTER                               */
401 /*----------------------------------------------------*/
receive_optimization_result(int & pollster_mesh_index,bool & stop_algo,double * & best_feasible,double * & best_infeasible,int source) const402 void Master_Slaves::receive_optimization_result
403 ( int     & pollster_mesh_index ,
404  bool    & stop_algo           ,
405  double *& best_feasible       ,
406  double *& best_infeasible     ,
407  int       source                ) const {
408 
409     int        itab[5];
410     MPI_Status status;
411 
412     MPI_Recv ( itab , 5 , MPI_INT , source ,
413               Master_Slaves::TAG_I1 , MPI_COMM_WORLD , &status );
414 
415     pollster_mesh_index = itab[0];
416 
417     // stop the algorithm ?
418     stop_algo = ( itab[4] == 1 );
419 
420     if ( !stop_algo ) {
421 
422         stop_type stop_reason = static_cast<stop_type>(itab[1]);
423 
424         switch ( stop_reason ) {
425             case ERROR:
426             case UNKNOWN_STOP_REASON:
427             case CTRL_C:
428             case MESH_PREC_REACHED:
429             case X0_FAIL:
430             case P1_FAIL:
431             case L_MAX_REACHED:
432             case L_LIMITS_REACHED:
433             case MAX_TIME_REACHED:
434             case MAX_BB_EVAL_REACHED:
435             case MAX_SGTE_EVAL_REACHED:
436             case MAX_EVAL_REACHED:
437             case MAX_SIM_BB_EVAL_REACHED:
438             case MAX_ITER_REACHED:
439             case FEAS_REACHED:
440             case F_TARGET_REACHED:
441             case STAT_SUM_TARGET_REACHED:
442             case L_CURVE_TARGET_REACHED:
443             case MULTI_MAX_BB_REACHED:
444             case MULTI_NB_MADS_RUNS_REACHED:
445             case MULTI_STAGNATION:
446             case MULTI_NO_PARETO_PTS:
447             case MAX_CACHE_MEMORY_REACHED:
448                 stop_algo = true;
449             default:
450                 stop_algo = false;
451         }
452     }
453 
454     int i , nb_pts = 0;
455     if ( itab[2] == 1 )
456         ++nb_pts;
457     if ( itab[3] == 1 )
458         ++nb_pts;
459 
460     // itab[2] == 1 --> bf != NULL
461     // itab[3] == 1 --> bi != NULL
462 
463     if ( nb_pts > 0 ) {
464 
465         int      n    = _p.get_dimension();
466         double * rtab = new double [(n+2)*nb_pts];
467 
468         MPI_Recv ( rtab , (n+2)*nb_pts , MPI_DOUBLE , source ,
469                   Master_Slaves::TAG_R1 , MPI_COMM_WORLD , &status );
470 
471         if ( nb_pts == 2 ) {
472 
473             // best feasible and infeasible updates:
474             bool update = false;
475 
476             if ( best_feasible ) {
477                 Double old_f = best_feasible[n+1];
478                 Double new_f = rtab         [n+1];
479                 if ( new_f < old_f )
480                     update = true;
481             }
482             else {
483                 best_feasible = new double[n+2];
484                 update = true;
485             }
486 
487             if ( update ) {
488                 for ( i = 0 ; i < n ; ++i )
489                     best_feasible[i] = rtab[i];
490                 best_feasible[n  ] = rtab[n];
491                 best_feasible[n+1] = rtab[n+1];
492             }
493 
494             update = false;
495 
496             if ( best_infeasible ) {
497 
498                 Double old_h = best_infeasible[n];
499                 Double new_h = rtab           [2*n+2];
500                 if ( new_h < old_h )
501                     update = true;
502             }
503             else {
504                 best_infeasible = new double[n+2];
505                 update = true;
506             }
507 
508             if ( update ) {
509                 int cur = n+2;
510                 for ( i = 0 ; i < n ; ++i )
511                     best_infeasible[i] = rtab[cur++];
512                 best_infeasible[n  ] = rtab[cur++];
513                 best_infeasible[n+1] = rtab[cur];
514             }
515             delete [] rtab;
516         }
517         else {
518 
519             // best feasible update:
520             if ( itab[2] == 1 ) {
521                 if ( best_feasible ) {
522                     Double old_f = best_feasible[n+1];
523                     Double new_f = rtab         [n+1];
524                     if ( new_f < old_f ) {
525                         delete [] best_feasible;
526                         best_feasible = rtab;
527                     }
528                     else
529                         delete [] rtab;
530                 }
531                 else
532                     best_feasible = rtab;
533             }
534 
535             // best infeasible update:
536             else {
537                 if ( best_infeasible ) {
538                     Double old_h = best_infeasible[n];
539                     Double new_h = rtab           [n];
540                     if ( new_h < old_h ) {
541                         delete [] best_infeasible;
542                         best_infeasible = rtab;
543                     }
544                     else
545                         delete [] rtab;
546                 }
547                 else
548                     best_infeasible = rtab;
549             }
550         }
551     }
552 }
553 
554 /*---------------------------------------------*/
555 /*  send an optimization result to the master  */
556 /*  POLLSTER --> MASTER                        */
557 /*---------------------------------------------*/
send_optimization_result(int pollster_mesh_index,bool stop_algo,const Eval_Point * bf,const Eval_Point * bi,stop_type st) const558 void Master_Slaves::send_optimization_result
559 ( int                pollster_mesh_index ,
560  bool               stop_algo           ,
561  const Eval_Point * bf                  ,
562  const Eval_Point * bi                  ,
563  stop_type          st                    ) const {
564 
565     // send a signal to the master:
566     MPI_Send ( &Master_Slaves::OPTI_RES_SIGNAL , 1 , MPI_CHAR ,
567               0 , Master_Slaves::TAG_SIGNAL , MPI_COMM_WORLD );
568 
569     // send the data:
570     int itab[5];
571 
572     itab[0] = pollster_mesh_index;
573     itab[1] = static_cast<int>(st);
574 
575     int nb_pts = 0;
576     if ( bf ) {
577         ++nb_pts;
578         itab[2] = 1;
579     }
580     else
581         itab[2] = 0;
582 
583     if ( bi ) {
584         ++nb_pts;
585         itab[3] = 1;
586     }
587     else
588         itab[3] = 0;
589 
590     itab[4] = (stop_algo) ? 1 : 0;
591 
592     MPI_Send ( itab , 5 , MPI_INT , 0 ,
593               Master_Slaves::TAG_I1 , MPI_COMM_WORLD );
594 
595     if ( nb_pts > 0 ) {
596 
597         int      n    = _p.get_dimension();
598         double * rtab = new double [(n+2)*nb_pts];
599 
600         int i , cur = 0;
601         if ( bf ) {
602             for ( i = 0 ; i < n ; ++i )
603                 rtab[cur++] = (*bf)[i].value();
604             rtab[cur++] = bf->get_h().value();
605             rtab[cur++] = bf->get_f().value();
606         }
607 
608         if ( bi ) {
609             for ( i = 0 ; i < n ; ++i )
610                 rtab[cur++] = (*bi)[i].value();
611             rtab[cur++] = bi->get_h().value();
612             rtab[cur  ] = bi->get_f().value();
613         }
614 
615         MPI_Send ( rtab , cur , MPI_DOUBLE , 0 ,
616                   Master_Slaves::TAG_R1 , MPI_COMM_WORLD );
617 
618         delete [] rtab;
619     }
620 }
621 
622 /*---------------------------------------------*/
623 /*  receive optimization data from the master  */
624 /*  MASTER --> REGULAR SLAVE                   */
625 /*---------------------------------------------*/
receive_optimization_data(bool & stop_algo,Point & x0,Double & fx0,int & pollster_mesh_index,int * free_vars) const626 void Master_Slaves::receive_optimization_data
627 ( bool   & stop_algo           ,
628  Point  & x0                  ,
629  Double & fx0                 ,
630  int    & pollster_mesh_index ,
631  int    * free_vars             ) const {
632 
633     // step 1/2: receive common pollster data:
634     receive_optimization_data ( stop_algo , x0 , fx0 );
635 
636     int i;
637 
638     // step 2/2: receive additional data for regular slaves:
639     if ( !stop_algo ) {
640 
641         int      * itab = new int [_ns+1];
642         MPI_Status status;
643 
644         MPI_Recv ( itab , _ns+1 , MPI_INT , 0 ,
645                   Master_Slaves::TAG_I2 , MPI_COMM_WORLD , &status );
646 
647         for ( i = 0 ; i < _ns ; ++i )
648             free_vars[i] = itab[i];
649 
650         pollster_mesh_index = itab[_ns];
651 
652         delete [] itab;
653     }
654     else {
655         pollster_mesh_index = 1;
656         for ( i = 0 ; i < _ns ; ++i )
657             free_vars[i] = -1;
658     }
659 }
660 
661 /*---------------------------------------------*/
662 /*  receive optimization data from the master  */
663 /*  MASTER --> POLLSTER                        */
664 /*---------------------------------------------*/
receive_optimization_data(bool & stop_algo,Point & x0,Double & fx0) const665 void Master_Slaves::receive_optimization_data ( bool   & stop_algo ,
666                                                Point  & x0        ,
667                                                Double & fx0         ) const {
668     char        c_stop;
669     MPI_Status  status;
670     MPI_Request req    = MPI_REQUEST_NULL;
671     int         i , n  = _p.get_dimension();
672 
673     // send a request for c_stop:
674     MPI_Irecv ( &c_stop , 1 , MPI_CHAR , 0 ,
675                Master_Slaves::TAG_CSTOP , MPI_COMM_WORLD , &req );
676 
677     // send a signal to the master:
678     MPI_Send ( &Master_Slaves::OPTI_DATA_SIGNAL , 1 , MPI_CHAR ,
679               0 , Master_Slaves::TAG_SIGNAL , MPI_COMM_WORLD );
680 
681     MPI_Wait ( &req , &status );
682 
683     // stop:
684     if ( c_stop == '1' ) {
685         stop_algo = true;
686         x0.reset();
687     }
688 
689     // continue:
690     else {
691 
692         stop_algo     = false;
693         double * rtab = new double [n+2];
694 
695         MPI_Recv ( rtab , n+2 , MPI_DOUBLE , 0 ,
696                   Master_Slaves::TAG_D1 , MPI_COMM_WORLD , &status );
697 
698         for ( i = 0 ; i < n ; ++i )
699             x0[i] = rtab[i];
700 
701         Double h = rtab[n];
702         fx0 = ( h <= _p.get_h_min() ) ? rtab[n+1] : INF;
703 
704         // get the best feasible point from the cache server:
705         {
706             char pt_flag;
707             int  npm1 = _np-1;
708             MPI_Irecv ( &pt_flag , 1 , MPI_CHAR , npm1 ,
709                        Cache_Server::TAG_BF , MPI_COMM_WORLD , &req );
710 
711             MPI_Send ( &Cache_Server::BF_SIGNAL , 1 , MPI_CHAR ,
712                       npm1 , Cache_Server::TAG_SIGNAL , MPI_COMM_WORLD );
713 
714             MPI_Wait ( &req , &status );
715 
716             if ( pt_flag == '1' ) {
717 
718                 MPI_Recv ( rtab , n+2 , MPI_DOUBLE , npm1 ,
719                           Cache_Server::TAG_X7 , MPI_COMM_WORLD , &status );
720 
721                 for ( i = 0 ; i < n ; ++i )
722                     x0[i] = rtab[i];
723 
724                 Double h = rtab[n];
725                 fx0 = ( h <= _p.get_h_min() ) ? rtab[n+1] : INF;
726 
727             }
728         }
729         delete [] rtab;
730 
731         // check the bounds:
732         const Point & lb = _p.get_lb();
733         const Point & ub = _p.get_ub();
734 
735         for ( i = 0 ; i < n ; ++i ) {
736             if ( lb[i].is_defined() && x0[i].value() < lb[i].value() )
737                 x0[i] = lb[i];
738             if ( ub[i].is_defined() && x0[i].value() > ub[i].value() )
739                 x0[i] = ub[i];
740         }
741     }
742 }
743 
744 /*-----------------------------------------------------*/
745 /*  send optimization data from the master to a slave  */
746 /*  MASTER --> POLLSTER or MASTER --> SLAVE            */
747 /*-----------------------------------------------------*/
send_optimization_data(int pollster_mesh_index,bool stop_algo,const double * best_feasible,const double * best_infeasible,int source) const748 void Master_Slaves::send_optimization_data
749 ( int            pollster_mesh_index ,
750  bool           stop_algo           ,
751  const double * best_feasible       ,
752  const double * best_infeasible     ,
753  int            source                ) const {
754 
755     char c_stop = (stop_algo) ? '1' : '0';
756 
757     MPI_Rsend ( &c_stop , 1 , MPI_CHAR , source ,
758                Master_Slaves::TAG_CSTOP , MPI_COMM_WORLD );
759 
760     // continue:
761     if ( !stop_algo ) {
762 
763         int n = _p.get_dimension();
764 
765         // data for pollster and regular slaves:
766         if ( best_feasible )
767             MPI_Send ( const_cast<double*>(best_feasible) , n+2 , MPI_DOUBLE ,
768                       source , Master_Slaves::TAG_D1 , MPI_COMM_WORLD );
769         else
770             MPI_Send ( const_cast<double*>(best_infeasible) , n+2 , MPI_DOUBLE ,
771                       source , Master_Slaves::TAG_D1 , MPI_COMM_WORLD );
772 
773         // additional data for regular slaves:
774         if ( source != 1 ) {
775 
776             int * itab = new int [_ns+1];
777 
778             // choose the free varables:
779             {
780                 Random_Pickup rp ( n );
781 
782                 for ( int i = 0 ; i < _ns ; ++i )
783                     itab[i] = rp.pickup(); // index of the ith free variable
784             }
785 
786             itab[_ns] = pollster_mesh_index;
787 
788             MPI_Send ( itab , _ns+1 , MPI_INT , source ,
789                       Master_Slaves::TAG_I2 , MPI_COMM_WORLD );
790 
791             delete [] itab;
792         }
793     }
794 }
795 
796 /*-----------------------------------------------*/
797 /*        check the initial mesh size values     */
798 /*-----------------------------------------------*/
check_delta(const Point & delta)799 bool Master_Slaves::check_delta ( const Point & delta ) {
800     int n = delta.size();
801     for ( int i = 0 ; i < n ; ++i )
802         if ( delta[i].value() < Double::get_epsilon() ||
803             delta[i].value() <= 0.0 )
804             return false;
805     return true;
806 }
807 
808