Пример #1
0
 def __init__(self, comm):
     assert comm.size > 1
     import mpi4py.MPI
     assert mpi4py.MPI.Is_initialized()
     super(DispatcherDistributed, self).__init__()
     self.clock = mpi4py.MPI.Wtime
     self.comm = comm
     # send rank of dispatcher to all workers
     self.dispatcher_rank = DispatcherProxy._init(self.comm,
                                                  ProcessType.dispatcher)
     assert self.dispatcher_rank == self.comm.rank
     self.worker_ranks = [
         i for i in range(self.comm.size) if i != self.comm.rank
     ]
     self.needs_work_queue = \
         collections.deque([],
                           len(self.worker_ranks))
     self._solve_info_by_source = \
         {i: _SolveInfo() for i in self.worker_ranks}
     self.last_known_bound = dict()
     self.external_bounds = SortedList()
     self.first_update = \
         {_r: True for _r in self.worker_ranks}
     self.has_work = set()
     self._send_requests = None
     self.explored_nodes_count = 0
Пример #2
0
 def __init__(self):
     super(DispatcherLocal, self).__init__()
     self.external_bound = None
     self.solve_info = _SolveInfo()
     self.first_update = None
     self.active_nodes = 0
     self.clock = time.time
Пример #3
0
 def update(self, best_objective, best_node, previous_bound, solve_info,
            node_list_):
     """A proxy to :func:`pybnb.dispatcher.Dispatcher.update`."""
     if best_node is not None:
         best_node = _SerializedNode.to_slots(best_node)
     node_list = []
     for node_ in node_list_:
         # make sure the user-defined queue_priority
         # can be safely marshaled
         assert (node_.queue_priority is None) or \
             node_.queue_priority == marshal.loads(
                 marshal.dumps(node_.queue_priority,
                               config.MARSHAL_PROTOCOL_VERSION))
         node_list.append(_SerializedNode.to_slots(node_))
     data = marshal.dumps((best_objective, best_node, previous_bound,
                           solve_info.data, node_list),
                          config.MARSHAL_PROTOCOL_VERSION)
     self.comm.Send([data, mpi4py.MPI.BYTE],
                    self.dispatcher_rank,
                    tag=DispatcherAction.update)
     self.comm.Probe(status=self._status)
     assert not self._status.Get_error()
     tag = self._status.Get_tag()
     recv_size = self._status.Get_count(mpi4py.MPI.BYTE)
     data = bytearray(recv_size)
     recv_data(self.comm, self._status, datatype=mpi4py.MPI.BYTE, out=data)
     if tag == DispatcherResponse.nowork:
         if six.PY2:
             data_ = str(data)
         else:
             data_ = data
         (best_objective, best_node_slots, global_bound,
          termination_condition_int, solve_info_data) = marshal.loads(data_)
         best_node = None
         if best_node_slots is not None:
             best_node = _SerializedNode.restore_node(best_node_slots)
         solve_info = _SolveInfo()
         solve_info.data = array.array('d', solve_info_data)
         return (True, best_objective, best_node,
                 (global_bound,
                  _int_to_termination_condition[termination_condition_int],
                  solve_info))
     else:
         assert tag == DispatcherResponse.work
         if six.PY2:
             data_ = str(data)
         else:
             data_ = data
         (best_objective, best_node_slots,
          node_slots) = marshal.loads(data_)
         best_node = None
         if best_node_slots is not None:
             best_node = _SerializedNode.restore_node(best_node_slots)
         node = _SerializedNode.restore_node(node_slots)
         return False, best_objective, best_node, node
Пример #4
0
 def test_add_from(self):
     info = _SolveInfo()
     info.explored_nodes_count = 1
     info.total_queue_time = 2
     info.queue_call_count = 3
     info.total_objective_time = 4
     info.objective_call_count = 5
     info.total_bound_time = 6
     info.bound_call_count = 7
     info.total_branch_time = 8
     info.branch_call_count = 9
     info.total_load_state_time = 10
     info.load_state_call_count = 11
     info1 = _SolveInfo()
     info1.explored_nodes_count = -2
     info1.total_queue_time = -3
     info1.queue_call_count = -4
     info1.total_objective_time = -5
     info1.objective_call_count = -6
     info1.total_bound_time = -7
     info1.bound_call_count = -8
     info1.total_branch_time = -9
     info1.branch_call_count = -10
     info1.total_load_state_time = -11
     info1.load_state_call_count = -12
     info.add_from(info1)
     assert info.explored_nodes_count  == -1
     assert info.total_queue_time  == -1
     assert info.queue_call_count  == -1
     assert info.total_objective_time  == -1
     assert info.objective_call_count  == -1
     assert info.total_bound_time  == -1
     assert info.bound_call_count  == -1
     assert info.total_branch_time  == -1
     assert info.branch_call_count  == -1
     assert info.total_load_state_time  == -1
     assert info.load_state_call_count  == -1
     with pytest.raises(TypeError):
         info.add_from(1)
