SCM.Do.Rule2Kernel
Kernel-level proof of do-calculus Rule 2: conditional kernels under intervention, levelset compatibility, and the rectangle-identity bridge.
Helpers 7 core · 7 supporting This file builds the value-space maps that insert intervention values into a conditioning assignment. ★ fixSetProj_fixSetExtend★ fillZrW_fixSetExtend
Value-Space Helpers for Rule 2
This file builds the value-space maps that insert intervention values into a conditioning assignment. These maps provide the bookkeeping needed to compare conditioning on an observed random copy with conditioning on the corresponding intervention value in Rule 2.
This map reads intervention values as values of the corresponding observed random variables.
Definition (Lean source)
The Rule 2 filler inserts intervention values into a conditioning assignment.
Definition (Lean source)
A value assignment on a disjoint union is measurably equivalent to the pair of assignments on the two parts.
Definition (Lean source)
This map reads observed treatment values as values for the corresponding intervention coordinates.
Definition (Lean source)
This map extends a base fixed-value assignment with treatment values for a post-intervention model.
Definition (Lean source)
For the intervention names X, whose random copies are observed in the base model and whose fixed copies are not yet part of the base model's fixed coordinates, projecting the extended post-intervention fixed assignment — built from the base assignment s0 and treatment value t — back onto the original fixed coordinates recovers s0.
Formal statement
Proof (Lean source)
For the intervention names X, whose random copies are observed in the base model and whose fixed copies are not yet part of the base model's fixed coordinates, filling the conditioning assignment z against the extended post-intervention fixed assignment built from the base assignment s0 and treatment value t equals directly combining t and z into one assignment on their union.
Formal statement
Proof (Lean source)
7 supporting declarations (lemmas, instances)
-
measurable_zFixedAsRandomlemma — Reading intervention values as observed random-variable values is a measurable operation.Proof (Lean source)
lemma measurable_zFixedAsRandom {Z : Finset N} : Measurable (zFixedAsRandom (Ω := Ω) (Z := Z)) := by refine measurable_pi_iff.mpr ?_ rintro ⟨v, hv⟩ obtain ⟨D, hD, rfl⟩ := Finset.mem_image.mp hv -- v = SWIGNode.random D; output is `z ⟨.fixed D, _⟩` exact measurable_pi_apply _ -
measurable_fillZrWtheorem — The Rule 2 filler is measurable as a function of the free conditioning assignment.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).FixedValuesconclusionMeasurable (M'.fillZrW Z hZ_obs hZ_fixed W s')Proof (Lean source)
theorem measurable_fillZrW (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)) (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) : Measurable (M'.fillZrW Z hZ_obs hZ_fixed W s') := by unfold fillZrW exact measurable_valuesUnionMk_right _ -
measurable_fillZrW_prodtheorem — The Rule 2 filler is jointly measurable in the post-intervention fixed slice and the free conditioning coordinates.hypothesesM' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedconclusionMeasurable (fun p : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues × ValuesOn W (swigΩ Ω) => M'.fillZrW Z hZ_obs hZ_fixed W p.1 p.2)Proof (Lean source)
theorem measurable_fillZrW_prod (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)) : Measurable (fun p : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues × ValuesOn W (swigΩ Ω) => M'.fillZrW Z hZ_obs hZ_fixed W p.1 p.2) := by unfold fillZrW change Measurable ((fun q : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω) => valuesUnionMk q.1 q.2) ∘ (fun p : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues × ValuesOn W (swigΩ Ω) => (zFixedAsRandom (valuesProjection (fixSet_image_fixed_subset M' Z hZ_obs hZ_fixed) p.1), p.2))) refine (measurable_valuesUnionMk (Ω := swigΩ Ω) (A := Z.image SWIGNode.random) (B := W)).comp ?_ refine prodMk ?_ measurable_snd exact measurable_zFixedAsRandom.comp ((measurable_valuesProjection _).comp measurable_fst) -
measurable_xRandomAsFixedlemma — Reading observed treatment values as intervention-coordinate values is measurable.Proof (Lean source)
lemma measurable_xRandomAsFixed {X : Finset N} : Measurable (xRandomAsFixed (Ω := Ω) (X := X)) := by refine measurable_pi_iff.mpr ?_ rintro ⟨v, hv⟩ obtain ⟨D, hD, rfl⟩ := Finset.mem_image.mp hv exact measurable_pi_apply _ -
fixSetExtend_apply_new_fixedlemma — A newly fixed coordinate in fixSetExtend reads the matching observed intervention coordinate.hypothesesM :SCM N ΩX :Finset NhObs :∀ D ∈ X, SWIGNode.random D ∈ M.observedhFix :∀ D ∈ X, SWIGNode.fixed D ∉ M.fixeds0 :M.FixedValuesD :NhD :D ∈ XconclusionM.fixSetExtend X hObs hFix s0 t ⟨SWIGNode.fixed D, SCM.fixed_mem_fixSet M X hObs hFix hD⟩= t ⟨SWIGNode.random D, Finset.mem_image.mpr ⟨D, hD, rfl⟩⟩Proof (Lean source)
@[simp] lemma fixSetExtend_apply_new_fixed (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (s0 : M.FixedValues) (t : ValuesOn (X.image SWIGNode.random) (swigΩ Ω)) {D : N} (hD : D ∈ X) : M.fixSetExtend X hObs hFix s0 t ⟨SWIGNode.fixed D, SCM.fixed_mem_fixSet M X hObs hFix hD⟩ = t ⟨SWIGNode.random D, Finset.mem_image.mpr ⟨D, hD, rfl⟩⟩ := by simp [fixSetExtend, hFix D hD, xRandomAsFixed] -
measurable_fixSetExtendlemma — Extending a base fixed-value assignment is measurable in the treatment value when the base assignment is held fixed.hypothesesM :SCM N ΩX :Finset NhObs :∀ D ∈ X, SWIGNode.random D ∈ M.observedhFix :∀ D ∈ X, SWIGNode.fixed D ∉ M.fixeds0 :M.FixedValuesconclusionMeasurable (M.fixSetExtend X hObs hFix s0)Proof (Lean source)
lemma measurable_fixSetExtend (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (s0 : M.FixedValues) : Measurable (M.fixSetExtend X hObs hFix s0) := by refine measurable_pi_iff.mpr ?_ rintro ⟨v, hv⟩ by_cases hM : v ∈ M.fixed · simp only [fixSetExtend, dif_pos hM]; exact measurable_const · have hXf : v ∈ X.image SWIGNode.fixed := (Finset.mem_union.mp (by simpa using hv)).resolve_left hM have : (fun t : ValuesOn (X.image SWIGNode.random) (swigΩ Ω) => M.fixSetExtend X hObs hFix s0 t ⟨v, hv⟩) = fun t => xRandomAsFixed t ⟨v, hXf⟩ := by funext t; simp only [fixSetExtend, dif_neg hM] rw [this] exact (measurable_xRandomAsFixed).eval -
zFixedAsRandom_proj_fixSetExtendlemma — Relabeling the treatment part of the extended fixed assignment back to observed coordinates recovers the treatment assignment.hypothesesM :SCM N ΩX :Finset NhObs :∀ D ∈ X, SWIGNode.random D ∈ M.observedhFix :∀ D ∈ X, SWIGNode.fixed D ∉ M.fixeds0 :M.FixedValuesconclusionSCM.zFixedAsRandom (valuesProjection (SCM.fixSet_image_fixed_subset M X hObs hFix) (M.fixSetExtend X hObs hFix s0 t))= tProof (Lean source)
lemma zFixedAsRandom_proj_fixSetExtend (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (s0 : M.FixedValues) (t : ValuesOn (X.image SWIGNode.random) (swigΩ Ω)) : SCM.zFixedAsRandom (valuesProjection (SCM.fixSet_image_fixed_subset M X hObs hFix) (M.fixSetExtend X hObs hFix s0 t)) = t := by funext ⟨v, hv⟩ obtain ⟨D, hD, rfl⟩ := Finset.mem_image.mp hv -- LHS unfolds: zFixedAsRandom at .random D reads the .fixed D coordinate. simp only [SCM.zFixedAsRandom, valuesProjection] -- The .fixed D coordinate of fixSetExtend: .fixed D ∉ M.fixed, so it is -- xRandomAsFixed t ⟨.fixed D, _⟩ = t ⟨.random D, _⟩. have hMf : SWIGNode.fixed D ∉ M.fixed := hFix D hD simp only [SCM.fixSetExtend, dif_neg hMf, SCM.xRandomAsFixed]
DiscreteZHelpers 1 core · 2 supporting This file provides the discrete-treatment measure-theoretic helpers used to state Pearl's action-observation exchange without requiring the post-intervention treatment coordinate to be almost surely pinned. ★ obsKernel_fixSet_W_marginal_eq_M1_marginal
Discrete Treatment Helpers for Rule 2
This file provides the discrete-treatment measure-theoretic helpers used to state
Pearl's action-observation exchange without requiring the post-intervention
treatment coordinate to be almost surely pinned. It proves the W-marginal
equality obsKernel_fixSet_W_marginal_eq_M1_marginal, the filled-assignment
pullback equality mu_C_comap_F_eq_nu_C_comap_F, and the discrete conditional
kernel bridge obsCondKernel_cross_eq_ae_of_discrete. Together these connect
post-intervention adjustment marginals to pre-intervention joint marginals using
overlap, positivity, and the non-descendance condition needed for the Rule 3
marginal step.
Rule 3 W-marginal equality for Rule 2. For the intervention on names Z, whose random copies are observed in the base model and whose fixed copies are not yet part of the base model's fixed coordinates, and a conditioning set W contained in the observed variables, if no fixed copy of a name in Z is an ancestor, in the post-intervention DAG, of any node in W, then the W-marginal of the intervened model's observational kernel at a fixed assignment s equals the W-marginal of the base model's observational kernel at the corresponding projected assignment.
Formal statement
Proof (Lean source)
2 supporting declarations (lemmas, instances)
-
mu_C_comap_F_eq_nu_C_comap_Flemma — Cross-SCM pullback equality along the filled assignment.hypothesesM' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhZrW :Z.image SWIGNode.random ∪ W ⊆ M'.observedhDisj_ZrW :Disjoint (Z.image SWIGNode.random) Ws :(M'.fixSet Z hZ_obs hZ_fixed).FixedValuesconclusion((M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s)).map (valuesProjection (Ω := swigΩ Ω) hZrW)).comap (M'.fillZrW Z hZ_obs hZ_fixed W s)= (((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s).map (valuesProjection (Ω := swigΩ Ω) ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))).comap (M'.fillZrW Z hZ_obs hZ_fixed W s)Proof (Lean source)
lemma mu_C_comap_F_eq_nu_C_comap_F (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)) (hZrW : Z.image SWIGNode.random ∪ W ⊆ M'.observed) (hDisj_ZrW : Disjoint (Z.image SWIGNode.random) W) [MeasurableSingletonClass (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))] (s : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) : ((M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s)).map (valuesProjection (Ω := swigΩ Ω) hZrW)).comap (M'.fillZrW Z hZ_obs hZ_fixed W s) = (((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s).map (valuesProjection (Ω := swigΩ Ω) ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))).comap (M'.fillZrW Z hZ_obs hZ_fixed W s) := by classical let M2 := M'.fixSet Z hZ_obs hZ_fixed let sM1 : M'.FixedValues := M'.fixSetProj Z hZ_obs hZ_fixed s let F := M'.fillZrW Z hZ_obs hZ_fixed W s have hZrW_M2 : Z.image SWIGNode.random ∪ W ⊆ M2.observed := (fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW have hF_emb : MeasurableEmbedding F := measurableEmbedding_fillZrW M' Z hZ_obs hZ_fixed W hDisj_ZrW s have hπC_M1 : Measurable (valuesProjection (Ω := swigΩ Ω) hZrW : M'.ObservedValues → _) := measurable_valuesProjection _ have hπC_M2 : Measurable (valuesProjection (Ω := swigΩ Ω) hZrW_M2 : M2.ObservedValues → _) := measurable_valuesProjection _ refine MeasureTheory.Measure.ext (fun A_W hA_W => ?_) rw [hF_emb.comap_apply, hF_emb.comap_apply] have hImg_meas : MeasurableSet (F '' A_W) := hF_emb.measurableSet_image' hA_W rw [MeasureTheory.Measure.map_apply hπC_M1 hImg_meas, MeasureTheory.Measure.map_apply hπC_M2 hImg_meas] have hBridge : M2.obsKernel s (univ ∩ (valuesProjection hZrW_M2)⁻¹' (F '' A_W)) = M'.obsKernel sM1 (univ ∩ (valuesProjection hZrW)⁻¹' (F '' A_W)) := obsKernel_inter_Wset_Zrand_levelset_eq M' Z hZ_obs hZ_fixed W hZrW hDisj_ZrW s MeasurableSet.univ hA_W rw [Set.univ_inter, Set.univ_inter] at hBridge exact hBridge.symm -
obsCondKernel_cross_eq_ae_of_discretelemma — Discrete-treatment cross-SCM conditional-kernel equality.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'.observedhZrW :Z.image SWIGNode.random ∪ W ⊆ M'.observed∀ n, StandardBorelSpace (swigΩ Ω n)∀ n, Nonempty (swigΩ Ω n)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) vStandardBorelSpace (M'.fixSet Z hZ_obs hZ_fixed).RandomValuesStandardBorelSpace (M'.fixSet Z hZ_obs hZ_fixed).ObservedValues∀ s :M'.FixedValues, IsFiniteMeasure (M'.obsKernel s)(M'.fixSet Z hZ_obs hZ_fixed).FixedValues, IsFiniteMeasure ((M'.fixSet Z hZ_obs hZ_fixed).jointKernel s)(M'.fixSet Z hZ_obs hZ_fixed).FixedValues, IsFiniteMeasure ((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s)CountableOrCountablyGenerated (M'.fixSet Z hZ_obs hZ_fixed).FixedValues (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))s :(M'.fixSet Z hZ_obs hZ_fixed).FixedValueshPositivity :((M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s)).map (valuesProjection (Ω := swigΩ Ω) hW)) ≪ (((M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s)).map (valuesProjection (Ω := swigΩ Ω) hZrW)).comap (M'.fillZrW Z hZ_obs hZ_fixed W s))hB :conclusion∀ᵐ w ∂(((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s).map (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW))),(M'.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY hZrW (M'.fixSetProj Z hZ_obs hZ_fixed s, M'.fillZrW Z hZ_obs hZ_fixed W s w)) B= ((M'.fixSet Z hZ_obs hZ_fixed).obsCondKernel Y W ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW) (s, w)) BProof (Lean source)
lemma obsCondKernel_cross_eq_ae_of_discrete (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) (hZrW : Z.image SWIGNode.random ∪ W ⊆ M'.observed) [∀ n, StandardBorelSpace (swigΩ Ω n)] [∀ n, Nonempty (swigΩ Ω n)] (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) [StandardBorelSpace (M'.fixSet Z hZ_obs hZ_fixed).RandomValues] [StandardBorelSpace (M'.fixSet Z hZ_obs hZ_fixed).ObservedValues] [StandardBorelSpace (ValuesOn Y (swigΩ Ω))] [Nonempty (ValuesOn Y (swigΩ Ω))] [StandardBorelSpace (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω))] [Nonempty (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω))] [∀ s : M'.FixedValues, IsFiniteMeasure (M'.obsKernel s)] [∀ s : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues, IsFiniteMeasure ((M'.fixSet Z hZ_obs hZ_fixed).jointKernel s)] [∀ s : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues, IsFiniteMeasure ((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s)] [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Ω Ω))] (s : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) (hPositivity : ((M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s)).map (valuesProjection (Ω := swigΩ Ω) hW)) ≪ (((M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s)).map (valuesProjection (Ω := swigΩ Ω) hZrW)).comap (M'.fillZrW Z hZ_obs hZ_fixed W s))) {B : Set (ValuesOn Y (swigΩ Ω))} (hB : MeasurableSet B) : ∀ᵐ w ∂(((M'.fixSet Z hZ_obs hZ_fixed).obsKernel s).map (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW))), (M'.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY hZrW (M'.fixSetProj Z hZ_obs hZ_fixed s, M'.fillZrW Z hZ_obs hZ_fixed W s w)) B = ((M'.fixSet Z hZ_obs hZ_fixed).obsCondKernel Y W ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW) (s, w)) B := by classical -- Abbreviations. let M2 := M'.fixSet Z hZ_obs hZ_fixed let sM1 : M'.FixedValues := M'.fixSetProj Z hZ_obs hZ_fixed s let F := M'.fillZrW Z hZ_obs hZ_fixed W s have hDisj_ZrW : Disjoint (Z.image SWIGNode.random) W := Disjoint.mono_right Finset.subset_union_left hdSep.2.2.1 have hY_M2 : Y ⊆ M2.observed := (fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY have hW_M2 : W ⊆ M2.observed := (fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW have hZrW_M2 : Z.image SWIGNode.random ∪ W ⊆ M2.observed := (fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW have hF_emb : MeasurableEmbedding F := measurableEmbedding_fillZrW M' Z hZ_obs hZ_fixed W hDisj_ZrW s -- Marginal measures. let μ_C : Measure (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω)) := (M'.obsKernel sM1).map (valuesProjection hZrW) let ν_C : Measure (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω)) := (M2.obsKernel s).map (valuesProjection hZrW_M2) let μ_W : Measure (ValuesOn W (swigΩ Ω)) := (M'.obsKernel sM1).map (valuesProjection (Ω := swigΩ Ω) hW) let ν_W : Measure (ValuesOn W (swigΩ Ω)) := (M2.obsKernel s).map (valuesProjection (Ω := swigΩ Ω) hW_M2) have hμC_def : μ_C = (M'.obsKernel sM1).map (valuesProjection (Ω := swigΩ Ω) hZrW) := rfl have hνC_def : ν_C = (M2.obsKernel s).map (valuesProjection (Ω := swigΩ Ω) hZrW_M2) := rfl -- (1) Cross-SCM bridge: μ_C.comap F-a.e. w, M1.obsCondKernel(C)(sM1, F w) B -- = M2.obsCondKernel(C)(s, F w) B. have h_L2 := obsCondKernel_cross_SCM_ae_eq_on_fillZrW M' Z hZ_obs hZ_fixed Y W hY hW hZrW hDisj_ZrW s hB -- (2) D-sep collapse: ν_C-a.e. c, M2.obsCondKernel(C)(s, c) B -- = M2.obsCondKernel(W)(s, π_W^C c) B. have h_L1 := obsCondKernel_dSep_collapse_ae M' Z hZ_obs hZ_fixed Y W hY hW hdSep s hB -- (3) Pullback equality: μ_C.comap F = ν_C.comap F. have hPartA : μ_C.comap F = ν_C.comap F := mu_C_comap_F_eq_nu_C_comap_F M' Z hZ_obs hZ_fixed W hZrW hDisj_ZrW s -- (4) Rule 3 marginal equality: ν_W = μ_W as measures. have hν_W_eq_μ_W : ν_W = μ_W := by change (M2.obsKernel s).map (valuesProjection hW_M2) = (M'.obsKernel sM1).map (valuesProjection hW) exact obsKernel_fixSet_W_marginal_eq_M1_marginal M' Z hZ_obs hZ_fixed W hW hWNonDesc s -- (5) Transport h_L1 from ν_C-a.e. (in `c`) to ν_C.comap F-a.e. (in `w`, -- with `c := F w`). Step (5a): ν_C-a.e. → ν_C.restrict (range F)-a.e. have h_L1_restrict : ∀ᵐ c ∂(ν_C.restrict (range F)), (M2.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY_M2 hZrW_M2 (s, c)) B = (M2.obsCondKernel Y W hY_M2 hW_M2 (s, valuesProjection (Finset.subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)) c)) B := MeasureTheory.ae_restrict_of_ae h_L1 -- (5b): ν_C.restrict (range F) = (ν_C.comap F).map F (`hF_emb.map_comap`). have h_map_comap_ν : (ν_C.comap F).map F = ν_C.restrict (range F) := hF_emb.map_comap ν_C rw [← h_map_comap_ν] at h_L1_restrict -- (5c): Pull back through F via MeasurableEmbedding.ae_map_iff. have h_L1_pulled : ∀ᵐ w ∂(ν_C.comap F), (M2.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY_M2 hZrW_M2 (s, F w)) B = (M2.obsCondKernel Y W hY_M2 hW_M2 (s, valuesProjection (Finset.subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)) (F w))) B := (hF_emb.ae_map_iff (μ := ν_C.comap F) (p := fun c => (M2.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY_M2 hZrW_M2 (s, c)) B = (M2.obsCondKernel Y W hY_M2 hW_M2 (s, valuesProjection (Finset.subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)) c)) B)).mp h_L1_restrict -- (6) `π_W^C (F w) = w`, by construction of F. have h_proj_F : ∀ w : ValuesOn W (swigΩ Ω), valuesProjection (Finset.subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)) (F w) = w := by intro w funext ⟨v, hvW⟩ have hv_in : v ∈ Z.image SWIGNode.random ∪ W := Finset.subset_union_right hvW have hvNotZr : v ∉ Z.image SWIGNode.random := fun hvZr => Finset.disjoint_left.mp hDisj_ZrW hvZr hvW simp only [valuesProjection, F, fillZrW] rw [valuesUnionMk_apply_right _ _ hv_in hvNotZr] -- (7) Simplify h_L1_pulled using h_proj_F. have h_L1_simpl : ∀ᵐ w ∂(ν_C.comap F), (M2.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY_M2 hZrW_M2 (s, F w)) B = (M2.obsCondKernel Y W hY_M2 hW_M2 (s, w)) B := by refine Filter.Eventually.mono h_L1_pulled (fun w hw => ?_) rw [h_proj_F] at hw exact hw -- (8) Combine h_L2 (μ_C.comap F-a.e.) with h_L1_simpl (ν_C.comap F-a.e.), -- using the pullback equality to identify the two measures. have h_L1_simpl_μ : ∀ᵐ w ∂(μ_C.comap F), (M2.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY_M2 hZrW_M2 (s, F w)) B = (M2.obsCondKernel Y W hY_M2 hW_M2 (s, w)) B := by rw [hPartA]; exact h_L1_simpl have h_chain_μ : ∀ᵐ w ∂(μ_C.comap F), (M'.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY hZrW (sM1, F w)) B = (M2.obsCondKernel Y W hY_M2 hW_M2 (s, w)) B := by filter_upwards [h_L2, h_L1_simpl_μ] with w hL2 hL1 exact hL2.trans hL1 -- (9) Transport from μ_C.comap F-a.e. to μ_W-a.e. via hPositivity. have h_chain_μW : ∀ᵐ w ∂μ_W, (M'.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY hZrW (sM1, F w)) B = (M2.obsCondKernel Y W hY_M2 hW_M2 (s, w)) B := hPositivity.ae_eq h_chain_μ -- (10) Rewrite the goal's measure ν_W to μ_W via the Rule 3 marginal equality. change ∀ᵐ w ∂ν_W, _ rw [hν_W_eq_μ_W] exact h_chain_μW
InterSingleton 1 core · 2 supporting This file proves that, on the event where the treatment and adjustment coordinates take the fixed value inserted by the intervention, the post-intervention observational kernel and the original observational kernel assig ★ obsKernel_inter_Wset_Zrand_levelset_eq
Level-Set Agreement for Rule 2
This file proves that, on the event where the treatment and adjustment coordinates take the fixed value inserted by the intervention, the post-intervention observational kernel and the original observational kernel assign the same mass to every additional measurable observed event. This level-set identity is the cross-model cylinder equality used in the disintegration argument for Rule 2.
For the intervention on names Z, whose random copies are observed in the base model and whose fixed copies are not yet part of the base model's fixed coordinates, with the union of the random copies of Z and a conditioning set W contained in the observed variables and the random copies of Z disjoint from W, fix an intervened fixed assignment s'; for measurable subsets S of the observed-value space and measurable subsets A of the values on W, the intervened model's observational kernel at s', evaluated on S intersected with the preimage under the Z.random ∪ W-projection of the image of A under the filled-assignment map, equals the base model's observational kernel at the projected fixed assignment, evaluated on the analogous set.
Formal statement
Proof (Lean source)
2 supporting declarations (lemmas, instances)
-
obsKernel_inter_singleton_Zrand_eqtheorem — Joint kernel agreement on the Z.random-level-set event.hypothesesM' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhZrW :Z.image SWIGNode.random ∪ W ⊆ M'.observeds' :(M'.fixSet Z hZ_obs hZ_fixed).FixedValuesS :Set M'.ObservedValueshS :conclusion(M'.fixSet Z hZ_obs hZ_fixed).obsKernel s' (S ∩ (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w})= M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s') (S ∩ (valuesProjection hZrW)⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w})Proof (Lean source)
theorem obsKernel_inter_singleton_Zrand_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)) (hZrW : Z.image SWIGNode.random ∪ W ⊆ M'.observed) [MeasurableSingletonClass (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))] (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) (w : ValuesOn W (swigΩ Ω)) {S : Set M'.ObservedValues} (hS : MeasurableSet S) : (M'.fixSet Z hZ_obs hZ_fixed).obsKernel s' (S ∩ (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w}) = M'.obsKernel (M'.fixSetProj Z hZ_obs hZ_fixed s') (S ∩ (valuesProjection hZrW)⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w}) := by classical -- Abbreviations (via `let`; avoid `set` to prevent elaboration surprises). let M1 := M' let M2 := M1.fixSet Z hZ_obs hZ_fixed -- Use the explicit `.symm ▸` cast so the form matches the goal. have hZrW_M2 : Z.image SWIGNode.random ∪ W ⊆ M2.observed := (fixSet_observed M1 Z hZ_obs hZ_fixed).symm ▸ hZrW let s_M1 : M1.FixedValues := M1.fixSetProj Z hZ_obs hZ_fixed s' let c := M'.fillZrW Z hZ_obs hZ_fixed W s' w -- Measurability bookkeeping. have h_sing : MeasurableSet ({c} : Set _) := measurableSet_singleton _ have hπ_M1 : Measurable (valuesProjection hZrW : M1.ObservedValues → _) := measurable_valuesProjection _ have hπ_M2 : Measurable (valuesProjection hZrW_M2 : M2.ObservedValues → _) := measurable_valuesProjection _ have h_pre_M1 : MeasurableSet ((valuesProjection hZrW)⁻¹' {c}) := hπ_M1 h_sing have h_pre_M2 : MeasurableSet ((valuesProjection hZrW_M2)⁻¹' {c}) := hπ_M2 h_sing have hI_M1 : MeasurableSet (S ∩ (valuesProjection hZrW)⁻¹' {c}) := hS.inter h_pre_M1 have hI_M2 : MeasurableSet (S ∩ (valuesProjection hZrW_M2)⁻¹' {c}) := hS.inter h_pre_M2 have hRTO_M2 : Measurable M2.randomToObserved := M2.measurable_randomToObserved have hRTO_M1 : Measurable M1.randomToObserved := M1.measurable_randomToObserved have hf_M1 : Measurable (fun ℓ : M1.LatentValues => M1.evalMap s_M1 ℓ) := M1.evalMap_measurable.comp (prodMk measurable_const measurable_id) have hf_M2 : Measurable (fun ℓ : M2.LatentValues => M2.evalMap s' ℓ) := M2.evalMap_measurable.comp (prodMk measurable_const measurable_id) have hcast : Measurable (valuesProjection (le_of_eq (fixSet_unobserved M1 Z hZ_obs hZ_fixed).symm) : M2.LatentValues → M1.LatentValues) := measurable_valuesProjection _ -- LHS: unfold obsKernel → jointKernel → latentProduct.map evalMap. unfold obsKernel rw [ProbabilityTheory.Kernel.map_apply _ ((M'.fixSet Z hZ_obs hZ_fixed).measurable_randomToObserved), ProbabilityTheory.Kernel.map_apply _ M'.measurable_randomToObserved] have hI_M2_exp : MeasurableSet (S ∩ (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w}) := by exact hS.inter ((measurable_valuesProjection _) (measurableSet_singleton _)) have hI_M1_exp : MeasurableSet (S ∩ (valuesProjection hZrW)⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w}) := by exact hS.inter ((measurable_valuesProjection _) (measurableSet_singleton _)) have hmap_M2 : (map (M'.fixSet Z hZ_obs hZ_fixed).randomToObserved ((M'.fixSet Z hZ_obs hZ_fixed).jointKernel s')) (S ∩ (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w}) = ((M'.fixSet Z hZ_obs hZ_fixed).jointKernel s') ((M'.fixSet Z hZ_obs hZ_fixed).randomToObserved ⁻¹' (S ∩ (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w})) := by exact MeasureTheory.Measure.map_apply ((M'.fixSet Z hZ_obs hZ_fixed).measurable_randomToObserved) hI_M2_exp have hmap_M1 : (map M'.randomToObserved (M'.jointKernel (M'.fixSetProj Z hZ_obs hZ_fixed s'))) (S ∩ (valuesProjection hZrW)⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w}) = (M'.jointKernel (M'.fixSetProj Z hZ_obs hZ_fixed s')) (M'.randomToObserved ⁻¹' (S ∩ (valuesProjection hZrW)⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w})) := by exact MeasureTheory.Measure.map_apply M'.measurable_randomToObserved hI_M1_exp rw [hmap_M2, hmap_M1, jointKernel_apply_eq (M'.fixSet Z hZ_obs hZ_fixed) s', jointKernel_apply_eq M' (M'.fixSetProj Z hZ_obs hZ_fixed s')] have hf_M2_exp : Measurable (fun ℓ : (M'.fixSet Z hZ_obs hZ_fixed).LatentValues => (M'.fixSet Z hZ_obs hZ_fixed).evalMap s' ℓ) := by exact (M'.fixSet Z hZ_obs hZ_fixed).evalMap_measurable.comp (prodMk measurable_const measurable_id) have hf_M1_exp : Measurable (fun ℓ : M'.LatentValues => M'.evalMap (M'.fixSetProj Z hZ_obs hZ_fixed s') ℓ) := by exact M'.evalMap_measurable.comp (prodMk measurable_const measurable_id) have hpre_M2 : MeasurableSet ((M'.fixSet Z hZ_obs hZ_fixed).randomToObserved ⁻¹' (S ∩ (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w})) := (M'.fixSet Z hZ_obs hZ_fixed).measurable_randomToObserved hI_M2_exp have hpre_M1 : MeasurableSet (M'.randomToObserved ⁻¹' (S ∩ (valuesProjection hZrW)⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w})) := M'.measurable_randomToObserved hI_M1_exp have heval_M2 : (map (fun ℓ : (M'.fixSet Z hZ_obs hZ_fixed).LatentValues => (M'.fixSet Z hZ_obs hZ_fixed).evalMap s' ℓ) (M'.fixSet Z hZ_obs hZ_fixed).latentProduct) ((M'.fixSet Z hZ_obs hZ_fixed).randomToObserved ⁻¹' (S ∩ (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w})) = (M'.fixSet Z hZ_obs hZ_fixed).latentProduct ((fun ℓ : (M'.fixSet Z hZ_obs hZ_fixed).LatentValues => (M'.fixSet Z hZ_obs hZ_fixed).evalMap s' ℓ) ⁻¹' ((M'.fixSet Z hZ_obs hZ_fixed).randomToObserved ⁻¹' (S ∩ (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW))⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w}))) := by exact MeasureTheory.Measure.map_apply hf_M2_exp hpre_M2 have heval_M1 : (map (fun ℓ : M'.LatentValues => M'.evalMap (M'.fixSetProj Z hZ_obs hZ_fixed s') ℓ) M'.latentProduct) (M'.randomToObserved ⁻¹' (S ∩ (valuesProjection hZrW)⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w})) = M'.latentProduct ((fun ℓ : M'.LatentValues => M'.evalMap (M'.fixSetProj Z hZ_obs hZ_fixed s') ℓ) ⁻¹' (M'.randomToObserved ⁻¹' (S ∩ (valuesProjection hZrW)⁻¹' {M'.fillZrW Z hZ_obs hZ_fixed W s' w}))) := by exact MeasureTheory.Measure.map_apply hf_M1_exp hpre_M1 rw [heval_M2, heval_M1, ← fixSet_latentProduct_compat M' Z hZ_obs hZ_fixed, MeasureTheory.Measure.map_apply (measurable_valuesProjection _) (hf_M1_exp hpre_M1)] -- Goal: M2.latentProduct {ℓ : rando(M2.evalMap s' ℓ) ∈ I} = M2.latentProduct {ℓ : ...}. -- Reduce to set equality on the same M2.latentProduct. congr 1 -- Two preimage sets (in M2.LatentValues): -- L2 := {ℓ : rando(M2.evalMap s' ℓ) ∈ S ∩ π_C⁻¹{c}} -- L1 := {ℓ : cast ℓ ∈ {ℓ_M1 : rando(M1.evalMap s_M1 ℓ_M1) ∈ S ∩ π_C⁻¹{c}}} -- = {ℓ : rando(M1.evalMap s_M1 (cast ℓ)) ∈ S ∩ π_C⁻¹{c}} apply Set.eq_of_subset_of_subset all_goals intro ℓ hℓ simp only [Set.mem_preimage, Set.mem_inter_iff] at hℓ ⊢ -- Both directions use the same core mechanism: on the preimage, one side's -- evalMap is on the Z-level set; bridge via Claim A/B to get pointwise -- agreement of rando(evalMap) at every observed, hence the other side -- inherits membership. · -- ⊆: LHS (M2-side) ⊆ RHS (M1-side via cast). rcases hℓ with ⟨hS_mem, hπ_mem⟩ -- Extract LS_M2 from π_C = c. have hLS_M2 : ∀ D (hD : D ∈ Z), M2.evalMap s' ℓ ⟨SWIGNode.random D, mem_union_left _ (hZ_obs D hD)⟩ = s' ⟨SWIGNode.fixed D, SCM.fixed_mem_fixSet M1 Z hZ_obs hZ_fixed hD⟩ := by intro D hD -- π_C(rando(M2.evalMap s' ℓ)) = c at ⟨.random D, _⟩. have hD_in : SWIGNode.random D ∈ Z.image SWIGNode.random ∪ W := mem_union_left _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩) have hcoord := congrFun hπ_mem ⟨SWIGNode.random D, hD_in⟩ have hc_at : c ⟨SWIGNode.random D, hD_in⟩ = s' ⟨SWIGNode.fixed D, SCM.fixed_mem_fixSet M1 Z hZ_obs hZ_fixed hD⟩ := by show (valuesUnionMk (zFixedAsRandom (valuesProjection (fixSet_image_fixed_subset M' Z hZ_obs hZ_fixed) s')) w) ⟨SWIGNode.random D, hD_in⟩ = s' ⟨SWIGNode.fixed D, SCM.fixed_mem_fixSet M1 Z hZ_obs hZ_fixed hD⟩ rw [valuesUnionMk_apply_left _ _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)] rfl exact hcoord.trans hc_at -- Apply the M2-direction level-set bridge at each observed v. refine ⟨?_, ?_⟩ · -- S membership: rando(M1.evalMap s_M1 (cast ℓ)) ∈ S. have heq : M1.randomToObserved (M1.evalMap s_M1 (valuesProjection (le_of_eq (fixSet_unobserved M1 Z hZ_obs hZ_fixed).symm) ℓ)) = M2.randomToObserved (M2.evalMap s' ℓ) := by funext v simp only [randomToObserved] exact (fixSet_evalMap_levelset_compat_M2 M' Z hZ_obs hZ_fixed s' ℓ hLS_M2 v.property).symm rw [heq] exact hS_mem · -- π_C membership: preserved under the same pointwise equality. have heq : M1.randomToObserved (M1.evalMap s_M1 (valuesProjection (le_of_eq (fixSet_unobserved M1 Z hZ_obs hZ_fixed).symm) ℓ)) = M2.randomToObserved (M2.evalMap s' ℓ) := by funext v simp only [randomToObserved] exact (fixSet_evalMap_levelset_compat_M2 M' Z hZ_obs hZ_fixed s' ℓ hLS_M2 v.property).symm rw [heq] exact hπ_mem · -- ⊇: RHS (M1-side via cast) ⊆ LHS (M2-side). rcases hℓ with ⟨hS_mem, hπ_mem⟩ -- Extract LS_M1(cast ℓ) from π_C = c. have hLS_M1 : ∀ D (hD : D ∈ Z), M1.evalMap s_M1 (valuesProjection (le_of_eq (fixSet_unobserved M1 Z hZ_obs hZ_fixed).symm) ℓ) ⟨SWIGNode.random D, mem_union_left _ (hZ_obs D hD)⟩ = s' ⟨SWIGNode.fixed D, SCM.fixed_mem_fixSet M1 Z hZ_obs hZ_fixed hD⟩ := by intro D hD have hD_in : SWIGNode.random D ∈ Z.image SWIGNode.random ∪ W := mem_union_left _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩) have hcoord := congrFun hπ_mem ⟨SWIGNode.random D, hD_in⟩ have hc_at : c ⟨SWIGNode.random D, hD_in⟩ = s' ⟨SWIGNode.fixed D, SCM.fixed_mem_fixSet M1 Z hZ_obs hZ_fixed hD⟩ := by show (valuesUnionMk (zFixedAsRandom -- … truncated; follow the source link for the rest … -
obsKernel_disintegrate_recttheorem — Base-model disintegration over condition coordinates.hypothesesconclusionM.obsKernel s ((valuesProjection hCC)⁻¹' D ∩ (valuesProjection hY)⁻¹' B)= ∫⁻ c in D, M.obsCondKernel Y CC hY hCC (s, c) B ∂((M.obsKernel s).map (valuesProjection hCC))Proof (Lean source)
theorem obsKernel_disintegrate_rect (M : SCM N Ω) (Y CC : Finset (SWIGNode N)) (hY : Y ⊆ M.observed) (hCC : CC ⊆ M.observed) [StandardBorelSpace (ValuesOn Y (swigΩ Ω))] [Nonempty (ValuesOn Y (swigΩ Ω))] [CountableOrCountablyGenerated M.FixedValues (ValuesOn CC (swigΩ Ω))] (s : M.FixedValues) {D : Set (ValuesOn CC (swigΩ Ω))} {B : Set (ValuesOn Y (swigΩ Ω))} (hD : MeasurableSet D) (hB : MeasurableSet B) : M.obsKernel s ((valuesProjection hCC)⁻¹' D ∩ (valuesProjection hY)⁻¹' B) = ∫⁻ c in D, M.obsCondKernel Y CC hY hCC (s, c) B ∂((M.obsKernel s).map (valuesProjection hCC)) := by classical have hπCC : Measurable (valuesProjection (Ω := swigΩ Ω) hCC) := measurable_valuesProjection _ have hπY : Measurable (valuesProjection (Ω := swigΩ Ω) hY) := measurable_valuesProjection _ -- κ := obsCondPairKernel. set κ : Kernel M.FixedValues (ValuesOn CC (swigΩ Ω) × ValuesOn Y (swigΩ Ω)) := M.obsCondPairKernel Y CC hY hCC with hκ_def haveI hMarkov_κ : IsMarkovKernel κ := by rw [hκ_def] unfold obsCondPairKernel exact ProbabilityTheory.Kernel.IsMarkovKernel.map _ (hπCC.prodMk hπY) haveI : IsFiniteKernel κ := inferInstance -- Step 1: κ s (D ×ˢ B) = obsKernel cylinder. have h_pre : (valuesProjection hCC)⁻¹' D ∩ (valuesProjection hY)⁻¹' B = (fun ω => (valuesProjection hCC ω, valuesProjection hY ω))⁻¹' (D ×ˢ B) := by ext ω; simp [Set.mem_inter_iff, Set.mem_preimage, Set.mem_prod] have hKpair : κ s (D ×ˢ B) = M.obsKernel s ((valuesProjection hCC)⁻¹' D ∩ (valuesProjection hY)⁻¹' B) := by rw [hκ_def]; unfold obsCondPairKernel rw [ProbabilityTheory.Kernel.map_apply' _ (hπCC.prodMk hπY) _ (hD.prod hB)] rw [h_pre] -- Step 2: Kernel.fst κ s = (M.obsKernel s).map (valuesProjection hCC). have hfst : ProbabilityTheory.Kernel.fst κ s = (M.obsKernel s).map (valuesProjection hCC) := by rw [hκ_def] unfold obsCondPairKernel rw [ProbabilityTheory.Kernel.fst_map_prod _ hπY, ProbabilityTheory.Kernel.map_apply _ hπCC] -- Step 3: Mathlib disintegration for κ. have hKey : ∫⁻ c in D, ProbabilityTheory.Kernel.condKernel κ (s, c) B ∂(ProbabilityTheory.Kernel.fst κ s) = κ s (D ×ˢ B) := ProbabilityTheory.setLIntegral_condKernel_eq_measure_prod (κ := κ) s hD hB -- Step 4: obsCondKernel = condKernel of κ (definitional, up to instance). -- Assemble (sidestep instance rewriting by going through ENNReal eq). rw [← hKpair, ← hKey, hfst] -- Goal: ∫⁻ c in D, condKernel κ (s,c) B d(map π_CC obsKernel s) -- = ∫⁻ c in D, obsCondKernel Y CC … (s,c) B d(map π_CC obsKernel s) refine MeasureTheory.lintegral_congr_ae ?_ refine Filter.Eventually.of_forall ?_ intro c -- obsCondKernel is defined as condKernel of obsCondPairKernel. change ProbabilityTheory.Kernel.condKernel κ (s, c) B = M.obsCondKernel Y CC hY hCC (s, c) B rfl
LevelsetCompat 2 core · 0 supporting This file proves that the evaluation maps of the single-intervention and double-intervention models agree on the latent level set where the single intervention already realizes the additional treatment values. ★ fixSet_evalMap_levelset_compat★ fixSet_evalMap_levelset_compat_M2
Rule 2 Level-Set Compatibility
This file proves that the evaluation maps of the single-intervention and double-intervention models agree on the latent level set where the single intervention already realizes the additional treatment values. This is the evaluation-map bridge used in the kernel proof of Rule 2 of do-calculus.
Cross-SCM evalMap level-set bridge for Rule 2. For the intervention on names Z, whose random copies are observed in the base model and whose fixed copies are not yet part of the base model's fixed coordinates, fix an intervened fixed assignment s' and a latent draw ℓ. Suppose on the "level set" picked out by ℓ, the base model's evaluation map at the projected fixed assignment already reproduces, at every random copy of a name in Z, the intervention value recorded in s'; then at any observed node v in the intervened model, the intervened model's evaluation map at (s', ℓ) agrees with the base model's evaluation map at the projected fixed assignment and the correspondingly reindexed latent draw.
Formal statement
Proof (Lean source)
M2-direction level-set evalMap bridge for Rule 2. For the intervention on names Z, whose random copies are observed in the base model and whose fixed copies are not yet part of the base model's fixed coordinates, fix an intervened fixed assignment s' and a latent draw ℓ. Suppose the intervened model's own evaluation map at (s', ℓ) already reproduces, at every random copy of a name in Z, the intervention value recorded in s'; then at any observed node v in the intervened model, the intervened model's evaluation map at (s', ℓ) agrees with the base model's evaluation map at the projected fixed assignment and the correspondingly reindexed latent draw.
Formal statement
Proof (Lean source)
RectIdentity 2 core · 0 supporting This file provides two almost-everywhere equalities of conditional kernels — a d-separation collapse and a cross-model image comparison — consumed by the discrete-treatment backdoor Rule-2 derivation. ★ obsCondKernel_dSep_collapse_ae★ obsCondKernel_cross_SCM_ae_eq_on_fillZrW
Rule 2 conditional-kernel a.e. helpers
This file provides two almost-everywhere equalities of conditional kernels — a d-separation collapse and a cross-model image comparison — consumed by the discrete-treatment backdoor Rule-2 derivation.
D-separation collapse for the post-intervention conditional kernel. For the intervention on names Z, whose random copies are observed in the base model and whose fixed copies are not yet part of the base model's fixed coordinates, with outcome set Y and conditioning set W contained in the observed variables, suppose 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. Then, fixing an intervened fixed assignment s and a measurable outcome set B, for almost every conditioning value on Z.random ∪ W, the intervened model's conditional distribution of Y given Z.random ∪ W assigns B the same probability as its conditional distribution of Y given W alone, evaluated at the W-projection of that conditioning value.
Formal statement
Proof (Lean source)
Cross-SCM conditional kernels agree along the fillZrW filled assignment. For the intervention on names Z, whose random copies are observed in the base model and whose fixed copies are not yet part of the base model's fixed coordinates, with outcome set Y and conditioning set W contained in the observed variables, the union of the random copies of Z and W contained in the observed variables with the random copies of Z disjoint from W, fix an intervened fixed assignment s; then for a measurable outcome set B and almost every conditioning value w, taken with respect to the pullback of the base model's law on Z.random ∪ W under the filled-assignment map, the base model's conditional distribution of Y given Z.random ∪ W, evaluated at the filled point built from w, and the intervened model's corresponding conditional distribution, evaluated at the same filled point, assign B the same probability.
Formal statement
Proof (Lean source)
WitnessBridge 4 core · 7 supporting This file isolates the genuinely-hard analytic step of the continuous-Z Rule 2 (backdoor) argument and assembles the cross-SCM bridge obsCondKernel_fixSet_M1_eq_ae_product around it. ★ obsSide_eq_witness★ doSide_M2_condDistrib_eq_M1_witness★ doSide_eq_witness★ obsCondKernel_fixSet_M1_eq_ae_product
Cross-SCM obsCondKernel identity via the posterior witness kernel
This file isolates the genuinely-hard analytic step of the continuous-Z
Rule 2 (backdoor) argument and assembles the cross-SCM bridge
obsCondKernel_fixSet_M1_eq_ae_product around it.
Posterior witness kernel
Both the obs-side and the do-side equal the posterior witness kernel
(condDistrib C_W (πW ∘ E) μ_lat).map (h t w)
where μ_lat = M.latentProduct, E = M.evalMap s, C_W = M.cutsetLatent Y (Zr∪W)
is the latent cut-set, and h is the cut-set override map. This is the law of
Y | W under the posterior of the cut-set given W, which — crucially —
respects the W–Y confounding allowed by the backdoor criterion. (The old
obsCondKernel_struct route pushed the prior latent law forward, giving
Y | do(C), which is wrong under confounding; that route is deleted.)
The spine is:
* condDistrib_map_comp (Mathlib helper): transport the obs-level
condDistrib π_Y π_{Zr∪W} (obsKernel s) onto the latent space
latentProduct, where π ∘ E are the pulled-back coordinate maps.
* condDistrib_map_of_condDistrib_fst_eq (witness lemma, CondDistribWitness.lean):
given the pointwise factorization Y = h X Z C and the conditional
independence C ⊥ X | Z (in condDistrib-equality form), it yields the
posterior witness-kernel form of condDistrib Y (X,Z).
* the do-side under M2 := M'.fixSet Z mirrors the obs-side (random Zr has no
children in M2), and the two witness kernels are identified via
fixSet_latentProduct_compat plus the fillZrW override agreement; positivity
(Rule 3) transports onto the product νZ ⊗ₘ μW.
Analytic cores
The construction is assembled from the following named lemmas:
* cutset_factor_pointwise — the pointwise factorization
π_Y ∘ E = h (π_Zr∘E) (π_W∘E) C_W, together with the OFF-diagonal override
characterization h zr w' (π_{C_W} ℓ) = evalMap_overrideC … (valuesUnionMk zr w') ℓ
(needed do-side, where the treatment is pinned at t off the M1 diagonal).
* cutset_condIndep_condDistrib — the CI C_W ⊥ (π_Zr∘E) | (π_W∘E) under
latentProduct, in the condDistrib-pair form the witness lemma consumes,
from cutsetLatent_dSep_of_dSep + full_globalMarkov_with_fixed.
* obsSide_eq_witness, doSide_eq_witness — the two witness-kernel identities.
* doSide_M2_pullback_eq_M1_witness — the fillZrW cross-SCM identification of the
M2-pullback W-conditional with the M1 witness kernel. Closed via the no-X
witness corollary condDistrib_map_of_funext (Mathlib/CondDistribWitness.lean)
plus the override chain evalMap_overrideC_at_self@M2 →
evalMap_overrideC_dropZr_on_fillZrW → evalMap_overrideC_fixSet_compat_on_fillZrW
→ the override characterization of h.
* obsCondKernel_fixSet_M1_eq_ae_product — the product-form connect + positivity
transport (consumed by condDistrib_fixSet_cross_SCM_bridge in Rule2AE).
Obs-side witness-kernel identity (pair-conditioned, on the latent space). Let M be a structural causal model with node sets Y, W and a set of treatment names Z, where Y is observed, the pre-intervention nodes of Z are observed, and W is observed. Suppose the latent cut-set for Y relative to Z's pre-intervention nodes together with W is d-separated, in M's causal graph, from Z's pre-intervention nodes given W and the fixed nodes, and let h be a jointly measurable map such that, at a fixed baseline assignment s, the realized value of Y factors pointwise as h applied to the realized pre-intervention-Z value, the realized W value, and the cut-set's latent value. Then, under M's latent product measure, the conditional law of Y given the pair of realized pre-intervention-Z and W values equals, for almost every such pair, the pushforward under h applied to that pair of the conditional law of the latent cut-set given the realized W value.
Formal statement
Proof (Lean source)
Do-side analytic core: the M2 W-conditional equals the M1 witness kernel. Let M' be a structural causal model and Z a set of treatment names with each treatment's pre-intervention node observed and each treatment's post-intervention node not already fixed in M', so that intervening on Z is well-formed; let Y, W be node sets with Y, W, the treatments' pre-intervention nodes, and their union with W all observed and Y disjoint from the treatments' pre-intervention nodes. Suppose no node of W is a descendant, in the intervened model's graph, of any treatment's post-intervention node, and let h be a jointly measurable map that, at a baseline assignment s0 to the original model's fixed nodes, factors the realized outcome as h applied to the realized treatment value, the realized W value, and the latent cut-set's value and additionally, for every candidate treatment/W pair, agrees there with the outcome obtained by instead overriding the baseline assignment s0 to that pair. Then, at the intervened model's slice fixing the treatments to a value t and the remaining fixed nodes to s0, the measure-level conditional law of Y given W equals, for almost every w under the W-marginal of the original model's observational kernel at s0, the pushforward under h t w of the original model's posterior conditional law of the latent cut-set given W.
Formal statement
Proof (Lean source)
Do-side per-slice witness identity (M1-witness-kernel form). Let M' be a structural causal model and Z a set of treatment names with each treatment's pre-intervention node observed and each treatment's post-intervention node not already fixed in M'; let Y, W be node sets with Y, W, the treatments' pre-intervention nodes, and their union with W all observed, Y disjoint from the treatments' pre-intervention nodes, and those pre-intervention nodes disjoint from W. Suppose no node of W is a descendant, in the intervened model's graph, of any treatment's post-intervention node, and let h be a jointly measurable map that, at a baseline assignment s0 to the original model's fixed nodes, factors the realized outcome as h applied to the realized treatment value, the realized W value, and the latent cut-set's value, and additionally for every candidate treatment/W pair agrees there with the outcome obtained by instead overriding the baseline assignment s0 to that pair. Then, at the intervened model's slice fixing the treatments to a value t and the remaining fixed nodes to s0, for almost every w under the W-marginal of the original model's observational kernel at s0, the intervened model's conditional-probability kernel for Y given W at (s', w) equals the pushforward under h t w of the original model's posterior conditional law of the latent cut-set given W.
Formal statement
Proof (Lean source)
Product-form cross-SCM bridge for the do-side conditional kernel. Let M' be a structural causal model and Z a set of treatment names with each treatment's pre-intervention node observed and each treatment's post-intervention node not already fixed in M'; let Y, W be node sets with Y, W, the treatments' pre-intervention nodes, and their union with W all observed, Y disjoint from the treatments' pre-intervention nodes, and those pre-intervention nodes disjoint from W. Suppose that, in the intervened model's graph, no node of W is a descendant of any treatment's post-intervention node, that, in the original model's graph, no node of W is a descendant of any treatment's pre-intervention node, and that in the intervened model's graph, Y is d-separated from the treatments' pre-intervention nodes given W together with the intervened model's fixed nodes. Assume also, at a baseline assignment s0 to the original model's fixed nodes, an overlap condition: the pushforward, under combining a treatment value with a W value, of the product of the treatments' pre-intervention marginal law and the W-marginal law (both taken from the original model's observational kernel at s0) is absolutely continuous with respect to the original model's marginal law on the treatments' pre-intervention nodes together with W, again at s0. Then for almost every pair (t, w) drawn from that product law, the intervened model's conditional-probability kernel for Y given W, evaluated at treatment value t and conditioning value w, equals the original model's conditional-probability kernel for Y given the union of the treatments' pre-intervention nodes and W, evaluated at the combined value (t, w).
Formal statement
Proof (Lean source)
7 supporting declarations (lemmas, instances)
-
measurableSet_measure_eqtheorem — The agreement set of two measurable measure-valued maps is measurable.hypothesesconclusionMeasurableSet {p | f p = g p}Proof (Lean source)
theorem measurableSet_measure_eq {γ β : Type*} [MeasurableSpace γ] [MeasurableSpace β] [CountablyGenerated β] {f g : γ → Measure β} (hf : Measurable f) (hg : Measurable g) (hf_fin : ∀ p, IsFiniteMeasure (f p)) : MeasurableSet {p | f p = g p} := by classical -- The countable π-system generated by `countableGeneratingSet β ∪ {univ}`. set C₀ : Set (Set β) := MeasurableSpace.countableGeneratingSet β ∪ {univ} with hC₀ have hC₀_count : C₀.Countable := MeasurableSpace.countable_countableGeneratingSet.union (Set.countable_singleton _) set C : Set (Set β) := generatePiSystem C₀ with hC -- Countability of the generated π-system (image of finite intersections). have hC_count : C.Countable := by have hsub : generatePiSystem C₀ ⊆ (fun F : Finset (Set β) => ⋂₀ (F : Set (Set β))) '' {F : Finset (Set β) | ↑F ⊆ C₀} := by intro t ht induction ht with | base h_s => exact ⟨{_}, by simpa using h_s, by simp⟩ | inter _ _ _ ihs ihu => obtain ⟨Fs, hFs, rfl⟩ := ihs obtain ⟨Fu, hFu, rfl⟩ := ihu refine ⟨Fs ∪ Fu, ?_, ?_⟩ · simp only [Set.mem_setOf_eq, Finset.coe_union, Set.union_subset_iff] exact ⟨hFs, hFu⟩ · simp [Set.sInter_union] refine Set.Countable.mono hsub (Set.Countable.image ?_ _) haveI : Countable C₀ := hC₀_count.to_subtype have hr : {F : Finset (Set β) | ↑F ⊆ C₀} ⊆ range (fun (G : Finset C₀) => G.map (Function.Embedding.subtype _)) := by intro F hF refine ⟨F.subtype (· ∈ C₀), ?_⟩ ext x simp only [Finset.mem_map, Finset.mem_subtype, Function.Embedding.coe_subtype] constructor · rintro ⟨a, ha, rfl⟩; exact ha · intro hx; exact ⟨⟨x, hF hx⟩, by simpa using hx, rfl⟩ exact Set.Countable.mono hr (Set.countable_range _) have hC_pi : IsPiSystem C := isPiSystem_generatePiSystem _ have hC_meas : ∀ s ∈ C, MeasurableSet s := by intro s hs refine generatePiSystem_measurableSet ?_ s hs intro t ht rcases ht with ht | ht · exact MeasurableSpace.measurableSet_countableGeneratingSet ht · rw [Set.mem_singleton_iff] at ht; exact ht ▸ MeasurableSet.univ have hUniv_C : univ ∈ C := subset_generatePiSystem_self _ (inr rfl) have hgenC : (inferInstance : MeasurableSpace β) = MeasurableSpace.generateFrom C := by rw [hC, generateFrom_generatePiSystem_eq, hC₀, ← MeasurableSpace.generateFrom_sup_generateFrom, MeasurableSpace.generateFrom_countableGeneratingSet] have h1 : MeasurableSpace.generateFrom ({univ} : Set (Set β)) = ⊥ := MeasurableSpace.generateFrom_singleton_univ rw [h1, sup_bot_eq] -- Rewrite the agreement set as a countable intersection over `C`. have hset : {p | f p = g p} = ⋂ s ∈ C, {p | f p s = g p s} := by ext p simp only [Set.mem_setOf_eq, Set.mem_iInter] constructor · intro hp s _; rw [hp] · intro hp haveI := hf_fin p refine MeasureTheory.Measure.ext_of_generateFrom_of_iUnion C (fun _ => univ) hgenC hC_pi ?_ (fun _ => hUniv_C) ?_ ?_ · rw [Set.iUnion_const] · intro _; exact (MeasureTheory.measure_ne_top (f p) _) · intro s hs; exact hp s hs rw [hset] -- Each `{p | f p s = g p s}` is measurable; countable intersection. refine MeasurableSet.biInter hC_count (fun s hs => ?_) have hfs : Measurable (fun p => f p s) := (MeasureTheory.Measure.measurable_coe (hC_meas s hs)).comp hf have hgs : Measurable (fun p => g p s) := (MeasureTheory.Measure.measurable_coe (hC_meas s hs)).comp hg exact measurableSet_eq_fun hfs hgs -
obsKernel_eq_latentProduct_maptheorem — obsKernel s is the latent product pushed through randomToObserved ∘ evalMap s.hypothesesM :SCM N Ωs :M.FixedValuesconclusionM.obsKernel s = M.latentProduct.map (fun ℓ => M.randomToObserved (M.evalMap s ℓ))Proof (Lean source)
theorem obsKernel_eq_latentProduct_map (M : SCM N Ω) (s : M.FixedValues) : M.obsKernel s = M.latentProduct.map (fun ℓ => M.randomToObserved (M.evalMap s ℓ)) := by have hev : Measurable (fun ℓ : M.LatentValues => M.evalMap s ℓ) := by have : M.evalMap s = fun ℓ => uncurry M.evalMap (s, ℓ) := rfl rw [this] exact M.evalMap_measurable.comp (prodMk measurable_const measurable_id) rw [obsKernel, ProbabilityTheory.Kernel.map_apply _ M.measurable_randomToObserved, jointKernel_apply_eq, MeasureTheory.Measure.map_map M.measurable_randomToObserved hev] rfl -
valuesProjection_randomToObserved_evalMap_meastheorem — The pulled-back observed-coordinate projection through randomToObserved ∘ evalMap s is the latent projection of the evaluation, valuesProjection hY ∘ randomToObserved ∘ E. This is definitional unfolding, exposed so downstream condDistrib_map_comp rewrites can name the composite.hypothesesconclusionMeasurable (fun ℓ : M.LatentValues => valuesProjection hY (M.randomToObserved (M.evalMap s ℓ)))Proof (Lean source)
theorem valuesProjection_randomToObserved_evalMap_meas (M : SCM N Ω) {Y : Finset (SWIGNode N)} (hY : Y ⊆ M.observed) (s : M.FixedValues) : Measurable (fun ℓ : M.LatentValues => valuesProjection hY (M.randomToObserved (M.evalMap s ℓ))) := by have hev : Measurable (fun ℓ : M.LatentValues => M.evalMap s ℓ) := by have : M.evalMap s = fun ℓ => uncurry M.evalMap (s, ℓ) := rfl rw [this] exact M.evalMap_measurable.comp (prodMk measurable_const measurable_id) exact (measurable_valuesProjection hY).comp (M.measurable_randomToObserved.comp hev) -
cutset_factor_pointwisetheorem — Cut-set factorization, pointwise, at the realized override.hypothesesM :SCM N Ω∀ n, Nonempty (Ω n)Z :Finset NhY :Y ⊆ M.observedhZrW :Z.image SWIGNode.random ∪ W ⊆ M.observeds :M.FixedValuesconclusion∃ h : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) → ValuesOn W (swigΩ Ω) → ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω) → ValuesOn Y (swigΩ Ω),Measurable (fun p : (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω)) × ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω) => h p.1.1 p.1.2 p.2) ∧(∀ ℓ : M.LatentValues, valuesProjection hY (M.randomToObserved (M.evalMap s ℓ)) = h (valuesProjection (fun _ hz => hZrW (mem_union_left _ hz)) (M.randomToObserved (M.evalMap s ℓ))) (valuesProjection (fun _ hw => hZrW (mem_union_right _ hw)) (M.randomToObserved (M.evalMap s ℓ))) (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W)) ℓ)) ∧(∀ (zr : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω)) (w' : ValuesOn W (swigΩ Ω)) (ℓ : M.LatentValues), h zr w' (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W)) ℓ) = M.evalMap_overrideC hY hZrW s (valuesUnionMk zr w') ℓ)Proof (Lean source)
theorem cutset_factor_pointwise (M : SCM N Ω) [∀ n, Nonempty (Ω n)] (Y W : Finset (SWIGNode N)) (Z : Finset N) (hY : Y ⊆ M.observed) (hZrW : Z.image SWIGNode.random ∪ W ⊆ M.observed) (s : M.FixedValues) : ∃ h : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) → ValuesOn W (swigΩ Ω) → ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω) → ValuesOn Y (swigΩ Ω), Measurable (fun p : (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω)) × ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω) => h p.1.1 p.1.2 p.2) ∧ (∀ ℓ : M.LatentValues, valuesProjection hY (M.randomToObserved (M.evalMap s ℓ)) = h (valuesProjection (fun _ hz => hZrW (mem_union_left _ hz)) (M.randomToObserved (M.evalMap s ℓ))) (valuesProjection (fun _ hw => hZrW (mem_union_right _ hw)) (M.randomToObserved (M.evalMap s ℓ))) (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W)) ℓ)) ∧ -- Override-form characterization: `h` evaluated at the cut-set projection of -- *any* latent `ℓ` equals the override map at that `ℓ` with override block -- `(zr, w')`. This pins `h` OFF the realized-`s` diagonal — needed do-side, -- where the treatment coordinate is fixed at `t` (off the M1 diagonal). (∀ (zr : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω)) (w' : ValuesOn W (swigΩ Ω)) (ℓ : M.LatentValues), h zr w' (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W)) ℓ) = M.evalMap_overrideC hY hZrW s (valuesUnionMk zr w') ℓ) := by classical have hZr : Z.image SWIGNode.random ⊆ M.observed := fun _ hz => hZrW (mem_union_left _ hz) have hW : W ⊆ M.observed := fun _ hw => hZrW (mem_union_right _ hw) set C := Z.image SWIGNode.random ∪ W with hC_def set CW := M.cutsetLatent Y C with hCW_def have hCWsub : CW ⊆ M.unobserved := M.cutsetLatent_subset Y C -- Default latent vector for filling non-cutset coords. have hNEΩ : ∀ w : SWIGNode N, Nonempty (swigΩ Ω w) := by intro w; cases w <;> exact inferInstance let ℓ₀ : M.LatentValues := fun u => (hNEΩ u.val).some -- The measurable section restoring the cutset coordinates. let extendCutset : ValuesOn CW (swigΩ Ω) → M.LatentValues := fun cwProj u => if h : u.val ∈ CW then cwProj ⟨u.val, h⟩ else ℓ₀ u have hext_meas : Measurable extendCutset := by refine measurable_pi_lambda _ (fun u => ?_) by_cases h : u.val ∈ CW · have : (fun cwProj : ValuesOn CW (swigΩ Ω) => extendCutset cwProj u) = fun cwProj => cwProj ⟨u.val, h⟩ := by funext cwProj; simp [extendCutset, h] rw [this]; exact measurable_pi_apply _ · have : (fun cwProj : ValuesOn CW (swigΩ Ω) => extendCutset cwProj u) = fun _ => ℓ₀ u := by funext cwProj; simp [extendCutset, h] rw [this]; exact measurable_const -- The section restores cutset coordinates. have hext_restore : ∀ cwProj : ValuesOn CW (swigΩ Ω), valuesProjection hCWsub (extendCutset cwProj) = cwProj := by intro cwProj; funext u simp only [valuesProjection, extendCutset, dif_pos u.property] refine ⟨fun zr w c => M.evalMap_overrideC hY hZrW s (valuesUnionMk zr w) (extendCutset c), ?_, ?_, ?_⟩ · -- Joint measurability via `measurable_evalMap_overrideC`. have hcomp : (fun p : (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω)) × ValuesOn CW (swigΩ Ω) => M.evalMap_overrideC hY hZrW s (valuesUnionMk p.1.1 p.1.2) (extendCutset p.2)) = (fun q : (M.FixedValues × ValuesOn C (swigΩ Ω)) × M.LatentValues => M.evalMap_overrideC hY hZrW q.1.1 q.1.2 q.2) ∘ (fun p => ((s, valuesUnionMk p.1.1 p.1.2), extendCutset p.2)) := by funext p; rfl rw [hcomp] refine (measurable_evalMap_overrideC M hY hZrW).comp ?_ refine prodMk ?_ (hext_meas.comp measurable_snd) refine measurable_const.prodMk ?_ exact measurable_valuesUnionMk.comp measurable_fst · -- Factorization at the realized point. intro ℓ set E := M.randomToObserved (M.evalMap s ℓ) with hE_def -- (a) valuesUnionMk of the two projections of E equals the (Zr∪W)-projection of E. have ha : valuesUnionMk (valuesProjection hZr E) (valuesProjection hW E) = valuesProjection hZrW E := by funext ⟨v, hv⟩ by_cases hvZr : v ∈ Z.image SWIGNode.random · rw [valuesUnionMk_apply_left _ _ hvZr]; rfl · have hvW : v ∈ W := (Finset.mem_union.mp hv).resolve_left hvZr rw [valuesUnionMk_apply_right _ _ hv hvZr]; rfl -- (b) override agrees with `ℓ` after the cutset section, by cutset agreement. have hb : M.evalMap_overrideC hY hZrW s (valuesProjection hZrW E) (extendCutset (valuesProjection hCWsub ℓ)) = M.evalMap_overrideC hY hZrW s (valuesProjection hZrW E) ℓ := by refine evalMap_overrideC_agree_cutset M hY hZrW s _ _ _ ?_ rw [hext_restore] -- (c) the override at its "self" C-value equals the real eval on Y. have hc : M.evalMap_overrideC hY hZrW s (valuesProjection hZrW E) ℓ = valuesProjection hY E := by -- Both sides are the (cast-transported) `evalObservedAux` at observed nodes. have hself : valuesProjection hZrW E = (fun v' : {v // v ∈ C} => (M.observedAt_observedIndex ⟨v'.val, hZrW v'.property⟩) ▸ evalObservedAux M s ℓ (M.observedIndex ⟨v'.val, hZrW v'.property⟩).val (M.observedIndex ⟨v'.val, hZrW v'.property⟩).isLt) := by funext v' change E ⟨v'.val, hZrW v'.property⟩ = _ change M.evalMap s ℓ ⟨v'.val, _⟩ = _ rw [M.evalMap_observed s ℓ _ (hZrW v'.property)] rw [hself, M.evalMap_overrideC_at_self hY hZrW s ℓ] funext v change _ = E ⟨v.val, hY v.property⟩ change _ = M.evalMap s ℓ ⟨v.val, _⟩ rw [M.evalMap_observed s ℓ _ (hY v.property)] -- Assemble. calc valuesProjection hY E = M.evalMap_overrideC hY hZrW s (valuesProjection hZrW E) ℓ := hc.symm _ = M.evalMap_overrideC hY hZrW s (valuesProjection hZrW E) (extendCutset (valuesProjection hCWsub ℓ)) := hb.symm _ = M.evalMap_overrideC hY hZrW s (valuesUnionMk (valuesProjection hZr E) (valuesProjection hW E)) (extendCutset (valuesProjection hCWsub ℓ)) := by rw [ha] · -- Override-form characterization (off-diagonal pinning of `h`). -- `h zr w' (π_{C_W} ℓ) = override (valuesUnionMk zr w') (extendCutset (π_{C_W} ℓ))`, -- and the override depends on the latent only through the cut-set projection, -- so we may replace `extendCutset (π_{C_W} ℓ)` by `ℓ` itself. intro zr w' ℓ change M.evalMap_overrideC hY hZrW s (valuesUnionMk zr w') (extendCutset (valuesProjection hCWsub ℓ)) = M.evalMap_overrideC hY hZrW s (valuesUnionMk zr w') ℓ refine evalMap_overrideC_agree_cutset M hY hZrW s _ _ _ ?_ rw [hext_restore] -
cutset_condIndep_condDistribtheorem — Cut-set conditional independence, in condDistrib-pair form.hypothesesM :SCM N ΩStandardBorelSpace M.RandomValues∀ n, StandardBorelSpace (swigΩ Ω n)∀ n, Nonempty (swigΩ Ω n)∀ s :M.FixedValues, IsFiniteMeasure (M.jointKernel s)Z :Finset NhZr :Z.image SWIGNode.random ⊆ M.observedhW :W ⊆ M.observedhdSepCW :M.dag.dSep (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (Z.image SWIGNode.random) (W ∪ M.fixed)s :M.FixedValuesconclusion(fun p : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω) => condDistrib (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) (fun ℓ : M.LatentValues => (valuesProjection hZr (M.randomToObserved (M.evalMap s ℓ)), valuesProjection hW (M.randomToObserved (M.evalMap s ℓ)))) M.latentProduct p)=ᵐ[M.latentProduct.map (fun ℓ : M.LatentValues => (valuesProjection hZr (M.randomToObserved (M.evalMap s ℓ)), valuesProjection hW (M.randomToObserved (M.evalMap s ℓ))))] (fun p => condDistrib (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) (fun ℓ : M.LatentValues => valuesProjection hW (M.randomToObserved (M.evalMap s ℓ))) M.latentProduct p.2)Proof (Lean source)
theorem cutset_condIndep_condDistrib (M : SCM N Ω) [StandardBorelSpace M.RandomValues] [∀ n, StandardBorelSpace (swigΩ Ω n)] [∀ n, Nonempty (swigΩ Ω n)] [∀ s : M.FixedValues, IsFiniteMeasure (M.jointKernel s)] (Y W : Finset (SWIGNode N)) (Z : Finset N) [StandardBorelSpace (ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω))] [Nonempty (ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω))] (hZr : Z.image SWIGNode.random ⊆ M.observed) (hW : W ⊆ M.observed) (hdSepCW : M.dag.dSep (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (Z.image SWIGNode.random) (W ∪ M.fixed)) (s : M.FixedValues) : (fun p : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω) => condDistrib (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) (fun ℓ : M.LatentValues => (valuesProjection hZr (M.randomToObserved (M.evalMap s ℓ)), valuesProjection hW (M.randomToObserved (M.evalMap s ℓ)))) M.latentProduct p) =ᵐ[M.latentProduct.map (fun ℓ : M.LatentValues => (valuesProjection hZr (M.randomToObserved (M.evalMap s ℓ)), valuesProjection hW (M.randomToObserved (M.evalMap s ℓ))))] (fun p => condDistrib (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) (fun ℓ : M.LatentValues => valuesProjection hW (M.randomToObserved (M.evalMap s ℓ))) M.latentProduct p.2) := by classical set Zr := Z.image SWIGNode.random with hZr_def set CW := M.cutsetLatent Y (Zr ∪ W) with hCW_def have hCWsub : CW ⊆ M.unobserved := M.cutsetLatent_subset Y (Zr ∪ W) -- Subset facts into `randomVars`. have hobs_rv : M.observed ⊆ M.randomVars := by intro v hv; exact Finset.mem_union_left _ hv have hunobs_rv : M.unobserved ⊆ M.randomVars := by intro v hv; exact Finset.mem_union_right _ hv have hZr_rv : Zr ⊆ M.randomVars := hZr.trans hobs_rv have hW_rv : W ⊆ M.randomVars := hW.trans hobs_rv have hCW_rv : CW ⊆ M.randomVars := hCWsub.trans hunobs_rv -- Bridge: for an observed set `D`, projecting `randomToObserved (evalMap s ℓ)` -- equals projecting `evalMap s ℓ` directly (same underlying values). have hbridge_obs : ∀ {D : Finset (SWIGNode N)} (hD : D ⊆ M.observed) (hD_rv : D ⊆ M.randomVars) (ℓ : M.LatentValues), valuesProjection hD (M.randomToObserved (M.evalMap s ℓ)) = valuesProjection hD_rv (M.evalMap s ℓ) := by intro D hD hD_rv ℓ; funext v; rfl -- Bridge: for the latent cutset, projecting `evalMap s ℓ` equals projecting `ℓ`. have hbridge_lat : ∀ ℓ : M.LatentValues, valuesProjection hCW_rv (M.evalMap s ℓ) = valuesProjection hCWsub ℓ := by intro ℓ; funext v change M.evalMap s ℓ ⟨v.val, hCW_rv v.property⟩ = ℓ ⟨v.val, hCWsub v.property⟩ rw [M.evalMap_unobserved s ℓ _ (hCWsub v.property)] -- Measurability of the pulled-back coordinate maps (as compositions with evalMap s). have hev : Measurable (fun ℓ : M.LatentValues => M.evalMap s ℓ) := by have : M.evalMap s = fun ℓ => uncurry M.evalMap (s, ℓ) := rfl rw [this] exact M.evalMap_measurable.comp (prodMk measurable_const measurable_id) -- Abbreviations for the pulled-back coordinate maps. set Xmap : M.LatentValues → ValuesOn Zr (swigΩ Ω) := fun ℓ => valuesProjection hZr (M.randomToObserved (M.evalMap s ℓ)) with hX_def set Zmap : M.LatentValues → ValuesOn W (swigΩ Ω) := fun ℓ => valuesProjection hW (M.randomToObserved (M.evalMap s ℓ)) with hZmap_def set Cmap : M.LatentValues → ValuesOn CW (swigΩ Ω) := valuesProjection hCWsub with hC_def have hXmeas : Measurable Xmap := (measurable_valuesProjection hZr).comp (M.measurable_randomToObserved.comp hev) have hZmeas : Measurable Zmap := (measurable_valuesProjection hW).comp (M.measurable_randomToObserved.comp hev) have hCmeas : Measurable Cmap := measurable_valuesProjection hCWsub -- Step 1: cutset graph d-sep is now a direct hypothesis; global Markov -- (FullCondIndep under jointKernel) follows. (Previously derived internally -- via `cutsetLatent_dSep_of_dSep` from `dSep Y Zr`, which is FALSE at M1; the -- cutset d-sep `dSep C_W Zr` is the satisfiable input and is threaded directly.) have hdSepCW : M.dag.dSep CW Zr (W ∪ M.fixed) := hdSepCW have hDisj_CWZr : Disjoint CW Zr := by rw [Finset.disjoint_left]; intro a haCW haZr exact not_obs_of_unobs M.toSWIGGraph (hCWsub haCW) (hZr haZr) have hDisj_CWW : Disjoint CW W := by rw [Finset.disjoint_left]; intro a haCW haW exact not_obs_of_unobs M.toSWIGGraph (hCWsub haCW) (hW haW) have hFCI : FullCondIndep M CW Zr W hCW_rv hZr_rv hW_rv (M.jointKernel s) := full_globalMarkov_with_fixed M CW Zr W M.fixed hCW_rv hZr_rv hW_rv (refl _) hdSepCW s -- `Zr ⟂ CW | W` form (swap X↔Y), which the Mathlib iff consumes as `g ⟂ᵢ[k] f`. have hFCI_symm : FullCondIndep M Zr CW W hZr_rv hCW_rv hW_rv (M.jointKernel s) := fullCondIndep_symm M hCW_rv hZr_rv hW_rv hFCI haveI : IsProbabilityMeasure M.latentProduct := inferInstance -- Measurability of the `valuesProjection` maps on `RandomValues`. have hCW_proj_meas : Measurable (valuesProjection (Ω := swigΩ Ω) hCW_rv) := measurable_valuesProjection hCW_rv have hZr_proj_meas : Measurable (valuesProjection (Ω := swigΩ Ω) hZr_rv) := measurable_valuesProjection hZr_rv have hW_proj_meas : Measurable (valuesProjection (Ω := swigΩ Ω) hW_rv) := measurable_valuesProjection hW_rv -- Step 2: Mathlib iff turns `FullCondIndep` into a condDistrib-pair equality -- under `jointKernel s`, conditioning on the pair `(W, Zr)`. have hCI_joint : (fun p => condDistrib (valuesProjection hCW_rv) (fun ξ => (valuesProjection hW_rv ξ, valuesProjection hZr_rv ξ)) (M.jointKernel s) p) =ᵐ[(M.jointKernel s).map (fun ξ => (valuesProjection hW_rv ξ, valuesProjection hZr_rv ξ))] (fun p => ((condDistrib (valuesProjection hCW_rv) (valuesProjection hW_rv) (M.jointKernel s)).prodMkRight _) p) := by have := (ProbabilityTheory.condIndepFun_iff_condDistrib_prod_ae_eq_prodMkRight (μ := M.jointKernel s) (f := valuesProjection hCW_rv) (g := valuesProjection hZr_rv) (k := valuesProjection hW_rv) hCW_proj_meas hZr_proj_meas hW_proj_meas).mp hFCI_symm exact this -- The two coordinate maps on `RandomValues`, and their compositions with `evalMap s`. set Wmap_rv : M.RandomValues → ValuesOn W (swigΩ Ω) := valuesProjection hW_rv with hWmap_rv set Zrmap_rv : M.RandomValues → ValuesOn Zr (swigΩ Ω) := valuesProjection hZr_rv with hZrmap_rv set CWmap_rv : M.RandomValues → ValuesOn CW (swigΩ Ω) := valuesProjection hCW_rv with hCWmap_rv set pairWZr : M.RandomValues → ValuesOn W (swigΩ Ω) × ValuesOn Zr (swigΩ Ω) := fun ξ => (Wmap_rv ξ, Zrmap_rv ξ) with hpairWZr have hpairWZr_meas : Measurable pairWZr := hW_proj_meas.prodMk hZr_proj_meas -- Rewrite `jointKernel s` as the pushforward of `latentProduct`. have hjk : M.jointKernel s = M.latentProduct.map (fun ℓ => M.evalMap s ℓ) := jointKernel_apply_eq M s simp only [hjk] at hCI_joint -- Compositions with `evalMap s` reduce to `Zmap`, `Xmap`, `Cmap`. have hcomp_pair : pairWZr ∘ (fun ℓ => M.evalMap s ℓ) = fun ℓ => (Zmap ℓ, Xmap ℓ) := by funext ℓ simp only [hpairWZr, hWmap_rv, hZrmap_rv, Function.comp_apply, hZmap_def, hX_def] rw [hbridge_obs hW hW_rv ℓ, hbridge_obs hZr hZr_rv ℓ] have hcomp_W : Wmap_rv ∘ (fun ℓ => M.evalMap s ℓ) = Zmap := by funext ℓ; simp only [hWmap_rv, Function.comp_apply, hZmap_def] rw [hbridge_obs hW hW_rv ℓ] have hcomp_CW : CWmap_rv ∘ (fun ℓ => M.evalMap s ℓ) = Cmap := by funext ℓ change CWmap_rv (M.evalMap s ℓ) = Cmap ℓ rw [hbridge_lat ℓ] -- Transfer the pair-conditioned `condDistrib` onto `latentProduct`. have htr_pair := condDistrib_map_comp (𝒴 := ValuesOn CW (swigΩ Ω)) M.latentProduct (φ := fun ℓ => M.evalMap s ℓ) (g := CWmap_rv) (f := pairWZr) hev hCW_proj_meas hpairWZr_meas have htr_W := condDistrib_map_comp (𝒴 := ValuesOn CW (swigΩ Ω)) M.latentProduct (φ := fun ℓ => M.evalMap s ℓ) (g := CWmap_rv) (f := Wmap_rv) hev hCW_proj_meas hW_proj_meas -- The `(W, Zr)`-ordered latent pair map and its marginal measure facts. set pairWZr_lat : M.LatentValues → ValuesOn W (swigΩ Ω) × ValuesOn Zr (swigΩ Ω) := fun ℓ => (Zmap ℓ, Xmap ℓ) with hpairWZr_lat have hpairWZr_lat_meas : Measurable pairWZr_lat := hZmeas.prodMk hXmeas -- Push `htr_pair`/`htr_W`/`hCI_joint` filters into `LP.map (·∘E)` form. rw [MeasureTheory.Measure.map_map hpairWZr_meas hev, hcomp_pair, hcomp_CW] at htr_pair rw [MeasureTheory.Measure.map_map hpairWZr_meas hev, hcomp_pair] at hCI_joint rw [MeasureTheory.Measure.map_map hW_proj_meas hev, hcomp_W, hcomp_CW] at htr_W -- `htr_pair` now: condDistrib CWmap_rv pairWZr (LP.map E) =ᵐ[LP.map pairWZr_lat] -- condDistrib Cmap pairWZr_lat LP -- `hCI_joint` now RHS uses prodMkRight of condDistrib CWmap_rv Wmap_rv (LP.map E). -- Reduce prodMkRight to evaluation at `.1`. have hCI_joint' : (fun p => condDistrib CWmap_rv pairWZr (M.latentProduct.map (fun ℓ => M.evalMap s ℓ)) p) =ᵐ[M.latentProduct.map pairWZr_lat] (fun p => condDistrib CWmap_rv Wmap_rv (M.latentProduct.map (fun ℓ => M.evalMap s ℓ)) p.1) := by filter_upwards [hCI_joint] with p hp rw [hp, ProbabilityTheory.Kernel.prodMkRight_apply] -- Lift `htr_W` from the `W`-marginal to the pair-marginal along `fst`. have htr_W_fst : (fun p => condDistrib CWmap_rv Wmap_rv (M.latentProduct.map (fun ℓ => M.evalMap s ℓ)) p.1) =ᵐ[M.latentProduct.map pairWZr_lat] (fun p : ValuesOn W (swigΩ Ω) × ValuesOn Zr (swigΩ Ω) => condDistrib Cmap Zmap M.latentProduct p.1) := by have hfst_marg : (M.latentProduct.map pairWZr_lat).map fst = M.latentProduct.map Zmap := by rw [MeasureTheory.Measure.map_map measurable_fst hpairWZr_lat_meas]; rfl have := MeasureTheory.ae_eq_comp (μ := M.latentProduct.map pairWZr_lat) (f := fst) (g := fun q => condDistrib CWmap_rv Wmap_rv (M.latentProduct.map (fun ℓ => M.evalMap s ℓ)) q) (g' := fun q => condDistrib Cmap Zmap M.latentProduct q) measurable_fst.aemeasurable (by rw [hfst_marg]; exact htr_W) exact this -- Assemble the `(W, Zr)`-ordered equality on `LP.map pairWZr_lat`. have keyWZr : (fun p => condDistrib Cmap pairWZr_lat M.latentProduct p) =ᵐ[M.latentProduct.map pairWZr_lat] (fun p : ValuesOn W (swigΩ Ω) × ValuesOn Zr (swigΩ Ω) => condDistrib Cmap Zmap M.latentProduct p.1) := (htr_pair.symm.trans hCI_joint').trans htr_W_fst -- Swap `(W, Zr)` to `(Zr, W)` via the product-comm measurable equivalence. set e : (ValuesOn W (swigΩ Ω) × ValuesOn Zr (swigΩ Ω)) ≃ᵐ (ValuesOn Zr (swigΩ Ω) × ValuesOn W (swigΩ Ω)) := MeasurableEquiv.prodComm with he_def have hpair_swap : (fun ℓ => (Xmap ℓ, Zmap ℓ)) = e ∘ pairWZr_lat := by funext ℓ; rfl -- `condDistrib Cmap (e ∘ pairWZr_lat) LP (e p) = condDistrib Cmap pairWZr_lat LP p`, a.e. have hreparam := condDistrib_comp_right_measurableEquiv (μ := M.latentProduct) (Y := Cmap) (X := pairWZr_lat) e hCmeas hpairWZr_lat_meas -- Transport the goal (over `LP.map (Xmap, Zmap) = (LP.map pairWZr_lat).map e`) to `keyWZr`. have hmap_e : M.latentProduct.map (fun ℓ => (Xmap ℓ, Zmap ℓ)) = (M.latentProduct.map pairWZr_lat).map e := by rw [hpair_swap, ← MeasureTheory.Measure.map_map e.measurable hpairWZr_lat_meas] -- Final: rewrite the goal's conditioning into `Xmap`/`Zmap`, then chain. change (fun p => condDistrib Cmap (fun ℓ => (Xmap ℓ, Zmap ℓ)) M.latentProduct p) =ᵐ[M.latentProduct.map (fun ℓ => (Xmap ℓ, Zmap ℓ))] (fun p => condDistrib Cmap Zmap M.latentProduct p.2) rw [hmap_e] -- On `(LP.map pairWZr_lat).map e`, pull back along the measurable embedding `e`. rw [EventuallyEq, e.measurableEmbedding.ae_map_iff] filter_upwards [keyWZr, hreparam] with p hkey hrep -- LHS at `e p`: condDistrib Cmap (Xmap,Zmap) LP (e p) = condDistrib Cmap pairWZr_lat LP p. have hLHS : condDistrib Cmap (fun ℓ => (Xmap ℓ, Zmap ℓ)) M.latentProduct (e p) = condDistrib Cmap pairWZr_lat M.latentProduct p := by rw [hpair_swap]; exact hrep change condDistrib Cmap (fun ℓ => (Xmap ℓ, Zmap ℓ)) M.latentProduct (e p) = condDistrib Cmap Zmap M.latentProduct (e p).2 rw [hLHS, hkey] -- RHS: `condDistrib Cmap Zmap LP p.1 = condDistrib Cmap Zmap LP (e p).2`. rfl -
obsCondKernel_union_eq_witnesstheorem — The (Zr∪W)-conditional packaged as the witness kernel.hypothesesM :SCM N ΩStandardBorelSpace M.RandomValues∀ n, StandardBorelSpace (swigΩ Ω n)∀ n, Nonempty (swigΩ Ω n)∀ s :M.FixedValues, IsFiniteMeasure (M.jointKernel s)Z :Finset NhY :Y ⊆ M.observedhZrW :Z.image SWIGNode.random ∪ W ⊆ M.observedhDisj_ZrW :Disjoint (Z.image SWIGNode.random) WhdSepCW :M.dag.dSep (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (Z.image SWIGNode.random) (W ∪ M.fixed)s :M.FixedValuesh :hh :hfac :∀ ℓ : M.LatentValues,valuesProjection hY (M.randomToObserved (M.evalMap s ℓ))= h (valuesProjection ((subset_union_left (s₁ := Z.image SWIGNode.random) (s₂ := W)).trans hZrW) (M.randomToObserved (M.evalMap s ℓ))) (valuesProjection ((subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)).trans hZrW) (M.randomToObserved (M.evalMap s ℓ))) (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W)) ℓ)conclusion(fun c => M.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY hZrW (s, c))=ᵐ[(M.obsKernel s).map (valuesProjection hZrW)] (fun c => ((condDistrib (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) (fun ℓ : M.LatentValues => valuesProjection (Finset.subset_union_right.trans hZrW) (M.randomToObserved (M.evalMap s ℓ))) M.latentProduct) (valuesProjection (subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)) c)).map (h (valuesProjection (subset_union_left (s₁ := Z.image SWIGNode.random) (s₂ := W)) c) (valuesProjection (subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)) c)))Proof (Lean source)
theorem obsCondKernel_union_eq_witness (M : SCM N Ω) [StandardBorelSpace M.RandomValues] [∀ n, StandardBorelSpace (swigΩ Ω n)] [∀ n, Nonempty (swigΩ Ω n)] [∀ s : M.FixedValues, IsFiniteMeasure (M.jointKernel s)] (Y W : Finset (SWIGNode N)) (Z : Finset N) [StandardBorelSpace (ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω))] [Nonempty (ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω))] [StandardBorelSpace (ValuesOn Y (swigΩ Ω))] [Nonempty (ValuesOn Y (swigΩ Ω))] [CountableOrCountablyGenerated M.FixedValues (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))] (hY : Y ⊆ M.observed) (hZrW : Z.image SWIGNode.random ∪ W ⊆ M.observed) (hDisj_ZrW : Disjoint (Z.image SWIGNode.random) W) (hdSepCW : M.dag.dSep (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (Z.image SWIGNode.random) (W ∪ M.fixed)) (s : M.FixedValues) (h : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) → ValuesOn W (swigΩ Ω) → ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω) → ValuesOn Y (swigΩ Ω)) (hh : Measurable (fun p : (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω)) × ValuesOn (M.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω) => h p.1.1 p.1.2 p.2)) (hfac : ∀ ℓ : M.LatentValues, valuesProjection hY (M.randomToObserved (M.evalMap s ℓ)) = h (valuesProjection ((subset_union_left (s₁ := Z.image SWIGNode.random) (s₂ := W)).trans hZrW) (M.randomToObserved (M.evalMap s ℓ))) (valuesProjection ((subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)).trans hZrW) (M.randomToObserved (M.evalMap s ℓ))) (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W)) ℓ)) : (fun c => M.obsCondKernel Y (Z.image SWIGNode.random ∪ W) hY hZrW (s, c)) =ᵐ[(M.obsKernel s).map (valuesProjection hZrW)] (fun c => ((condDistrib (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) (fun ℓ : M.LatentValues => valuesProjection (Finset.subset_union_right.trans hZrW) (M.randomToObserved (M.evalMap s ℓ))) M.latentProduct) (valuesProjection (subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)) c)).map (h (valuesProjection (subset_union_left (s₁ := Z.image SWIGNode.random) (s₂ := W)) c) (valuesProjection (subset_union_right (s₁ := Z.image SWIGNode.random) (s₂ := W)) c))) := by classical have hZr : Z.image SWIGNode.random ⊆ M.observed := Finset.subset_union_left.trans hZrW have hW : W ⊆ M.observed := Finset.subset_union_right.trans hZrW -- Abbreviations: the observed-eval pullback `E` and the conditioning maps. set E : M.LatentValues → M.ObservedValues := fun ℓ => M.randomToObserved (M.evalMap s ℓ) with hE_def have hEmeas : Measurable E := M.measurable_randomToObserved.comp (by have : (fun ℓ : M.LatentValues => M.evalMap s ℓ) = fun ℓ => uncurry M.evalMap (s, ℓ) := rfl rw [show E = M.randomToObserved ∘ (fun ℓ => M.evalMap s ℓ) from rfl] at * exact M.evalMap_measurable.comp (measurable_const.prodMk measurable_id)) have hπY : Measurable (valuesProjection (Ω := swigΩ Ω) hY) := measurable_valuesProjection hY have hπZrW : Measurable (valuesProjection (Ω := swigΩ Ω) hZrW) := measurable_valuesProjection hZrW -- Step 1: obsCondKernel ↔ condDistrib. have h1 := M.obsCondKernel_ae_eq_condDistrib Y (Z.image SWIGNode.random ∪ W) hY hZrW s -- Step 2: transport the condDistrib onto `latentProduct` along `E`. have hobs : M.obsKernel s = M.latentProduct.map E := M.obsKernel_eq_latentProduct_map s have h2 := condDistrib_map_comp (𝒴 := ValuesOn Y (swigΩ Ω)) M.latentProduct (φ := E) (g := valuesProjection hY) (f := valuesProjection hZrW) hEmeas hπY hπZrW -- Step 3: reparametrize the `πZrW∘E` conditioning by the union iso. have h3 := condDistrib_comp_right_measurableEquiv (Ω := ValuesOn Y (swigΩ Ω)) M.latentProduct (Y := valuesProjection hY ∘ E) (X := valuesProjection hZrW ∘ E) (valuesUnionEquiv hDisj_ZrW) (hπY.comp hEmeas) (hπZrW.comp hEmeas) -- Step 4: the witness identity (pair-conditioned). have h4 := obsSide_eq_witness M Y W Z hY hZr hW hdSepCW s h hh hfac -- The pair map equals `e ∘ (π_{Zr∪W} ∘ E)` (both pick the `Zr`- and `W`-coords). have hpair : (fun ℓ : M.LatentValues => (valuesProjection hZr (E ℓ), valuesProjection hW (E ℓ))) = (⇑(valuesUnionEquiv hDisj_ZrW)) ∘ (valuesProjection hZrW ∘ E) := by funext ℓ; rfl -- Common base measure `ν` and the base alignments. have hbase1 : map (valuesProjection hZrW) (M.obsKernel s) = map (valuesProjection hZrW ∘ E) M.latentProduct := by rw [hobs, MeasureTheory.Measure.map_map hπZrW hEmeas] simp only [← hobs] at h2 -- Chain h1, h2: obsCondKernel = condDistrib of the pulled-back coords. have h12 := h1.trans h2 -- Transport h4 from base `map pair lat` to `ν` via the iso `e`. have hh4base : map (fun ℓ : M.LatentValues => (valuesProjection hZr (M.randomToObserved (M.evalMap s ℓ)), valuesProjection hW (M.randomToObserved (M.evalMap s ℓ)))) M.latentProduct = map (valuesUnionEquiv hDisj_ZrW) (map (valuesProjection hZrW ∘ E) M.latentProduct) := by rw [show (fun ℓ : M.LatentValues => (valuesProjection hZr (M.randomToObserved (M.evalMap s ℓ)), valuesProjection hW (M.randomToObserved (M.evalMap s ℓ)))) = (⇑(valuesUnionEquiv hDisj_ZrW)) ∘ (valuesProjection hZrW ∘ E) from hpair, ← MeasureTheory.Measure.map_map (valuesUnionEquiv hDisj_ZrW).measurable (hπZrW.comp hEmeas)] rw [hh4base] at h4 -- The witness kernel (its coe is defeq to `h4`'s RHS), used for measurability. have hwk_meas : Measurable (fun p : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω) => (condDistrib (valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) (fun ℓ => valuesProjection hW (M.randomToObserved (M.evalMap s ℓ))) M.latentProduct p.2).map (h p.1 p.2)) := ProbabilityTheory.Kernel.measurable (witnessKernel M.latentProduct (Z := fun ℓ => valuesProjection hW (M.randomToObserved (M.evalMap s ℓ))) (C := valuesProjection (M.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) hh) have h4' := (MeasureTheory.ae_map_iff (valuesUnionEquiv hDisj_ZrW).measurable.aemeasurable (measurableSet_measure_eq (ProbabilityTheory.Kernel.measurable _) hwk_meas (fun _ => inferInstance))).mp h4 -- Final assembly (all a.e. statements share base `ν = map (πZrW ∘ E) latentProduct`). rw [hbase1] at h12 ⊢ filter_upwards [h12, h3, h4'] with c hc12 hc3 hc4 rw [hc12, ← hc3] exact hc4 -
doSide_M2_pullback_eq_M1_witnesstheorem — Do-side cross-SCM core: the M2-pullback W-conditional on M2.latentProduct equals the M1 posterior witness kernel.hypothesesM' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhY :Y ⊆ M'.observedhZrW :Z.image SWIGNode.random ∪ W ⊆ M'.observedhDisj_YZr :Disjoint Y (Z.image SWIGNode.random)hWNonDesc :∀ z ∈ Z, ∀ v ∈ W, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed z) vStandardBorelSpace M'.RandomValuesStandardBorelSpace (M'.fixSet Z hZ_obs hZ_fixed).RandomValuesStandardBorelSpace (M'.fixSet Z hZ_obs hZ_fixed).ObservedValuess0 :M'.FixedValuesh :hh :hoverride :∀ (zr : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω)) (w' : ValuesOn W (swigΩ Ω)) (ℓ : M'.LatentValues),h zr w' (valuesProjection (M'.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W)) ℓ)= M'.evalMap_overrideC hY hZrW s0 (valuesUnionMk zr w') ℓconclusion(fun w => condDistrib (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ∘ fun ℓ : (M'.fixSet Z hZ_obs hZ_fixed).LatentValues => (M'.fixSet Z hZ_obs hZ_fixed).randomToObserved ((M'.fixSet Z hZ_obs hZ_fixed).evalMap (M'.fixSetExtend Z hZ_obs hZ_fixed s0 t) ℓ)) (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ (fun _ hw => hZrW (mem_union_right _ hw))) ∘ fun ℓ : (M'.fixSet Z hZ_obs hZ_fixed).LatentValues => (M'.fixSet Z hZ_obs hZ_fixed).randomToObserved ((M'.fixSet Z hZ_obs hZ_fixed).evalMap (M'.fixSetExtend Z hZ_obs hZ_fixed s0 t) ℓ)) (M'.fixSet Z hZ_obs hZ_fixed).latentProduct w)=ᵐ[(M'.obsKernel s0).map (valuesProjection (fun _ hw => hZrW (mem_union_right _ hw)))] (fun w => ((condDistrib (valuesProjection (M'.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) (fun ℓ : M'.LatentValues => valuesProjection (fun _ hw => hZrW (mem_union_right _ hw)) (M'.randomToObserved (M'.evalMap s0 ℓ))) M'.latentProduct) w).map (h t w))Proof (Lean source)
theorem doSide_M2_pullback_eq_M1_witness (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) (hZrW : Z.image SWIGNode.random ∪ W ⊆ M'.observed) (hDisj_YZr : Disjoint Y (Z.image SWIGNode.random)) (hWNonDesc : ∀ z ∈ Z, ∀ v ∈ W, ¬ (M'.fixSet Z hZ_obs hZ_fixed).dag.isAncestor (SWIGNode.fixed z) v) [StandardBorelSpace M'.RandomValues] [StandardBorelSpace (ValuesOn Y (swigΩ Ω))] [Nonempty (ValuesOn Y (swigΩ Ω))] [StandardBorelSpace (ValuesOn (M'.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω))] [Nonempty (ValuesOn (M'.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω))] [StandardBorelSpace (M'.fixSet Z hZ_obs hZ_fixed).RandomValues] [StandardBorelSpace (M'.fixSet Z hZ_obs hZ_fixed).ObservedValues] [StandardBorelSpace (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω))] [Nonempty (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω))] [CountableOrCountablyGenerated (M'.fixSet Z hZ_obs hZ_fixed).FixedValues (ValuesOn W (swigΩ Ω))] [MeasurableSingletonClass (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))] (s0 : M'.FixedValues) (t : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω)) (h : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) → ValuesOn W (swigΩ Ω) → ValuesOn (M'.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω) → ValuesOn Y (swigΩ Ω)) (hh : Measurable (fun p : (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) × ValuesOn W (swigΩ Ω)) × ValuesOn (M'.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω) => h p.1.1 p.1.2 p.2)) (hoverride : ∀ (zr : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω)) (w' : ValuesOn W (swigΩ Ω)) (ℓ : M'.LatentValues), h zr w' (valuesProjection (M'.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W)) ℓ) = M'.evalMap_overrideC hY hZrW s0 (valuesUnionMk zr w') ℓ) : (fun w => condDistrib (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY) ∘ fun ℓ : (M'.fixSet Z hZ_obs hZ_fixed).LatentValues => (M'.fixSet Z hZ_obs hZ_fixed).randomToObserved ((M'.fixSet Z hZ_obs hZ_fixed).evalMap (M'.fixSetExtend Z hZ_obs hZ_fixed s0 t) ℓ)) (valuesProjection ((fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ (fun _ hw => hZrW (mem_union_right _ hw))) ∘ fun ℓ : (M'.fixSet Z hZ_obs hZ_fixed).LatentValues => (M'.fixSet Z hZ_obs hZ_fixed).randomToObserved ((M'.fixSet Z hZ_obs hZ_fixed).evalMap (M'.fixSetExtend Z hZ_obs hZ_fixed s0 t) ℓ)) (M'.fixSet Z hZ_obs hZ_fixed).latentProduct w) =ᵐ[(M'.obsKernel s0).map (valuesProjection (fun _ hw => hZrW (mem_union_right _ hw)))] (fun w => ((condDistrib (valuesProjection (M'.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W))) (fun ℓ : M'.LatentValues => valuesProjection (fun _ hw => hZrW (mem_union_right _ hw)) (M'.randomToObserved (M'.evalMap s0 ℓ))) M'.latentProduct) w).map (h t w)) := by classical have hW : W ⊆ M'.observed := fun _ hw => hZrW (mem_union_right _ hw) set M2 := M'.fixSet Z hZ_obs hZ_fixed with hM2 set s' := M'.fixSetExtend Z hZ_obs hZ_fixed s0 t with hs' haveI : IsProbabilityMeasure M'.latentProduct := inferInstance haveI : IsFiniteMeasure M'.latentProduct := inferInstance set hY_M2 : Y ⊆ M2.observed := (fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hY with hhY_M2 set hW_M2 : W ⊆ M2.observed := (fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hW with hhW_M2 set hZrW_M2 : Z.image SWIGNode.random ∪ W ⊆ M2.observed := (fixSet_observed M' Z hZ_obs hZ_fixed).symm ▸ hZrW with hhZrW_M2 -- The M2 / M1 observed-eval pullbacks. Both act on `M'.LatentValues = M2.LatentValues`. set E2 : M2.LatentValues → M2.ObservedValues := fun ℓ => M2.randomToObserved (M2.evalMap s' ℓ) with hE2_def set E1 : M'.LatentValues → M'.ObservedValues := fun ℓ => M'.randomToObserved (M'.evalMap s0 ℓ) with hE1_def -- Cut-set subset (the SAME finset on the M1 side; latent index spaces agree by `rfl`). have hCWsub : M'.cutsetLatent Y (Z.image SWIGNode.random ∪ W) ⊆ M'.unobserved := M'.cutsetLatent_subset Y (Z.image SWIGNode.random ∪ W) -- (P2): the `W`-projection of `E2` equals that of `E1` (W non-descendant of the do-targets). have hP2 : ∀ ℓ : M2.LatentValues, valuesProjection hW_M2 (E2 ℓ) = valuesProjection hW (E1 ℓ) := by intro ℓ; funext v have hvW : v.val ∈ W := v.property have hvObs : v.val ∈ M'.observed := hW v.property have hkey := fixSet_evalMap_nonAnc_compat M' Z hZ_obs hZ_fixed s' ℓ (v := v.val) hvObs (fun z hz => hWNonDesc z hz v.val hvW) rw [M'.fixSetProj_fixSetExtend Z hZ_obs hZ_fixed s0 t] at hkey change M2.evalMap s' ℓ _ = M'.evalMap s0 _ _ rw [hkey]; rfl -- (P1): the `Y`-projection of `E2` is the M1 witness map at treatment `t`. -- Proof: M2's override at `Y` reduces — via `evalMap_overrideC_dropZr_on_fillZrW` and the -- cross-SCM compat `evalMap_overrideC_fixSet_compat_on_fillZrW` — to M1's override at the -- block value `valuesUnionMk t (π_W (E2 ℓ))`, which `hoverride` identifies with `h t ·`. have hP1 : ∀ ℓ : M2.LatentValues, valuesProjection hY_M2 (E2 ℓ) = h t (valuesProjection hW_M2 (E2 ℓ)) (valuesProjection hCWsub ℓ) := by intro ℓ -- Abbreviate the realized `W`-value of `E2 ℓ`. set w := valuesProjection hW_M2 (E2 ℓ) with hw_def -- (a) M2.evalMap_overrideC over `W` at its self-value equals `π_Y (E2 ℓ)`. have hself_W : (w : ValuesOn W (swigΩ Ω)) = (fun v' : {v // v ∈ W} => (M2.observedAt_observedIndex ⟨v'.val, hW_M2 v'.property⟩) ▸ evalObservedAux M2 s' ℓ (M2.observedIndex ⟨v'.val, hW_M2 v'.property⟩).val (M2.observedIndex ⟨v'.val, hW_M2 v'.property⟩).isLt) := by funext v' change (E2 ℓ) ⟨v'.val, hW_M2 v'.property⟩ = _ change M2.evalMap s' ℓ ⟨v'.val, _⟩ = _ rw [M2.evalMap_observed s' ℓ _ (hW_M2 v'.property)] have hcW : M2.evalMap_overrideC hY_M2 hW_M2 s' w ℓ = valuesProjection hY_M2 (E2 ℓ) := by rw [hself_W, M2.evalMap_overrideC_at_self hY_M2 hW_M2 s' ℓ] funext v change _ = (E2 ℓ) ⟨v.val, hY_M2 v.property⟩ change _ = M2.evalMap s' ℓ ⟨v.val, _⟩ rw [M2.evalMap_observed s' ℓ _ (hY_M2 v.property)] -- (b) override over `W` = override over `Zr∪W` at the `fillZrW`-filled block (`dropZr`). have hdrop : M2.evalMap_overrideC hY_M2 hZrW_M2 s' (M'.fillZrW Z hZ_obs hZ_fixed W s' w) ℓ = M2.evalMap_overrideC hY_M2 hW_M2 s' w ℓ := evalMap_overrideC_dropZr_on_fillZrW M' Z hZ_obs hZ_fixed Y W hY_M2 hZrW_M2 hDisj_YZr s' ℓ w -- (c) cross-SCM compat: M2 override over `Zr∪W` at `fillZrW` = M1 override over `Zr∪W` -- at `fillZrW`, base `fixSetProj s' = s0`, latent reindex = identity. have hcompat : M2.evalMap_overrideC hY_M2 hZrW_M2 s' (M'.fillZrW Z hZ_obs hZ_fixed W s' w) ℓ = M'.evalMap_overrideC hY hZrW s0 (valuesUnionMk t w) ℓ := by -- Rewrite the `M2`-side fill block to `valuesUnionMk t w` (`s' = fixSetExtend s0 t`). rw [hs', fillZrW_fixSetExtend M' Z hZ_obs hZ_fixed W s0 t w, ← hs'] funext v -- unfold both overrides to `evalObservedAuxOverride` at the SAME node `v.val`. rw [evalMap_overrideC_eq M2 hY_M2 hZrW_M2 s' _ ℓ v, evalMap_overrideC_eq M' hY hZrW s0 _ ℓ v] -- the compat lemma compares the full-observed-output overrides at node `v.val`; -- both unfold to the same `evalObservedAuxOverride` value, so transport via it. have hcv := evalMap_overrideC_fixSet_compat_on_fillZrW M' Z hZ_obs hZ_fixed W hZrW_M2 s' w ℓ (v := v.val) (hY_M2 v.property) -- `hcv` (read right→left) equates M2 and M1 full-output overrides at `⟨v.val, _⟩`. rw [evalMap_overrideC_eq M2 (refl _) hZrW_M2 s' _ ℓ ⟨v.val, hY_M2 v.property⟩, evalMap_overrideC_eq M' (refl _) hZrW (M'.fixSetProj Z hZ_obs hZ_fixed s') _ _ ⟨v.val, hY v.property⟩] at hcv -- `s0 = fixSetProj s'`, `valuesUnionMk t w = fillZrW W s' w`, reindex ℓ = ℓ. rw [M'.fixSetProj_fixSetExtend Z hZ_obs hZ_fixed s0 t, fillZrW_fixSetExtend M' Z hZ_obs hZ_fixed W s0 t w] at hcv exact hcv.symm -- (d) `hoverride` identifies the M1 override at `(t, w)` with `h t w (π_{C_W} ℓ)`. rw [← hcW, ← hdrop, hcompat] exact (hoverride t w ℓ).symm -- Measurability of the M1 conditioning / cut-set maps (reuse the SCM helper). have hZmeas : Measurable (fun ℓ : M'.LatentValues => valuesProjection hW (E1 ℓ)) := M'.valuesProjection_randomToObserved_evalMap_meas hW s0 have hCmeas : Measurable (valuesProjection (Ω := swigΩ Ω) hCWsub) := measurable_valuesProjection hCWsub -- `H := fun w c => h t w c` packages the witness map at the fixed treatment `t`. have hH : Measurable (fun p : ValuesOn W (swigΩ Ω) × ValuesOn (M'.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω) => h t p.1 p.2) := hh.comp (((measurable_const.prodMk measurable_fst).prodMk measurable_snd)) -- The no-treatment witness corollary on `M'.latentProduct`, conditioning on `π_W ∘ E1`. have hwit := condDistrib_map_of_funext (Ω := M'.LatentValues) (𝒵 := ValuesOn W (swigΩ Ω)) (𝒞 := ValuesOn (M'.cutsetLatent Y (Z.image SWIGNode.random ∪ W)) (swigΩ Ω)) (𝒴 := ValuesOn Y (swigΩ Ω)) M'.latentProduct (Z := fun ℓ : M'.LatentValues => valuesProjection hW (E1 ℓ)) (C := valuesProjection hCWsub) (H := fun w c => h t w c) hZmeas hCmeas hH -- The corollary's LHS factorized map `fun ℓ => h t (π_W (E1 ℓ)) (π_{C_W} ℓ)` equals `π_Y ∘ E2`. have hYeq : (fun ℓ : M'.LatentValues => h t (valuesProjection hW (E1 ℓ)) (valuesProjection hCWsub ℓ)) = fun ℓ : M2.LatentValues => valuesProjection hY_M2 (E2 ℓ) := by funext ℓ; rw [hP1 ℓ, hP2 ℓ] rw [hYeq] at hwit -- The base `M'.latentProduct.map (π_W ∘ E1)` equals `μW = (obsKernel s0).map π_W`. have hE1meas : Measurable (fun ℓ : M'.LatentValues => M'.randomToObserved (M'.evalMap s0 ℓ)) := M'.measurable_randomToObserved.comp (M'.evalMap_measurable.comp (measurable_const.prodMk measurable_id)) have hbaseμW : M'.latentProduct.map (fun ℓ : M'.LatentValues => valuesProjection hW (E1 ℓ)) = (M'.obsKernel s0).map (valuesProjection hW) := by rw [M'.obsKernel_eq_latentProduct_map s0, MeasureTheory.Measure.map_map (measurable_valuesProjection hW) hE1meas] rfl rw [hbaseμW] at hwit -- The goal's LHS conditioning map `π_W ∘ E2` equals `π_W ∘ E1` (by (P2)); rewrite `hwit`'s -- conditioning back to the `E2`-form so its LHS matches the goal's LHS (defeq otherwise). have hWmapeq : (fun ℓ : M2.LatentValues => valuesProjection hW_M2 (E2 ℓ)) = fun ℓ : M'.LatentValues => valuesProjection hW (E1 ℓ) := funext hP2 convert hwit using 3 congr 1
WMarginal 2 core · 4 supporting This file proves the filled-assignment measure identities used in the conditional version of Rule 2. ★ obsKernel_fixSet_W_marginal_pushforward_eq★ obsKernel_fixSet_W_rect_integral_eq
Marginal Identities for Rule 2
This file proves the filled-assignment measure identities used in the
conditional version of Rule 2. The helper lemmas describe the image of a
measurable W-event under fillZrW, prove that fillZrW is injective and a
measurable embedding, and use that embedding in
obsKernel_fixSet_W_marginal_pushforward_eq. The theorem
obsKernel_fixSet_W_rect_integral_eq then gives the rectangle integral identity
under the explicit hypothesis that the intervened random treatment copies equal
their assigned fixed intervention values almost surely. These conditional
identities are later upgraded to the full kernel statement of Rule 2.
W-marginal pushforward identity. 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 an observation block W such that the union of Z's random copies and W is observed and disjoint from Z's random copies. If, under the intervened model's law of the observed variables given the fixed values s', the post-intervention random copies of Z almost surely equal their assigned intervention values, then for every measurable W-event A, the intervened model's marginal probability of A on W equals the base model's probability of the pullback of A through the map that fills in the pinned Z-random-copy coordinates alongside W.
Formal statement
Proof (Lean source)
Cross-SCM rectangle bridge for the W-marginal. 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, together with an outcome block Y and a conditioning block W of observed variables such that the union of Z's random copies and W is observed and disjoint from Z's random copies. Assume that, under the intervened model's law given the fixed values s, the post-intervention random copies of Z almost surely equal their assigned intervention values. Then for every measurable W-event A and every measurable Y-event B, integrating, over A and with respect to the intervened model's W-marginal, the base model's conditional probability of B given the outcome of filling in Z's pinned random-copy values alongside each w reconstructs the intervened model's probability that both the W-event A and the Y-event B occur.
Formal statement
Proof (Lean source)
4 supporting declarations (lemmas, instances)
-
fillZrW_image_eqlemma — The image of a W-event under the filled-assignment map fillZrW Z hZ_obs hZ_fixed W s is exactly the set of assignments on Z.image .random ∪ W whose W-projection lies in the event and whose Z.image .random projection equals the fixed intervention value zFixedAsRandom (valuesProjection (fixSet_image_fixed_subset ...) s).hypothesesM' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhDisj_ZrW :Disjoint (Z.image SWIGNode.random) Ws' :(M'.fixSet Z hZ_obs hZ_fixed).FixedValuesconclusion(M'.fillZrW Z hZ_obs hZ_fixed W s') '' A= (fun c : ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω) => valuesProjection (subset_union_right (s₁ := Z.image SWIGNode.random)) c)⁻¹' A ∩ (fun c => valuesProjection (subset_union_left (s₂ := W)) c)⁻¹' ({zFixedAsRandom (valuesProjection (fixSet_image_fixed_subset M' Z hZ_obs hZ_fixed) s')} : Set (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω)))Proof (Lean source)
lemma fillZrW_image_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)) (hDisj_ZrW : Disjoint (Z.image SWIGNode.random) W) (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) (A : Set (ValuesOn W (swigΩ Ω))) : (M'.fillZrW Z hZ_obs hZ_fixed W s') '' A = (fun c : ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω) => valuesProjection (Finset.subset_union_right (s₁ := Z.image SWIGNode.random)) c)⁻¹' A ∩ (fun c => valuesProjection (subset_union_left (s₂ := W)) c)⁻¹' ({zFixedAsRandom (valuesProjection (fixSet_image_fixed_subset M' Z hZ_obs hZ_fixed) s')} : Set (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω))) := by classical let F := M'.fillZrW Z hZ_obs hZ_fixed W s' let ζ_s : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) := zFixedAsRandom (valuesProjection (fixSet_image_fixed_subset M' Z hZ_obs hZ_fixed) s') ext c constructor · rintro ⟨w, hwA, rfl⟩ refine ⟨?_, ?_⟩ · simp only [Set.mem_preimage] have : valuesProjection (Finset.subset_union_right : W ⊆ _) (F w) = w := by funext ⟨v, hv⟩ simp only [valuesProjection, F, fillZrW] by_cases hvA : v ∈ Z.image SWIGNode.random · exfalso exact Finset.disjoint_left.mp hDisj_ZrW hvA hv · rw [valuesUnionMk_apply_right _ _ _ hvA] rw [this] exact hwA · simp only [Set.mem_preimage, Set.mem_singleton_iff] funext ⟨v, hv⟩ simp only [valuesProjection, fillZrW] rw [valuesUnionMk_apply_left _ _ hv] · rintro ⟨hW_mem, hZr_mem⟩ simp only [Set.mem_preimage] at hW_mem simp only [Set.mem_preimage, Set.mem_singleton_iff] at hZr_mem refine ⟨valuesProjection (Finset.subset_union_right : W ⊆ _) c, hW_mem, ?_⟩ funext ⟨v, hv⟩ simp only [fillZrW] rcases Finset.mem_union.mp hv with hZrV | hWV · rw [valuesUnionMk_apply_left _ _ hZrV] have := congrFun hZr_mem ⟨v, hZrV⟩ simp only [valuesProjection] at this exact this.symm · by_cases hZrV' : v ∈ Z.image SWIGNode.random · rw [valuesUnionMk_apply_left _ _ hZrV'] have := congrFun hZr_mem ⟨v, hZrV'⟩ simp only [valuesProjection] at this exact this.symm · rw [valuesUnionMk_apply_right _ _ _ hZrV'] simp only [valuesProjection] -
fillZrW_injectivelemma — fillZrW Z _ _ W s' is injective when Z.image .random and W are disjoint.hypothesesM' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhDisj_ZrW :Disjoint (Z.image SWIGNode.random) Ws' :(M'.fixSet Z hZ_obs hZ_fixed).FixedValuesconclusionInjective (M'.fillZrW Z hZ_obs hZ_fixed W s')Proof (Lean source)
lemma fillZrW_injective (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)) (hDisj_ZrW : Disjoint (Z.image SWIGNode.random) W) (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) : Injective (M'.fillZrW Z hZ_obs hZ_fixed W s') := by classical intro w₁ w₂ h funext ⟨v, hv⟩ -- Project both sides of `h` to the W-coordinate v. have h_in : v ∈ Z.image SWIGNode.random ∪ W := Finset.subset_union_right hv have hvNotZr : v ∉ Z.image SWIGNode.random := fun hvZr => Finset.disjoint_left.mp hDisj_ZrW hvZr hv have hcoord := congrFun h ⟨v, h_in⟩ simp only [fillZrW] at hcoord rw [valuesUnionMk_apply_right _ _ h_in hvNotZr, valuesUnionMk_apply_right _ _ h_in hvNotZr] at hcoord exact hcoord -
measurableSet_fillZrW_imagelemma — A measurable W-event has a measurable image under fillZrW.hypothesesM' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhDisj_ZrW :Disjoint (Z.image SWIGNode.random) Ws' :(M'.fixSet Z hZ_obs hZ_fixed).FixedValueshA :conclusionMeasurableSet ((M'.fillZrW Z hZ_obs hZ_fixed W s') '' A)Proof (Lean source)
lemma measurableSet_fillZrW_image (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)) (hDisj_ZrW : Disjoint (Z.image SWIGNode.random) W) [MeasurableSingletonClass (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))] (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) {A : Set (ValuesOn W (swigΩ Ω))} (hA : MeasurableSet A) : MeasurableSet ((M'.fillZrW Z hZ_obs hZ_fixed W s') '' A) := by classical let ζ_s : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) := zFixedAsRandom (valuesProjection (fixSet_image_fixed_subset M' Z hZ_obs hZ_fixed) s') by_cases hW : Nonempty (ValuesOn W (swigΩ Ω)) · obtain ⟨w₀⟩ := hW -- The Zr-singleton `{ζ_s}` is measurable (pulled back from the -- measurable singleton in `ValuesOn (Zr ∪ W)`). have hSingZr : MeasurableSet ({ζ_s} : Set (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω))) := by have hmeas : Measurable (fun ζ : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) => valuesUnionMk ζ w₀) := by refine measurable_pi_iff.mpr ?_ rintro ⟨v, hv⟩ by_cases hvZ : v ∈ Z.image SWIGNode.random · have h_eq : (fun ζ : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) => valuesUnionMk ζ w₀ ⟨v, hv⟩) = (fun ζ => ζ ⟨v, hvZ⟩) := funext fun _ => valuesUnionMk_apply_left _ _ hvZ rw [h_eq] exact measurable_pi_apply _ · have hvW : v ∈ W := (Finset.mem_union.mp hv).resolve_left hvZ have h_eq : (fun ζ : ValuesOn (Z.image SWIGNode.random) (swigΩ Ω) => valuesUnionMk ζ w₀ ⟨v, hv⟩) = (fun _ => w₀ ⟨v, hvW⟩) := funext fun _ => valuesUnionMk_apply_right _ _ hv hvZ rw [h_eq] exact measurable_const have h_pre : ({ζ_s} : Set (ValuesOn (Z.image SWIGNode.random) (swigΩ Ω))) = (fun ζ => valuesUnionMk ζ w₀)⁻¹' ({valuesUnionMk ζ_s w₀} : Set (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))) := by ext ζ simp only [Set.mem_singleton_iff, Set.mem_preimage] refine ⟨fun h => by rw [h], fun h => ?_⟩ funext ⟨v, hv⟩ have hv_union : v ∈ Z.image SWIGNode.random ∪ W := subset_union_left hv have h_coord := congrFun h ⟨v, hv_union⟩ rw [valuesUnionMk_apply_left _ _ hv, valuesUnionMk_apply_left _ _ hv] at h_coord exact h_coord rw [h_pre] exact hmeas (measurableSet_singleton _) rw [fillZrW_image_eq M' Z hZ_obs hZ_fixed W hDisj_ZrW s' A] refine MeasurableSet.inter ?_ ?_ · exact (measurable_valuesProjection _) hA · exact (measurable_valuesProjection _) hSingZr · -- `ValuesOn W` empty: A = ∅, so F '' A = ∅. have hA_empty : A = ∅ := by ext w exact ⟨fun _ => (hW ⟨w⟩).elim, fun h => h.elim⟩ rw [hA_empty, Set.image_empty] exact MeasurableSet.empty -
measurableEmbedding_fillZrWlemma — fillZrW Z _ _ W s' is a MeasurableEmbedding when Z.image .random and W are disjoint.hypothesesM' :SCM N ΩZ :Finset NhZ_obs :∀ D ∈ Z, SWIGNode.random D ∈ M'.observedhZ_fixed :∀ D ∈ Z, SWIGNode.fixed D ∉ M'.fixedhDisj_ZrW :Disjoint (Z.image SWIGNode.random) Ws' :(M'.fixSet Z hZ_obs hZ_fixed).FixedValuesconclusionMeasurableEmbedding (M'.fillZrW Z hZ_obs hZ_fixed W s')Proof (Lean source)
lemma measurableEmbedding_fillZrW (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)) (hDisj_ZrW : Disjoint (Z.image SWIGNode.random) W) [MeasurableSingletonClass (ValuesOn (Z.image SWIGNode.random ∪ W) (swigΩ Ω))] (s' : (M'.fixSet Z hZ_obs hZ_fixed).FixedValues) : MeasurableEmbedding (M'.fillZrW Z hZ_obs hZ_fixed W s') := { injective := fillZrW_injective M' Z hZ_obs hZ_fixed W hDisj_ZrW s' measurable := measurable_fillZrW M' Z hZ_obs hZ_fixed W s' measurableSet_image' := fun _ hA => measurableSet_fillZrW_image M' Z hZ_obs hZ_fixed W hDisj_ZrW s' hA }