diff env/lib/python3.9/site-packages/networkx/algorithms/asteroidal.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/env/lib/python3.9/site-packages/networkx/algorithms/asteroidal.py	Mon Mar 22 18:12:50 2021 +0000
@@ -0,0 +1,168 @@
+"""
+Algorithms for asteroidal triples and asteroidal numbers in graphs.
+
+An asteroidal triple in a graph G is a set of three non-adjacent vertices
+u, v and w such that there exist a path between any two of them that avoids
+closed neighborhood of the third. More formally, v_j, v_k belongs to the same
+connected component of G - N[v_i], where N[v_i] denotes the closed neighborhood
+of v_i. A graph which does not contain any asteroidal triples is called
+an AT-free graph. The class of AT-free graphs is a graph class for which
+many NP-complete problems are solvable in polynomial time. Amongst them,
+independent set and coloring.
+"""
+import networkx as nx
+from networkx.utils import not_implemented_for
+
+__all__ = ["is_at_free", "find_asteroidal_triple"]
+
+
+@not_implemented_for("directed")
+@not_implemented_for("multigraph")
+def find_asteroidal_triple(G):
+    r"""Find an asteroidal triple in the given graph.
+
+    An asteroidal triple is a triple of non-adjacent vertices such that
+    there exists a path between any two of them which avoids the closed
+    neighborhood of the third. It checks all independent triples of vertices
+    and whether they are an asteroidal triple or not. This is done with the
+    help of a data structure called a component structure.
+    A component structure encodes information about which vertices belongs to
+    the same connected component when the closed neighborhood of a given vertex
+    is removed from the graph. The algorithm used to check is the trivial
+    one, outlined in [1]_, which has a runtime of
+    :math:`O(|V||\overline{E} + |V||E|)`, where the second term is the
+    creation of the component structure.
+
+    Parameters
+    ----------
+    G : NetworkX Graph
+        The graph to check whether is AT-free or not
+
+    Returns
+    -------
+    list or None
+        An asteroidal triple is returned as a list of nodes. If no asteroidal
+        triple exists, i.e. the graph is AT-free, then None is returned.
+        The returned value depends on the certificate parameter. The default
+        option is a bool which is True if the graph is AT-free, i.e. the
+        given graph contains no asteroidal triples, and False otherwise, i.e.
+        if the graph contains at least one asteroidal triple.
+
+    Notes
+    -----
+    The component structure and the algorithm is described in [1]_. The current
+    implementation implements the trivial algorithm for simple graphs.
+
+    References
+    ----------
+    .. [1] Ekkehard Köhler,
+       "Recognizing Graphs without asteroidal triples",
+       Journal of Discrete Algorithms 2, pages 439-452, 2004.
+       https://www.sciencedirect.com/science/article/pii/S157086670400019X
+    """
+    V = set(G.nodes)
+
+    if len(V) < 6:
+        # An asteroidal triple cannot exist in a graph with 5 or less vertices.
+        return None
+
+    component_structure = create_component_structure(G)
+    E_complement = set(nx.complement(G).edges)
+
+    for e in E_complement:
+        u = e[0]
+        v = e[1]
+        u_neighborhood = set(G[u]).union([u])
+        v_neighborhood = set(G[v]).union([v])
+        union_of_neighborhoods = u_neighborhood.union(v_neighborhood)
+        for w in V - union_of_neighborhoods:
+            """Check for each pair of vertices whether they belong to the
+            same connected component when the closed neighborhood of the
+            third is removed."""
+            if (
+                component_structure[u][v] == component_structure[u][w]
+                and component_structure[v][u] == component_structure[v][w]
+                and component_structure[w][u] == component_structure[w][v]
+            ):
+                return [u, v, w]
+
+    return None
+
+
+@not_implemented_for("directed")
+@not_implemented_for("multigraph")
+def is_at_free(G):
+    """Check if a graph is AT-free.
+
+    The method uses the `find_asteroidal_triple` method to recognize
+    an AT-free graph. If no asteroidal triple is found the graph is
+    AT-free and True is returned. If at least one asteroidal triple is
+    found the graph is not AT-free and False is returned.
+
+    Parameters
+    ----------
+    G : NetworkX Graph
+        The graph to check whether is AT-free or not.
+
+    Returns
+    -------
+    bool
+        True if G is AT-free and False otherwise.
+
+    Examples
+    --------
+    >>> G = nx.Graph([(0, 1), (0, 2), (1, 2), (1, 3), (1, 4), (4, 5)])
+    >>> nx.is_at_free(G)
+    True
+
+    >>> G = nx.cycle_graph(6)
+    >>> nx.is_at_free(G)
+    False
+    """
+    return find_asteroidal_triple(G) is None
+
+
+@not_implemented_for("directed")
+@not_implemented_for("multigraph")
+def create_component_structure(G):
+    r"""Create component structure for G.
+
+    A *component structure* is an `nxn` array, denoted `c`, where `n` is
+    the number of vertices,  where each row and column corresponds to a vertex.
+
+    .. math::
+        c_{uv} = \begin{cases} 0, if v \in N[u] \\
+            k, if v \in component k of G \setminus N[u] \end{cases}
+
+    Where `k` is an arbitrary label for each component. The structure is used
+    to simplify the detection of asteroidal triples.
+
+    Parameters
+    ----------
+    G : NetworkX Graph
+        Undirected, simple graph.
+
+    Returns
+    -------
+    component_structure : dictionary
+        A dictionary of dictionaries, keyed by pairs of vertices.
+
+    """
+    V = set(G.nodes)
+    component_structure = {}
+    for v in V:
+        label = 0
+        closed_neighborhood = set(G[v]).union({v})
+        row_dict = {}
+        for u in closed_neighborhood:
+            row_dict[u] = 0
+
+        G_reduced = G.subgraph(set(G.nodes) - closed_neighborhood)
+        for cc in nx.connected_components(G_reduced):
+            label += 1
+            for u in cc:
+                row_dict[u] = label
+
+        component_structure[v] = row_dict
+
+    return component_structure