Пример #1
0
    def __init__(
        self,
        gid: str,
        nodes: Union[Set[AbstractNode], FrozenSet[AbstractNode]],
        edges: Union[Set[AbstractEdge], FrozenSet[AbstractEdge]],
        data={},
    ):
        super().__init__(oid=gid, odata=data)
        if not isinstance(nodes, (frozenset, set)):
            raise TypeError("Nodes must be a set or a frozenset")
        if not isinstance(edges, (frozenset, set)):
            raise TypeError("Edges must be a set or a frozenset")
        self._nodes: FrozenSet[AbstractNode] = BaseGraphOps.get_nodes(
            ns=nodes, es=edges
        )
        self._edges: FrozenSet[AbstractEdge] = frozenset(edges)
        #
        self.gdata: Dict[str, List[str]] = BaseGraphOps.to_edgelist(self)
        if self._nodes is not None:
            self.is_empty = len(self._nodes) == 0
        else:
            self.is_empty = True

        is_trivial = BaseGraphAnalyzer.is_trivial(self)
        if is_trivial:
            msg = "This library is not compatible with computations with trivial graph"
            msg += "\nNodes: "
            msg += str([n.id() for n in self.V])
            msg += "\nEdges: " + str([e.id() for e in self.E])
            raise ValueError(msg)
Пример #2
0
 def test_to_edgelist(self):
     gdata = BaseGraphOps.to_edgelist(self.graph)
     mdata = gdata
     gdata = {"n4": [], "n1": ["e1"], "n3": ["e2"], "n2": ["e1", "e2"]}
     for k, vs in mdata.copy().items():
         self.assertEqual(k in mdata, k in gdata)
         for v in vs:
             self.assertEqual(v in mdata[k], v in gdata[k])
Пример #3
0
 def max_degree_vs(g: AbstractGraph) -> Set[AbstractNode]:
     """!
     \brief obtain vertex set of whose degrees are equal to maximum degree.
     """
     md = BaseGraphAnalyzer.max_degree(g)
     gdata = BaseGraphOps.to_edgelist(g)
     nodes = set([v for v in g.V if len(gdata[v.id()]) == md])
     return nodes
Пример #4
0
 def min_degree_vs(g: AbstractGraph) -> Set[AbstractNode]:
     """!
     \brief obtain set of vertices whose degree equal to minimum degree of
     graph instance
     """
     md = BaseGraphAnalyzer.min_degree(g)
     gdata = BaseGraphOps.to_edgelist(g)
     nodes = set([v for v in g.V if len(gdata[v.id()]) == md])
     return nodes
Пример #5
0
    def is_neighbour_of(self, n1: AbstractNode, n2: AbstractNode) -> bool:
        """!
        \brief check if two nodes are neighbours
        We define the condition of neighborhood as having a common edge, not
        being the same

        \code{.py}

        >>> n1 = Node("n1", {})
        >>> n2 = Node("n2", {})
        >>> n3 = Node("n3", {})
        >>> n4 = Node("n4", {})
        >>> e1 = Edge(
        >>>     "e1", start_node=n1, end_node=n2, edge_type=EdgeType.UNDIRECTED
        >>> )
        >>> e2 = Edge(
        >>>     "e2", start_node=n2, end_node=n3, edge_type=EdgeType.UNDIRECTED
        >>> )
        >>> e3 = Edge(
        >>>     "e3", start_node=n3, end_node=n4, edge_type=EdgeType.UNDIRECTED
        >>> )
        >>> graph_2 = Graph(
        >>>   "g2",
        >>>   data={"my": "graph", "data": "is", "very": "awesome"},
        >>>   nodes=set([n1, n2, n3, n4]),
        >>>   edges=set([e1, e2, e3]),
        >>> )
        >>> graph_2.is_neighbour_of(n2, n3)
        >>> True
        >>> graph_2.is_neighbour_of(n2, n2)
        >>> False

        \endcode
        """

        def cond(
            n_1: AbstractNode, n_2: AbstractNode, e: AbstractEdge
        ) -> bool:
            """!
            \brief neighborhood condition
            """
            estart = e.start()
            eend = e.end()
            c1 = estart == n_1 and eend == n_2
            c2 = estart == n_2 and eend == n_1
            return c1 or c2

        gdata = BaseGraphOps.to_edgelist(self)

        n1_edge_ids = set(gdata[n1.id()])
        n2_edge_ids = set(gdata[n2.id()])
        edge_ids = n1_edge_ids.intersection(n2_edge_ids)
        # filter self loops
        edges = set([e for e in self.E if e.id() in edge_ids])
        return self.is_related_to(n1=n1, n2=n2, condition=cond, es=edges)
Пример #6
0
    def average_degree(g: AbstractGraph) -> float:
        """!
        \brief obtain the average degree of graph instance

        The average degree is calculated using the formula:
        \f[ d(G) = \frac{1}{V[G]} \sum_{v \in V[G]} d(v) \f]

        It can be found in Diestel 2017, p. 5
        """
        gdata = BaseGraphOps.to_edgelist(g)
        return sum([len(gdata[v.id()]) for v in g.V]) / len(g.V)
Пример #7
0
    def comp_degree(g: AbstractGraph, fn: Callable[[int, int], bool],
                    comp_val: int) -> int:
        """!
        \brief generic comparison function for degree related operations

        It is used in the context of finding maximum or minimum degree of the
        graph instance.
        """
        compare_v = comp_val
        gdata = BaseGraphOps.to_edgelist(g)
        for nid in g.V:
            nb_edges = len(gdata[nid.id()])
            if fn(nb_edges, compare_v):
                compare_v = nb_edges
        return compare_v
Пример #8
0
 def added_edge_between_if_none(
     g: AbstractGraph,
     n1: AbstractNode,
     n2: AbstractNode,
     is_directed: bool = False,
 ) -> BaseGraph:
     """!
     Add edge between nodes. If there are no edges in between.
     The flag is_directed specifies if the edge is directed or not
     """
     if not BaseGraphOps.is_in(g, n1) or not BaseGraphOps.is_in(g, n2):
         raise ValueError("one of the nodes is not present in graph")
     n1id = n1.id()
     n2id = n2.id()
     gdata = BaseGraphOps.to_edgelist(g)
     first_eset = set(gdata[n1id])
     second_eset = set(gdata[n2id])
     common_edge_ids = first_eset.intersection(second_eset)
     if len(common_edge_ids) == 0:
         # there are no edges between the nodes
         if isinstance(g, AbstractUndiGraph):
             edge = Edge.undirected(eid=str(uuid4()),
                                    start_node=n1,
                                    end_node=n2)
             return BaseGraphAlgOps.add(g, edge)
         elif isinstance(g, AbstractDiGraph):
             edge = Edge.directed(eid=str(uuid4()),
                                  start_node=n1,
                                  end_node=n2)
             return BaseGraphAlgOps.add(g, edge)
         elif is_directed is True:
             edge = Edge.directed(eid=str(uuid4()),
                                  start_node=n1,
                                  end_node=n2)
             return BaseGraphAlgOps.add(g, edge)
         elif is_directed is False:
             edge = Edge.undirected(eid=str(uuid4()),
                                    start_node=n1,
                                    end_node=n2)
             return BaseGraphAlgOps.add(g, edge)
         else:
             raise ValueError("Must specify an edge type to be added")
     else:
         # there is already an edge in between
         return g