SCM.Examples

Worked structural-causal-model examples (instrumental variables and related DAGs) exercising the SCM and identification layers.

Back­Door 7 core · 4 supporting This file constructs the canonical directed acyclic graph for backdoor adjustment, with a treatment, an outcome, an observed confounder, and latent root noise variables. ★ bdTopo_lt

Backdoor Adjustment Example

This file constructs the canonical directed acyclic graph for backdoor adjustment, with a treatment, an outcome, an observed confounder, and latent root noise variables. The declarations BDNode, bdEdge, bdDAG, and bdSWIG define the graph and its standard SWIG representation. The examples check parents, roots, c-components, ID reachability, and the split-graph d-separation condition behind the graphical backdoor criterion; the final backdoor-criterion example verifies that the observed confounder is a valid adjustment set for the treatment-outcome effect.

inductive BDNode reviewed
Causalean.SCM.Examples.BackDoor

The backdoor example has treatment, outcome, observed-confounder, and three latent-root vertices.

Definition (Lean source)
inductive BDNode | bdD -- treatment | bdY -- outcome | bdZ -- observed confounder | bdU1 -- latent root for Z | bdU2 -- latent root for D | bdU3 -- latent root for Y deriving DecidableEq
Causalean.SCM.Examples.BackDoor.BDNode · Causalean/SCM/Examples/BackDoor.lean:70
def bdEdge reviewed
Causalean.SCM.Examples.BackDoor

The backdoor graph has confounding paths through the observed confounder, a direct treatment-outcome edge, and one latent root for each observed node.

Definition (Lean source)
def bdEdge : BDNodeBDNode → Prop | bdZ, bdD => True | bdZ, bdY => True | bdD, bdY => True | bdU1, bdZ => True | bdU2, bdD => True | bdU3, bdY => True | _, _ => False
Causalean.SCM.Examples.BackDoor.bdEdge · Causalean/SCM/Examples/BackDoor.lean:114 · uses BDNode
def bdTopo reviewed
Causalean.SCM.Examples.BackDoor

The backdoor graph orders latent roots first, then confounder, treatment, and outcome.

Definition (Lean source)
def bdTopo : BDNode → ℕ | bdU1 => 0 | bdU2 => 1 | bdU3 => 2 | bdZ => 3 | bdD => 4 | bdY => 5
Causalean.SCM.Examples.BackDoor.bdTopo · Causalean/SCM/Examples/BackDoor.lean:132 · uses BDNode
theorem bdTopo_lt reviewed
Causalean.SCM.Examples.BackDoor

Every edge of the backdoor-example graph connects a node with a strictly smaller assigned order label to one with a strictly larger label — the chosen ordering is a valid topological order for the graph.

Formal statement
∀ u v
if
bdEdge u v
then
Proof (Lean source)
theorem bdTopo_lt : ∀ u v, bdEdge u v → bdTopo u < bdTopo v := by intro u v h; cases u <;> cases v <;> simp_all [bdEdge, bdTopo]
Causalean.SCM.Examples.BackDoor.bdTopo_lt · Causalean/SCM/Examples/BackDoor.lean:141 · uses BDNode , bdEdge , bdTopo
def bdDAG reviewed
Causalean.SCM.Examples.BackDoor

This directed acyclic graph formalizes the canonical backdoor-adjustment example.

Definition (Lean source)
def bdDAG : DAG BDNode where edge := bdEdge decEdge := inferInstance acyclic := DAG.acyclic_of_topoOrder bdTopo_lt
def bdSWIG reviewed
Causalean.SCM.Examples.BackDoor

This SWIG graph represents the backdoor example before any intervention.

Definition (Lean source)
def bdSWIG : SWIGGraph BDNode where dag := initialSWIG bdDAG fixed := ∅ observed := {SWIGNode.random bdD, SWIGNode.random bdY, SWIGNode.random bdZ} unobserved := {SWIGNode.random bdU1, SWIGNode.random bdU2, SWIGNode.random bdU3} fixed_is_fixed := by intro s hs; simp at hs observed_is_random := by intro v hv; simp at hv rcases hv with rfl | rfl | rfl <;> exact ⟨_, rfl⟩ unobserved_is_random := by intro u hu; simp at hu rcases hu with rfl | rfl | rfl <;> exact ⟨_, rfl⟩ obs_unobs_disjoint := by native_decide dag_edges_classified := by native_decide fixed_image_in_observed := by intro s hs; simp at hs fixed_are_roots := by intro s hs; simp at hs unobs_are_roots := by intro u hu; simp at hu rcases hu with rfl | rfl | rfl · simpa [initialSWIG] using swig_random_root_of_root bdDAG ∅ bdU1 (by native_decide : bdDAG.parents bdU1 = ∅) · simpa [initialSWIG] using swig_random_root_of_root bdDAG ∅ bdU2 (by native_decide : bdDAG.parents bdU2 = ∅) · simpa [initialSWIG] using swig_random_root_of_root bdDAG ∅ bdU3 (by native_decide : bdDAG.parents bdU3 = ∅) fixed_outside_fixed_isolated := by intro n _ cases n <;> exact ⟨by native_decide, by native_decide⟩ all_children_in_observed := by native_decide
def bdEdgeTypes reviewed
Causalean.SCM.Examples.BackDoor

