예제 #1
0
    def test_from_vertex_obj(self) -> None:
        g = Graph()
        g.add_vertex(1, color="blue")

        vertex_data = pp_module.VertexData.from_vertex_obj(g[1])
        assert vertex_data.label == "1", "label should be '1'"
        assert vertex_data.attr[
            "color"] == "blue", "should have 'color' attribute set to 'blue'"
        assert vertex_data.vertex_object, "should have reference to vertex object"
예제 #2
0
 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
예제 #3
0
 def test_issubclass_and_isinstance(self) -> None:
     g = Graph()
     v1 = g.add_vertex(1)
     assert isinstance(
         v1, vertex_module.VertexBase
     ), "v1 should be an instance of superclass VertexBase"
     assert isinstance(v1, Vertex), "v1 should be a Vertex instance"
     assert issubclass(
         Vertex,
         vertex_module.VertexBase), "Vertex should be VertexBase subclass"
예제 #4
0
    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"
예제 #5
0
    def test_basic_operations(self) -> None:
        g = Graph([(1, 2), (2, 3), (3, 4), (4, 5)])
        vertex_priority: VertexDict[float] = VertexDict()
        vertex_priority[1] = 100
        vertex_priority[2] = 90
        vertex_priority[3] = 80
        vertex_priority[4] = 70
        vertex_priority[5] = 70

        priority_function = get_priority_function(vertex_priority)

        vpq: PriorityQueue[Vertex] = PriorityQueue(priority_function)
        vpq.add_or_update(g[5])
        vpq.add_or_update(g[4])
        vpq.add_or_update(g[1])
        vpq.add_or_update(g[2])
        vpq.add_or_update(g[3])

        assert len(vpq) == 5, "Priority queue should contain 5 vertices."
        next_v = vpq.pop()
        assert next_v == g[
            5], "First lowest priority vertex should be vertex 5."

        next_v = vpq.pop()
        assert next_v == g[4], (
            "Second lowest priority vertex should be vertex 4, since 4 "
            " was inserted after 5.")
        vertex_priority[1] = 0
        vpq.add_or_update(g[1])
        assert len(vpq) == 3, (
            "Priority queue should contain 3 vertices after popping and "
            " updating.")
        next_v = vpq.pop()
        assert next_v == g[
            1], "Lowest priority vertex should be 1 after setting priority to 0."

        next_v = vpq.pop()
        assert next_v == g[3], "Lowest priority vertex should be 3."

        g.add_vertex(10)
        vertex_priority[10] = 200
        vpq.add_or_update(g[10])

        next_v = vpq.pop()
        assert next_v == g[2], "Lowest priority vertex should be 2."

        assert len(vpq) == 1, "Priority queue should contain 1 vertex."
        next_v = vpq.pop()
        assert next_v == g[10], "Lowest priority vertex should be 10."

        assert len(vpq) == 0, "Priority queue should be empty."

        # Attempting to pop an item from an empty priority queue should raise KeyError.
        with pytest.raises(KeyError):
            vpq.pop()
예제 #6
0
 def test_repr_str_and_label(self) -> None:
     g = Graph()
     v1 = g.add_vertex("a")
     v2 = g.add_vertex(2)
     assert v1.label == "a", "v1 label should be 'a'"
     assert v2.label == "2", "v2 label should be '2'"
     assert v1.__repr__(
     ) == v1.label, "vertex __repr__() should be its label"
     assert v1.__str__() == v1.label, "vertex __str__() should be its label"
     assert v1.__repr__() == v1.__str__(
     ), "vertex __repr__() should match __str__()"
예제 #7
0
 def test_get_vertex_label(self) -> None:
     g = Graph()
     v_obj: Vertex = g.add_vertex(1)
     assert vertex_module.get_vertex_label(
         v_obj) == "1", "vertex object label should be '1'"
     assert vertex_module.get_vertex_label(
         10) == "10", "int vertex label should be '10'"
     assert vertex_module.get_vertex_label(
         "s") == "s", "str vertex label should be 's'"
     assert (vertex_module.get_vertex_label(("s", {
         "color": "blue"
     })) == "s"), "vertex tuple should have label 's'"
