1212import mpisppy .log
1313
1414from mpisppy .cylinders .spcommunicator import RecvArray , SPCommunicator
15+ from math import inf
1516
1617from mpisppy import global_toc
1718
1819from mpisppy .cylinders .spwindow import Field
1920
2021# Could also pass, e.g., sys.stdout instead of a filename
21- mpisppy .log .setup_logger (__name__ ,
22+ mpisppy .log .setup_logger ("mpisppy.cylinders.Hub" ,
2223 "hub.log" ,
2324 level = logging .CRITICAL )
24- logger = logging .getLogger (__name__ )
25+ logger = logging .getLogger ("mpisppy.cylinders.Hub" )
2526
2627class Hub (SPCommunicator ):
2728
2829 send_fields = (* SPCommunicator .send_fields , Field .SHUTDOWN , Field .BEST_OBJECTIVE_BOUNDS ,)
29- receive_fields = (* SPCommunicator .receive_fields ,)
30+ receive_fields = (* SPCommunicator .receive_fields , Field . OBJECTIVE_INNER_BOUND , Field . OBJECTIVE_OUTER_BOUND , )
3031
3132 _hub_algo_best_bound_provider = False
3233
@@ -36,11 +37,17 @@ def __init__(self, spbase_object, fullcomm, strata_comm, cylinder_comm, communic
3637 logger .debug (f"Built the hub object on global rank { fullcomm .Get_rank ()} " )
3738 # for logging
3839 self .print_init = True
40+ self .latest_ib_char = None
41+ self .latest_ob_char = None
42+ self .last_ib_idx = None
43+ self .last_ob_idx = None
3944 # for termination based on stalling out
4045 self .stalled_iter_cnt = 0
4146 self .last_outer_bound = self .BestOuterBound
4247 self .last_inner_bound = self .BestInnerBound
4348
49+ self .initialize_bound_values ()
50+
4451 return
4552
4653 @abc .abstractmethod
@@ -170,6 +177,72 @@ def hub_finalize(self):
170177 global_toc ("Statistics at termination" , True )
171178 self .screen_trace ()
172179
180+ def receive_innerbounds (self ):
181+ """ Get inner bounds from inner bound spokes
182+ NOTE: Does not check if there _are_ innerbound spokes
183+ (but should be harmless to call if there are none)
184+ """
185+ logging .debug ("Hub is trying to receive from InnerBounds" )
186+ for idx , cls , recv_buf in self .receive_field_spcomms [Field .OBJECTIVE_INNER_BOUND ]:
187+ is_new = self .get_receive_buffer (recv_buf , Field .OBJECTIVE_INNER_BOUND , idx )
188+ if is_new :
189+ bound = recv_buf [0 ]
190+ logging .debug ("!! new InnerBound to opt {}" .format (bound ))
191+ self .BestInnerBound = self .InnerBoundUpdate (bound , cls , idx )
192+ logging .debug ("ph back from InnerBounds" )
193+
194+ def receive_outerbounds (self ):
195+ """ Get outer bounds from outer bound spokes
196+ NOTE: Does not check if there _are_ outerbound spokes
197+ (but should be harmless to call if there are none)
198+ """
199+ logging .debug ("Hub is trying to receive from OuterBounds" )
200+ for idx , cls , recv_buf in self .receive_field_spcomms [Field .OBJECTIVE_OUTER_BOUND ]:
201+ is_new = self .get_receive_buffer (recv_buf , Field .OBJECTIVE_OUTER_BOUND , idx )
202+ if is_new :
203+ bound = recv_buf [0 ]
204+ logging .debug ("!! new OuterBound to opt {}" .format (bound ))
205+ self .BestOuterBound = self .OuterBoundUpdate (bound , cls , idx )
206+ logging .debug ("ph back from OuterBounds" )
207+
208+ def OuterBoundUpdate (self , new_bound , cls = None , idx = None , char = '*' ):
209+ current_bound = self .BestOuterBound
210+ if self ._outer_bound_update (new_bound , current_bound ):
211+ if cls is None :
212+ self .latest_ob_char = char
213+ self .last_ob_idx = 0
214+ else :
215+ self .latest_ob_char = cls .converger_spoke_char
216+ self .last_ob_idx = idx
217+ return new_bound
218+ else :
219+ return current_bound
220+
221+ def InnerBoundUpdate (self , new_bound , cls = None , idx = None , char = '*' ):
222+ current_bound = self .BestInnerBound
223+ if self ._inner_bound_update (new_bound , current_bound ):
224+ if cls is None :
225+ self .latest_ib_char = char
226+ self .last_ib_idx = 0
227+ else :
228+ self .latest_ib_char = cls .converger_spoke_char
229+ self .last_ib_idx = idx
230+ return new_bound
231+ else :
232+ return current_bound
233+
234+ def initialize_bound_values (self ):
235+ if self .opt .is_minimizing :
236+ self .BestInnerBound = inf
237+ self .BestOuterBound = - inf
238+ self ._inner_bound_update = lambda new , old : (new < old )
239+ self ._outer_bound_update = lambda new , old : (new > old )
240+ else :
241+ self .BestInnerBound = - inf
242+ self .BestOuterBound = inf
243+ self ._inner_bound_update = lambda new , old : (new > old )
244+ self ._outer_bound_update = lambda new , old : (new < old )
245+
173246 def _populate_boundsout_cache (self , buf ):
174247 """ Populate a given buffer with the current bounds
175248 """
@@ -221,7 +294,6 @@ def send_terminate(self):
221294 return
222295
223296 def sync_bounds (self ):
224- self .receive_nonant_bounds ()
225297 self .receive_outerbounds ()
226298 self .receive_innerbounds ()
227299 self .send_boundsout ()
0 commit comments