The backdoor example treats every graph edge as nonparametric.

Definition (Lean source)
def bdEdgeTypes : EdgeTypeAssignment bdDAG := EdgeTypeAssignment.allNonparametric bdDAG
4 supporting declarations (lemmas, instances)
Continuous­Backdoor 13 core · 10 supporting This file gives a real-valued backdoor example in which the confounder, treatment, and outcome all take values in ℝ. ★ cb_backdoor_criterion★ cb_backdoor_identified

Real-Valued Backdoor Example

This file gives a real-valued backdoor example in which the confounder, treatment, and outcome all take values in . The declarations CBNode, CBΩ, cbDAG, cbSWIGGraph, and continuousBackdoorSCM build a degenerate constant structural model whose purpose is to exercise the real-valued graph and kernel interfaces. The theorem cb_backdoor_criterion verifies the graphical backdoor criterion by computation, and cb_backdoor_identified applies the kernel-based backdoor pipeline once the required overlap and positivity conditions are supplied as hypotheses.

abbrev CBNode reviewed
Causalean.SCM.Examples.ContinuousBackdoor

The continuous-backdoor example has three nodes: confounder, treatment, and outcome.

Definition (Lean source)
abbrev CBNode : Type := Fin 3
Causalean.SCM.Examples.ContinuousBackdoor.CBNode · Causalean/SCM/Examples/ContinuousBackdoor.lean:78
abbrev CBΩ reviewed
Causalean.SCM.Examples.ContinuousBackdoor

Every node in the continuous-backdoor example takes real values.

Definition (Lean source)
abbrev CBΩ : CBNode → Type := fun _ => ℝ
Causalean.SCM.Examples.ContinuousBackdoor.CBΩ · Causalean/SCM/Examples/ContinuousBackdoor.lean:81 · uses CBNode
def Zidx reviewed
Causalean.SCM.Examples.ContinuousBackdoor

This node index denotes the confounder in the continuous-backdoor example.

Definition (Lean source)
@[reducible] def Zidx : CBNode := 0
Causalean.SCM.Examples.ContinuousBackdoor.Zidx · Causalean/SCM/Examples/ContinuousBackdoor.lean:84 · uses CBNode
def Xidx reviewed
Causalean.SCM.Examples.ContinuousBackdoor

This node index denotes the treatment in the continuous-backdoor example.

Definition (Lean source)
@[reducible] def Xidx : CBNode := 1
Causalean.SCM.Examples.ContinuousBackdoor.Xidx · Causalean/SCM/Examples/ContinuousBackdoor.lean:86 · uses CBNode
def Yidx reviewed
Causalean.SCM.Examples.ContinuousBackdoor

This node index denotes the outcome in the continuous-backdoor example.

Definition (Lean source)
@[reducible] def Yidx : CBNode := 2
Causalean.SCM.Examples.ContinuousBackdoor.Yidx · Causalean/SCM/Examples/ContinuousBackdoor.lean:88 · uses CBNode
def cbEdgeBool reviewed
Causalean.SCM.Examples.ContinuousBackdoor

The edge indicator records confounder-to-treatment, confounder-to-outcome, and treatment-to-outcome arrows.

Definition (Lean source)
def cbEdgeBool : CBNodeCBNodeBool := fun a b => (a.val == 0 && b.val == 1) || (a.val == 0 && b.val == 2) || (a.val == 1 && b.val == 2)
Causalean.SCM.Examples.ContinuousBackdoor.cbEdgeBool · Causalean/SCM/Examples/ContinuousBackdoor.lean:95 · uses CBNode
def cbEdge reviewed
Causalean.SCM.Examples.ContinuousBackdoor

The edge relation says exactly that the confounder points to treatment and outcome, and treatment points to outcome.

Definition (Lean source)
def cbEdge : CBNodeCBNode → Prop := fun a b => cbEdgeBool a b = true
Causalean.SCM.Examples.ContinuousBackdoor.cbEdge · Causalean/SCM/Examples/ContinuousBackdoor.lean:102 · uses CBNode
def cbTopo reviewed
Causalean.SCM.Examples.ContinuousBackdoor

The continuous-backdoor graph orders confounder before treatment before outcome.

