Пример #1
0
    def put_get(self, item):
        if self._queue.size() > 0:
            cnt_next, tmp_ = self._queue.next()
            assert type(cnt_next) is int
            if self._queue.requires_priority:
                if not Node._has_queue_priority(item):
                    raise ValueError("A node queue priority is required")
                priority = Node._extract_queue_priority(item)
                cnt, item_ = self._queue.put_get(item, priority)
            else:
                cnt, item_ = self._queue.put_get(item)
            if item_ is not item:
                assert item_ is tmp_
                bound = Node._extract_bound(item)
                assert not math.isnan(bound)
                bound_ = Node._extract_bound(item_)
                assert not math.isnan(bound_)
                if self._sense == maximize:
                    self._sorted_by_bound.add((-bound, cnt, item))
                    self._sorted_by_bound.remove((-bound_, cnt_next, item_))
                else:
                    self._sorted_by_bound.add((bound, cnt, item))
                    self._sorted_by_bound.remove((bound_, cnt_next, item_))
        else:
            if self._queue.requires_priority:
                if not Node._has_queue_priority(item):
                    raise ValueError("A node queue priority is required")
                priority = Node._extract_queue_priority(item)
                cnt, item_ = self._queue.put_get(item, priority)
            else:
                cnt, item_ = self._queue.put_get(item)

        return cnt, item_
Пример #2
0
 def test_usage_maximize(self):
     q = WorstBoundFirstPriorityQueue(maximize)
     assert q.size() == 0
     assert q.bound() is None
     assert len(list(q.items())) == 0
     assert q.get() is None
     items = []
     for i in range(1, 11):
         node = Node(size=0)
         node.bound = -i
         assert node.queue_priority is None
         cnt_ = q.put(node._data)
         assert cnt_ == i - 1
         assert node.queue_priority == node.bound
         items.append(node._data)
         assert q.size() == i
         assert q.bound() == -1
         _check_items(q, items)
     assert q.size() == 10
     assert q.bound() == -1
     removed = q.filter(lambda data: \
                        Node._extract_bound(data) <= -5)
     assert q.size() == 6
     assert len(removed) == 4
     for data in removed:
         assert Node._extract_bound(data) > -5
     assert q.bound() == -5
     for i in range(5, 11):
         node = Node(data_=q.get())
         assert node.bound == -i
         assert node.queue_priority == node.bound
         if i != 10:
             assert q.bound() == -i - 1
         else:
             assert q.bound() is None
     assert q.size() == 0
     node = Node(size=0)
     node.bound = 1
     assert node.queue_priority is None
     cnt_, data = q.put_get(node._data)
     assert cnt_ == 10
     assert data is node._data
     assert node.queue_priority == 1
     node.bound = 2
     cnt_ = q.put(node._data)
     assert node.queue_priority == 2
     assert cnt_ == 11
     node2 = Node(size=0)
     node2.bound = 3
     assert node2.queue_priority is None
     cnt_, data = q.put_get(node2._data)
     assert cnt_ == 12
     assert data is node2._data
     assert node2.queue_priority == 3
     node2.bound = 1
     cnt_, data = q.put_get(node2._data)
     assert node2.queue_priority == 1
     assert cnt_ == 13
     assert data is node._data
     assert q.size() == 1
Пример #3
0
 def _get_work_to_send(self, dest):
     node_data = self._get_work_item()
     bound = Node._extract_bound(node_data)
     self.last_known_bound[dest] = bound
     self.external_bounds.add(bound)
     self.has_work.add(dest)
     return node_data
Пример #4
0
 def put_get(self, item):
     bound = Node._extract_bound(item)
     if self._sense == minimize:
         priority = -bound
     else:
         priority = bound
     Node._insert_queue_priority(item, priority)
     return self._queue.put_get(item, priority)
Пример #5
0
 def _get_gap(self, item):
     objective = Node._extract_objective(item)
     bound = Node._extract_bound(item)
     if self._sense == minimize:
         gap = objective - bound
     else:
         gap = bound - objective
     assert not math.isnan(gap)
     return gap
Пример #6
0
 def filter(self, func):
     removed = []
     for cnt, item in self._queue.filter(func, include_counters=True):
         removed.append(item)
         bound = Node._extract_bound(item)
         if self._sense == maximize:
             self._sorted_by_bound.remove((-bound, cnt, item))
         else:
             self._sorted_by_bound.remove((bound, cnt, item))
     return removed
Пример #7
0
 def get(self):
     if self._queue.size() > 0:
         cnt, tmp_ = self._queue.next()
         assert type(cnt) is int
         item = self._queue.get()
         assert tmp_ is item
         bound = Node._extract_bound(item)
         if self._sense == maximize:
             self._sorted_by_bound.remove((-bound, cnt, item))
         else:
             self._sorted_by_bound.remove((bound, cnt, item))
         return item
     else:
         return None
Пример #8
0
 def put(self, item):
     bound = Node._extract_bound(item)
     assert not math.isnan(bound)
     if self._queue.requires_priority:
         if not Node._has_queue_priority(item):
             raise ValueError("A node queue priority is required")
         priority = Node._extract_queue_priority(item)
         cnt = self._queue.put(item, priority)
     else:
         cnt = self._queue.put(item)
     if self._sense == maximize:
         self._sorted_by_bound.add((-bound, cnt, item))
     else:
         self._sorted_by_bound.add((bound, cnt, item))
     return cnt