Пример #5
0
    def update(self,
               best_objective,
               previous_bound,
               solve_info,
               node_data_list):
        """A proxy to :func:`pybnb.dispatcher.Dispatcher.update`."""
        size = 3 + _SolveInfo._data_size
        node_count = len(node_data_list)
        if node_count > 0:
            for node_data_ in node_data_list:
                size += 1
                size += len(node_data_)
        if (self._update_buffer is None) or \
           len(self._update_buffer) < size:
            self._update_buffer = numpy.empty(size, dtype=float)
        data = self._update_buffer
        data[0] = best_objective
        assert float(data[0]) == best_objective
        data[1] = previous_bound
        assert float(data[1]) == previous_bound
        data[2] = node_count
        assert data[2] == node_count
        assert int(data[2]) == int(node_count)
        data[3:(_SolveInfo._data_size)+3] = solve_info.data
        if node_count > 0:
            pos = _SolveInfo._data_size+3
            for node_data in node_data_list:
                data[pos] = len(node_data)
                pos += 1
                data[pos:pos+len(node_data)] = node_data
                pos += len(node_data)

        self.comm.Send([data,mpi4py.MPI.DOUBLE],
                       self.dispatcher_rank,
                       tag=DispatcherAction.update)
        self.comm.Probe(status=self._status)
        assert not self._status.Get_error()
        tag = self._status.Get_tag()
        if tag == DispatcherResponse.nowork:
            data = recv_data(self.comm, self._status)
            best_objective = float(data[0])
            global_bound = float(data[1])
            termination_condition = \
                _int_to_termination_condition[int(data[2])]
            solve_info = _SolveInfo()
            solve_info.data[:] = data[3:]
            return (True,
                    best_objective,
                    (global_bound,
                     termination_condition,
                     solve_info))
        else:
            assert tag == DispatcherResponse.work
            recv_size = self._status.Get_count(mpi4py.MPI.DOUBLE)
            if len(self._update_buffer) < recv_size:
                self._update_buffer = numpy.empty(recv_size, dtype=float)
            # Note that this function returns a node data
            # array that is a view on its own update
            # buffer. Thus, it assumes that the caller is no
            # longer using the node data view that was
            # returned when the next update is called
            # (because it will be corrupted).
            data = self._update_buffer[:recv_size]
            recv_data(self.comm,
                      self._status,
                      datatype=mpi4py.MPI.DOUBLE,
                      out=data)
            best_objective = Node._extract_best_objective(data)
            return False, best_objective, data
