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                     Double::set_epsilon ( default_eps );
236 
237                     Mads mads ( _p , NULL , NULL , &cache , NULL );
238                     stop_reason     = mads.run();
239                     best_feasible   = mads.get_best_feasible();
240                     best_infeasible = mads.get_best_infeasible();
241 
242                     bool success = false;
243 
244                     if ( best_feasible ) {
245 
246                         success = (best_feasible->get_f() < old_f);
247 
248                         if ( _debug )
249                             _p.out() << "POLLSTER: ELL="
250                             << mesh_index << " BBE="
251                             << mads.get_stats().get_bb_eval()
252                             << " OLD_F=" << old_f << " NEW_F="
253                             << best_feasible->get_f()
254                             << " SUCCESS=" << success << endl;
255                     }
256 
257                     // pollster mesh update:
258                     if ( success )
259                             ++mesh_index;
260                         else
261                             --mesh_index;
262 
263                 }
264             }
265 
266             send_optimization_result ( mesh_index      ,
267                                       stop_algo       ,
268                                       best_feasible   ,
269                                       best_infeasible ,
270                                       stop_reason       );
271         }
272 
273         /*------------------*/
274         /*  regular slaves  */
275         /*------------------*/
276         else {
277 
278             int i , j , pollster_mesh_index;
279 
280             receive_optimization_data ( stop_algo           ,
281                                        x0                  ,
282                                        old_f               ,
283                                        pollster_mesh_index ,
284                                        free_vars             );
285 
286             if ( _debug ) {
287                 _p.out() << "SLAVE #" << _rank
288                 << ": OPTIM. DATA: [STOP=" << stop_algo
289                 << "] [POLLSTER_MESH_INDEX=" << pollster_mesh_index
290                 << "] [X0=" << x0 << " ] [f(X0)="
291                 << old_f << "] [FREE VARS= ";
292                 for ( i = 0 ; i < _ns ; ++i )
293                     _p.out() << free_vars[i] << " ";
294                 _p.out() << " ]" << endl;
295             }
296 
297             if ( !stop_algo ) {
298 
299                 // starting point:
300                 _p.reset_X0();
301                 _p.set_X0 ( x0 );
302 
303                 // mesh of the regular slave:
304                 int ell_0 = 0;
305                 if ( pollster_mesh_index > ell_0 )
306                     ell_0 = pollster_mesh_index;
307 
308                 _p.check();  // Must do check to access signature
309                 _p.get_signature()->get_mesh()->set_mesh_indices( NOMAD::Point( n,ell_0 ) );
310                 delta_0=_p.get_signature()->get_mesh()->get_delta();
311 
312                 _p.get_signature()->get_mesh()->set_mesh_indices( NOMAD::Point( n ,pollster_mesh_index ) );
313                 delta_min=_p.get_signature()->get_mesh()->get_delta();
314 
315 
316 
317                 Double::set_epsilon ( 1e-16 );
318                 if ( !check_delta ( delta_0 ) || !check_delta ( delta_min ) )
319                     stop_algo = true;
320 
321                 else {
322 
323 
324 
325                     // free variables:
326                     {
327                         _p.reset_fixed_variables();
328                         bool fix_var;
329                         for ( i = 0 ; i < n ; ++i ) {
330                             fix_var = true;
331                             for ( j = 0 ; j < _ns ; ++j )
332                                 if ( free_vars[j] == i ) {
333                                     fix_var = false;
334                                     break;
335                                 }
336                             if ( fix_var )
337                                 _p.set_FIXED_VARIABLE ( i );
338                         }
339                     }
340 
341                     // check the parameters:
342                     _p.check();
343 
344                     // modify mesh termination criterions
345                     _p.get_signature()->get_mesh()->set_mesh_indices( NOMAD::Point( n,ell_0 ) );
346 
347                     if ( pollster_mesh_index <=0 )
348                         _p.get_signature()->get_mesh()->set_limit_mesh_index( pollster_mesh_index );
349                     else
350                         _p.get_signature()->get_mesh()->set_limit_mesh_index( 0 );
351 
352                     _p.get_signature()->get_mesh()->set_min_mesh_sizes( delta_min );
353                     _p.get_signature()->get_mesh()->set_delta_0 ( delta_0 );
354 
355 
356 
357                     Double::set_epsilon ( default_eps );
358 
359                     // MADS run:
360                     Mads mads ( _p , NULL , NULL , &cache , NULL );
361                     mads.run();
362                     best_feasible   = mads.get_best_feasible();
363                     best_infeasible = mads.get_best_infeasible();
364 
365                     if ( _debug && best_feasible ) {
366                         _p.out() << "RANK #" << _rank << ": POLLSTER_ELL="
367                         << pollster_mesh_index << " VARS = [";
368                         for ( i = 0 ; i < _ns ; ++i )
369                             _p.out() << free_vars[i] << " ";
370                         _p.out() << " ] BBE=" << mads.get_stats().get_bb_eval()
371                         << " OLD_F=" << old_f << " NEW_F="
372                         << best_feasible->get_f()
373                         << " SUCCESS="
374                         << (best_feasible->get_f() < old_f)
375                         << endl;
376                     }
377                 }
378             }
379 
380             {
381                 int       tmp1 = -1;
382                 bool      tmp2 = false;
383                 stop_type tmp3 = UNKNOWN_STOP_REASON;
384                 send_optimization_result ( tmp1            ,
385                                           tmp2            ,
386                                           best_feasible   ,
387                                           best_infeasible ,
388                                           tmp3              );
389             }
390         }
391 
392         // loop increment:
393         ++run_index;
394     }
395 
396     delete [] free_vars;
397 }
398 
399 /*----------------------------------------------------*/
400 /*  receive an optimization result from the pollster  */
401 /*  POLLSTER --> MASTER                               */
402 /*----------------------------------------------------*/
receive_optimization_result(int & pollster_mesh_index,bool & stop_algo,double * & best_feasible,double * & best_infeasible,int source) const403 void Master_Slaves::receive_optimization_result
404 ( int     & pollster_mesh_index ,
405  bool    & stop_algo           ,
406  double *& best_feasible       ,
407  double *& best_infeasible     ,
408  int       source                ) const {
409 
410     int        itab[5];
411     MPI_Status status;
412 
413     MPI_Recv ( itab , 5 , MPI_INT , source ,
414               Master_Slaves::TAG_I1 , MPI_COMM_WORLD , &status );
415 
416     pollster_mesh_index = itab[0];
417 
418     // stop the algorithm ?
419     stop_algo = ( itab[4] == 1 );
420 
421     if ( !stop_algo ) {
422 
423         stop_type stop_reason = static_cast<stop_type>(itab[1]);
424 
425         switch ( stop_reason ) {
426             case ERROR:
427             case UNKNOWN_STOP_REASON:
428             case CTRL_C:
429             case MESH_PREC_REACHED:
430             case X0_FAIL:
431             case P1_FAIL:
432             case L_MAX_REACHED:
433             case L_LIMITS_REACHED:
434             case MAX_TIME_REACHED:
435             case MAX_BB_EVAL_REACHED:
436             case MAX_SGTE_EVAL_REACHED:
437             case MAX_EVAL_REACHED:
438             case MAX_SIM_BB_EVAL_REACHED:
439             case MAX_ITER_REACHED:
440             case FEAS_REACHED:
441             case F_TARGET_REACHED:
442             case STAT_SUM_TARGET_REACHED:
443             case L_CURVE_TARGET_REACHED:
444             case MULTI_MAX_BB_REACHED:
445             case MULTI_NB_MADS_RUNS_REACHED:
446             case MULTI_STAGNATION:
447             case MULTI_NO_PARETO_PTS:
448             case MAX_CACHE_MEMORY_REACHED:
449                 stop_algo = true;
450             default:
451                 stop_algo = false;
452         }
453     }
454 
455     int i , nb_pts = 0;
456     if ( itab[2] == 1 )
457         ++nb_pts;
458     if ( itab[3] == 1 )
459         ++nb_pts;
460 
461     // itab[2] == 1 --> bf != NULL
462     // itab[3] == 1 --> bi != NULL
463 
464     if ( nb_pts > 0 ) {
465 
466         int      n    = _p.get_dimension();
467         double * rtab = new double [(n+2)*nb_pts];
468 
469         MPI_Recv ( rtab , (n+2)*nb_pts , MPI_DOUBLE , source ,
470                   Master_Slaves::TAG_R1 , MPI_COMM_WORLD , &status );
471 
472         if ( nb_pts == 2 ) {
473 
474             // best feasible and infeasible updates:
475             bool update = false;
476 
477             if ( best_feasible ) {
478                 Double old_f = best_feasible[n+1];
479                 Double new_f = rtab         [n+1];
480                 if ( new_f < old_f )
481                     update = true;
482             }
483             else {
484                 best_feasible = new double[n+2];
485                 update = true;
486             }
487 
488             if ( update ) {
489                 for ( i = 0 ; i < n ; ++i )
490                     best_feasible[i] = rtab[i];
491                 best_feasible[n  ] = rtab[n];
492                 best_feasible[n+1] = rtab[n+1];
493             }
494 
495             update = false;
496 
497             if ( best_infeasible ) {
498 
499                 Double old_h = best_infeasible[n];
500                 Double new_h = rtab           [2*n+2];
501                 if ( new_h < old_h )
502                     update = true;
503             }
504             else {
505                 best_infeasible = new double[n+2];
506                 update = true;
507             }
508 
509             if ( update ) {
510                 int cur = n+2;
511                 for ( i = 0 ; i < n ; ++i )
512                     best_infeasible[i] = rtab[cur++];
513                 best_infeasible[n  ] = rtab[cur++];
514                 best_infeasible[n+1] = rtab[cur];
515             }
516             delete [] rtab;
517         }
518         else {
519 
520             // best feasible update:
521             if ( itab[2] == 1 ) {
522                 if ( best_feasible ) {
523                     Double old_f = best_feasible[n+1];
524                     Double new_f = rtab         [n+1];
525                     if ( new_f < old_f ) {
526                         delete [] best_feasible;
527                         best_feasible = rtab;
528                     }
529                     else
530                         delete [] rtab;
531                 }
532                 else
533                     best_feasible = rtab;
534             }
535 
536             // best infeasible update:
537             else {
538                 if ( best_infeasible ) {
539                     Double old_h = best_infeasible[n];
540                     Double new_h = rtab           [n];
541                     if ( new_h < old_h ) {
542                         delete [] best_infeasible;
543                         best_infeasible = rtab;
544                     }
545                     else
546                         delete [] rtab;
547                 }
548                 else
549                     best_infeasible = rtab;
550             }
551         }
552     }
553 }
554 
555 /*---------------------------------------------*/
556 /*  send an optimization result to the master  */
557 /*  POLLSTER --> MASTER                        */
558 /*---------------------------------------------*/
send_optimization_result(int pollster_mesh_index,bool stop_algo,const Eval_Point * bf,const Eval_Point * bi,stop_type st) const559 void Master_Slaves::send_optimization_result
560 ( int                pollster_mesh_index ,
561  bool               stop_algo           ,
562  const Eval_Point * bf                  ,
563  const Eval_Point * bi                  ,
564  stop_type          st                    ) const {
565 
566     // send a signal to the master:
567     MPI_Send ( &Master_Slaves::OPTI_RES_SIGNAL , 1 , MPI_CHAR ,
568               0 , Master_Slaves::TAG_SIGNAL , MPI_COMM_WORLD );
569 
570     // send the data:
571     int itab[5];
572 
573     itab[0] = pollster_mesh_index;
574     itab[1] = static_cast<int>(st);
575 
576     int nb_pts = 0;
577     if ( bf ) {
578         ++nb_pts;
579         itab[2] = 1;
580     }
581     else
582         itab[2] = 0;
583 
584     if ( bi ) {
585         ++nb_pts;
586         itab[3] = 1;
587     }
588     else
589         itab[3] = 0;
590 
591     itab[4] = (stop_algo) ? 1 : 0;
592 
593     MPI_Send ( itab , 5 , MPI_INT , 0 ,
594               Master_Slaves::TAG_I1 , MPI_COMM_WORLD );
595 
596     if ( nb_pts > 0 ) {
597 
598         int      n    = _p.get_dimension();
599         double * rtab = new double [(n+2)*nb_pts];
600 
601         int i , cur = 0;
602         if ( bf ) {
603             for ( i = 0 ; i < n ; ++i )
604                 rtab[cur++] = (*bf)[i].value();
605             rtab[cur++] = bf->get_h().value();
606             rtab[cur++] = bf->get_f().value();
607         }
608 
609         if ( bi ) {
610             for ( i = 0 ; i < n ; ++i )
611                 rtab[cur++] = (*bi)[i].value();
612             rtab[cur++] = bi->get_h().value();
613             rtab[cur  ] = bi->get_f().value();
614         }
615 
616         MPI_Send ( rtab , cur , MPI_DOUBLE , 0 ,
617                   Master_Slaves::TAG_R1 , MPI_COMM_WORLD );
618 
619         delete [] rtab;
620     }
621 }
622 
623 /*---------------------------------------------*/
624 /*  receive optimization data from the master  */
625 /*  MASTER --> REGULAR SLAVE                   */
626 /*---------------------------------------------*/
receive_optimization_data(bool & stop_algo,Point & x0,Double & fx0,int & pollster_mesh_index,int * free_vars) const627 void Master_Slaves::receive_optimization_data
628 ( bool   & stop_algo           ,
629  Point  & x0                  ,
630  Double & fx0                 ,
631  int    & pollster_mesh_index ,
632  int    * free_vars             ) const {
633 
634     // step 1/2: receive common pollster data:
635     receive_optimization_data ( stop_algo , x0 , fx0 );
636 
637     int i;
638 
639     // step 2/2: receive additional data for regular slaves:
640     if ( !stop_algo ) {
641 
642         int      * itab = new int [_ns+1];
643         MPI_Status status;
644 
645         MPI_Recv ( itab , _ns+1 , MPI_INT , 0 ,
646                   Master_Slaves::TAG_I2 , MPI_COMM_WORLD , &status );
647 
648         for ( i = 0 ; i < _ns ; ++i )
649             free_vars[i] = itab[i];
650 
651         pollster_mesh_index = itab[_ns];
652 
653         delete [] itab;
654     }
655     else {
656         pollster_mesh_index = 1;
657         for ( i = 0 ; i < _ns ; ++i )
658             free_vars[i] = -1;
659     }
660 }
661 
662 /*---------------------------------------------*/
663 /*  receive optimization data from the master  */
664 /*  MASTER --> POLLSTER                        */
665 /*---------------------------------------------*/
receive_optimization_data(bool & stop_algo,Point & x0,Double & fx0) const666 void Master_Slaves::receive_optimization_data ( bool   & stop_algo ,
667                                                Point  & x0        ,
668                                                Double & fx0         ) const {
669     char        c_stop;
670     MPI_Status  status;
671     MPI_Request req    = MPI_REQUEST_NULL;
672     int         i , n  = _p.get_dimension();
673 
674     // send a request for c_stop:
675     MPI_Irecv ( &c_stop , 1 , MPI_CHAR , 0 ,
676                Master_Slaves::TAG_CSTOP , MPI_COMM_WORLD , &req );
677 
678     // send a signal to the master:
679     MPI_Send ( &Master_Slaves::OPTI_DATA_SIGNAL , 1 , MPI_CHAR ,
680               0 , Master_Slaves::TAG_SIGNAL , MPI_COMM_WORLD );
681 
682     MPI_Wait ( &req , &status );
683 
684     // stop:
685     if ( c_stop == '1' ) {
686         stop_algo = true;
687         x0.reset();
688     }
689 
690     // continue:
691     else {
692 
693         stop_algo     = false;
694         double * rtab = new double [n+2];
695 
696         MPI_Recv ( rtab , n+2 , MPI_DOUBLE , 0 ,
697                   Master_Slaves::TAG_D1 , MPI_COMM_WORLD , &status );
698 
699         for ( i = 0 ; i < n ; ++i )
700             x0[i] = rtab[i];
701 
702         Double h = rtab[n];
703         fx0 = ( h <= _p.get_h_min() ) ? rtab[n+1] : INF;
704 
705         // get the best feasible point from the cache server:
706         {
707             char pt_flag;
708             int  npm1 = _np-1;
709             MPI_Irecv ( &pt_flag , 1 , MPI_CHAR , npm1 ,
710                        Cache_Server::TAG_BF , MPI_COMM_WORLD , &req );
711 
712             MPI_Send ( &Cache_Server::BF_SIGNAL , 1 , MPI_CHAR ,
713                       npm1 , Cache_Server::TAG_SIGNAL , MPI_COMM_WORLD );
714 
715             MPI_Wait ( &req , &status );
716 
717             if ( pt_flag == '1' ) {
718 
719                 MPI_Recv ( rtab , n+2 , MPI_DOUBLE , npm1 ,
720                           Cache_Server::TAG_X7 , MPI_COMM_WORLD , &status );
721 
722                 for ( i = 0 ; i < n ; ++i )
723                     x0[i] = rtab[i];
724 
725                 Double h = rtab[n];
726                 fx0 = ( h <= _p.get_h_min() ) ? rtab[n+1] : INF;
727 
728             }
729         }
730         delete [] rtab;
731 
732         // check the bounds:
733         const Point & lb = _p.get_lb();
734         const Point & ub = _p.get_ub();
735 
736         for ( i = 0 ; i < n ; ++i ) {
737             if ( lb[i].is_defined() && x0[i].value() < lb[i].value() )
738                 x0[i] = lb[i];
739             if ( ub[i].is_defined() && x0[i].value() > ub[i].value() )
740                 x0[i] = ub[i];
741         }
742     }
743 }
744 
745 /*-----------------------------------------------------*/
746 /*  send optimization data from the master to a slave  */
747 /*  MASTER --> POLLSTER or MASTER --> SLAVE            */
748 /*-----------------------------------------------------*/
send_optimization_data(int pollster_mesh_index,bool stop_algo,const double * best_feasible,const double * best_infeasible,int source) const749 void Master_Slaves::send_optimization_data
750 ( int            pollster_mesh_index ,
751  bool           stop_algo           ,
752  const double * best_feasible       ,
753  const double * best_infeasible     ,
754  int            source                ) const {
755 
756     char c_stop = (stop_algo) ? '1' : '0';
757 
758     MPI_Rsend ( &c_stop , 1 , MPI_CHAR , source ,
759                Master_Slaves::TAG_CSTOP , MPI_COMM_WORLD );
760 
761     // continue:
762     if ( !stop_algo ) {
763 
764         int n = _p.get_dimension();
765 
766         // data for pollster and regular slaves:
767         if ( best_feasible )
768             MPI_Send ( const_cast<double*>(best_feasible) , n+2 , MPI_DOUBLE ,
769                       source , Master_Slaves::TAG_D1 , MPI_COMM_WORLD );
770         else
771             MPI_Send ( const_cast<double*>(best_infeasible) , n+2 , MPI_DOUBLE ,
772                       source , Master_Slaves::TAG_D1 , MPI_COMM_WORLD );
773 
774         // additional data for regular slaves:
775         if ( source != 1 ) {
776 
777             int * itab = new int [_ns+1];
778 
779             // choose the free varables:
780             {
781                 Random_Pickup rp ( n );
782 
783                 for ( int i = 0 ; i < _ns ; ++i )
784                     itab[i] = rp.pickup(); // index of the ith free variable
785             }
786 
787             itab[_ns] = pollster_mesh_index;
788 
789             MPI_Send ( itab , _ns+1 , MPI_INT , source ,
790                       Master_Slaves::TAG_I2 , MPI_COMM_WORLD );
791 
792             delete [] itab;
793         }
794     }
795 }
796 
797 /*-----------------------------------------------*/
798 /*        check the initial mesh size values     */
799 /*-----------------------------------------------*/
check_delta(const Point & delta)800 bool Master_Slaves::check_delta ( const Point & delta ) {
801     int n = delta.size();
802     for ( int i = 0 ; i < n ; ++i )
803         if ( delta[i].value() < Double::get_epsilon() ||
804             delta[i].value() <= 0.0 )
805             return false;
806     return true;
807 }
808 
809