Causal Model in pyAgrum

Causality in pyAgrum primarily involves building a causal model—that is, constructing an (observational) Bayesian network along with a set of latent variables and defining their relationships with observed variables. It also includes the ability to compute causal effects in such models using do-calculus.
pyAgrum provides a set of tools to perform causal inference and estimate causal effects from data. This includes the ability to identify interventions, compute causal impacts, and evaluate the effects of interventions on observed variables.
Note
The causal module can use a LaTeX special arrow () to compactly represent an intervention. By default, it uses the classical “do” notation. You can change this behavior using the following configuration keys:
pyagrum.config["causal","latex_do_prefix"]="\hookrightarrow("pyagrum.config["causal","latex_do_suffix"]=")"A pyagrum.CausalModel extends a pyagrum.BayesNet with latent (hidden) variables
and explicit causal assumptions. It is the entry point for do-calculus reasoning and causal effect
identification.
SEE ALSO
Section titled “SEE ALSO”Causal computation in pyAgrum : Functions for computing causal impacts and applying do-calculus.
class pyagrum.CausalModel(*args)
Section titled “class pyagrum.CausalModel(*args)”A causal model pairing an observational Bayesian network with a causal DAG.
A CausalModel extends an observational BayesNet by adding latent (hidden) variables that represent unobserved common causes between observed variables. The causal DAG includes both observed and latent nodes, while the observational BN contains only the observed ones.
CausalModel(bn) -> CausalModel : Parameters: : - bn (pyagrum.BayesNet) – the observational Bayesian network.
CausalModel(bn, latents, assumeNonSpurious=False) -> CausalModel
: Parameters:
: - bn (pyagrum.BayesNet) – the observational Bayesian network.
- latents (list of (str, list of str)) – description of latent
variables. Each entry is a pair (name, children) where name
is the latent variable name and children is the list of observed
variable names it affects.
- assumeNonSpurious (bool) – if True, existing arcs between the children
of each latent variable are preserved. Default is False (arcs between
affected children are removed as they are assumed to be explained by
the latent confounder).
Examples
>>> import pyagrum as gum>>> bn = pyagrum.BayesNet.fastPrototype('X->Y;X->Z;Y->Z')>>> cm = pyagrum.CausalModel(bn)Create a model with a latent confounder U between X and Y:
>>> cm = pyagrum.CausalModel(bn, [('U', ['X', 'Y'])], assumeNonSpurious=False)addLatentVariable(*args)
Section titled “addLatentVariable(*args)”Add a latent (hidden) variable to the causal model.
The latent variable is added as a common cause of the specified children. By default, any existing arc between two affected children is removed, as it is assumed to be explained by the new latent confounder.
- Parameters:
- name (str) – Name of the new latent variable.
- children (list of str) – Names of the observed variables that are children of this latent variable.
- assumeNonSpurious (bool , optional) – If True, preserve existing arcs between the specified children. Default is False.
- Return type:
None
assumeNonSpurious(*args)
Section titled “assumeNonSpurious(*args)”Mark an arc in the causal DAG as non-spurious (a genuine causal effect).
- Parameters:
- x (int or str) – Tail of the arc (NodeId or variable name).
- y (int or str) – Head of the arc (NodeId or variable name).
- Return type:
None
assumeSpurious(*args)
Section titled “assumeSpurious(*args)”Mark an arc in the causal DAG as spurious.
A spurious arc x→y means the observed correlation between x and y is believed to be explained by a latent common cause rather than a direct causal effect. This changes the structural interpretation but does not remove the arc.
- Parameters:
- x (int or str) – Tail of the arc (NodeId or variable name).
- y (int or str) – Head of the arc (NodeId or variable name).
- Return type:
None
backDoor(*args)
Section titled “backDoor(*args)”Find a backdoor adjustment set between cause and effect.
Returns the first valid backdoor adjustment set found. A backdoor set Z blocks all spurious (non-causal) paths between cause and effect while leaving all directed causal paths open, enabling estimation of the causal effect P(effect | do(cause)) via standard conditioning on Z.
- Parameters:
- cause (int or str) – The treatment variable (NodeId or variable name).
- effect (int or str) – The outcome variable (NodeId or variable name).
- Returns:
A valid backdoor adjustment set as NodeIds, or
Noneif no backdoor set exists. Note: an empty set is a valid backdoor (returned when X has no back-door paths);Nonemeans the causal effect cannot be identified via the backdoor criterion. - Return type:
list[int] |None
SEE ALSO
Section titled “SEE ALSO”pyagrum.DoorCriteria.enumerateBackdoorSets
: enumerate all valid sets.
causalBN()
Section titled “causalBN()”Deprecated alias for causalDAG. Use causalDAG() instead.
Deprecated
Section titled “Deprecated”Deprecated since version 2.3.2: Use causalDAG() instead.
- Returns: the causal DAG of the model
- Return type: pyagrum.DAG
causalDAG()
Section titled “causalDAG()”Return the full causal DAG, including latent variables.
- Returns: The causal DAG (observed + latent nodes).
- Return type:
DAG
children(*args)
Section titled “children(*args)”Return the children of a variable in the causal DAG.
- Parameters: x (int or str) – The variable (NodeId or name).
- Returns: NodeIds of the variable’s children in the causal DAG.
- Return type:
list[int]
connectedComponents()
Section titled “connectedComponents()”Return the connected components of the causal DAG (treating arcs as undirected).
- Returns: A mapping from component index to the set of NodeIds in that component.
- Return type:
dict[int,list[int]]
existsArc(*args)
Section titled “existsArc(*args)”Check whether an arc exists in the causal DAG.
- Parameters:
- x (int or str) – Tail of the arc (NodeId or variable name).
- y (int or str) – Head of the arc (NodeId or variable name).
- Returns: True if the arc x→y exists in the causal DAG.
- Return type:
bool
frontDoor(*args)
Section titled “frontDoor(*args)”Find a frontdoor adjustment set between cause and effect.
Returns the first valid frontdoor adjustment set found. A frontdoor set Z intercepts all directed paths from cause to effect and enables estimation of P(effect | do(cause)) even in the presence of unobserved confounders.
- Parameters:
- cause (int or str) – The treatment variable (NodeId or variable name).
- effect (int or str) – The outcome variable (NodeId or variable name).
- Returns:
A valid frontdoor adjustment set as NodeIds, or
Noneif no frontdoor set exists. Note: an empty set is a valid frontdoor in degenerate cases;Nonemeans the causal effect cannot be identified via the frontdoor criterion. - Return type:
list[int] |None
SEE ALSO
Section titled “SEE ALSO”pyagrum.DoorCriteria.enumerateFrontdoorSets
: enumerate all valid sets.
idFromName(name)
Section titled “idFromName(name)”Return the NodeId of a variable by name.
- Parameters:
name (
str) – The variable name. - Returns: The NodeId of the variable.
- Return type:
int - Raises: pyagrum.NotFound – If no variable with that name exists in the causal model.
inducedCausalSubModel(cm, subset)
Section titled “inducedCausalSubModel(cm, subset)”Return the causal sub-model induced by a subset of observed nodes.
The sub-model is restricted to the specified nodes, preserving the relevant portion of the causal DAG and latent structure.
- Parameters:
- cm (
CausalModel) – The original causal model. - subset (
list[int]) – NodeIds of the observed variables to keep.
- cm (
- Returns: The induced causal sub-model.
- Return type:
CausalModel
isAssumedSpurious(*args)
Section titled “isAssumedSpurious(*args)”Check whether the arc x→y is assumed spurious.
- Parameters:
- x (int or str) – Tail of the arc (NodeId or variable name).
- y (int or str) – Head of the arc (NodeId or variable name).
- Returns: True if the arc x→y is marked as spurious.
- Return type:
bool
latentVariablesIds()
Section titled “latentVariablesIds()”Return the NodeIds of all latent (hidden) variables in the causal model.
- Returns: NodeIds of latent variables.
- Return type:
list[int]
latentVariablesNames()
Section titled “latentVariablesNames()”Return the names of all latent (hidden) variables in the causal model.
- Returns: Names of latent variables.
- Return type:
set[str]
nameFromId(id)
Section titled “nameFromId(id)”Return the name of a variable by NodeId.
- Parameters:
id (
int) – The NodeId of the variable. - Returns: The variable name.
- Return type:
str - Raises: pyagrum.NotFound – If no variable with that NodeId exists in the causal model.
names()
Section titled “names()”Return the names of all variables in the causal model (observed and latent).
- Returns: The set of all variable names.
- Return type:
set[str]
observationalBN()
Section titled “observationalBN()”Return the observational Bayesian network underlying the causal model.
Warning
Do not use this BN for causal inference. It represents the observational
distribution only. Use pyagrum.causalImpact() for
interventional queries.
- Returns: The observational BN (observed variables only).
- Return type:
BayesNet
parents(*args)
Section titled “parents(*args)”Return the parents of a variable in the causal DAG.
- Parameters: x (int or str) – The variable (NodeId or name).
- Returns: NodeIds of the variable’s parents in the causal DAG.
- Return type:
list[int]
toDot(*args)
Section titled “toDot(*args)”Return a Graphviz dot string representing the causal model.
Observed nodes are shown with default styling. Latent nodes are displayed with a distinct background colour. Their names are hidden by default.
- Parameters:
- SHOW_LATENT_NAMES (bool , optional) – If True, display the names of latent nodes in the graph. Default is False.
- NODE_BG (str , optional) – Background colour for latent nodes (hex or CSS colour name). Default is ‘#404040’.
- NODE_FG (str , optional) – Text colour for latent nodes. Default is ‘white’.
- EDGE_COL (str , optional) – Edge colour. Default is ‘#4A4A4A’.
- Returns: A dot-format string representation of the causal model.
- Return type:
str
Examples
>>> import pyagrum as gum>>> bn = pyagrum.BayesNet.fastPrototype('X->Y->Z')>>> cm = pyagrum.CausalModel(bn)>>> print(cm.toDot())variable(*args)
Section titled “variable(*args)”Return the variable with the given id or name (observed variables only).
- Parameters: id_or_name (int | str) – the node id or name of the variable
- Returns: the discrete variable
- Return type:
DiscreteVariable - Raises: pyagrum.NotFound – if the id or name does not correspond to an observed variable in the model
Backdoor and frontdoor criteria
Section titled “Backdoor and frontdoor criteria”class pyagrum.DoorCriteria
Section titled “class pyagrum.DoorCriteria”Utility class implementing the backdoor and frontdoor criteria on a causal DAG.
All methods are static and take the DAG as their first argument. This class is stateless: it does not store any model.
A backdoor adjustment set Z between X and Y blocks all spurious (non-causal) paths from X to Y while leaving all directed causal paths open.
A frontdoor adjustment set Z between X and Y intercepts every directed path from X to Y, has no open backdoor path from X to Z, and all backdoor paths from Z to Y are blocked by X.
Notes
High-level search for a single valid set is available via
pyagrum.CausalModel.backDoor() and
pyagrum.CausalModel.frontDoor().
Examples
>>> import pyagrum as gum>>> bn = pyagrum.BayesNet.fastPrototype('X->Z->Y')>>> dag = bn.dag()>>> x, y, z = bn.idFromName('X'), bn.idFromName('Y'), bn.idFromName('Z')>>> pyagrum.DoorCriteria.satisfiesBackdoorCriterion(dag, x, y, set())True>>> pyagrum.DoorCriteria.enumerateFrontdoorSets(dag, x, y)[{z}]static backdoorReach(dag, X)
Section titled “static backdoorReach(dag, X)”Return all nodes reachable from X via a backdoor path.
A backdoor path starts with an arc pointing into X (i.e. it begins by going to a parent of X) and then follows any sequence of edges.
- Parameters:
- dag (
DAG) – The causal DAG. - X (
int) – NodeId of the source variable.
- dag (
- Returns: NodeIds of all nodes reachable from X via a backdoor path.
- Return type:
list[int]
static enumerateBackdoorSets(dag, X, Y, , excluded_nodes=None, max_cardinality=0, only_minimal=True, stopAtFirst=False)
Section titled “static enumerateBackdoorSets(dag, X, Y, , excluded_nodes=None, max_cardinality=0, only_minimal=True, stopAtFirst=False)”Enumerate valid backdoor adjustment sets for the causal effect of X on Y.
- Parameters:
- dag (pyagrum.DAG) – The causal DAG.
- X (int) – NodeId of the treatment variable.
- Y (int) – NodeId of the outcome variable.
- excluded_nodes (set of int , optional) – Nodes that cannot appear in any adjustment set. Default is empty.
- max_cardinality (int , optional) – Maximum size of returned sets. 0 means no limit. Default is 0.
- only_minimal (bool , optional) – If True, return only minimal adjustment sets (no redundant variables). Default is True.
- stopAtFirst (bool , optional) – If True, stop after finding the first valid set. Default is False.
- Returns: All valid backdoor adjustment sets (as NodeId sets).
- Return type: list of set of int
static enumerateFrontdoorSets(dag, X, Y, , excluded_nodes=None, max_cardinality=0, only_minimal=True, stopAtFirst=False)
Section titled “static enumerateFrontdoorSets(dag, X, Y, , excluded_nodes=None, max_cardinality=0, only_minimal=True, stopAtFirst=False)”Enumerate valid frontdoor adjustment sets for the causal effect of X on Y.
- Parameters:
- dag (pyagrum.DAG) – The causal DAG.
- X (int) – NodeId of the treatment variable.
- Y (int) – NodeId of the outcome variable.
- excluded_nodes (set of int , optional) – Nodes that cannot appear in any adjustment set. Default is empty.
- max_cardinality (int , optional) – Maximum size of returned sets. 0 means no limit. Default is 0.
- only_minimal (bool , optional) – If True, return only minimal adjustment sets. Default is True.
- stopAtFirst (bool , optional) – If True, stop after finding the first valid set. Default is False.
- Returns: All valid frontdoor adjustment sets (as NodeId sets).
- Return type: list of set of int
static existsUnblockedDirectedPath(dag, X, Y, Z)
Section titled “static existsUnblockedDirectedPath(dag, X, Y, Z)”Test whether a directed path from X to Y exists that is not blocked by Z.
- Parameters:
- dag (
DAG) – The causal DAG. - X (
int) – NodeId of the source variable. - Y (
int) – NodeId of the target variable. - Z (
list[int]) – Blocking set (NodeIds). A directed path is blocked if it passes through a node in Z.
- dag (
- Returns: True if at least one unblocked directed path from X to Y exists.
- Return type:
bool
static firstBackdoor(*args)
Section titled “static firstBackdoor(*args)”Return the first valid backdoor adjustment set for the causal effect of X on Y.
- Parameters:
- dag (pyagrum.DAG) – The causal DAG.
- X (int) – NodeId of the treatment variable.
- Y (int) – NodeId of the outcome variable.
- excluded_nodes (set of int , optional) – Nodes that cannot appear in any adjustment set. Default is empty.
- max_cardinality (int , optional) – Maximum size of the adjustment set. 0 means no limit. Default is 0.
- only_minimal (bool , optional) – If True, return only a minimal adjustment set. Default is True.
- Returns: The first valid backdoor adjustment set as a list of NodeIds, or None if none exists.
- Return type:
list[int] |None
static firstFrontdoor(*args)
Section titled “static firstFrontdoor(*args)”Return the first valid frontdoor adjustment set for the causal effect of X on Y.
- Parameters:
- dag (pyagrum.DAG) – The causal DAG.
- X (int) – NodeId of the treatment variable.
- Y (int) – NodeId of the outcome variable.
- excluded_nodes (set of int , optional) – Nodes that cannot appear in any adjustment set. Default is empty.
- max_cardinality (int , optional) – Maximum size of the adjustment set. 0 means no limit. Default is 0.
- only_minimal (bool , optional) – If True, return only a minimal adjustment set. Default is True.
- Returns: The first valid frontdoor adjustment set as a list of NodeIds, or None if none exists.
- Return type:
list[int] |None
static hasBackdoorPath(dag, X, Y, Z)
Section titled “static hasBackdoorPath(dag, X, Y, Z)”Test whether an open backdoor path from X to Y exists given evidence on Z.
- Parameters:
- dag (
DAG) – The causal DAG. - X (
int) – NodeId of the treatment variable. - Y (
int) – NodeId of the outcome variable. - Z (
list[int]) – Conditioning set (NodeIds).
- dag (
- Returns: True if an open backdoor path from X to Y exists after conditioning on Z.
- Return type:
bool
static nodesOnDirectedPaths(dag, X, Y)
Section titled “static nodesOnDirectedPaths(dag, X, Y)”Return the set of nodes lying on any directed path from X to Y.
- Parameters:
- dag (
DAG) – The causal DAG. - X (
int) – NodeId of the source variable. - Y (
int) – NodeId of the target variable.
- dag (
- Returns: NodeIds of all nodes (including X and Y) that lie on at least one directed path from X to Y. Empty if no directed path exists.
- Return type:
list[int] |None
static satisfiesBackdoorCriterion(dag, X, Y, Z)
Section titled “static satisfiesBackdoorCriterion(dag, X, Y, Z)”Test whether Z satisfies the backdoor criterion for the effect of X on Y.
A set Z satisfies the backdoor criterion with respect to (X, Y) if:
- No node in Z is a descendant of X in the causal DAG.
- Z blocks every backdoor path between X and Y (paths that begin with an arc pointing into X).
- Parameters:
- dag (
DAG) – The causal DAG. - X (
int) – NodeId of the treatment variable. - Y (
int) – NodeId of the outcome variable. - Z (
list[int]) – Candidate adjustment set (NodeIds).
- dag (
- Returns: True if Z satisfies the backdoor criterion for (X, Y).
- Return type:
bool
static satisfiesFrontdoorCriterion(dag, X, Y, Z)
Section titled “static satisfiesFrontdoorCriterion(dag, X, Y, Z)”Test whether Z satisfies the frontdoor criterion for the effect of X on Y.
A set Z satisfies the frontdoor criterion with respect to (X, Y) if:
- Z intercepts all directed paths from X to Y.
- There are no unblocked backdoor paths from X to Z.
- All backdoor paths from Z to Y are blocked by X.
- Parameters:
- dag (
DAG) – The causal DAG. - X (
int) – NodeId of the treatment variable. - Y (
int) – NodeId of the outcome variable. - Z (
list[int]) – Candidate mediator set (NodeIds).
- dag (
- Returns: True if Z satisfies the frontdoor criterion for (X, Y).
- Return type:
bool