Definition (Lean source)
def cbTopo : CBNode → ℕ := fun n => n.val
Causalean.SCM.Examples.ContinuousBackdoor.cbTopo · Causalean/SCM/Examples/ContinuousBackdoor.lean:109 · uses CBNode
def cbDAG reviewed
Causalean.SCM.Examples.ContinuousBackdoor

This directed acyclic graph formalizes the three-node continuous backdoor example.

Definition (Lean source)
def cbDAG : DAG CBNode where edge := cbEdge decEdge := inferInstance acyclic := DAG.acyclic_of_topoOrder cbTopo_lt
Causalean.SCM.Examples.ContinuousBackdoor.cbDAG · Causalean/SCM/Examples/ContinuousBackdoor.lean:117 · uses DAG , CBNode
def cbSWIGGraph reviewed
Causalean.SCM.Examples.ContinuousBackdoor

This computable SWIG graph represents the continuous-backdoor example before any intervention.

Definition (Lean source)
def cbSWIGGraph : SWIGGraph CBNode where dag := initialSWIG cbDAG fixed := ∅ observed := {SWIGNode.random Zidx, SWIGNode.random Xidx, SWIGNode.random Yidx} unobserved := ∅ fixed_is_fixed := by intro s hs; simp at hs observed_is_random := by intro v hv; simp at hv rcases hv with rfl | rfl | rfl <;> exact ⟨_, rfl⟩ unobserved_is_random := by intro u hu; simp at hu obs_unobs_disjoint := by rw [Finset.disjoint_right]; intro x hx; simp at hx dag_edges_classified := by native_decide fixed_image_in_observed := by intro s hs; simp at hs fixed_are_roots := by intro s hs; simp at hs unobs_are_roots := by intro u hu; simp at hu fixed_outside_fixed_isolated := by intro n _ refine ⟨?_, ?_⟩ · revert n; decide · revert n; decide all_children_in_observed := by native_decide
Causalean.SCM.Examples.ContinuousBackdoor.cbSWIGGraph · Causalean/SCM/Examples/ContinuousBackdoor.lean:127 · uses CBNode , SWIGGraph
def continuousBackdoorSCM reviewed
Causalean.SCM.Examples.ContinuousBackdoor

This real-valued backdoor structural model has observed nodes for a confounder, treatment, and outcome, with no latent variables.

Definition (Lean source)
noncomputable def continuousBackdoorSCM : SCM CBNode CBΩ where toSWIGGraph := cbSWIGGraph edgeTypes := EdgeTypeAssignment.allNonparametric cbSWIGGraph.dag iota_valueSpace := by intro s exact (notMem_empty s.val s.property).elim structFun := fun v => by -- Structural functions: constant 0 for every observed node. `swigΩ CBΩ v.val` -- reduces to `ℝ` for any `.random _` or `.fixed _` (since `CBΩ _ = ℝ`). rcases v with ⟨n, _⟩ cases n <;> exact fun _ => (0 : ℝ) structFun_measurable := by intro v rcases v with ⟨n, _⟩ cases n <;> exact measurable_const latentDist := fun u => (notMem_empty u.val u.property).elim isProbability_latent := by intro u exact (notMem_empty u.val u.property).elim
Causalean.SCM.Examples.ContinuousBackdoor.continuousBackdoorSCM · Causalean/SCM/Examples/ContinuousBackdoor.lean:158 · uses SCM , CBNode , CBΩ
theorem cb_backdoor_criterion reviewed
Causalean.SCM.Examples.ContinuousBackdoor

The observed confounder satisfies the graphical backdoor criterion relative to the treatment and outcome nodes in the continuous-backdoor example graph.

Formal statement
cbSWIGGraph.backdoorCriterion ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed {SWIGNode.random Yidx} {SWIGNode.random Zidx}
Proof (Lean source)
theorem cb_backdoor_criterion : cbSWIGGraph.backdoorCriterion ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed {SWIGNode.random Yidx} {SWIGNode.random Zidx} := by refine ⟨?_, ?_, ?_, ?_, ?_⟩ · -- Guard: `{random Z}` is observed. intro z hz rw [mem_singleton] at hz subst hz change SWIGNode.random Zidx ∈ ({SWIGNode.random Zidx, SWIGNode.random Xidx, SWIGNode.random Yidx} : Finset (SWIGNode CBNode)) simp · -- Guard: `{random Z}` is disjoint from `{random Y}`. native_decide · -- Guard: `{random Z}` is disjoint from `{random X}`. native_decide · -- Condition (i): no element of `{random Z}` is a descendant of `random X`. intro z hz D hD rw [mem_singleton] at hz hD subst hz; subst hD -- Goal: ¬ (initialSWIG cbDAG).isAncestor (.random X) (.random Z). -- The only edges from `random X` go to `random Y`; `Z` is not reachable. native_decide · -- Condition (ii): `{random Z} ∪ {fixed X}` d-separates `{random Y}` from -- `{random X}` in the splitMono graph. Discharged via `splitMonoDAG` -- (computable) + `native_decide`, mirroring `SCM/Examples/BackDoor.lean`. exact (by native_decide : (cbSWIGGraph.splitMonoDAG ({Xidx} : Finset CBNode)).dSep {SWIGNode.random Yidx} (image SWIGNode.random ({Xidx} : Finset CBNode)) ({SWIGNode.random Zidx} ∪ image SWIGNode.fixed ({Xidx} : Finset CBNode)))
theorem cb_backdoor_identified reviewed
Causalean.SCM.Examples.ContinuousBackdoor

