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 · 6 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.
Full conditional independence on RandomValues M (= V ∪ L).
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)
6 supporting declarations (lemmas, instances)
-
fullCondIndep_symmtheorem — Symmetry for FullCondIndep.hypothesesM :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 unfold FullCondIndep at h ⊢ exact condIndep_valuesProjection_symm hX hY hZ h -
fullCondIndep_subset_righttheorem — Subset right for FullCondIndep.hypothesesM :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 unfold FullCondIndep at h ⊢ exact condIndep_valuesProjection_subset_right hX hY hY' hZ hY'Y h -
fullCondIndep_decompositiontheorem — Decomposition for FullCondIndep.hypothesesM :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 unfold FullCondIndep 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'.hypothesesM :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.hypothesesM :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.hypothesesM :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 unfold FullCondIndep 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.
Observational conditional independence.
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.hypothesesM :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.hypothesesM :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 · 2 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:
* SCM.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)
2 supporting declarations (lemmas, instances)
-
observed_subset_randomVarstheorem — Observed nodes lie in randomVars.Proof (Lean source)
-
condIndepFun_of_maptheorem — Pushforward bridge for CondIndepFun.hypothesesα :β :γ :δ :ε :Type*φ :α → βhφ :X :β → γhX :Y :β → δhY :Z :β → εhZ :ν :IsFiniteMeasure (ν.map φ)h :conclusionProof (Lean source)
theorem condIndepFun_of_map {α : Type*} [MeasurableSpace α] [StandardBorelSpace α] {β : Type*} [MeasurableSpace β] [StandardBorelSpace β] {γ : Type*} [MeasurableSpace γ] [StandardBorelSpace γ] [Nonempty γ] {δ : Type*} [MeasurableSpace δ] [StandardBorelSpace δ] [Nonempty δ] {ε : Type*} [MeasurableSpace ε] {φ : α → β} (hφ : Measurable φ) {X : β → γ} (hX : Measurable X) {Y : β → δ} (hY : Measurable Y) {Z : β → ε} (hZ : Measurable Z) {ν : Measure α} [IsFiniteMeasure ν] [IsFiniteMeasure (ν.map φ)] (h : CondIndepFun (comap (Z ∘ φ) inferInstance) (comap_le (hZ.comp hφ)) (X ∘ φ) (Y ∘ φ) ν) : CondIndepFun (comap Z inferInstance) (hZ.comap_le) X Y (ν.map φ) := by -- condDistrib commutes with precomposition by φ (via Measure.map_map) have hcd1 : condDistrib (Y ∘ φ) (Z ∘ φ) ν = condDistrib Y Z (ν.map φ) := by simp only [condDistrib] congr 1 exact (MeasureTheory.Measure.map_map (hZ.prodMk hY) hφ).symm have hcd2 : condDistrib (Y ∘ φ) (fun ω ↦ ((Z ∘ φ) ω, (X ∘ φ) ω)) ν = condDistrib Y (fun b ↦ (Z b, X b)) (ν.map φ) := by simp only [condDistrib] congr 1 exact (MeasureTheory.Measure.map_map ((hZ.prodMk hX).prodMk hY) hφ).symm have hfilt : ν.map (fun ω ↦ ((Z ∘ φ) ω, (X ∘ φ) ω)) = (ν.map φ).map (fun b ↦ (Z b, X b)) := (MeasureTheory.Measure.map_map (hZ.prodMk hX) hφ).symm -- Use the condDistrib characterization of conditional independence rw [ProbabilityTheory.condIndepFun_iff_condDistrib_prod_ae_eq_prodMkRight hY hX hZ] have h' := (ProbabilityTheory.condIndepFun_iff_condDistrib_prod_ae_eq_prodMkRight (hY.comp hφ) (hX.comp hφ) (hZ.comp hφ)).mp h rw [hcd2, hcd1, hfilt] at h' exact h'
CutsetDSep 2 core · 10 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)
10 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.hypothesesconclusion(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.hypothesesu 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.hypothesesu 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.hypotheseshWNonDescM1 :∀ 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.hypotheseshWNonDescM1 :∀ 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.hypothesesconclusionv ≠ 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 — An active path in the original structural causal model remains active after fixing the treatment set, when each of its directed edges has a non-treatment source.hypotheseshWNonDescM1 :∀ D ∈ Z, ∀ w ∈ W, ¬ M.dag.isAncestor (SWIGNode.random D) whact :M.dag.IsActivePath (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.IsActivePath (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.IsActivePath (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.IsActivePath (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.hypothesesProof (Lean source)
lemma 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.IsActivePath 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.IsActivePath 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.IsActivePath 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.IsActivePath C p) : G.IsActivePath 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 -
get_appendTaillemma — Appending the tail of one nonempty list to another nonempty list preserves the first list's entries and then reads the remaining entries from the second list with a one-place shift.hypothesesconclusion(pa ++ q.tail).length = pa.length + q.length - 1 ∧(∀ (j : ℕ) (hj : j < pa.length), (pa ++ q.tail).get ⟨j, by rw [length_append]; have := length_tail (l := q); omega⟩ = pa.get ⟨j, hj⟩) ∧(∀ (j : ℕ) (hjL : pa.length ≤ j) (hj : j < (pa ++ q.tail).length), (pa ++ q.tail).get ⟨j, hj⟩ = q.get ⟨j - pa.length + 1, by rw [length_append, length_tail] at hj have : 1 ≤ q.length := List.length_pos_iff.mpr hq omega⟩)Proof (Lean source)
lemma get_appendTail {V : Type*} (pa q : List V) (_hpa : pa ≠ []) (hq : q ≠ []) : (pa ++ q.tail).length = pa.length + q.length - 1 ∧ (∀ (j : ℕ) (hj : j < pa.length), (pa ++ q.tail).get ⟨j, by rw [length_append]; have := List.length_tail (l := q); omega⟩ = pa.get ⟨j, hj⟩) ∧ (∀ (j : ℕ) (hjL : pa.length ≤ j) (hj : j < (pa ++ q.tail).length), (pa ++ q.tail).get ⟨j, hj⟩ = q.get ⟨j - pa.length + 1, by rw [length_append, List.length_tail] at hj have : 1 ≤ q.length := List.length_pos_iff.mpr hq omega⟩) := by have htail_len : q.tail.length = q.length - 1 := List.length_tail have hqpos : 1 ≤ q.length := List.length_pos_iff.mpr hq refine ⟨?_, ?_, ?_⟩ · rw [length_append, htail_len]; omega · intro j hj simp only [List.get_eq_getElem, List.getElem_append_left (h := hj)] · intro j hjL hj have hjr : j - pa.length < q.tail.length := by rw [length_append] at hj; omega have e1 : (pa ++ q.tail).get ⟨j, hj⟩ = q.tail[j - pa.length]'hjr := by simp only [List.get_eq_getElem] rw [List.getElem_append_right (by omega)] rw [e1, List.getElem_tail] simp [List.get_eq_getElem]
DoCalculus 3 core · 0 supporting This file states the three rules of Pearl's do-calculus for structural causal models in a single-intervention form. ★ do_rule1★ do_rule2_kernel★ do_rule3
Do-Calculus for Structural Causal Models
This file states the three rules of Pearl's do-calculus for structural causal models in a single-intervention form. The results connect graphical separation conditions in intervention graphs to observational conditional independences and conditional-kernel equalities used by the identification layer.
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 2: Action/observation exchange (single-SCM form, kernel-native). 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, with outcome and conditioning sets Y and W, and with the random copies of Z and their union with W all observed in M'. Suppose that, in the model intervened on Z, Y is d-separated from the random copies of Z given W together with the post-intervention fixed nodes, that no fixed copy of a Z-variable is a post-intervention ancestor of any node in W, and that no random copy of a Z-variable is an M'-ancestor of any node in W, so W is not downstream of the intervention in either graph. At a fixed-value point s0, assume the law obtained by independently pairing a treatment value drawn from the observational marginal of Z's random copies with a conditioning value drawn from the observational marginal of W is absolutely continuous with respect to the actual observational joint law of Z's random copies and W. Then for almost every such independently-paired pair (t, w), the Y-given-W conditional kernel of the model intervened at t, evaluated at the fixed value extended by t and at w, equals the Y-given-(Z ∪ W) conditional kernel of M' evaluated at s0 and the point filled by combining t and w.
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. Then the joint law of (Y, W) under the intervened model, at any post-intervention fixed value, 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 4 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 SCM.reindexSubtypeProj and
SCM.indepFun_valuesProjection_latentProduct, the product-measure independence
tools used internally by the Markov proof.
The latent ancestors of a node set are the unobserved nodes that either belong to the set or are ancestors of one of its nodes.
Definition (Lean source)
Measurable reindexing equivalence between the coordinate tuple on the subtype-image S.subtype (· ∈ P) of S ⊆ P and the coordinate tuple on S itself. It is the identity on values, only relabelling the index from the doubly-nested subtype to the direct subtype {j // j ∈ S}.
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.Proof (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.hypothesesM :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.hypothesesM :SCM N ΩStandardBorelSpace M.RandomValuesStandardBorelSpace M.LatentValues∀ (v : SWIGNode N),s :M.FixedValuesh :M.dag.OrderedLocalSG M.randomVars X Y Zconclusion∀ (hX : X ⊆ M.randomVars) (hY : Y ⊆ M.randomVars) (hZ : Z ⊆ M.randomVars),FullCondIndep 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.hypothesesM :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
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).hypothesesM :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
Rule2AE 1 core · 1 supporting The retired pointwise Rule 2 form quantified a.e. ★ obsCondKernel_fixSet_eq_ae_witness
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).hypothesesM' :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 `obsCondKernel_fixSet_eq_ae_witness`). 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 form of Rule 3 of do-calculus for structural causal models. ★ condDistrib_intervention_ancestral_eq
Rule 3 Kernel Identity
This file proves the kernel-level form of Rule 3 of do-calculus 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 (Option B in the design; covers the simplified Z_Y = Z case of the tex's Rule 3, sufficient for backdoor / frontdoor demos). 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.hypothesesM' :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.hypothesesM2 :SCM N ΩZ :Finset Nv :SWIGNode NhNoDesc :∀ z ∈ Z, ¬ M2.dag.isAncestor (SWIGNode.fixed z) vconclusion∀ z ∈ Z, SWIGNode.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.hypothesesM2 :SCM N ΩZ :Finset Nv w :SWIGNode NhwP :w ∈ M2.dag.parents vhNoDesc :∀ z ∈ Z, ¬ M2.dag.isAncestor (SWIGNode.fixed z) vconclusion∀ z ∈ Z, ¬ 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.hypothesesM' :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 · 4 supporting The joint-marginal Rule 3\* (do_rule3 / condDistrib_intervention_ancestral_eq) transports the *joint* law of an ancestrally-blocked outcome block across an intervention. ★ do_rule3_conditional
Conditional Rule 3 of do-Calculus (a.e. obsCondKernel form)
The joint-marginal Rule 3\* (do_rule3 / condDistrib_intervention_ancestral_eq)
transports the joint law of an ancestrally-blocked outcome block across an
intervention. This file upgrades it to the conditional Rule 3 — Pearl's
p(Y | do(z), W) = p(Y | W) — in the honest almost-everywhere form, matching the
style of do_rule2_kernel.
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_conditional_condDistrib— conditional Rule 3, literalcondDistribform.do_rule3_conditional— conditional Rule 3, headline a.e.obsCondKernelform.
References
- Basic Concepts.tex, Proposition (do-Calculus), Rule 3.
- Pearl (2009), Causality, Chapter 3.
Conditional Rule 3 (headline, a.e. obsCondKernel form). Pearl's Rule 3 for the 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 for almost every value w of W under the intervened 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)
4 supporting declarations (lemmas, instances)
-
condDistrib_eq_of_map_prod_eqtheorem — Two conditional distributions with the same joint law are equal.hypothesesh :μ.map (fun a => (X a, Y a)) = ν.map (fun a => (X' a, Y' a))conclusioncondDistrib Y X μ = condDistrib Y' X' νProof (Lean source)
theorem condDistrib_eq_of_map_prod_eq {α α' β γ : Type*} [MeasurableSpace α] [MeasurableSpace α'] [MeasurableSpace β] [MeasurableSpace γ] [StandardBorelSpace β] [Nonempty β] {X : α → γ} {Y : α → β} {X' : α' → γ} {Y' : α' → β} {μ : Measure α} {ν : Measure α'} [IsFiniteMeasure μ] [IsFiniteMeasure ν] (h : μ.map (fun a => (X a, Y a)) = ν.map (fun a => (X' a, Y' a))) : condDistrib Y X μ = condDistrib Y' X' ν := by rw [condDistrib, condDistrib] congr 1 -
obsKernel_map_prodWY_eqtheorem — Rule 3\* on the (W, Y) joint pushforward.hypothesesM' :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.hypothesesM' :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_conditional_condDistribtheorem — Conditional Rule 3 (literal condDistrib form).hypothesesM' :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_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 2 core · 5 supporting This file provides the finite-product projection infrastructure used by SCM conditional-independence proofs. ★ condIndep_valuesProjection_weak_union★ condIndep_valuesProjection_contraction
Conditional Independence for Finite-Product Projections
This file provides the finite-product projection infrastructure used by SCM
conditional-independence proofs. It proves compositional and sigma-algebra facts
for valuesProjection, defines valuesUnionMk for assembling two coordinate
blocks into their union, and proves the specialized weak-union and contraction
rules condIndep_valuesProjection_weak_union and
condIndep_valuesProjection_contraction. These results specialize general
conditional-expectation semi-graphoid identities to the value-block projections
used by structural causal models.
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 μ.
Formal statement
Proof (Lean source)
Contraction for coordinate projections. Let X, Y, W, Z be subsets of a common finite index set I, with X, Y, W, and Z all contained in I, and let μ be a finite measure on the resulting finite-product value space indexed by I. 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, where independence is always of the corresponding coordinate projections under μ.
Formal statement
Proof (Lean source)
5 supporting declarations (lemmas, instances)
-
valuesProjection_comptheorem — Composition identity for valuesProjection: restricting to K ⊆ J ⊆ I in one step equals composing the two restrictions.hypothesesconclusionProof (Lean source)
theorem valuesProjection_comp {M : Type*} {I J K : Finset M} {Ω' : M → Type*} [∀ n, MeasurableSpace (Ω' n)] (hKJ : K ⊆ J) (hJI : J ⊆ I) : valuesProjection (Ω := Ω') (hKJ.trans hJI) = valuesProjection hKJ ∘ valuesProjection hJI := by funext ξ ⟨k, hk⟩ simp only [Function.comp_apply, valuesProjection] -
comap_valuesProjection_monotheorem — The comap σ-algebra is monotone in the projected set: if A ⊆ B ⊆ I, then σ(π_A) ≤ σ(π_B) on ValuesOn I.hypothesesconclusionProof (Lean source)
theorem comap_valuesProjection_mono {M : Type*} {I A B : Finset M} {Ω' : M → Type*} [∀ n, MeasurableSpace (Ω' n)] (hAB : A ⊆ B) (hBI : B ⊆ I) : comap (valuesProjection (Ω := Ω') (hAB.trans hBI)) inferInstance ≤ comap (valuesProjection (Ω := Ω') hBI) inferInstance := by have hcomp := valuesProjection_comp (Ω' := Ω') hAB hBI rw [hcomp] intro s ⟨t, ht, hts⟩ exact ⟨valuesProjection hAB ⁻¹' t, measurable_valuesProjection hAB ht, hts⟩ -
measurable_valuesProjection_union_suptheorem — The projection to A ∪ B is measurable for the supremum of the separate projection σ-algebras.hypothesesconclusion@Measurable (ValuesOn I Ω') (ValuesOn (A ∪ B) Ω') (comap (valuesProjection (Ω := Ω') hA) inferInstance ⊔ comap (valuesProjection (Ω := Ω') hB) inferInstance) inferInstance (valuesProjection (Ω := Ω') (union_subset hA hB))Proof (Lean source)
theorem measurable_valuesProjection_union_sup {M : Type*} [DecidableEq M] {I A B : Finset M} {Ω' : M → Type*} [∀ n, MeasurableSpace (Ω' n)] (hA : A ⊆ I) (hB : B ⊆ I) : @Measurable (ValuesOn I Ω') (ValuesOn (A ∪ B) Ω') (comap (valuesProjection (Ω := Ω') hA) inferInstance ⊔ comap (valuesProjection (Ω := Ω') hB) inferInstance) inferInstance (valuesProjection (Ω := Ω') (union_subset hA hB)) := by let hAB : A ∪ B ⊆ I := union_subset hA hB change @Measurable (ValuesOn I Ω') (∀ i : {i // i ∈ A ∪ B}, Ω' i.val) (comap (valuesProjection (Ω := Ω') hA) inferInstance ⊔ comap (valuesProjection (Ω := Ω') hB) inferInstance) inferInstance (fun ξ : ValuesOn I Ω' => fun i : {i // i ∈ A ∪ B} => ξ ⟨i.val, hAB i.property⟩) refine (@measurable_pi_iff (ValuesOn I Ω') {i // i ∈ A ∪ B} (fun i : {i // i ∈ A ∪ B} => Ω' i.val) (comap (valuesProjection (Ω := Ω') hA) inferInstance ⊔ comap (valuesProjection (Ω := Ω') hB) inferInstance) inferInstance (fun ξ : ValuesOn I Ω' => fun i : {i // i ∈ A ∪ B} => ξ ⟨i.val, hAB i.property⟩)).2 ?_ intro ⟨i, hiAB⟩ by_cases hiA : i ∈ A · have hπA : @Measurable (ValuesOn I Ω') (ValuesOn A Ω') (comap (valuesProjection (Ω := Ω') hA) inferInstance ⊔ comap (valuesProjection (Ω := Ω') hB) inferInstance) inferInstance (valuesProjection (Ω := Ω') hA) := Measurable.of_comap_le le_sup_left exact (measurable_pi_apply (⟨i, hiA⟩ : {j // j ∈ A})).comp hπA · have hiB : i ∈ B := (Finset.mem_union.mp hiAB).resolve_left hiA have hπB : @Measurable (ValuesOn I Ω') (ValuesOn B Ω') (comap (valuesProjection (Ω := Ω') hA) inferInstance ⊔ comap (valuesProjection (Ω := Ω') hB) inferInstance) inferInstance (valuesProjection (Ω := Ω') hB) := Measurable.of_comap_le le_sup_right exact (measurable_pi_apply (⟨i, hiB⟩ : {j // j ∈ B})).comp hπB -
comap_valuesProjection_union_eq_suptheorem — The σ-algebra generated by the projection to A ∪ B is the supremum of the σ-algebras generated by the separate projections to A and to B.hypothesesconclusion= comap (valuesProjection (Ω := Ω') hA) inferInstance ⊔ comap (valuesProjection (Ω := Ω') hB) inferInstanceProof (Lean source)
theorem comap_valuesProjection_union_eq_sup {M : Type*} [DecidableEq M] {I A B : Finset M} {Ω' : M → Type*} [∀ n, MeasurableSpace (Ω' n)] (hA : A ⊆ I) (hB : B ⊆ I) : comap (valuesProjection (Ω := Ω') (union_subset hA hB)) inferInstance = comap (valuesProjection (Ω := Ω') hA) inferInstance ⊔ comap (valuesProjection (Ω := Ω') hB) inferInstance := by let hAB : A ∪ B ⊆ I := union_subset hA hB apply le_antisymm · exact comap_le (measurable_valuesProjection_union_sup (Ω' := Ω') hA hB) · exact sup_le (comap_valuesProjection_mono (Ω' := Ω') subset_union_left hAB) (comap_valuesProjection_mono (Ω' := Ω') subset_union_right hAB) -
valuesUnionMk_projection_comptheorem — Projecting to A and B and then assembling the union block recovers the direct projection to A ∪ B.hypothesesconclusion= valuesProjection (union_subset hA hB)Proof (Lean source)
theorem valuesUnionMk_projection_comp {M : Type*} [DecidableEq M] {I A B : Finset M} {Ω' : M → Type*} [∀ n, MeasurableSpace (Ω' n)] (hA : A ⊆ I) (hB : B ⊆ I) : (fun ξ : ValuesOn I Ω' => valuesUnionMk (Ω := Ω') (valuesProjection hA ξ) (valuesProjection hB ξ)) = valuesProjection (union_subset hA hB) := by let hAB : A ∪ B ⊆ I := union_subset hA hB funext ξ ⟨i, hiAB⟩ by_cases hiA : i ∈ A · simp [valuesUnionMk, valuesProjection, hiA] · simp [valuesUnionMk, valuesProjection, hiA]
ValuesReindex 2 core · 4 supporting Equational laws for valuesUnionMk (combine two coordinate blocks into one on their union) under union reordering and ∅ collapse, stated as Eqs transported along valuesEquivOfEq (the canonical measurable equivalence for p ★ valuesUnionMk_comm★ valuesOn_heq_of_coord
ValuesOn reindexing layer (do-calculus identification toolkit)
Equational laws for valuesUnionMk (combine two coordinate blocks into one on
their union) under union reordering and ∅ collapse, stated as Eqs
transported along valuesEquivOfEq (the canonical measurable equivalence for
propositionally-equal index Finsets) rather than as HEqs.
ValuesOn (A ∪ B) and ValuesOn (B ∪ A) are equal but not definitionally
equal, which is what forces HEq/cast gymnastics in the identification proofs
(e.g. the front-door derivation). Routing through valuesEquivOfEq keeps every
statement an Eq, so rw/simp consume them directly and call sites never
construct an HEq by hand. The valuesUnionMk_comm,
valuesUnionMk_empty_right, and valuesOn_heq_of_coord lemmas are the public
reindexing helpers used by do-calculus identification proofs.
Union commutativity. When A and B are disjoint, reindexing valuesUnionMk a b (a block on A ∪ B) along A ∪ B = B ∪ A yields valuesUnionMk b a.
Formal statement
Proof (Lean source)
HEq of value assignments from coordinatewise agreement. Given two node sets I and J that are equal as sets and value assignments f on I and g on J, if f and g agree at every node common to both index sets, then f and g are heterogeneously equal (HEq).
Formal statement
Proof (Lean source)
4 supporting declarations (lemmas, instances)
-
valuesUnionMk_empty_rightlemma — Right ∅ collapse. Reindexing valuesUnionMk a e (with e the trivial block on ∅) along A ∪ ∅ = A recovers a.Proof (Lean source)
lemma valuesUnionMk_empty_right {M : Type*} [DecidableEq M] {Ω : M → Type*} [∀ m, MeasurableSpace (Ω m)] {A : Finset M} (a : ValuesOn A Ω) (e : ValuesOn (∅ : Finset M) Ω) : valuesEquivOfEq (union_empty A) (valuesUnionMk a e) = a := by funext ⟨v, hv⟩ have hvA : v ∈ A ∪ (∅ : Finset M) := by rwa [union_empty] show valuesUnionMk a e ⟨v, hvA⟩ = a ⟨v, hv⟩ simp only [valuesUnionMk, dif_pos hv] -
valuesEquivOfEq_heqlemma — A value block is HEq to its reindexing along a Finset equality. The bridge that lets the equiv-mediated Eq laws above discharge legacy HEq goals in one line.hypothesesconclusionHEq (valuesEquivOfEq h x) xProof (Lean source)
lemma valuesEquivOfEq_heq {M : Type*} {Ω : M → Type*} [∀ m, MeasurableSpace (Ω m)] {I J : Finset M} (h : I = J) (x : ValuesOn I Ω) : HEq (valuesEquivOfEq h x) x := by subst h exact heq_of_eq rfl -
valuesUnionMk_comm_heqlemma — Union commutativity, HEq form. Supersedes the ad-hoc per-proof HEq construction: a one-line corollary of valuesUnionMk_comm.hypothesesconclusionProof (Lean source)
lemma valuesUnionMk_comm_heq {M : Type*} [DecidableEq M] {Ω : M → Type*} [∀ m, MeasurableSpace (Ω m)] {A B : Finset M} (hAB : Disjoint A B) (a : ValuesOn A Ω) (b : ValuesOn B Ω) : HEq (valuesUnionMk a b) (valuesUnionMk b a) := by rw [← valuesUnionMk_comm hAB a b] exact (valuesEquivOfEq_heq _ _).symm -
valuesUnionMk_empty_right_heqlemma — Right ∅ collapse, HEq form. valuesUnionMk a e (trivial ∅ block) is HEq to a; a one-line corollary of valuesUnionMk_empty_right.hypothesesconclusionHEq (valuesUnionMk a e) aProof (Lean source)
lemma valuesUnionMk_empty_right_heq {M : Type*} [DecidableEq M] {Ω : M → Type*} [∀ m, MeasurableSpace (Ω m)] {A : Finset M} (a : ValuesOn A Ω) (e : ValuesOn (∅ : Finset M) Ω) : HEq (valuesUnionMk a e) a := by have h : valuesEquivOfEq (union_empty A) (valuesUnionMk a e) = a := valuesUnionMk_empty_right a e have hx : HEq (valuesUnionMk a e) (valuesEquivOfEq (union_empty A) (valuesUnionMk a e)) := (valuesEquivOfEq_heq (union_empty A) (valuesUnionMk a e)).symm rw [h] at hx exact hx