Discovery.Invariant­Prediction.Helpers

Measure-theoretic and structural helper lemmas for invariant prediction, especially target-mechanism factorization and environment-invariance arguments.

Mechanism­Factor 6 core · 15 supporting This file isolates the measure-theoretic and structural helper facts used by EnvFamily.mechanism_invariant: the target mechanism factors through its observed parents, latent parents, and an explicit fixed-parent value ar ★ condDistrib_eq_mechanismKernel_of_indep★ condDistrib_target_eq_mechanismKernel★ mechanismKernel_cf_env_eq

Mechanism-factor helpers for invariant prediction

This file isolates the measure-theoretic and structural helper facts used by EnvFamily.mechanism_invariant: the target mechanism factors through its observed parents, latent parents, and an explicit fixed-parent value argument. This parameterized fixed-parent kernel supports comparing environments without requiring their fixed-parent assignments to agree.

The main ingredients are:

* paLat and paLat_eq, the latent parents of the target and their environment-independence; * mechanismFun and mechanismFunCf, the target structural function as a map of observed, latent, and fixed parent values; * condDistrib_eq_mechanismKernel_of_indep, the abstract conditional-law factorization under independence of latent noise and predictors; * condDistrib_target_eq_mechanismKernel, the per-environment specialization to the target conditional law; and * mechanismKernel_cf_env_eq, the cross-environment equality of the fixed-parent-parameterized mechanism kernels.

def paLat reviewed
Causalean.Discovery.InvariantPrediction.EnvFamily

The latent parents of the target in environment i.

Definition (Lean source)
def paLat (F : EnvFamily N Ω ι) (i : ι) : Finset (SWIGNode N) := (F.M i).dag.parents F.yNode ∩ (F.M i).unobserved
Causalean.Discovery.InvariantPrediction.EnvFamily.paLat · Causalean/Discovery/InvariantPrediction/Helpers/MechanismFactor.lean:47 · uses EnvFamily , SWIGNode
def mechanismFun reviewed
Causalean.Discovery.InvariantPrediction.EnvFamily

The target mechanism as a measurable map of observed and latent parents.

