aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/networkx/algorithms/asteroidal.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/networkx/algorithms/asteroidal.py')
-rw-r--r--.venv/lib/python3.12/site-packages/networkx/algorithms/asteroidal.py171
1 files changed, 171 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/networkx/algorithms/asteroidal.py b/.venv/lib/python3.12/site-packages/networkx/algorithms/asteroidal.py
new file mode 100644
index 00000000..3f9b2ab5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/networkx/algorithms/asteroidal.py
@@ -0,0 +1,171 @@
+"""
+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")
+@nx._dispatchable
+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")
+@nx._dispatchable
+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")
+@nx._dispatchable
+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