Source code for causal_networkx.algorithms.dag

from itertools import combinations
from typing import Set, Tuple

from networkx.algorithms import (
    is_directed_acyclic_graph as nx_is_directed_acyclic_graph,
)
from networkx.algorithms import topological_sort as nx_topological_sort

from causal_networkx import ADMG, DAG


[docs]def is_directed_acyclic_graph(G): """Check if ``G`` is a directed acyclic graph (DAG) or not. Parameters ---------- G : instance of DAG The causal graph. Returns ------- is_dag : bool True if ``G`` is a DAG, False otherwise. Examples -------- Undirected graph:: >>> G = ADMG(nx.Graph([(1, 2), (2, 3)])) >>> causal_networkx.is_directed_acyclic_graph(G) False Directed graph with cycle:: >>> G = ADMG(nx.DiGraph([(1, 2), (2, 3), (3, 1)])) >>> causal_networkx.is_directed_acyclic_graph(G) False Directed acyclic graph:: >>> G = ADMG(nx.DiGraph([(1, 2), (2, 3)])) >>> causal_networkx.is_directed_acyclic_graph(G) True See also -------- topological_sort """ return nx_is_directed_acyclic_graph(G.dag)
[docs]def topological_sort(G: ADMG): """Returns a generator of nodes in topologically sorted order. A topological sort is a nonunique permutation of the nodes of a directed graph such that an edge from u to v implies that u appears before v in the topological sort order. This ordering is valid only if the graph has no directed cycles. Parameters ---------- G : ADMG A causal directed acyclic graph (DAG) Yields ------ nodes Yields the nodes in topological sorted order. See also -------- networkx.algorithms.dag.topological_sort """ # topological sorting only occurs from the directed edges, # not bi-directed edges return nx_topological_sort(G.dag)
[docs]def compute_v_structures(graph: DAG) -> Set[Tuple]: """Iterate through the graph to compute all v-structures. Parameters ---------- graph : instance of DAG A causal graph. Returns ------- vstructs : Set[Tuple] The v structures within the graph. """ vstructs: Set[Tuple] = set() for node in graph.nodes: for p1, p2 in combinations(set(graph.parents(node)).union(graph.spouses(node)), 2): if not graph.has_adjacency(p1, p2): p1_, p2_ = sorted((p1, p2)) vstructs.add((p1_, node, p2_)) return vstructs