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   // insert the point in local cache:
695   const Eval_Point * cache_x = Cache::find ( *x );
696   if ( cache_x ) {
697     delete x;
698     return cache_x;
699   }
700 
701   x->set_current_run ( true );
702   const_cast<Cache_Server*>(this)->Cache::insert ( *x );
703   x->set_current_run ( false );
704 
705   return x;
706 }
707 
708 /*---------------------------------------*/
709 /*    get the number of extern points    */
710 /*---------------------------------------*/
get_nb_extern_points(void) const711 int Cache_Server::get_nb_extern_points ( void ) const {
712 
713   int nb_client_extern_pts = Cache::get_nb_extern_points();
714   int nb_server_extern_pts = 0;
715   int npm1                 = _np-1;
716 
717   if ( _rank != npm1 ) {
718 
719     // send a request for the number of extern points:
720     MPI_Request req;
721     MPI_Irecv ( &nb_server_extern_pts , 1 , MPI_INT , npm1 ,
722 		Cache_Server::TAG_NB_EP , MPI_COMM_WORLD , &req );
723 
724     // number of extern points signal :
725     MPI_Send ( &Cache_Server::NB_EP_SIGNAL , 1 , MPI_CHAR ,
726 	       npm1 , Cache_Server::TAG_SIGNAL , MPI_COMM_WORLD );
727 
728     // wait for the request:
729     MPI_Status status;
730     MPI_Wait ( &req , &status );
731   }
732 
733   return nb_client_extern_pts + nb_server_extern_pts;
734 }
735 
736 /*---------------------------------*/
737 /*    display the extern points    */
738 /*---------------------------------*/
display_extern_pts(const Display & out) const739 void Cache_Server::display_extern_pts ( const Display & out ) const {
740 
741   int npm1 = _np-1;
742 
743   // server:
744   // -------
745   if ( _rank == npm1 ) {
746 
747     list<const Eval_Point*>::const_iterator it;
748     out << endl << open_block ("Clients extern points");
749 
750     for ( int i = 0 ; i < npm1 ; ++i ) {
751       out.open_block ( "client #"+itos(i) );
752       for ( it  = _clients_ext_pts[i].begin() ;
753 	    it != _clients_ext_pts[i].end  () ;
754 	    ++it ) {
755 	out << "#" << (*it)->get_tag() << " ( ";
756 	(*it)->Point::display ( out );
757 	out << " ) " << " ["
758 	    << (*it)->get_bb_outputs() << " ] f="
759 	    << (*it)->get_f() << " h="
760 	    << (*it)->get_h() << endl;
761       }
762       out.close_block();
763     }
764   }
765 
766   // clients:
767   else {
768 
769     out << endl
770 	<< open_block ( "Process #" + itos(_rank) + ": extern points" );
771 
772     out << "number of points = "
773  	<< get_nb_extern_points() << endl;
774 
775     const Eval_Point * extern_pt = get_and_remove_extern_point();
776 
777     while ( extern_pt ) {
778 
779       out << "#" << extern_pt->get_tag() << " ( ";
780       extern_pt->Point::display ( out );
781       out << " ) " << " ["
782 	  << extern_pt->get_bb_outputs() << " ] f="
783 	  << extern_pt->get_f() << " h="
784 	  << extern_pt->get_h() << endl;
785 
786       extern_pt = get_and_remove_extern_point();
787     }
788   }
789   out << close_block() << endl;
790 }
791 
792 /*--------------------------------------*/
793 /*  update and display the best points  */
794 /*--------------------------------------*/
update_best_points(const Eval_Point & x,int source)795 void Cache_Server::update_best_points ( const Eval_Point & x      ,
796 					int                source   ) {
797   const Double & f = x.get_f();
798   const Double & h = x.get_h();
799 
800   if ( !f.is_defined() || !h.is_defined() )
801     return;
802 
803   int  i;
804   bool add_x = false;
805 
806   // feasible:
807   if ( h <= _h_min ) {
808 
809     // new best feasible point:
810     if ( !_bf || f < _bf->get_f() ) {
811       _bf   = &x;
812       add_x = true;
813       display_current_solution();
814     }
815   }
816 
817   // infeasible:
818   else {
819     if ( !_bi1 || h < _bi1->get_h() ) {
820       _bi1  = &x;
821       add_x = true;
822     }
823     if ( !_bi2 || f < _bi2->get_f() ) {
824       _bi2  = &x;
825       add_x = true;
826     }
827   }
828 
829   if ( add_x )
830     for ( i = 0 ; i < _np-1 ; ++i )
831       if ( i != source )
832 	_clients_ext_pts[i].push_front ( &x );
833 }
834 
835 /*-----------------------------------------*/
836 /*    display the current best solution    */
837 /*-----------------------------------------*/
display_current_solution(void) const838 void Cache_Server::display_current_solution ( void ) const {
839   if ( _rank != _np-1 || !_bf )
840     return;
841   if ( _debug )
842     _out << "CACHE SERVER: CURRENT SOLUTION: \t";
843   _out << _clock.get_real_time() << "\t"
844        << size() << "\t" << _bf->get_f() << endl;
845 }
846 
847 /*-------------------------------*/
848 /*    display the best points    */
849 /*-------------------------------*/
display_best_points(const Display & out) const850 void Cache_Server::display_best_points ( const Display & out ) const {
851   if ( _rank != _np-1 )
852     return;
853 
854   // display the last solution:
855   display_current_solution();
856 
857   // stats:
858   out << "evaluations: " << size()      << endl
859       << "cache hits : " << _cache_hits << endl;
860 
861   // best feasible solution:
862   out << "best feasible solution: ";
863   if ( _bf ) {
864     out << "x=( ";
865     _bf->Point::display(out);
866     out << " )"
867 	<< " F(x)=[ " << _bf->get_bb_outputs() << " ] h="
868 	<< _bf->get_h() << " f=" << _bf->get_f() << endl;
869   }
870   else {
871 
872     out << "NULL" << endl;
873 
874     // best infeasible solutions:
875     if ( _bi1 ) {
876       out << "best infeas. sol. #1  : x=( ";
877       _bi1->Point::display(out);
878       out << " )"
879 	  << " F(x)=[ " << _bi1->get_bb_outputs() << " ] h="
880 	  << _bi1->get_h() << " f=" << _bi1->get_f() << endl;
881     }
882 
883     if ( _bi2 && _bi2 != _bi1 ) {
884       out << "best infeas. sol. #2  : x=( ";
885       _bi2->Point::display(out);
886       out << " )"
887 	  << " F(x)=[ " << _bi2->get_bb_outputs() << " ] h="
888 	  << _bi2->get_h() << " f=" << _bi2->get_f() << endl;
889     }
890   }
891 }
892