Backdoor adjustment identity on the continuous-backdoor example. Fix an assignment s0 of values to the model's fixed background variables. If for every post-intervention background assignment, the do(X)-intervened marginal law of Z is absolutely continuous with respect to its purely observational marginal law — the Rule-2 joint overlap condition, and the product of the observational marginal laws of the treatment's random image and of Z is absolutely continuous with respect to their joint observational law — the joint positivity condition, then almost everywhere under that product measure, the conditional law of the outcome Y given Z under the intervention that fixes the treatment equals the purely observational conditional law of Y given both the treatment and Z — the backdoor Rule-2 adjustment identity.

Formal statement
s0 :
continuousBackdoorSCM.FixedValues
hOverlap :
hPositivity_ae :
(((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_Xr_obs) ⊗ₘ const _ ((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_Zobs))).map (fun p => valuesUnionMk p.1 p.2)) ≪ ((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_XrZ_obs))
∀ᵐ p ∂((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_Xr_obs) ⊗ₘ const _ ((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_Zobs))),
(continuousBackdoorSCM.fixSet ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed).obsCondKernel {SWIGNode.random Yidx} {SWIGNode.random Zidx} ((SCM.fixSet_observed continuousBackdoorSCM ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed).symm ▸ cb_Yobs) ((SCM.fixSet_observed continuousBackdoorSCM ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed).symm ▸ cb_Zobs) (continuousBackdoorSCM.fixSetExtend ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed s0 p.1, p.2)
= continuousBackdoorSCM.obsCondKernel {SWIGNode.random Yidx} (({Xidx} : Finset CBNode).image SWIGNode.random ∪ {SWIGNode.random Zidx}) cb_Yobs cb_XrZ_obs (s0, valuesUnionMk p.1 p.2)
Proof (Lean source)
theorem cb_backdoor_identified (s0 : continuousBackdoorSCM.FixedValues) (hOverlap : ∀ s : (continuousBackdoorSCM.fixSet ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed).FixedValues, Rule2JointOverlap continuousBackdoorSCM ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed {SWIGNode.random Zidx} cb_XrZ_obs s) (hPositivity_ae : (((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_Xr_obs) ⊗ₘ const _ ((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_Zobs))).map (fun p => valuesUnionMk p.1 p.2)) ≪ ((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_XrZ_obs))) : ∀ᵐ p ∂((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_Xr_obs) ⊗ₘ const _ ((continuousBackdoorSCM.obsKernel s0).map (valuesProjection cb_Zobs))), (continuousBackdoorSCM.fixSet ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed).obsCondKernel {SWIGNode.random Yidx} {SWIGNode.random Zidx} ((SCM.fixSet_observed continuousBackdoorSCM ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed).symm ▸ cb_Yobs) ((SCM.fixSet_observed continuousBackdoorSCM ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed).symm ▸ cb_Zobs) (continuousBackdoorSCM.fixSetExtend ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed s0 p.1, p.2) = continuousBackdoorSCM.obsCondKernel {SWIGNode.random Yidx} (({Xidx} : Finset CBNode).image SWIGNode.random ∪ {SWIGNode.random Zidx}) cb_Yobs cb_XrZ_obs (s0, valuesUnionMk p.1 p.2) := SCM.backdoor_rule2_ae continuousBackdoorSCM ({Xidx} : Finset CBNode) cb_Xrand_obs cb_Xfixed {SWIGNode.random Yidx} {SWIGNode.random Zidx} cb_Yobs cb_Zobs cb_Xr_obs cb_XrZ_obs cb_disj_YXr cb_disj_XrZ cb_backdoor_criterion s0 hOverlap hPositivity_ae
10 supporting declarations (lemmas, instances)
Frontdoor 6 core · 4 supporting This file constructs the canonical frontdoor graph with one latent confounder between treatment and outcome, an observed mediator, and no intervention fixed at the initial graph. ★ fdTopo_lt

Frontdoor Example

