def test_add_edges_from(self) -> None: g = MultiGraph() g.add_edges_from([ (1, 2, 4.5, { "color": "blue", "mass": 42 }), (4, 3, 9.5), (5, 6, { "color": "red", "mass": 99 }), (8, 7), (7, 8), ]) connection12 = g.get_edge(1, 2).connections()[0] connection34 = g.get_edge(3, 4).connections()[0] assert g.edge_count == 5, "graph should have 5 edge connections" assert g.get_edge( 1, 2).weight == 4.5, "edge (1, 2) should have weight 4.5" assert connection12[ "color"] == "blue", "edge (1, 2) should have 'color' set to 'blue'" assert connection12[ "mass"] == 42, "edge (1, 2) should have 'mass' set to 42" assert not connection34.has_attributes_dict( ), "edge (3, 4) should not have attributes dict" assert (g.get_edge(5, 6).weight == edge_module.DEFAULT_WEIGHT ), "edge should have default weight" assert g.get_edge(7, 8) is g.get_edge( 8, 7), "order of vertices should not matter" assert (g.get_edge(7, 8).multiplicity == 2 ), "edge (7, 8) should have two parallel connections"
def test_multigraph_read_adj_list02(self) -> None: g = MultiGraph() read_adj_list(os.path.join(os.getcwd(), TEST_DIR, GRAPH_FILE02), g) assert g.edge_count == len( g.edges()), "g should have no parallel edges" assert g.edge_count == 6, "graph should have 6 edges" assert g.vertex_count == 4, "graph should have 4 vertices" assert g[1].degree == g[2].degree, "v1 and v2 should have same degree" assert g[1].degree == 3, "v1 should have degree 3" assert g.get_edge(2, 4) is not None, "graph should have edge (2, 4)" assert g.get_edge(1, 3) is not None, "graph should have edge (1, 3)"
def test_multigraph_read_adj_list03(self) -> None: g = MultiGraph() read_adj_list(os.path.join(os.getcwd(), TEST_DIR, GRAPH_FILE03), g) assert g.edge_count == len( g.edges()), "g should have no parallel edges" assert g.edge_count == 14, "graph should have 14 edges" assert g.vertex_count == 8, "graph should have 8 vertices" assert g[1].degree < g[2].degree, "v1 and v2 should have same degree" assert g[1].degree == 3, "v1 should have degree 3" assert g[2].degree == 4, "v2 should have degree 4" assert g.get_edge(2, 4) is not None, "graph should have edge (2, 4)" with pytest.raises(KeyError): assert g.get_edge(2, 6) is None, "graph should not have edge (2, 6)"
def test__init__from_graph(self) -> None: g0 = MultiGraph([(2, 1, 5.0, { "color": "red" }), (2, 1, 2.5, { "color": "blue" })]) g = MultiDiGraph(g0) assert g.has_edge( 2, 1), "multigraph should have edge (2, 1) copied from graph" connection21 = g.get_edge(2, 1).connections()[0] assert ( connection21["color"] == "red" ), "first connection of edge (2, 1) should have 'color' attribute set to red" assert g.get_edge( 2, 1).weight == 7.5, "multiedge (2, 1) should have weight 7.5" assert g.edge_count == 2, "graph should have two edges" assert g.weight == 7.5, "graph should have weight 6.0" assert g.get_edge(2, 1) is not g0.get_edge( # type: ignore 2, 1), "multigraph should have deep copies of edges and vertices"
def test__init__from_graph(self) -> None: mg = MultiGraph([(1, 2, 5.0, { "color": "red" }), (1, 2, 10.0, { "color": "black" }), (3, 4)]) assert mg.weight == 16.0, "multigraph should have weight 16.0" g = Graph(mg) assert g.has_edge( 1, 2), "graph should have edge (1, 2) copied from multigraph" assert (g.get_edge(1, 2)["color"] == "red" ), "edge (1, 2) should have 'color' attribute set to red" assert g.get_edge( 1, 2).weight == 5.0, "edge (1, 2) should have weight 5.0" assert g.has_edge( 3, 4), "graph should have edge (3, 4) copied from multigraph" assert g.edge_count == 2, "graph should have two edges" assert g.weight == 6.0, "graph should have weight 6.0" assert g.get_edge(1, 2) is not mg.get_edge( # type: ignore 1, 2), "graph should have deep copies of edges and vertices"
def test_multigraph_read_adj_list01(self) -> None: g = MultiGraph() read_adj_list(os.path.join(os.getcwd(), TEST_DIR, GRAPH_FILE01), g) v1_loop_edge = g[1].loop_edge assert v1_loop_edge is not None assert v1_loop_edge.multiplicity == 2, "v1 should have 2 loops" assert g[1].degree == 6, "deg(v1) should be 6" assert len(g[2].incident_edges()) == 2, ( "v2 should have 4 incident edges, 3 of which are parallel and stored in one " " Edge object.") assert g[2].degree == 4, "v2 should have degree 4" assert g[3].degree == 3, "v3 should have degree 3" assert ( g.get_edge(3, 2).multiplicity == 3 ), "there should be 2 parallel edges between (2, 3) [3 edges total]" assert ( g.get_edge(2, 3).multiplicity == 3 ), "there should be 2 parallel edges between (2, 3) [3 edges total]" assert g[4].degree == 1, "v4 should have degree 1" assert g[ 5].degree == 0, "v5 should have degree 0 (i.e. isolated vertex)" with pytest.raises(KeyError): assert g.get_edge( 1, 5) is None, "There should be no edge connected to v5" assert g.get_edge(1, 4) is not None, "There should be an edge (1, 4)" assert g.get_edge(1, 2) is not None, "There should be an edge (1, 2)"
def test_edges_and_edge_count(self) -> None: g = MultiGraph([(1, 2), (2, 1), (2, 3), (3, 4)]) assert set(g.edges()) == { g.get_edge(1, 2), g.get_edge(2, 3), g.get_edge(3, 4), }, "multiedges should be (1, 2), (2, 3), (3, 4)" assert g.edge_count == 4, "graph should have 4 edge connections" assert (g.get_edge(1, 2).multiplicity == 2 ), "multiedge (1, 2) should have two parallel connections"
def test_floyd_warshall_undirected_negative_weight_cycle(self) -> None: g = MultiGraph([ ("s", "t", 10), ("s", "y", 5), ("t", "y", -6), ("t", "x", 1), ("x", "z", 4), ("y", "t", 8), ("y", "x", 4), ("y", "z", 3), ("z", "s", 7), ("z", "x", 6), ]) with pytest.raises(NegativeWeightCycle): floyd_warshall(g)
def test_bellman_ford_undirected_negative_weight_cycle(self) -> None: g = MultiGraph( [ ("s", "t", 10), ("s", "y", 5), ("t", "y", -6), ("t", "x", 1), ("x", "z", 4), ("y", "t", 8), ("y", "x", 4), ("y", "z", -3), ("z", "s", 7), ("z", "x", 6), ] ) with pytest.raises(NegativeWeightCycle): bellman_ford(g, "s")
def test_kruskal_multigraph(self) -> None: g = MultiGraph([("a", "b", 5), ("a", "c", 3), ("b", "d", 6), ("c", "d", 4), ("c", "d", 7)]) min_tree = list(undirected.kruskal_spanning_tree(g, minimum=True)) assert len(min_tree) == 3 assert min_tree[0] == g.get_edge("a", "c") assert min_tree[1] == g.get_edge("c", "d") assert min_tree[2] == g.get_edge("a", "b") max_tree = list(undirected.kruskal_spanning_tree(g, minimum=False)) assert len(max_tree) == 3 assert max_tree[0] == g.get_edge("c", "d") assert max_tree[1] == g.get_edge("b", "d") assert max_tree[2] == g.get_edge("a", "b")
def test__init__from_graph(self) -> None: g0 = Graph([(1, 2, 5.0, {"color": "red"}), (3, 4)]) g = MultiGraph(g0) assert g.has_edge( 1, 2), "multigraph should have edge (1, 2) copied from graph" connection12 = g.get_edge(1, 2).connections()[0] assert ( connection12["color"] == "red" ), "edge connection (1, 2) should have 'color' attribute set to red" assert g.get_edge( 1, 2).weight == 5.0, "edge (1, 2) should have weight 5.0" assert g.has_edge(3, 4), "graph should have edge (3, 4) copied from graph" assert g.edge_count == 2, "graph should have two edges" assert g.weight == 6.0, "graph should have weight 6.0" assert g.get_edge(1, 2) is not g0.get_edge( # type: ignore 1, 2), "multigraph should have deep copies of edges and vertices"
def test_floyd_warshall_undirected(self) -> None: g = MultiGraph([ ("s", "t", 10), ("s", "y", 5), ("t", "y", 6), ("t", "x", 1), ("x", "z", 4), ("y", "t", 8), ("y", "x", 4), ("y", "z", 3), ("z", "s", 7), ("z", "x", 6), ]) all_paths_dict: VertexDict[VertexDict[ ShortestPath[MultiVertex]]] = floyd_warshall(g) assert (len(all_paths_dict) == 5 ), "all_paths_dict dictionary should have length equal to |V|." assert all_paths_dict["s"][ "s"].length == 0, "length of path s ~> s should be 0" assert all_paths_dict["s"][ "t"].length == 10, "length of path s ~> t should be 10" assert all_paths_dict["s"][ "x"].length == 9, "length of path s ~> x should be 9" assert all_paths_dict["s"][ "y"].length == 5, "length of path s ~> y should be 5" assert all_paths_dict["s"][ "z"].length == 7, "length of path s ~> z should be 7" assert all_paths_dict["x"][ "s"].length == 9, "length of path x ~> s should be 9" assert all_paths_dict["x"][ "t"].length == 1, "length of path x ~> t should be 1" assert all_paths_dict["x"][ "x"].length == 0, "length of path x ~> x should be 0" assert all_paths_dict["x"][ "y"].length == 4, "length of path x ~> y should be 5" assert all_paths_dict["x"][ "z"].length == 4, "length of path x ~> z should be 7"
def test_dijkstra_undirected_graph(self) -> None: g = MultiGraph( [ ("s", "t", 10), ("s", "y", 5), ("t", "y", 2), ("t", "x", 1), ("x", "z", 4), ("y", "t", 3), ("y", "x", 9), ("y", "z", 2), ("z", "s", 7), ("z", "x", 6), ] ) path_dict: VertexDict[ShortestPath[MultiVertex]] = dijkstra(g, "s") assert path_dict["s"].length == 0, "Length of s path should be 0." assert path_dict["t"].length == 7, "Length of path s ~> t should be 7." assert path_dict["x"].length == 8, "Length of path s ~> x should be 8." assert path_dict["y"].length == 5, "Length of path s ~> y should be 5." assert path_dict["z"].length == 7, "Length of path s ~> z should be 7."
def test_get_random_edge(self) -> None: g = MultiGraph([(1, 2), (1, 2), (3, 4)]) cnt1: Counter[MultiEdge] = collections.Counter() for _ in range(1000): rand_edge = g.get_random_edge_weighted_by_multiplicity() if rand_edge is None: raise Exception("rand_edge returned None") cnt1[rand_edge] += 1 assert cnt1[g.get_edge( 1, 2)] > 600, r"~66% of random samples should be edge (1, 2)" assert cnt1[g.get_edge( 3, 4)] < 400, r"~33% of random samples should be edge (3, 4)" cnt2: Counter[MultiEdge] = collections.Counter() for _ in range(1000): rand_edge = g.get_random_edge() if rand_edge is None: raise Exception("rand_edge returned None") cnt2[rand_edge] += 1 assert cnt2[g.get_edge( 1, 2)] > 420, r"~50% of random samples should be edge (1, 2)" assert cnt2[g.get_edge( 3, 4)] > 420, r"~50% of random samples should be edge (3, 4)"
def test_bellman_ford_undirected(self) -> None: g = MultiGraph( [ ("s", "t", 10), ("s", "y", 5), ("t", "y", 6), ("t", "x", 1), ("x", "z", 4), ("y", "t", 8), ("y", "x", 4), ("y", "z", 3), ("z", "s", 7), ("z", "x", 6), ] ) path_dict: VertexDict[ShortestPath[MultiVertex]] = bellman_ford(g, "s") assert len(path_dict) == 5, "Shortest path_dict dictionary should have length equal to |V|." assert path_dict["s"].length == 0, "Length of s path should be 0." assert path_dict["t"].length == 10, "Length of path s ~> t should be 10." assert path_dict["x"].length == 9, "Length of path s ~> x should be 9." assert path_dict["y"].length == 5, "Length of path s ~> y should be 5." assert path_dict["z"].length == 7, "Length of path s ~> z should be 7."
def test_add_edge(self) -> None: g = MultiGraph() edge = g.add_edge(1, 2, weight=4.5, color="blue", mass=42) assert isinstance(edge, MultiEdge), "new edge should a MultiEdge object" assert g.get_edge( 1, 2).weight == 4.5, "edge (1, 2) should have weight 4.5" connection12 = g.get_edge(1, 2).connections()[0] assert connection12[ "color"] == "blue", "edge should have 'color' attribute set to 'blue'" assert connection12[ "mass"] == 42, "edge should have 'mass' attribute set to 42" edge_dup = g.add_edge(1, 2, weight=1.5, color="red", mass=57) assert ( edge is edge_dup ), "adding an edge with same vertices as existing edge should return existing edge" assert ( g.get_edge(1, 2).multiplicity == 2 ), "after adding parallel connection, edge multiplicity should be 2" g.add_edge(3, 4) assert (g.get_edge(3, 4).weight == edge_module.DEFAULT_WEIGHT ), "edge should have default weight" connection34 = g.get_edge(3, 4).connections()[0] assert not connection34.has_attributes_dict( ), "edge should not have attributes dictionary"
def test_multigraph_write_adj_list01(self) -> None: g = MultiGraph() read_adj_list(os.path.join(os.getcwd(), TEST_DIR, GRAPH_FILE01), g) write_adj_list_to_file( os.path.join(os.getcwd(), TEST_DIR, GRAPH_OUTPUT_FILE01), g)