Пример #6
0
 def test_methods(self):
     info = _SolveInfo()
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.explored_nodes_count += 1
     assert info.explored_nodes_count == 1
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info._increment_explored_nodes_stat(2)
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.total_queue_time += 1.5
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 1.5
     assert info.queue_call_count == 0
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.queue_call_count += 1
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 1.5
     assert info.queue_call_count == 1
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info._increment_queue_stat(2.0, 2)
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.total_objective_time += 1.5
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 1.5
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.objective_call_count += 1
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 1.5
     assert info.objective_call_count == 1
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info._increment_objective_stat(2.0, 2)
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.total_bound_time += 1.5
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 1.5
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.bound_call_count += 1
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 1.5
     assert info.bound_call_count == 1
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info._increment_bound_stat(2.0, 2)
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 3.5
     assert info.bound_call_count == 3
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.total_branch_time += 1.5
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 3.5
     assert info.bound_call_count == 3
     assert info.total_branch_time == 1.5
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.branch_call_count += 1
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 3.5
     assert info.bound_call_count == 3
     assert info.total_branch_time == 1.5
     assert info.branch_call_count == 1
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info._increment_branch_stat(2.0, 2)
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 3.5
     assert info.bound_call_count == 3
     assert info.total_branch_time == 3.5
     assert info.branch_call_count == 3
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     info.total_load_state_time += 1.5
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 3.5
     assert info.bound_call_count == 3
     assert info.total_branch_time == 3.5
     assert info.branch_call_count == 3
     assert info.total_load_state_time == 1.5
     assert info.load_state_call_count == 0
     info.load_state_call_count += 1
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 3.5
     assert info.bound_call_count == 3
     assert info.total_branch_time == 3.5
     assert info.branch_call_count == 3
     assert info.total_load_state_time == 1.5
     assert info.load_state_call_count == 1
     info._increment_load_state_stat(2.0, 2)
     assert info.explored_nodes_count == 3
     assert info.total_queue_time == 3.5
     assert info.queue_call_count == 3
     assert info.total_objective_time == 3.5
     assert info.objective_call_count == 3
     assert info.total_bound_time == 3.5
     assert info.bound_call_count == 3
     assert info.total_branch_time == 3.5
     assert info.branch_call_count == 3
     assert info.total_load_state_time == 3.5
     assert info.load_state_call_count == 3
     info.reset()
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
Пример #7
0
 def test__SimpleSolveInfoCollector(self):
     class Junk(Problem):
         def __init__(self):
             self.d = {}
             self.d['sense'] = False
             self.d['objective'] = False
             self.d['bound'] = False
             self.d['save_state'] = False
             self.d['load_state'] = False
             self.d['branch'] = False
             self.d['notify_solve_begins'] = False
             self.d['notify_new_best_node'] = False
             self.d['notify_solve_finished'] = False
         def sense(self):
             self.d['sense'] = True
             return -1
         def objective(self):
             time.sleep(0.01)
             self.d['objective'] = True
             return -2
         def bound(self):
             time.sleep(0.01)
             self.d['bound'] = True
             return -3
         def save_state(self, node):
             self.d['save_state'] = True
         def load_state(self, node):
             time.sleep(0.01)
             self.d['load_state'] = True
         def branch(self):
             time.sleep(0.01)
             self.d['branch'] = True
             return ()
         def notify_solve_begins(self,
                                   comm,
                                   worker_comm,
                                   convergence_checker):
             self.d['notify_solve_begins'] = True
         def notify_new_best_node(self,
                                  node,
                                  current):
             self.d['notify_new_best_node'] = True
         def notify_solve_finished(self,
                                   comm,
                                   worker_comm,
                                   results):
             self.d['notify_solve_finished'] = True
     j = Junk()
     assert j.d['sense'] == False
     assert j.d['objective'] == False
     assert j.d['bound'] == False
     assert j.d['save_state'] == False
     assert j.d['load_state'] == False
     assert j.d['branch'] == False
     assert j.d['notify_solve_begins'] == False
     assert j.d['notify_new_best_node'] == False
     assert j.d['notify_solve_finished'] == False
     p = _SimpleSolveInfoCollector(j)
     p.set_clock(time.time)
     info = _SolveInfo()
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     p.set_solve_info_object(info)
     assert j.d['sense'] == False
     assert j.d['objective'] == False
     assert j.d['bound'] == False
     assert j.d['save_state'] == False
     assert j.d['load_state'] == False
     assert j.d['branch'] == False
     assert j.d['notify_solve_begins'] == False
     assert j.d['notify_new_best_node'] == False
     assert j.d['notify_solve_finished'] == False
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     p.sense()
     assert j.d['sense'] == True
     assert j.d['objective'] == False
     assert j.d['bound'] == False
     assert j.d['save_state'] == False
     assert j.d['load_state'] == False
     assert j.d['branch'] == False
     assert j.d['notify_solve_begins'] == False
     assert j.d['notify_new_best_node'] == False
     assert j.d['notify_solve_finished'] == False
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time == 0
     assert info.objective_call_count == 0
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     p.objective()
     assert j.d['sense'] == True
     assert j.d['objective'] == True
     assert j.d['bound'] == False
     assert j.d['save_state'] == False
     assert j.d['load_state'] == False
     assert j.d['branch'] == False
     assert j.d['notify_solve_begins'] == False
     assert j.d['notify_new_best_node'] == False
     assert j.d['notify_solve_finished'] == False
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time > 0
     assert info.objective_call_count == 1
     assert info.total_bound_time == 0
     assert info.bound_call_count == 0
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     p.bound()
     assert j.d['sense'] == True
     assert j.d['objective'] == True
     assert j.d['bound'] == True
     assert j.d['save_state'] == False
     assert j.d['load_state'] == False
     assert j.d['branch'] == False
     assert j.d['notify_solve_begins'] == False
     assert j.d['notify_new_best_node'] == False
     assert j.d['notify_solve_finished'] == False
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time > 0
     assert info.objective_call_count == 1
     assert info.total_bound_time > 0
     assert info.bound_call_count == 1
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     p.save_state(None)
     assert j.d['sense'] == True
     assert j.d['objective'] == True
     assert j.d['bound'] == True
     assert j.d['save_state'] == True
     assert j.d['load_state'] == False
     assert j.d['branch'] == False
     assert j.d['notify_solve_begins'] == False
     assert j.d['notify_new_best_node'] == False
     assert j.d['notify_solve_finished'] == False
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time > 0
     assert info.objective_call_count == 1
     assert info.total_bound_time > 0
     assert info.bound_call_count == 1
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time == 0
     assert info.load_state_call_count == 0
     p.load_state(None)
     assert j.d['sense'] == True
     assert j.d['objective'] == True
     assert j.d['bound'] == True
     assert j.d['save_state'] == True
     assert j.d['load_state'] == True
     assert j.d['branch'] == False
     assert j.d['notify_solve_begins'] == False
     assert j.d['notify_new_best_node'] == False
     assert j.d['notify_solve_finished'] == False
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time > 0
     assert info.objective_call_count == 1
     assert info.total_bound_time > 0
     assert info.bound_call_count == 1
     assert info.total_branch_time == 0
     assert info.branch_call_count == 0
     assert info.total_load_state_time > 0
     assert info.load_state_call_count == 1
     list(p.branch())
     assert j.d['sense'] == True
     assert j.d['objective'] == True
     assert j.d['bound'] == True
     assert j.d['save_state'] == True
     assert j.d['load_state'] == True
     assert j.d['branch'] == True
     assert j.d['notify_solve_begins'] == False
     assert j.d['notify_new_best_node'] == False
     assert j.d['notify_solve_finished'] == False
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time > 0
     assert info.objective_call_count == 1
     assert info.total_bound_time > 0
     assert info.bound_call_count == 1
     assert info.total_branch_time > 0
     assert info.branch_call_count == 1
     assert info.total_load_state_time > 0
     assert info.load_state_call_count == 1
     p.notify_solve_begins(None, None, None)
     assert j.d['sense'] == True
     assert j.d['objective'] == True
     assert j.d['bound'] == True
     assert j.d['save_state'] == True
     assert j.d['load_state'] == True
     assert j.d['branch'] == True
     assert j.d['notify_solve_begins'] == True
     assert j.d['notify_new_best_node'] == False
     assert j.d['notify_solve_finished'] == False
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time > 0
     assert info.objective_call_count == 1
     assert info.total_bound_time > 0
     assert info.bound_call_count == 1
     assert info.total_branch_time > 0
     assert info.branch_call_count == 1
     assert info.total_load_state_time > 0
     assert info.load_state_call_count == 1
     p.notify_new_best_node(None, None)
     assert j.d['sense'] == True
     assert j.d['objective'] == True
     assert j.d['bound'] == True
     assert j.d['save_state'] == True
     assert j.d['load_state'] == True
     assert j.d['branch'] == True
     assert j.d['notify_solve_begins'] == True
     assert j.d['notify_new_best_node'] == True
     assert j.d['notify_solve_finished'] == False
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time > 0
     assert info.objective_call_count == 1
     assert info.total_bound_time > 0
     assert info.bound_call_count == 1
     assert info.total_branch_time > 0
     assert info.branch_call_count == 1
     assert info.total_load_state_time > 0
     assert info.load_state_call_count == 1
     p.notify_solve_finished(None, None, None)
     assert j.d['sense'] == True
     assert j.d['objective'] == True
     assert j.d['bound'] == True
     assert j.d['save_state'] == True
     assert j.d['load_state'] == True
     assert j.d['branch'] == True
     assert j.d['notify_solve_begins'] == True
     assert j.d['notify_new_best_node'] == True
     assert j.d['notify_solve_finished'] == True
     assert info.explored_nodes_count == 0
     assert info.total_queue_time == 0
     assert info.queue_call_count == 0
     assert info.total_objective_time > 0
     assert info.objective_call_count == 1
     assert info.total_bound_time > 0
     assert info.bound_call_count == 1
     assert info.total_branch_time > 0
     assert info.branch_call_count == 1
     assert info.total_load_state_time > 0
     assert info.load_state_call_count == 1