This file constructs the canonical frontdoor graph with one latent confounder between treatment and outcome, an observed mediator, and no intervention fixed at the initial graph. The declarations FDNode, fdEdge, fdDAG, and fdSWIG define the graph and standard SWIG representation. The examples verify the c-components, show that the recursive ID certificate idSucceedsRec succeeds for P(Y | do(X)), show that the simpler no-fixing reachability certificate does not apply to the same outcome district, and check that the executable idAlgorithm returns true on the concrete graph.

inductive FDNode reviewed
Causalean.SCM.Examples.Frontdoor

The frontdoor example has latent confounder, treatment, mediator, and outcome vertices.

Definition (Lean source)
inductive FDNode | fdU -- latent confounder of X and Y | fdX -- treatment | fdM -- mediator | fdY -- outcome deriving DecidableEq, Repr
Causalean.SCM.Examples.Frontdoor.FDNode · Causalean/SCM/Examples/Frontdoor.lean:34
def fdEdge reviewed
Causalean.SCM.Examples.Frontdoor

The frontdoor graph has latent confounding of X and Y, and the directed path X → M → Y.

Definition (Lean source)
def fdEdge : FDNodeFDNode → Prop | fdU, fdX => True | fdU, fdY => True | fdX, fdM => True | fdM, fdY => True | _, _ => False
Causalean.SCM.Examples.Frontdoor.fdEdge · Causalean/SCM/Examples/Frontdoor.lean:53 · uses FDNode
def fdTopo reviewed
Causalean.SCM.Examples.Frontdoor

The frontdoor graph orders latent confounder, treatment, mediator, then outcome.

Definition (Lean source)
def fdTopo : FDNode → ℕ | fdU => 0 | fdX => 1 | fdM => 2 | fdY => 3
Causalean.SCM.Examples.Frontdoor.fdTopo · Causalean/SCM/Examples/Frontdoor.lean:69 · uses FDNode
theorem fdTopo_lt reviewed
Causalean.SCM.Examples.Frontdoor

Every edge of the frontdoor-example graph connects a node with a smaller assigned order label to one with a larger label, so the chosen ordering is a valid topological order.

Formal statement
∀ u v
if
fdEdge u v
then
Proof (Lean source)
theorem fdTopo_lt : ∀ u v, fdEdge u v → fdTopo u < fdTopo v := by intro u v h; cases u <;> cases v <;> simp_all [fdEdge, fdTopo]
Causalean.SCM.Examples.Frontdoor.fdTopo_lt · Causalean/SCM/Examples/Frontdoor.lean:76 · uses FDNode , fdEdge , fdTopo
def fdDAG reviewed
Causalean.SCM.Examples.Frontdoor

This directed acyclic graph formalizes the canonical frontdoor example.

Definition (Lean source)
def fdDAG : DAG FDNode where edge := fdEdge decEdge := inferInstance acyclic := DAG.acyclic_of_topoOrder fdTopo_lt
def fdSWIG reviewed
Causalean.SCM.Examples.Frontdoor

This SWIG graph represents the frontdoor example before any intervention.

Definition (Lean source)
def fdSWIG : SWIGGraph FDNode where dag := initialSWIG fdDAG fixed := ∅ observed := {SWIGNode.random fdX, SWIGNode.random fdM, SWIGNode.random fdY} unobserved := {SWIGNode.random fdU} fixed_is_fixed := by intro s hs; simp at hs observed_is_random := by intro v hv; simp at hv rcases hv with rfl | rfl | rfl <;> exact ⟨_, rfl⟩ unobserved_is_random := by intro u hu; simp at hu subst hu exact ⟨_, rfl⟩ obs_unobs_disjoint := by native_decide dag_edges_classified := by native_decide fixed_image_in_observed := by intro s hs; simp at hs fixed_are_roots := by intro s hs; simp at hs unobs_are_roots := by intro u hu; simp at hu subst hu simpa [initialSWIG] using swig_random_root_of_root fdDAG ∅ fdU (by native_decide : fdDAG.parents fdU = ∅) fixed_outside_fixed_isolated := by intro n _ cases n <;> exact ⟨by native_decide, by native_decide⟩ all_children_in_observed := by native_decide
4 supporting declarations (lemmas, instances)
IV 10 core · 5 supporting This file constructs the standard instrumental-variable graph with an instrument, a treatment, an outcome, and an unobserved confounder of the treatment-outcome relationship. ★ ivTopo_lt

Instrumental Variable Example

This file constructs the standard instrumental-variable graph with an instrument, a treatment, an outcome, and an unobserved confounder of the treatment-outcome relationship. It exercises the graphical, component, edge-type, and structural-model interfaces used by instrumental-variable examples elsewhere in the library.

inductive IVNode reviewed
Causalean.SCM.Examples.IV

The instrumental-variable example has instrument, treatment, outcome, and unobserved-confounder vertices.

