pywhy_graphs.CPDAG#

class pywhy_graphs.CPDAG(incoming_directed_edges=None, incoming_undirected_edges=None, directed_edge_name: str = 'directed', undirected_edge_name: str = 'undirected', **attr)[source]#

Completed partially directed acyclic graphs (CPDAG).

CPDAGs generalize causal DAGs by allowing undirected edges. Undirected edges imply uncertainty in the orientation of the causal relationship. For example, A - B, can be A -> B or A <- B, allowing for a Markov equivalence class of DAGs for each CPDAG.

Parameters:
incoming_directed_edgesinput directed edges (optional, default: None)

Data to initialize directed edges. All arguments that are accepted by networkx.DiGraph are accepted.

incoming_undirected_edgesinput undirected edges (optional, default: None)

Data to initialize undirected edges. All arguments that are accepted by networkx.Graph are accepted.

directed_edge_namestr

The name for the directed edges. By default ‘directed’.

undirected_edge_namestr

The name for the directed edges. By default ‘undirected’.

attrkeyword arguments, optional (default= no attributes)

Attributes to add to graph as key=value pairs.

Notes

CPDAGs are Markov equivalence class of causal DAGs. The implicit assumption in these causal graphs are the Structural Causal Model (or SCM) is Markovian, inducing causal sufficiency, where there is no unobserved latent confounder. This allows CPDAGs to be learned from score-based (such as the “GES” algorithm) and constraint-based (such as the PC algorithm) approaches for causal structure learning.

One should not use CPDAGs if they suspect their data has unobserved latent confounders.

Edge Type Subgraphs

The data structure underneath the hood is stored in two networkx graphs: networkx.Graph and networkx.DiGraph to represent the non-directed edges and directed edges. Non-directed edges in an CPDAG can be present as undirected edges standing for uncertainty in which directino the directed edge is in.

  • Directed edges (<-, ->, indicating causal relationship) = networkx.DiGraph

    The subgraph of directed edges may be accessed by the CPDAG.sub_directed_graph. Their edges in networkx format can be accessed by CPDAG.directed_edges and the corresponding name of the edge type by CPDAG.directed_edge_name.

  • Undirected edges (–, indicating uncertainty) = networkx.Graph

    The subgraph of undirected edges may be accessed by the CPDAG.sub_undirected_graph. Their edges in networkx format can be accessed by CPDAG.undirected_edges and the corresponding name of the edge type by CPDAG.undirected_edge_name.

By definition, no cycles may exist due to the directed edges.

add_edge(u_of_edge, v_of_edge, edge_type='all', **attr)[source]#

Add an edge between u and v.

The nodes u and v will be automatically added if they are not already in the graph.

Edge attributes can be specified with keywords or by directly accessing the edge’s attribute dictionary.

Parameters:
u_for_edge, v_for_edgenodes

Nodes can be, for example, strings or numbers. Nodes must be hashable (and not None) Python objects.

edge_typestr

The edge type. By default ‘all’, which will then add an edge in all edge type subgraphs.

attrkeyword arguments, optional

Edge data (or labels or objects) can be assigned using keyword arguments.

See also

add_edges_from

add a collection of edges

add_edges_from(ebunch_to_add, edge_type, **attr)[source]#

Add all the edges in ebunch_to_add.

Parameters:
ebunch_to_addcontainer of edges

Each edge given in the container will be added to the graph. The edges must be given as 2-tuples (u, v) or 3-tuples (u, v, d) where d is a dictionary containing edge data.

edge_typestr

The edge type to add edges to. By default ‘all’, which will then add an edge in all edge type subgraphs.

attrkeyword arguments, optional

Edge data (or labels or objects) can be assigned using keyword arguments.

See also

add_edge

add a single edge

Notes

Adding the same edge twice has no effect but any edge data will be updated when each duplicate edge is added.

Edge attributes specified in an ebunch take precedence over attributes specified via keyword arguments.

property directed_edge_name: str#

Name of the directed edge internal graph.

property directed_edges: Mapping#

EdgeView of the directed edges.

orient_uncertain_edge(u: int | float | str | Any, v: int | float | str | Any) None[source]#

Orient undirected edge into an arrowhead.

If there is an undirected edge u - v, then the arrowhead will orient u -> v. If the correct order is v <- u, then simply pass the arguments in different order.

Parameters:
unode

The parent node

vnode

The node that ‘u’ points to in the graph.

possible_children(n: int | float | str | Any) Iterator[int | float | str | Any][source]#

Return an iterator over children of node n.

Children of node ‘n’ are nodes with a directed edge from ‘n’ to that node. For example, ‘n’ -> ‘x’, ‘n’ -> ‘y’. Nodes only connected via a bidirected edge are not considered children: ‘n’ <-> ‘y’.

Parameters:
nnode

A node in the causal DAG.

Returns:
childrenIterator

An iterator of the children of node ‘n’.

possible_parents(n: int | float | str | Any) Iterator[int | float | str | Any][source]#

Return an iterator over parents of node n.

Parents of node ‘n’ are nodes with a directed edge from ‘n’ to that node. For example, ‘n’ <- ‘x’, ‘n’ <- ‘y’. Nodes only connected via a bidirected edge are not considered parents: ‘n’ <-> ‘y’.

Parameters:
nnode

A node in the causal DAG.

Returns:
parentsIterator

An iterator of the parents of node ‘n’.

sub_directed_graph() DiGraph[source]#

Sub-graph of just the directed edges.

sub_undirected_graph() Graph[source]#

Sub-graph of just the undirected edges.

property undirected_edge_name: str#

Name of the undirected edge internal graph.

property undirected_edges: Mapping#

EdgeView of the undirected edges.

Examples using pywhy_graphs.CPDAG#

An introduction to causal graphs and how to use them

An introduction to causal graphs and how to use them

Drawing graphs and setting their layout for visual comparison

Drawing graphs and setting their layout for visual comparison