class SolverManager_Serial(AsynchronousSolverManager): def clear(self): """ Clear manager state """ super(SolverManager_Serial, self).clear() self.results = OrderedDict() def _perform_queue(self, ah, *args, **kwds): """ Perform the queue operation. This method returns the ActionHandle, and the ActionHandle status indicates whether the queue was successful. """ opt = kwds.pop('solver', kwds.pop('opt', None)) if opt is None: raise ActionManagerError( "No solver passed to %s, use keyword option 'solver'" % (type(self).__name__) ) time_start = time.time() if isinstance(opt, string_types): with pyomo.opt.SolverFactory(opt) as _opt: results = _opt.solve(*args, **kwds) else: results = opt.solve(*args, **kwds) results.pyomo_solve_time = time.time()-time_start self.results[ah.id] = results ah.status = ActionStatus.done self.event_handle[ah.id].update(ah) return ah def _perform_wait_any(self): """ Perform the wait_any operation. This method returns an ActionHandle with the results of waiting. If None is returned then the ActionManager assumes that it can call this method again. Note that an ActionHandle can be returned with a dummy value, to indicate an error. """ if len(self.results) > 0: ah_id, result = self.results.popitem(last=False) self.results[ah_id] = result return self.event_handle[ah_id] return ActionHandle(error=True, explanation=("No queued evaluations available in " "the 'serial' solver manager, which " "executes solvers synchronously"))
class PyroAsynchronousActionManager(AsynchronousActionManager): def __init__(self, host=None, port=None, verbose=0): self.host = host self.port = port self._verbose = verbose self._paused = False self._paused_task_dict = {} self._dispatcher_name_to_client = {} self._dispatcher_proxies = {} # map from task id to the corresponding action handle. # we only retain entries for tasks for which we expect # a result/response. self._last_extracted_ah_id = None super(PyroAsynchronousActionManager, self).__init__() # the list of cached results obtained from the dispatch server. # to avoid communication overhead, grab any/all results available, # and then cache them here - but return one-at-a-time via # the standard _perform_wait_any interface. the elements in this # list are simply tasks - at this point, we don't care about the # queue name associated with the task. self.results = OrderedDict() def clear(self): """ Clear manager state """ super(PyroAsynchronousActionManager, self).clear() self.results = OrderedDict() def close(self): """Close the manager.""" if len(self.results): print("WARNING: %s is closing with %s local " "results waiting to be processed." % (type(self).__name__, len(self.results))) if len(self._paused_task_dict): print("WARNING: %s is closing with %s paused " "tasks waiting to be queued." % (type(self).__name__, len(self._paused_task_dict))) self.results = OrderedDict() self._paused = False self._paused_task_dict = {} for client in self._dispatcher_name_to_client.values(): # the client will release the dispatcher proxy client.close() self._dispatcher_name_to_client = {} self._dispatcher_proxies = {} def pause(self): self._paused = True def unpause(self): self._paused = False if len(self._paused_task_dict): for dispatcher_name in self._paused_task_dict: client = self._dispatcher_name_to_client[dispatcher_name] client.add_tasks(self._paused_task_dict[dispatcher_name], verbose=self._verbose > 1) self._paused_task_dict = {} def get_results(self, ah): return self.results.pop(ah.id, None) def wait_all(self, *args): """ Wait for all actions to complete. The arguments to this method are expected to be ActionHandle objects or iterators that return ActionHandle objects. If no arguments are provided, then this method will terminate after all queued actions are complete. """ # Collect event handlers from the arguments ahs = self._flatten(*args) if len(ahs): while len(ahs) > 0: ahs.difference_update( [ah for ah in ahs if ah.id in self.results]) if len(ahs): self._download_results() else: while self.queued_action_counter > 0: self._download_results() def wait_any(self, *args): # Collect event handlers from the arguments ahs = self._flatten(*args) if len(ahs): while (1): for ah in ahs: if ah.id in self.results: return ah self._download_results() else: while len(self.results) == 0: self._download_results() ah_id, result = self.results.popitem(last=False) if ah_id == self._last_extracted_ah_id: self._last_extracted_ah_id = ah_id self._download_results() self.results[ah_id] = result ah_id, result = self.results.popitem(last=False) self.results[ah_id] = result return self.event_handle[ah_id] def wait_for(self, ah): """ Wait for the specified action to complete. """ while (1): if ah.id in self.results: break else: self._download_results() return self.get_results(ah) def _create_client(self, dispatcher=None): if dispatcher is None: client = pyu_pyro.Client(host=self.host, port=self.port) else: client = pyu_pyro.Client(dispatcher=dispatcher) if client.URI in self._dispatcher_name_to_client: self._dispatcher_name_to_client[client.URI].close() self._dispatcher_name_to_client[client.URI] = client return client # # Perform the queue operation. This method returns the # ActionHandle, and the ActionHandle status indicates whether # the queue was successful. # def _perform_queue(self, ah, *args, **kwds): queue_name = kwds.pop('queue_name', None) generate_response = kwds.pop('generate_response', True) dispatcher_name = self._get_dispatcher_name(queue_name) task_data = self._get_task_data(ah, *args, **kwds) task = pyu_pyro.Task(data=task_data, id=ah.id, generateResponse=generate_response) if self._paused: if dispatcher_name not in self._paused_task_dict: self._paused_task_dict[dispatcher_name] = dict() if queue_name not in self._paused_task_dict[dispatcher_name]: self._paused_task_dict[dispatcher_name][queue_name] = [] self._paused_task_dict[dispatcher_name][queue_name].append(task) else: client = self._dispatcher_name_to_client[dispatcher_name] client.add_task(task, verbose=self._verbose > 1, override_type=queue_name) # only populate the action_handle-to-task dictionary is a # response is expected. if not generate_response: ah.status = ActionStatus.done self.event_handle[ah.id].update(ah) self.queued_action_counter -= 1 return ah # # Abstract Methods # def _get_dispatcher_name(self, queue_name): raise NotImplementedError( type(self).__name__ + ": This method is abstract") def _get_task_data(self, ah, **kwds): raise NotImplementedError( type(self).__name__ + ": This method is abstract") def _download_results(self): raise NotImplementedError( type(self).__name__ + ": This method is abstract")