Definition (Lean source)
inductive IVNode | Z -- instrument (binary) | D -- treatment (binary) | Y -- outcome (continuous) | U -- unobserved confounder deriving DecidableEq
Causalean.SCM.Examples.IV.IVNode · Causalean/SCM/Examples/IV.lean:47
def ivEdge reviewed
Causalean.SCM.Examples.IV

The instrumental-variable graph has instrument-to-treatment, treatment-to-outcome, and latent-confounder-to-treatment/outcome edges.

Definition (Lean source)
def ivEdge : IVNodeIVNode → Prop | Z, D => True | D, Y => True | U, D => True | U, Y => True | _, _ => False
Causalean.SCM.Examples.IV.ivEdge · Causalean/SCM/Examples/IV.lean:88 · uses IVNode
def ivTopo reviewed
Causalean.SCM.Examples.IV

The instrumental-variable graph orders the unobserved confounder and instrument before treatment and outcome.

Definition (Lean source)
def ivTopo : IVNode → ℕ | U => 0 | Z => 1 | D => 2 | Y => 3
Causalean.SCM.Examples.IV.ivTopo · Causalean/SCM/Examples/IV.lean:108 · uses IVNode
theorem ivTopo_lt reviewed
Causalean.SCM.Examples.IV

Every edge of the instrumental-variable example graph connects a node with a smaller assigned order label to one with a larger label, so the chosen ordering is a valid topological order.

Formal statement
∀ u v
if
ivEdge u v
then
Proof (Lean source)
theorem ivTopo_lt : ∀ u v, ivEdge u v → ivTopo u < ivTopo v := by intro u v h; cases u <;> cases v <;> simp_all [ivEdge, ivTopo]
Causalean.SCM.Examples.IV.ivTopo_lt · Causalean/SCM/Examples/IV.lean:116 · uses IVNode , ivEdge , ivTopo
def ivDAG reviewed
Causalean.SCM.Examples.IV

This directed acyclic graph formalizes the standard instrumental-variable example.

Definition (Lean source)
def ivDAG : DAG IVNode where edge := ivEdge decEdge := inferInstance acyclic := DAG.acyclic_of_topoOrder ivTopo_lt
def ivSWIGGraph reviewed
Causalean.SCM.Examples.IV

This SWIG graph represents the instrumental-variable example before any intervention.

Definition (Lean source)
def ivSWIGGraph : SWIGGraph IVNode where dag := initialSWIG ivDAG fixed := ∅ observed := {SWIGNode.random Z, SWIGNode.random D, SWIGNode.random Y} unobserved := {SWIGNode.random U} fixed_is_fixed := by intro s hs; simp at hs observed_is_random := by intro v hv simp only [Finset.mem_insert, mem_singleton] at hv rcases hv with rfl | rfl | rfl <;> exact ⟨_, rfl⟩ unobserved_is_random := by intro u hu simp only [mem_singleton] at hu subst u exact ⟨U, rfl⟩ obs_unobs_disjoint := by native_decide dag_edges_classified := by native_decide fixed_image_in_observed := by intro s hs; simp at hs fixed_are_roots := by intro s hs; simp at hs unobs_are_roots := by intro u hu simp only [mem_singleton] at hu subst u simpa [initialSWIG] using (swig_random_root_of_root ivDAG ∅ U (by native_decide : ivDAG.parents U = ∅)) fixed_outside_fixed_isolated := by intro n _ cases n <;> exact ⟨by native_decide, by native_decide⟩ all_children_in_observed := by native_decide
def ivEdgeTypes reviewed
Causalean.SCM.Examples.IV

The instrumental-variable edge assignment makes the instrument's effect on treatment strictly increasing and leaves all other edges nonparametric.

Definition (Lean source)
def ivEdgeTypes : EdgeTypeAssignment ivDAG where edgeType | Z, D => .monotonic .strictlyIncreasing | _, _ => .nonparametric
def ivΩ reviewed
Causalean.SCM.Examples.IV

This toy instrumental-variable model uses a one-point value space for every node.

Definition (Lean source)
def ivΩ : IVNode → Type := fun _ => Unit
Causalean.SCM.Examples.IV.ivΩ · Causalean/SCM/Examples/IV.lean:324 · uses IVNode
def ivSCM reviewed
Causalean.SCM.Examples.IV

This concrete instrumental-variable structural model realizes the example with one-point value spaces.

