1 #include "Cache_Server.hpp"
2 using namespace std;
3 using namespace NOMAD;
4 
5 /*--------------------------*/
6 /*  tags and signal values  */
7 /*--------------------------*/
8 const int  Cache_Server::TAG_SIGNAL    = 0;
9 const int  Cache_Server::TAG_CACHE_HIT = 1;
10 const int  Cache_Server::TAG_X1        = 2;
11 const int  Cache_Server::TAG_X2        = 3;
12 const int  Cache_Server::TAG_X3        = 4;
13 const int  Cache_Server::TAG_X4        = 5;
14 const int  Cache_Server::TAG_X5        = 6;
15 const int  Cache_Server::TAG_X6        = 7;
16 const int  Cache_Server::TAG_X7        = 8;
17 const int  Cache_Server::TAG_BBOR      = 9;
18 const int  Cache_Server::TAG_BBOC      = 10;
19 const int  Cache_Server::TAG_NB_EP     = 11;
20 const int  Cache_Server::TAG_EP        = 12;
21 const int  Cache_Server::TAG_BF        = 13;
22 char       Cache_Server::STOP_SIGNAL   = 'S';
23 char       Cache_Server::FIND_SIGNAL   = 'F';
24 char       Cache_Server::INSERT_SIGNAL = 'I';
25 char       Cache_Server::NB_EP_SIGNAL  = 'N';
26 char       Cache_Server::EP_SIGNAL     = 'E';
27 char       Cache_Server::BF_SIGNAL     = 'B';
28 
29 /*-----------------------------------*/
30 /*            constructor            */
31 /*-----------------------------------*/
Cache_Server(const Display & out,int rank,int np,const Double & h_min,int max_bbe,bool allow_multiple_evals,bool debug)32 Cache_Server::Cache_Server ( const Display & out                  ,
33                             int             rank                 ,
34                             int             np                   ,
35                             const Double  & h_min                ,
36                             int             max_bbe              ,
37                             bool            allow_multiple_evals ,
38                             bool            debug                  )
39 : Cache             ( out , TRUTH ) ,
40 _rank             ( rank        ) ,
41 _np               ( np          ) ,
42 _debug            ( debug       ) ,
43 _h_min            ( h_min       ) ,
44 _max_bbe          ( max_bbe     ) ,
45 _bf               ( NULL        ) ,
46 _bi1              ( NULL        ) ,
47 _bi2              ( NULL        ) ,
48 _multiple_evals   ( 0           ) ,
49 _cache_hits       ( 0           ) ,
50 _cache_search_pts ( 0           ) ,
51 _waited_pts       ( NULL        ) ,
52 _clients_ext_pts  ( NULL        )   {
53 
54     // cache server:
55     if ( _rank == _np - 1 ) {
56 
57         _clients_ext_pts = new list<const Eval_Point*> [_np];
58 
59         if ( !allow_multiple_evals ) {
60             _waited_pts = new Point * [_np];
61             for ( int i = 0 ; i < _np ; ++i )
62                 _waited_pts[i] = NULL;
63         }
64     }
65 }
66 
67 /*-----------------------------------*/
68 /*             destructor            */
69 /*-----------------------------------*/
~Cache_Server(void)70 Cache_Server::~Cache_Server ( void ) {
71     if ( _waited_pts ) {
72         for ( int i = 0 ; i < _np ; ++i )
73             if ( _waited_pts[i] )
74                 delete _waited_pts;
75         delete [] _waited_pts;
76     }
77 
78     if ( _clients_ext_pts )
79         delete [] _clients_ext_pts;
80 }
81 
82 /*-----------------------------------*/
83 /*  start the server (process np-1)  */
84 /*-----------------------------------*/
start(void)85 void Cache_Server::start ( void ) {
86 
87     int npm1 = _np-1;
88 
89     if ( _rank != npm1 )
90         return;
91 
92     MPI_Status status;
93     int        nb_stops = 0;
94     int        source;
95     char       signal;
96 
97     /*-------------*/
98     /*  main loop  */
99     /*-------------*/
100     while ( nb_stops != npm1 ) {
101 
102         MPI_Recv ( &signal , 1 , MPI_CHAR , MPI_ANY_SOURCE ,
103                   Cache_Server::TAG_SIGNAL , MPI_COMM_WORLD , &status );
104 
105         source = status.MPI_SOURCE;
106 
107         // stop signal:
108         // ------------
109         if ( signal == Cache_Server::STOP_SIGNAL ) {
110             if ( _debug )
111                 _out << "CACHE SERVER: STOP SIGNAL FROM RANK " << source << endl;
112             ++nb_stops;
113         }
114 
115         // find signal:
116         // ------------
117         else if ( signal == Cache_Server::FIND_SIGNAL ) {
118             if ( _debug )
119                 _out << "CACHE SERVER: FIND SIGNAL FROM RANK " << source << endl;
120             process_find_signal ( source );
121         }
122 
123         // insert signal:
124         // --------------
125         else if ( signal == Cache_Server::INSERT_SIGNAL ) {
126             if ( _debug ) {
127                 _out << "CACHE SERVER: INSERT SIGNAL FROM RANK "
128                 << source;
129                 if ( source == 1 )
130                     _out << " (POLLSTER)";
131                 _out << endl;
132             }
133             process_insert_signal ( source );
134         }
135 
136         // number of extern points signal:
137         // -------------------------------
138         else if ( signal == Cache_Server::NB_EP_SIGNAL ) {
139             if ( _debug ) {
140                 _out << "CACHE SERVER: NB EXTERN POINTS SIGNAL FROM RANK "
141                 << source;
142                 if ( source == 1 )
143                     _out << " (POLLSTER)";
144                 _out << endl;
145             }
146             int nb_client_extern_pts = _clients_ext_pts[source].size();
147             MPI_Rsend ( &nb_client_extern_pts , 1 , MPI_INT , source ,
148                        Cache_Server::TAG_NB_EP , MPI_COMM_WORLD );
149         }
150 
151         // extern point signal:
152         // --------------------
153         else if ( signal == Cache_Server::EP_SIGNAL ) {
154             if ( _debug ) {
155                 _out << "CACHE SERVER: EXTERN POINT SIGNAL FROM RANK "
156                 << source;
157                 if ( source == 1 )
158                     _out << " (POLLSTER)";
159                 _out << endl;
160             }
161             process_ep_signal ( source );
162         }
163 
164         // best feasible point signal:
165         else if ( signal == Cache_Server::BF_SIGNAL ) {
166             if ( _debug ) {
167                 _out << "CACHE SERVER: BEST FEASIBLE POINT SIGNAL FROM RANK "
168                 << source;
169                 if ( source == 1 )
170                     _out << " (POLLSTER)";
171             }
172             process_bf_signal ( source );
173         }
174     }
175 }
176 
177 /*---------------------------------*/
178 /*    stop the server (clients)    */
179 /*---------------------------------*/
stop(void) const180 void Cache_Server::stop ( void ) const {
181 
182     int npm1 = _np-1;
183 
184     if ( _rank == npm1 )
185         return;
186 
187     MPI_Send ( &Cache_Server::STOP_SIGNAL , 1 , MPI_CHAR ,
188               npm1 , Cache_Server::TAG_SIGNAL , MPI_COMM_WORLD );
189 }
190 
191 /*----------------------------------------------*/
192 /*    process the best feasible point signal    */
193 /*----------------------------------------------*/
process_bf_signal(int source) const194 void Cache_Server::process_bf_signal ( int source ) const {
195 
196     char pt_flag = (_bf) ? '1' : '0';
197 
198     MPI_Rsend ( &pt_flag , 1 , MPI_CHAR , source ,
199                Cache_Server::TAG_BF , MPI_COMM_WORLD );
200 
201     if ( _bf ) {
202         int n = _bf->size();
203         double * rtab = new double[n+2];
204         for ( int i = 0 ; i < n ; ++i )
205             rtab[i] = (*_bf)[i].value();
206         rtab[n] = _bf->get_h().value();
207         rtab[n+1] = _bf->get_f().value();
208 
209         MPI_Send ( rtab , n+2 , MPI_DOUBLE , source ,
210                   Cache_Server::TAG_X7 , MPI_COMM_WORLD );
211 
212         delete [] rtab;
213     }
214 
215 }
216 
217 /*---------------------------------------*/
218 /*    process the extern point signal    */
219 /*---------------------------------------*/
process_ep_signal(int source) const220 void Cache_Server::process_ep_signal ( int source ) const {
221 
222     int nb_pt = ( _clients_ext_pts[source].size() > 0 ) ? 1 : 0;
223 
224     MPI_Rsend ( &nb_pt , 1 , MPI_INT , source ,
225                Cache_Server::TAG_EP , MPI_COMM_WORLD );
226 
227     // send and remove the extern point:
228     if ( nb_pt > 0 ) {
229 
230         const Eval_Point * x = *(_clients_ext_pts[source].begin());
231 
232         ++_cache_search_pts;
233 
234         // send the point :
235         int i , n = x->size() , m = x->get_m();
236         int itab[5];
237         itab[0] = n;
238         itab[1] = m;
239         itab[2] = ( x->is_eval_ok() ) ? 1 : 0;
240 
241         if ( x->get_signature() && (x->get_signature()->get_mesh()->get_mesh_indices())[0].is_defined() )
242         {
243             itab[3]=1;
244             itab[4]=static_cast<int>((x->get_signature()->get_mesh()->get_mesh_indices())[0].value());
245         }
246         else
247             itab[3] = itab[4] = 0;
248 
249         double * rtab = new double[n+2*m];
250         for ( i = 0 ; i < n ; ++i )
251             rtab[i] = (*x)[i].value();
252 
253         const Point & bbo = x->get_bb_outputs();
254 
255         for ( i = 0 ; i < m ; ++i )
256             if ( bbo[i].is_defined() ) {
257                 rtab[2*i+n  ] = 1.0;
258                 rtab[2*i+n+1] = bbo[i].value();
259             }
260             else
261                 rtab[2*i+n] = rtab[2*i+n+1] = -1.0;
262 
263         MPI_Send ( itab , 5 , MPI_INT , source ,
264                   Cache_Server::TAG_X5 , MPI_COMM_WORLD );
265 
266         MPI_Send ( rtab , n+2*m , MPI_DOUBLE , source ,
267                   Cache_Server::TAG_X6 , MPI_COMM_WORLD );
268 
269         // remove the point:
270         _clients_ext_pts[source].pop_front();
271     }
272 }
273 
274 /*-------------------------------*/
275 /*    process the find signal    */
276 /*-------------------------------*/
process_find_signal(int source) const277 void Cache_Server::process_find_signal ( int source ) const {
278 
279     MPI_Status status;
280     int i;
281 
282     // receive the point coordinates:
283     int itab[2];
284     MPI_Recv ( itab , 2 , MPI_INT , source ,
285               Cache_Server::TAG_X1 , MPI_COMM_WORLD , &status );
286 
287     int n = itab[0];
288     int m = itab[1];
289 
290     double * rtab = new double[n];
291 
292     MPI_Recv ( rtab , n , MPI_DOUBLE , source ,
293               Cache_Server::TAG_X2 , MPI_COMM_WORLD , &status );
294 
295     // create the Eval_Point to search:
296     Eval_Point * x = new Eval_Point ( n , m );
297 
298     for ( i = 0 ; i < n ; ++i )
299         (*x)[i] = rtab[i];
300 
301     delete [] rtab;
302 
303     // search in cache, or stop the algorithm:
304     const Eval_Point * cache_x;
305 
306     if ( _max_bbe > 0 && size() >= _max_bbe ) {
307         Eval_Point * stop_point = new Eval_Point ( n , m );
308         for ( i = 0 ; i < n ; ++i )
309             (*stop_point)[i] = (*x)[i];
310         stop_point->set_eval_status ( EVAL_FAIL );
311         cache_x = stop_point;
312     }
313     else
314         cache_x = Cache::find ( *x );
315 
316     // cache hit signal :
317     int cache_hit;
318 
319     // point in cache :
320     if ( cache_x ) {
321 
322         delete x;
323 
324         cache_hit = 1;
325 
326         ++_cache_hits;
327 
328         MPI_Rsend ( &cache_hit , 1 , MPI_INT , source ,
329                    Cache_Server::TAG_CACHE_HIT , MPI_COMM_WORLD );
330 
331         // bb output values, defined values and eval_ok flag:
332         rtab               = new double[m];
333         char        * ctab = new char  [m+1];
334         const Point & bbo  = cache_x->get_bb_outputs();
335 
336         for ( i = 0 ; i < m ; ++i ) {
337             if ( bbo[i].is_defined() ) {
338                 rtab[i] = bbo[i].value();
339                 ctab[i] = '1';
340             }
341             else {
342                 rtab[i] = INF;
343                 ctab[i] = '0';
344             }
345         }
346 
347         ctab[m] = ( cache_x->is_eval_ok() ) ? '1' : '0';
348 
349         MPI_Send ( rtab , m , MPI_DOUBLE , source ,
350                   Cache_Server::TAG_BBOR , MPI_COMM_WORLD );
351 
352         MPI_Send ( ctab , m+1 , MPI_CHAR , source ,
353                   Cache_Server::TAG_BBOC , MPI_COMM_WORLD );
354 
355         delete [] rtab;
356         delete [] ctab;
357 
358         // remove this point from _clients_ext_pts:
359         {
360             list<const Eval_Point *>::iterator
361             it  = _clients_ext_pts[source].begin() ,
362             end = _clients_ext_pts[source].end  ();
363             while ( it != end ) {
364                 if ( *it == cache_x ) {
365                     _clients_ext_pts[source].erase(it);
366                     break;
367                 }
368                 ++it;
369             }
370         }
371     }
372 
373     // point not in cache :
374     else {
375 
376         cache_hit = 0;
377 
378         // evaluation in progress ?
379         if ( _waited_pts ) {
380 
381             for ( i = 0 ; i < _np ; ++i )
382                 if ( _waited_pts[i] && *_waited_pts[i] == *x ) {
383                     cache_hit = -1;
384                     break;
385                 }
386 
387             if ( cache_hit == 0 )
388                 _waited_pts[source] = x;
389             else
390                 delete x;
391         }
392         else
393             delete x;
394 
395         MPI_Rsend ( &cache_hit , 1 , MPI_INT , source ,
396                    Cache_Server::TAG_CACHE_HIT , MPI_COMM_WORLD );
397     }
398 }
399 
400 /*--------------------*/
401 /*    find a point    */
402 /*--------------------*/
find(const Eval_Point & x) const403 const Eval_Point * Cache_Server::find ( const Eval_Point & x ) const {
404 
405     int npm1 = _np-1;
406 
407     // server:
408     if ( _rank == npm1 )
409         return Cache::find ( x );
410 
411     // A. search in local cache:
412     const Eval_Point * cache_x = Cache::find ( x );
413     if ( cache_x )
414         return cache_x;
415 
416     // B. ask the server.
417     int i , n = x.size() , m = x.get_m();
418     int itab[2];
419     itab[0] = n;
420     itab[1] = m;
421     double * rtab = new double[n];
422     for ( i = 0 ; i < n ; ++i )
423         rtab[i] = x[i].value();
424 
425     int      cache_hit = -1;
426     MPI_Request    req = MPI_REQUEST_NULL;
427     MPI_Status  status;
428 
429     while ( cache_hit < 0 ) {
430 
431         // B1. send a request for cache_hit:
432         MPI_Irecv ( &cache_hit , 1 , MPI_INT , npm1 ,
433                    Cache_Server::TAG_CACHE_HIT , MPI_COMM_WORLD , &req );
434 
435         // B2. send the find signal:
436         MPI_Send ( &Cache_Server::FIND_SIGNAL , 1 , MPI_CHAR ,
437                   npm1 , Cache_Server::TAG_SIGNAL , MPI_COMM_WORLD );
438 
439         // B3. send the point coordinates:
440         MPI_Send ( itab , 2 , MPI_INT , npm1 ,
441                   Cache_Server::TAG_X1 , MPI_COMM_WORLD );
442         MPI_Send ( rtab , n , MPI_DOUBLE , npm1 ,
443                   Cache_Server::TAG_X2 , MPI_COMM_WORLD );
444 
445         // B4. wait for the cache_hit request:
446         MPI_Wait ( &req , &status );
447 
448         // cache hit possible values:
449         //
450         //  -1: point is being evaluated by another process (wait)
451         //   0: point not in cache server
452         //   1: point in cache server
453     }
454 
455     delete [] rtab;
456 
457     // C. cache hit: receive the point outputs:
458     if ( cache_hit == 1 ) {
459 
460         // C.1. bb output values and eval status:
461         rtab = new double[m];
462         MPI_Recv ( rtab , m , MPI_DOUBLE , npm1 ,
463                   Cache_Server::TAG_BBOR , MPI_COMM_WORLD , &status );
464 
465         char * ctab = new char[m+1];
466         MPI_Recv ( ctab , m+1 , MPI_CHAR , npm1 ,
467                   Cache_Server::TAG_BBOC , MPI_COMM_WORLD , &status );
468 
469         Point bbo(m);
470         for ( i = 0 ; i < m ; ++i )
471             if ( ctab[i]=='1' )
472                 bbo[i] = rtab[i];
473 
474         delete [] rtab;
475 
476         //  C.2. eval point construction:
477         Eval_Point * y = new Eval_Point ( n , m );
478         y->set_bb_output ( bbo );
479         for ( i = 0 ; i < n ; ++i )
480             (*y)[i] = x[i];
481 
482         y->set_eval_status ( (ctab[m]=='1') ? EVAL_OK : EVAL_FAIL );
483 
484         y->set_current_run ( x.get_current_run() );
485 
486         delete [] ctab;
487 
488         cache_x = y;
489 
490 
491         // C.3. insertion in local cache:
492         const_cast<Cache_Server*>(this)->Cache::insert ( *cache_x );
493     }
494 
495     return cache_x;
496 }
497 
498 /*------------------------------------*/
499 /*    process the insertion signal    */
500 /*------------------------------------*/
process_insert_signal(int source)501 void Cache_Server::process_insert_signal ( int source ) {
502 
503     if ( _waited_pts && _waited_pts[source] ) {
504         delete _waited_pts[source];
505         _waited_pts[source] = NULL;
506     }
507 
508     MPI_Status status;
509 
510     // receive the evaluation point:
511     int itab[7];
512     MPI_Recv ( itab , 7 , MPI_INT , source ,
513               Cache_Server::TAG_X3 , MPI_COMM_WORLD , &status );
514 
515     int n = itab[0];
516     int m = itab[1];
517 
518     double * rtab = new double[n+2*m+2];
519 
520     MPI_Recv ( rtab , n+2*m+2 , MPI_DOUBLE , source ,
521               Cache_Server::TAG_X4 , MPI_COMM_WORLD , &status );
522 
523     // create the Eval_Point to insert:
524     Eval_Point * x = new Eval_Point ( n , m );
525 
526     int i;
527     for ( i = 0 ; i < n ; ++i )
528         (*x)[i] = rtab[i];
529 
530     for ( i = 0 ; i < m ; ++i )
531         if ( rtab[2*i+n] > 0 )
532             x->set_bb_output ( i , rtab[2*i+n+1] );
533 
534     if ( itab[5] == 1 )
535         x->set_f ( rtab[n+2*m  ] );
536 
537     if ( itab[6] == 1 )
538         x->set_h ( rtab[n+2*m+1] );
539 
540     delete [] rtab;
541 
542     x->set_eval_status ( ( itab[2] == 1 ) ? EVAL_OK : EVAL_FAIL );
543 
544     // Eval_Point insertion in cache and multiple_evals detection:
545     const Eval_Point * cache_x = Cache::find ( *x );
546     if ( cache_x ) {
547         ++_multiple_evals;
548         delete x;
549         x = const_cast<Eval_Point *>(cache_x);
550     }
551     else
552         Cache::insert ( *x );
553 
554     // update the best points:
555     update_best_points ( *x , source );
556 }
557 
558 /*--------------------*/
559 /*   insert a point   */
560 /*--------------------*/
insert(const NOMAD::Eval_Point & x)561 void Cache_Server::insert ( const NOMAD::Eval_Point & x ) {
562 
563     // insertion in local cache :
564     Cache::insert ( x );
565 
566     int npm1 = _np-1;
567     if ( _rank == npm1 )
568         return;
569 
570     // insert signal :
571     MPI_Send ( &Cache_Server::INSERT_SIGNAL , 1 , MPI_CHAR ,
572               npm1 , Cache_Server::TAG_SIGNAL , MPI_COMM_WORLD );
573 
574     // send the point :
575     int i , n = x.size() , m = x.get_m();
576     int itab[7];
577     itab[0] = n;
578     itab[1] = m;
579     itab[2] = ( x.is_eval_ok() ) ? 1 : 0;
580 
581     if ( x.get_signature() && (x.get_signature()->get_mesh()->get_mesh_indices())[0].is_defined() )
582     {
583         itab[3]=1;
584         itab[4]=static_cast<int>((x.get_signature()->get_mesh()->get_mesh_indices())[0].value());
585     }
586     else
587         itab[3] = itab[4] = 0;
588 
589     double * rtab = new double[n+2*m+2];
590     for ( i = 0 ; i < n ; ++i )
591         rtab[i] = x[i].value();
592 
593     const Point & bbo = x.get_bb_outputs();
594 
595     for ( i = 0 ; i < m ; ++i )
596         if ( bbo[i].is_defined() ) {
597             rtab[2*i+n  ] = 1.0;
598             rtab[2*i+n+1] = bbo[i].value();
599         }
600         else
601             rtab[2*i+n] = rtab[2*i+n+1] = -1.0;
602 
603     // f and h values:
604     if ( x.get_f().is_defined() ) {
605         itab[5    ] = 1;
606         rtab[n+2*m] = x.get_f().value();
607     }
608     else {
609         itab[5    ] = 0;
610         rtab[n+2*m] = INF;
611     }
612     if ( x.get_h().is_defined() ) {
613         itab[6      ] = 1;
614         rtab[n+2*m+1] = x.get_h().value();
615     }
616     else {
617         itab[6      ] = 0;
618         rtab[n+2*m+1] = INF;
619     }
620 
621     MPI_Send ( itab , 7 , MPI_INT , npm1 ,
622               Cache_Server::TAG_X3 , MPI_COMM_WORLD );
623 
624     MPI_Send ( rtab , n+2*m+2 , MPI_DOUBLE , npm1 ,
625               Cache_Server::TAG_X4 , MPI_COMM_WORLD );
626 
627     delete [] rtab;
628 }
629 
630 /*--------------------------------------*/
631 /*    get and remove an extern point    */
632 /*--------------------------------------*/
get_and_remove_extern_point(void) const633 const Eval_Point * Cache_Server::get_and_remove_extern_point ( void ) const {
634 
635     int npm1 = _np-1;
636 
637     if ( _rank == npm1 )
638         return NULL;
639 
640     // extern point from the client:
641     // -----------------------------
642     if ( Cache::get_nb_extern_points() > 0 )
643         return Cache::get_and_remove_extern_point();
644 
645     // extern point from the server:
646     // -----------------------------
647 
648     int nb_pt;
649 
650     // send a request for an extern point:
651     MPI_Request req;
652     MPI_Irecv ( &nb_pt , 1 , MPI_INT , npm1 ,
653                Cache_Server::TAG_EP , MPI_COMM_WORLD , &req );
654 
655     // extern points signal :
656     MPI_Send ( &Cache_Server::EP_SIGNAL , 1 , MPI_CHAR ,
657               npm1 , Cache_Server::TAG_SIGNAL , MPI_COMM_WORLD );
658 
659     // wait for the request:
660     MPI_Status status;
661     MPI_Wait ( &req , &status );
662 
663     if ( nb_pt == 0 )
664         return NULL;
665 
666     // receive the extern point:
667     int itab[5];
668     MPI_Recv ( itab , 5 , MPI_INT , npm1 ,
669               Cache_Server::TAG_X5 , MPI_COMM_WORLD , &status );
670 
671     int n = itab[0];
672     int m = itab[1];
673 
674     double * rtab = new double[n+2*m];
675 
676     MPI_Recv ( rtab , n+2*m , MPI_DOUBLE , npm1 ,
677               Cache_Server::TAG_X6 , MPI_COMM_WORLD , &status );
678 
679     // create the Eval_Point:
680     Eval_Point * x = new Eval_Point ( n , m );
681 
682     int i;
683     for ( i = 0 ; i < n ; ++i )
684         (*x)[i] = rtab[i];
685 
686     for ( i = 0 ; i < m ; ++i )
687         if ( rtab[2*i+n] > 0 )
688             x->set_bb_output ( i , rtab[2*i+n+1] );
689 
690     delete [] rtab;
691 
692     x->set_eval_status ( ( itab[2] == 1 ) ? EVAL_OK : EVAL_FAIL );
693 
694 
695     // insert the point in local cache:
696     const Eval_Point * cache_x = Cache::find ( *x );
697     if ( cache_x ) {
698         delete x;
699         return cache_x;
700     }
701 
702     x->set_current_run ( true );
703     const_cast<Cache_Server*>(this)->Cache::insert ( *x );
704     x->set_current_run ( false );
705 
706     return x;
707 }
708 
709 /*---------------------------------------*/
710 /*    get the number of extern points    */
711 /*---------------------------------------*/
get_nb_extern_points(void) const712 int Cache_Server::get_nb_extern_points ( void ) const {
713 
714     int nb_client_extern_pts = Cache::get_nb_extern_points();
715     int nb_server_extern_pts = 0;
716     int npm1                 = _np-1;
717 
718     if ( _rank != npm1 ) {
719 
720         // send a request for the number of extern points:
721         MPI_Request req;
722         MPI_Irecv ( &nb_server_extern_pts , 1 , MPI_INT , npm1 ,
723                    Cache_Server::TAG_NB_EP , MPI_COMM_WORLD , &req );
724 
725         // number of extern points signal :
726         MPI_Send ( &Cache_Server::NB_EP_SIGNAL , 1 , MPI_CHAR ,
727                   npm1 , Cache_Server::TAG_SIGNAL , MPI_COMM_WORLD );
728 
729         // wait for the request:
730         MPI_Status status;
731         MPI_Wait ( &req , &status );
732     }
733 
734     return nb_client_extern_pts + nb_server_extern_pts;
735 }
736 
737 /*---------------------------------*/
738 /*    display the extern points    */
739 /*---------------------------------*/
display_extern_pts(const Display & out) const740 void Cache_Server::display_extern_pts ( const Display & out ) const {
741 
742     int npm1 = _np-1;
743 
744     // server:
745     // -------
746     if ( _rank == npm1 ) {
747 
748         list<const Eval_Point*>::const_iterator it;
749         out << endl << open_block ("Clients extern points");
750 
751         for ( int i = 0 ; i < npm1 ; ++i ) {
752             out.open_block ( "client #"+itos(i) );
753             for ( it  = _clients_ext_pts[i].begin() ;
754                  it != _clients_ext_pts[i].end  () ;
755                  ++it ) {
756                 out << "#" << (*it)->get_tag() << " ( ";
757                 (*it)->Point::display ( out );
758                 out << " ) " << " ["
759                 << (*it)->get_bb_outputs() << " ] f="
760                 << (*it)->get_f() << " h="
761                 << (*it)->get_h() << endl;
762             }
763             out.close_block();
764         }
765     }
766 
767     // clients:
768     else {
769 
770         out << endl
771         << open_block ( "Process #" + itos(_rank) + ": extern points" );
772 
773         out << "number of points = "
774         << get_nb_extern_points() << endl;
775 
776         const Eval_Point * extern_pt = get_and_remove_extern_point();
777 
778         while ( extern_pt ) {
779 
780             out << "#" << extern_pt->get_tag() << " ( ";
781             extern_pt->Point::display ( out );
782             out << " ) " << " ["
783             << extern_pt->get_bb_outputs() << " ] f="
784             << extern_pt->get_f() << " h="
785             << extern_pt->get_h() << endl;
786 
787             extern_pt = get_and_remove_extern_point();
788         }
789     }
790     out << close_block() << endl;
791 }
792 
793 /*--------------------------------------*/
794 /*  update and display the best points  */
795 /*--------------------------------------*/
update_best_points(const Eval_Point & x,int source)796 void Cache_Server::update_best_points ( const Eval_Point & x      ,
797                                        int                source   ) {
798     const Double & f = x.get_f();
799     const Double & h = x.get_h();
800 
801     if ( !f.is_defined() || !h.is_defined() )
802         return;
803 
804     int  i;
805     bool add_x = false;
806 
807     // feasible:
808     if ( h <= _h_min ) {
809 
810         // new best feasible point:
811         if ( !_bf || f < _bf->get_f() ) {
812             _bf   = &x;
813             add_x = true;
814             display_current_solution();
815         }
816     }
817 
818     // infeasible:
819     else {
820         if ( !_bi1 || h < _bi1->get_h() ) {
821             _bi1  = &x;
822             add_x = true;
823         }
824         if ( !_bi2 || f < _bi2->get_f() ) {
825             _bi2  = &x;
826             add_x = true;
827         }
828     }
829 
830     if ( add_x )
831         for ( i = 0 ; i < _np-1 ; ++i )
832             if ( i != source )
833                 _clients_ext_pts[i].push_front ( &x );
834 }
835 
836 /*-----------------------------------------*/
837 /*    display the current best solution    */
838 /*-----------------------------------------*/
display_current_solution(void) const839 void Cache_Server::display_current_solution ( void ) const {
840     if ( _rank != _np-1 || !_bf )
841         return;
842     if ( _debug )
843         _out << "CACHE SERVER: CURRENT SOLUTION: \t";
844     _out << _clock.get_real_time() << "\t"
845     << size() << "\t" << _bf->get_f() << endl;
846 }
847 
848 /*-------------------------------*/
849 /*    display the best points    */
850 /*-------------------------------*/
display_best_points(const Display & out) const851 void Cache_Server::display_best_points ( const Display & out ) const {
852     if ( _rank != _np-1 )
853         return;
854 
855     // display the last solution:
856     display_current_solution();
857 
858     // stats:
859     out << "evaluations: " << size()      << endl
860     << "cache hits : " << _cache_hits << endl;
861 
862     // best feasible solution:
863     out << "best feasible solution: ";
864     if ( _bf ) {
865         out << "x=( ";
866         _bf->Point::display(out);
867         out << " )"
868         << " F(x)=[ " << _bf->get_bb_outputs() << " ] h="
869         << _bf->get_h() << " f=" << _bf->get_f() << endl;
870     }
871     else {
872 
873         out << "NULL" << endl;
874 
875         // best infeasible solutions:
876         if ( _bi1 ) {
877             out << "best infeas. sol. #1  : x=( ";
878             _bi1->Point::display(out);
879             out << " )"
880             << " F(x)=[ " << _bi1->get_bb_outputs() << " ] h="
881             << _bi1->get_h() << " f=" << _bi1->get_f() << endl;
882         }
883 
884         if ( _bi2 && _bi2 != _bi1 ) {
885             out << "best infeas. sol. #2  : x=( ";
886             _bi2->Point::display(out);
887             out << " )"
888             << " F(x)=[ " << _bi2->get_bb_outputs() << " ] h="
889             << _bi2->get_h() << " f=" << _bi2->get_f() << endl;
890         }
891     }
892 }
893