Пример #9
0
 def _check_update_best_objective(self, objective):
     updated = False
     if self.converger.objective_improved(objective, self.best_objective):
         updated = True
         if self.journalist is not None:
             self.journalist.new_objective(report=self.log_new_incumbent)
         self.best_objective = objective
         eligible_for_queue_ = self.converger.eligible_for_queue
         extract_bound_ = Node._extract_bound
         removed = self.queue.filter(lambda node_data_: eligible_for_queue_(
             extract_bound_(node_data_), objective))
         for node_data in removed:
             self._check_update_worst_terminal_bound(
                 Node._extract_bound(node_data))
     return updated
Пример #10
0
 def _add_work_to_queue(self, node_data, set_tree_id=True):
     if set_tree_id:
         assert not Node._has_tree_id(node_data)
         Node._insert_tree_id(node_data, self.next_tree_id)
         self.next_tree_id += 1
     else:
         assert Node._has_tree_id(node_data)
         assert Node._extract_tree_id(node_data) < self.next_tree_id
     bound = Node._extract_bound(node_data)
     if self.converger.eligible_for_queue(bound, self.best_objective):
         self.queue.put(node_data)
         return True
     else:
         self._check_update_worst_terminal_bound(bound)
         return False
Пример #11
0
 def test_usage_minimize(self):
     q = CustomPriorityQueue(minimize)
     assert q.size() == 0
     assert q.bound() is None
     assert len(list(q.items())) == 0
     assert q.get() is None
     items = []
     for i in range(1, 11):
         node = Node(size=0)
         node.bound = i
         node.queue_priority = -i
         assert q.put(node._data) == i - 1
         assert node.queue_priority == -i
         items.append(node._data)
         assert q.size() == i
         assert q.bound() == 1
         _check_items(q, items)
     assert q.size() == 10
     assert q.bound() == 1
     removed = q.filter(lambda data: \
                        Node._extract_bound(data) >= 5)
     assert q.size() == 6
     assert len(removed) == 4
     for data in removed:
         assert Node._extract_bound(data) < 5
     assert q.bound() == 5
     for i in range(5, 11):
         node = Node(data_=q.get())
         assert node.bound == i
         assert node.queue_priority == -i
         if i != 10:
             assert q.bound() == i + 1
         else:
             assert q.bound() is None
     assert q.size() == 0
     node = Node(size=0)
     node.bound = 0
     node.queue_priority = 1
     cnt_, data = q.put_get(node._data)
     assert cnt_ == 10
     assert data is node._data
     assert node.queue_priority == 1
     assert q.bound() is None
     node.queue_priority = 2
     cnt_ = q.put(node._data)
     assert node.queue_priority == 2
     assert cnt_ == 11
     assert q.bound() == 0
     node2 = Node(size=0)
     node2.bound = 1
     node2.queue_priority = 3
     cnt_, data = q.put_get(node2._data)
     assert cnt_ == 12
     assert data is node2._data
     assert node2.queue_priority == 3
     assert q.bound() == 0
     node2.queue_priority = 1
     cnt_, data = q.put_get(node2._data)
     assert node2.queue_priority == 1
     assert cnt_ == 13
     assert data is node._data
     assert q.size() == 1
     assert q.bound() == 1
Пример #12
0
 def bound(self):
     try:
         return Node._extract_bound(self._sorted_by_bound[0][2])
     except IndexError:
         return None
Пример #13
0
 def bound(self):
     try:
         return Node._extract_bound(self._queue.next()[1])
     except IndexError:
         return None
Пример #14
0
    def update(self, best_objective, previous_bound, solve_info,
               node_data_list):
        """Update local worker information.

        Parameters
        ----------
        best_objective : float
            The current best objective value known to the
            worker.
        previous_bound : float
            The updated bound computed for the last node
            that was processed by the worker.
        solve_info : :class:`_SolveInfo`
            The most up-to-date worker solve information.
        node_data_list : list
            A list of node data arrays to add to the queue.

        Returns
        -------
        solve_finished : bool
            Indicates if the dispatcher has terminated the solve.
        new_objective : float
            The best objective value known to the dispatcher.
        data : ``array.array`` or None
            If solve_finished is false, a data array
            representing a new node for the worker to
            process. Otherwise, a tuple containing the
            global bound, the termination condition string,
            and the number of explored nodes.
        """
        assert self.initialized
        self._check_update_best_objective(best_objective)
        self.solve_info.data[:] = solve_info.data
        self.external_bound = None
        self.active_nodes = 0
        if len(node_data_list):
            for node_data in node_data_list:
                self._add_work_to_queue(node_data, set_tree_id=True)
        else:
            if not self.first_update:
                self._check_update_worst_terminal_bound(previous_bound)
        self.first_update = False
        last_global_bound = self.last_global_bound
        self._check_convergence()
        if (self.queue.size() == 0) and \
           (self.termination_condition is None):
            self.termination_condition = TerminationCondition.no_nodes
        if self.termination_condition is None:
            node_data = self._get_work_item()
            self.active_nodes = 1
            self.external_bound = Node._extract_bound(node_data)
            if self.journalist is not None:
                force = (last_global_bound == \
                         self.converger.unbounded_objective) and \
                         (last_global_bound != \
                          self.last_global_bound)
                self.journalist.tic(force=force)
            return (False, self.best_objective, node_data)
        else:
            if self.journalist is not None:
                self.journalist.tic(force=True)
                self.journalist.log_info(self.journalist._lines)
            self.initialized = False
            return (True, self.best_objective, (self._get_current_bound(),
                                                self.termination_condition,
                                                self._get_final_solve_info()))