Source code for fast.cbfs
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import heapq as hq
[docs]class CBFS:
"""
Implements the `CBFS algorithm
<https://www.researchgate.net/publication/315650019_Cyclic_best_first_search_Using_contours_to_guide_branch-and-bound_algorithms_Cyclic_Best_First_Search>`.
"""
def __init__(self, num_queues: int, pop_idx: int = 0):
"""
Constructor.
Args:
num_queues (int): A strictly positive ``int`` specifying the number of
queues managed by this :py:class:`CBFS` instance.
pop_idx (int): The index of the active queue.
It must verify ``0 <= pop_idx < self.num_queues``.
"""
self.queues = [
[] for _ in range(num_queues)
]
for q in self.queues:
hq.heapify(q)
self.num_queues = num_queues # The number of queues managed by this CBFS instance.
self.pop_idx = pop_idx # The active the CBFS queue.
self.num_popped = 0 # The number of popped item from the active CBFS queue in the current cycle.
self.num_to_pop = 1 # The number of items to pop from a queue for each cycle.
self.num_items = 0 # The number of items stored in the CBFS queues.
[docs] def pop(self) -> object:
"""
Pops an item from this :py:class:`CBFS` instance.
Returns:
The popped item.
"""
if self.num_items == 0:
raise RuntimeError("Error (CBFS) cannot pop from an empty queue!")
if self.num_popped == self.num_to_pop:
self.pop_idx = (self.pop_idx + 1) % self.num_queues
self.num_popped = 0
while len(self.queues[self.pop_idx]) == 0:
self.pop_idx = (self.pop_idx + 1) % self.num_queues
self.num_popped = 0
result = hq.heappop(self.queues[self.pop_idx])
self.num_popped += 1
self.num_items -= 1 # TODO if self.num_items > 0:
return result
[docs] def push(self, item: object, push_idx: int):
"""
Pushes a new item to this :py:class:`CBFS` instance.
Args:
item (object): The item to be pushed
push_idx (int): The queue index where the item must be pushed.
It must verifies ``0 <= push_idx < self.num_queues``.
"""
hq.heappush(self.queues[push_idx], item)
self.num_items += 1
[docs] def is_empty(self) -> bool:
"""
Checks whether this :py:class:`CBFS` instance contains at least one item.
"""
return self.num_items <= 0 # TODO == 0