Definition (Lean source)
noncomputable def ivSCM : SCM IVNode ivΩ where dag := initialSWIG ivDAG fixed := ∅ observed := {SWIGNode.random Z, SWIGNode.random D, SWIGNode.random Y} unobserved := {SWIGNode.random U} fixed_is_fixed := by intro s hs; simp at hs observed_is_random := by intro v hv; simp at hv rcases hv with rfl | rfl | rfl <;> exact ⟨_, rfl⟩ unobserved_is_random := by intro u hu; simp at hu; subst hu; exact ⟨U, rfl⟩ obs_unobs_disjoint := by native_decide dag_edges_classified := by native_decide fixed_image_in_observed := by intro s hs; simp at hs fixed_are_roots := by intro s hs; simp at hs unobs_are_roots := by intro u hu; simp at hu; subst hu simpa [initialSWIG] using (swig_random_root_of_root ivDAG ∅ U (by native_decide : ivDAG.parents U = ∅)) fixed_outside_fixed_isolated := by intro n _ cases n <;> exact ⟨by native_decide, by native_decide⟩ all_children_in_observed := by native_decide edgeTypes := EdgeTypeAssignment.allNonparametric (initialSWIG ivDAG) iota_valueSpace := by intro s exact (notMem_empty s.val s.property).elim structFun := fun v => by -- `swigΩ ivΩ v.val = Unit` for any constructor of `SWIGNode`, since `ivΩ _ = Unit`. rcases v with ⟨n, _⟩ cases n <;> exact fun _ => () structFun_measurable := by intro v rcases v with ⟨n, _⟩ cases n <;> exact measurable_const latentDist := fun u => by rcases u with ⟨n, _⟩ cases n <;> exact dirac () isProbability_latent := by intro u rcases u with ⟨n, _⟩ cases n <;> exact inferInstanceAs (IsProbabilityMeasure (dirac (α := Unit) ()))
def ivDoDGraph reviewed
Causalean.SCM.Examples.IV

This graph is the SWIG obtained by intervening on the treatment in the instrumental-variable DAG.

Definition (Lean source)
def ivDoDGraph : DAG (SWIGNode IVNode) := swigDAG ivDAG {D}
5 supporting declarations (lemmas, instances)
  • instDecidableEqIVNode instance
    deriving DecidableEq
    Causalean.SCM.Examples.IV.instDecidableEqIVNode · Causalean/SCM/Examples/IV.lean:54
  • instReprIVNode instance — Instrumental-variable vertices can be rendered as their fully qualified constructor names.
    instance instReprIVNode : Repr IVNode where reprPrec := instReprIVNode.repr
    Causalean.SCM.Examples.IV.instReprIVNode · Causalean/SCM/Examples/IV.lean:75
  • instFintypeIVNode instance — The instrumental-variable vertex set is finite, with four named vertices.
    instance : Fintype IVNode where elems := {Z, D, Y, U} complete := by intro x; cases x <;> simp
    Causalean.SCM.Examples.IV.instFintypeIVNode · Causalean/SCM/Examples/IV.lean:79
  • instDecidableRelIVNodeIvEdge instance — A proposed instrumental-variable edge is decidable by case analysis on its endpoints.
    instance : DecidableRel ivEdge := by intro a b cases a <;> cases b <;> first | exact isTrue trivial | exact isFalse (by simp only [ivEdge]; exact fun h => h)
    Causalean.SCM.Examples.IV.instDecidableRelIVNodeIvEdge · Causalean/SCM/Examples/IV.lean:97
  • ivΩ_measurable instance — Every one-point value space in the toy instrumental-variable model carries the trivial measurable structure.
    instance ivΩ_measurable : ∀ n, MeasurableSpace (ivΩ n) := fun _ => ⊤
    Causalean.SCM.Examples.IV.ivΩ_measurable · Causalean/SCM/Examples/IV.lean:330
Monotone­Counterfactual­Bound 6 core · 3 supporting This file gives a worked example of structural monotonicity in a two-node Boolean SCM. ★ monotoneCounterfactualBound★ monotoneCounterfactualBound_assumption_satisfiable★ monotoneCounterfactualBound_fails_without_monotonicity

Monotone Counterfactual Bound Example

This file gives a worked example of structural monotonicity in a two-node Boolean SCM. The target is the unit-level response contrast of the outcome equation when the parent coordinate is changed from false to true.

Without any structural restriction that contrast has logical range [-1, 1]. Under the monotone-mechanism assumption it must lie in [0, 1]. The companion counterexample below uses the reversing Boolean SCM as the reference model to show that graph and observational compatibility alone do not generally imply a [0, 1] response-contrast bound.

def boolScore reviewed
Causalean.SCM.Examples.MonotoneCounterfactualBound

A Boolean value is scored as one for true and zero for false.

Definition (Lean source)
def boolScore (b : Bool) : ℝ := if b then 1 else 0
Causalean.SCM.Examples.MonotoneCounterfactualBound.boolScore · Causalean/SCM/Examples/MonotoneCounterfactualBound.lean:31
def boolParentAssignmentIn reviewed
Causalean.SCM.Examples.MonotoneCounterfactualBound

A parent assignment inside an arbitrary Boolean-chain SCM.

