Identification Algorithms
Queries and certificates
CausalDynamics.CausalQuery — Type
CausalQuerySupertype for queries posed against a causal graph or temporal unrolling.
CausalDynamics.TotalEffectQuery — Type
TotalEffectQuery(treatment, outcome)Backdoor-identifiable total effect of treatment on outcome. Node labels may be Int indices or Symbol names (with a node_names map).
CausalDynamics.MediationQuery — Type
MediationQuery(treatment, outcome, mediators)Interventional mediation decomposition (NDE / NIE / TE) via mediators on directed paths.
CausalDynamics.TemporalEffectQuery — Type
TemporalEffectQuery(treatment, outcome, t_treat, t_outcome)Total effect of treatment at occasion t_treat on outcome at t_outcome after unrolling a TemporalDAGSpec.
CausalDynamics.InterventionalPolicyQuery — Type
InterventionalPolicyQuery(treatment, outcome; shift=nothing)Modified treatment policy / stochastic intervention contrast on treatment. shift is an application-defined policy descriptor (estimators interpret it).
CausalDynamics.identify — Function
identify(g, query::TotalEffectQuery; node_names=nothing) -> IdentificationResultidentify(g, query::MediationQuery; node_names=nothing) -> IdentificationResultidentify(g, query::InterventionalPolicyQuery; node_names=nothing) -> IdentificationResultPolicy contrasts reduce to total-effect identification on the same (treatment, outcome) pair.
identify(unrolling::TemporalUnrolling, query::TemporalEffectQuery) -> IdentificationResultidentify(g, query::CausalQuery; kwargs...) -> IdentificationResultCausalDynamics.IdentificationResult — Type
IdentificationResult{T}Machine-readable output of identify: adjustment sets, strategy, and assumptions.
CausalDynamics.certificate_dict — Function
certificate_dict(result) -> Dict{Symbol, Any}CausalDynamics.graph_fingerprint — Function
graph_fingerprint(g) -> UInt64Stable hash of directed edges for reproducibility certificates.
CausalDynamics.identification_report — Function
identification_report(g, treatment, outcome; node_names=nothing) -> Vector{NamedTuple}Enumerate candidate adjustment sets and mark which satisfy the backdoor criterion. Returns a vector of named tuples (no DataFrames dependency).
Adjustment and instruments
CausalDynamics.backdoor_adjustment_set — Function
backdoor_adjustment_set(g, X, Y)Find a valid backdoor adjustment set for estimating the causal effect of X on Y.
Delegates to CausalInference.find_min_backdoor_adjustment. Returns nothing if no valid set exists (false from CausalInference).
Arguments
g: Directed acyclic graphX: Treatment nodeY: Outcome node
Returns
Set{Int}of adjustment nodes (possibly empty if no backdoors), ornothing
CausalDynamics.is_backdoor_adjustable — Function
is_backdoor_adjustable(g, X, Y)Return true if a backdoor adjustment set exists (including the empty set when there are no backdoor paths).
CausalDynamics.frontdoor_adjustment_set — Function
frontdoor_adjustment_set(g, X, Y, M)Check if M is a valid frontdoor adjustment set for estimating the causal effect of X on Y.
The frontdoor criterion states that a set M is a valid frontdoor adjustment set if:
- M blocks all directed paths from X to Y
- There are no backdoor paths from X to M
- All backdoor paths from M to Y are blocked by X
Uses reachability (BFS), not path enumeration — safe on dense DAGs.
Arguments
g: Directed acyclic graphX: Treatment nodeY: Outcome nodeM: Potential mediator set
Returns
trueif M is a valid frontdoor adjustment set,falseotherwise
CausalDynamics.find_frontdoor_mediators — Function
find_frontdoor_mediators(g, X, Y)Find single-node frontdoor mediators between X and Y.
Candidates are nodes on some directed path X → Y (nodes_on_directed_paths), checked with frontdoor_adjustment_set. Avoids enumerating all simple paths.
CausalDynamics.find_path_mediators — Function
find_path_mediators(g, treatment, outcome) -> Set{Int}Structural mediator candidates between treatment and outcome: nodes that lie on at least one proper directed path treatment → ⋯ → outcome (excluding the endpoints).
On a DAG this is
intersect(get_descendants(g, treatment), get_ancestors(g, outcome))This is not the frontdoor criterion. For single-node sets that satisfy the frontdoor criterion, use find_frontdoor_mediators.
Arguments
g: Directed acyclic graphtreatment: Treatment node indexoutcome: Outcome node index
Returns
Set{Int}of mediator candidate indices
Examples
using CausalDynamics, Graphs
# Nodes: A=1, M1=2, M2=3, M3=4, Y=5, C=6, D=7
# A → M1 → M2 → Y; A → M3 → Y; C → A; C → Y; A → D
g = DiGraph(7)
add_edge!(g, 1, 2); add_edge!(g, 2, 3); add_edge!(g, 3, 5)
add_edge!(g, 1, 4); add_edge!(g, 4, 5)
add_edge!(g, 6, 1); add_edge!(g, 6, 5)
add_edge!(g, 1, 7)
find_path_mediators(g, 1, 5) # Set([2, 3, 4]) == {M1, M2, M3}find_path_mediators(g, treatment, outcome; node_names) -> SetAs find_path_mediators with Int indices, but treatment / outcome may be Symbols when node_names maps indices to names (same conventions as identify).
Returns a Set{Symbol} when node_names is provided, otherwise Set{Int}.
CausalDynamics.find_minimal_mediator_sets — Function
find_minimal_mediator_sets(g, treatment, outcome; max_candidates=20) -> MinimalMediatorSets{Int}Inclusion-minimal sets of mediators that intercept every directed path treatment → ⋯ → outcome.
A set $S$ intercepts all directed paths when intercepts_all_directed_paths (g, treatment, outcome, S) is true. Equivalently, $S$ is a hitting set for the intermediate nodes of every directed path.
Returns a MinimalMediatorSets with:
sets: all inclusion-minimal cuts, sorted by(length, sorted members)status::ok,:no_path,:uncuttable_direct_edge, or:uncuttable
Uses directed reachability (BFS with forbidden nodes), not full path enumeration. Candidate nodes are find_path_mediators. Enumeration of subsets is exponential in the number of candidates; max_candidates caps that search.
This is not the frontdoor criterion — see find_frontdoor_mediators. Nor does it choose mediators for MediationQuery; pass a chosen set explicitly after inspecting .sets.
Examples
using CausalDynamics, Graphs
# Sequential: A → M1 → M2 → Y
g = DiGraph(4)
add_edge!(g, 1, 2); add_edge!(g, 2, 3); add_edge!(g, 3, 4)
r = find_minimal_mediator_sets(g, 1, 4)
r.status # :ok
r.sets # [Set([2]), Set([3])]
# Parallel: A → M1 → Y and A → M2 → Y
g = DiGraph(4)
add_edge!(g, 1, 2); add_edge!(g, 2, 4)
add_edge!(g, 1, 3); add_edge!(g, 3, 4)
find_minimal_mediator_sets(g, 1, 4).sets # [Set([2, 3])]
# Mixed: A → M1 → M3 → Y and A → M2 → M3 → Y
g = DiGraph(5)
add_edge!(g, 1, 2); add_edge!(g, 2, 4); add_edge!(g, 4, 5)
add_edge!(g, 1, 3); add_edge!(g, 3, 4)
find_minimal_mediator_sets(g, 1, 5).sets # [Set([4]), Set([2, 3])]find_minimal_mediator_sets(g, treatment, outcome; node_names, max_candidates=20)As find_minimal_mediator_sets with Int indices. With node_names, returns MinimalMediatorSets{Symbol}.
CausalDynamics.MinimalMediatorSets — Type
MinimalMediatorSets{T}Result of find_minimal_mediator_sets.
Fields
sets: Inclusion-minimal mediator sets, sorted by(length, sorted members)status::ok—setsholds the cuts (possibly empty only in degenerate cases):no_path— no directed path from treatment to outcome:uncuttable_direct_edge— a direct treatment→outcome edge cannot be cut by mediators:uncuttable— a residual directed path avoids every path-mediator candidate
Iterates over sets (so collect(result) and Set(result) still work).
CausalDynamics.intercepts_all_directed_paths — Function
intercepts_all_directed_paths(g, treatment, outcome, S) -> BoolReturn true if mediator set S intercepts every directed path from treatment to outcome (no directed route avoids every node in S). Endpoints are never forbidden. Same criterion used by find_minimal_mediator_sets.
CausalDynamics.find_instruments — Function
find_instruments(g, X, Y)Find instrumental variables for estimating the causal effect of X on Y.
An instrumental variable Z must satisfy:
- Z has a causal effect on X
- Z affects Y only through X (exclusion restriction)
- Z is independent of confounders of X and Y (independence)
Arguments
g: Directed acyclic graphX: Treatment nodeY: Outcome node
Returns
- Vector of potential instrumental variables
Examples
using CausalDynamics, Graphs
# IV example
g = DiGraph(4)
add_edge!(g, 1, 2) # Z → X
add_edge!(g, 2, 3) # X → Y
add_edge!(g, 4, 2) # U → X
add_edge!(g, 4, 3) # U → Y
# Z is a valid instrument
instruments = find_instruments(g, 2, 3) # [1]References
- Angrist, J. D., & Pischke, J. S. (2009). Mostly Harmless Econometrics
CausalDynamics.is_valid_instrument — Function
is_valid_instrument(g, Z, X, Y)Check if Z is a valid instrumental variable for X → Y.
An instrument Z must satisfy three conditions:
- Relevance: Z has a causal effect on X (directed path Z → X)
- Exclusion restriction: Z affects Y only through X (all paths Z → Y go through X)
- Independence: Z is independent of confounders (no backdoor paths Z → Y)
Arguments
g::AbstractGraph: Directed acyclic graphZ::Int: Potential instrument nodeX::Int: Treatment nodeY::Int: Outcome node
Returns
Bool:trueif Z is a valid instrument,falseotherwise
Examples
using CausalDynamics, Graphs
# Valid instrument
g = DiGraph(4)
add_edge!(g, 1, 2) # Z → X
add_edge!(g, 2, 3) # X → Y
add_edge!(g, 4, 2) # U → X
add_edge!(g, 4, 3) # U → Y
is_valid_instrument(g, 1, 2, 3) # true
# Invalid: Z has direct path to Y
g2 = DiGraph(3)
add_edge!(g2, 1, 2) # Z → X
add_edge!(g2, 1, 3) # Z → Y (violates exclusion)
add_edge!(g2, 2, 3) # X → Y
is_valid_instrument(g2, 1, 2, 3) # falseNotes
- The independence condition (3) is checked conservatively: if any backdoor paths exist, returns
false - In practice, independence may hold even with backdoor paths if they are blocked
References
- Angrist, J. D., & Pischke, J. S. (2009). Mostly Harmless Econometrics, Chapter 4
CausalDynamics.find_all_adjustment_sets — Function
find_all_adjustment_sets(g, X, Y)List valid backdoor adjustment sets via CausalInference.list_backdoor_adjustment.
CausalDynamics.is_valid_adjustment_set — Function
is_valid_adjustment_set(g, X, Y, Z)Check if Z is a valid backdoor adjustment set via CausalInference.
CausalDynamics.minimal_adjustment_set — Function
minimal_adjustment_set(g, X, Y)Minimal backdoor adjustment set (same as backdoor_adjustment_set).
Column resolvers
Map graph node labels to data columns after identification.
CausalDynamics.ColumnResolver — Type
ColumnResolverTrait-like API for resolving identification nodes to data columns.
CausalDynamics.IdentityColumnResolver — Type
IdentityColumnResolverPass node labels through unchanged (symbols or indices).
CausalDynamics.DictColumnResolver — Type
DictColumnResolver(mapping)Resolve via explicit node => column mapping.
CausalDynamics.resolve_columns — Function
resolve_columns(resolver, nodes, available) -> VectorReturn columns present in available that correspond to nodes.
CausalDynamics.resolve_identification_columns — Function
resolve_identification_columns(result, resolver, column_names) -> IdentificationResult