Пример #8
0
 def _get_final_solve_info(self):
     solve_info = _SolveInfo()
     for worker_solve_info in self._solve_info_by_source.values():
         solve_info.add_from(worker_solve_info)
     return solve_info
Пример #9
0
 def _get_final_solve_info(self):
     """Get the final solve information"""
     solve_info = _SolveInfo()
     solve_info.data[:] = self.solve_info.data
     return solve_info
Пример #10
0
    def serve(self):
        """Start listening for distributed branch-and-bound
        commands and map them to commands in the local
        dispatcher interface."""

        def rebuild_update_requests(size):
            update_requests = {}
            update_data = bytearray(size)
            for i in self.worker_ranks:
                update_requests[i] = self.comm.Recv_init(
                    update_data, source=i, tag=DispatcherAction.update
                )
            return update_requests, update_data

        update_requests = None
        solve_info_ = _SolveInfo()
        data = None
        msg = Message(self.comm)
        while 1:
            msg.probe()
            tag = msg.tag
            source = msg.source
            if tag == DispatcherAction.update:
                size = msg.status.Get_count(datatype=mpi4py.MPI.BYTE)
                if (data is None) or (len(data) < size):
                    update_requests, data = rebuild_update_requests(size)
                req = update_requests[msg.status.Get_source()]
                req.Start()
                req.Wait()
                if six.PY2:
                    data_ = str(data)
                else:
                    data_ = data
                (
                    best_objective,
                    best_node,
                    terminal_bound,
                    solve_info_data,
                    node_list,
                ) = marshal.loads(data_)
                solve_info_.data = array.array("d", solve_info_data)
                if best_node is not None:
                    best_node = _SerializedNode(best_node)
                node_list = [_SerializedNode(state) for state in node_list]
                ret = self.update(
                    best_objective,
                    best_node,
                    terminal_bound,
                    solve_info_,
                    node_list,
                    source,
                )
                stop = ret[0]
                if stop:
                    best_node = ret[2]
                    if best_node is not None:
                        best_node = _SerializedNode.restore_node(best_node.slots)
                    return (
                        ret[1],  # best_objective
                        best_node,
                        ret[3][0],  # global_bound
                        ret[3][1],  # termination_condition
                        ret[3][2],
                    )  # global_solve_info
            elif tag == DispatcherAction.log_info:
                msg.recv(mpi4py.MPI.CHAR)
                self.log_info(msg.data)
            elif tag == DispatcherAction.log_warning:
                msg.recv(mpi4py.MPI.CHAR)
                self.log_warning(msg.data)
            elif tag == DispatcherAction.log_debug:
                msg.recv(mpi4py.MPI.CHAR)
                self.log_debug(msg.data)
            elif tag == DispatcherAction.log_error:
                msg.recv(mpi4py.MPI.CHAR)
                self.log_error(msg.data)
            elif tag == DispatcherAction.log_critical:
                msg.recv(mpi4py.MPI.CHAR)
                self.log_critical(msg.data)
            elif tag == DispatcherAction.stop_listen:
                msg.recv()
                assert msg.data is None
                return (None, None, None, None, None)
            else:  # pragma:nocover
                raise RuntimeError(
                    "Dispatcher received invalid "
                    "message tag '%s' from rank '%s'" % (tag, source)
                )
