def __init__(self, iterable=()): """Initialize a priority queue, optionally with items from iterable. The items in the priority queue are stored in a binary minheap. Items are first sorted by priority, then queue insertion order. Priority is expressed as an integer with 0 being the most important. args: iterable: an optional iterable to add to the priority queue. Items added this way will be given a priority of None. each item inside iterable can be either: * A QNode object * A container with value, priority * A non-iterable value """ self.heap = BinaryHeap(iterable=()) for item in iterable: try: is_container = len(item) == 2 except TypeError: # Case of QNode or non-iterable item self.insert(item) else: if is_container: # Case of value, iterable self.insert(item[0], item[1]) else: raise TypeError( "More than two args: instantiation supports\ non-iter value or iter of value, priority")
def test_heap_delete_min_build_heap(benchmark, dsa_, values): nums = deepcopy(values) dsa_obj = BinaryHeap() dsa_obj.build_heap(values) to_del = values[len(values) // 2] benchmark(dsa_obj.delete_min)
def test_iterable_becomes_attribute_if_passed_as_argument(eh): """An iterable in our case is limited to list, tuple.""" from binary_heap import BinaryHeap b = BinaryHeap([1, 2, 3]) c = BinaryHeap((1, 2, 3)) assert type(b.iterable) == list assert type(c.iterable) == tuple
def __init__(self, width, length, height): """ Generates all maze cells and edges """ self.width = width self.length = length self.height = height self.generated = False self.graph = Graph((width, length, height)) self.edge_queue = BinaryHeap() self.edges_added = 0 self.inter_layer_edges = 0 for x in range(width): for y in range(length): for z in range(height): self.graph.add_vertex((x, y, z)) self.areas = UnionFind([cell.get_pos() for cell in self]) self.edge_choices = RandomSet(self.graph.get_all_edges()) self.queue_factor = len(self.edge_choices) // LAYER_FACTOR for _ in range(self.queue_factor): edge = self.edge_choices.pop_random() self._queue_edge(edge) self.player = self.graph.get_cell((0, 0, 0)) self.end_cell = self.graph.get_cell( (self.width - 1, self.length - 1, self.height - 1)) self.end_cell.is_end = True
def test_delete_min(self): names = ['A', 'B', 'C', 'D', 'E', 'F', 'G'] values = [5, 3, 7, 1, 9, 10, 11] binary_heap = BinaryHeap(self.setup(names, values)) binary_heap.build_heap() self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [1, 3, 7, 5, 9, 10, 11]) self.assertEqual(binary_heap.delete_min().get_value_attribute(), 1)
def make_valid_heaps(): valid_heaps = [] for permutation in unsorted_lists: heap = BinaryHeap() for item in permutation: heap.insert(item) valid_heaps.append(heap) return valid_heaps
def test_heap(): test_heap = B_heap() test_heap.push(7) test_heap.push(8) test_heap.push(9) test_heap.push(3) return test_heap
def test_correctness(self): for case in cases: bheap = BinaryHeap() bheap.build_heap(case) retrieved = [] while len(bheap) > 0: retrieved.append(bheap.delete_min()) self.assertEqual(retrieved, sorted(case))
def test_build_heap_extract_all_elements_should_return_sorted_elements(self): nums = [3, 4, -1, 15, 2, 77, -3, 4, 12] heap = BinaryHeap(nums) result = [] expected = [77, 15, 12, 4, 4, 3, 2, -1, -3] while len(heap) > 0: result.append(heap.extract_max()) self.assertEqual(result, expected)
def test_pop_returns_sorted_values(): """Test pop entire bin returns sorted values.""" from binary_heap import BinaryHeap import random rand_nums = list(set([random.randint(0, 1000000000) for i in range(10000)])) b = BinaryHeap(rand_nums) # import pdb; pdb.set_trace() all_popped = [b.pop() for i in range(1, len(b.heap))] assert all_popped == sorted(rand_nums, reverse=True)
def test_push(): for x in range(50): a = BinaryHeap() for i in range(47): a.push(random.randint(0,100)) assert max(a._list) == a._list[0] index = a._size - 1 while index : assert a._list[index] <= a._list[(index-1)//2] index -= 1
def test_empty_heap_insert_extract_elements_should_return_sorted_elements(self): nums = [3, 4, -1, 15, 2, 77, -3, 4, 12] heap = BinaryHeap() expected = [77, 15, 12, 4, 4, 3, 2, -1, -3] result = [] for num in nums: heap.insert(num) while heap.count > 0: result.append(heap.extract_max()) self.assertEqual(result, expected)
def heap_sort(arr): ''' This consists of 2 steps: 1. build a min heap, which is O(nlogn) 2. extract all n elements of the heap, which is O(nlogn) Overall, this takes O(nlogn) ''' heap = BinaryHeap(arr) result = [] while not heap.is_empty(): result.append(heap.extract_min()) return result
def test_binary_heap_max(self): bh = BinaryHeap() bh.push(1) bh.push(3) bh.push(2) self.assertEqual(bh.max(), 3) self.assertEqual(bh.size(), 3)
def test_binary_heap_push(self): bh = BinaryHeap() self.assertEqual(bh.size(), 0) bh.push(1) bh.push(2) bh.push(3) self.assertEqual(bh.size(), 3)
class PriorityQueue: def __init__(self): self.binary_heap = BinaryHeap(lambda a, b: a[1] < b[1]) def insert(self, element): self.binary_heap.insert(element) def multiple_insert(self, elements): for element in elements: self.insert(element) def extract(self): element = self.binary_heap.extract() return element[0] if element else element
def test_insert(self): bh = BinaryHeap(compare=lambda a, b: a < b) bh.insert(3) bh.insert(3) bh.insert(2) self.assertSequenceEqual([3, 3, 2], bh.values) bh.insert(4) self.assertSequenceEqual([4, 3, 2, 3], bh.values)
def test_insert_nodes_with_descending_values(self): binary_heap = BinaryHeap() binary_heap.insert(HeapNode({'name': 'A', 'value': 0.91}, 'value')) self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [0.91]) binary_heap.insert(HeapNode({'name': 'B', 'value': 0.57}, 'value')) self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [0.57, 0.91]) binary_heap.insert(HeapNode({'name': 'B', 'value': 0.34}, 'value')) self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [0.34, 0.91, 0.57])
def test_init_max(): #TEST for MAX a = BinaryHeap("max",*[random.randint(0,100) for i in range(37)]) index = a._size - 1 while index : assert a._list[index] <= a._list[(index-1)//2] index -= 1
def __init__(self, iterable=()): """Initialize a priority queue, optionally with items from iterable. The items in the priority queue are stored in a binary minheap. Items are first sorted by priority, then queue insertion order. Priority is expressed as an integer with 0 being the most important. args: iterable: an optional iterable to add to the priority queue. Items added this way will be given a priority of None. each item inside iterable can be either: * A QNode object * A container with value, priority * A non-iterable value """ self.heap = BinaryHeap(iterable=()) for item in iterable: try: is_container = len(item) == 2 except TypeError: # Case of QNode or non-iterable item self.insert(item) else: if is_container: # Case of value, iterable self.insert(item[0], item[1]) else: raise TypeError("More than two args: instantiation supports\ non-iter value or iter of value, priority")
def merge_list_using_heap(list1, list2, len_list1, len_list2): heap_instance = BinaryHeap() heap_instance.buildHeap(list2) for i in range(len_list1): if list1[i] > heap_instance.heaplist[0]: list1[i], heap_instance.heaplist[0] = heap_instance.heaplist[ 0], list1[i] heap_instance.shiftDown(0) heap_instance.inplace_sort() sorted_list = heap_instance.getHeap() sorted_list.reverse() print(list1 + sorted_list) return
def test_multipop_maxheap(): maxheap = BinaryHeap([7, 9, 18, 1, 38, 5.4, 6, 200], minheap=False) length = len(maxheap) maxheap.pop() maxheap.pop() maxheap.push(400) maxheap.pop() maxheap.pop() assert maxheap.pop() == 9 assert len(maxheap) == length - 4
def test_multipop_minheap(): minheap = BinaryHeap([7, 9, 18, 1, 38, 5.4, 6, 200]) length = len(minheap) minheap.pop() minheap.pop() minheap.push(0) minheap.pop() minheap.pop() assert minheap.pop() == 7 assert len(minheap) == length - 4
def least_cost_path(graph, start, dest, cost): reached = {} # empty dictionary events = BinaryHeap() # empty heap events.insert((start, start), 0) # vertex s burns at time 0 while len(events) > 0: edge, time = events.popmin() if edge[1] not in reached: reached[edge[1]] = edge[0] for nbr in graph.neighbours(edge[1]): events.insert((edge[1], nbr), time + cost.distance((edge[1], nbr))) # if the dest is not in reached, then no route was found if dest not in reached: return [] current = dest route = [current] # go through the reached vertices until we get back to start and append # each vertice that we "stop" at while current != start: current = reached[current] route.append(current) # reverse the list because we made a list that went from the dest to start route = route[::-1] return route
def least_cost_path(graph, start, dest, cost): reached = {} # empty dictionary events = BinaryHeap() # empty heap events.insert((start, start), 0) # vertex s burns at time 0 while len(events) > 0: edge, time = events.popmin() if edge[1] not in reached: reached[edge[1]] = edge[0] for nbr in graph.neighbours(edge[1]): events.insert((edge[1], nbr), time + cost.distance( (edge[1], nbr))) if dest not in reached: return [] current = dest path = [current] while current != start: current = reached[current] path.append(current) path = path[::-1] return path
def search(self): self.start_time = time.process_time() self.open = BinaryHeap() self.expansions = 0 initial_node = Node(self.initial_state) initial_node.g = 0 initial_node.h = self.heuristic(self.initial_state) initial_node.key = self.fvalue(0, initial_node.h) # asignamos el valor f self.open.insert(initial_node) # para cada estado alguna vez generado, generated almacena # el Node que le corresponde self.generated = {} self.generated[self.initial_state] = initial_node while not self.open.is_empty(): n = self.open.extract() # extrae n de la open if n.state.is_goal(): self.end_time = time.process_time() self.s = n return n succ = n.state.successors() self.expansions += 1 for child_state, action, cost in succ: child_node = self.generated.get(child_state) is_new = child_node is None # es la primera vez que veo a child_state path_cost = n.g + cost # costo del camino encontrado hasta child_state if is_new or path_cost < child_node.g: # si vemos el estado child_state por primera vez o lo vemos por # un mejor camino, entonces lo agregamos a open if is_new: # creamos el nodo de child_state child_node = Node(child_state, n) child_node.h = self.heuristic(child_state) self.generated[child_state] = child_node child_node.action = action child_node.parent = n child_node.g = path_cost child_node.key = self.fvalue( child_node.g, child_node.h ) * 100 - child_node.g # actualizamos el valor f de child_node self.open.insert( child_node ) # inserta child_node a la open si no esta en la open self.end_time = time.process_time( ) # en caso contrario, modifica la posicion de child_node en open return None
def setUp(self): size = 8 self.random_list = random.sample(range(0, size), size) print "random list generated: " + str(self.random_list) self.heap = BinaryHeap(size) for key in self.random_list: if not self.heap.is_full(): self.heap.insert(key)
class TestBinaryHeap(unittest.TestCase): def setUp(self): self.heap = BinaryHeap() self.replayMemory = ReplayMemory(10, 32, 4, 84, 84) def test_Add(self): totalNo = 10 for i in range(totalNo): state = np.zeros((84, 84), dtype=np.int) state.fill(i) td = i addedIndex = self.replayMemory.add(0, 0, state, 0) self.heap.add(addedIndex, td) for i in range(totalNo): topItem = self.heap.getTop() self.assertEqual(totalNo - i - 1, topItem[0]) self.heap.remove(0)
def least_cost_path(graph, start, dest, location): """ *** NOTE: This function is a modified version of our previous *** *** implementation of Dijkstra's Algorithm from Assignment 1 *** *** Part 1. Comments in code indicate changes made. *** Find and return a least cost path in graph from start vertex to dest vertex. Args: graph (Graph): The digraph defining the edges between the vertices. start: The vertex where the path starts. It is assumed that start is a vertex of graph. dest: The vertex where the path ends. It is assumed that dest is a vertex of graph. location: A dictionary containing all the vertices on the screen. Keys of location are identifiers holding the vertices as values. Returns: list: A potentially empty list (if no path can be found) of the vertices in the graph. If there was a path, the first vertex is always start, the last is always dest in the list. Any two consecutive vertices correspond to some edge in graph. """ reached = {} events = BinaryHeap() events.insert((start, start), 0) while len(events) > 0: edge, time = events.popmin() if edge[1] not in reached: reached[edge[1]] = edge[0] # each vertex in our graph is a tuple, so we use tuples to find neighbours # instead of single values to find the neighbours of a vertex for nbr in graph.neighbours(location[edge[1]]): # find the identifier/key value attached to nbr tuple nbrID = neighbour_identifier(nbr, location) # insert to binary heap appropriately events.insert((edge[1], nbrID), time + distance(location[edge[1]], nbr)) # FIND MINIMUM PATH IF POSSIBLE if dest not in reached: return [] # start at the dest and continously ind the parent of current vertex # until have reached starting vertex current = dest path = [current] while current != start: current = reached[current] path.append(current) path = path[::-1] # reverse the list so starts from the ghost return path
def test_pop(): bt = BinaryHeap() for i in range(50): bt.push(random.randint(0,1000)) for i in range(49): tmp = max(bt._list[1:]) bt.pop() assert tmp == bt._list[0] bt.pop() assert 0 == len(bt._list) # testing for empty list pop a = BinaryHeap() with pytest.raises(IndexError): assert a.pop()
class PriorityQueue: def __init__(self): self.queue = BinaryHeap() # log(n) worst case (both time and space) def enqueue(self, elem): self.queue.insert_element(elem) # log(n) worst case (both time and space) def dequeue(self): return self.queue.extract_min() def peek_min(self): return self.queue[0] def isEmpty(self): return self.queue.isEmpty() def __str__(self): return self.queue.__str__()
class PriorityQueue(object): def __init__(self): self.heap = BinaryHeap() self.seniority = 0 def insert(self, priority, val): self.heap.push((priority, self.seniority, val)) self.seniority -= 1 def pop(self): try: return self.heap.pop()[2] except IndexError: raise IndexError("The queue is empty") def peek(self): try: return self.heap._list[0][2] except IndexError: raise IndexError("The queue is empty")
def task_1ab(): task_list = deepcopy(TASK_ONE_A) _, bh_obj = create_heap_for_loop_insert(task_list) # for-loop, insert() bh_linear = BinaryHeap() # New bh-obj for linear insertion bh_linear.build_heap(task_list) # Build with linear insertion # HeapList bh_list = ", ".join([str(l) for l in bh_obj.heapList[1::]]) bh_linear_list = ", ".join([str(l) for l in bh_linear.heapList[1::]]) # "For-loop"-obj walks xa, a = travers_tree_inorder(bh_obj) xb, b = travers_tree_postorder(bh_obj) xc, c = travers_tree_preorder(bh_obj) xd, d = level_order(bh_obj) # "Linear"-obj walks ignore, aa = travers_tree_inorder(bh_linear) ignore, bb = travers_tree_postorder(bh_linear) ignore, cc = travers_tree_preorder(bh_linear) ignore, dd = level_order(bh_linear) table = Table("Task", "Array", "Insert Method") table.add_row("1a, algorithm 1", bh_list, "for-loop") table.add_row("1b, algorithm 2", bh_linear_list, "Linear") table.add_row("", "", "") table.add_row("1c, " + xa, ", ".join([str(l) for l in a]), "for-loop") table.add_row("1c, " + xb, ", ".join([str(l) for l in b]), "for-loop") table.add_row("1c, " + xc, ", ".join([str(l) for l in c]), "for-loop") table.add_row("1c, " + xd, ", ".join([str(l) for l in d]), "for-loop") table.add_row("", "", "") table.add_row("1c, " + xa, ", ".join([str(l) for l in aa]), "Linear") table.add_row("1c, " + xb, ", ".join([str(l) for l in bb]), "Linear") table.add_row("1c, " + xc, ", ".join([str(l) for l in cc]), "Linear") table.add_row("1c, " + xd, ", ".join([str(l) for l in dd]), "Linear") console = Console() console.print(table)
def shorted_path(G, src): dist = {} pred = {} n = 0 infinity = sys.maxint for v in G.keys(): dist[v] = infinity pred[v] = None n +=1 dist[src] = 0 bh = BinaryHeap(n, src, infinity) while not bh.isEmpty(): u = bh.pop() for v, w in G[u]: newLen = dist[u] + w if newLen < dist[v]: dist[v] = newLen bh.decreaseKey(v, newLen) pred[v] = u return dist, pred
def test_update_with_lower_value_for_leaf_node(self): values = [1, 3, 5, 7, 9, 10, 11] names = ['A', 'B', 'C', 'D', 'E', 'F', 'G'] binary_heap = BinaryHeap(self.setup(names, values)) binary_heap.build_heap() binary_heap.update(6, 4) self.assertEqual([x.get_value_attribute() for x in binary_heap.node_list if x is not None], [1, 3, 4, 7, 9, 5, 11])
def test_unique_values_raises_error_if_1_value_in_list(): """If a value is pushed into heap that already exists, error is raised.""" from binary_heap import BinaryHeap b = BinaryHeap() b.push(1) with pytest.raises(ValueError): b.push(1)
class TestBinaryHeap(unittest.TestCase): def setUp(self): size = 8 self.random_list = random.sample(range(0, size), size) print "random list generated: " + str(self.random_list) self.heap = BinaryHeap(size) for key in self.random_list: if not self.heap.is_full(): self.heap.insert(key) def tearDown(self): pass def test_delete_min(self): order_list = sorted(self.random_list) index = 0 while not self.heap.is_empty(): min_value = self.heap.delete_min() print min_value self.assertEqual(min_value, order_list[index]) index += 1
def testBinaryHeapOperations(self): arr = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] heap = BinaryHeap(arr) self.assertEqual(6, heap.left(3)) self.assertEqual(7, heap.right(3)) self.assertEqual(1, heap.parent(3)) self.assertEqual(8, heap.get_item(4)) self.assertEqual(len(arr), heap.heap_size())
def test_valid_heaps(): heap = BinaryHeap() heap._list = [0, 1, 2, 3] heap._size = 3 is_valid_heap(heap) heap2 = BinaryHeap() heap2._list = [0, 1, 2, 3, 4] heap2._size = 4 is_valid_heap(heap2)
class PriorityQueue(object): def __init__(self): self._heap = BinaryHeap() def peek(self): return self._heap.peek_min() def is_empty(self): return self._heap.is_empty() def enqueue(self, value): self._heap.insert(value) def dequeue(self): self._heap.extract_min() def __iter__(self): yield from iter(self._heap) def __len__(self): return len(self._heap)
def setUp(self): self.heap = BinaryHeap() self.replayMemory = ReplayMemory(10, 32, 4, 84, 84)
def test_perc_down(): heap = BinaryHeap() heap._list = [0, 1, 100, 2] heap._size = 3 heap._perc_down(1) is_valid_heap(heap)
def test_perc_up(): heap = BinaryHeap() heap._list = [0, 100, 101, 1] heap._size = 3 heap._perc_up(3) is_valid_heap(heap)
def test_pop_minheap(): minheap = BinaryHeap([7, 9, 18, 1, 38, 5.4, 6]) minheap.push(0) length = len(minheap) assert minheap.pop() == 0 assert len(minheap) == length - 1
def test_bubbledown_maxheap(): maxheap = BinaryHeap([6, 5, 4, 3, 2, 1, 0], minheap=False) maxheap[6] = 4000 maxheap._bubbleup(6) assert maxheap[0] == 4000 assert is_maxheap_sorted(maxheap)
def test_bubbledown_minheap(): minheap = BinaryHeap([0, 1, 2, 3, 4, 5, 6]) minheap[0] = 4000 minheap._bubbledown(0) assert minheap[0] == 1 assert is_minheap_sorted(minheap)
def test_valid_instantiation_max(input, output): """Test instantiation by creating and doing one pop""" heap_under_test = BinaryHeap(input, minheap=False) assert is_maxheap_sorted(heap_under_test) assert heap_under_test.pop() == output
def naive_construct_heap(alist): new_heap = BinaryHeap() for number in alist: new_heap.insert(number) return new_heap
def test_is_unsorted_minheap_comparison(): minheap = BinaryHeap(minheap=True) assert minheap._is_unsorted(1, 2)
def test_find_children(): minheap = BinaryHeap([0, 1, 2, 3, 4, 5, 6]) assert minheap._find_children(0) == (1, 2) assert minheap._find_children(2) == (5, 6)
def test_find_parent(): minheap = BinaryHeap([0, 1, 2, 3, 4, 5, 6]) assert minheap._find_parent(2) == 0 assert minheap._find_parent(6) == 2
def test_pop_maxheap(): maxheap = BinaryHeap([7, 9, 18, 1, 38, 5.4, 6], minheap=False) maxheap.push(400) length = len(maxheap) assert maxheap.pop() == 400 assert len(maxheap) == length - 1
def test_is_unsorted_maxheap_comparison(): minheap = BinaryHeap(minheap=False) assert minheap._is_unsorted(2, 1)
def __init__(self): self._heap = BinaryHeap()
def test_swap(): minheap = BinaryHeap([0, 1, 2, 3, 4, 5, 6]) minheap._swap(0, 6) assert minheap.tree[0] == 6 assert minheap.tree[6] == 0
def test_binary_heap(): _heap = BinaryHeap() with raises(IndexError): _heap.pop() _heap.push(2) _heap.push(20) _heap.push(-12) _heap.push(223) _heap.push(12) _heap.push(-2) sortedList = _heap.values assert _heap.values == [223, 20, -2, 2, 12, -12] _heap.pop() _heap.pop() assert _heap.values == [12, 2, -2, -12]