예제 #8
0
 def test_issubclass_and_isinstance(self) -> None:
     g = Graph()
     edge: Edge = g.add_edge(1, 2)
     assert isinstance(
         edge, edge_module.EdgeBase
     ), "edge should be an instance of superclass EdgeBase"
     assert isinstance(
         edge, edge_module.MutableEdgeBase
     ), "edge should be an instance of superclass MutableEdgeBase"
     assert isinstance(edge, Edge), "edge should be an Edge instance"
     assert issubclass(
         Edge, edge_module.EdgeBase), "Edge should be EdgeBase subclass"
     assert issubclass(Edge, edge_module.MutableEdgeBase
                       ), "Edge should be MutableEdgeBase subclass"
예제 #9
0
    def test_create_edge_label(self) -> None:
        g = Graph()
        v1 = g.add_vertex(1)
        v2 = g.add_vertex(2)
        assert (edge_module.create_edge_label(
            v1, v1, is_directed=g.is_directed()) == "(1, 1)"
                ), "loop edge label should be (1, 1)"
        assert (edge_module.create_edge_label(
            v1, v2, is_directed=g.is_directed()) == "(1, 2)"
                ), "edge label should be (1, 2)"
        assert (edge_module.create_edge_label(
            v2, v1, is_directed=g.is_directed()) == "(1, 2)"
                ), "edge label should be (1, 2)"
        assert (edge_module.create_edge_label(
            5, 9, is_directed=g.is_directed()) == "(5, 9)"
                ), "edge label should be (5, 9)"
        assert (edge_module.create_edge_label(
            "t", "s", is_directed=g.is_directed()) == "(s, t)"
                ), "edge label should be (s, t)"

        g2 = DiGraph()
        v3 = g2.add_vertex(3)
        v4 = g2.add_vertex(4)
        assert (edge_module.create_edge_label(
            v3, v4, is_directed=g2.is_directed()) == "(3, 4)"
                ), "edge label should be (3, 4)"
        assert (edge_module.create_edge_label(
            v4, v3, is_directed=g2.is_directed()) == "(4, 3)"
                ), "edge label should be (4, 3)"
        assert (edge_module.create_edge_label(
            "t", "s", is_directed=g2.is_directed()) == "(t, s)"
                ), "edge label should be (t, s)"
예제 #10
0
 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"
예제 #11
0
    def test_comparison_operators(self) -> None:
        g = Graph()
        v1 = g.add_vertex("a")
        v2 = g.add_vertex("b")

        assert v1 < v2, "v1 should be less than v2"
        assert v1 <= v2, "v1 should be less than or equal to v2"
        assert v2 > v1, "v2 should be greater than v1"
        assert v2 >= v1, "v2 should be greater than or equal to v1"
        assert v1 == "a", "v1 should be equal to a vertex represented by label 'a'"
        assert v1 < "b", "v1 should be less than a vertex represented by label 'b'"
        assert v1 > 1, "v1 should be great than a vertex represented by label 1"
        assert v1 < ("b", {
            "color": "blue"
        }), "v1 should be less than vertex tuple 'b'"
예제 #12
0
    def test_attr_dictionary(self) -> None:
        g = Graph()
        v1 = g.add_vertex("a")
        assert v1._attr is None, "attr dictionary should be None by default"
        v1.attr["weight"] = 1000
        assert v1.attr[
            "weight"] == 1000, "v1 should have 'weight' attribute set to 1000"
        assert v1[
            "weight"] == 1000, "'weight' attribute should be accessible with index getter"
        v1["color"] = "blue"
        assert v1[
            "color"] == "blue", "v1 should have color attribute set to 'blue'"

        with pytest.raises(KeyError):
            _ = v1["unknown_key"]
예제 #13
0
    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"
예제 #14
0
    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"
예제 #15
0
    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'"
