def test_min_max_doubly_sorted(): dictionnary = Dictionnary(implementation='doubly_sorted') assert dictionnary.min() is None item_0 = KeyedItem(key=0, content=0) item_1 = KeyedItem(key=1, content=1) item_2 = KeyedItem(key=2, content=2) item_3 = KeyedItem(key=3, content=3) dictionnary.insert(item_0) dictionnary.insert(item_1) dictionnary.insert(item_2) dictionnary.insert(item_3) assert dictionnary.min() is item_0 assert dictionnary.max() is item_3
def test_min_max_balanced_tree(): dictionnary = Dictionnary(implementation='balanced_tree') assert dictionnary.min() is None item_0 = KeyedItem(key=0, content=0) item_1 = KeyedItem(key=1, content=1) item_2 = KeyedItem(key=2, content=2) item_3 = KeyedItem(key=3, content=3) dictionnary.insert(item_0) dictionnary.insert(item_1) dictionnary.insert(item_2) dictionnary.insert(item_3) assert dictionnary.min() is item_0 assert dictionnary.max() is item_3
def test_find_min_balanced_tree(): priority_queue = PriorityQueue(implementation='balanced_tree') assert priority_queue.find_min() is None item_4 = KeyedItem(4, 4) item_2 = KeyedItem(2, 2) item_3 = KeyedItem(3, 3) item_1 = KeyedItem(1, 1) priority_queue.insert(item_4) assert priority_queue.find_min() is item_4 priority_queue.insert(item_2) assert priority_queue.find_min() is item_2 priority_queue.insert(item_3) assert priority_queue.find_min() is item_2 priority_queue.insert(item_1) assert priority_queue.find_min() is item_1
def test_find_min_unsorted_array(): priority_queue = PriorityQueue(implementation='unsorted_array') assert priority_queue.find_min() is None item_4 = KeyedItem(4, 4) item_2 = KeyedItem(2, 2) item_3 = KeyedItem(3, 3) item_1 = KeyedItem(1, 1) priority_queue.insert(item_4) assert priority_queue.find_min() is item_4 priority_queue.insert(item_2) assert priority_queue.find_min() is item_2 priority_queue.insert(item_3) assert priority_queue.find_min() is item_2 priority_queue.insert(item_1) assert priority_queue.find_min() is item_1
def test_find_root(): heap = Heap() items = [KeyedItem(key=i) for i in range(10)] random_items = [item for item in items] random.shuffle(random_items) heap.heapify(random_items) assert heap.find_root() is items[0]
def test_primitives(): dictionnary = Dictionnary() with pytest.raises(NotImplementedError): dictionnary.search(key=0) with pytest.raises(NotImplementedError): dictionnary.insert(KeyedItem(0, 0)) with pytest.raises(NotImplementedError): dictionnary.delete(KeyedItem(0, 0)) with pytest.raises(NotImplementedError): dictionnary.max() with pytest.raises(NotImplementedError): dictionnary.min() with pytest.raises(NotImplementedError): dictionnary.predecessor(KeyedItem(0, 0)) with pytest.raises(NotImplementedError): dictionnary.successor(KeyedItem(0, 0))
def test_delete_last(): heap = Heap() items = [KeyedItem(key=i) for i in range(10)] heap.heapify(items) heap.delete(items[9]) for i in range(9): assert heap.extract_root() is items[i] assert heap.extract_root() is None
def test_primitives(): priority_queue = PriorityQueue() with pytest.raises(NotImplementedError): priority_queue.insert(KeyedItem(0, 0)) with pytest.raises(NotImplementedError): priority_queue.find_min() with pytest.raises(NotImplementedError): priority_queue.delete_min()
def test_search_balanced_tree(): dictionnary = Dictionnary(implementation='balanced_tree') item_0 = KeyedItem(key=0, content=0) item_1 = KeyedItem(key=1, content=1) item_2 = KeyedItem(key=2, content=2) item_3 = KeyedItem(key=3, content=3) item_4 = KeyedItem(key=4, content=4) dictionnary.insert(item_0) assert dictionnary.search(key=0) is item_0 dictionnary.insert(item_3) dictionnary.insert(item_1) dictionnary.insert(item_4) dictionnary.insert(item_2) assert dictionnary.search(key=0) is item_0 assert dictionnary.search(key=1) is item_1 assert dictionnary.search(key=2) is item_2 assert dictionnary.search(key=3) is item_3 assert dictionnary.search(key=4) is item_4
def test_construct_max_heap(): heap = Heap(heaptype='max') items = [KeyedItem(key=i) for i in range(10)] random_items = [item for item in items] random.shuffle(random_items) heap.heapify(random_items) for i in range(10): assert heap.extract_root() is items[10 - i - 1] assert heap.extract_root() is None
def test_search_doubly_unsorted(): dictionnary = Dictionnary(implementation='doubly_unsorted') item_0 = KeyedItem(key=0, content=0) item_1 = KeyedItem(key=1, content=1) item_2 = KeyedItem(key=2, content=2) item_3 = KeyedItem(key=3, content=3) item_4 = KeyedItem(key=4, content=4) dictionnary.insert(item_0) assert dictionnary.search(key=0) is item_0 dictionnary.insert(item_3) dictionnary.insert(item_1) dictionnary.insert(item_4) dictionnary.insert(item_2) assert dictionnary.search(key=0) is item_0 assert dictionnary.search(key=1) is item_1 assert dictionnary.search(key=2) is item_2 assert dictionnary.search(key=3) is item_3 assert dictionnary.search(key=4) is item_4
def test_predecessor_successor_balanced_tree(): dictionnary = Dictionnary(implementation='balanced_tree') item_0 = KeyedItem(key=0, content=0) item_1 = KeyedItem(key=1, content=1) item_2 = KeyedItem(key=2, content=2) item_3 = KeyedItem(key=3, content=3) dictionnary.insert(item_0) dictionnary.insert(item_1) dictionnary.insert(item_2) dictionnary.insert(item_3) assert dictionnary.predecessor(item_0) is None assert dictionnary.predecessor(item_1) is item_0 assert dictionnary.predecessor(item_2) is item_1 assert dictionnary.predecessor(item_3) is item_2 assert dictionnary.successor(item_0) is item_1 assert dictionnary.successor(item_1) is item_2 assert dictionnary.successor(item_2) is item_3 assert dictionnary.successor(item_3) is None
def test_delete_unsorted_array(): dictionnary = Dictionnary(implementation='unsorted_array') item_0 = KeyedItem(key=0, content=0) item_1 = KeyedItem(key=1, content=1) item_2 = KeyedItem(key=2, content=2) item_3 = KeyedItem(key=3, content=3) dictionnary.insert(item_0) dictionnary.insert(item_1) dictionnary.insert(item_2) dictionnary.insert(item_3) dictionnary.delete(item_0) assert dictionnary.min() is item_1 dictionnary.delete(item_1) assert dictionnary.min() is item_2 dictionnary.delete(item_3) assert dictionnary.max() is item_2 dictionnary.delete(item_2) assert dictionnary.min() is None assert dictionnary.max() is None
def test_delete_root(): heap = Heap() items = [KeyedItem(key=i) for i in range(10)] random_items = [item for item in items] random.shuffle(random_items) heap.heapify(random_items) heap.delete(items[0]) for i in range(1, 10): assert heap.extract_root() is items[i] assert heap.extract_root() is None
def test_insert_min_heap(): heap = Heap() items = [KeyedItem(key=i) for i in range(10)] random_items = [item for item in items] random.shuffle(random_items) for item in random_items: heap.insert(item) for i in range(10): assert heap.extract_root() is items[i] assert heap.extract_root() is None
def test_delete_with_bubble_down(): heap = Heap() items_keys = list(range(5)) + list(range(100, 112)) items = [KeyedItem(key=i) for i in items_keys] heap.heapify(items) heap.delete(items[5]) for i in range(17): if i != 5: root = heap.extract_root() assert root is items[i] assert heap.extract_root() is None
def test_delete_sorted_array(): priority_queue = PriorityQueue(implementation='sorted_array') item_4 = KeyedItem(4, 4) item_2 = KeyedItem(2, 2) item_3 = KeyedItem(3, 3) item_1 = KeyedItem(1, 1) priority_queue.insert(item_4) priority_queue.insert(item_2) priority_queue.insert(item_3) priority_queue.insert(item_1) assert priority_queue.find_min() is item_1 priority_queue.delete_min() assert priority_queue.find_min() is item_2 priority_queue.delete_min() assert priority_queue.find_min() is item_3 priority_queue.delete_min() assert priority_queue.find_min() is item_4 priority_queue.delete_min() assert priority_queue.find_min() is None priority_queue.delete_min() assert priority_queue.find_min() is None
def test_delete_with_bubble_up(): heap = Heap() items_keys = (list(range(2)) + [100] + list(range(2, 4)) + list(range(101, 103)) + list(range(4, 8)) + list(range(103, 107)) + list(range(8, 10))) items = [KeyedItem(key=i) for i in items_keys] heap.heapify(items) heap.delete(items[5]) for i in range(2): assert heap.extract_root() is items[i] for i in range(3, 5): assert heap.extract_root() is items[i] for i in range(7, 11): assert heap.extract_root() is items[i] for i in range(15, 17): assert heap.extract_root() is items[i] assert heap.extract_root() is items[2] assert heap.extract_root() is items[6] for i in range(11, 15): assert heap.extract_root() is items[i] assert heap.extract_root() is None
def test_search_unsorted_array(): dictionnary = Dictionnary(implementation='unsorted_array') item = KeyedItem(key=0, content=0) dictionnary.insert(item) assert dictionnary.search(key=0) is item
def test_delete_only_item(): heap = Heap() item = KeyedItem(key=0) heap.insert(item) heap.delete(item) assert heap.extract_root() is None
def test_search_fail_doubly_sorted(): dictionnary = Dictionnary(implementation='doubly_sorted') item = KeyedItem(key=0, content=0) dictionnary.insert(item) with pytest.raises(FileNotFoundError): dictionnary.search(key=1)
def run_dijkstra_algorithm(graph: Graph, source: Vertex) -> NodeList: nb_processed_vertices = 1 nb_vertices = graph.nb_vertices shortest_paths = NodeList(vertices=graph.adjacency_lists) # a list of vertices does the bookkeeping of keeping track # of which vertices are processed/unprocessed vertex_statuses = NodeList(vertices=graph.adjacency_lists, default=False) class ItemContent: def __init__(self, vertex: Vertex, edge: Edge=None): self.vertex = vertex self.edge = edge class Path: def __init__(self, source: Vertex): self.source = source self.destination = None self.path_to_last_hop = None self.last_hop = None self.distance = None def build(self, path_to_last_hop, last_hop: Edge): if self.source is not path_to_last_hop.source: raise PathError if path_to_last_hop.destination is not last_hop.head: raise PathError self.path_to_last_hop = path_to_last_hop self.last_hop = last_hop self.destination = last_hop.tail self.distance = path_to_last_hop.distance + last_hop.weight # a heap contains all vertices not in the path # their keys are the min distance to the source vertex # initialization in O(n + m) heap = Heap(heaptype='min') for vertex in graph.adjacency_lists: shortest_paths[vertex] = Path(source=source) shortest_paths[vertex].distance = inf shortest_paths[source].destination = source shortest_paths[source].distance = 0 for edgenode in graph.adjacency_lists[source].edgenodes: tail = edgenode.tail if edgenode.weight < 0: raise GraphTypeError if shortest_paths[tail].distance is not None and edgenode.weight < shortest_paths[tail].distance: shortest_paths[tail].destination = tail shortest_paths[tail].last_hop = edgenode.to_edge(head=source) shortest_paths[tail].distance = edgenode.weight vertex_items = [] for vertex in graph.adjacency_lists: if vertex is not source: vertex_item = KeyedItem(key=shortest_paths[vertex].distance, content=ItemContent(vertex=vertex, edge=shortest_paths[vertex].last_hop)) vertex_items.append(vertex_item) vertex_statuses[vertex] = vertex_item heap.heapify(vertex_items) del vertex_items def update_heap(deleted_vertex: Vertex, distance_to_deleted_vertex: float): nonlocal graph, heap, vertex_statuses # update status vertex_statuses[deleted_vertex] = False # remove from the heap all vertices connected to # the deleted vertex for edgenode in graph.adjacency_lists[deleted_vertex].edgenodes: tail = edgenode.tail # check if the tail is in unprocessed vertices set vertex_item = vertex_statuses[tail] if vertex_item: distance = vertex_item.key vertex = vertex_item.content.vertex edge = vertex_item.content.edge # delete it from the heap heap.delete(vertex_item) # recompute its distance if edgenode.weight < 0: raise GraphTypeError new_distance = distance_to_deleted_vertex + edgenode.weight if new_distance < distance: distance = new_distance edge = edgenode.to_edge(head=deleted_vertex) vertex_item.key = distance vertex_item.content = ItemContent(vertex=vertex, edge=edge) # insert it back into the heap heap.insert(vertex_item) while nb_processed_vertices < nb_vertices: # pick cheapest edge crossing the cut # from the graph shortest_path_tree = (processed_vertices, paths) # to the graph graph - shortest_path_tree heap_item = heap.extract_root() last_hop = heap_item.content.edge v = heap_item.content.vertex # add it to the path leading to v shortest_paths[v].build(path_to_last_hop=shortest_paths[last_hop.head], last_hop=last_hop) # update nb_processed_vertices nb_processed_vertices += 1 # update heap update_heap(deleted_vertex=v, distance_to_deleted_vertex=shortest_paths[v].distance) return shortest_paths
def test_max_heapsort(): sorted_items = [KeyedItem(key=i) for i in range(99, -1, -1)] items = [item for item in sorted_items] random.shuffle(items) assert heapsort(items, order='max') == sorted_items
def test_search_fail_balanced_tree(): dictionnary = Dictionnary(implementation='balanced_tree') item = KeyedItem(key=0, content=0) dictionnary.insert(item) with pytest.raises(FileNotFoundError): dictionnary.search(key=1)
def test_min_heapsort(): sorted_items = [KeyedItem(key=i) for i in range(100)] items = [item for item in sorted_items] random.shuffle(items) assert heapsort(items) == sorted_items
def test_negative_numbers_countsort(): sorted_items = [KeyedItem(key=i) for i in range(-100, 100)] items = [item for item in sorted_items] random.shuffle(items) assert countsort(items) == sorted_items