SCM.Do
The do-calculus on structural causal models: the three rules, global/local Markov properties, semi-graphoid axioms, and the kernel-level Rule 2 development.
FullCondIndep 3 core · 7 supporting This file defines conditional independence on the full random state of a structural causal model, including both observed variables and latent variables. ★ fullCondIndep_weak_union★ fullCondIndep_contraction
Full Conditional Independence
This file defines conditional independence on the full random state of a structural causal model, including both observed variables and latent variables. It also develops the semi-graphoid rules needed before projecting full-distribution Markov statements down to observational distributions.
For a population of nodes that is finite and has decidable equality, a value-space assignment to those nodes with a measurable structure on every assigned value space, a structural causal model whose full random state is a standard Borel space, three sets of random nodes that are each contained in the model's random-node set, and a finite measure on the full random state, full conditional independence asserts that the coordinate values of the first and second node sets are conditionally independent given the σ-algebra generated by the coordinate values of the third set.
Definition (Lean source)
Weak union for full conditional independence. Let M be a structural causal model and let μ be a finite measure on the full random state (observed together with latent variables). Suppose X, Y ∪ W, and Z ∪ W are all sets of M's random variables, and that, under μ, X is conditionally independent of Y ∪ W given Z. Then X is conditionally independent of Y given Z ∪ W.
Formal statement
Proof (Lean source)
Contraction for full conditional independence. Let M be a structural causal model and let μ be a finite measure on the full random state. Suppose X, Y, W, and Z are all sets of M's random variables, and that, under μ, X is conditionally independent of Y given Z ∪ W and X is conditionally independent of W given Z. Then X is conditionally independent of Y ∪ W given Z.
Formal statement
Proof (Lean source)
7 supporting declarations (lemmas, instances)
-
FullCondIndep_ifflemma — Full conditional independence of two node sets given a third, under a measure on the model's random values, is exactly conditional independence of the two coordinate projections given the σ-algebra generated by the conditioning projection.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValueshX :X ⊆ M.randomVarshY :Y ⊆ M.randomVarshZ :Z ⊆ M.randomVarsμ :Measure M.RandomValuesconclusionFullCondIndep M X Y Z hX hY hZ μ↔ CondIndepFun (comap (valuesProjection hZ) inferInstance) (comap_valuesProjection_le hZ) (valuesProjection hX) (valuesProjection hY) μProof (Lean source)
@[causal_defs_simps] lemma FullCondIndep_iff (M : SCM N Ω) [StandardBorelSpace M.RandomValues] (X Y Z : Finset (SWIGNode N)) (hX : X ⊆ M.randomVars) (hY : Y ⊆ M.randomVars) (hZ : Z ⊆ M.randomVars) (μ : Measure M.RandomValues) [IsFiniteMeasure μ] : FullCondIndep M X Y Z hX hY hZ μ ↔ CondIndepFun (comap (valuesProjection hZ) inferInstance) (comap_valuesProjection_le hZ) (valuesProjection hX) (valuesProjection hY) μ := Iff.rfl -
fullCondIndep_symmtheorem — Symmetry for FullCondIndep.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValueshX :X ⊆ M.randomVarshY :Y ⊆ M.randomVarshZ :Z ⊆ M.randomVarsμ :Measure M.RandomValuesh :FullCondIndep M X Y Z hX hY hZ μconclusionFullCondIndep M Y X Z hY hX hZ μProof (Lean source)
theorem fullCondIndep_symm (M : SCM N Ω) [StandardBorelSpace M.RandomValues] {X Y Z : Finset (SWIGNode N)} (hX : X ⊆ M.randomVars) (hY : Y ⊆ M.randomVars) (hZ : Z ⊆ M.randomVars) {μ : Measure M.RandomValues} [IsFiniteMeasure μ] (h : FullCondIndep M X Y Z hX hY hZ μ) : FullCondIndep M Y X Z hY hX hZ μ := by simp only [causal_defs_simps] at h ⊢ exact condIndep_valuesProjection_symm hX hY hZ h -
fullCondIndep_subset_righttheorem — Subset right for FullCondIndep.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValueshX :X ⊆ M.randomVarshY :Y ⊆ M.randomVarshY' :Y' ⊆ M.randomVarshZ :Z ⊆ M.randomVarshY'Y :Y' ⊆ Yμ :Measure M.RandomValuesh :FullCondIndep M X Y Z hX hY hZ μconclusionFullCondIndep M X Y' Z hX hY' hZ μProof (Lean source)
theorem fullCondIndep_subset_right (M : SCM N Ω) [StandardBorelSpace M.RandomValues] {X Y Y' Z : Finset (SWIGNode N)} (hX : X ⊆ M.randomVars) (hY : Y ⊆ M.randomVars) (hY' : Y' ⊆ M.randomVars) (hZ : Z ⊆ M.randomVars) (hY'Y : Y' ⊆ Y) {μ : Measure M.RandomValues} [IsFiniteMeasure μ] (h : FullCondIndep M X Y Z hX hY hZ μ) : FullCondIndep M X Y' Z hX hY' hZ μ := by simp only [causal_defs_simps] at h ⊢ exact condIndep_valuesProjection_subset_right hX hY hY' hZ hY'Y h -
fullCondIndep_decompositiontheorem — Decomposition for FullCondIndep.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValueshX :X ⊆ M.randomVarshYW :(Y ∪ W) ⊆ M.randomVarshZ :Z ⊆ M.randomVarsμ :Measure M.RandomValuesh :FullCondIndep M X (Y ∪ W) Z hX hYW hZ μconclusionFullCondIndep M X Y Z hX (Finset.subset_union_left.trans hYW) hZ μProof (Lean source)
theorem fullCondIndep_decomposition (M : SCM N Ω) [StandardBorelSpace M.RandomValues] {X Y W Z : Finset (SWIGNode N)} (hX : X ⊆ M.randomVars) (hYW : (Y ∪ W) ⊆ M.randomVars) (hZ : Z ⊆ M.randomVars) {μ : Measure M.RandomValues} [IsFiniteMeasure μ] (h : FullCondIndep M X (Y ∪ W) Z hX hYW hZ μ) : FullCondIndep M X Y Z hX (Finset.subset_union_left.trans hYW) hZ μ := by let hY : Y ⊆ M.randomVars := Finset.subset_union_left.trans hYW simp only [causal_defs_simps] at h ⊢ exact condIndep_valuesProjection_decomposition hX hYW hZ h -
fullCondIndep_congr_lefttheorem — Transport FullCondIndep along a Finset equality in the first argument. Used in the Verma–Pearl induction to convert {a} ∪ A' to insert a A'.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValuesheq :X = X'hX :X ⊆ M.randomVarshY :Y ⊆ M.randomVarshZ :Z ⊆ M.randomVarsμ :Measure M.RandomValuesh :FullCondIndep M X Y Z hX hY hZ μconclusionFullCondIndep M X' Y Z (heq ▸ hX) hY hZ μProof (Lean source)
theorem fullCondIndep_congr_left (M : SCM N Ω) [StandardBorelSpace M.RandomValues] {X X' Y Z : Finset (SWIGNode N)} (heq : X = X') {hX : X ⊆ M.randomVars} {hY : Y ⊆ M.randomVars} {hZ : Z ⊆ M.randomVars} {μ : Measure M.RandomValues} [IsFiniteMeasure μ] (h : FullCondIndep M X Y Z hX hY hZ μ) : FullCondIndep M X' Y Z (heq ▸ hX) hY hZ μ := by subst heq; exact h -
fullCondIndep_congr_righttheorem — Transport FullCondIndep along a Finset equality in the conditioning set. Used to align an empty conditioning set with parents v ∩ randomVars when v is a latent root.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValuesheq :Z = Z'hX :X ⊆ M.randomVarshY :Y ⊆ M.randomVarshZ :Z ⊆ M.randomVarsμ :Measure M.RandomValuesh :FullCondIndep M X Y Z hX hY hZ μconclusionFullCondIndep M X Y Z' hX hY (heq ▸ hZ) μProof (Lean source)
theorem fullCondIndep_congr_right (M : SCM N Ω) [StandardBorelSpace M.RandomValues] {X Y Z Z' : Finset (SWIGNode N)} (heq : Z = Z') {hX : X ⊆ M.randomVars} {hY : Y ⊆ M.randomVars} {hZ : Z ⊆ M.randomVars} {μ : Measure M.RandomValues} [IsFiniteMeasure μ] (h : FullCondIndep M X Y Z hX hY hZ μ) : FullCondIndep M X Y Z' hX hY (heq ▸ hZ) μ := by subst heq; exact h -
fullCondIndep_const_lefttheorem — The empty source set is conditionally independent of anything: with X = ∅, the projection valuesProjection ∅ is constant, so FullCondIndep holds trivially. Interprets the nil constructor of OrderedLocalSG.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValueshY :Y ⊆ M.randomVarshZ :Z ⊆ M.randomVarsμ :Measure M.RandomValuesconclusionFullCondIndep M ∅ Y Z (empty_subset _) hY hZ μProof (Lean source)
theorem fullCondIndep_const_left (M : SCM N Ω) [StandardBorelSpace M.RandomValues] {Y Z : Finset (SWIGNode N)} (hY : Y ⊆ M.randomVars) (hZ : Z ⊆ M.randomVars) {μ : Measure M.RandomValues} [IsFiniteMeasure μ] : FullCondIndep M ∅ Y Z (empty_subset _) hY hZ μ := by simp only [causal_defs_simps] let c : ValuesOn (∅ : Finset (SWIGNode N)) (swigΩ Ω) := fun w => absurd w.property (notMem_empty _) have hconst : valuesProjection (Ω := swigΩ Ω) (empty_subset M.randomVars) = fun _ => c := by funext ξ w; exact absurd w.property (notMem_empty _) rw [hconst] exact ProbabilityTheory.condIndepFun_const_left c (valuesProjection hY)
SemiGraphoid 4 core · 7 supporting This file defines ObsCondIndep, conditional independence for projections of the observed state of a structural causal model under an arbitrary finite observational measure. ★ obsCondIndep_decomposition★ obsCondIndep_weak_union★ obsCondIndep_contraction
Observational Conditional Independence
This file defines ObsCondIndep, conditional independence for projections of
the observed state of a structural causal model under an arbitrary finite
observational measure. It also proves the semi-graphoid rules used by the Markov
and do-calculus layers: obsCondIndep_symm, obsCondIndep_subset_right,
obsCondIndep_decomposition, obsCondIndep_weak_union, and
obsCondIndep_contraction. The corresponding condIndep_valuesProjection_*
theorems expose the same coordinate-projection facts directly for finite product
spaces.
For a finite collection of distinguishable node labels with measurable value spaces, a structural causal model, three sets of observed nodes, respectively the first, second, and conditioning sets, each of which is contained in the model's observed-node set, and a finite measure on the standard-Borel observed-value space, the observational conditional-independence relation asserts that the value vectors on the first and second node sets are conditionally independent given the value vector on the conditioning set under that measure.
Definition (Lean source)
Decomposition. Let X, Y, W, Z be finite node sets of the structural causal model M, with X and the union of Y and W contained in the observed nodes, and Z contained in the observed nodes, under a finite measure μ on the observed values. If X is conditionally independent of the union of Y and W given Z, then X is conditionally independent of Y given Z.
Formal statement
Proof (Lean source)
Weak union. Let X, Y, W, Z be finite node sets of the structural causal model M, with X and the union of Y and W contained in the observed nodes, and Z contained in the observed nodes, under a finite measure μ on the observed values. If X is conditionally independent of the union of Y and W given Z, then X is conditionally independent of Y given the union of Z and W.
Formal statement
Proof (Lean source)
Contraction. Fix subsets X, Y, W, Z of the node set of the structural causal model M, with X, Y, W, and Z each contained in the observed nodes, and let μ be a finite measure on the observed values. If X is conditionally independent of Y given the union of Z and W and X is conditionally independent of W given Z, then X is conditionally independent of the union of Y and W given Z.
Formal statement
Proof (Lean source)
7 supporting declarations (lemmas, instances)
-
obsCondIndep_symmtheorem — Symmetry. Conditional independence is symmetric in X and Y.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.ObservedValueshX :X ⊆ M.observedhY :Y ⊆ M.observedhW :W ⊆ M.observedμ :Measure M.ObservedValuesh :ObsCondIndep M X Y W hX hY hW μconclusionObsCondIndep M Y X W hY hX hW μProof (Lean source)
theorem obsCondIndep_symm (M : SCM N Ω) [StandardBorelSpace M.ObservedValues] {X Y W : Finset (SWIGNode N)} (hX : X ⊆ M.observed) (hY : Y ⊆ M.observed) (hW : W ⊆ M.observed) {μ : Measure M.ObservedValues} [IsFiniteMeasure μ] (h : ObsCondIndep M X Y W hX hY hW μ) : ObsCondIndep M Y X W hY hX hW μ := h.symm -
condIndep_valuesProjection_symmtheorem — Symmetry for CondIndepFun when coordinates are given by valuesProjection.hypotheseshX :X ⊆ IhY :Y ⊆ IhZ :Z ⊆ Iμ :h :CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hY) μconclusionCondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hY) (valuesProjection (Ω := swigΩ Ω) hX) μProof (Lean source)
theorem condIndep_valuesProjection_symm {I X Y Z : Finset (SWIGNode N)} (hX : X ⊆ I) (hY : Y ⊆ I) (hZ : Z ⊆ I) [StandardBorelSpace (ValuesOn I (swigΩ Ω))] {μ : Measure (ValuesOn I (swigΩ Ω))} [IsFiniteMeasure μ] (h : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hY) μ) : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hY) (valuesProjection (Ω := swigΩ Ω) hX) μ := h.symm -
condIndep_valuesProjection_subset_righttheorem — Subset-right for CondIndepFun when coordinates are given by valuesProjection.hypotheseshX :X ⊆ IhY :Y ⊆ IhY' :Y' ⊆ IhZ :Z ⊆ IhY'Y :Y' ⊆ Yμ :h :CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hY) μconclusionCondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hY') μProof (Lean source)
theorem condIndep_valuesProjection_subset_right {I X Y Y' Z : Finset (SWIGNode N)} (hX : X ⊆ I) (hY : Y ⊆ I) (hY' : Y' ⊆ I) (hZ : Z ⊆ I) (hY'Y : Y' ⊆ Y) [StandardBorelSpace (ValuesOn I (swigΩ Ω))] {μ : Measure (ValuesOn I (swigΩ Ω))} [IsFiniteMeasure μ] (h : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hY) μ) : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hY') μ := by have h' := h.comp measurable_id (measurable_valuesProjection (Ω' := swigΩ Ω) hY'Y) simpa [Function.id_comp, valuesProjection_comp (Ω' := swigΩ Ω) hY'Y hY] using h' -
condIndep_valuesProjection_decompositiontheorem — Decomposition for CondIndepFun when coordinates are given by valuesProjection.hypotheseshX :X ⊆ IhYW :(Y ∪ W) ⊆ IhZ :Z ⊆ Iμ :h :CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hYW) μconclusionCondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) (Finset.subset_union_left.trans hYW)) μProof (Lean source)
theorem condIndep_valuesProjection_decomposition {I X Y W Z : Finset (SWIGNode N)} (hX : X ⊆ I) (hYW : (Y ∪ W) ⊆ I) (hZ : Z ⊆ I) [StandardBorelSpace (ValuesOn I (swigΩ Ω))] {μ : Measure (ValuesOn I (swigΩ Ω))} [IsFiniteMeasure μ] (h : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hYW) μ) : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) (Finset.subset_union_left.trans hYW)) μ := condIndep_valuesProjection_subset_right hX hYW (Finset.subset_union_left.trans hYW) hZ subset_union_left h -
condIndep_valuesProjection_weak_union_axiomtheorem — Weak union for CondIndepFun when coordinates are given by valuesProjection.hypotheseshX :X ⊆ IhYW :(Y ∪ W) ⊆ IhZ :Z ⊆ Iμ :h :CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hYW) μconclusionCondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) (union_subset hZ (Finset.subset_union_right.trans hYW))) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) (union_subset hZ (Finset.subset_union_right.trans hYW))) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) (Finset.subset_union_left.trans hYW)) μProof (Lean source)
theorem condIndep_valuesProjection_weak_union_axiom {I X Y W Z : Finset (SWIGNode N)} (hX : X ⊆ I) (hYW : (Y ∪ W) ⊆ I) (hZ : Z ⊆ I) [StandardBorelSpace (ValuesOn I (swigΩ Ω))] {μ : Measure (ValuesOn I (swigΩ Ω))} [IsFiniteMeasure μ] (h : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hYW) μ) : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) (union_subset hZ (Finset.subset_union_right.trans hYW))) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) (union_subset hZ (Finset.subset_union_right.trans hYW))) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) (Finset.subset_union_left.trans hYW)) μ := condIndep_valuesProjection_weak_union (M := SWIGNode N) (I := I) (X := X) (Y := Y) (W := W) (Z := Z) (Ω := swigΩ Ω) hX hYW (union_subset hZ (Finset.subset_union_right.trans hYW)) h -
condIndep_valuesProjection_contraction_axiomtheorem — Contraction for CondIndepFun when coordinates are given by valuesProjection.hypotheseshX :X ⊆ IhY :Y ⊆ IhW :W ⊆ IhZ :Z ⊆ Iμ :h1 :CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) (union_subset hZ hW)) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) (union_subset hZ hW)) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hY) μh2 :CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hW) μconclusionCondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) (union_subset hY hW)) μProof (Lean source)
theorem condIndep_valuesProjection_contraction_axiom {I X Y W Z : Finset (SWIGNode N)} (hX : X ⊆ I) (hY : Y ⊆ I) (hW : W ⊆ I) (hZ : Z ⊆ I) [StandardBorelSpace (ValuesOn I (swigΩ Ω))] {μ : Measure (ValuesOn I (swigΩ Ω))} [IsFiniteMeasure μ] (h1 : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) (union_subset hZ hW)) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) (union_subset hZ hW)) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hY) μ) (h2 : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) hW) μ) : CondIndepFun (comap (valuesProjection (Ω := swigΩ Ω) hZ) inferInstance) (comap_valuesProjection_le (Ω' := swigΩ Ω) hZ) (valuesProjection (Ω := swigΩ Ω) hX) (valuesProjection (Ω := swigΩ Ω) (union_subset hY hW)) μ := condIndep_valuesProjection_contraction (M := SWIGNode N) (I := I) (X := X) (Y := Y) (W := W) (Z := Z) (Ω := swigΩ Ω) hX hY hW hZ h1 h2 -
obsCondIndep_subset_righttheorem — Subset right. If X ⊥ Y | Z and Y' ⊆ Y, then X ⊥ Y' | Z.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.ObservedValueshX :X ⊆ M.observedhY :Y ⊆ M.observedhY' :Y' ⊆ M.observedhZ :Z ⊆ M.observedhY'Y :Y' ⊆ Yμ :Measure M.ObservedValuesh :ObsCondIndep M X Y Z hX hY hZ μconclusionObsCondIndep M X Y' Z hX hY' hZ μProof (Lean source)
theorem obsCondIndep_subset_right (M : SCM N Ω) [StandardBorelSpace M.ObservedValues] {X Y Y' Z : Finset (SWIGNode N)} (hX : X ⊆ M.observed) (hY : Y ⊆ M.observed) (hY' : Y' ⊆ M.observed) (hZ : Z ⊆ M.observed) (hY'Y : Y' ⊆ Y) {μ : Measure M.ObservedValues} [IsFiniteMeasure μ] (h : ObsCondIndep M X Y Z hX hY hZ μ) : ObsCondIndep M X Y' Z hX hY' hZ μ := by unfold ObsCondIndep at h ⊢ exact condIndep_valuesProjection_subset_right (μ := μ) hX hY hY' hZ hY'Y h
LocalMarkov 2 core · 1 supporting This file proves that each observed variable in a structural causal model is conditionally independent of its non-descendants, given all of its parents, under the full joint distribution over observed and latent variable ★ full_local_markov★ full_local_markov_latent
Full Local Markov Property
This file proves that each observed variable in a structural causal model is conditionally independent of its non-descendants, given all of its parents, under the full joint distribution over observed and latent variables. It also proves the latent-root analogue and records the pushforward bridge used to move conditional independence through the evaluation map.
The main public results are:
* Causalean.Mathlib.Probability.Independence.Conditional.condIndepFun_of_map,
which transports conditional independence through a
measurable pushforward.
* SCM.full_local_markov, the observed-node local Markov property for
jointKernel.
* SCM.full_local_markov_latent, the corresponding independence statement for
latent root nodes.
Full Local Markov Property. If v is an observed node of the model, then under the joint distribution over all random (observed and latent) coordinates at fixed value s, the v-coordinate is conditionally independent of its non-descendants — restricted to random nodes — given all of its parents, including any latent parents, likewise restricted to random nodes.
Formal statement
Proof (Lean source)
Latent Local Markov Property. If a is a latent (unobserved) node of the model, then under the joint distribution over all random coordinates at fixed value s, the a-coordinate is unconditionally independent of its non-descendants — restricted to random nodes — i.e. conditionally independent given the empty conditioning set.
Formal statement
Proof (Lean source)
1 supporting declaration (lemmas, instances)
-
observed_subset_randomVarstheorem — Observed nodes lie in randomVars.Proof (Lean source)
CutsetDSep 2 core · 9 supporting This file transfers d-separation from a target set Y to the latent cutset that drives Y while avoiding an overridden block. ★ cutsetLatent_dSep_of_dSep★ cutsetLatent_dSep_of_fixSet_dSep
Concatenation d-separation for the latent cutset
This file transfers d-separation from a target set Y to the latent cutset that
drives Y while avoiding an overridden block. If Y is d-separated from the
randomised do-block Zr given the adjustment set W together with a block of
fixed nodes F, then the same separation holds for the latent cutset
cutsetLatent Y (Zr ∪ W). The proof concatenates an active path from Zr to a
cutset node c with the directed cutset arm c → … → Y: the join at the latent
node c is a fork, so the glued path is active and reaches Y from Zr,
contradicting the assumed separation.
Main results
* SCM.cutsetLatent_dSep_of_dSep — the concatenation d-separation:
dSep Y Zr (W ∪ F) → dSep (cutsetLatent Y (Zr ∪ W)) Zr (W ∪ F).
* SCM.cutsetLatent_dSep_of_fixSet_dSep — the cross-model variant: separation of
Y from Zr in the intervened graph fixSet Z (given W ∪ fixSet.fixed),
together with backdoor criterion (i) for W (no w ∈ W is a base-graph
descendant of any treatment random D, D ∈ Z), yields the same latent-cutset
separation in the base graph M. The base-graph active path is transported
edge-by-edge into fixSet Z; criterion (i) guarantees no treatment out-edge is
needed.
Concatenation d-separation for the latent cutset. Suppose W consists of observed nodes and F consists of fixed nodes, and that the target set Y is d-separated from the randomised do-block Zr given W together with F. Then the latent cutset cutsetLatent Y (Zr ∪ W) — the latent roots reaching Y along a directed path whose interior avoids Zr ∪ W — is likewise d-separated from Zr given the same W ∪ F.
Formal statement
Proof (Lean source)
Cross-model concatenation d-separation for the latent cutset. Suppose that, in the intervened model M.fixSet Z _ _, the target set Y is d-separated from the randomised do-block Zr = Z.image .random given the adjustment set W together with the post-intervention fixed block, where W consists of observed nodes and no w ∈ W is, in the base graph M.dag, a descendant of any treatment's random copy .random D (D ∈ Z) — backdoor criterion (i). Then, in the base model M, the latent cutset cutsetLatent Y (Zr ∪ W) is d-separated from Zr given W ∪ M.fixed.
Formal statement
Proof (Lean source)
9 supporting declarations (lemmas, instances)
-
edge_fixSet_of_edgelemma — A directed edge in the original graph remains an edge after fixing treatments when its source is not the random copy of any treatment being fixed.hypothesesN :sharedType u_1N → Type u_2hZ_obs :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.random D ∈ M.observedhZ_fixed :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.fixed D ∉ M.fixedu v :SWIGNode Nhe :M.dag.edge u vhu :∀ D ∈ Z, u ≠ SWIGNode.random Dconclusion(M.fixSet Z hZ_obs hZ_fixed).dag.edge u vProof (Lean source)
lemma edge_fixSet_of_edge {u v : SWIGNode N} (he : M.dag.edge u v) (hu : ∀ D ∈ Z, u ≠ SWIGNode.random D) : (M.fixSet Z hZ_obs hZ_fixed).dag.edge u v := by have h_eqrel : (M.fixSet Z hZ_obs hZ_fixed).dag.edge u v ↔ SWIGGraph.splitMonoEdgeRel M.toSWIGGraph.dag.edge Z u v := by simp only [SCM.fixSet, SCM.fixMono, SWIGGraph.splitMono, SWIGGraph.splitMonoDAG] rw [h_eqrel] cases u with | random u' => by_cases h : u' ∈ Z · exact absurd rfl (hu u' h) · simpa only [SWIGGraph.splitMonoEdgeRel, if_neg h] using he | fixed d => by_cases h : d ∈ Z · -- `.fixed d` (`d ∈ Z`) is isolated in `M` (`hZ_fixed`), so `he` is impossible. have hfix_notin : SWIGNode.fixed d ∉ M.fixed := hZ_fixed d h have hiso := (M.fixed_outside_fixed_isolated d hfix_notin).2 have hch : v ∈ M.dag.children (SWIGNode.fixed d) := M.dag.mem_children.mpr he rw [hiso] at hch exact absurd hch (notMem_empty _) · simpa only [SWIGGraph.splitMonoEdgeRel, if_neg h] using he -
edge_of_edge_fixSetlemma — Every directed edge after fixing treatments is either an original edge or the redirected outgoing edge from the fixed copy of a treatment being fixed.hypothesesN :sharedType u_1N → Type u_2hZ_obs :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.random D ∈ M.observedhZ_fixed :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.fixed D ∉ M.fixedu v :SWIGNode Nhe :(M.fixSet Z hZ_obs hZ_fixed).dag.edge u vconclusionM.dag.edge u v ∨ (∃ D ∈ Z, u = SWIGNode.fixed D ∧ M.dag.edge (SWIGNode.random D) v)Proof (Lean source)
lemma edge_of_edge_fixSet {u v : SWIGNode N} (he : (M.fixSet Z hZ_obs hZ_fixed).dag.edge u v) : M.dag.edge u v ∨ (∃ D ∈ Z, u = SWIGNode.fixed D ∧ M.dag.edge (SWIGNode.random D) v) := by have h_eqrel : (M.fixSet Z hZ_obs hZ_fixed).dag.edge u v ↔ SWIGGraph.splitMonoEdgeRel M.toSWIGGraph.dag.edge Z u v := by simp only [SCM.fixSet, SCM.fixMono, SWIGGraph.splitMono, SWIGGraph.splitMonoDAG] rw [h_eqrel] at he cases u with | random u' => by_cases h : u' ∈ Z · simp only [SWIGGraph.splitMonoEdgeRel, if_pos h] at he · exact inl (by simpa only [SWIGGraph.splitMonoEdgeRel, if_neg h] using he) | fixed d => by_cases h : d ∈ Z · exact inr ⟨d, h, rfl, by simpa only [SWIGGraph.splitMonoEdgeRel, if_pos h] using he⟩ · exact inl (by simpa only [SWIGGraph.splitMonoEdgeRel, if_neg h] using he) -
isAncestor_fixSet_of_isAncestorlemma — A directed ancestry path in a causal graph remains after intervening on a set when every possible edge source along that path is not a random copy of an intervened variable. Thus the original ancestor remains an ancestor in the intervened graph.hypothesesN :sharedType u_1N → Type u_2hZ_obs :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.random D ∈ M.observedhZ_fixed :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.fixed D ∉ M.fixedu v :SWIGNode Nhanc :M.dag.isAncestor u vhNoT :∀ sif(s = u ∨ M.dag.isAncestor u s)andM.dag.isAncestor s vthen∀ D ∈ Z, s ≠ SWIGNode.random Dconclusion(M.fixSet Z hZ_obs hZ_fixed).dag.isAncestor u vProof (Lean source)
lemma isAncestor_fixSet_of_isAncestor {u v : SWIGNode N} (hanc : M.dag.isAncestor u v) (hNoT : ∀ s, (s = u ∨ M.dag.isAncestor u s) → M.dag.isAncestor s v → ∀ D ∈ Z, s ≠ SWIGNode.random D) : (M.fixSet Z hZ_obs hZ_fixed).dag.isAncestor u v := by induction hanc with | @edge b he => exact DAG.isAncestor.edge (edge_fixSet_of_edge M Z hZ_obs hZ_fixed he (hNoT u (inl rfl) (DAG.isAncestor.edge he))) | @trans w b hrec he ih => -- `u ⤳ w → b`. The last edge source `w` is `u` or a proper ancestor of `b` -- reachable from `u`, and an ancestor of `b`; so `hNoT` gives `w` non-treatment. have hwNoT : ∀ D ∈ Z, w ≠ SWIGNode.random D := hNoT w (inr hrec) (DAG.isAncestor.edge he) refine DAG.isAncestor.trans ?_ (edge_fixSet_of_edge M Z hZ_obs hZ_fixed he hwNoT) refine ih ?_ intro s hs hsw exact hNoT s hs (DAG.isAncestor.trans hsw he) -
treatment_not_isAncestor_condlemma — Under the backdoor non-descendancy condition, a treatment node cannot be a proper ancestor of any node in the observed-or-fixed conditioning block.hypothesesN :sharedType u_1N → Type u_2hWNonDescM1 :∀ D ∈ Z, ∀ w ∈ W, ¬ M.dag.isAncestor (SWIGNode.random D) wD :NhD :D ∈ Zc :SWIGNode Nhc :c ∈ W ∪ M.fixedhanc :M.dag.isAncestor (SWIGNode.random D) cconclusionProof (Lean source)
lemma treatment_not_isAncestor_cond (W : Finset (SWIGNode N)) (hWNonDescM1 : ∀ D ∈ Z, ∀ w ∈ W, ¬ M.dag.isAncestor (SWIGNode.random D) w) {D : N} (hD : D ∈ Z) {c : SWIGNode N} (hc : c ∈ W ∪ M.fixed) (hanc : M.dag.isAncestor (SWIGNode.random D) c) : False := by rcases Finset.mem_union.mp hc with hcW | hcF · exact hWNonDescM1 D hD c hcW hanc · -- `c ∈ M.fixed` is a root, hence has no incoming edge: but `· ⤳ c` ends with -- an edge `· → c`, contradiction. have hpar : ∃ p, M.dag.edge p c := by cases hanc with | edge he => exact ⟨_, he⟩ | trans _ he => exact ⟨_, he⟩ obtain ⟨p, hpc⟩ := hpar have hpmem : p ∈ M.dag.parents c := M.dag.mem_parents.mpr hpc rw [M.fixed_are_roots c hcF] at hpmem exact absurd hpmem (notMem_empty _) -
bbZAncestors_fixSet_transportlemma — A node in the Bayes-ball ancestor set of a target set and the model's fixed nodes remains in the corresponding ancestor set after intervention, once the fixed treatment copies are added to the target set, provided no treatment's random copy is an ancestor of a target node.hypothesesN :sharedType u_1N → Type u_2hZ_obs :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.random D ∈ M.observedhZ_fixed :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.fixed D ∉ M.fixedhWNonDescM1 :∀ D ∈ Z, ∀ w ∈ W, ¬ M.dag.isAncestor (SWIGNode.random D) wm :SWIGNode Nhm :m ∈ M.dag.bbZAncestors (W ∪ M.fixed)conclusionm ∈ (M.fixSet Z hZ_obs hZ_fixed).dag.bbZAncestors (W ∪ M.fixed ∪ Z.image SWIGNode.fixed)Proof (Lean source)
lemma bbZAncestors_fixSet_transport (W : Finset (SWIGNode N)) (hWNonDescM1 : ∀ D ∈ Z, ∀ w ∈ W, ¬ M.dag.isAncestor (SWIGNode.random D) w) {m : SWIGNode N} (hm : m ∈ M.dag.bbZAncestors (W ∪ M.fixed)) : m ∈ (M.fixSet Z hZ_obs hZ_fixed).dag.bbZAncestors (W ∪ M.fixed ∪ Z.image SWIGNode.fixed) := by simp only [DAG.bbZAncestors, DAG.ancestralSet, DAG.ancestorsSet, mem_union, mem_filter, Finset.mem_univ, true_and] at hm ⊢ rcases hm with hmC | ⟨c, hcC, hanc⟩ · exact inl (inl hmC) · -- `m ⤳ c` in `M`; transport the directed path to `M.fixSet Z`. refine inr ⟨c, inl hcC, ?_⟩ have hcC' : c ∈ W ∪ M.fixed := Finset.mem_union.mpr hcC refine isAncestor_fixSet_of_isAncestor M Z hZ_obs hZ_fixed hanc ?_ intro s _ hsc D hD hsEq subst hsEq exact treatment_not_isAncestor_cond M Z W hWNonDescM1 hD hcC' hsc -
not_fixedTreatment_of_uadjlemma — A node incident to a directed edge in the base graph cannot be the fixed copy of a treatment variable that is newly fixed by the intervention.hypothesesN :sharedType u_1N → Type u_2hZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M.fixeda v :SWIGNode Nh :M.dag.UAdj a vD :NhD :D ∈ Zconclusionv ≠ SWIGNode.fixed DProof (Lean source)
lemma not_fixedTreatment_of_uadj (hZ_fixed : ∀ D ∈ Z, SWIGNode.fixed D ∉ M.fixed) {a v : SWIGNode N} (h : M.dag.UAdj a v) {D : N} (hD : D ∈ Z) : v ≠ SWIGNode.fixed D := by intro hveq have hiso := M.fixed_outside_fixed_isolated D (hZ_fixed D hD) rw [hveq] at h rcases h with hav | hva · -- `edge a (fixed D)`: `a` is a parent of `fixed D`, but `fixed D` is a root. have hmem : a ∈ M.dag.parents (SWIGNode.fixed D) := M.dag.mem_parents.mpr hav rw [hiso.1] at hmem; exact absurd hmem (notMem_empty _) · -- `edge (fixed D) a`: `a` is a child of `fixed D`, but `fixed D` is isolated. have hmem : a ∈ M.dag.children (SWIGNode.fixed D) := M.dag.mem_children.mpr hva rw [hiso.2] at hmem; exact absurd hmem (notMem_empty _) -
path_fixSet_activelemma — Given a finite structural causal model, treatment set, and conditioning set, if every treatment random copy is observed, no treatment fixed copy is already fixed, no treatment random copy is an ancestor of a conditioning node, a path is active before intervention, and neither source of a directed edge along the path is a treatment random copy, then the path remains active after fixing the treatment set and adding its fixed copies to the conditioning set.hypothesesN :sharedType u_1N → Type u_2hZ_obs :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.random D ∈ M.observedhZ_fixed :shared∀ D ∈ Z, Causalean.Graph.SWIGNode.fixed D ∉ M.fixedhWNonDescM1 :∀ D ∈ Z, ∀ w ∈ W, ¬ M.dag.isAncestor (SWIGNode.random D) whact :M.dag.IsActiveWalk (W ∪ M.fixed) PhInEdge :∀ (i : ℕ) (hi : i + 1 < P.length),(M.dag.edge (P.get ⟨i, by omega⟩) (P.get ⟨i + 1, hi⟩) → ∀ D ∈ Z, P.get ⟨i, by omega⟩ ≠ SWIGNode.random D) ∧(M.dag.edge (P.get ⟨i + 1, hi⟩) (P.get ⟨i, by omega⟩) → ∀ D ∈ Z, P.get ⟨i + 1, hi⟩ ≠ SWIGNode.random D)conclusion(M.fixSet Z hZ_obs hZ_fixed).dag.IsActiveWalk (W ∪ M.fixed ∪ Z.image SWIGNode.fixed) PProof (Lean source)
lemma path_fixSet_active (W : Finset (SWIGNode N)) (hWNonDescM1 : ∀ D ∈ Z, ∀ w ∈ W, ¬ M.dag.isAncestor (SWIGNode.random D) w) {P : List (SWIGNode N)} (hact : M.dag.IsActiveWalk (W ∪ M.fixed) P) (hInEdge : ∀ (i : ℕ) (hi : i + 1 < P.length), (M.dag.edge (P.get ⟨i, by omega⟩) (P.get ⟨i + 1, hi⟩) → ∀ D ∈ Z, P.get ⟨i, by omega⟩ ≠ SWIGNode.random D) ∧ (M.dag.edge (P.get ⟨i + 1, hi⟩) (P.get ⟨i, by omega⟩) → ∀ D ∈ Z, P.get ⟨i + 1, hi⟩ ≠ SWIGNode.random D)) : (M.fixSet Z hZ_obs hZ_fixed).dag.IsActiveWalk (W ∪ M.fixed ∪ Z.image SWIGNode.fixed) P := by obtain ⟨hadj, hcoll⟩ := hact set M2 := M.fixSet Z hZ_obs hZ_fixed with hM2 -- Adjacency survives. have hadj2 : ∀ (i : ℕ) (hi : i + 1 < P.length), M2.dag.UAdj (P.get ⟨i, by omega⟩) (P.get ⟨i + 1, hi⟩) := by intro i hi rcases hadj i hi with he | he · exact inl (edge_fixSet_of_edge M Z hZ_obs hZ_fixed he ((hInEdge i hi).1 he)) · exact inr (edge_fixSet_of_edge M Z hZ_obs hZ_fixed he ((hInEdge i hi).2 he)) refine ⟨hadj2, fun i hi => ?_⟩ -- The triple (l, m, r) at index i. set l := P.get ⟨i, by omega⟩ with hl set m := P.get ⟨i + 1, by omega⟩ with hm set r := P.get ⟨i + 2, hi⟩ with hr have hc := hcoll i hi simp only at hc ⊢ -- M2-collider ↔ M1-collider on the path triple. have hColl_iff : M2.dag.IsCollider l m r ↔ M.dag.IsCollider l m r := by constructor · rintro ⟨hlm, hrm⟩ refine ⟨?_, ?_⟩ · rcases edge_of_edge_fixSet M Z hZ_obs hZ_fixed hlm with h | ⟨D, hD, hlEq, _⟩ · exact h · -- `l = .fixed D` (D ∈ Z) is impossible: `l` is path-adjacent to `m`. exact absurd hlEq (not_fixedTreatment_of_uadj M Z hZ_fixed (M.dag.UAdj_symm (hadj i (by omega))) hD) · rcases edge_of_edge_fixSet M Z hZ_obs hZ_fixed hrm with h | ⟨D, hD, hrEq, _⟩ · exact h · have hadj_mr : M.dag.UAdj m r := hadj (i + 1) (by omega) exact absurd hrEq (not_fixedTreatment_of_uadj M Z hZ_fixed hadj_mr hD) · rintro ⟨hlm, hrm⟩ exact ⟨edge_fixSet_of_edge M Z hZ_obs hZ_fixed hlm ((hInEdge i (by omega)).1 hlm), edge_fixSet_of_edge M Z hZ_obs hZ_fixed hrm ((hInEdge (i + 1) (by omega)).2 hrm)⟩ by_cases hC : M.dag.IsCollider l m r · rw [if_pos (hColl_iff.mpr hC)] rw [if_pos hC] at hc exact bbZAncestors_fixSet_transport M Z hZ_obs hZ_fixed W hWNonDescM1 hc · rw [if_neg (fun h => hC (hColl_iff.mp h))] rw [if_neg hC] at hc -- `m ∉ W ∪ M.fixed`; also `m ∉ Z.image .fixed` since `m` is on the path. intro hmem rcases Finset.mem_union.mp hmem with hm1 | hm2 · exact hc hm1 · obtain ⟨D, hD, hDeq⟩ := Finset.mem_image.mp hm2 exact not_fixedTreatment_of_uadj M Z hZ_fixed (hadj i (by omega)) hD (hm ▸ hDeq.symm) -
activePath_forwardRun_absurdlemma — An active path that starts with an arrow flowing away from an ancestor cannot end at a root when that ancestor has no directed route to any activated conditioning ancestor. The result rules out a forward run that must either enter a root or create an activated collider.hypothesesV :G :DAG VC :Finset Vs :VhTreat :∀ kifk ∈ G.bbZAncestors Cthen¬ G.isAncestor s kprev m :Vrest :List VG.IsActiveWalk C (prev :: m :: rest)G.edge prev m(s = prev ∨ G.isAncestor s prev)(∀ p, ¬ G.edge p ((prev :: m :: rest).getLast (by simp)))conclusionProof (Lean source)
lemma Graph.DAG.activePath_forwardRun_absurd {V : Type*} [DecidableEq V] [Fintype V] (G : DAG V) {C : Finset V} {s : V} (hTreat : ∀ k, k ∈ G.bbZAncestors C → ¬ G.isAncestor s k) : ∀ (prev m : V) (rest : List V), G.IsActiveWalk C (prev :: m :: rest) → G.edge prev m → (s = prev ∨ G.isAncestor s prev) → (∀ p, ¬ G.edge p ((prev :: m :: rest).getLast (by simp))) → False := by intro prev m rest induction rest generalizing prev m with | nil => intro hact hpm _hsprev hroot -- The run is `[prev, m]`; `m` is the last node and a root, but `prev → m`. exact hroot prev (by simpa using hpm) | cons t rest ih => intro hact hpm hsprev hroot -- `s ⤳ m` from `s ⤳ prev → m`. have hsm : G.isAncestor s m := by rcases hsprev with hEq | hanc · exact hEq ▸ DAG.isAncestor.edge hpm · exact DAG.isAncestor.trans hanc hpm obtain ⟨hadj, hcoll⟩ := hact -- Adjacency of `m` and `t` (triple index 0 in the path). have hmt : G.UAdj m t := by have h := hadj 1 (by simp) simpa using h -- The active-path triple condition at index 0: triple (prev, m, t). have htri := hcoll 0 (by simp) simp only [List.get_eq_getElem, List.getElem_cons_zero, List.getElem_cons_succ] at htri rcases hmt with hmt | htm · -- Forward `m → t`: recurse with `prev := m`, dropping `prev`. -- The tail `m :: t :: rest` is active. have hact_tail : G.IsActiveWalk C (m :: t :: rest) := by refine ⟨fun i hi => ?_, fun i hi => ?_⟩ · have h := hadj (i + 1) (by simpa [Nat.add_assoc] using Nat.succ_lt_succ hi) simpa using h · have h := hcoll (i + 1) (by simpa [Nat.add_assoc] using Nat.succ_lt_succ hi) simpa [Nat.add_assoc] using h have hroot' : ∀ p, ¬ G.edge p ((m :: t :: rest).getLast (by simp)) := by simpa using hroot exact ih m t hact_tail hmt (inr hsm) hroot' · -- Backward `t → m`: `m` is a collider on the triple `(prev, m, t)`. have hC : G.IsCollider prev m t := ⟨hpm, htm⟩ rw [if_pos hC] at htri -- `htri : m ∈ bbZAncestors C`; but `s ⤳ m`. exact hTreat m htri hsm -
isActivePath_droplemma — Removing any initial segment of an active graph path leaves a path that is still active under the same conditioning set.hypothesesconclusionG.IsActiveWalk C (p.drop j)Proof (Lean source)
lemma DAG.isActivePath_drop {V : Type*} [DecidableEq V] [Fintype V] (G : DAG V) {C : Finset V} {p : List V} (j : ℕ) (hact : G.IsActiveWalk C p) : G.IsActiveWalk C (p.drop j) := by obtain ⟨hadj, hcoll⟩ := hact have hlen : (p.drop j).length = p.length - j := List.length_drop .. refine ⟨fun i hi => ?_, fun i hi => ?_⟩ · have hi' : j + i + 1 < p.length := by rw [hlen] at hi; omega have e0 : (p.drop j).get ⟨i, by omega⟩ = p.get ⟨j + i, by omega⟩ := by simp [List.getElem_drop] have e1 : (p.drop j).get ⟨i + 1, hi⟩ = p.get ⟨j + (i + 1), by omega⟩ := by simp [List.getElem_drop] rw [e0, e1] have := hadj (j + i) (by omega) exact this · have hi' : j + i + 2 < p.length := by rw [hlen] at hi; omega have e0 : (p.drop j).get ⟨i, by omega⟩ = p.get ⟨j + i, by omega⟩ := by simp [List.getElem_drop] have e1 : (p.drop j).get ⟨i + 1, by omega⟩ = p.get ⟨j + (i + 1), by omega⟩ := by simp [List.getElem_drop] have e2 : (p.drop j).get ⟨i + 2, hi⟩ = p.get ⟨j + (i + 2), by omega⟩ := by simp [List.getElem_drop] rw [e0, e1, e2] have := hcoll (j + i) (by omega) exact this
DoCalculus 2 core · 0 supporting This file states Rule 1 and restricted sufficient forms of Rule 2 and Rule 3* for structural causal models in a single-intervention form. ★ do_rule1★ do_rule3_star
Do-Calculus for Structural Causal Models
This file states Rule 1 and restricted sufficient forms of Rule 2 and Rule 3* for structural causal models in a single-intervention form. The Rule 2 result also assumes non-descendancy and product absolute continuity; the Rule 3* result uses the stronger non-ancestor premise on the whole outcome/conditioning block. These are sound interfaces used by the identification layer, not the full Pearl rules at their stated graphical generality.
Rule 1: Insertion/deletion of observations (single-SCM form). On any structural causal model M', suppose Y, Z, and W are all observed nodes of M', and that Y is d-separated from Z given W together with the fixed nodes M'.fixed, in the split graph M'.dag. Then, at any fixed-value point s, Y and Z are conditionally independent given W under the observational kernel M'.obsKernel s.
Formal statement
Proof (Lean source)
**Rule 3*: insertion/deletion of actions (simplified joint-marginal form).** Fix a structural causal model M' and a treatment set Z for which each member's random copy is already observed in M' and each member's fixed copy is not yet among M''s fixed nodes, together with outcome and conditioning sets Y and W, both observed in M'. Suppose no node of Y ∪ W is, in the model intervened on Z, a descendant of the fixed copy of any variable in Z. For any post-intervention fixed value, the joint law of (Y, W) under the intervened model equals the joint law of (Y, W) under the base model M' at the corresponding pre-intervention fixed value.
Formal statement
Proof (Lean source)
GlobalMarkov 3 core · 5 supporting This file proves the full global Markov property: d-separation in the causal graph implies conditional independence under the joint distribution over observed and latent variables. ★ full_globalMarkov_with_fixed★ full_globalMarkov
Full Global Markov Property
This file proves the full global Markov property: d-separation in the causal graph implies conditional independence under the joint distribution over observed and latent variables. The result is the full-distribution input from which the observational Markov property is obtained by projection.
The main exported theorem is SCM.full_globalMarkov, with
SCM.full_globalMarkov_with_fixed providing the form used by do-calculus proofs
where fixed intervention nodes appear in the graphical conditioning set but only
random coordinates remain in the probabilistic conditioning set. The file also
exposes Causalean.Mathlib.MeasureTheory.reindexSubtypeProj and
SCM.indepFun_valuesProjection_latentProduct, the product-measure independence
tools used internally by the Markov proof.
For a finite collection of nodes, a structural causal model, and a finite set of nodes in its single-world intervention graph, the latent ancestors of that set are exactly the unobserved nodes that either belong to the set or are ancestors of at least one node in the set.
Definition (Lean source)
Full Global Markov with fixed-node conditioning shadow. If X, Y, and Z_rand are sets of nodes drawn from the model's random (observed and latent) nodes and Z_fix is a set of the model's fixed (intervened) nodes, and X is d-separated from Y by the union Z_rand ∪ Z_fix in the model's causal graph, then under the joint distribution over all random coordinates at fixed value s, the X-coordinates and the Y-coordinates are conditionally independent given only the Z_rand-coordinates — the fixed nodes contribute to the graphical separation but, since their values are already pinned by s, drop out of the probabilistic conditioning set.
Formal statement
Proof (Lean source)
Full Global Markov Property. If X, Y, and Z are sets of nodes drawn from the model's random (observed and latent) nodes and X is d-separated from Y by Z in the model's causal graph, then under the joint distribution over all random coordinates at fixed value s, the X-coordinates and the Y-coordinates are conditionally independent given the Z-coordinates.
Formal statement
Proof (Lean source)
5 supporting declarations (lemmas, instances)
-
indepFun_valuesProjection_latentProducttheorem — Under M.latentProduct = ⊗_{u ∈ 𝐋} ℙ(L_u), the coordinate-tuple projections at two disjoint latent blocks A, B ⊆ M.unobserved are independent. The latent product is a Measure.pi over the subtype of unobserved nodes, so this is indepFun_pi_of_disjoint transported along the reindexSubtypeProj relabelling.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩhA :A ⊆ M.unobservedhB :B ⊆ M.unobservedhAB :Disjoint A BconclusionProof (Lean source)
theorem indepFun_valuesProjection_latentProduct (M : SCM N Ω) {A B : Finset (SWIGNode N)} (hA : A ⊆ M.unobserved) (hB : B ⊆ M.unobserved) (hAB : Disjoint A B) : IndepFun (valuesProjection (Ω := swigΩ Ω) hA) (valuesProjection (Ω := swigΩ Ω) hB) M.latentProduct := by classical letI := M.isProbability_latent set A' : Finset {i // i ∈ M.unobserved} := A.subtype (· ∈ M.unobserved) with hA'def set B' : Finset {i // i ∈ M.unobserved} := B.subtype (· ∈ M.unobserved) with hB'def have hA'B' : Disjoint A' B' := by rw [Finset.disjoint_left]; intro i hiA hiB rw [hA'def, Finset.mem_subtype] at hiA rw [hB'def, Finset.mem_subtype] at hiB exact (Finset.disjoint_left.mp hAB hiA) hiB letI f_unobs : Fintype {i // i ∈ M.unobserved} := Fintype.ofFinite _ have hbase_pi : IndepFun (finsetCoordProj (Ω := fun i : {i // i ∈ M.unobserved} => swigΩ Ω i.val) A') (finsetCoordProj (Ω := fun i : {i // i ∈ M.unobserved} => swigΩ Ω i.val) B') (pi (fun u => M.latentDist u)) := indepFun_pi_of_disjoint (fun u => M.latentDist u) hA'B' have h_fintype : f_unobs = fintype M.unobserved := Subsingleton.elim _ _ have hbase : IndepFun (finsetCoordProj (Ω := fun i : {i // i ∈ M.unobserved} => swigΩ Ω i.val) A') (finsetCoordProj (Ω := fun i : {i // i ∈ M.unobserved} => swigΩ Ω i.val) B') M.latentProduct := by rw [h_fintype] at hbase_pi simpa only [latentProduct] using hbase_pi exact hbase.comp (reindexSubtypeProj (Ω' := swigΩ Ω) A hA).measurable (reindexSubtypeProj (Ω' := swigΩ Ω) B hB).measurable -
fullCondIndep_ordered_localtheorem — For a random node, any set of random non-descendants that contains its random parents is conditionally independent of the remaining nodes in that set given those parents, under the model's joint kernel.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValuesStandardBorelSpace M.LatentValues∀ s : M.FixedValues, IsFiniteMeasure (M.jointKernel s)∀ (v : SWIGNode N),s :M.FixedValuesv :SWIGNode Nhv :v ∈ M.randomVarshP :P ⊆ M.randomVarshP_nonDesc :P ⊆ M.dag.nonDescendants v_hpa_sub :(M.dag.parents v ∩ M.randomVars) ⊆ PconclusionFullCondIndep M {v} (P \ (M.dag.parents v ∩ M.randomVars)) (M.dag.parents v ∩ M.randomVars) (Finset.singleton_subset_iff.mpr hv) (trans (sdiff_subset) hP) (inter_subset_right) (M.jointKernel s)Proof (Lean source)
theorem fullCondIndep_ordered_local (M : SCM N Ω) [StandardBorelSpace M.RandomValues] [StandardBorelSpace M.LatentValues] [∀ s : M.FixedValues, IsFiniteMeasure (M.jointKernel s)] [∀ (v : SWIGNode N), StandardBorelSpace (ValuesOn ({v} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (v : SWIGNode N), Nonempty (ValuesOn ({v} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (v : SWIGNode N), StandardBorelSpace (ValuesOn (M.dag.nonDescendants v ∩ M.randomVars) (swigΩ Ω))] [∀ (v : SWIGNode N), Nonempty (ValuesOn (M.dag.nonDescendants v ∩ M.randomVars) (swigΩ Ω))] (s : M.FixedValues) (v : SWIGNode N) (hv : v ∈ M.randomVars) (P : Finset (SWIGNode N)) (hP : P ⊆ M.randomVars) (hP_nonDesc : P ⊆ M.dag.nonDescendants v) (_hpa_sub : (M.dag.parents v ∩ M.randomVars) ⊆ P) : FullCondIndep M {v} (P \ (M.dag.parents v ∩ M.randomVars)) (M.dag.parents v ∩ M.randomVars) (Finset.singleton_subset_iff.mpr hv) (trans (sdiff_subset) hP) (inter_subset_right) (M.jointKernel s) := by classical -- `P \ pa ⊆ nonDescendants v ∩ randomVars`: from `hP_nonDesc` (left) and `hP` (right). have hsub_right : (P \ (M.dag.parents v ∩ M.randomVars)) ⊆ M.dag.nonDescendants v ∩ M.randomVars := by intro u hu rcases Finset.mem_sdiff.mp hu with ⟨huP, _⟩ exact Finset.mem_inter.mpr ⟨hP_nonDesc huP, hP huP⟩ rcases Finset.mem_union.mp hv with hobs | hunobs · -- Observed case: direct from `full_local_markov` + `fullCondIndep_subset_right`. have hLM := full_local_markov M v hobs s exact fullCondIndep_subset_right M (Finset.singleton_subset_iff.mpr hv) inter_subset_right (trans (sdiff_subset) hP) inter_subset_right hsub_right hLM · -- Latent case: `a` is a root, so `parents v ∩ randomVars = ∅`. have hpar_empty : M.dag.parents v = ∅ := M.unobs_are_roots v hunobs have hpa_inter_empty : M.dag.parents v ∩ M.randomVars = ∅ := by rw [hpar_empty]; exact Finset.empty_inter _ -- `full_local_markov_latent` gives `{v} ⊥ (nonDescendants v ∩ randomVars) | ∅`. have hLM := full_local_markov_latent M v hunobs s -- Shrink the right set to `P \ pa ⊆ nonDescendants v ∩ randomVars`. have hLM' := fullCondIndep_subset_right M (Finset.singleton_subset_iff.mpr hv) inter_subset_right (trans (sdiff_subset) hP) (empty_subset _) hsub_right hLM -- Align the conditioning set `∅` with `parents v ∩ randomVars` (both `∅`). exact fullCondIndep_congr_right M hpa_inter_empty.symm hLM' -
fullCondIndep_of_orderedLocalSGtheorem — A conditional-independence conclusion derived from the graph's ordered local Markov statements and semi-graphoid rules also holds in the structural causal model's full joint distribution.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValuesStandardBorelSpace M.LatentValues∀ (v : SWIGNode N),s :M.FixedValuesh :M.dag.OrderedLocalSG M.randomVars X Y ZhX :X ⊆ M.randomVarshY :Y ⊆ M.randomVarshZ :Z ⊆ M.randomVarsconclusionFullCondIndep M X Y Z hX hY hZ (M.jointKernel s)Proof (Lean source)
theorem fullCondIndep_of_orderedLocalSG (M : SCM N Ω) [StandardBorelSpace M.RandomValues] [StandardBorelSpace M.LatentValues] [∀ (v : SWIGNode N), StandardBorelSpace (ValuesOn ({v} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (v : SWIGNode N), Nonempty (ValuesOn ({v} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (v : SWIGNode N), StandardBorelSpace (ValuesOn (M.dag.nonDescendants v ∩ M.randomVars) (swigΩ Ω))] [∀ (v : SWIGNode N), Nonempty (ValuesOn (M.dag.nonDescendants v ∩ M.randomVars) (swigΩ Ω))] (s : M.FixedValues) {X Y Z : Finset (SWIGNode N)} (h : M.dag.OrderedLocalSG M.randomVars X Y Z) : ∀ (hX : X ⊆ M.randomVars) (hY : Y ⊆ M.randomVars) (hZ : Z ⊆ M.randomVars), FullCondIndep M X Y Z hX hY hZ (M.jointKernel s) := by induction h with | nil Y Z hY' hZ' => intro hX hY hZ; exact fullCondIndep_const_left M hY hZ | basis v hv P hP hND hPa => intro hX hY hZ; exact fullCondIndep_ordered_local M s v hv P hP hND hPa | symm h' ih => intro hX hY hZ obtain ⟨hX0, hY0, hZ0⟩ := h'.subset_random exact fullCondIndep_symm M hX0 hY0 hZ0 (ih hX0 hY0 hZ0) | decomp h' ih => intro hX hY hZ obtain ⟨hX0, hYW0, hZ0⟩ := h'.subset_random exact fullCondIndep_decomposition M hX0 hYW0 hZ (ih hX0 hYW0 hZ0) | weakUnion h' ih => intro hX hY hZ obtain ⟨hX0, hYW0, hZ0⟩ := h'.subset_random exact fullCondIndep_weak_union M hX0 hYW0 hZ (ih hX0 hYW0 hZ0) | contract h1 h2 ih1 ih2 => intro hX hY hZ obtain ⟨hX1, hY1, hZW1⟩ := h1.subset_random obtain ⟨_, hW2, hZ2⟩ := h2.subset_random exact fullCondIndep_contraction M hX1 hY1 hW2 hZ2 (ih1 hX1 hY1 hZW1) (ih2 hX1 hW2 hZ2) -
fullCondIndep_singleton_of_dSep_with_fixedtheorem — D-separation of one random node from a target set implies conditional independence after conditioning on the random nodes, even when the graph's conditioning set also contains fixed intervention nodes. The fixed nodes affect the graphical separation but do not appear among the random values being conditioned on.hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValues∀ n, StandardBorelSpace (swigΩ Ω n)∀ n, Nonempty (swigΩ Ω n)a :SWIGNode Nha :a ∈ M.randomVarshY :Y ⊆ M.randomVarshW_rand :W_rand ⊆ M.randomVarshW_fix :W_fix ⊆ M.fixedhdSep :M.dag.dSep {a} Y (W_rand ∪ W_fix)s :M.FixedValuesconclusionFullCondIndep M {a} Y W_rand (Finset.singleton_subset_iff.mpr ha) hY hW_rand (M.jointKernel s)Proof (Lean source)
theorem fullCondIndep_singleton_of_dSep_with_fixed (M : SCM N Ω) [StandardBorelSpace M.RandomValues] [∀ n, StandardBorelSpace (swigΩ Ω n)] [∀ n, Nonempty (swigΩ Ω n)] (a : SWIGNode N) (Y W_rand W_fix : Finset (SWIGNode N)) (ha : a ∈ M.randomVars) (hY : Y ⊆ M.randomVars) (hW_rand : W_rand ⊆ M.randomVars) (hW_fix : W_fix ⊆ M.fixed) (hdSep : M.dag.dSep {a} Y (W_rand ∪ W_fix)) (s : M.FixedValues) : FullCondIndep M {a} Y W_rand (Finset.singleton_subset_iff.mpr ha) hY hW_rand (M.jointKernel s) := by have hFR : Disjoint M.fixed M.randomVars := by rw [Finset.disjoint_left] intro x hxF hxR obtain ⟨k, rfl⟩ := M.fixed_is_fixed x hxF rcases Finset.mem_union.mp hxR with h | h · obtain ⟨m, hm⟩ := M.observed_is_random _ h; exact absurd hm (by simp) · obtain ⟨m, hm⟩ := M.unobserved_is_random _ h; exact absurd hm (by simp) have hDeriv : M.dag.OrderedLocalSG M.randomVars {a} Y W_rand := M.dag.orderedLocalSG_of_dSep_with_fixed M.randomVars {a} Y W_rand W_fix (fun f hf => M.fixed_are_roots f (hW_fix hf)) (hFR.mono_left hW_fix) (Finset.singleton_subset_iff.mpr ha) hY hW_rand hdSep exact fullCondIndep_of_orderedLocalSG M s hDeriv (Finset.singleton_subset_iff.mpr ha) hY hW_rand
MarkovEquivDistributional 4 core · 1 supporting The graph-level MarkovEquiv (same d-separations) is connected here to *distributions*. ★ IsGlobalIMap★ DistMarkovEquiv★ isGlobalIMap_dag_self
Markov equivalence — the distributional I-map layer
The graph-level MarkovEquiv (same d-separations) is connected here to distributions.
A distribution μ is a global I-map of a DAG G when every d-separation of G is a
conditional independence of μ; it is faithful to G when, conversely, every such
conditional independence reflects an actual d-separation. The global Markov property
(full_globalMarkov) says every structural causal model is a global I-map of its own DAG —
this is the bridge from graphs to distributions, restated here as isGlobalIMap_dag_self.
The theorem in this file proves the easy direction:
* distMarkovEquiv_of_markovEquiv: graph-level Markov equivalence implies
distributional Markov equivalence (the two DAGs are I-maps of exactly the same
distributions). This is immediate from the definitions: the I-map condition is the same
predicate when the d-separations agree.
The d-separation triples handled here are pairwise disjoint, matching the global Markov property; this is the standard setting for the I-map and faithfulness notions. The file states the I-map direction needed by the public Markov-equivalence API and leaves faithfulness-existence results outside this layer.
For a directed acyclic graph on the split nodes, a structural causal model, and a finite measure on that model's random-value space, the global I-map property means that, for every three finite sets of random nodes contained respectively in the model's random variables, d-separation of the first and second sets given the third in the graph implies their conditional independence under the measure.
Definition (Lean source)
For a directed acyclic graph on the split nodes, a structural causal model, and a finite measure on that model's random-value space, the faithfulness property means that, for every three pairwise-disjoint finite sets of random nodes contained respectively in the model's random variables, their conditional independence under the measure implies that the graph d-separates the first and second sets given the third.
Definition (Lean source)
For a family of value spaces indexed by the base variables and two directed acyclic graphs on the same split-node set, distributional Markov equivalence means that, for every structural causal model with those value spaces and every finite measure on its random-value space, the measure is a global I-map of the first graph if and only if it is a global I-map of the second.
Definition (Lean source)
The bridge, restated. For any structural causal model M and any point s of its fixed values, the joint distribution of M's random values under s is a global I-map of M's own DAG — this is exactly the global Markov property full_globalMarkov.
Formal statement
Proof (Lean source)
1 supporting declaration (lemmas, instances)
-
distMarkovEquiv_of_markovEquivtheorem — Easy half. For two DAGs G₁, G₂ on the same node set, if they are Markov equivalent — they declare exactly the same d-separations, then they are distributionally Markov equivalent: a distribution is a global I-map of one exactly when it is a global I-map of the other.Proof (Lean source)
theorem distMarkovEquiv_of_markovEquiv {G₁ G₂ : DAG (SWIGNode N)} (h : MarkovEquiv G₁ G₂) : DistMarkovEquiv Ω G₁ G₂ := by intro M _ μ _ constructor · intro himap X Y Z hX hY hZ hdsep exact himap X Y Z hX hY hZ ((h X Y Z).mpr hdsep) · intro himap X Y Z hX hY hZ hdsep exact himap X Y Z hX hY hZ ((h X Y Z).mp hdsep)
ObsMarkov 2 core · 1 supporting This file transfers conditional independence from the full distribution over random and latent coordinates to the observational distribution over observed coordinates. ★ globalMarkov★ globalMarkov_with_fixed
Observational Markov Property
This file transfers conditional independence from the full distribution over random and latent coordinates to the observational distribution over observed coordinates. It then packages graphical separation hypotheses as observational conditional independences for use in do-calculus arguments.
Global Markov Property. If X, Y, and Z are sets of observed nodes and X is d-separated from Y by Z in the model's full causal graph, which also includes any latent nodes, then under the observational distribution — the law of the observed coordinates alone, at fixed value s — the X-coordinates and Y-coordinates are conditionally independent given the Z-coordinates.
Formal statement
Proof (Lean source)
Global Markov with fixed-node conditioning. If X, Y, and Z_obs are sets of observed nodes and Z_fix is a set of the model's fixed (intervened) nodes, and X is d-separated from Y by the union Z_obs ∪ Z_fix in the model's full causal graph, then under the observational distribution at fixed value s, the X-coordinates and Y-coordinates are conditionally independent given only the Z_obs-coordinates — the fixed nodes contribute to the graphical separation but, since their values are already pinned by s, drop out of the probabilistic conditioning set.
Formal statement
Proof (Lean source)
1 supporting declaration (lemmas, instances)
-
obs_condIndep_of_fulltheorem — Projection lemma. For X, Y, Z ⊆ V (all observed), conditional independence at the full distribution level (jointKernel) implies conditional independence at the observational level (obsKernel).hypothesesN :sharedType uNN → Type uΩM :SCM N ΩStandardBorelSpace M.RandomValuesStandardBorelSpace M.ObservedValuesX Y Z :hX :X ⊆ M.observedhY :Y ⊆ M.observedhZ :Z ⊆ M.observeds :M.FixedValueshfull :FullCondIndep M X Y Z (hX.trans (observed_subset_randomVars M)) (hY.trans (observed_subset_randomVars M)) (hZ.trans (observed_subset_randomVars M)) (M.jointKernel s)conclusionObsCondIndep M X Y Z hX hY hZ (M.obsKernel s)Proof (Lean source)
theorem obs_condIndep_of_full (M : SCM N Ω) [StandardBorelSpace M.RandomValues] [StandardBorelSpace M.ObservedValues] {X Y Z : Finset (SWIGNode N)} [StandardBorelSpace (ValuesOn X (swigΩ Ω))] [Nonempty (ValuesOn X (swigΩ Ω))] [StandardBorelSpace (ValuesOn Y (swigΩ Ω))] [Nonempty (ValuesOn Y (swigΩ Ω))] (hX : X ⊆ M.observed) (hY : Y ⊆ M.observed) (hZ : Z ⊆ M.observed) (s : M.FixedValues) (hfull : FullCondIndep M X Y Z (hX.trans (observed_subset_randomVars M)) (hY.trans (observed_subset_randomVars M)) (hZ.trans (observed_subset_randomVars M)) (M.jointKernel s)) : ObsCondIndep M X Y Z hX hY hZ (M.obsKernel s) := by -- `obsKernel s = (jointKernel s).map randomToObserved` (kernel-level pushforward). have hobs_eq : M.obsKernel s = (M.jointKernel s).map M.randomToObserved := ProbabilityTheory.Kernel.map_apply _ M.measurable_randomToObserved s -- `IsFiniteMeasure` propagates across the equation; needed since `CondIndepFun` -- carries `[IsFiniteMeasure μ]` as an instance argument. haveI : IsFiniteMeasure ((M.jointKernel s).map M.randomToObserved) := hobs_eq ▸ (inferInstance : IsFiniteMeasure (M.obsKernel s)) -- Apply the pushforward bridge to build CondIndepFun on -- `(M.jointKernel s).map M.randomToObserved`. unfold FullCondIndep at hfull have hresult : CondIndepFun (comap (valuesProjection hZ) inferInstance) (comap_valuesProjection_le hZ) (valuesProjection hX) (valuesProjection hY) ((M.jointKernel s).map M.randomToObserved) := condIndepFun_of_map (φ := M.randomToObserved) M.measurable_randomToObserved (measurable_valuesProjection hX) (measurable_valuesProjection hY) (measurable_valuesProjection hZ) hfull -- Transport hresult to the `obsKernel s` form. Since `CondIndepFun` has -- `[IsFiniteMeasure μ]` as an instance argument, direct `rw`/`▸` fails the motive -- check; `convert` handles the measure slot via its built-in congruence machinery. unfold ObsCondIndep convert hresult using 2
Overlap 1 core · 0 supporting This file defines a kernel-level support condition used by identification rules. ★ Rule2JointOverlap
Overlap
This file defines a kernel-level support condition used by identification
rules. The predicate Rule2JointOverlap requires the
post-intervention marginal on Z.random ∪ W to be absolutely continuous with
respect to the corresponding observational marginal. This continuous-friendly
condition is an explicit assumption of backdoor/frontdoor interfaces; it is not
implied merely by discreteness, measurability of structural functions, or an
unchanged latent law.
For a finite node-label set, measurable node-value spaces, a structural causal model, an intervention target set, proof that each target is an observed random node not already fixed, an additional observed-node set, proof that the random copies of the targets together with that set are observed, and a fixed-value assignment after intervention, Rule 2 joint overlap means that the post-intervention observational marginal on those nodes is absolutely continuous with respect to the corresponding pre-intervention observational marginal at the projected fixed-value assignment.
Definition (Lean source)
Rule2AE 1 core · 1 supporting The retired pointwise Rule 2 form quantified a.e. ★ do_rule2_kernel_of_nondescendant_product_ae
Rule 2, a.e. in the treatment value (product form + positivity)
The retired pointwise Rule 2 form quantified a.e. in the conditioning value
w but pointwise in the treatment value (the Z.random do-value spliced via
fillZrW). For non-atomic treatment that point lies on a μ_C-null slice where
Mathlib's obsCondKernel representative is unpinned, so the pointwise form is
too strong.
The honest generalization quantifies a.e. over the product νZ ⊗ₘ μW of the observational
treatment marginal νZ := (M'.obsKernel s0).map π_{Zr} and conditioning marginal
μW := (M'.obsKernel s0).map π_W, under a positivity hypothesis (νZ ⊗ₘ μW) ∘ fill⁻¹ ≪ μ_C.
Both regimes are covered: atomic νZ makes "a.e." pointwise on the support.
Why the product (not the joint μ_C): the do-side (M'.fixSet Z).obsCondKernel Y W is pinned only
under the do-model W-marginal (= μW via Rule 3*), i.e. under the product; the obs-side
M'.obsCondKernel is pinned under μ_C. Positivity (product ≪ μ_C) lifts the
obs-side onto the product, where the do-side is natively pinned. The proof lifts
the discrete d-sep collapse and cross-SCM
bridge (obsCondKernel_dSep_collapse_ae, obsCondKernel_cross_SCM_ae_eq_on_fillZrW,
obsKernel_fixSet_W_marginal_eq_M1_marginal) from the per-treatment slice to
the product via Fubini over the treatment + the product↔joint AC transfer.
Rule 2, a.e. in the treatment value (product form + positivity). Consider intervening on the finite set of names Z, where each name's random copy is already observed in the base model and its fixed copy is not yet part of the base model's fixed coordinates, with outcome set Y and conditioning set W contained in the observed variables, together with the random copies of Z and their union with W. Assume in the post-intervention SWIG DAG, Y is d-separated from the random copies of Z given W together with the post-intervention fixed set, no fixed copy of a name in Z is an ancestor of any node of W in the post-intervention DAG, no random copy of a name in Z is an ancestor of any node of W in the original DAG, and positivity: the pushforward of the product of the treatment and conditioning marginals under the fill map is absolutely continuous with respect to the base model's law on Z.random ∪ W. Then for almost every pair (t, w) under that product measure, the W-conditional kernel of the model intervened at treatment value t, evaluated together with w, restricted to Y, equals the base model's conditional distribution of Y given Z.random ∪ W evaluated at the combined point (t, w).
Formal statement
Proof (Lean source)
1 supporting declaration (lemmas, instances)
-
condDistrib_fixSet_cross_SCM_bridgetheorem — Joint-μ_C-a.e. cross-SCM condDistrib bridge (isolated hard lemma).hypothesesN :sharedType u_1N → Type u_2M' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhY :Y ⊆ M'.observedhW :W ⊆ M'.observedhZr :Z.image SWIGNode.random ⊆ M'.observedhZrW :Z.image SWIGNode.random ∪ W ⊆ M'.observedhdSep :(M'.fixSet Z hZ_obs hZ_fixed).dag.dSep Y (Z.image SWIGNode.random) (W ∪ (M'.fixSet Z hZ_obs hZ_fixed).fixed)hWNonDesc :∀ z ∈ Z, ∀ v ∈ W, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed z) vhWNonDescM1 :∀ D ∈ Z, ∀ w ∈ W, ¬ M'.dag.isAncestor (SWIGNode.random D) w∀ n, StandardBorelSpace (swigΩ Ω n)∀ n, Nonempty (swigΩ Ω n)CountableOrCountablyGenerated (M'.fixSet Z hZ_obs hZ_fixed).FixedValues (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))s0 :M'.FixedValueshPositivity_ae :(((M'.obsKernel s0).map (valuesProjection hZr) ⊗ₘ const _ ((M'.obsKernel s0).map (valuesProjection hW))).map (fun p => valuesUnionMk p.1 p.2)) ≪ ((M'.obsKernel s0).map (valuesProjection hZrW))conclusion∀ᵐ p ∂((M'.obsKernel s0).map (valuesProjection hZr) ⊗ₘ const _ ((M'.obsKernel s0).map (valuesProjection hW))), (M'.fixSet Z hZ_obs hZ_fixed).obsCondKernel Y W ((SCM.fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ((SCM.fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW) (M'.fixSetExtend Z hZ_obs hZ_fixed s0 p.1, p.2)= condDistrib (valuesProjection hY) (valuesProjection hZrW) (M'.obsKernel s0) (valuesUnionMk p.1 p.2)Proof (Lean source)
theorem condDistrib_fixSet_cross_SCM_bridge (M' : SCM N Ω) (Z : Finset N) (hZ_obs : ∀ D ∈ Z, SWIGNode.random D ∈ M'.observed) (hZ_fixed : ∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixed) (Y W : Finset (SWIGNode N)) (hY : Y ⊆ M'.observed) (hW : W ⊆ M'.observed) (hZr : Z.image SWIGNode.random ⊆ M'.observed) (hZrW : Z.image SWIGNode.random ∪ W ⊆ M'.observed) (hdSep : (M'.fixSet Z hZ_obs hZ_fixed).dag.dSep Y (Z.image SWIGNode.random) (W ∪ (M'.fixSet Z hZ_obs hZ_fixed).fixed)) (hWNonDesc : ∀ z ∈ Z, ∀ v ∈ W, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed z) v) (hWNonDescM1 : ∀ D ∈ Z, ∀ w ∈ W, ¬ M'.dag.isAncestor (SWIGNode.random D) w) [∀ n, StandardBorelSpace (swigΩ Ω n)] [∀ n, Nonempty (swigΩ Ω n)] [CountableOrCountablyGenerated M'.FixedValues (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))] [CountableOrCountablyGenerated (M'.fixSet Z hZ_obs hZ_fixed).FixedValues (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))] [CountableOrCountablyGenerated (M'.fixSet Z hZ_obs hZ_fixed).FixedValues (ValuesOn W (swigΩ Ω))] [MeasurableSingletonClass (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))] (s0 : M'.FixedValues) (hPositivity_ae : (((M'.obsKernel s0).map (valuesProjection hZr) ⊗ₘ ProbabilityTheory.Kernel.const _ ((M'.obsKernel s0).map (valuesProjection hW))).map (fun p => valuesUnionMk p.1 p.2)) ≪ ((M'.obsKernel s0).map (valuesProjection hZrW))) : ∀ᵐ p ∂((M'.obsKernel s0).map (valuesProjection hZr) ⊗ₘ ProbabilityTheory.Kernel.const _ ((M'.obsKernel s0).map (valuesProjection hW))), (M'.fixSet Z hZ_obs hZ_fixed).obsCondKernel Y W ((SCM.fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ((SCM.fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW) (M'.fixSetExtend Z hZ_obs hZ_fixed s0 p.1, p.2) = condDistrib (valuesProjection hY) (valuesProjection hZrW) (M'.obsKernel s0) (valuesUnionMk p.1 p.2) := by classical have hDisj_YZr : Disjoint Y (Z.image SWIGNode.random) := hdSep.1 have hDisj_ZrW : Disjoint (Z.image SWIGNode.random) W := Disjoint.mono_right subset_union_left hdSep.2.2.1 -- The product measure `λ = νZ ⊗ₘ const μW` and the fill map `G = valuesUnionMk`. set νZ := (M'.obsKernel s0).map (valuesProjection hZr) with hνZ set μW := (M'.obsKernel s0).map (valuesProjection hW) with hμW set lam := νZ ⊗ₘ ProbabilityTheory.Kernel.const _ μW with hlam set G : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω) → ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω) := fun p => valuesUnionMk p.1 p.2 with hG have hG_meas : Measurable G := measurable_valuesUnionMk -- (II) obs-side bridge: `M1.obsCondKernel Y (Zr∪W) (s0, G p) = condDistrib … (G p)`, λ-a.e. -- (the proven obs-side AC transport, mirrored from `do_rule2_kernel_of_nondescendant_product_ae`). have h_obs_cd := obsCondKernel_ae_eq_condDistrib M' Y (Z.image SWIGNode.random ∪ W) hY hZrW s0 have h_obs_ae_mapG : (fun c => M'.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY hZrW (s0, c)) =ᵐ[lam.map G] condDistrib (valuesProjection hY) (valuesProjection hZrW) (M'.obsKernel s0) := MeasureTheory.Measure.AbsolutelyContinuous.ae_eq hPositivity_ae h_obs_cd have h_obs_prod : ∀ᵐ p ∂lam, M'.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY hZrW (s0, G p) = condDistrib (valuesProjection hY) (valuesProjection hZrW) (M'.obsKernel s0) (G p) := MeasureTheory.ae_of_ae_map hG_meas.aemeasurable h_obs_ae_mapG -- (I) do-side reduction: `M2.obsCondKernel Y W (fixSetExtend s0 t, w) -- = M1.obsCondKernel Y (Zr∪W) (s0, G (t,w))`, λ-a.e. -- This is the posterior witness-kernel cross-SCM bridge -- `obsCondKernel_fixSet_M1_eq_ae_product`: -- both sides equal the posterior witness kernel -- `(condDistrib C_W (π_W∘E) latentProduct).map (h t w)` (`obsSide_eq_witness` + its -- do-side M2 mirror), lifted to the product via Rule 3* (`ν_W = μW`) + positivity. have h_doSide : ∀ᵐ p ∂lam, (M'.fixSet Z hZ_obs hZ_fixed).obsCondKernel Y W ((SCM.fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ((SCM.fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW) (M'.fixSetExtend Z hZ_obs hZ_fixed s0 p.1, p.2) = M'.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY hZrW (s0, G p) := SCM.obsCondKernel_fixSet_M1_eq_ae_product M' Z hZ_obs hZ_fixed Y W hY hW hZr hZrW hDisj_ZrW hDisj_YZr hWNonDesc hWNonDescM1 hdSep s0 hPositivity_ae -- Chain (I) then (II). filter_upwards [h_doSide, h_obs_prod] with p hI hII rw [hI, hII]
Rule3 1 core · 4 supporting This file proves the kernel-level non-ancestor marginal transport used by the restricted Rule 3* interface for structural causal models. ★ condDistrib_intervention_ancestral_eq
Rule 3* Non-Ancestor Kernel Identity
This file proves the kernel-level non-ancestor marginal transport used by the
restricted Rule 3* interface for structural causal models. The transport theorem
fixSet_latentProduct_compat identifies
the latent-product measure before and after an additional intervention,
fixSet_evalMap_nonAnc_compat proves pointwise agreement of evaluation at nodes
with no fixed-intervention ancestors, and
condDistrib_intervention_ancestral_eq packages these facts as equality of
observed marginal kernels for targets not descended from the added intervention
nodes.
**Rule 3* core — intervention on non-ancestors of T is irrelevant.** This is the simplified joint non-ancestor transport used by the library's Rule 3* interface. Fix a do-set Z of nodes whose random copies are observed in the base model and whose fixed nodes have not already been intervened on and a target block T of observed variables. If none of the fixed copies of Z's nodes is an ancestor, in the intervention SWIG graph, of any node in T, then the T-marginal law of the intervened model equals the T-marginal law of the base model evaluated at the corresponding fixed values.
Formal statement
Proof (Lean source)
4 supporting declarations (lemmas, instances)
-
fixSet_latentProduct_compattheorem — **Cross-SCM latent-product transport for Rule 3*.**hypothesesN :sharedType u_1N → Type u_2M' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedconclusion((M'.fixSet Z hZ_obs hZ_fixed).latentProduct).map (valuesProjection (le_of_eq (fixSet_unobserved M' Z hZ_obs hZ_fixed).symm))= M'.latentProductProof (Lean source)
theorem fixSet_latentProduct_compat (M' : SCM N Ω) (Z : Finset N) (hZ_obs : ∀ D ∈ Z, SWIGNode.random D ∈ M'.observed) (hZ_fixed : ∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixed) : ((M'.fixSet Z hZ_obs hZ_fixed).latentProduct).map (valuesProjection (le_of_eq (fixSet_unobserved M' Z hZ_obs hZ_fixed).symm)) = M'.latentProduct := by set M2 := M'.fixSet Z hZ_obs hZ_fixed with hM2 have h_unobs : M2.unobserved = M'.unobserved := fixSet_unobserved M' Z hZ_obs hZ_fixed -- Under the monolithic `fixSet := fixMono`, `M2.unobserved = M'.unobserved` by -- `rfl` and `M2.latentDist = M'.latentDist` pointwise by `rfl`. So the -- `valuesProjection`-transport across the identity type-equality is the -- identity, and the measure identity reduces to `rfl` on `Measure.pi`. change (M2.latentProduct).map (valuesEquivOfEq (Ω := swigΩ Ω) h_unobs) = M'.latentProduct unfold latentProduct letI := M2.isProbability_latent letI := M'.isProbability_latent rw [(measurePreserving_valuesEquivOfEq (Ω := swigΩ Ω) h_unobs (fun u => M2.latentDist u)).map_eq] congr 1 -
hNoDesc_implies_no_fixed_parentlemma — If none of the fixed intervention nodes is an ancestor of a node, none is a parent of that node.hypotheseshNoDesc :∀ z ∈ Z, ¬ M2.dag.isAncestor (SWIGNode.fixed z) vz ∈ Z :conclusionSWIGNode.fixed z ∉ M2.dag.parents vProof (Lean source)
lemma hNoDesc_implies_no_fixed_parent {M2 : SCM N Ω} {Z : Finset N} {v : SWIGNode N} (hNoDesc : ∀ z ∈ Z, ¬ M2.dag.isAncestor (SWIGNode.fixed z) v) : ∀ z ∈ Z, SWIGNode.fixed z ∉ M2.dag.parents v := fun z hz hP => hNoDesc z hz (DAG.isAncestor.edge (M2.dag.mem_parents.mp hP)) -
hNoDesc_descend_to_parentlemma — If none of the fixed intervention nodes is an ancestor of a node, then none is an ancestor of any parent of that node.hypotheseshwP :w ∈ M2.dag.parents vhNoDesc :∀ z ∈ Z, ¬ M2.dag.isAncestor (SWIGNode.fixed z) vz ∈ Z :conclusion¬ M2.dag.isAncestor (SWIGNode.fixed z) wProof (Lean source)
lemma hNoDesc_descend_to_parent {M2 : SCM N Ω} {Z : Finset N} {v w : SWIGNode N} (hwP : w ∈ M2.dag.parents v) (hNoDesc : ∀ z ∈ Z, ¬ M2.dag.isAncestor (SWIGNode.fixed z) v) : ∀ z ∈ Z, ¬ M2.dag.isAncestor (SWIGNode.fixed z) w := fun z hz hanc => hNoDesc z hz (DAG.isAncestor.trans hanc (M2.dag.mem_parents.mp hwP)) -
fixSet_evalMap_nonAnc_compattheorem — **Cross-SCM evalMap bridge for Rule 3*.**hypothesesN :sharedType u_1N → Type u_2M' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixeds' :(M'.fixSet Z hZ_obs hZ_fixed).FixedValuesℓ :(M'.fixSet Z hZ_obs hZ_fixed).LatentValuesv :SWIGNode Nhv :v ∈ (M'.fixSet Z hZ_obs hZ_fixed).observedhNoDesc :∀ z ∈ Z, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed z) vconclusion(M'.fixSet Z hZ_obs hZ_fixed).evalMap s' ℓ ⟨v, mem_union_left _ hv⟩= M'.evalMap (M'.fixSetProj Z hZ_obs hZ_fixed s') (valuesProjection (le_of_eq (fixSet_unobserved M' Z hZ_obs hZ_fixed).symm) ℓ) ⟨v, mem_union_left _ (le_of_eq (fixSet_observed M' Z hZ_obs hZ_fixed) hv)⟩Proof (Lean source)
theorem fixSet_evalMap_nonAnc_compat (M' : SCM N Ω) (Z : Finset N) (hZ_obs : ∀ D ∈ Z, SWIGNode.random D ∈ M'.observed) (hZ_fixed : ∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixed) (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) (ℓ : (M'.fixSet Z hZ_obs hZ_fixed).LatentValues) {v : SWIGNode N} (hv : v ∈ (M'.fixSet Z hZ_obs hZ_fixed).observed) (hNoDesc : ∀ z ∈ Z, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed z) v) : (M'.fixSet Z hZ_obs hZ_fixed).evalMap s' ℓ ⟨v, mem_union_left _ hv⟩ = M'.evalMap (M'.fixSetProj Z hZ_obs hZ_fixed s') (valuesProjection (le_of_eq (fixSet_unobserved M' Z hZ_obs hZ_fixed).symm) ℓ) ⟨v, mem_union_left _ (le_of_eq (fixSet_observed M' Z hZ_obs hZ_fixed) hv)⟩ := by classical -- Abbreviations (via `let` to avoid `set`'s hypothesis-shadowing behaviour -- on dependent arguments). let M2 := M'.fixSet Z hZ_obs hZ_fixed have h_obs_eq : M2.observed = M'.observed := rfl have h_unobs : M2.unobserved = M'.unobserved := rfl let s_M1 : M'.FixedValues := M'.fixSetProj Z hZ_obs hZ_fixed s' let ℓ_M1 : M'.LatentValues := valuesProjection (le_of_eq h_unobs.symm) ℓ -- Strong recursion on `M2.observedIndex ⟨v, hv⟩`, with the no-ancestor -- hypothesis carried through the recursion. Under the monolithic -- `fixSet := fixMono`, `M2.observed = M'.observed` and `M2.unobserved = -- M'.unobserved` hold by `rfl`, so the coercions in the goal are identities. suffices h_obs : ∀ (n : ℕ) (w : SWIGNode N) (hw : w ∈ M2.observed) (_hNoD : ∀ z ∈ Z, ¬ M2.dag.isAncestor (SWIGNode.fixed z) w), (M2.observedIndex ⟨w, hw⟩).val = n → M2.evalMap s' ℓ ⟨w, mem_union_left _ hw⟩ = M'.evalMap s_M1 ℓ_M1 ⟨w, mem_union_left _ hw⟩ by exact h_obs _ v hv hNoDesc rfl intro n induction n using Nat.strongRecOn with | _ n ih => intro v hv hNoD hidx -- No `.fixed D` (D ∈ Z) is a parent of v in M2 (contrapositive of hNoD). have hNoFP : ∀ D ∈ Z, SWIGNode.fixed D ∉ M2.dag.parents v := fun D hD hP => hNoD D hD (DAG.isAncestor.edge (M2.dag.mem_parents.mp hP)) have h_parents_eq : M2.dag.parents v = M'.dag.parents v := fixSet_parents_eq_of_no_fixed_parent M' Z hZ_obs hZ_fixed hNoFP have hv_M1 : v ∈ M'.observed := hv -- Unfold both `evalMap`s via `evalMap_observed_unfold`. rw [SCM.evalMap_observed_unfold M2 s' ℓ ⟨v, hv⟩, SCM.evalMap_observed_unfold M' s_M1 ℓ_M1 ⟨v, hv_M1⟩] -- LHS's outer `M2.structFun ⟨v, hv⟩` is definitionally -- `M'.structFun ⟨v, hv_M1⟩` precomposed with `fixMonoParentMap`. -- After `congr 1`, the goal reduces to pointwise equality of the two -- parent tuples over `M'.dag.parents v`. change M'.structFun ⟨v, hv_M1⟩ (fixMonoParentMap M'.toSWIGGraph Z hZ_obs hZ_fixed v (fun w : {w // w ∈ (M'.splitMono Z hZ_obs hZ_fixed).dag.parents v} => if huo : w.val ∈ M2.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M2.fixed then s' ⟨w.val, hfix⟩ else have hedge : M2.dag.edge w.val v := M2.dag.mem_parents.mp w.property have hobs : w.val ∈ M2.observed := by rcases Finset.mem_union.mp (M2.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo M2.evalMap s' ℓ ⟨w.val, mem_union_left _ hobs⟩)) = M'.structFun ⟨v, hv_M1⟩ (fun w : {w // w ∈ M'.dag.parents v} => if huo : w.val ∈ M'.unobserved then ℓ_M1 ⟨w.val, huo⟩ else if hfix : w.val ∈ M'.fixed then s_M1 ⟨w.val, hfix⟩ else have hedge : M'.dag.edge w.val v := M'.dag.mem_parents.mp w.property have hobs : w.val ∈ M'.observed := by rcases Finset.mem_union.mp (M'.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo M'.evalMap s_M1 ℓ_M1 ⟨w.val, mem_union_left _ hobs⟩) congr 1 -- Pointwise equality of the two parent tuples. funext w -- Bridge: w : {w // w ∈ M'.dag.parents v}, and the LHS tuple is indexed -- by `M'.dag.parents v` too (output of `fixMonoParentMap`). On the LHS, -- unfold `fixMonoParentMap` according to w.val's constructor. have hNoRD : ∀ D ∈ Z, SWIGNode.random D ∉ M'.dag.parents v := by intro D hD hRD apply hNoFP D hD have hP_M2 := (SWIGGraph.splitMono_parents_char M'.toSWIGGraph Z hZ_obs hZ_fixed v (SWIGNode.fixed D)).2 (inr ⟨D, hD, rfl, hRD⟩) exact hP_M2 -- Per-parent three-way case split on `w.val`. rcases w with ⟨wVal, hwVal_M1⟩ -- wVal's position in the LHS (fixMonoParentMap) depends on its form. have hwVal_M2 : wVal ∈ M2.dag.parents v := h_parents_eq.symm ▸ hwVal_M1 -- Compute the LHS at wVal. cases wVal with | random u => have hu_notZ : u ∉ Z := by intro hu exact hNoRD u hu hwVal_M1 -- fixMonoParentMap at ⟨.random u, hwVal_M1⟩ with u ∉ Z: -- reads the ξ at ⟨.random u, (splitMono_parents_char …).2 (inl …)⟩. rw [fixMonoParentMap_apply_random_notMem M'.toSWIGGraph Z hZ_obs hZ_fixed v _ u hu_notZ hwVal_M1] -- Now both sides are `if-elif-else` on wVal = .random u. -- M2.unobserved = M'.unobserved (rfl), M2.fixed = M'.fixed ∪ Z.image .fixed. -- For .random u, it is never in Z.image .fixed, so being in M2.fixed iff M'.fixed. by_cases huo : (SWIGNode.random u : SWIGNode N) ∈ M'.unobserved · have huo_M2 : SWIGNode.random u ∈ M2.unobserved := huo simp only [dif_pos huo, dif_pos huo_M2] -- ℓ_M1 at ⟨.random u, huo⟩ = ℓ at ⟨.random u, huo_M2⟩ since -- ℓ_M1 := valuesProjection (le_of_eq rfl.symm) ℓ = (by rfl) ℓ. rfl · have huo_M2 : SWIGNode.random u ∉ M2.unobserved := huo simp only [dif_neg huo, dif_neg huo_M2] by_cases hfix : (SWIGNode.random u : SWIGNode N) ∈ M'.fixed · -- .random u ∈ M'.fixed — impossible since M'.fixed elements are .fixed nodes. exfalso rcases M'.fixed_is_fixed _ hfix with ⟨_, hfix_eq⟩ cases hfix_eq · have hfix_M2 : (SWIGNode.random u : SWIGNode N) ∉ M2.fixed := by intro h have : (SWIGNode.random u : SWIGNode N) ∈ M'.fixed ∪ Z.image SWIGNode.fixed := h rcases Finset.mem_union.mp this with h1 | h2 · exact hfix h1 · rcases Finset.mem_image.mp h2 with ⟨_, _, hEq⟩ cases hEq simp only [dif_neg hfix, dif_neg hfix_M2] -- Observed case: apply IH. -- Need to derive `M2.observedIndex ⟨.random u, hobs_M2⟩ < n`. have hobs_M1 : (SWIGNode.random u : SWIGNode N) ∈ M'.observed := by have hedge_M1 : M'.dag.edge (SWIGNode.random u) v := M'.dag.mem_parents.mp hwVal_M1 rcases Finset.mem_union.mp (M'.dag_edges_classified _ _ hedge_M1).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo have hobs_M2 : (SWIGNode.random u : SWIGNode N) ∈ M2.observed := hobs_M1 -- IH on w. have hNoD_w : ∀ z ∈ Z, ¬ M2.dag.isAncestor (SWIGNode.fixed z) (SWIGNode.random u) := by intro z hz hanc exact hNoD z hz (DAG.isAncestor.trans hanc (M2.dag.mem_parents.mp hwVal_M2)) have hidx_w : (M2.observedIndex ⟨SWIGNode.random u, hobs_M2⟩).val < (M2.observedIndex ⟨v, hv⟩).val := by have hedge_M2 : M2.dag.edge (SWIGNode.random u) v := M2.dag.mem_parents.mp hwVal_M2 have hv_eq : (M2.observedAt ⟨(M2.observedIndex ⟨v, hv⟩).val, (M2.observedIndex ⟨v, hv⟩).isLt⟩).val = v := by have := M2.observedAt_observedIndex ⟨v, hv⟩ convert this have hedge_M2' : M2.dag.edge (SWIGNode.random u) (M2.observedAt ⟨(M2.observedIndex ⟨v, hv⟩).val, (M2.observedIndex ⟨v, hv⟩).isLt⟩).val := by rw [hv_eq]; exact hedge_M2 exact M2.observed_parent_index_lt (M2.observedIndex ⟨v, hv⟩).isLt hedge_M2' hobs_M2 rw [hidx] at hidx_w exact ih _ hidx_w (SWIGNode.random u) hobs_M2 hNoD_w rfl | fixed d => -- fixMonoParentMap at ⟨.fixed d, hwVal_M1⟩: copies ξ at ⟨.fixed d, _⟩. rw [fixMonoParentMap_apply_fixed M'.toSWIGGraph Z hZ_obs hZ_fixed v _ d hwVal_M1] -- Both sides: .fixed d. Unobserved case: impossible (unobserved elts are .random). have huo : (SWIGNode.fixed d : SWIGNode N) ∉ M'.unobserved := by intro h rcases M'.unobserved_is_random _ h with ⟨_, hEq⟩ cases hEq have huo_M2 : (SWIGNode.fixed d : SWIGNode N) ∉ M2.unobserved := huo simp only [dif_neg huo, dif_neg huo_M2] -- Fixed case: .fixed d ∈ M'.fixed iff .fixed d ∈ M2.fixed (if d ∉ Z) -- or d ∈ Z (then .fixed d ∈ M2.fixed but may or may not be in M'.fixed). by_cases hfix_M1 : (SWIGNode.fixed d : SWIGNode N) ∈ M'.fixed · have hfix_M2 : (SWIGNode.fixed d : SWIGNode N) ∈ M2.fixed := by change _ ∈ M'.fixed ∪ Z.image SWIGNode.fixed exact mem_union_left _ hfix_M1 simp only [dif_pos hfix_M1, dif_pos hfix_M2] -- s_M1 := fixSetProj s' = valuesProjection (fixSet_fixed_subset) s'. -- So s_M1 ⟨.fixed d, hfix_M1⟩ = s' ⟨.fixed d, fixSet_fixed_subset hfix_M1⟩ -- = s' ⟨.fixed d, hfix_M2⟩ (by proof irrelevance). rfl · -- .fixed d ∉ M'.fixed. Is it in M2.fixed? Only if d ∈ Z. by_cases hd_Z : d ∈ Z · -- .fixed d ∈ M2.fixed via Z.image. -- But wait — .fixed d being a parent of v in M'.dag would need d ∈ M'.fixed -- (since fixed nodes outside M'.fixed are isolated). exfalso have := M'.fixed_outside_fixed_isolated d hfix_M1 have hCh : v ∈ M'.dag.children (SWIGNode.fixed d) := M'.dag.mem_children.mpr (M'.dag.mem_parents.mp hwVal_M1) simp [this.2] at hCh · have hfix_M2 : (SWIGNode.fixed d : SWIGNode N) ∉ M2.fixed := by intro h rcases Finset.mem_union.mp (show _ ∈ M'.fixed ∪ Z.image SWIGNode.fixed from h) with h1 | h2 · exact hfix_M1 h1 · rcases Finset.mem_image.mp h2 with ⟨d', hd'Z, hEq⟩ have : d = d' := SWIGNode.fixed.inj hEq.symm exact hd_Z (this ▸ hd'Z) simp only [dif_neg hfix_M1, dif_neg hfix_M2] -- Observed case — but `.fixed d ∉ M'.observed` since observed elts are .random. exfalso have hobs : (SWIGNode.fixed d : SWIGNode N) ∈ M'.observed := by have hedge_M1 : M'.dag.edge (SWIGNode.fixed d) v := M'.dag.mem_parents.mp hwVal_M1 rcases Finset.mem_union.mp (M'.dag_edges_classified _ _ hedge_M1).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix_M1 · exact hob · exact absurd h2 huo rcases M'.observed_is_random _ hobs with ⟨_, hEq⟩ cases hEq
Rule3Conditional 1 core · 3 supporting The joint-marginal Rule 3\* (do_rule3_star / condDistrib_intervention_ancestral_eq) transports the *joint* law of an ancestrally-blocked outcome block across an intervention. ★ do_rule3_star_conditional
Conditional Rule 3* (a.e. obsCondKernel form)
The joint-marginal Rule 3\* (do_rule3_star / condDistrib_intervention_ancestral_eq)
transports the joint law of an ancestrally-blocked outcome block across an
intervention. This file derives its conditional Rule 3\* consequence,
p(Y | do(z), W) = p(Y | W), under the same strong non-ancestor premise, in an
almost-everywhere form. It does not formalize Pearl's full Rule 3 premise.
The mathematical content is a single disintegration fact: condDistrib depends
only on the joint pushforward μ.map (X, Y), and Rule 3\* makes the two joint
pushforwards (under do(Z) and under the base model) literally equal on the
target/conditioning block. No positivity or ratio infrastructure is required
because there is no do-side pinning here (unlike Rule 2); the intervention only
transports a marginal.
Main declarations
condDistrib_eq_of_map_prod_eq— generic: equal joint pushforwards ⇒ equalcondDistrib.obsKernel_map_prodWY_eq— Rule 3\* specialized to the(W, Y)joint pushforward.obsKernel_map_W_eq— Rule 3\* specialized to theW-marginal.do_rule3_star_conditional_condDistrib— conditional Rule 3*, literalcondDistribform.do_rule3_star_conditional— conditional Rule 3*, headline a.e.obsCondKernelform.
References
- Basic Concepts.tex, Proposition (do-Calculus), Rule 3*.
- Malinsky, Shpitser & Richardson (2019), for Rule 3*.
- Pearl (2009), Causality, Chapter 3, for comparison with the full Rule 3.
**Conditional Rule 3* (headline, a.e. obsCondKernel form).** The non-ancestor specialization of deletion of actions, stated against the project's jointly-measurable conditional kernel. Fix a do-set Z of nodes whose random copies are observed in the base model and whose fixed nodes have not already been intervened on, an outcome block Y and a conditioning block W of observed variables. If none of the fixed copies of Z's nodes is an ancestor, in the intervention SWIG graph, of any node in Y ∪ W, then at a post-intervention fixed assignment, for almost every value w of W under the base model's W-marginal, the Y-given-W conditional kernel of the model intervened at do(Z) equals the Y-given-W conditional kernel of the base model, both evaluated at the corresponding fixed values.
Formal statement
Proof (Lean source)
3 supporting declarations (lemmas, instances)
-
obsKernel_map_prodWY_eqtheorem — Rule 3\* on the (W, Y) joint pushforward.hypothesesN :sharedType u_1N → Type u_2M' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhY :Y ⊆ M'.observedhW :W ⊆ M'.observedhNoDesc :∀ v ∈ Y ∪ W, ∀ d ∈ Z, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed d) vs' :(M'.fixSet Z hZ_obs hZ_fixed).FixedValuesconclusion((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s').map (fun ω => (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW) ω, valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ω))= (M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s')).map (fun ω => (valuesProjection hW ω, valuesProjection hY ω))Proof (Lean source)
theorem obsKernel_map_prodWY_eq (M' : SCM N Ω) (Z : Finset N) (hZ_obs : ∀ D ∈ Z, SWIGNode.random D ∈ M'.observed) (hZ_fixed : ∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixed) (Y W : Finset (SWIGNode N)) (hY : Y ⊆ M'.observed) (hW : W ⊆ M'.observed) (hNoDesc : ∀ v ∈ Y ∪ W, ∀ d ∈ Z, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed d) v) (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) : ((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s').map (fun ω => (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW) ω, valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ω)) = (M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s')).map (fun ω => (valuesProjection hW ω, valuesProjection hY ω)) := by -- Factor both pair-maps through the single `Y ∪ W` projection, then apply -- Rule 3* (`condDistrib_intervention_ancestral_eq`) on that union block. classical let M2 := M'.fixSet Z hZ_obs hZ_fixed let U := Y ∪ W have hU : U ⊆ M'.observed := Finset.union_subset hY hW have hU_do : U ⊆ M2.observed := by simpa [M2, SCM.fixSet_observed] using hU have hW_U : W ⊆ U := Finset.subset_union_right have hY_U : Y ⊆ U := Finset.subset_union_left let pairU : ValuesOn U (swigΩ Ω) → ValuesOn W (swigΩ Ω) × ValuesOn Y (swigΩ Ω) := fun ω => (valuesProjection hW_U ω, valuesProjection hY_U ω) have hpairU_meas : Measurable pairU := by exact (measurable_valuesProjection hW_U).prodMk (measurable_valuesProjection hY_U) have hPair_do_comp : pairU ∘ valuesProjection hU_do = (fun ω : M2.ObservedValues => (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW) ω, valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ω)) := by funext ω apply Prod.ext · simpa [pairU, Function.comp_apply] using congrFun (valuesProjection_comp (Ω' := swigΩ Ω) hW_U hU_do).symm ω · simpa [pairU, Function.comp_apply] using congrFun (valuesProjection_comp (Ω' := swigΩ Ω) hY_U hU_do).symm ω have hPair_base_comp : pairU ∘ valuesProjection hU = (fun ω : M'.ObservedValues => (valuesProjection hW ω, valuesProjection hY ω)) := by funext ω apply Prod.ext · simpa [pairU, Function.comp_apply] using congrFun (valuesProjection_comp (Ω' := swigΩ Ω) hW_U hU).symm ω · simpa [pairU, Function.comp_apply] using congrFun (valuesProjection_comp (Ω' := swigΩ Ω) hY_U hU).symm ω have hR3 : (M2.obsKernel s').map (valuesProjection hU_do) = (M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s')).map (valuesProjection hU) := by simpa [M2, U] using condDistrib_intervention_ancestral_eq M' Z hZ_obs hZ_fixed U hU (fun z hz v hv => hNoDesc v (by simpa [U] using hv) z hz) s' change (M2.obsKernel s').map (fun ω => (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW) ω, valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ω)) = (M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s')).map (fun ω => (valuesProjection hW ω, valuesProjection hY ω)) rw [← hPair_do_comp, ← hPair_base_comp] rw [← MeasureTheory.Measure.map_map hpairU_meas (measurable_valuesProjection hU_do)] rw [← MeasureTheory.Measure.map_map hpairU_meas (measurable_valuesProjection hU)] exact congrArg (map pairU) hR3 -
obsKernel_map_W_eqtheorem — Rule 3\* on the W-marginal.hypothesesN :sharedType u_1N → Type u_2M' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhW :W ⊆ M'.observedhNoDesc :∀ v ∈ W, ∀ d ∈ Z, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed d) vs' :(M'.fixSet Z hZ_obs hZ_fixed).FixedValuesconclusion((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s').map (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW))= (M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s')).map (valuesProjection hW)Proof (Lean source)
theorem obsKernel_map_W_eq (M' : SCM N Ω) (Z : Finset N) (hZ_obs : ∀ D ∈ Z, SWIGNode.random D ∈ M'.observed) (hZ_fixed : ∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixed) (W : Finset (SWIGNode N)) (hW : W ⊆ M'.observed) (hNoDesc : ∀ v ∈ W, ∀ d ∈ Z, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed d) v) (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) : ((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s').map (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW)) = (M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s')).map (valuesProjection hW) := condDistrib_intervention_ancestral_eq M' Z hZ_obs hZ_fixed W hW (fun z hz v hv => hNoDesc v hv z hz) s' -
do_rule3_star_conditional_condDistribtheorem — **Conditional Rule 3* (literal condDistrib form).** Fix a do-set whose random copies are observed and whose fixed copies have not already been intervened on, an observed target block, and an observed conditioning block. If no fixed copy of an intervened node is an ancestor of the target or conditioning block, then at each post-intervention fixed assignment, the conditional distribution of the target given the conditioning block is the same after intervention as under the base model at the corresponding fixed assignment.hypothesesN :sharedType u_1N → Type u_2M' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhY :Y ⊆ M'.observedhW :W ⊆ M'.observedhNoDesc :∀ v ∈ Y ∪ W, ∀ d ∈ Z, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed d) vs' :(M'.fixSet Z hZ_obs hZ_fixed).FixedValuesconclusioncondDistrib (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY)) (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW)) ((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s')= condDistrib (valuesProjection hY) (valuesProjection hW) (M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s'))Proof (Lean source)
theorem do_rule3_star_conditional_condDistrib (M' : SCM N Ω) (Z : Finset N) (hZ_obs : ∀ D ∈ Z, SWIGNode.random D ∈ M'.observed) (hZ_fixed : ∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixed) (Y W : Finset (SWIGNode N)) (hY : Y ⊆ M'.observed) (hW : W ⊆ M'.observed) [StandardBorelSpace (ValuesOn Y (swigΩ Ω))] [Nonempty (ValuesOn Y (swigΩ Ω))] (hNoDesc : ∀ v ∈ Y ∪ W, ∀ d ∈ Z, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed d) v) (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) : condDistrib (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY)) (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW)) ((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s') = condDistrib (valuesProjection hY) (valuesProjection hW) (M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s')) := condDistrib_eq_of_map_prod_eq (obsKernel_map_prodWY_eq M' Z hZ_obs hZ_fixed Y W hY hW hNoDesc s')
ValuesProjectionCI 1 core · 0 supporting This file specializes the weak-union rule for conditional independence to finite-product coordinate projections. ★ condIndep_valuesProjection_weak_union
Conditional Independence for Finite-Product Projections
This file specializes the weak-union rule for conditional independence to finite-product
coordinate projections. General projection algebra lives in
Causalean.Mathlib.MeasureTheory.FinsetValues; general contraction for these projections lives
in Causalean.Mathlib.Probability.Independence.Conditional.CondExp_Part2.
Weak union for coordinate projections. Let X, Y, W, Z be subsets of a finite index set I, with X, the union of Y and W, and the union of Z and W all contained in I, and let μ be a finite measure on the finite-product value space indexed by I. If X is conditionally independent of the union of Y and W given Z, then X is conditionally independent of Y given the union of Z and W, where independence is always of the corresponding coordinate projections under μ.