def setUp(self): self.undirected = UndirectedGraph() self.undirected.add_edge(1, 2, 2) self.undirected.add_edge(1, 3, 6) self.undirected.add_edge(2, 4, 1) self.undirected.add_edge(3, 5, 4)
def setUp(self): g = UndirectedGraph() g.add_edge(1, 2, 2) g.add_edge(1, 3, 6) g.add_edge(2, 3, 3) g.add_edge(2, 4, 9) g.add_edge(3, 4, 1) g.add_edge(3, 5, 4) g.add_edge(4, 5, 6) self.graph = g
def prim(graph: UndirectedGraph) -> UndirectedGraph: """ Prim's algorithm is a greedy algorithm that finds a minimum spanning tree for a weighted undirected graph. This means it finds a subset of the edges that forms a tree that includes every vertex O(E + V log V) """ current_vertex = graph.get_vertices()[0] new_graph = UndirectedGraph() heap = FibonacciHeap(map(lambda x: (x, current_vertex), graph.get_outgoing_edges(current_vertex))) vertices = {current_vertex} while not heap.is_empty(): edge, current_vertex = heap.pop() next_vertex = edge.a if edge.a != current_vertex else edge.b if next_vertex in vertices: continue # Add edge to the minimum spanning tree vertices.add(next_vertex) new_graph.add_edge(current_vertex, next_vertex, edge.weight) # Add all edges from this new point to the heap [heap.insert((edge, next_vertex)) for edge in graph.get_outgoing_edges(next_vertex)] return new_graph
def contains_cycle(graph: UndirectedGraph) -> bool: """ Simple breadth first cycle detection for Undirected graphs """ graph = copy.deepcopy(graph) # type: Graph visited_nodes = set() queue = Queue() queue.enqueue(graph.get_vertices()[0]) while not queue.is_empty(): vertex = queue.dequeue() for neighbour in graph.get_successive_vertices(vertex): if neighbour in visited_nodes: return True visited_nodes.add(neighbour) queue.enqueue(neighbour) graph.delete_edge(vertex, neighbour) return False
def setUp(self): self.undirected = UndirectedGraph() self.undirected.add_edge(1, 2, 2) self.undirected.add_edge(1, 3, 6) self.undirected.add_edge(2, 3, 3) self.undirected.add_edge(2, 4, 1) self.undirected.add_edge(3, 4, 1) self.undirected.add_edge(3, 5, 4) self.undirected.add_edge(4, 5, 6) self.directed = DirectedGraph() self.directed.add_edge(1, 2, 2) self.directed.add_edge(1, 3, 6) self.directed.add_edge(2, 3, 3) self.directed.add_edge(2, 4, 1) self.directed.add_edge(3, 4, 1) self.directed.add_edge(3, 5, 4) self.directed.add_edge(4, 5, 6)
class TestCyclical(unittest.TestCase): def setUp(self): self.undirected = UndirectedGraph() self.undirected.add_edge(1, 2, 2) self.undirected.add_edge(1, 3, 6) self.undirected.add_edge(2, 4, 1) self.undirected.add_edge(3, 5, 4) def test_topological_sort(self): assert not contains_cycle(self.undirected) self.undirected.add_edge(4, 5, 6) assert contains_cycle(self.undirected)
def kruskal(graph: UndirectedGraph) -> UndirectedGraph: """ Kruskal's algorithm is a minimum-spanning-tree algorithm which finds an edge of the least possible weight that connects any two trees in the forest. It is a greedy algorithm in graph theory as it finds a minimum spanning tree for a connected weighted undirected graph adding increasing cost arcs at each step. Time complexity: O(E log V) """ spanning_tree = UndirectedGraph() union_find = UnionFind(max(graph.get_vertices()) + 1) heap = FibonacciHeap(graph.get_all_edges()) while not heap.is_empty(): edge = heap.pop() # Only add the edge if it will not create a cycle if union_find.find(edge.a) != union_find.find(edge.b): spanning_tree.add_edge(edge.a, edge.b, edge.weight) union_find.union(edge.a, edge.b) return spanning_tree
class TestGraph(unittest.TestCase): def setUp(self): self.undirected = UndirectedGraph() self.undirected.add_edge(1, 2, 2) self.undirected.add_edge(1, 3, 6) self.undirected.add_edge(2, 3, 3) self.undirected.add_edge(2, 4, 1) self.undirected.add_edge(3, 4, 1) self.undirected.add_edge(3, 5, 4) self.undirected.add_edge(4, 5, 6) self.directed = DirectedGraph() self.directed.add_edge(1, 2, 2) self.directed.add_edge(1, 3, 6) self.directed.add_edge(2, 3, 3) self.directed.add_edge(2, 4, 1) self.directed.add_edge(3, 4, 1) self.directed.add_edge(3, 5, 4) self.directed.add_edge(4, 5, 6) def test_get_edges(self): assert self.undirected.get_all_edges() == self.directed.get_all_edges() assert self.undirected.get_vertices() == self.directed.get_vertices() def test_directed_graph(self): assert len(self.directed.get_successive_vertices(4)) == 1 assert len(self.undirected.get_successive_vertices(4)) == 3 assert self.undirected.edge_exists(4, 3) assert not self.directed.edge_exists(4, 3) self.directed.delete_edge(4, 3) self.undirected.delete_edge(4, 3) assert len(self.directed.get_all_edges()) == len(self.undirected.get_all_edges()) + 1 def test_undirected_graph(self): g = UndirectedGraph()
def test_undirected_graph(self): g = UndirectedGraph()
class TestGraph(unittest.TestCase): def setUp(self): self.undirected = UndirectedGraph() self.undirected.add_edge(1, 2, 2) self.undirected.add_edge(1, 3, 6) self.undirected.add_edge(2, 3, 3) self.undirected.add_edge(2, 4, 1) self.undirected.add_edge(3, 4, 1) self.undirected.add_edge(3, 5, 4) self.undirected.add_edge(4, 5, 6) self.directed = DirectedGraph() self.directed.add_edge(1, 2, 2) self.directed.add_edge(1, 3, 6) self.directed.add_edge(2, 3, 3) self.directed.add_edge(2, 4, 1) self.directed.add_edge(3, 4, 1) self.directed.add_edge(3, 5, 4) self.directed.add_edge(4, 5, 6) def test_get_edges(self): assert self.undirected.get_all_edges() == self.directed.get_all_edges() assert self.undirected.get_vertices() == self.directed.get_vertices() def test_directed_graph(self): assert len(self.directed.get_successive_vertices(4)) == 1 assert len(self.undirected.get_successive_vertices(4)) == 3 assert self.undirected.edge_exists(4, 3) assert not self.directed.edge_exists(4, 3) self.directed.delete_edge(4, 3) self.undirected.delete_edge(4, 3) assert len(self.directed.get_all_edges()) == len( self.undirected.get_all_edges()) + 1 def test_undirected_graph(self): g = UndirectedGraph()