Пример #11
0
    def serve(self):
        """Start listening for distributed branch-and-bound
        commands and map them to commands in the local
        dispatcher interface."""
        def rebuild_update_requests(size):
            update_requests = {}
            # Note: The code below relies on the fact that
            #       this is an array.array type and _not_ a
            #       numpy.array type. It issumes a copy of
            #       the data is made when a slice is
            #       created.
            update_data = array.array('d', [0]) * size
            for i in self.worker_ranks:
                update_requests[i] = self.comm.Recv_init(
                    update_data, source=i, tag=DispatcherAction.update)
            return update_requests, update_data

        update_requests = None
        data = None
        solve_info_ = _SolveInfo()
        msg = Message(self.comm)
        while (1):
            msg.probe()
            tag = msg.tag
            source = msg.source
            if tag == DispatcherAction.update:
                size = msg.status.Get_count(datatype=mpi4py.MPI.DOUBLE)
                if (data is None) or \
                   (len(data) < size):
                    update_requests, data = \
                        rebuild_update_requests(size)
                req = update_requests[msg.status.Get_source()]
                req.Start()
                req.Wait()
                best_objective = float(data[0])
                previous_bound = float(data[1])
                assert int(data[2]) == data[2]
                nodes_receiving_count = int(data[2])
                solve_info_.data[:] = data[3:(_SolveInfo._data_size + 3)]
                if nodes_receiving_count > 0:
                    pos = 3 + _SolveInfo._data_size
                    node_data_list = []
                    for i in range(nodes_receiving_count):
                        assert int(data[pos]) == data[pos]
                        data_size = int(data[pos])
                        pos += 1
                        node_data_list.append(data[pos:pos + data_size])
                        pos += data_size
                else:
                    node_data_list = ()
                ret = self.update(best_objective, previous_bound, solve_info_,
                                  node_data_list, source)
                stop = ret[0]
                if stop:
                    return (
                        ret[1],  # best_objective
                        ret[2][0],  # global_bound
                        ret[2][1],  # termination_condition
                        ret[2][2])  # global_solve_info
            elif tag == DispatcherAction.log_info:
                msg.recv(mpi4py.MPI.CHAR)
                self.log_info(msg.data)
            elif tag == DispatcherAction.log_warning:
                msg.recv(mpi4py.MPI.CHAR)
                self.log_warning(msg.data)
            elif tag == DispatcherAction.log_debug:
                msg.recv(mpi4py.MPI.CHAR)
                self.log_debug(msg.data)
            elif tag == DispatcherAction.log_error:
                msg.recv(mpi4py.MPI.CHAR)
                self.log_error(msg.data)
            elif tag == DispatcherAction.stop_listen:
                msg.recv()
                assert msg.data is None
                return (None, None, None, None)
            else:  #pragma:nocover
                raise RuntimeError("Dispatcher received invalid "
                                   "message tag '%s' from rank '%s'" %
                                   (tag, source))
