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