Definition (Lean source)
def boolParentAssignmentIn (M : SCM BoolChainNode boolChainΩ) (b : Bool) : ∀ w : {w // w ∈ M.dag.parents (SWIGNode.random y)}, swigΩ boolChainΩ w.val := by intro w rcases w with ⟨n, _⟩ cases n with | random n => cases n with | d => exact b | y => exact false | fixed n => cases n <;> exact false
def monotoneResponseContrast reviewed
Causalean.SCM.Examples.MonotoneCounterfactualBound

The real-valued response contrast of the Boolean outcome equation.

Definition (Lean source)
noncomputable def monotoneResponseContrast : SCM BoolChainNode boolChainΩ → ℝ := fun M => if hchild : SWIGNode.random y ∈ M.observed then if SWIGNode.random d ∈ M.dag.parents (SWIGNode.random y) then boolScore (M.structFun ⟨SWIGNode.random y, hchild⟩ (boolParentAssignmentIn M true)) - boolScore (M.structFun ⟨SWIGNode.random y, hchild⟩ (boolParentAssignmentIn M false)) else 0 else 0
theorem monotoneCounterfactualBound reviewed
Causalean.SCM.Examples.MonotoneCounterfactualBound

Structural monotonicity of the outcome mechanism in the treatment parent forces every response contrast in the compatible class to lie in the valid [0, 1] partial-identification interval.

Formal statement
compatibleInterval boolChainSWIG (MonotoneMechanism (Ω := boolChainΩ) (SWIGNode.random y) (SWIGNode.random d)) monotoneBoolSCM monotoneResponseContrastIcc (0 : ℝ) 1
Proof (Lean source)
theorem monotoneCounterfactualBound : compatibleInterval boolChainSWIG (MonotoneMechanism (Ω := boolChainΩ) (SWIGNode.random y) (SWIGNode.random d)) monotoneBoolSCM monotoneResponseContrastIcc (0 : ℝ) 1 := by intro z hz rcases hz with ⟨⟨M, hM⟩, hz⟩ rcases hM.2.1 with ⟨hchild, hparent, hmono⟩ have hparent_le : boolParentAssignmentIn M false ⟨SWIGNode.random d, hparent⟩ ≤ boolParentAssignmentIn M true ⟨SWIGNode.random d, hparent⟩ := by change false ≤ true decide have hsame : ∀ w, w.val ≠ SWIGNode.random d → boolParentAssignmentIn M false w = boolParentAssignmentIn M true w := by intro w hw rcases w with ⟨n, hn⟩ cases n with | random n => cases n with | d => simp at hw | y => rfl | fixed n => cases n <;> rfl have hresp : M.structFun ⟨SWIGNode.random y, hchild⟩ (boolParentAssignmentIn M false) ≤ M.structFun ⟨SWIGNode.random y, hchild⟩ (boolParentAssignmentIn M true) := hmono (boolParentAssignmentIn M false) (boolParentAssignmentIn M true) hparent_le hsame rw [← hz] change monotoneResponseContrast M ∈ Icc (0 : ℝ) 1 rw [responseContrast_eq_of_present M hchild hparent] exact boolScore_sub_mem_Icc hresp
theorem monotoneCounterfactualBound_assumption_satisfiable reviewed
Causalean.SCM.Examples.MonotoneCounterfactualBound

The class of structural causal models compatible with the Boolean-chain graph and monotone in the outcome's treatment parent, evaluated against the copying model as reference, is nonempty.

Formal statement
Proof (Lean source)
theorem monotoneCounterfactualBound_assumption_satisfiable : CompatibleSCM boolChainSWIG (MonotoneMechanism (Ω := boolChainΩ) (SWIGNode.random y) (SWIGNode.random d)) monotoneBoolSCM monotoneBoolSCM := by exact compatibleSCM_self _ _ _ rfl monotoneBoolSCM_satisfies
theorem monotoneCounterfactualBound_fails_without_monotonicity reviewed
Causalean.SCM.Examples.MonotoneCounterfactualBound

Without the monotonicity restriction, the unconstrained compatible class's response contrast need not lie in [0, 1].

Formal statement
Proof (Lean source)
theorem monotoneCounterfactualBound_fails_without_monotonicity : ¬ compatibleInterval boolChainSWIG (fun _ : SCM BoolChainNode boolChainΩ => True) antitoneBoolSCM monotoneResponseContrastIcc (0 : ℝ) 1 := by intro hsub have hmem : (-1 : ℝ) ∈ compatibleInterval boolChainSWIG (fun _ : SCM BoolChainNode boolChainΩ => True) antitoneBoolSCM monotoneResponseContrast := by refine ⟨⟨antitoneBoolSCM, ?_⟩, ?_⟩ · exact compatibleSCM_self _ _ _ rfl trivial · exact monotoneResponseContrast_antitoneBoolSCM have hbad := hsub hmem norm_num at hbad
3 supporting declarations (lemmas, instances)