Пример #12
0
 def __init__(self,
              comm=_notset,
              dispatcher_rank=0):
     mpi = True
     if comm is None:
         mpi = False
     self._comm = None
     self._worker_flag = None
     self._dispatcher_flag = None
     self._disp = None
     self._time = None
     if mpi:
         import mpi4py.MPI
         assert mpi4py.MPI.Is_initialized()
         assert comm is not None
         if comm is _notset:
             comm = mpi4py.MPI.COMM_WORLD
         if (int(dispatcher_rank) != dispatcher_rank) or \
            (dispatcher_rank < 0) or \
            (dispatcher_rank >= comm.size):
             raise ValueError("The 'dispatcher_rank' keyword "
                              "has been set to %s, which is not "
                              "an available rank given the "
                              "size of the MPI communicator (%d)."
                              % (dispatcher_rank, comm.size))
         self._comm = comm
         if comm.size > 1:
             dispatcher_rank = int(dispatcher_rank)
             if comm.rank == dispatcher_rank:
                 self._disp = DispatcherDistributed(comm)
                 self._worker_flag = False
                 self._dispatcher_flag = True
             else:
                 self._disp = DispatcherProxy(comm)
                 self._worker_flag = True
                 self._dispatcher_flag = False
         else:
             self._disp = DispatcherLocal()
             self._worker_flag = True
             self._dispatcher_flag = True
         self._time = mpi4py.MPI.Wtime
     else:
         if dispatcher_rank != 0:
             raise ValueError(
                 "MPI functionality has been disabled but "
                 "the 'dispatcher_rank' keyword is set to "
                 "something other than 0.")
         assert self._comm is None
         self._disp = DispatcherLocal()
         self._worker_flag = True
         self._dispatcher_flag = True
         self._time = time.time
     assert self._worker_flag in (True, False)
     assert self._dispatcher_flag in (True, False)
     assert self._disp is not None
     assert self._time is not None
     self._solve_start = None
     self._wall_time = 0.0
     self._best_objective = None
     self._local_solve_info = _SolveInfo()
     self._global_solve_info = None