def test_contract(self) -> None: g = Graph([(1, 2), (1, 3), (2, 3), (2, 4), (2, 2)]) assert g[1].adj_vertices() == { g[2], g[3], }, "vertex 1 should be adjacent to vertices 2 and 3" g.get_edge(1, 2).contract(remove_loops=False) assert g[1].adj_vertices() == { g[1], g[3], g[4], }, "after edge contraction, vertex 1 should be adjacent to vertices 1, 3, and 4" assert g[1].loop_edge is not None assert ( g[1].loop_edge.label == "(1, 1)" ), "vertex 1 should have loop edge (1, 1), due to loop that was on vertex 2" assert not g.has_vertex( 2), "after edge contraction, vertex 2 should be removed" g2 = Graph([("a", "b"), ("b", "c"), ("b", "b")]) g2.get_edge("a", "b").contract(remove_loops=True) assert not g2[ "a"].loop_edge, "loop edge should be removed after edge contraction"
def test_weight(self) -> None: g = Graph([(1, 2), (3, 4, 9.5)]) assert ( g.get_edge(1, 2).weight == edge_module.DEFAULT_WEIGHT ), "edge without a specified weight should default to edge_module.DEFAULT_WEIGHT" assert g.get_edge( 3, 4).weight == 9.5, "weight of edge (3, 4) should be 9.5" with pytest.raises(AttributeError): g.get_edge(3, 4).weight = 100 # type: ignore
def test__eq__(self) -> None: g1 = Graph([(1, 2), (3, 4, 2.5)]) g2 = Graph([(1, 2), (3, 4, 5.0)]) assert g1.get_edge(1, 2) == g2.get_edge(1, 2), "edges (1, 2) should be equal" assert g1.get_edge(3, 4) != g2.get_edge( 3, 4), "edges (3, 4, 2.5) and (3, 4, 5.0) should not be equal"
def test_weight(self) -> None: g = Graph() g.add_edge(1, 2) edge_data1 = pp_module.EdgeData.from_edge_obj(g.get_edge(1, 2)) assert edge_data1.weight == edge_module.DEFAULT_WEIGHT, "weight should be default" g.add_edge(3, 4, 9.5) edge_data2 = pp_module.EdgeData.from_edge_obj(g.get_edge(3, 4)) assert edge_data2.weight == 9.5, "weight should be 9.5" v5 = pp_module.VertexData("5") v6 = pp_module.VertexData("6") edge_data3 = pp_module.EdgeData(v5, v6) assert edge_data3.weight == edge_module.DEFAULT_WEIGHT, "weight should be default"
def test_incident_edges_and_loop_edge(self) -> None: g = Graph() g.add_vertex(0) assert not g[0].loop_edge, "vertex 0 should not have a loop edge" g.add_edge(1, 1) assert g[1].incident_edges() == {g.get_edge( 1, 1)}, "vertex 1 should have self loop as incident edge" assert g[1].loop_edge, "vertex 1 should have a self loop" g.add_edge(1, 2) assert len(g[1].incident_edges() ) == 2, "vertex 1 should have two incident edges"
def test_remove(self) -> None: g = Graph([(1, 2), (2, 3)]) assert g.has_edge(1, 2), "prior to removal, graph should have edge (1, 2)" assert not g[1].is_isolated( ), "vertex 1 should not be isolated prior to edge removal" g.get_edge(1, 2).remove(remove_semi_isolated_vertices=False) assert not g.has_edge( 1, 2), "after removal, graph should not have edge (1, 2)" assert g.has_vertex( 1 ), "after edge removal, isolated vertex 1 should still be in graph" assert g[1].is_isolated( ), "vertex 1 should be isolated after edge removal" g2 = Graph([(1, 2), (1, 1), (2, 3)]) g2.get_edge(1, 2).remove(remove_semi_isolated_vertices=True) assert not g2.has_vertex( 1 ), "after edge removal, semi-isolated vertex 1 should have been removed"
def test_equality_operator(self) -> None: g = Graph([(1, 2), (3, 4, 3.5), (4, 5, 7.5, { "color": "blue" }), (6, 7, 9.5, { "k": "v" })]) g2 = Graph([(2, 1), (3, 4), (4, 5, 7.5, { "color": "red" }), (6, 7, 9.5, { "k": "v" })]) assert g.get_edge(1, 2) == g.get_edge( 1, 2), "edge (1, 2) should equal itself within the same graph" assert g.get_edge(1, 2) == g2.get_edge( 2, 1), "edges (1, 2) and (2, 1) should be the same edge" assert g.get_edge(3, 4) != g2.get_edge( 3, 4), "edges (3, 4) should not be equal due to different weights" assert g.get_edge(4, 5) != g2.get_edge( 4, 5), "edges (4, 5) should not be equal due to different attributes" assert g.get_edge(6, 7) == g2.get_edge(6, 7), "edges (6, 7) should be equal"
def test_attr(self) -> None: v1 = pp_module.VertexData("1") v2 = pp_module.VertexData("2") edge_data = pp_module.EdgeData(v1, v2) assert not edge_data.attr, "there should be no attributes by default" assert not edge_data.edge_object, "there should be no edge object reference" edge_data.attr["color"] = "blue" assert edge_data.attr[ "color"] == "blue", "should have 'color' attribute set to 'blue'" g = Graph() g.add_edge(1, 2) edge_data2 = pp_module.EdgeData.from_edge_obj(g.get_edge(1, 2)) assert not edge_data2.attr, "there should be no attributes from edge (1, 2)" edge_data2.attr["color"] = "blue" assert edge_data2.attr[ "color"] == "blue", "should have 'color' attribute set to 'blue'"
def test_repr_str_and_label(self) -> None: g = Graph([(2, 1)]) assert g.get_edge(2, 1).label == "(1, 2)", "edge label should be (1, 2)" assert (g.get_edge(2, 1).__str__() == g.get_edge( 2, 1).__repr__()), "edge __repr__ should equal __str__" assert g.get_edge( 2, 1).__str__() == "(1, 2)", "edge __str__ should be (1, 2)" g.add_edge(3, 4, weight=1.5) assert g.get_edge(2, 1).label == "(1, 2)", "edge label should be (1, 2)" assert ( g.get_edge(2, 1).__str__() == "(1, 2, 1.0)" ), "edge __str__ should be (1, 2, 1.0) after adding weighted edge to graph"
def test_attr__getitem__setitem__(self) -> None: g = Graph([(1, 2)]) edge = g.get_edge(1, 2) assert not edge.has_attributes_dict( ), "attr dict should not be instantiated" _ = edge.attr assert (edge.has_attributes_dict( )), "attr dict should be instantiated after using property accessor" edge.attr["mass"] = 1000 assert edge.attr[ "mass"] == 1000, "edge should have 'mass' attribute set to 1000" assert edge[ "mass"] == 1000, "edge __getitem__(key) should be alias for edge.attr[key]" edge["color"] = "blue" assert ( edge.attr["color"] == "blue" ), "__setitem__(key, value) should be alias for attr[key] = value" with pytest.raises(KeyError): _ = edge["unknown_key"]
def test_is_vertex_type(self) -> None: g = Graph() v: Vertex = g.add_vertex(1) assert vertex_module.is_vertex_type( v), "Vertex object should be a VertexType" g2 = DiGraph() di_v: DiVertex = g2.add_vertex(1) assert vertex_module.is_vertex_type( di_v), "DiVertex object should be a VertexType" g3 = MultiGraph() multi_v: MultiVertex = g3.add_vertex(1) assert vertex_module.is_vertex_type( multi_v), "MultiVertex object should be a VertexType" g4 = MultiDiGraph() multi_di_v: MultiDiVertex = g4.add_vertex(1) assert vertex_module.is_vertex_type( multi_di_v), "MultiDiVertex should be a VertexType" assert vertex_module.is_vertex_type( 10), "int vertex label should be a VertexType" assert vertex_module.is_vertex_type( "s"), "str vertex label should be a VertexType" assert vertex_module.is_vertex_type(("s", { "color": "blue" })), "vertex tuple should be a VertexType" assert not vertex_module.is_vertex_type( 10.99), "float should not be a VertexType" assert not vertex_module.is_vertex_type( ("s", "t")), "edge tuple should not be a VertexType" assert not vertex_module.is_vertex_type( ("s", "t", 4.5)), "edge tuple with edge weight should not be a VertexType" g.add_edge("s", "t") assert not vertex_module.is_vertex_type(g.get_edge( "s", "t")), "edge object should not be a VertexType"
def test_parse_edge_type(self) -> None: g = Graph() g.add_edge(1, 2) edge_data1 = pp_module.parse_edge_type(g.get_edge(1, 2)) assert edge_data1.vertex1.label == "1" assert edge_data1.vertex2.label == "2" mg = MultiGraph([(3, 4), (3, 4)]) edge_data2 = pp_module.parse_edge_type(mg.get_edge(3, 4)) assert edge_data2.vertex1.label == "3" assert edge_data2.vertex2.label == "4" edge_tuple = (1, 2) edge_data3 = pp_module.parse_edge_type(edge_tuple) assert edge_data3.vertex1.label == "1" assert edge_data3.vertex2.label == "2" edge_tuple_weighted = (3, 4, 3.5) edge_data4 = pp_module.parse_edge_type(edge_tuple_weighted) assert edge_data4.vertex1.label == "3" assert edge_data4.vertex2.label == "4" assert edge_data4.weight == 3.5 edge_tuple_attr = (4, 5, {"color": "blue"}) edge_data5 = pp_module.parse_edge_type(edge_tuple_attr) assert edge_data5.vertex1.label == "4" assert edge_data5.vertex2.label == "5" assert edge_data5.weight == edge_module.DEFAULT_WEIGHT assert edge_data5.attr["color"] == "blue" edge_tuple_weighted_attr = (6, 7, 9.5, {"k": "v"}) edge_data6 = pp_module.parse_edge_type(edge_tuple_weighted_attr) assert edge_data6.vertex1.label == "6" assert edge_data6.vertex2.label == "7" assert edge_data6.weight == 9.5 assert edge_data6.attr["k"] == "v"
def test_vertex1_vertex2(self) -> None: g = Graph() g.add_edge(2, 1) assert g.get_edge(1, 2).vertex1 == 2, "vertex1 should be 2" assert g.get_edge(1, 2).vertex2 == 1, "vertex2 should be 1"
def test_loop(self) -> None: g = Graph([(1, 1)]) assert g.get_edge( 1, 1).is_loop(), "edge (1, 1) should self identify as a loop" assert g.get_edge(1, 1).vertex1 == 1, "loop edge vertex1 should be 1" assert g.get_edge(1, 1).vertex2 == 1, "loop edge vertex2 should be 1"