Definition (Lean source)
noncomputable def mechanismFun (F : EnvFamily N Ω ι) (i₀ i : ι) : ValuesOn (F.paObs i₀) (swigΩ Ω) × ValuesOn (F.paLat i) (swigΩ Ω) → ValuesOn ({F.yNode} : Finset (SWIGNode N)) (swigΩ Ω) := fun p w => let val : swigΩ Ω F.yNode := (F.M i).structFun ⟨F.yNode, F.hYobs i⟩ (fun d : {d // d ∈ (F.M i).dag.parents F.yNode} => if hlat : d.val ∈ (F.M i).unobserved then p.2 ⟨d.val, Finset.mem_inter.mpr ⟨d.property, hlat⟩⟩ else if hfix : d.val ∈ (F.M i).fixed then (F.s i) ⟨d.val, hfix⟩ else have hedge : (F.M i).dag.edge d.val F.yNode := (F.M i).dag.mem_parents.mp d.property have hobs : d.val ∈ (F.M i).observed := by rcases Finset.mem_union.mp ((F.M i).dag_edges_classified d.val F.yNode hedge).1 with hfo | hu · rcases Finset.mem_union.mp hfo with hf | ho · exact absurd hf hfix · exact ho · exact absurd hu hlat p.1 ⟨d.val, by rw [← F.paObs_eq i i₀] exact Finset.mem_inter.mpr ⟨d.property, hobs⟩⟩) cast (congrArg (swigΩ Ω) (Finset.mem_singleton.mp w.property).symm) val
def mechanismFunCf reviewed
Causalean.Discovery.InvariantPrediction.EnvFamily

The target mechanism as a measurable map of observed and latent parents, parameterized by an explicit fixed-parent value argument cf. Identical to mechanismFun i₀ i except that the fixed-parent branch reads its value from cf instead of from the environment's intervention assignment s i. This lets the mechanism factor be keyed on paFix-values (used by the redesigned Invariant witness κ), so cross-environment agreement no longer needs the environments to assign the same value to a fixed parent.

Definition (Lean source)
noncomputable def mechanismFunCf (F : EnvFamily N Ω ι) (i₀ i : ι) (cf : ValuesOn (F.paFix i) (swigΩ Ω)) : ValuesOn (F.paObs i₀) (swigΩ Ω) × ValuesOn (F.paLat i) (swigΩ Ω) → ValuesOn ({F.yNode} : Finset (SWIGNode N)) (swigΩ Ω) := fun p w => let val : swigΩ Ω F.yNode := (F.M i).structFun ⟨F.yNode, F.hYobs i⟩ (fun d : {d // d ∈ (F.M i).dag.parents F.yNode} => if hlat : d.val ∈ (F.M i).unobserved then p.2 ⟨d.val, Finset.mem_inter.mpr ⟨d.property, hlat⟩⟩ else if hfix : d.val ∈ (F.M i).fixed then cf ⟨d.val, Finset.mem_inter.mpr ⟨d.property, hfix⟩⟩ else have hedge : (F.M i).dag.edge d.val F.yNode := (F.M i).dag.mem_parents.mp d.property have hobs : d.val ∈ (F.M i).observed := by rcases Finset.mem_union.mp ((F.M i).dag_edges_classified d.val F.yNode hedge).1 with hfo | hu · rcases Finset.mem_union.mp hfo with hf | ho · exact absurd hf hfix · exact ho · exact absurd hu hlat p.1 ⟨d.val, by rw [← F.paObs_eq i i₀] exact Finset.mem_inter.mpr ⟨d.property, hobs⟩⟩) cast (congrArg (swigΩ Ω) (Finset.mem_singleton.mp w.property).symm) val
theorem condDistrib_eq_mechanismKernel_of_indep reviewed
Causalean.Discovery.InvariantPrediction.EnvFamily

Let XX, LL, and YY be measurable random elements of a probability space, with YY's value space standard Borel and nonempty, and let ΦΦ be a measurable map such that YY equals Φ(X,L)Φ(X,L) almost everywhere. If LL is independent of XX, then the conditional distribution of YY given XX agrees, for almost every pushed-forward value of XX, with the mechanism kernel obtained by pushing the law of LL forward through ΦΦ paired with that value of XX.

Formal statement
X :
α → β
L :
α → γ
Y :
α → δ
Φ :
β × γ → δ
hX :
hL :
hY :
:
hind :
IndepFun L X μ
hYeq :
Y =ᵐ[μ] fun ω => Φ (X ω, L ω)
(fun x => condDistrib Y X μ x)
=ᵐ[μ.map X] mechanismKernel (μ.map L) Φ
Proof (Lean source)
theorem condDistrib_eq_mechanismKernel_of_indep {α β γ δ : Type*} [MeasurableSpace α] [MeasurableSpace β] [MeasurableSpace γ] [MeasurableSpace δ] [StandardBorelSpace δ] [Nonempty δ] (μ : Measure α) [IsProbabilityMeasure μ] {X : α → β} {L : α → γ} {Y : α → δ} {Φ : β × γ → δ} (hX : Measurable X) (hL : Measurable L) (hY : Measurable Y) (hΦ : Measurable Φ) (hind : IndepFun L X μ) (hYeq : Y =ᵐ[μ] fun ω => Φ (X ω, L ω)) : (fun x => condDistrib Y X μ x) =ᵐ[μ.map X] mechanismKernel (μ.map L) Φ := by classical haveI : IsFiniteMeasure μ := inferInstance haveI : IsProbabilityMeasure (μ.map L) := Measure.isProbabilityMeasure_map hL.aemeasurable haveI : IsMarkovKernel (mechanismKernel (μ.map L) Φ) := instIsMarkovKernelMechanismKernel (μ.map L) hΦ have hXL : Measurable (fun ω => (X ω, L ω)) := hX.prodMk hL have hgraph : Measurable (fun p : β × γ => (p.1, Φ p)) := measurable_fst.prodMk hΦ have hprod : μ.map (fun ω => (X ω, L ω)) = (μ.map X).prod (μ.map L) := (indepFun_iff_map_prod_eq_prod_map_map hX.aemeasurable hL.aemeasurable).mp hind.symm have hpair_congr : (fun ω => (X ω, Y ω)) =ᵐ[μ] fun ω => (X ω, Φ (X ω, L ω)) := by filter_upwards [hYeq] with ω hω rw [hω] refine condDistrib_ae_eq_of_measure_eq_compProd X hY.aemeasurable ?_ calc μ.map (fun ω => (X ω, Y ω)) = μ.map (fun ω => (X ω, Φ (X ω, L ω))) := Measure.map_congr hpair_congr _ = Measure.map (fun p : β × γ => (p.1, Φ p)) (μ.map (fun ω => (X ω, L ω))) := by rw [Measure.map_map hgraph hXL] rfl _ = Measure.map (fun p : β × γ => (p.1, Φ p)) ((μ.map X).prod (μ.map L)) := by rw [hprod] _ = (μ.map X).compProd (mechanismKernel (μ.map L) Φ) := map_graph_prod_eq_compProd (μ.map X) (μ.map L) hΦ
Causalean.Discovery.InvariantPrediction.EnvFamily.condDistrib_eq_mechanismKernel_of_indep · Causalean/Discovery/InvariantPrediction/Helpers/MechanismFactor.lean:308 · uses mechanismKernel
theorem condDistrib_target_eq_mechanismKernel reviewed
Causalean.Discovery.InvariantPrediction.EnvFamily

For an invariant-prediction environment family and a reference index i₀ together with an environment i, in environment i the conditional law of the target given its observed parents, under the joint kernel restricted to that environment, agrees with the mechanism kernel formed by pushing the latent-parent law of environment i forward through the target's structural mechanism function, paired with the parent value.

Formal statement
F :
EnvFamily N Ω ι
i₀ i :
ι
(by classical haveI : StandardBorelSpace (ValuesOn ({F.yNode} : Finset (SWIGNode N)) (swigΩ Ω)) := F.borelTarget haveI : Nonempty (ValuesOn ({F.yNode} : Finset (SWIGNode N)) (swigΩ Ω)) := F.neTarget let hYrv : ({F.yNode} : Finset (SWIGNode N)) ⊆ (F.M i).randomVars := by intro w hw rw [mem_singleton] at hw subst hw exact mem_union_left _ (F.hYobs i) let hPrv : F.paObs i₀ ⊆ (F.M i).randomVars := by rw [F.paObs_eq i₀ i] exact (inter_subset_right).trans (by change (F.M i).observed ⊆ (F.M i).observed ∪ (F.M i).unobserved exact subset_union_left) let hLrv : F.paLat i ⊆ (F.M i).randomVars := by exact (inter_subset_right).trans (by change (F.M i).unobserved ⊆ (F.M i).observed ∪ (F.M i).unobserved exact subset_union_right) exact (fun c => condDistrib (valuesProjection hYrv) (valuesProjection hPrv) ((F.M i).jointKernel (F.s i)) c) =ᵐ[((F.M i).jointKernel (F.s i)).map (valuesProjection hPrv)] mechanismKernel (((F.M i).jointKernel (F.s i)).map (valuesProjection hLrv)) (F.mechanismFun i₀ i))
Proof (Lean source)
theorem condDistrib_target_eq_mechanismKernel (F : EnvFamily N Ω ι) (i₀ i : ι) : (by classical haveI : StandardBorelSpace (ValuesOn ({F.yNode} : Finset (SWIGNode N)) (swigΩ Ω)) := F.borelTarget haveI : Nonempty (ValuesOn ({F.yNode} : Finset (SWIGNode N)) (swigΩ Ω)) := F.neTarget let hYrv : ({F.yNode} : Finset (SWIGNode N)) ⊆ (F.M i).randomVars := by intro w hw rw [mem_singleton] at hw subst hw exact mem_union_left _ (F.hYobs i) let hPrv : F.paObs i₀ ⊆ (F.M i).randomVars := by rw [F.paObs_eq i₀ i] exact (inter_subset_right).trans (by change (F.M i).observed ⊆ (F.M i).observed ∪ (F.M i).unobserved exact subset_union_left) let hLrv : F.paLat i ⊆ (F.M i).randomVars := by exact (inter_subset_right).trans (by change (F.M i).unobserved ⊆ (F.M i).observed ∪ (F.M i).unobserved exact subset_union_right) exact (fun c => condDistrib (valuesProjection hYrv) (valuesProjection hPrv) ((F.M i).jointKernel (F.s i)) c) =ᵐ[((F.M i).jointKernel (F.s i)).map (valuesProjection hPrv)] mechanismKernel (((F.M i).jointKernel (F.s i)).map (valuesProjection hLrv)) (F.mechanismFun i₀ i)) := by classical dsimp only haveI : StandardBorelSpace (ValuesOn ({F.yNode} : Finset (SWIGNode N)) (swigΩ Ω)) := F.borelTarget haveI : Nonempty (ValuesOn ({F.yNode} : Finset (SWIGNode N)) (swigΩ Ω)) := F.neTarget have hYrv : ({F.yNode} : Finset (SWIGNode N)) ⊆ (F.M i).randomVars := by intro w hw rw [mem_singleton] at hw subst hw exact mem_union_left _ (F.hYobs i) have hPrv : F.paObs i₀ ⊆ (F.M i).randomVars := by rw [F.paObs_eq i₀ i] exact (inter_subset_right).trans (by change (F.M i).observed ⊆ (F.M i).observed ∪ (F.M i).unobserved exact subset_union_left) have hLrv : F.paLat i ⊆ (F.M i).randomVars := by exact (inter_subset_right).trans (by show (F.M i).unobserved ⊆ (F.M i).observed ∪ (F.M i).unobserved exact subset_union_right) have hObsExo : (F.M i).dag.parents F.yNode ∩ (F.M i).observed ⊆ (F.M i).randomVars := (inter_subset_right).trans (by show (F.M i).observed ⊆ (F.M i).observed ∪ (F.M i).unobserved exact subset_union_left) have hLatExo : (F.M i).dag.parents F.yNode ∩ (F.M i).unobserved ⊆ (F.M i).randomVars := (inter_subset_right).trans (by show (F.M i).unobserved ⊆ (F.M i).observed ∪ (F.M i).unobserved exact subset_union_right) let e := valuesEquivOfEq (Ω := swigΩ Ω) (F.paObs_eq i i₀) have hOcomp : e ∘ (valuesProjection hObsExo : (F.M i).RandomValuesValuesOn (F.paObs i) (swigΩ Ω)) = (valuesProjection hPrv : (F.M i).RandomValuesValuesOn (F.paObs i₀) (swigΩ Ω)) := by funext ξ x rfl have hind : IndepFun (valuesProjection hLrv) (valuesProjection hPrv) ((F.M i).jointKernel (F.s i)) := by have h0 := (F.hExo i).comp (φ := id) (ψ := e) measurable_id e.measurable change IndepFun (id ∘ valuesProjection hLatExo) (e ∘ valuesProjection hObsExo) ((F.M i).jointKernel (F.s i)) at h0 rw [hOcomp] at h0 exact h0 have hEvalMeas : Measurable (fun ℓ : (F.M i).LatentValues => (F.M i).evalMap (F.s i) ℓ) := by have : (fun ℓ : (F.M i).LatentValues => (F.M i).evalMap (F.s i) ℓ) = fun ℓ => uncurry (F.M i).evalMap (F.s i, ℓ) := rfl rw [this] exact (F.M i).evalMap_measurable.comp (prodMk measurable_const measurable_id) have hpair : ((F.M i).jointKernel (F.s i)).map (fun ω => (valuesProjection hPrv ω, valuesProjection hYrv ω)) = ((F.M i).jointKernel (F.s i)).map (fun ω => (valuesProjection hPrv ω, F.mechanismFun i₀ i (valuesProjection hPrv ω, valuesProjection hLrv ω))) := by rw [SCM.jointKernel_apply_eq] rw [Measure.map_map ((measurable_valuesProjection hPrv).prodMk (measurable_valuesProjection hYrv)) hEvalMeas] have hRightMeas : Measurable (fun ω => (valuesProjection hPrv ω, F.mechanismFun i₀ i (valuesProjection hPrv ω, valuesProjection hLrv ω))) := (measurable_valuesProjection hPrv).prodMk ((F.measurable_mechanismFun i₀ i).comp ((measurable_valuesProjection hPrv).prodMk (measurable_valuesProjection hLrv))) rw [Measure.map_map hRightMeas hEvalMeas] congr 1 funext ℓ dsimp rw [F.target_projection_evalMap_eq_mechanismFun i₀ i ℓ] exact condDistrib_eq_mechanismKernel_of_indep_of_pair_map ((F.M i).jointKernel (F.s i)) (measurable_valuesProjection hPrv) (measurable_valuesProjection hLrv) (measurable_valuesProjection hYrv) (F.measurable_mechanismFun i₀ i) hind hpair
theorem mechanismKernel_cf_env_eq reviewed
Causalean.Discovery.InvariantPrediction.EnvFamily

Fix an environment family, a base environment i₀, two environments i and j, and a fixed-parent value assignment cf for environment i. If the latent parents of the target in environment i are among its random variables and likewise for environment j, then the target-mechanism kernel built from environment i at cf equals the target-mechanism kernel built from environment j at the value obtained by transporting cf through the shared fixed-parent set.

Formal statement
F :
EnvFamily N Ω ι
i₀ i j :
ι
cf :
ValuesOn (F.paFix i) (swigΩ Ω)
hLrv :
F.paLat i ⊆ (F.M i).randomVars
hLrv' :
F.paLat j ⊆ (F.M j).randomVars
mechanismKernel (((F.M i).jointKernel (F.s i)).map (valuesProjection hLrv)) (F.mechanismFunCf i₀ i cf)
= mechanismKernel (((F.M j).jointKernel (F.s j)).map (valuesProjection hLrv')) (F.mechanismFunCf i₀ j (valuesProjection (le_of_eq (F.paFix_eq j i)) cf))
Proof (Lean source)
theorem mechanismKernel_cf_env_eq (F : EnvFamily N Ω ι) (i₀ i j : ι) (cf : ValuesOn (F.paFix i) (swigΩ Ω)) (hLrv : F.paLat i ⊆ (F.M i).randomVars) (hLrv' : F.paLat j ⊆ (F.M j).randomVars) : mechanismKernel (((F.M i).jointKernel (F.s i)).map (valuesProjection hLrv)) (F.mechanismFunCf i₀ i cf) = mechanismKernel (((F.M j).jointKernel (F.s j)).map (valuesProjection hLrv')) (F.mechanismFunCf i₀ j (valuesProjection (le_of_eq (F.paFix_eq j i)) cf)) := by classical apply ProbabilityTheory.Kernel.ext intro o rw [mechanismKernel_apply _ (F.measurable_mechanismFunCf i₀ i cf) o, mechanismKernel_apply _ (F.measurable_mechanismFunCf i₀ j _) o] let hLun : F.paLat i ⊆ (F.M i).unobserved := Finset.inter_subset_right let hLun' : F.paLat j ⊆ (F.M j).unobserved := Finset.inter_subset_right rw [F.jointKernel_map_paLat_eq_latentProduct_map i hLrv hLun, F.jointKernel_map_paLat_eq_latentProduct_map j hLrv' hLun'] have hSliceMeas : Measurable (fun l : ValuesOn (F.paLat i) (swigΩ Ω) => F.mechanismFunCf i₀ i cf (o, l)) := (F.measurable_mechanismFunCf i₀ i cf).comp (prodMk measurable_const measurable_id) have hSliceMeas' : Measurable (fun l : ValuesOn (F.paLat j) (swigΩ Ω) => F.mechanismFunCf i₀ j (valuesProjection (le_of_eq (F.paFix_eq j i)) cf) (o, l)) := (F.measurable_mechanismFunCf i₀ j _).comp (prodMk measurable_const measurable_id) rw [Measure.map_map hSliceMeas (measurable_valuesProjection hLun), Measure.map_map hSliceMeas' (measurable_valuesProjection hLun')] exact map_heq_transport (congrArg (fun S => ValuesOn S (swigΩ Ω)) (F.hUnobs i j)) (F.latentValues_measurableSpace_heq i j) (F.latentProduct_heq i j) <| by apply Function.hfunext (congrArg (fun S => ValuesOn S (swigΩ Ω)) (F.hUnobs i j)) intro l l' hl apply heq_of_eq funext w rcases w with ⟨w, hw⟩ have hwy : w = F.yNode := Finset.mem_singleton.mp hw subst hwy simp only [Function.comp_apply] unfold mechanismFunCf simp only apply F.structFun_yNode_apply_eq i j intro d hdi hdj by_cases hlat : d ∈ (F.M i).unobserved · have hlat' : d ∈ (F.M j).unobserved := by rw [← F.hUnobs i j] exact hlat simp only [hlat, hlat', dif_pos, valuesProjection] have hidx : (⟨d, hlat⟩ : {d // d ∈ (F.M i).unobserved}) ≍ (⟨d, hlat'⟩ : {d // d ∈ (F.M j).unobserved}) := by apply (Subtype.heq_iff_coe_eq (by intro x; rw [F.hUnobs i j])).mpr rfl have hval : HEq (l ⟨d, hlat⟩) (l' ⟨d, hlat'⟩) := by apply dcongr_heq hidx · intro u u' hu have huv : u.val = u'.val := by exact (Subtype.heq_iff_coe_eq (by intro x; rw [F.hUnobs i j])).mp hu rw [huv] · intro _ _ exact hl exact eq_of_heq hval · have hlat' : d ∉ (F.M j).unobserved := by intro h apply hlat rw [F.hUnobs i j] exact h simp only [hlat, hlat'] by_cases hfix : d ∈ (F.M i).fixed · have hfix' : d ∈ (F.M j).fixed := F.fixed_parent_mem_fixed_of_mem (Finset.mem_inter.mpr ⟨hdi, hfix⟩) simp only [dif_neg (not_false), dif_pos hfix, dif_pos hfix', valuesProjection] · have hfix' : d ∉ (F.M j).fixed := by intro h apply hfix exact F.fixed_parent_mem_fixed_of_mem (i := j) (j := i) (d := d) (Finset.mem_inter.mpr ⟨hdj, h⟩) simp only [hfix, hfix'] rfl
15 supporting declarations (lemmas, instances)