예제 #16
0
    def test_parse_vertex_type(self) -> None:
        g = Graph()
        g.add_vertex(1, mass=5.5)
        vertex_data1 = pp_module.parse_vertex_type(g[1])
        assert vertex_data1.label == "1"
        assert vertex_data1.attr["mass"] == 5.5

        mg = MultiGraph([(3, 4), (3, 4)])
        vertex_data2 = pp_module.parse_vertex_type(mg[4])
        assert vertex_data2.label == "4"

        vertex_data3 = pp_module.parse_vertex_type(3)
        assert vertex_data3.label == "3"

        vertex_data4 = pp_module.parse_vertex_type("s")
        assert vertex_data4.label == "s"

        vertex_data5 = pp_module.parse_vertex_type(("t", {"mass": 42}))
        assert vertex_data5.label == "t"
        assert vertex_data5.attr["mass"] == 42.0
예제 #17
0
    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"]
예제 #18
0
    def test_degree(self) -> None:
        g = Graph()
        v0 = g.add_vertex(0)
        assert v0.degree == 0, "vertex 0 should have degree 0"

        g.add_edge(1, 1)
        assert g[1].degree == 2, "vertex 1 with self loop should have degree 2"

        g.add_edge(1, 2)
        assert g[1].degree == 3, "vertex 1 should have degree 3"
예제 #19
0
    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"
예제 #20
0
    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"
예제 #21
0
    def test_is_isolated(self) -> None:
        g = Graph()
        v1 = g.add_vertex(1)
        assert v1.is_isolated(), "v1 should be isolated"

        g.add_edge(v1, v1)
        assert v1.loop_edge, "v1 should have a self loop"
        assert not v1.is_isolated(
        ), "vertex with self-loop should not be considered isolated"
        assert v1.is_isolated(
            ignore_self_loops=True
        ), "vertex with self-loop should be considered semi-isolated"

        g.add_edge(v1, 2)
        assert not v1.is_isolated(
        ), "vertex connected to a different vertex should not be isolated"

        v1.remove_incident_edges()
        assert v1.is_isolated(
        ), "vertex should be isolated after removing incident edges"
예제 #22
0
    def test_remove_and_edge_removal(self) -> None:
        g = Graph()
        v1 = g.add_vertex("a")
        assert g.vertex_count == 1, "graph should have one vertex"
        v1.remove()
        assert g.vertex_count == 0, "graph should have zero vertices after vertex self removal"
        v2 = g.add_vertex("b")
        g.add_edge("b", "c")
        g.add_edge("b", "b")

        with pytest.raises(VertizeeException):
            v2.remove()

        assert len(
            v2.incident_edges()) == 2, "v2 should have two incident edges"
        v2.remove_loops()
        assert v2.loop_edge is None, "v2 should not have a loop edge after removal"
        assert len(v2.incident_edges()
                   ) == 1, "v2 should have one incident after removing loop"
        v2.remove_incident_edges()
        assert len(v2.incident_edges(
        )) == 0, "v2 should not have any incident edges after removal"
예제 #23
0
    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"
예제 #24
0
 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"
예제 #25
0
    def test_adj_vertices(self) -> None:
        g = Graph()
        g.add_vertex(1)
        assert not g[1].adj_vertices(
        ), "vertex 1 should have no adjacent vertices"

        g.add_edge(1, 2)
        assert next(iter(
            g[1].adj_vertices())) == 2, "vertex 1 should adjacent to vertex 2"

        g.add_edge(1, 3)
        assert len(g[1].adj_vertices()
                   ) == 2, "vertex 1 should be adjacent to vertices 2 and 3"
        assert next(iter(g[3].adj_vertices())
                    ) == g[1], "vertex 3 should be adjacent to vertex 1"

        g.add_edge(2, 4)
        assert g[4] not in g[1].adj_vertices(
        ), "vertex 1 should not be adjacent to vertex 4"
        assert g[2] not in g[2].adj_vertices(
        ), "vertex 2 should not be adjacent to itself"

        g.add_edge(4, 4)
        assert g[4] in g[4].adj_vertices(
        ), "vertex 4 should be adjacent to itself"
예제 #26
0
 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"
예제 #27
0
 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"
예제 #28
0
    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"