SCM.ID.Density

Density-based SCM identification tools: reference measures, observational chain-rule factorization, c-component density factors, and do-law marginal bridges.

Reference­Measure 6 core · 1 supporting A *reference measure family* assigns one σ-finite measure to every SWIG-node value space: the counting measure for a discrete node, Lebesgue measure for a continuous node, or any σ-finite choice. ★ ReferenceMeasures★ DominatedObs★ obsDensity★ withDensity_obsDensity_eq★ obsKernel_eq_of_obsDensity_ae_eq

Reference measure and joint observational density

A reference measure family assigns one σ-finite measure to every SWIG-node value space: the counting measure for a discrete node, Lebesgue measure for a continuous node, or any σ-finite choice. Its finite product over a node set is the joint reference measure, and a gSCM is dominated when its observational kernel is absolutely continuous with respect to that joint reference. In the dominated case the observational law has a joint density (Radon–Nikodym derivative), and the law is recovered from the density.

This is the foundation for the density-assisted c-component factorization: Tian's assembly step P(v) = ∏_C Q[C] is a commutative regrouping of scalar density factors, which has no kernel-composition analogue. The downstream ID theorems in this slice specialize these reference-measure definitions to finite node value spaces with measurable singleton sets and faithful finite-product references.

structure ReferenceMeasures reviewed
Causalean.SCM

A reference measure family assigns a measure on every random or fixed node's value space, required to be σ-finite.

Definition (Lean source)
Ω :
N → Type*
∀ n, MeasurableSpace (Ω n)
The reference measure on the value space of node `v`.
μ :
∀ v : SWIGNode N, Measure (swigΩ Ω v)
Each reference measure is σ-finite.
sigmaFinite :
∀ v, SigmaFinite (μ v)
Causalean.SCM.ReferenceMeasures · Causalean/SCM/ID/Density/ReferenceMeasure.lean:35
def jointRef reviewed
Causalean.SCM

The joint reference measure is the finite product of the per-node reference measures over a node set.

Definition (Lean source)
noncomputable def jointRef (ref : ReferenceMeasures Ω) (I : Finset (SWIGNode N)) : Measure (ValuesOn I (swigΩ Ω)) := pi (fun i : {i // i ∈ I} => ref.μ i.val)
def DominatedObs reviewed
Causalean.SCM

A structural causal model is dominated when each observational law is absolutely continuous with respect to the joint reference measure.

Definition (Lean source)
def DominatedObs (M : SCM N Ω) (ref : ReferenceMeasures Ω) : Prop := ∀ s : M.FixedValues, M.obsKernel s ≪ jointRef ref M.observed
def obsDensity reviewed
Causalean.SCM

The joint observational density is the Radon-Nikodym derivative of the observational law with respect to the observed-node reference product.

Definition (Lean source)
noncomputable def obsDensity (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) : ValuesOn M.observed (swigΩ Ω) → ENNReal := (M.obsKernel s).rnDeriv (jointRef ref M.observed)
theorem withDensity_obsDensity_eq reviewed
Causalean.SCM

In a structural causal model whose observational law is absolutely continuous with respect to the joint reference measure on the observed nodes, weighting that joint reference measure by the observational density recovers the observational law exactly.

Formal statement
M :
SCM N Ω
hdom :
s :
M.FixedValues
(jointRef ref M.observed).withDensity (M.obsDensity ref s) = M.obsKernel s
Proof (Lean source)
theorem withDensity_obsDensity_eq (M : SCM N Ω) (ref : ReferenceMeasures Ω) (hdom : DominatedObs M ref) (s : M.FixedValues) : (jointRef ref M.observed).withDensity (M.obsDensity ref s) = M.obsKernel s := by unfold obsDensity exact MeasureTheory.Measure.withDensity_rnDeriv_eq _ _ (hdom s)
theorem obsKernel_eq_of_obsDensity_ae_eq reviewed
Causalean.SCM

Within a model whose observational law is dominated by the joint reference measure, if the joint observational densities at two fixed-value slices agree almost everywhere with respect to that reference measure, then the two slices induce the same observational law.

Formal statement
M :
SCM N Ω
hdom :
s₁ s₂ :
M.FixedValues
hdens :
(M.obsDensity ref s₁) =ᵐ[jointRef ref M.observed] (M.obsDensity ref s₂)
M.obsKernel s₁ = M.obsKernel s₂
Proof (Lean source)
theorem obsKernel_eq_of_obsDensity_ae_eq (M : SCM N Ω) (ref : ReferenceMeasures Ω) (hdom : DominatedObs M ref) (s₁ s₂ : M.FixedValues) (hdens : (M.obsDensity ref s₁) =ᵐ[jointRef ref M.observed] (M.obsDensity ref s₂)) : M.obsKernel s₁ = M.obsKernel s₂ := by rw [← withDensity_obsDensity_eq M ref hdom s₁, ← withDensity_obsDensity_eq M ref hdom s₂, MeasureTheory.withDensity_congr_ae hdens]
1 supporting declaration (lemmas, instances)
Finite­Reference 3 core · 7 supporting When every node value space is finite with measurable singletons, the per-node reference measures in a σ-finite reference family are finite. ★ absolutelyContinuous_jointRef_of_faithful★ aemeasurable_fiber_rnDeriv_of_finite

Finite reference measures for discrete ID densities

When every node value space is finite with measurable singletons, the per-node reference measures in a σ-finite reference family are finite. Consequently the finite products jointRef ref I are finite as well. This file packages those instances and the simple measurability fact used by the finite/discrete chain-rule density proof.

def ReferenceFaithful reviewed
Causalean.SCM

A reference family is faithful when every single coordinate value has nonzero reference mass.

Definition (Lean source)
def ReferenceFaithful (ref : ReferenceMeasures Ω) : Prop := ∀ (v : SWIGNode N) (x : swigΩ Ω v), ref.μ v {x} ≠ 0
lemma absolutelyContinuous_jointRef_of_faithful reviewed
Causalean.SCM

Faithful references dominate. On a finite coordinate product indexed by a node set I, if the reference family ref is faithful — every single coordinate value carries nonzero reference mass, then every measure μ on that product is absolutely continuous with respect to the joint reference measure.

Formal statement
href :
I :
μ :
μ ≪ jointRef ref I
Proof (Lean source)
lemma aemeasurable_fiber_rnDeriv_of_finite reviewed
Causalean.SCM

For finite index types α and β, a joint measure μ on α × β, a measure ρ on β, and a Markov kernel κ from α to β, the fibre Radon-Nikodym derivative selector (κ p.1).rnDeriv ρ p.2 is almost-everywhere measurable with respect to μ.

Formal statement
μ :
Measure (α × β)
ρ :
κ :
Kernel α β
AEMeasurable (fun p : α × β => (κ p.1).rnDeriv ρ p.2) μ
Proof (Lean source)
lemma aemeasurable_fiber_rnDeriv_of_finite {α β : Type*} [MeasurableSpace α] [MeasurableSpace β] [Finite α] [Finite β] [MeasurableSingletonClass α] [MeasurableSingletonClass β] (μ : Measure (α × β)) (ρ : Measure β) (κ : Kernel α β) : AEMeasurable (fun p : α × β => (κ p.1).rnDeriv ρ p.2) μ := (measurable_of_finite (fun p : α × β => (κ p.1).rnDeriv ρ p.2)).aemeasurable
Causalean.SCM.aemeasurable_fiber_rnDeriv_of_finite · Causalean/SCM/ID/Density/FiniteReference.lean:129
7 supporting declarations (lemmas, instances)
Identify­Mass 10 core · 5 supporting This file contains the finite, mass-level coordinate operations used by the recursive ID recovery. ★ identifyMassRec_base★ identifyMassRec_hedge★ identifyMassRec_step

Mass-level IDENTIFY functionals

This file contains the finite, mass-level coordinate operations used by the recursive ID recovery. The graph helpers SWIGGraph.topoLinearOrder, SWIGGraph.nodesAt, SWIGGraph.nodeIndex, and SWIGGraph.prefixIn enumerate selected SWIG nodes in topological order. The mass operations SCM.marginalizeOn and SCM.extractDistrict implement the coordinate marginalization and district-ratio extraction steps. The recursion SCM.identifyMassRec then combines induced ancestral restriction, hedge detection, and district extraction, with simp equations for its base, hedge, and recursive branches.

def topoLinearOrder reviewed
Causalean.SWIGGraph

This order compares graph nodes by their topological position in the SWIG graph.

Definition (Lean source)
noncomputable def topoLinearOrder (G : SWIGGraph N) : LinearOrder (SWIGNode N) := LinearOrder.lift' G.dag.topoOrder G.dag.topoOrder_injective
Causalean.SWIGGraph.topoLinearOrder · Causalean/SCM/ID/Density/IdentifyMass.lean:34 · uses SWIGGraph , SWIGNode
def nodesAt reviewed
Causalean.SWIGGraph

This selector returns the node at a given position in a finite node set sorted by graph topological order.

Definition (Lean source)
noncomputable def nodesAt (G : SWIGGraph N) (D : Finset (SWIGNode N)) (i : Fin D.card) : {v // v ∈ D} := by classical letI := G.topoLinearOrder exact D.orderIsoOfFin rfl i
def nodeIndex reviewed
Causalean.SWIGGraph

This selector returns a node's position inside a finite node set sorted by graph topological order.

Definition (Lean source)
noncomputable def nodeIndex (G : SWIGGraph N) (D : Finset (SWIGNode N)) (v : {v // v ∈ D}) : Fin D.card := by classical letI := G.topoLinearOrder exact (D.orderIsoOfFin rfl).symm v
def prefixIn reviewed
Causalean.SWIGGraph

This finite set contains the first selected nodes in graph topological order.

Definition (Lean source)
noncomputable def prefixIn (G : SWIGGraph N) (D : Finset (SWIGNode N)) (n : ℕ) : Finset (SWIGNode N) := D.filter (fun v => if h : v ∈ D then (G.nodeIndex D ⟨v, h⟩).val < n else False)
def marginalizeOn reviewed
Causalean.SCM

Marginalize a full-observed mass function by summing over the coordinates in W and overriding those coordinates in the evaluation point.

Definition (Lean source)
noncomputable def marginalizeOn [∀ n, Fintype (Ω n)] (O W : Finset (SWIGNode N)) (hW : W ⊆ O) (q : ValuesOn O (swigΩ Ω) → ENNReal) : ValuesOn O (swigΩ Ω) → ENNReal := fun x => ∑ y : ValuesOn W (swigΩ Ω), q (overrideOn x y)
def extractDistrict reviewed
Causalean.SCM

Extract the district factor for C' from a mass function on A by multiplying adjacent prefix marginal ratios along the topological order of G'.

Definition (Lean source)
noncomputable def extractDistrict [∀ n, Fintype (Ω n)] (O : Finset (SWIGNode N)) (G' : SWIGGraph N) (A C' : Finset (SWIGNode N)) (hA : A ⊆ O) (q : ValuesOn O (swigΩ Ω) → ENNReal) : ValuesOn O (swigΩ Ω) → ENNReal := fun x => ∏ i ∈ Finset.univ.filter (fun i : Fin A.card => (G'.nodesAt A i).val ∈ C'), marginalizeOn O (A \ G'.prefixIn A (i.val + 1)) (fun _ hv => hA ((Finset.mem_sdiff.mp hv).1)) q x / marginalizeOn O (A \ G'.prefixIn A i.val) (fun _ hv => hA ((Finset.mem_sdiff.mp hv).1)) q x
def identifyMassRec reviewed
Causalean.SCM

The mass-level IDENTIFY recursion. Starting with a mass function for T, it recursively projects to the induced ancestral set of C, extracts the containing district there, and stops when the induced ancestral set is exactly C. The hedge branch A = T returns the current mass function; successful reachability proofs never use that branch.

Definition (Lean source)
noncomputable def identifyMassRec [∀ n, Fintype (Ω n)] (O : Finset (SWIGNode N)) (G : SWIGGraph N) : (T C : Finset (SWIGNode N)) → (hT : T ⊆ O) → (q : ValuesOn O (swigΩ Ω) → ENNReal) → ValuesOn O (swigΩ Ω) → ENNReal | T, C, hT, q => let A := ID.inducedAncestral G T C let hA : A ⊆ O := fun _ hv => hT (ID.inducedAncestral_subset_left G T C hv) if _hAC : A = C then marginalizeOn O (T \ C) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) q else if _hAT : A = T then q else let C₁ := ID.containingCComponent (G.induce A) C let hC₁ : C₁ ⊆ O := fun _ hv => hT (ID.inducedAncestral_subset_left G T C (ID.containingCComponent_induce_subset G A C hv)) identifyMassRec O G C₁ C hC₁ (extractDistrict O (G.induce A) A C₁ hA (marginalizeOn O (T \ A) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) q)) termination_by T _ _ _ => T.card decreasing_by classical have hAsubT : A ⊆ T := ID.inducedAncestral_subset_left G T C have hAssubT : A ⊂ T := Finset.ssubset_iff_subset_ne.mpr ⟨hAsubT, _hAT⟩ have hC₁subA : C₁ ⊆ A := ID.containingCComponent_induce_subset G A C exact Nat.lt_of_le_of_lt (Finset.card_le_card hC₁subA) (Finset.card_lt_card hAssubT)
theorem identifyMassRec_base reviewed
Causalean.SCM

For a target set T contained in the observed coordinates, if the graph-induced ancestral set of T relative to C already equals C, then the mass-level IDENTIFY recursion identifyMassRec on T stops immediately and returns the marginal of the input mass function q obtained by summing out the coordinates in T \ C.

Formal statement
∀ n, Fintype (Ω n)
M :
SCM N Ω
G :
T C :
hT :
T ⊆ M.observed
q :
ValuesOn M.observed (swigΩ Ω) → ENNReal
hAC :
ID.inducedAncestral G T C = C
identifyMassRec M.observed G T C hT q
= marginalizeOn M.observed (T \ C) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) q
Proof (Lean source)
@[simp] theorem identifyMassRec_base [∀ n, Fintype (Ω n)] (M : SCM N Ω) (G : SWIGGraph N) (T C : Finset (SWIGNode N)) (hT : T ⊆ M.observed) (q : ValuesOn M.observed (swigΩ Ω) → ENNReal) (hAC : ID.inducedAncestral G T C = C) : identifyMassRec M.observed G T C hT q = marginalizeOn M.observed (T \ C) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) q := by rw [identifyMassRec] simp [hAC]
theorem identifyMassRec_hedge reviewed
Causalean.SCM

For a target set T contained in the observed coordinates, if the graph-induced ancestral set of T relative to C does not equal C but it equals T itself — the hedge case, reached only after the base case has failed — then the recursion identifyMassRec on T returns the input mass function q unchanged.

Formal statement
∀ n, Fintype (Ω n)
M :
SCM N Ω
G :
T C :
hT :
T ⊆ M.observed
q :
ValuesOn M.observed (swigΩ Ω) → ENNReal
hAC :
ID.inducedAncestral G T C ≠ C
hAT :
ID.inducedAncestral G T C = T
identifyMassRec M.observed G T C hT q = q
Proof (Lean source)
@[simp] theorem identifyMassRec_hedge [∀ n, Fintype (Ω n)] (M : SCM N Ω) (G : SWIGGraph N) (T C : Finset (SWIGNode N)) (hT : T ⊆ M.observed) (q : ValuesOn M.observed (swigΩ Ω) → ENNReal) (hAC : ID.inducedAncestral G T C ≠ C) (hAT : ID.inducedAncestral G T C = T) : identifyMassRec M.observed G T C hT q = q := by have hTC : T ≠ C := by intro h exact hAC (hAT.trans h) rw [identifyMassRec] simp [hAT, hTC]
theorem identifyMassRec_step reviewed
Causalean.SCM

For a target set T contained in the observed coordinates, if the graph-induced ancestral set of T relative to C does not equal C and does not equal T either — i.e. neither the base nor the hedge case applies — then the recursion identifyMassRec on T unfolds one step: it extracts, from the mass function q marginalized onto the induced ancestral set, the district factor of the c-component of C inside that induced ancestral graph, and recurses on that district.

Formal statement
∀ n, Fintype (Ω n)
M :
SCM N Ω
G :
T C :
hT :
T ⊆ M.observed
q :
ValuesOn M.observed (swigΩ Ω) → ENNReal
hAC :
ID.inducedAncestral G T C ≠ C
hAT :
ID.inducedAncestral G T C ≠ T
identifyMassRec M.observed G T C hT q
= let A := ID.inducedAncestral G T C let hA : A ⊆ M.observed := fun _ hv => hT (ID.inducedAncestral_subset_left G T C hv) let C₁ := ID.containingCComponent (G.induce A) C let hC₁ : C₁ ⊆ M.observed := fun _ hv => hT (ID.inducedAncestral_subset_left G T C (ID.containingCComponent_induce_subset G A C hv)) identifyMassRec M.observed G C₁ C hC₁ (extractDistrict M.observed (G.induce A) A C₁ hA (marginalizeOn M.observed (T \ A) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) q))
Proof (Lean source)
@[simp] theorem identifyMassRec_step [∀ n, Fintype (Ω n)] (M : SCM N Ω) (G : SWIGGraph N) (T C : Finset (SWIGNode N)) (hT : T ⊆ M.observed) (q : ValuesOn M.observed (swigΩ Ω) → ENNReal) (hAC : ID.inducedAncestral G T C ≠ C) (hAT : ID.inducedAncestral G T C ≠ T) : identifyMassRec M.observed G T C hT q = let A := ID.inducedAncestral G T C let hA : A ⊆ M.observed := fun _ hv => hT (ID.inducedAncestral_subset_left G T C hv) let C₁ := ID.containingCComponent (G.induce A) C let hC₁ : C₁ ⊆ M.observed := fun _ hv => hT (ID.inducedAncestral_subset_left G T C (ID.containingCComponent_induce_subset G A C hv)) identifyMassRec M.observed G C₁ C hC₁ (extractDistrict M.observed (G.induce A) A C₁ hA (marginalizeOn M.observed (T \ A) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) q)) := by rw [identifyMassRec] simp [hAC, hAT]
5 supporting declarations (lemmas, instances)
Latent­Blocks 7 core · 9 supporting This file provides the local-consistency predicate used by the ID density factorization and the latent-block decomposition facts that make q-masses split across c-components. ★ latentBlock_pairwise_disjoint★ localConsistent_fixSet_iff★ evalMap_agree_iff_localConsistent

Latent-block factorization and local consistency

This file provides the local-consistency predicate used by the ID density factorization and the latent-block decomposition facts that make q-masses split across c-components. Local consistency says that an observed assignment agrees with the structural function at a node when parents are read from fixed values, the observed assignment, and a latent realization.

def prevFromObservedValues reviewed
Causalean.SCM

The recursive evaluator can read all earlier observed coordinates from a full observed assignment.

Definition (Lean source)
noncomputable def prevFromObservedValues (M : SCM N Ω) (x : ValuesOn M.observed (swigΩ Ω)) {n : ℕ} : ∀ m : ℕ, m < n → ∀ hm : m < M.observed.card, swigΩ Ω (M.observedAt ⟨m, hm⟩).val := fun m _ hm => x (M.observedAt ⟨m, hm⟩)
def latentBlock reviewed
Causalean.SCM

The latent variables with an edge into a candidate observed c-component.

Definition (Lean source)
noncomputable def latentBlock (M : SCM N Ω) (C : Finset (SWIGNode N)) : Finset (SWIGNode N) := M.unobserved.filter (fun u => ∃ v ∈ C, M.dag.edge u v)
lemma latentBlock_pairwise_disjoint reviewed
Causalean.SCM

If C is a full c-component of the causal model's SWIG graph and C' is likewise a full c-component, and C and C' are distinct, then their latent-parent blocks — the unobserved nodes with an edge into the component — are disjoint.

Formal statement
M :
SCM N Ω
C C' :
hC :
C ∈ M.toSWIGGraph.cComponentSet
hC' :
C' ∈ M.toSWIGGraph.cComponentSet
hne :
C ≠ C'
Disjoint (M.latentBlock C) (M.latentBlock C')
Proof (Lean source)
lemma latentBlock_pairwise_disjoint (M : SCM N Ω) {C C' : Finset (SWIGNode N)} (hC : C ∈ M.toSWIGGraph.cComponentSet) (hC' : C' ∈ M.toSWIGGraph.cComponentSet) (hne : C ≠ C') : Disjoint (M.latentBlock C) (M.latentBlock C') := by rw [Finset.disjoint_left] intro u huC huC' obtain ⟨hu, v, hvC, huv⟩ := by simpa [latentBlock] using (Finset.mem_filter.mp huC) obtain ⟨hu', w, hwC', huw⟩ := by simpa [latentBlock] using (Finset.mem_filter.mp huC') have hdisj := M.toSWIGGraph.cComponentSet_pairwise_disjoint hC hC' hne have hwNotC : w ∉ C := by intro hwC exact (Finset.disjoint_left.mp hdisj) hwC hwC' exact M.toSWIGGraph.no_shared_unobserved_parent_of_mem_cComponentSet_of_not_mem hC hvC hwNotC hu huv huw
def localConsistent reviewed
Causalean.SCM

v's mechanism, parents read locally from x/s/, reproduces x v.

Definition (Lean source)
noncomputable def localConsistent (M : SCM N Ω) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) (v : SWIGNode N) (hv : v ∈ M.observed) (ℓ : M.LatentValues) : Prop := let j := M.observedIndex ⟨v, hv⟩ (M.observedAt_observedIndex ⟨v, hv⟩) ▸ M.structFun (M.observedAt j) (fun w => M.parentMap s ℓ j.isLt (prevFromObservedValues M x) w) = x ⟨v, hv⟩
lemma localConsistent_fixSet_iff reviewed
Causalean.SCM

Consider an intervention on a node set W whose random copies are all observed and whose fixed copies are not already fixed in the base model, giving the intervened model M.fixSet W. Fix a node v that is not itself one of the intervened random copies and that is observed both in the intervened model and in the base model. If the intervened model's observed assignment x' agrees with the base assignment x on every base-observed coordinate, the base assignment records, at each intervened node, the same value that the intervened model's fixed values assign to the corresponding fixed coordinate, and the intervened model's fixed values sW project, via fixSetProj, onto the base fixed values s, then local consistency of the structural evaluation at v in the intervened model, under sW, x', and a latent realization , is equivalent to local consistency at v in the base model, under s, x, and the same .

Formal statement
M :
SCM N Ω
W :
hObs :
∀ D ∈ W, SWIGNode.random D ∈ M.observed
hFix :
∀ D ∈ W, SWIGNode.fixed D ∉ M.fixed
sW :
(M.fixSet W hObs hFix).FixedValues
s :
M.FixedValues
x' :
ValuesOn (M.fixSet W hObs hFix).observed (swigΩ Ω)
x :
ValuesOn M.observed (swigΩ Ω)
v :
hv' :
v ∈ (M.fixSet W hObs hFix).observed
hv :
v ∈ M.observed
hnot :
v ∉ W.image SWIGNode.random
hobsAgree :
∀ w (hw : w ∈ M.observed), x' ⟨w, by simpa [fixSet_observed] using hw⟩ = x ⟨w, hw⟩
hpin :
∀ D (hD : D ∈ W),
x ⟨SWIGNode.random D, hObs D hD⟩
= sW ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩
hproj :
M.fixSetProj W hObs hFix sW = s
:
M.LatentValues
(M.fixSet W hObs hFix).localConsistent sW x' v hv' ℓ ↔ M.localConsistent s x v hv ℓ
Proof (Lean source)
lemma localConsistent_fixSet_iff (M : SCM N Ω) (W : Finset N) (hObs : ∀ D ∈ W, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ W, SWIGNode.fixed D ∉ M.fixed) (sW : (M.fixSet W hObs hFix).FixedValues) (s : M.FixedValues) (x' : ValuesOn (M.fixSet W hObs hFix).observed (swigΩ Ω)) (x : ValuesOn M.observed (swigΩ Ω)) (v : SWIGNode N) (hv' : v ∈ (M.fixSet W hObs hFix).observed) (hv : v ∈ M.observed) (hnot : v ∉ W.image SWIGNode.random) (hobsAgree : ∀ w (hw : w ∈ M.observed), x' ⟨w, by simpa [fixSet_observed] using hw⟩ = x ⟨w, hw⟩) (hpin : ∀ D (hD : D ∈ W), x ⟨SWIGNode.random D, hObs D hD⟩ = sW ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩) (hproj : M.fixSetProj W hObs hFix sW = s) (ℓ : M.LatentValues) : (M.fixSet W hObs hFix).localConsistent sW x' v hv' ℓ ↔ M.localConsistent s x v hv ℓ := by rw [localConsistent_iff_structFun_dispatch (M.fixSet W hObs hFix) sW x' v hv' ℓ, localConsistent_iff_structFun_dispatch M s x v hv ℓ] rw [fixSet_structFun_apply] have _ : v ∉ W.image SWIGNode.random := hnot have hxv : x' ⟨v, hv'⟩ = x ⟨v, hv⟩ := by simpa [fixSet_observed] using hobsAgree v hv have hsf : M.structFun ⟨v, hv⟩ (fixMonoParentMap M.toSWIGGraph W hObs hFix v (fun w : {w // w ∈ (M.splitMono W hObs hFix).dag.parents v} => if huo : w.val ∈ (M.fixSet W hObs hFix).unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ (M.fixSet W hObs hFix).fixed then sW ⟨w.val, hfix⟩ else have hedge : (M.fixSet W hObs hFix).dag.edge w.val v := (M.fixSet W hObs hFix).dag.mem_parents.mp w.property have hobs : w.val ∈ (M.fixSet W hObs hFix).observed := by rcases Finset.mem_union.mp ((M.fixSet W hObs hFix).dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x' ⟨w.val, hobs⟩)) = M.structFun ⟨v, hv⟩ (fun w : {w // w ∈ M.dag.parents v} => if huo : w.val ∈ M.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M.fixed then s ⟨w.val, hfix⟩ else have hedge : M.dag.edge w.val v := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x ⟨w.val, hobs⟩) := by congr 1 funext w have hedgeM : M.dag.edge w.val v := M.dag.mem_parents.mp w.property obtain ⟨wVal, hwMem⟩ := w simp only at * cases wVal with | fixed d => have hdfix : SWIGNode.fixed d ∈ M.fixed := by by_contra hdf have hiso := M.fixed_outside_fixed_isolated d hdf have : v ∈ M.dag.children (SWIGNode.fixed d) := M.dag.mem_children.mpr hedgeM rw [hiso.2] at this exact (notMem_empty _) this have hdfix' : SWIGNode.fixed d ∈ (M.fixSet W hObs hFix).fixed := Finset.mem_union_left _ hdfix have hdnuo : SWIGNode.fixed d ∉ M.unobserved := by intro h obtain ⟨m, hm⟩ := M.unobserved_is_random _ h exact absurd hm (by simp) have hdnuo' : SWIGNode.fixed d ∉ (M.fixSet W hObs hFix).unobserved := by simpa [fixSet_unobserved] using hdnuo rw [fixMonoParentMap_apply_fixed M.toSWIGGraph W hObs hFix v _ d hwMem] simp only [Subtype.coe_mk] rw [dif_neg hdnuo', dif_pos hdfix', dif_neg hdnuo, dif_pos hdfix] simpa [fixSetProj, valuesProjection] using congrFun hproj (⟨SWIGNode.fixed d, hdfix⟩ : {w // w ∈ M.fixed}) | random u => by_cases hu : u ∈ W · have hru_obs : SWIGNode.random u ∈ M.observed := hObs u hu have hru_nuo : SWIGNode.random u ∉ M.unobserved := fun h => (Finset.disjoint_left.mp M.obs_unobs_disjoint hru_obs) h have hru_nfix : SWIGNode.random u ∉ M.fixed := by intro h obtain ⟨m, hm⟩ := M.fixed_is_fixed _ h exact absurd hm (by simp) have hfu : SWIGNode.fixed u ∈ (M.fixSet W hObs hFix).fixed := fixed_mem_fixSet M W hObs hFix hu have hfu_nuo : SWIGNode.fixed u ∉ (M.fixSet W hObs hFix).unobserved := by intro h obtain ⟨m, hm⟩ := (M.fixSet W hObs hFix).unobserved_is_random _ h exact absurd hm (by simp) rw [fixMonoParentMap_apply_random M.toSWIGGraph W hObs hFix v u hu _ hwMem] simp only [Subtype.coe_mk] rw [dif_neg hfu_nuo, dif_pos hfu, dif_neg hru_nuo, dif_neg hru_nfix] simpa using (hpin u hu).symm · have hru_nfix : SWIGNode.random u ∉ M.fixed := by intro h obtain ⟨m, hm⟩ := M.fixed_is_fixed _ h exact absurd hm (by simp) have hru_ndfix : SWIGNode.random u ∉ (M.fixSet W hObs hFix).fixed := by intro h obtain ⟨m, hm⟩ := (M.fixSet W hObs hFix).fixed_is_fixed _ h exact absurd hm (by simp) rw [fixMonoParentMap_apply_random_notMem M.toSWIGGraph W hObs hFix v _ u hu hwMem] simp only [Subtype.coe_mk] by_cases huo : SWIGNode.random u ∈ M.unobserved · have huo' : SWIGNode.random u ∈ (M.fixSet W hObs hFix).unobserved := by simpa [fixSet_unobserved] using huo rw [dif_pos huo', dif_pos huo] · have huo' : SWIGNode.random u ∉ (M.fixSet W hObs hFix).unobserved := by simpa [fixSet_unobserved] using huo rw [dif_neg huo', dif_neg huo, dif_neg hru_ndfix, dif_neg hru_nfix] have hru_obs : SWIGNode.random u ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedgeM).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hru_nfix · exact hob · exact absurd h2 huo simpa [fixSet_observed] using hobsAgree (SWIGNode.random u) hru_obs change (M.structFun ⟨v, hv⟩ (fixMonoParentMap M.toSWIGGraph W hObs hFix v (fun w : {w // w ∈ (M.splitMono W hObs hFix).dag.parents v} => if huo : w.val ∈ (M.fixSet W hObs hFix).unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ (M.fixSet W hObs hFix).fixed then sW ⟨w.val, hfix⟩ else have hedge : (M.fixSet W hObs hFix).dag.edge w.val v := (M.fixSet W hObs hFix).dag.mem_parents.mp w.property have hobs : w.val ∈ (M.fixSet W hObs hFix).observed := by rcases Finset.mem_union.mp ((M.fixSet W hObs hFix).dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x' ⟨w.val, hobs⟩)) = x' ⟨v, hv'⟩) ↔ (M.structFun ⟨v, hv⟩ (fun w : {w // w ∈ M.dag.parents v} => if huo : w.val ∈ M.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M.fixed then s ⟨w.val, hfix⟩ else have hedge : M.dag.edge w.val v := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x ⟨w.val, hobs⟩) = x ⟨v, hv⟩) rw [hsf, hxv]
def ObsParentClosed reviewed
Causalean.SCM

A finite set of observed nodes is closed under observed parents.

Definition (Lean source)
def ObsParentClosed (M : SCM N Ω) (P : Finset (SWIGNode N)) : Prop := P ⊆ M.observed ∧ ∀ v ∈ P, ∀ w ∈ M.observed, M.dag.edge w v → w ∈ P
theorem evalMap_agree_iff_localConsistent reviewed
Causalean.SCM

On a set P of observed nodes closed under taking observed parents (every observed parent of a member of P is itself in P), agreement of the structural evaluation evalMap with the recorded observed assignment x at every node of P is equivalent to pointwise local consistency of x against a fixed-value slice s and latent realization at every node of P.

Formal statement
M :
SCM N Ω
s :
M.FixedValues
P :
hP :
M.ObsParentClosed P
x :
ValuesOn M.observed (swigΩ Ω)
:
M.LatentValues
(∀ v (hv : v ∈ P), M.evalMap s ℓ ⟨v, mem_union_left _ (hP.1 hv)⟩ = x ⟨v, hP.1 hv⟩)
↔ ∀ v (hv : v ∈ P), M.localConsistent s x v (hP.1 hv) ℓ
Proof (Lean source)
theorem evalMap_agree_iff_localConsistent (M : SCM N Ω) (s : M.FixedValues) (P : Finset (SWIGNode N)) (hP : M.ObsParentClosed P) (x : ValuesOn M.observed (swigΩ Ω)) (ℓ : M.LatentValues) : (∀ v (hv : v ∈ P), M.evalMap s ℓ ⟨v, mem_union_left _ (hP.1 hv)⟩ = x ⟨v, hP.1 hv⟩) ↔ ∀ v (hv : v ∈ P), M.localConsistent s x v (hP.1 hv) ℓ := by constructor · intro hEval v hv exact (evalMap_eq_iff_localConsistent_of_observed_parent_agree M s x ℓ v (hP.1 hv) (by intro w hwObs hedge exact hEval w (hP.2 v hv w hwObs hedge))).mp (hEval v hv) · intro hLocal suffices hstr : ∀ (n : ℕ) (hn : n < M.observed.card), (M.observedAt ⟨n, hn⟩).val ∈ P → M.evalMap s ℓ ⟨(M.observedAt ⟨n, hn⟩).val, mem_union_left _ (M.observedAt ⟨n, hn⟩).property⟩ = x (M.observedAt ⟨n, hn⟩) by intro v hv have hidx := hstr (M.observedIndex ⟨v, hP.1 hv⟩).val (M.observedIndex ⟨v, hP.1 hv⟩).isLt (by have hsub := observedAt_observedIndex_subtype M (hP.1 hv) simpa [hsub] using hv) have hval : (M.observedAt (M.observedIndex ⟨v, hP.1 hv⟩)).val = v := M.observedAt_observedIndex ⟨v, hP.1 hv⟩ exact evalMap_eq_x_of_observedAt_eq M s x ℓ (M.observedIndex ⟨v, hP.1 hv⟩) (hP.1 hv) hval hidx intro n induction n using Nat.strongRecOn with | _ n ih => intro hn hvP let vobs : {v // v ∈ M.observed} := M.observedAt ⟨n, hn⟩ have hiff := evalMap_eq_iff_localConsistent_of_observed_parent_agree M s x ℓ vobs.val vobs.property (by intro w hwObs hedge have hwP : w ∈ P := hP.2 vobs.val hvP w hwObs hedge set j : Fin M.observed.card := M.observedIndex ⟨w, hwObs⟩ with hj have hlt : j.val < n := by rw [hj] exact M.observed_parent_index_lt hn hedge hwObs have hih := ih j.val hlt j.isLt (by have hsub : M.observedAt j = ⟨w, hwObs⟩ := by rw [hj] exact observedAt_observedIndex_subtype M hwObs simpa [hsub] using hwP) have hval : (M.observedAt j).val = w := by rw [hj] exact M.observedAt_observedIndex ⟨w, hwObs⟩ exact evalMap_eq_x_of_observedAt_eq M s x ℓ j hwObs hval hih) exact hiff.mpr (hLocal vobs.val hvP)
9 supporting declarations (lemmas, instances)
  • latentBlock_pairwise_disjoint_induce_components lemma — Distinct c-components of an induced SWIG have disjoint latent-parent blocks in the ambient SCM.
    M :
    SCM N Ω
    R :
    C C' :
    hC :
    C ∈ (M.toSWIGGraph.induce R).cComponentSet
    hC' :
    C' ∈ (M.toSWIGGraph.induce R).cComponentSet
    hne :
    C ≠ C'
    Disjoint (M.latentBlock C) (M.latentBlock C')
    Proof (Lean source)
    lemma latentBlock_pairwise_disjoint_induce_components (M : SCM N Ω) (R : Finset (SWIGNode N)) {C C' : Finset (SWIGNode N)} (hC : C ∈ (M.toSWIGGraph.induce R).cComponentSet) (hC' : C' ∈ (M.toSWIGGraph.induce R).cComponentSet) (hne : C ≠ C') : Disjoint (M.latentBlock C) (M.latentBlock C') := by classical rw [Finset.disjoint_left] intro u huC huC' obtain ⟨hu, v, hvC, huv⟩ := by simpa [latentBlock] using (Finset.mem_filter.mp huC) obtain ⟨_hu', w, hwC', huw⟩ := by simpa [latentBlock] using (Finset.mem_filter.mp huC') have hvIndObs : v ∈ (M.toSWIGGraph.induce R).observed := (M.toSWIGGraph.induce R).cComponentSet_subset_observed C hC hvC have hwIndObs : w ∈ (M.toSWIGGraph.induce R).observed := (M.toSWIGGraph.induce R).cComponentSet_subset_observed C' hC' hwC' have hvR : v ∈ R := by simpa [SWIGGraph.induce] using (Finset.mem_inter.mp hvIndObs).1 have hwR : w ∈ R := by simpa [SWIGGraph.induce] using (Finset.mem_inter.mp hwIndObs).1 have hsame := M.toSWIGGraph.induce_cComponentOf_eq_of_shared_unobserved_parent R hu hvR hwR huv huw have hvComp : (M.toSWIGGraph.induce R).cComponentOf v = C := (M.toSWIGGraph.induce R).cComponentOf_eq_of_mem_cComponentSet hC hvC have hwComp : (M.toSWIGGraph.induce R).cComponentOf w = C' := (M.toSWIGGraph.induce R).cComponentOf_eq_of_mem_cComponentSet hC' hwC' exact hne (hvComp ▸ hwComp ▸ hsame)
    Causalean.SCM.latentBlock_pairwise_disjoint_induce_components · Causalean/SCM/ID/Density/LatentBlocks.lean:64
  • latentBlock_pairwise_disjoint_fixSet_induce_components lemma — Do-model specialization of induced-component latent-block disjointness.
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    R :
    C C' :
    hC :
    C ∈ ((M.fixSet X hObs hFix).toSWIGGraph.induce R).cComponentSet
    hC' :
    C' ∈ ((M.fixSet X hObs hFix).toSWIGGraph.induce R).cComponentSet
    hne :
    C ≠ C'
    Disjoint ((M.fixSet X hObs hFix).latentBlock C) ((M.fixSet X hObs hFix).latentBlock C')
    Proof (Lean source)
    lemma latentBlock_pairwise_disjoint_fixSet_induce_components (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (R : Finset (SWIGNode N)) {C C' : Finset (SWIGNode N)} (hC : C ∈ ((M.fixSet X hObs hFix).toSWIGGraph.induce R).cComponentSet) (hC' : C' ∈ ((M.fixSet X hObs hFix).toSWIGGraph.induce R).cComponentSet) (hne : C ≠ C') : Disjoint ((M.fixSet X hObs hFix).latentBlock C) ((M.fixSet X hObs hFix).latentBlock C') := latentBlock_pairwise_disjoint_induce_components (M.fixSet X hObs hFix) R hC hC' hne
    Causalean.SCM.latentBlock_pairwise_disjoint_fixSet_induce_components · Causalean/SCM/ID/Density/LatentBlocks.lean:98
  • localConsistent_depends_only_on_block lemma — Local consistency at v depends only on the latent block of v's c-component.
    M :
    SCM N Ω
    s :
    M.FixedValues
    x :
    ValuesOn M.observed (swigΩ Ω)
    v :
    hv :
    v ∈ M.observed
    ℓ ℓ' :
    M.LatentValues
    hℓ :
    ∀ u (hu : u ∈ M.latentBlock (M.toSWIGGraph.cComponentOf v)),
    ℓ ⟨u, (Finset.mem_filter.mp hu).1⟩ = ℓ' ⟨u, (Finset.mem_filter.mp hu).1⟩
    M.localConsistent s x v hv ℓ ↔ M.localConsistent s x v hv ℓ'
    Proof (Lean source)
    lemma localConsistent_depends_only_on_block (M : SCM N Ω) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) (v : SWIGNode N) (hv : v ∈ M.observed) (ℓ ℓ' : M.LatentValues) (hℓ : ∀ u (hu : u ∈ M.latentBlock (M.toSWIGGraph.cComponentOf v)), ℓ ⟨u, (Finset.mem_filter.mp hu).1⟩ = ℓ' ⟨u, (Finset.mem_filter.mp hu).1⟩) : M.localConsistent s x v hv ℓ ↔ M.localConsistent s x v hv ℓ' := by unfold localConsistent set j : Fin M.observed.card := M.observedIndex ⟨v, hv⟩ with hj have hat : (M.observedAt j).val = v := by rw [hj] exact M.observedAt_observedIndex ⟨v, hv⟩ have hfun : M.structFun (M.observedAt j) (fun w => M.parentMap s ℓ j.isLt (prevFromObservedValues M x) w) = M.structFun (M.observedAt j) (fun w => M.parentMap s ℓ' j.isLt (prevFromObservedValues M x) w) := by congr 1 funext w by_cases huo : w.val ∈ M.unobserved · rw [parentMap_unobserved M s ℓ j.isLt _ w huo, parentMap_unobserved M s ℓ' j.isLt _ w huo] have hedge_v : M.dag.edge w.val v := by have hedge_at : M.dag.edge w.val (M.observedAt j).val := M.dag.mem_parents.mp w.property simpa [hat] using hedge_at have hvComp : v ∈ M.toSWIGGraph.cComponentOf v := M.toSWIGGraph.mem_cComponentOf_self (by simpa using hv) have huBlock : w.val ∈ M.latentBlock (M.toSWIGGraph.cComponentOf v) := by rw [latentBlock, mem_filter] exact ⟨huo, ⟨v, hvComp, hedge_v⟩⟩ exact hℓ w.val huBlock · by_cases hfix : w.val ∈ M.fixed · rw [parentMap_fixed M s ℓ j.isLt _ w hfix, parentMap_fixed M s ℓ' j.isLt _ w hfix] · have hedge : M.dag.edge w.val (M.observedAt j).val := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo rw [parentMap_observed M s ℓ j.isLt _ w hobs, parentMap_observed M s ℓ' j.isLt _ w hobs] subst j change ((M.observedAt_observedIndex ⟨v, hv⟩) ▸ M.structFun (M.observedAt (M.observedIndex ⟨v, hv⟩)) (fun w => M.parentMap s ℓ (M.observedIndex ⟨v, hv⟩).isLt (prevFromObservedValues M x) w) = x ⟨v, hv⟩) ↔ ((M.observedAt_observedIndex ⟨v, hv⟩) ▸ M.structFun (M.observedAt (M.observedIndex ⟨v, hv⟩)) (fun w => M.parentMap s ℓ' (M.observedIndex ⟨v, hv⟩).isLt (prevFromObservedValues M x) w) = x ⟨v, hv⟩) rw [hfun]
    Causalean.SCM.localConsistent_depends_only_on_block · Causalean/SCM/ID/Density/LatentBlocks.lean:124
  • observedAt_observedIndex_subtype lemma — Taking an observed node to its topological index and back recovers the same observed-node subtype value.
    M :
    SCM N Ω
    v :
    hv :
    v ∈ M.observed
    M.observedAt (M.observedIndex ⟨v, hv⟩) = ⟨v, hv⟩
    Proof (Lean source)
    lemma observedAt_observedIndex_subtype (M : SCM N Ω) {v : SWIGNode N} (hv : v ∈ M.observed) : M.observedAt (M.observedIndex ⟨v, hv⟩) = ⟨v, hv⟩ := Subtype.ext (M.observedAt_observedIndex ⟨v, hv⟩)
    Causalean.SCM.observedAt_observedIndex_subtype · Causalean/SCM/ID/Density/LatentBlocks.lean:188
  • prevFromObservedValues_apply_observed lemma
    M :
    SCM N Ω
    x :
    ValuesOn M.observed (swigΩ Ω)
    n :
    n < M.observed.card
    w :
    {w // w ∈ M.dag.parents (M.observedAt ⟨n, hn⟩).val}
    hobs :
    w.val ∈ M.observed
    hlt :
    (M.observedIndex ⟨w.val, hobs⟩).val < n
    (M.observedAt_observedIndex ⟨w.val, hobs⟩) ▸ prevFromObservedValues M x (M.observedIndex ⟨w.val, hobs⟩).val hlt (M.observedIndex ⟨w.val, hobs⟩).isLt
    = x ⟨w.val, hobs⟩
    Proof (Lean source)
    lemma prevFromObservedValues_apply_observed (M : SCM N Ω) (x : ValuesOn M.observed (swigΩ Ω)) {n : ℕ} {hn : n < M.observed.card} {w : {w // w ∈ M.dag.parents (M.observedAt ⟨n, hn⟩).val}} (hobs : w.val ∈ M.observed) (hlt : (M.observedIndex ⟨w.val, hobs⟩).val < n) : (M.observedAt_observedIndex ⟨w.val, hobs⟩) ▸ prevFromObservedValues M x (M.observedIndex ⟨w.val, hobs⟩).val hlt (M.observedIndex ⟨w.val, hobs⟩).isLt = x ⟨w.val, hobs⟩ := by unfold prevFromObservedValues set wobs : {v // v ∈ M.observed} := M.observedAt (M.observedIndex ⟨w.val, hobs⟩) have hsub : wobs = ⟨w.val, hobs⟩ := by change M.observedAt (M.observedIndex ⟨w.val, hobs⟩) = ⟨w.val, hobs⟩ exact observedAt_observedIndex_subtype M hobs change (Subtype.ext_iff.mp hsub) ▸ x wobs = x ⟨w.val, hobs⟩ clear_value wobs subst hsub rfl
    Causalean.SCM.prevFromObservedValues_apply_observed · Causalean/SCM/ID/Density/LatentBlocks.lean:195
  • parentMap_prevFromObservedValues_eq_dispatch lemma
    M :
    SCM N Ω
    s :
    M.FixedValues
    x :
    ValuesOn M.observed (swigΩ Ω)
    :
    M.LatentValues
    j :
    Fin M.observed.card
    w :
    {w // w ∈ M.dag.parents (M.observedAt j).val}
    M.parentMap s ℓ j.isLt (prevFromObservedValues M x) w
    = (if huo : w.val ∈ M.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M.fixed then s ⟨w.val, hfix⟩ else have hedge : M.dag.edge w.val (M.observedAt j).val := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x ⟨w.val, hobs⟩)
    Proof (Lean source)
    lemma parentMap_prevFromObservedValues_eq_dispatch (M : SCM N Ω) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) (ℓ : M.LatentValues) (j : Fin M.observed.card) (w : {w // w ∈ M.dag.parents (M.observedAt j).val}) : M.parentMap s ℓ j.isLt (prevFromObservedValues M x) w = (if huo : w.val ∈ M.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M.fixed then s ⟨w.val, hfix⟩ else have hedge : M.dag.edge w.val (M.observedAt j).val := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x ⟨w.val, hobs⟩) := by by_cases huo : w.val ∈ M.unobserved · rw [parentMap_unobserved M s ℓ j.isLt _ w huo, dif_pos huo] · rw [dif_neg huo] by_cases hfix : w.val ∈ M.fixed · rw [parentMap_fixed M s ℓ j.isLt _ w hfix, dif_pos hfix] · rw [dif_neg hfix] have hedge : M.dag.edge w.val (M.observedAt j).val := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo rw [parentMap_observed M s ℓ j.isLt _ w hobs] exact prevFromObservedValues_apply_observed M x hobs (M.observed_parent_index_lt j.isLt hedge hobs)
    Causalean.SCM.parentMap_prevFromObservedValues_eq_dispatch · Causalean/SCM/ID/Density/LatentBlocks.lean:216
  • localConsistent_iff_structFun_dispatch lemma
    M :
    SCM N Ω
    s :
    M.FixedValues
    x :
    ValuesOn M.observed (swigΩ Ω)
    v :
    hv :
    v ∈ M.observed
    :
    M.LatentValues
    M.localConsistent s x v hv ℓ
    ↔ M.structFun ⟨v, hv⟩ (fun w : {w // w ∈ M.dag.parents v} => if huo : w.val ∈ M.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M.fixed then s ⟨w.val, hfix⟩ else have hedge : M.dag.edge w.val v := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x ⟨w.val, hobs⟩) = x ⟨v, hv⟩
    Proof (Lean source)
    lemma localConsistent_iff_structFun_dispatch (M : SCM N Ω) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) (v : SWIGNode N) (hv : v ∈ M.observed) (ℓ : M.LatentValues) : M.localConsistent s x v hv ℓ ↔ M.structFun ⟨v, hv⟩ (fun w : {w // w ∈ M.dag.parents v} => if huo : w.val ∈ M.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M.fixed then s ⟨w.val, hfix⟩ else have hedge : M.dag.edge w.val v := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x ⟨w.val, hobs⟩) = x ⟨v, hv⟩ := by set j : Fin M.observed.card := M.observedIndex ⟨v, hv⟩ with hj set vobs : {v // v ∈ M.observed} := M.observedAt j with hvobs have hsub : vobs = ⟨v, hv⟩ := by rw [hvobs] rw [hj] exact observedAt_observedIndex_subtype M hv have hiff := localConsistent_iff_structFun_dispatch_at_observedAt M s x ℓ j change M.localConsistent s x vobs.val vobs.property ℓ ↔ M.structFun vobs (fun w : {w // w ∈ M.dag.parents vobs.val} => if huo : w.val ∈ M.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M.fixed then s ⟨w.val, hfix⟩ else have hedge : M.dag.edge w.val vobs.val := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x ⟨w.val, hobs⟩) = x vobs at hiff clear_value vobs subst hsub exact hiff
    Causalean.SCM.localConsistent_iff_structFun_dispatch · Causalean/SCM/ID/Density/LatentBlocks.lean:368
  • evalMap_eq_iff_localConsistent_of_observed_parent_agree lemma — When all observed parents agree with their assigned values, evaluation at an observed node equals its assignment exactly when the latent values are locally consistent.
    M :
    SCM N Ω
    s :
    M.FixedValues
    x :
    ValuesOn M.observed (swigΩ Ω)
    :
    M.LatentValues
    v :
    hv :
    v ∈ M.observed
    hprev :
    ∀ w (hw : w ∈ M.observed)
    if
    M.dag.edge w v
    then
    M.evalMap s ℓ ⟨w, mem_union_left _ hw⟩ = x ⟨w, hw⟩
    M.evalMap s ℓ ⟨v, mem_union_left _ hv⟩ = x ⟨v, hv⟩ ↔ M.localConsistent s x v hv ℓ
    Proof (Lean source)
    lemma evalMap_eq_iff_localConsistent_of_observed_parent_agree (M : SCM N Ω) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) (ℓ : M.LatentValues) (v : SWIGNode N) (hv : v ∈ M.observed) (hprev : ∀ w (hw : w ∈ M.observed), M.dag.edge w v → M.evalMap s ℓ ⟨w, mem_union_left _ hw⟩ = x ⟨w, hw⟩) : M.evalMap s ℓ ⟨v, mem_union_left _ hv⟩ = x ⟨v, hv⟩ ↔ M.localConsistent s x v hv ℓ := by rw [evalMap_observed_unfold M s ℓ ⟨v, hv⟩, localConsistent_iff_structFun_dispatch M s x v hv ℓ] have hfun : M.structFun ⟨v, hv⟩ (fun w : {w // w ∈ M.dag.parents v} => if huo : w.val ∈ M.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M.fixed then s ⟨w.val, hfix⟩ else have hedge : M.dag.edge w.val v := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo M.evalMap s ℓ ⟨w.val, mem_union_left _ hobs⟩) = M.structFun ⟨v, hv⟩ (fun w : {w // w ∈ M.dag.parents v} => if huo : w.val ∈ M.unobserved then ℓ ⟨w.val, huo⟩ else if hfix : w.val ∈ M.fixed then s ⟨w.val, hfix⟩ else have hedge : M.dag.edge w.val v := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo x ⟨w.val, hobs⟩) := by congr 1 funext w by_cases huo : w.val ∈ M.unobserved · rw [dif_pos huo, dif_pos huo] · rw [dif_neg huo, dif_neg huo] by_cases hfix : w.val ∈ M.fixed · rw [dif_pos hfix, dif_pos hfix] · rw [dif_neg hfix, dif_neg hfix] have hedge : M.dag.edge w.val v := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo exact hprev w.val hobs hedge rw [hfun]
    Causalean.SCM.evalMap_eq_iff_localConsistent_of_observed_parent_agree · Causalean/SCM/ID/Density/LatentBlocks.lean:416
  • evalMap_eq_x_of_observedAt_eq lemma — If structural evaluation at an indexed observed node equals its recorded value, then the same equality holds after replacing that node by any equal observed node.
    M :
    SCM N Ω
    s :
    M.FixedValues
    x :
    ValuesOn M.observed (swigΩ Ω)
    :
    M.LatentValues
    j :
    Fin M.observed.card
    v :
    hv :
    v ∈ M.observed
    hval :
    (M.observedAt j).val = v
    h :
    M.evalMap s ℓ ⟨(M.observedAt j).val, mem_union_left M.unobserved (M.observedAt j).property⟩
    = x (M.observedAt j)
    M.evalMap s ℓ ⟨v, mem_union_left _ hv⟩ = x ⟨v, hv⟩
    Proof (Lean source)
    lemma evalMap_eq_x_of_observedAt_eq (M : SCM N Ω) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) (ℓ : M.LatentValues) (j : Fin M.observed.card) {v : SWIGNode N} (hv : v ∈ M.observed) (hval : (M.observedAt j).val = v) (h : M.evalMap s ℓ ⟨(M.observedAt j).val, mem_union_left M.unobserved (M.observedAt j).property⟩ = x (M.observedAt j)) : M.evalMap s ℓ ⟨v, mem_union_left _ hv⟩ = x ⟨v, hv⟩ := by set vobs : {v // v ∈ M.observed} := M.observedAt j with hvobs have hsub : vobs = ⟨v, hv⟩ := by rw [hvobs] exact Subtype.ext hval change M.evalMap s ℓ ⟨vobs.val, mem_union_left M.unobserved vobs.property⟩ = x vobs at h clear_value vobs subst hsub exact h
    Causalean.SCM.evalMap_eq_x_of_observedAt_eq · Causalean/SCM/ID/Density/LatentBlocks.lean:474
Chain­Rule­Density 6 core · 20 supporting For a dominated structural causal model with σ-finite node reference measures, the joint observational density factors along the topological order of the observed nodes as a product of one-node conditional densities, ass ★ obsDensity_eq_qFactorDensityProduct

Observational chain-rule density

For a dominated structural causal model with σ-finite node reference measures, the joint observational density factors along the topological order of the observed nodes as a product of one-node conditional densities, assuming the stepwise fibre Radon--Nikodym data (fibre domination and a jointly measurable fibre derivative) is available. This is the density analogue of the kernel chain rule obsKernel_eq_qFactorProduct; unlike the kernel version it holds for continuous (Lebesgue-referenced) nodes, not just finite/discrete ones.

The right-hand side below is deliberately not a tautological copy of obsDensity: each factor is the Radon--Nikodym derivative of the one-node conditional kernel obsStepCondKernel against the corresponding one-node reference measure, evaluated at the prefix and coordinate read from the full observed assignment.

def obsStepCondDensity reviewed
Causalean.SCM

The one-node conditional density factor at an observed coordinate.

Definition (Lean source)
noncomputable def obsStepCondDensity (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) (i : Fin M.observed.card) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [StandardBorelSpace (ValuesOn ({(M.observedAt i).val} : Finset (SWIGNode N)) (swigΩ Ω))] [Nonempty (ValuesOn ({(M.observedAt i).val} : Finset (SWIGNode N)) (swigΩ Ω))] [CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes i.val) (swigΩ Ω))] : ValuesOn M.observed (swigΩ Ω) → ENNReal := fun x => ((M.obsStepCondKernel i.isLt) (s, valuesProjection (M.prefixNodes_subset_observed i.val) x)).rnDeriv (ref.μ (M.observedAt i).val) (x (M.observedAt i))
def qFactorDensityProduct reviewed
Causalean.SCM

The chain-rule density product for the observational law.

Definition (Lean source)
noncomputable def qFactorDensityProduct (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [∀ (k : ℕ) (hk : k < M.observed.card), StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M.observed.card), Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))] : ValuesOn M.observed (swigΩ Ω) → ENNReal := fun x => ∏ i : Fin M.observed.card, M.obsStepCondDensity ref s i x
def prefixDensityProduct reviewed
Causalean.SCM

The recursive prefix density product matching obsChainKernel.

Definition (Lean source)
noncomputable def prefixDensityProduct (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [∀ (k : ℕ) (hk : k < M.observed.card), StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M.observed.card), Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))] : (k : ℕ) → ValuesOn (M.prefixNodes k) (swigΩ Ω) → ENNReal | 0, _ => 1 | k + 1, z => M.prefixDensityProduct ref s k (valuesProjection (M.prefixNodes_mono (Nat.le_succ k)) z) * if h : k < M.observed.card then ((M.obsStepCondKernel h) (s, valuesProjection (M.prefixNodes_mono (Nat.le_succ k)) z)).rnDeriv (ref.μ (M.observedAt ⟨k, h⟩).val) (z ⟨(M.observedAt ⟨k, h⟩).val, by rw [M.prefixNodes_succ h] exact mem_union_right _ (mem_singleton_self _)⟩) else 1
def ObsStepFiberRN reviewed
Causalean.SCM

Per-step analytic hypotheses needed to expose the fibre Radon--Nikodym derivative against a σ-finite one-node reference.

Definition (Lean source)
def ObsStepFiberRN (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [∀ (k : ℕ) (hk : k < M.observed.card), StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M.observed.card), Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))] : Prop := ∀ (k : ℕ) (hk : k < M.observed.card), let node : SWIGNode N := (M.observedAt ⟨k, hk⟩).val let νk : Measure (ValuesOn (M.prefixNodes k) (swigΩ Ω)) := jointRef ref (M.prefixNodes k) let chain : Measure (ValuesOn (M.prefixNodes k) (swigΩ Ω)) := M.obsChainKernel k (le_of_lt hk) s let stepK : Kernel (ValuesOn (M.prefixNodes k) (swigΩ Ω)) (swigΩ Ω node) := (M.obsStepCondKernel hk).sectR s (∀ᵐ a ∂chain, stepK a ≪ ref.μ node) ∧ AEMeasurable (fun p : ValuesOn (M.prefixNodes k) (swigΩ Ω) × swigΩ Ω node => (stepK p.1).rnDeriv (ref.μ node) p.2) (νk.prod (ref.μ node))
def prefixStepDensityInPrefix reviewed
Causalean.SCM

The i-th one-step density factor read from a k-prefix assignment.

Definition (Lean source)
noncomputable def prefixStepDensityInPrefix (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [∀ (i : ℕ) (hi : i < M.observed.card), StandardBorelSpace (ValuesOn ({(M.observedAt ⟨i, hi⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (i : ℕ) (hi : i < M.observed.card), Nonempty (ValuesOn ({(M.observedAt ⟨i, hi⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ i : ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes i) (swigΩ Ω))] (k : ℕ) (z : ValuesOn (M.prefixNodes k) (swigΩ Ω)) (i : ℕ) : ENNReal := if hi : i < k then if hcard : i < M.observed.card then ((M.obsStepCondKernel hcard) (s, valuesProjection (M.prefixNodes_mono (le_of_lt hi)) z)).rnDeriv (ref.μ (M.observedAt ⟨i, hcard⟩).val) (z ⟨(M.observedAt ⟨i, hcard⟩).val, by rw [M.observedAt_mem_prefixNodes_iff k ⟨i, hcard⟩] exact hi⟩) else 1 else 1
theorem obsDensity_eq_qFactorDensityProduct reviewed
Causalean.SCM

Observational density chain rule. In a structural causal model whose observational law is absolutely continuous with respect to the joint reference measure on the observed nodes, if in addition the stepwise fibre Radon--Nikodym condition holds along the observed topological order, then the joint observational density agrees, almost everywhere with respect to that joint reference measure, with the product of the one-node conditional density factors taken in observed topological order.

Formal statement
M :
SCM N Ω
hdom :
s :
M.FixedValues
∀ s' :
M.FixedValues, IsFiniteMeasure (M.obsKernel s')
∀ (k : ℕ) (hk : k < M.observed.card),
StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ (k : ℕ) (hk : k < M.observed.card),
Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ k :
ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))
hstep :
M.obsDensity ref s =ᵐ[jointRef ref M.observed] M.qFactorDensityProduct ref s
Proof (Lean source)
theorem obsDensity_eq_qFactorDensityProduct (M : SCM N Ω) (ref : ReferenceMeasures Ω) (hdom : DominatedObs M ref) (s : M.FixedValues) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [∀ (k : ℕ) (hk : k < M.observed.card), StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M.observed.card), Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))] (hstep : ObsStepFiberRN M ref s) : M.obsDensity ref s =ᵐ[jointRef ref M.observed] M.qFactorDensityProduct ref s := by unfold obsDensity rw [c_component_factorization M s] exact M.qFactorProduct_rnDeriv_eq_qFactorDensityProduct ref hdom s hstep
20 supporting declarations (lemmas, instances)
CComponent­Density 2 core · 1 supporting The joint observational density is a *scalar* product of one-node conditional densities (qFactorDensityProduct). ★ qFactorDensityProduct_eq_prod_cComponentFactor

c-component regrouping of the chain-rule density

The joint observational density is a scalar product of one-node conditional densities (qFactorDensityProduct). Because scalar multiplication is commutative, that product can be regrouped by c-component: collect the factors whose node lies in each c-component of the graph. This regrouping is exactly the step that has no kernel-composition analogue — composed kernels cannot be permuted to bring a non-contiguous c-component's factors together, but scalar density factors can.

This file performs the regrouping (qFactorDensityProduct_eq_prod_cComponentFactor) and isolates the per-component scalar factor cComponentDensityFactor, which the next layer identifies with Tian's Q[C] density.

def cComponentDensityFactor reviewed
Causalean.SCM

The per-c-component density factor: the product of the one-node conditional density factors over exactly the observed nodes lying in the c-component C. This is the density-side analogue of Tian's c-factor Q[C].

Definition (Lean source)
noncomputable def cComponentDensityFactor (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) (C : Finset (SWIGNode N)) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [∀ (k : ℕ) (hk : k < M.observed.card), StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M.observed.card), Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))] : ValuesOn M.observed (swigΩ Ω) → ENNReal := fun x => ∏ i ∈ Finset.univ.filter (fun i : Fin M.observed.card => M.toSWIGGraph.cComponentOf (M.observedAt i).val = C), M.obsStepCondDensity ref s i x
theorem qFactorDensityProduct_eq_prod_cComponentFactor reviewed
Causalean.SCM

c-component regrouping of the chain-rule density product. For a structural causal model M, a reference measure family ref, a fixed assignment s, and a value assignment x to the observed coordinates, the product of all one-node conditional density factors equals the product, over the c-components of the graph, of the per-component density factors.

Formal statement
M :
SCM N Ω
s :
M.FixedValues
∀ s' :
M.FixedValues, IsFiniteMeasure (M.obsKernel s')
∀ (k : ℕ) (hk : k < M.observed.card),
StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ (k : ℕ) (hk : k < M.observed.card),
Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ k :
ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))
x :
ValuesOn M.observed (swigΩ Ω)
M.qFactorDensityProduct ref s x
= ∏ C ∈ M.toSWIGGraph.cComponentSet, M.cComponentDensityFactor ref s C x
Proof (Lean source)
theorem qFactorDensityProduct_eq_prod_cComponentFactor (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [∀ (k : ℕ) (hk : k < M.observed.card), StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M.observed.card), Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))] (x : ValuesOn M.observed (swigΩ Ω)) : M.qFactorDensityProduct ref s x = ∏ C ∈ M.toSWIGGraph.cComponentSet, M.cComponentDensityFactor ref s C x := by classical have hmaps : ∀ i ∈ (Finset.univ : Finset (Fin M.observed.card)), M.toSWIGGraph.cComponentOf (M.observedAt i).val ∈ M.toSWIGGraph.cComponentSet := by intro i _ exact Finset.mem_image.mpr ⟨(M.observedAt i).val, (M.observedAt i).property, rfl⟩ unfold qFactorDensityProduct cComponentDensityFactor exact (Finset.prod_fiberwise_of_maps_to hmaps (fun i => M.obsStepCondDensity ref s i x)).symm
1 supporting declaration (lemmas, instances)
  • cComponentDensityFactor_heq_of_obsKernel_heq lemma — Cross-model c-component density-factor transport. If two structural causal models share the same SWIG graph and have heterogeneously-equal observational kernels, then every c-component density factor recovered from the observational chain-rule density is heterogeneously equal across the two models.
    M₁ M₂ :
    SCM N Ω
    C :
    hsg :
    M₁.toSWIGGraph = M₂.toSWIGGraph
    hobs :
    HEq M₁.obsKernel M₂.obsKernel
    ∀ s' :
    M₁.FixedValues, IsFiniteMeasure (M₁.obsKernel s')
    ∀ (k : ℕ) (hk : k < M₁.observed.card),
    StandardBorelSpace (ValuesOn ({(M₁.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
    ∀ (k : ℕ) (hk : k < M₁.observed.card),
    Nonempty (ValuesOn ({(M₁.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
    ∀ k :
    ℕ, CountableOrCountablyGenerated M₁.FixedValues (ValuesOn (M₁.prefixNodes k) (swigΩ Ω))
    ∀ s' :
    M₂.FixedValues, IsFiniteMeasure (M₂.obsKernel s')
    ∀ (k : ℕ) (hk : k < M₂.observed.card),
    StandardBorelSpace (ValuesOn ({(M₂.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
    ∀ (k : ℕ) (hk : k < M₂.observed.card),
    Nonempty (ValuesOn ({(M₂.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
    ∀ k :
    ℕ, CountableOrCountablyGenerated M₂.FixedValues (ValuesOn (M₂.prefixNodes k) (swigΩ Ω))
    HEq (fun s => M₁.cComponentDensityFactor ref s C) (fun s => M₂.cComponentDensityFactor ref s C)
    Proof (Lean source)
    lemma cComponentDensityFactor_heq_of_obsKernel_heq (M₁ M₂ : SCM N Ω) (ref : ReferenceMeasures Ω) (C : Finset (SWIGNode N)) (hsg : M₁.toSWIGGraph = M₂.toSWIGGraph) (hobs : HEq M₁.obsKernel M₂.obsKernel) [∀ s' : M₁.FixedValues, IsFiniteMeasure (M₁.obsKernel s')] [∀ (k : ℕ) (hk : k < M₁.observed.card), StandardBorelSpace (ValuesOn ({(M₁.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M₁.observed.card), Nonempty (ValuesOn ({(M₁.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M₁.FixedValues (ValuesOn (M₁.prefixNodes k) (swigΩ Ω))] [∀ s' : M₂.FixedValues, IsFiniteMeasure (M₂.obsKernel s')] [∀ (k : ℕ) (hk : k < M₂.observed.card), StandardBorelSpace (ValuesOn ({(M₂.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M₂.observed.card), Nonempty (ValuesOn ({(M₂.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M₂.FixedValues (ValuesOn (M₂.prefixNodes k) (swigΩ Ω))] : HEq (fun s => M₁.cComponentDensityFactor ref s C) (fun s => M₂.cComponentDensityFactor ref s C) := by obtain ⟨⟨dag₁, fixed₁, observed₁, unobserved₁, fio₁, oi₁, od₁, oou₁, foi₁, fou₁, aic₁, dc₁, foff₁, aco₁⟩, eT₁, iota₁, sf₁, mf₁, lD₁, pL₁⟩ := M₁ obtain ⟨⟨dag₂, fixed₂, observed₂, unobserved₂, fio₂, oi₂, od₂, oou₂, foi₂, fou₂, aic₂, dc₂, foff₂, aco₂⟩, eT₂, iota₂, sf₂, mf₂, lD₂, pL₂⟩ := M₂ cases hsg have hfio : fio₂ = fio₁ := Subsingleton.elim _ _ subst fio₂ have hoi : oi₂ = oi₁ := Subsingleton.elim _ _ subst oi₂ have hod : od₂ = od₁ := Subsingleton.elim _ _ subst od₂ have hoou : oou₂ = oou₁ := Subsingleton.elim _ _ subst oou₂ have hfoi : foi₂ = foi₁ := Subsingleton.elim _ _ subst foi₂ have hfou : fou₂ = fou₁ := Subsingleton.elim _ _ subst fou₂ have haic : aic₂ = aic₁ := Subsingleton.elim _ _ subst aic₂ have hdc : dc₂ = dc₁ := Subsingleton.elim _ _ subst dc₂ have hfoff : foff₂ = foff₁ := Subsingleton.elim _ _ subst foff₂ have haco : aco₂ = aco₁ := Subsingleton.elim _ _ subst aco₂ have hk : _ = _ := eq_of_heq hobs apply heq_of_eq funext s x unfold cComponentDensityFactor congr 1 funext i unfold obsStepCondDensity obsStepCondKernel SCM.obsCondKernel SCM.obsCondPairKernel repeat' congr
    Causalean.SCM.cComponentDensityFactor_heq_of_obsKernel_heq · Causalean/SCM/ID/Density/CComponentDensity.lean:86
Pi­Union 3 core · 5 supporting For disjoint node sets A and B, the canonical measurable equivalence valuesUnionEquiv : ValuesOn (A ∪ B) ≃ᵐ ValuesOn A × ValuesOn B carries the finite product reference measure on A ∪ B to the product of the references o ★ measurePreserving_valuesUnionEquiv

Product measure over a disjoint union of value coordinates

For disjoint node sets A and B, the canonical measurable equivalence valuesUnionEquiv : ValuesOn (A ∪ B) ≃ᵐ ValuesOn A × ValuesOn B carries the finite product reference measure on A ∪ B to the product of the references on A and on B. In other words Measure.pi over a disjoint union is the product of the two Measure.pi's. This is the reference-splitting fact that lets the density chain rule peel off one coordinate at a time.

The proof routes the project's union equivalence through Mathlib's sumPiEquivProdPi (the value reindexing along the Sum decomposition of the union index) and piCongrLeft (the index reindexing), both measure-preserving.

def overrideOn reviewed
Causalean.SCM

Override the coordinates in W of an assignment on I, leaving the other coordinates unchanged.

Definition (Lean source)
def overrideOn {I W : Finset (SWIGNode N)} (x : ValuesOn I (swigΩ Ω)) (y : ValuesOn W (swigΩ Ω)) : ValuesOn I (swigΩ Ω) := fun i => if h : i.val ∈ W then y ⟨i.val, h⟩ else x i
def unionSumEquiv reviewed
Causalean.SCM

The index equivalence {a ∈ A} ⊕ {b ∈ B} ≃ {i ∈ A ∪ B} for disjoint A, B.

Definition (Lean source)
def unionSumEquiv {A B : Finset (SWIGNode N)} (hDisj : Disjoint A B) : ({a // a ∈ A} ⊕ {b // b ∈ B}) ≃ {i // i ∈ A ∪ B} where toFun := elim (fun a => ⟨a.val, mem_union_left _ a.property⟩) (fun b => ⟨b.val, mem_union_right _ b.property⟩) invFun i := if h : i.val ∈ A then inl ⟨i.val, h⟩ else inr ⟨i.val, (Finset.mem_union.mp i.property).resolve_left h⟩ left_inv := by rintro (⟨a, ha⟩ | ⟨b, hb⟩) · simp [ha] · have hbA : b ∉ A := fun h => (Finset.disjoint_left.mp hDisj h) hb simp [hbA] right_inv := by rintro ⟨i, hi⟩ by_cases h : i ∈ A · simp [h] · simp [h]
lemma measurePreserving_valuesUnionEquiv reviewed
Causalean.SCM

Measure.pi splits over a disjoint union. Given a family of σ-finite reference measures μ, one per coordinate, together with two finite index sets A and B assumed disjoint, the canonical equivalence carrying value assignments on A ∪ B to pairs of assignments on A and on B is measure-preserving from the product reference measure on A ∪ B to the product of the component reference measures on A and on B.

Formal statement
A B :
hDisj :
μ :
∀ v : SWIGNode N, Measure (swigΩ Ω v)
∀ v, SigmaFinite (μ v)
MeasurePreserving (valuesUnionEquiv (A := A) (B := B) hDisj) (pi (fun i : {i // i ∈ A ∪ B} => μ i.val)) ((pi (fun a : {a // a ∈ A} => μ a.val)).prod (pi (fun b : {b // b ∈ B} => μ b.val)))
Proof (Lean source)
lemma measurePreserving_valuesUnionEquiv {A B : Finset (SWIGNode N)} (hDisj : Disjoint A B) (μ : ∀ v : SWIGNode N, Measure (swigΩ Ω v)) [∀ v, SigmaFinite (μ v)] : MeasurePreserving (valuesUnionEquiv (A := A) (B := B) hDisj) (MeasureTheory.Measure.pi (fun i : {i // i ∈ A ∪ B} => μ i.val)) ((MeasureTheory.Measure.pi (fun a : {a // a ∈ A} => μ a.val)).prod (MeasureTheory.Measure.pi (fun b : {b // b ∈ B} => μ b.val))) := by classical set g := unionSumEquiv hDisj with hg have mpc : MeasurePreserving (MeasurableEquiv.piCongrLeft (fun i : {i // i ∈ A ∪ B} => swigΩ Ω i.val) g) (MeasureTheory.Measure.pi (fun j => μ (g j).val)) (MeasureTheory.Measure.pi (fun i : {i // i ∈ A ∪ B} => μ i.val)) := measurePreserving_piCongrLeft (fun i : {i // i ∈ A ∪ B} => μ i.val) g have mps : MeasurePreserving (MeasurableEquiv.sumPiEquivProdPi (fun j => swigΩ Ω (g j).val)) (MeasureTheory.Measure.pi (fun j => μ (g j).val)) ((MeasureTheory.Measure.pi fun a : {a // a ∈ A} => μ (g (inl a)).val).prod (MeasureTheory.Measure.pi fun b : {b // b ∈ B} => μ (g (inr b)).val)) := measurePreserving_sumPiEquivProdPi (fun j => μ (g j).val) have hcomp := mps.comp (mpc.symm (MeasurableEquiv.piCongrLeft _ g)) have hfun : ⇑(valuesUnionEquiv (A := A) (B := B) hDisj) = ⇑(MeasurableEquiv.sumPiEquivProdPi (fun j => swigΩ Ω (g j).val)) ∘ ⇑(MeasurableEquiv.piCongrLeft (fun i : {i // i ∈ A ∪ B} => swigΩ Ω i.val) g).symm := by funext ξ apply Prod.ext · funext a; rfl · funext b; rfl refine ⟨(valuesUnionEquiv hDisj).measurable, ?_⟩ rw [hfun] exact hcomp.map_eq
5 supporting declarations (lemmas, instances)
QMass 5 core · 12 supporting This file develops the finite mass identities behind the density route to ID. ★ qLocalMass_marginalize_ancestralClosed★ qLocalMass_prod_of_latentBlock_disjoint★ obsKernel_marginal_singleton_eq_prod_qLocalMass★ doObsKernelAncestralMarginal_positiveMass

Local q-masses for ID density factorization

This file develops the finite mass identities behind the density route to ID. The central definition is qLocalMass, the latent-product mass of satisfying local consistency on a chosen observed node set. The file proves elimination and marginalization lemmas for local q-masses, factors local consistency events over disjoint latent blocks, and derives the c-component factorization obsKernel_marginal_singleton_eq_prod_qLocalMass for observed marginal atoms.

It also supplies the positivity bridge doObsKernelAncestralMarginal_positiveMass for do-model ancestral marginals and the pure ENNReal telescope prod_filter_div_telescope, both used by the Tian district-density recovery in QFactor.

def qLocalMass reviewed
Causalean.SCM

The latent-product mass of satisfying local consistency on an observed subset.

Definition (Lean source)
noncomputable def qLocalMass (M : SCM N Ω) (s : M.FixedValues) (T : Finset (SWIGNode N)) (hT : T ⊆ M.observed) (x : ValuesOn M.observed (swigΩ Ω)) : ENNReal := M.latentProduct {ℓ | ∀ v (hv : v ∈ T), M.localConsistent s x v (hT hv) ℓ}
lemma qLocalMass_marginalize_ancestralClosed reviewed
Causalean.SCM

For a set of observed nodes T and a subset W of T such that every parent, within T, of a node in W also lies in W, marginalizing the local q-mass on T over the coordinates in T \ W yields the local q-mass on W.

Formal statement
∀ n, Fintype (Ω n)
M :
SCM N Ω
s :
M.FixedValues
T W :
hT :
T ⊆ M.observed
hWT :
W ⊆ T
hclosed :
∀ v ∈ T, ∀ w ∈ W, M.dag.edge v w → v ∈ W
x :
ValuesOn M.observed (swigΩ Ω)
marginalizeOn M.observed (T \ W) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s T hT) x
= M.qLocalMass s W (fun _ hv => hT (hWT hv)) x
Proof (Lean source)
lemma qLocalMass_marginalize_ancestralClosed [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (s : M.FixedValues) (T W : Finset (SWIGNode N)) (hT : T ⊆ M.observed) (hWT : W ⊆ T) (hclosed : ∀ v ∈ T, ∀ w ∈ W, M.dag.edge v w → v ∈ W) (x : ValuesOn M.observed (swigΩ Ω)) : marginalizeOn M.observed (T \ W) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s T hT) x = M.qLocalMass s W (fun _ hv => hT (hWT hv)) x := by classical let P : Nat → Prop := fun n => ∀ (T : Finset (SWIGNode N)) (hT : T ⊆ M.observed) (hWT : W ⊆ T), (∀ v ∈ T, ∀ w ∈ W, M.dag.edge v w → v ∈ W) → ∀ x : ValuesOn M.observed (swigΩ Ω), (T \ W).card = n → marginalizeOn M.observed (T \ W) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s T hT) x = M.qLocalMass s W (fun _ hv => hT (hWT hv)) x have hP : ∀ n, P n := by intro n induction n using Nat.strong_induction_on with | h n ih => intro T hT hWT hclosed x hcard by_cases hempty : T \ W = ∅ · have hTW : T ⊆ W := by intro v hvT by_contra hvW have hvS : v ∈ T \ W := Finset.mem_sdiff.mpr ⟨hvT, hvW⟩ simp [hempty] at hvS have hEq : T = W := Finset.Subset.antisymm hTW hWT subst T simpa [Finset.sdiff_self] using (marginalizeOn_empty M (M.qLocalMass s W hT) x) · have hne : (T \ W).Nonempty := Finset.nonempty_iff_ne_empty.mpr hempty obtain ⟨v, hvS, hNoChild⟩ := exists_sdiff_topoMax_noChild M hne hclosed let U : Finset (SWIGNode N) := (T \ W).erase v have hvT : v ∈ T := (Finset.mem_sdiff.mp hvS).1 have hvNotW : v ∉ W := (Finset.mem_sdiff.mp hvS).2 have hvNotU : v ∉ U := by dsimp [U] simp have hS_eq : T \ W = insert v U := by dsimp [U] exact (Finset.insert_erase hvS).symm have hUobs : U ⊆ M.observed := by intro u hu exact hT ((Finset.mem_sdiff.mp (mem_of_mem_erase hu)).1) have hInsobs : insert v U ⊆ M.observed := by intro u hu have huS : u ∈ T \ W := by simpa [hS_eq] using hu exact hT ((Finset.mem_sdiff.mp huS).1) let hTerase : T.erase v ⊆ M.observed := fun _ hv => hT (mem_of_mem_erase hv) have hfun : (fun x' : ValuesOn M.observed (swigΩ Ω) => ∑ ω : swigΩ Ω v, M.qLocalMass s T hT (overrideOn x' (singletonValuePt v ω))) = (fun x' : ValuesOn M.observed (swigΩ Ω) => M.qLocalMass s (T.erase v) hTerase x') := by funext x' simpa using (qLocalMass_sum_point_eliminate M s T hT hvT hNoChild x') have hEraseSdiff : (T.erase v) \ W = U := by dsimp [U] exact erase_sdiff_eq_sdiff_erase have hcard_lt : ((T.erase v) \ W).card < n := by rw [hEraseSdiff] dsimp [U] rw [← hcard] exact Finset.card_erase_lt_of_mem hvS have hWTerase : W ⊆ T.erase v := by intro w hw refine Finset.mem_erase.mpr ⟨?_, hWT hw⟩ intro hwv exact hvNotW (by simpa [hwv] using hw) have hclosedErase : ∀ a ∈ T.erase v, ∀ w ∈ W, M.dag.edge a w → a ∈ W := by intro a ha w hw haw exact hclosed a (mem_of_mem_erase ha) w hw haw calc marginalizeOn M.observed (T \ W) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s T hT) x = marginalizeOn M.observed (insert v U) hInsobs (M.qLocalMass s T hT) x := by exact marginalizeOn_congr_finset M hS_eq (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) hInsobs (M.qLocalMass s T hT) x _ = marginalizeOn M.observed U hUobs (fun x' => ∑ ω : swigΩ Ω v, M.qLocalMass s T hT (overrideOn x' (singletonValuePt v ω))) x := by exact marginalizeOn_insert M hvNotU hInsobs hUobs (M.qLocalMass s T hT) x _ = marginalizeOn M.observed U hUobs (M.qLocalMass s (T.erase v) hTerase) x := by rw [hfun] _ = marginalizeOn M.observed ((T.erase v) \ W) (fun _ hv => hTerase ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s (T.erase v) hTerase) x := by exact marginalizeOn_congr_finset M hEraseSdiff.symm hUobs (fun _ hv => hTerase ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s (T.erase v) hTerase) x _ = M.qLocalMass s W (fun _ hv => hT (hWT hv)) x := by have hIH := ih ((T.erase v) \ W).card hcard_lt (T.erase v) hTerase hWTerase hclosedErase x rfl simpa [hTerase] using hIH exact hP (T \ W).card T hT hWT hclosed x rfl
lemma qLocalMass_prod_of_latentBlock_disjoint reviewed
Causalean.SCM

For a finite family 𝒞 of observed node sets whose latent parent blocks are pairwise disjoint, the local q-mass on the union of the family equals the product, over the members U of 𝒞, of the local q-mass on U.

Formal statement
∀ n, Fintype (Ω n)
M :
SCM N Ω
s :
M.FixedValues
𝒞 :
h𝒞obs :
∀ U ∈ 𝒞, U ⊆ M.observed
hblock :
(↑𝒞 : Set (Finset (SWIGNode N))).Pairwise (fun U U' => Disjoint (M.latentBlock U) (M.latentBlock U'))
x :
ValuesOn M.observed (swigΩ Ω)
M.qLocalMass s (𝒞.sup id) (fun v hv => by rw [mem_sup] at hv rcases hv with ⟨U, hU, hvU⟩ exact h𝒞obs U hU hvU) x
= ∏ U ∈ 𝒞, if hU : U ∈ 𝒞 then M.qLocalMass s U (h𝒞obs U hU) x else 1
Proof (Lean source)
lemma qLocalMass_prod_of_latentBlock_disjoint [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (s : M.FixedValues) (𝒞 : Finset (Finset (SWIGNode N))) (h𝒞obs : ∀ U ∈ 𝒞, U ⊆ M.observed) (hblock : (↑𝒞 : Set (Finset (SWIGNode N))).Pairwise (fun U U' => Disjoint (M.latentBlock U) (M.latentBlock U'))) (x : ValuesOn M.observed (swigΩ Ω)) : M.qLocalMass s (𝒞.sup id) (fun v hv => by rw [mem_sup] at hv rcases hv with ⟨U, hU, hvU⟩ exact h𝒞obs U hU hvU) x = ∏ U ∈ 𝒞, if hU : U ∈ 𝒞 then M.qLocalMass s U (h𝒞obs U hU) x else 1 := by classical let hSup : 𝒞.sup id ⊆ M.observed := fun v hv => by rw [mem_sup] at hv rcases hv with ⟨U, hU, hvU⟩ exact h𝒞obs U hU hvU let E : Finset (SWIGNode N) → Set M.LatentValues := fun U => if hU : U ∈ 𝒞 then {ℓ : M.LatentValues | ∀ v (hv : v ∈ U), M.localConsistent s x v (h𝒞obs U hU hv) ℓ} else Set.univ have hevent : {ℓ : M.LatentValues | ∀ v (hv : v ∈ 𝒞.sup id), M.localConsistent s x v (hSup hv) ℓ} = ⋂ U ∈ 𝒞, E U := by simpa [E, hSup] using localConsistent_event_eq_family_biInter M s 𝒞 h𝒞obs hSup x have hcoord : iIndepFun (fun u : {u // u ∈ M.unobserved} => fun ℓ : M.LatentValues => ℓ u) M.latentProduct := by haveI : ∀ u : {u // u ∈ M.unobserved}, IsProbabilityMeasure (M.latentDist u) := M.isProbability_latent unfold SCM.latentProduct exact ProbabilityTheory.iIndepFun_pi (X := fun _ : {u // u ∈ M.unobserved} => id) (fun _ => aemeasurable_id) have hfactor : ∀ S : Finset (Finset (SWIGNode N)), S ⊆ 𝒞 → M.latentProduct (⋂ U ∈ S, E U) = ∏ U ∈ S, M.latentProduct (E U) := by intro S refine Finset.induction_on S ?base ?step · intro _hS simp [E] · intro U S hUnot ih hSinsert have hS : S ⊆ 𝒞 := by intro V hV exact hSinsert (mem_insert_of_mem hV) have hU : U ∈ 𝒞 := hSinsert (mem_insert_self U S) have hdisj : Disjoint (S.biUnion (latentBlockIndex M)) (latentBlockIndex M U) := latentBlockIndex_biUnion_disjoint_of_pairwise M hS hU hUnot hblock have hindep : IndepFun (fun ℓ : M.LatentValues => fun u : S.biUnion (latentBlockIndex M) => ℓ u) (fun ℓ : M.LatentValues => fun u : latentBlockIndex M U => ℓ u) M.latentProduct := hcoord.indepFun_finset (S.biUnion (latentBlockIndex M)) (latentBlockIndex M U) hdisj (fun u => measurable_pi_apply u) have hmeasS : MeasurableSet[ comap (fun ℓ : M.LatentValues => fun u : S.biUnion (latentBlockIndex M) => ℓ u) inferInstance] (⋂ V ∈ S, E V) := by have hbase := localConsistent_biInter_event_measurable_comap_latentBlockIndex_of_family M s 𝒞 S hS h𝒞obs x convert hbase using 1 ext ℓ simp only [Set.mem_iInter, Set.mem_setOf_eq] constructor · intro h V hVS have hEV := h V hVS simpa [E, hS hVS] using hEV · intro h V hVS have hEV := h V hVS simpa [E, hS hVS] using hEV have hmeasU : MeasurableSet[ comap (fun ℓ : M.LatentValues => fun u : latentBlockIndex M U => ℓ u) inferInstance] (E U) := by simpa [E, hU] using localConsistent_event_measurable_comap_latentBlockIndex_of_family M s U (h𝒞obs U hU) x have hinter := hindep.meas_inter (μ := M.latentProduct) hmeasS hmeasU calc M.latentProduct (⋂ V ∈ insert U S, E V) = M.latentProduct ((⋂ V ∈ S, E V) ∩ E U) := by congr 1 ext ℓ simp [E, and_comm] _ = M.latentProduct (⋂ V ∈ S, E V) * M.latentProduct (E U) := by exact hinter _ = (∏ V ∈ S, M.latentProduct (E V)) * M.latentProduct (E U) := by rw [ih hS] _ = ∏ V ∈ insert U S, M.latentProduct (E V) := by rw [Finset.prod_insert hUnot] rw [mul_comm] have hfull := hfactor 𝒞 (fun _ h => h) unfold qLocalMass rw [hevent] rw [hfull] refine Finset.prod_congr rfl ?_ intro U hU simp [E, hU]
theorem obsKernel_marginal_singleton_eq_prod_qLocalMass reviewed
Causalean.SCM

For a set of observed nodes P that is closed under observed parents, the singleton mass of the projection of the observational law onto P equals the product, over the full c-components C of the graph, of the local q-mass on C ∩ P.

Formal statement
∀ n, Fintype (Ω n)
M :
SCM N Ω
s :
M.FixedValues
P :
hP :
M.ObsParentClosed P
x :
ValuesOn M.observed (swigΩ Ω)
((M.obsKernel s).map (valuesProjection hP.1)) {valuesProjection hP.1 x}
= ∏ C ∈ M.toSWIGGraph.cComponentSet, M.qLocalMass s (C ∩ P) (fun _ hv => hP.1 (mem_of_mem_inter_right hv)) x
Proof (Lean source)
theorem obsKernel_marginal_singleton_eq_prod_qLocalMass [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (s : M.FixedValues) (P : Finset (SWIGNode N)) (hP : M.ObsParentClosed P) (x : ValuesOn M.observed (swigΩ Ω)) : ((M.obsKernel s).map (valuesProjection hP.1)) {valuesProjection hP.1 x} = ∏ C ∈ M.toSWIGGraph.cComponentSet, M.qLocalMass s (C ∩ P) (fun _ hv => hP.1 (mem_of_mem_inter_right hv)) x := by classical rw [obsKernel_marginal_singleton_eq_latentProduct_agree M s hP.1 x] have hset : {ℓ | ∀ v : {v // v ∈ P}, M.evalMap s ℓ ⟨v.val, mem_union_left M.unobserved (hP.1 v.property)⟩ = x ⟨v.val, hP.1 v.property⟩} = {ℓ | ∀ v (hv : v ∈ P), M.localConsistent s x v (hP.1 hv) ℓ} := by ext ℓ constructor · intro hEval exact (M.evalMap_agree_iff_localConsistent s P hP x ℓ).mp (fun v hv => hEval ⟨v, hv⟩) · intro hLocal v exact (M.evalMap_agree_iff_localConsistent s P hP x ℓ).mpr hLocal v.val v.property rw [hset] exact latentProduct_localConsistent_factorization M s P hP x
lemma doObsKernelAncestralMarginal_positiveMass reviewed
Causalean.SCM.ID

For an intervention set X whose random copies are observed and whose fixed copies are not already frozen, a positive observational kernel at every fixed-value assignment, and an outcome set Y disjoint from the random copies of X, the do(X)-law ancestral marginal kernel used in the identification density assembly also has everywhere-positive point mass.

Formal statement
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
M :
SCM N Ω
X :
hObs :
∀ D ∈ X, SWIGNode.random D ∈ M.observed
hFix :
∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
Y :
hpos :
∀ s' : M.FixedValues, DiscreteID.PositiveMass (M.obsKernel s')
hYX :
∀ d ∈ X, SWIGNode.random d ∉ Y
sDo :
(M.fixSet X hObs hFix).FixedValues
DiscreteID.PositiveMass (doObsKernelAncestralMarginal M X hObs hFix Y sDo)
Proof (Lean source)
lemma doObsKernelAncestralMarginal_positiveMass [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (Y : Finset (SWIGNode N)) (hpos : ∀ s' : M.FixedValues, DiscreteID.PositiveMass (M.obsKernel s')) (hYX : ∀ d ∈ X, SWIGNode.random d ∉ Y) (sDo : (M.fixSet X hObs hFix).FixedValues) : DiscreteID.PositiveMass (doObsKernelAncestralMarginal M X hObs hFix Y sDo) := by classical let MX := M.fixSet X hObs hFix let D := fixObservedAncestralSet M X hObs hFix Y let A := fixAncestralSet M X hObs hFix Y have hDclosed : MX.ObsParentClosed D := by simpa [MX, D] using fixObservedAncestralSet_obsParent_closed M X hObs hFix Y intro xD let xFull : ValuesOn M.observed (swigΩ Ω) := fun v => if hvD : v.val ∈ D then xD ⟨v.val, hvD⟩ else match v.val with | SWIGNode.random d => if hd : d ∈ X then sDo ⟨SWIGNode.fixed d, mem_union_right _ (Finset.mem_image.mpr ⟨d, hd, rfl⟩)⟩ else Classical.choice (inferInstance : Nonempty (swigΩ Ω (SWIGNode.random d))) | SWIGNode.fixed d => Classical.choice (inferInstance : Nonempty (swigΩ Ω (SWIGNode.fixed d))) let xDo : ValuesOn MX.observed (swigΩ Ω) := fun v => xFull ⟨v.val, v.property⟩ have hprojD : valuesProjection hDclosed.1 xDo = xD := by ext v simp [valuesProjection, xDo, xFull, v.property] have hpin : ∀ d (hd : d ∈ X), xFull ⟨SWIGNode.random d, hObs d hd⟩ = sDo ⟨SWIGNode.fixed d, mem_union_right _ (Finset.mem_image.mpr ⟨d, hd, rfl⟩)⟩ := by intro d hd have hnotD : SWIGNode.random d ∉ D := by intro hdD have hdA : SWIGNode.random d ∈ A := (Finset.mem_inter.mp hdD).1 exact hYX d hd ((random_intervened_mem_fixAncestralSet_iff_mem_Y M X hObs hFix Y hd).mp hdA) simp [xFull, hnotD, hd] have hobsAgree : ∀ w (hw : w ∈ M.observed), xDo ⟨w, by simpa [MX, SCM.fixSet_observed] using hw⟩ = xFull ⟨w, hw⟩ := by intro w hw rfl have hq_ne : ∀ C ∈ MX.toSWIGGraph.cComponentSet, MX.qLocalMass sDo (C ∩ D) (fun _ hv => hDclosed.1 (Finset.mem_of_mem_inter_right hv)) xDo ≠ 0 := by intro C _hC have hsubsetM : C ∩ D ⊆ M.observed := by intro v hv have hvD : v ∈ D := Finset.mem_of_mem_inter_right hv exact Finset.inter_subset_right hvD have hqeq : MX.qLocalMass sDo (C ∩ D) (fun _ hv => hDclosed.1 (Finset.mem_of_mem_inter_right hv)) xDo = M.qLocalMass (M.fixSetProj X hObs hFix sDo) (C ∩ D) hsubsetM xFull := by unfold qLocalMass congr 1 ext ℓ constructor · intro hLocal v hv have hvD : v ∈ D := Finset.mem_of_mem_inter_right hv have hnot : v ∉ X.image SWIGNode.random := by intro hvX rcases Finset.mem_image.mp hvX with ⟨d, hd, rfl⟩ have hdA : SWIGNode.random d ∈ A := (Finset.mem_inter.mp hvD).1 exact hYX d hd ((random_intervened_mem_fixAncestralSet_iff_mem_Y M X hObs hFix Y hd).mp hdA) exact (localConsistent_fixSet_iff M X hObs hFix sDo (M.fixSetProj X hObs hFix sDo) xDo xFull v ((fun _ hv => hDclosed.1 (Finset.mem_of_mem_inter_right hv)) v hv) (hsubsetM hv) hnot hobsAgree hpin rfl ℓ).mp (hLocal v hv) · intro hLocal v hv have hvD : v ∈ D := Finset.mem_of_mem_inter_right hv have hnot : v ∉ X.image SWIGNode.random := by intro hvX rcases Finset.mem_image.mp hvX with ⟨d, hd, rfl⟩ have hdA : SWIGNode.random d ∈ A := (Finset.mem_inter.mp hvD).1 exact hYX d hd ((random_intervened_mem_fixAncestralSet_iff_mem_Y M X hObs hFix Y hd).mp hdA) exact (localConsistent_fixSet_iff M X hObs hFix sDo (M.fixSetProj X hObs hFix sDo) xDo xFull v ((fun _ hv => hDclosed.1 (Finset.mem_of_mem_inter_right hv)) v hv) (hsubsetM hv) hnot hobsAgree hpin rfl ℓ).mpr (hLocal v hv) rw [hqeq] exact M.qLocalMass_pos_of_positiveObs (M.fixSetProj X hObs hFix sDo) (hpos (M.fixSetProj X hObs hFix sDo)) (C ∩ D) hsubsetM xFull have hmass := MX.obsKernel_marginal_singleton_eq_prod_qLocalMass sDo D hDclosed xDo have hkey : doObsKernelAncestralMarginal M X hObs hFix Y = MX.obsKernel.map (valuesProjection hDclosed.1) := rfl unfold DiscreteID.singletonMass rw [hkey, ProbabilityTheory.Kernel.map_apply _ (measurable_valuesProjection hDclosed.1), ← hprojD, hmass] exact Finset.prod_ne_zero_iff.mpr hq_ne
12 supporting declarations (lemmas, instances)
  • qLocalMass_empty lemma — The empty local q-mass is one.
    M :
    SCM N Ω
    s :
    M.FixedValues
    x :
    ValuesOn M.observed (swigΩ Ω)
    M.qLocalMass s ∅ (by simp) x = 1
    Proof (Lean source)
    @[simp] lemma qLocalMass_empty (M : SCM N Ω) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) : M.qLocalMass s ∅ (by simp) x = 1 := by simp [qLocalMass]
    Causalean.SCM.qLocalMass_empty · Causalean/SCM/ID/Density/QMass.lean:48
  • qLocalMass_anti lemma — Local q-mass is antitone in the constrained observed set.
    M :
    SCM N Ω
    s :
    M.FixedValues
    T T' :
    hTT' :
    T ⊆ T'
    hT :
    T ⊆ M.observed
    hT' :
    T' ⊆ M.observed
    x :
    ValuesOn M.observed (swigΩ Ω)
    M.qLocalMass s T' hT' x ≤ M.qLocalMass s T hT x
    Proof (Lean source)
    lemma qLocalMass_anti (M : SCM N Ω) (s : M.FixedValues) {T T' : Finset (SWIGNode N)} (hTT' : T ⊆ T') (hT : T ⊆ M.observed) (hT' : T' ⊆ M.observed) (x : ValuesOn M.observed (swigΩ Ω)) : M.qLocalMass s T' hT' x ≤ M.qLocalMass s T hT x := by apply MeasureTheory.measure_mono intro ℓ hℓ v hv exact hℓ v (hTT' hv)
    Causalean.SCM.qLocalMass_anti · Causalean/SCM/ID/Density/QMass.lean:55
  • marginalizeOn_empty lemma — Marginalizing a mass function over an empty set of observed coordinates leaves its value at every observed assignment unchanged.
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    q :
    ValuesOn M.observed (swigΩ Ω) → ENNReal
    x :
    ValuesOn M.observed (swigΩ Ω)
    marginalizeOn M.observed ∅ (by simp) q x = q x
    Proof (Lean source)
    lemma marginalizeOn_empty [∀ n, Fintype (Ω n)] (M : SCM N Ω) (q : ValuesOn M.observed (swigΩ Ω) → ENNReal) (x : ValuesOn M.observed (swigΩ Ω)) : marginalizeOn M.observed ∅ (by simp) q x = q x := by classical unfold marginalizeOn let y0 : ValuesOn (∅ : Finset (SWIGNode N)) (swigΩ Ω) := fun i => elim (notMem_empty i.val i.property) rw [Finset.sum_eq_single y0] · congr funext i simp · intro y _hy hy exact (hy (Subsingleton.elim y y0)).elim · intro hy exact (hy (Finset.mem_univ y0)).elim
    Causalean.SCM.marginalizeOn_empty · Causalean/SCM/ID/Density/QMass.lean:161
  • qLocalMass_sum_point_eliminate lemma — Summing a local q-mass over one childless observed coordinate removes that coordinate from the constrained set.
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    s :
    M.FixedValues
    T :
    hT :
    T ⊆ M.observed
    v :
    hvT :
    v ∈ T
    hNoChild :
    ∀ w ∈ T, ¬ M.dag.edge v w
    x :
    ValuesOn M.observed (swigΩ Ω)
    (∑ ω : swigΩ Ω v, M.qLocalMass s T hT (overrideOn x (singletonValuePt v ω)))
    = M.qLocalMass s (T.erase v) (fun _ hv => hT (mem_of_mem_erase hv)) x
    Proof (Lean source)
    lemma qLocalMass_sum_point_eliminate [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (s : M.FixedValues) (T : Finset (SWIGNode N)) (hT : T ⊆ M.observed) {v : SWIGNode N} (hvT : v ∈ T) (hNoChild : ∀ w ∈ T, ¬ M.dag.edge v w) (x : ValuesOn M.observed (swigΩ Ω)) : (∑ ω : swigΩ Ω v, M.qLocalMass s T hT (overrideOn x (singletonValuePt v ω))) = M.qLocalMass s (T.erase v) (fun _ hv => hT (mem_of_mem_erase hv)) x := by classical let Erest : Set M.LatentValues := {ℓ | ∀ w (hw : w ∈ T.erase v), M.localConsistent s x w (hT (mem_of_mem_erase hw)) ℓ} let Fset : swigΩ Ω v → Set M.LatentValues := fun ω => {ℓ | localStructValue M s x v (hT hvT) ℓ = ω} have hevent : ∀ ω : swigΩ Ω v, {ℓ : M.LatentValues | ∀ w (hw : w ∈ T), M.localConsistent s (overrideOn x (singletonValuePt v ω)) w (hT hw) ℓ} = Erest ∩ Fset ω := by intro ω simpa [Erest, Fset] using qLocalEvent_override_singleton_eq_inter M s hT hvT hNoChild x ω have hdisj : PairwiseDisjoint (↑(Finset.univ : Finset (swigΩ Ω v))) (fun ω => Erest ∩ Fset ω) := by intro ω₁ _ ω₂ _ hne change Disjoint (Erest ∩ Fset ω₁) (Erest ∩ Fset ω₂) rw [Set.disjoint_left] intro ℓ hℓ₁ hℓ₂ exact hne (hℓ₁.2.symm.trans hℓ₂.2) have hmeas : ∀ ω ∈ (Finset.univ : Finset (swigΩ Ω v)), MeasurableSet (Erest ∩ Fset ω) := by intro ω _hω exact Set.Finite.measurableSet (Set.toFinite _) have hunion : (⋃ ω ∈ (Finset.univ : Finset (swigΩ Ω v)), Erest ∩ Fset ω) = Erest := by ext ℓ simp [Fset] simp only [qLocalMass] calc (∑ ω : swigΩ Ω v, M.latentProduct {ℓ : M.LatentValues | ∀ w (hw : w ∈ T), M.localConsistent s (overrideOn x (singletonValuePt v ω)) w (hT hw) ℓ}) = ∑ ω : swigΩ Ω v, M.latentProduct (Erest ∩ Fset ω) := by refine Finset.sum_congr rfl ?_ intro ω _hω rw [hevent ω] _ = M.latentProduct (⋃ ω ∈ (Finset.univ : Finset (swigΩ Ω v)), Erest ∩ Fset ω) := by symm simpa using (MeasureTheory.measure_biUnion_finset (μ := M.latentProduct) (s := (Finset.univ : Finset (swigΩ Ω v))) (f := fun ω => Erest ∩ Fset ω) hdisj hmeas) _ = M.latentProduct Erest := by rw [hunion]
    Causalean.SCM.qLocalMass_sum_point_eliminate · Causalean/SCM/ID/Density/QMass.lean:421
  • latentProduct_singleton_eq_prod lemma — The latent-product mass of a singleton latent assignment equals the product of the singleton masses assigned by the latent distributions at every unobserved node.
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    ℓ₀ :
    M.LatentValues
    M.latentProduct ({ℓ₀} : Set M.LatentValues)
    = ∏ u : {u // u ∈ M.unobserved}, M.latentDist u ({ℓ₀ u} : Set (swigΩ Ω u.val))
    Proof (Lean source)
    lemma latentProduct_singleton_eq_prod [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (ℓ₀ : M.LatentValues) : M.latentProduct ({ℓ₀} : Set M.LatentValues) = ∏ u : {u // u ∈ M.unobserved}, M.latentDist u ({ℓ₀ u} : Set (swigΩ Ω u.val)) := by classical haveI : ∀ u : {u // u ∈ M.unobserved}, IsProbabilityMeasure (M.latentDist u) := M.isProbability_latent haveI : ∀ u : {u // u ∈ M.unobserved}, SigmaFinite (M.latentDist u) := fun _ => inferInstance unfold SCM.latentProduct have hsingleton : ({ℓ₀} : Set M.LatentValues) = Set.univ.pi (fun u => ({ℓ₀ u} : Set (swigΩ Ω u.val))) := by ext ℓ simp [Set.mem_pi, funext_iff] rw [hsingleton, MeasureTheory.Measure.pi_pi]
    Causalean.SCM.latentProduct_singleton_eq_prod · Causalean/SCM/ID/Density/QMass.lean:637
  • measurableSet_comap_piFinset_of_depends lemma — A set of finite product outcomes whose membership depends only on a specified finite set of coordinates is measurable with respect to the σ-algebra on those coordinates.
    ι :
    Type*
    ι → Type*
    ∀ i, MeasurableSpace (α i)
    ∀ i, Fintype (α i)
    S :
    A :
    Set (∀ i, α i)
    hdep :
    ∀ ξ ξ'
    if
    (∀ i (_hi : i ∈ S), ξ i = ξ' i)
    then
    (ξ ∈ A ↔ ξ' ∈ A)
    MeasurableSet[ comap (fun ξ : (∀ i, α i) => fun i : S => ξ i) inferInstance] A
    Proof (Lean source)
    lemma measurableSet_comap_piFinset_of_depends {ι : Type*} [Fintype ι] {α : ι → Type*} [∀ i, MeasurableSpace (α i)] [∀ i, Fintype (α i)] [∀ i, MeasurableSingletonClass (α i)] (S : Finset ι) (A : Set (∀ i, α i)) (hdep : ∀ ξ ξ', (∀ i (_hi : i ∈ S), ξ i = ξ' i) → (ξ ∈ A ↔ ξ' ∈ A)) : MeasurableSet[ comap (fun ξ : (∀ i, α i) => fun i : S => ξ i) inferInstance] A := by let B : Set (∀ i : S, α i.val) := {η | ∃ ξ ∈ A, (fun i : S => ξ i) = η} refine ⟨B, Set.Finite.measurableSet B.toFinite, ?_⟩ ext ξ change ξ ∈ ((fun ξ : (∀ i, α i) => fun i : S => ξ i) ⁻¹' B) ↔ ξ ∈ A constructor · rintro ⟨ξ', hξ'A, hξ'⟩ exact (hdep ξ' ξ (by intro i hi exact congrFun hξ' ⟨i, hi⟩)).mp hξ'A · intro hξA exact ⟨ξ, hξA, rfl⟩
    Causalean.SCM.measurableSet_comap_piFinset_of_depends · Causalean/SCM/ID/Density/QMass.lean:659
  • localConsistent_depends_only_on_latentBlock_of_mem lemma — Local consistency at an observed node in a node set is unchanged when two latent assignments agree on every unobserved parent of a node in that set.
    M :
    SCM N Ω
    s :
    M.FixedValues
    x :
    ValuesOn M.observed (swigΩ Ω)
    U :
    v :
    hvU :
    v ∈ U
    hv :
    v ∈ M.observed
    ℓ ℓ' :
    M.LatentValues
    hℓ :
    ∀ u (hu : u ∈ M.latentBlock U),
    ℓ ⟨u, (Finset.mem_filter.mp hu).1⟩ = ℓ' ⟨u, (Finset.mem_filter.mp hu).1⟩
    M.localConsistent s x v hv ℓ ↔ M.localConsistent s x v hv ℓ'
    Proof (Lean source)
    lemma localConsistent_depends_only_on_latentBlock_of_mem (M : SCM N Ω) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) {U : Finset (SWIGNode N)} {v : SWIGNode N} (hvU : v ∈ U) (hv : v ∈ M.observed) (ℓ ℓ' : M.LatentValues) (hℓ : ∀ u (hu : u ∈ M.latentBlock U), ℓ ⟨u, (Finset.mem_filter.mp hu).1⟩ = ℓ' ⟨u, (Finset.mem_filter.mp hu).1⟩) : M.localConsistent s x v hv ℓ ↔ M.localConsistent s x v hv ℓ' := by unfold localConsistent set j : Fin M.observed.card := M.observedIndex ⟨v, hv⟩ with hj have hat : (M.observedAt j).val = v := by rw [hj] exact M.observedAt_observedIndex ⟨v, hv⟩ have hfun : M.structFun (M.observedAt j) (fun w => M.parentMap s ℓ j.isLt (prevFromObservedValues M x) w) = M.structFun (M.observedAt j) (fun w => M.parentMap s ℓ' j.isLt (prevFromObservedValues M x) w) := by congr 1 funext w by_cases huo : w.val ∈ M.unobserved · rw [parentMap_unobserved M s ℓ j.isLt _ w huo, parentMap_unobserved M s ℓ' j.isLt _ w huo] have hedge_v : M.dag.edge w.val v := by have hedge_at : M.dag.edge w.val (M.observedAt j).val := M.dag.mem_parents.mp w.property simpa [hat] using hedge_at have huBlock : w.val ∈ M.latentBlock U := by rw [latentBlock, mem_filter] exact ⟨huo, ⟨v, hvU, hedge_v⟩⟩ exact hℓ w.val huBlock · by_cases hfix : w.val ∈ M.fixed · rw [parentMap_fixed M s ℓ j.isLt _ w hfix, parentMap_fixed M s ℓ' j.isLt _ w hfix] · have hedge : M.dag.edge w.val (M.observedAt j).val := M.dag.mem_parents.mp w.property have hobs : w.val ∈ M.observed := by rcases Finset.mem_union.mp (M.dag_edges_classified _ _ hedge).1 with h1 | h2 · rcases Finset.mem_union.mp h1 with hfx | hob · exact absurd hfx hfix · exact hob · exact absurd h2 huo rw [parentMap_observed M s ℓ j.isLt _ w hobs, parentMap_observed M s ℓ' j.isLt _ w hobs] subst j change ((M.observedAt_observedIndex ⟨v, hv⟩) ▸ M.structFun (M.observedAt (M.observedIndex ⟨v, hv⟩)) (fun w => M.parentMap s ℓ (M.observedIndex ⟨v, hv⟩).isLt (prevFromObservedValues M x) w) = x ⟨v, hv⟩) ↔ ((M.observedAt_observedIndex ⟨v, hv⟩) ▸ M.structFun (M.observedAt (M.observedIndex ⟨v, hv⟩)) (fun w => M.parentMap s ℓ' (M.observedIndex ⟨v, hv⟩).isLt (prevFromObservedValues M x) w) = x ⟨v, hv⟩) rw [hfun]
    Causalean.SCM.localConsistent_depends_only_on_latentBlock_of_mem · Causalean/SCM/ID/Density/QMass.lean:876
  • localConsistent_event_eq_component_biInter lemma — For an observed-parent-closed node set, local consistency at all of its nodes is equivalent to local consistency within each of its confounded components.
    M :
    SCM N Ω
    s :
    M.FixedValues
    P :
    hP :
    M.ObsParentClosed P
    x :
    ValuesOn M.observed (swigΩ Ω)
    {ℓ : M.LatentValues | ∀ v (hv : v ∈ P), M.localConsistent s x v (hP.1 hv) ℓ}
    = ⋂ C ∈ M.toSWIGGraph.cComponentSet, {ℓ : M.LatentValues | ∀ v (hv : v ∈ C ∩ P), M.localConsistent s x v (hP.1 (mem_of_mem_inter_right hv)) ℓ}
    Proof (Lean source)
    lemma localConsistent_event_eq_component_biInter (M : SCM N Ω) (s : M.FixedValues) (P : Finset (SWIGNode N)) (hP : M.ObsParentClosed P) (x : ValuesOn M.observed (swigΩ Ω)) : {ℓ : M.LatentValues | ∀ v (hv : v ∈ P), M.localConsistent s x v (hP.1 hv) ℓ} = ⋂ C ∈ M.toSWIGGraph.cComponentSet, {ℓ : M.LatentValues | ∀ v (hv : v ∈ C ∩ P), M.localConsistent s x v (hP.1 (mem_of_mem_inter_right hv)) ℓ} := by classical ext ℓ constructor · intro hℓ rw [Set.mem_iInter] intro C rw [Set.mem_iInter] intro _hC v hv exact hℓ v (mem_of_mem_inter_right hv) · intro hℓ v hvP rw [Set.mem_iInter] at hℓ have hC : M.toSWIGGraph.cComponentOf v ∈ M.toSWIGGraph.cComponentSet := by rw [SWIGGraph.cComponentSet, mem_image] exact ⟨v, hP.1 hvP, rfl⟩ have hvC : v ∈ M.toSWIGGraph.cComponentOf v := M.toSWIGGraph.mem_cComponentOf_self (hP.1 hvP) have hℓC := hℓ (M.toSWIGGraph.cComponentOf v) rw [Set.mem_iInter] at hℓC exact hℓC hC v (Finset.mem_inter.mpr ⟨hvC, hvP⟩)
    Causalean.SCM.localConsistent_event_eq_component_biInter · Causalean/SCM/ID/Density/QMass.lean:1045
  • localConsistent_event_eq_family_biInter lemma — For a finite family of observed node sets, local consistency over their union is equivalent to local consistency over every member of the family.
    M :
    SCM N Ω
    s :
    M.FixedValues
    𝒞 :
    h𝒞obs :
    ∀ U ∈ 𝒞, U ⊆ M.observed
    hSup :
    𝒞.sup id ⊆ M.observed
    x :
    ValuesOn M.observed (swigΩ Ω)
    {ℓ : M.LatentValues | ∀ v (hv : v ∈ 𝒞.sup id), M.localConsistent s x v (hSup hv) ℓ}
    = ⋂ U ∈ 𝒞, if hU : U ∈ 𝒞 then {ℓ : M.LatentValues | ∀ v (hv : v ∈ U), M.localConsistent s x v (h𝒞obs U hU hv) ℓ} else univ
    Proof (Lean source)
    lemma localConsistent_event_eq_family_biInter (M : SCM N Ω) (s : M.FixedValues) (𝒞 : Finset (Finset (SWIGNode N))) (h𝒞obs : ∀ U ∈ 𝒞, U ⊆ M.observed) (hSup : 𝒞.sup id ⊆ M.observed) (x : ValuesOn M.observed (swigΩ Ω)) : {ℓ : M.LatentValues | ∀ v (hv : v ∈ 𝒞.sup id), M.localConsistent s x v (hSup hv) ℓ} = ⋂ U ∈ 𝒞, if hU : U ∈ 𝒞 then {ℓ : M.LatentValues | ∀ v (hv : v ∈ U), M.localConsistent s x v (h𝒞obs U hU hv) ℓ} else univ := by classical ext ℓ constructor · intro hℓ rw [Set.mem_iInter] intro U rw [Set.mem_iInter] intro hU simp [hU] intro v hv have hvSup : v ∈ 𝒞.sup id := by rw [mem_sup] exact ⟨U, hU, hv⟩ convert hℓ v hvSup using 1 · intro hℓ v hvSup rw [Set.mem_iInter] at hℓ rw [mem_sup] at hvSup rcases hvSup with ⟨U, hU, hvU⟩ have hℓU := hℓ U rw [Set.mem_iInter] at hℓU have hUevent : ℓ ∈ {ℓ : M.LatentValues | ∀ v (hv : v ∈ U), M.localConsistent s x v (h𝒞obs U hU hv) ℓ} := by simpa [hU] using hℓU hU convert hUevent v hvU using 1
    Causalean.SCM.localConsistent_event_eq_family_biInter · Causalean/SCM/ID/Density/QMass.lean:1078
  • qLocalMass_prod_inter_of_latentBlock_disjoint lemma — Local q-mass on a covered set factors over an abstract family after intersecting each family member with the covered set.
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    s :
    M.FixedValues
    P :
    hPobs :
    P ⊆ M.observed
    𝒞 :
    h𝒞obs :
    ∀ U ∈ 𝒞, U ⊆ M.observed
    hcover :
    P ⊆ 𝒞.sup id
    hblock :
    (↑𝒞 : Set (Finset (SWIGNode N))).Pairwise (fun U U' => Disjoint (M.latentBlock U) (M.latentBlock U'))
    x :
    ValuesOn M.observed (swigΩ Ω)
    M.qLocalMass s P hPobs x
    = ∏ U ∈ 𝒞, if hU : U ∈ 𝒞 then M.qLocalMass s (U ∩ P) (fun _ hv => h𝒞obs U hU (mem_of_mem_inter_left hv)) x else 1
    Proof (Lean source)
    lemma qLocalMass_prod_inter_of_latentBlock_disjoint [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (s : M.FixedValues) (P : Finset (SWIGNode N)) (hPobs : P ⊆ M.observed) (𝒞 : Finset (Finset (SWIGNode N))) (h𝒞obs : ∀ U ∈ 𝒞, U ⊆ M.observed) (hcover : P ⊆ 𝒞.sup id) (hblock : (↑𝒞 : Set (Finset (SWIGNode N))).Pairwise (fun U U' => Disjoint (M.latentBlock U) (M.latentBlock U'))) (x : ValuesOn M.observed (swigΩ Ω)) : M.qLocalMass s P hPobs x = ∏ U ∈ 𝒞, if hU : U ∈ 𝒞 then M.qLocalMass s (U ∩ P) (fun _ hv => h𝒞obs U hU (mem_of_mem_inter_left hv)) x else 1 := by classical let E : Finset (SWIGNode N) → Set M.LatentValues := fun U => if hU : U ∈ 𝒞 then {ℓ : M.LatentValues | ∀ v (hv : v ∈ U ∩ P), M.localConsistent s x v (h𝒞obs U hU (mem_of_mem_inter_left hv)) ℓ} else Set.univ have hevent : {ℓ : M.LatentValues | ∀ v (hv : v ∈ P), M.localConsistent s x v (hPobs hv) ℓ} = ⋂ U ∈ 𝒞, E U := by ext ℓ constructor · intro hℓ rw [Set.mem_iInter] intro U rw [Set.mem_iInter] intro hU simp [E, hU] intro v _hvU hvP exact hℓ v hvP · intro hℓ v hvP rw [Set.mem_iInter] at hℓ have hvSup : v ∈ 𝒞.sup id := hcover hvP rw [mem_sup] at hvSup rcases hvSup with ⟨U, hU, hvU⟩ have hℓU := hℓ U rw [Set.mem_iInter] at hℓU have hUevent : ℓ ∈ {ℓ : M.LatentValues | ∀ v (hv : v ∈ U ∩ P), M.localConsistent s x v (h𝒞obs U hU (mem_of_mem_inter_left hv)) ℓ} := by simpa [E, hU] using hℓU hU have hvUP : v ∈ U ∩ P := Finset.mem_inter.mpr ⟨hvU, hvP⟩ convert hUevent v hvUP using 1 have hcoord : iIndepFun (fun u : {u // u ∈ M.unobserved} => fun ℓ : M.LatentValues => ℓ u) M.latentProduct := by haveI : ∀ u : {u // u ∈ M.unobserved}, IsProbabilityMeasure (M.latentDist u) := M.isProbability_latent unfold SCM.latentProduct exact ProbabilityTheory.iIndepFun_pi (X := fun _ : {u // u ∈ M.unobserved} => id) (fun _ => aemeasurable_id) have hfactor : ∀ S : Finset (Finset (SWIGNode N)), S ⊆ 𝒞 → M.latentProduct (⋂ U ∈ S, E U) = ∏ U ∈ S, M.latentProduct (E U) := by intro S refine Finset.induction_on S ?base ?step · intro _hS simp [E] · intro U S hUnot ih hSinsert have hS : S ⊆ 𝒞 := by intro V hV exact hSinsert (mem_insert_of_mem hV) have hU : U ∈ 𝒞 := hSinsert (mem_insert_self U S) have hdisj : Disjoint (S.biUnion (latentBlockIndex M)) (latentBlockIndex M U) := latentBlockIndex_biUnion_disjoint_of_pairwise M hS hU hUnot hblock have hindep : IndepFun (fun ℓ : M.LatentValues => fun u : S.biUnion (latentBlockIndex M) => ℓ u) (fun ℓ : M.LatentValues => fun u : latentBlockIndex M U => ℓ u) M.latentProduct := hcoord.indepFun_finset (S.biUnion (latentBlockIndex M)) (latentBlockIndex M U) hdisj (fun u => measurable_pi_apply u) have hmeasS : MeasurableSet[ comap (fun ℓ : M.LatentValues => fun u : S.biUnion (latentBlockIndex M) => ℓ u) inferInstance] (⋂ V ∈ S, E V) := by refine measurableSet_comap_piFinset_of_depends (S := S.biUnion (latentBlockIndex M)) _ ?_ intro ℓ ℓ' hagree constructor · intro hℓ rw [Set.mem_iInter] at hℓ rw [Set.mem_iInter] intro V have hℓV := hℓ V rw [Set.mem_iInter] at hℓV rw [Set.mem_iInter] intro hVS have hV𝒞 : V ∈ 𝒞 := hS hVS simp [E, hV𝒞] intro v hvV hvP have hlocal : M.localConsistent s x v (h𝒞obs V hV𝒞 hvV) ℓ := by have hEV : ℓ ∈ E V := hℓV hVS have hEV' : ∀ v (hv : v ∈ V ∩ P), M.localConsistent s x v (h𝒞obs V hV𝒞 (mem_of_mem_inter_left hv)) ℓ := by simpa [E, hV𝒞] using hEV exact hEV' v (Finset.mem_inter.mpr ⟨hvV, hvP⟩) exact (localConsistent_depends_only_on_latentBlock_of_mem M s x hvV (h𝒞obs V hV𝒞 hvV) ℓ ℓ' (by intro u hu have hmemBlock : (⟨u, (Finset.mem_filter.mp hu).1⟩ : {u // u ∈ M.unobserved}) ∈ latentBlockIndex M V := (mem_latentBlockIndex_iff M V _).mpr hu have hmem : (⟨u, (Finset.mem_filter.mp hu).1⟩ : {u // u ∈ M.unobserved}) ∈ S.biUnion (latentBlockIndex M) := by rw [Finset.mem_biUnion] exact ⟨V, hVS, hmemBlock⟩ have hcoord := hagree ⟨u, (Finset.mem_filter.mp hu).1⟩ hmem simpa using hcoord)).mp hlocal · intro hℓ' rw [Set.mem_iInter] at hℓ' rw [Set.mem_iInter] intro V have hℓ'V := hℓ' V rw [Set.mem_iInter] at hℓ'V rw [Set.mem_iInter] intro hVS have hV𝒞 : V ∈ 𝒞 := hS hVS simp [E, hV𝒞] intro v hvV hvP have hlocal : M.localConsistent s x v (h𝒞obs V hV𝒞 hvV) ℓ' := by have hEV : ℓ' ∈ E V := hℓ'V hVS have hEV' : ∀ v (hv : v ∈ V ∩ P), M.localConsistent s x v (h𝒞obs V hV𝒞 (mem_of_mem_inter_left hv)) ℓ' := by simpa [E, hV𝒞] using hEV exact hEV' v (Finset.mem_inter.mpr ⟨hvV, hvP⟩) exact (localConsistent_depends_only_on_latentBlock_of_mem M s x hvV (h𝒞obs V hV𝒞 hvV) ℓ' ℓ (by intro u hu have hmemBlock : (⟨u, (Finset.mem_filter.mp hu).1⟩ : {u // u ∈ M.unobserved}) ∈ latentBlockIndex M V := (mem_latentBlockIndex_iff M V _).mpr hu have hmem : (⟨u, (Finset.mem_filter.mp hu).1⟩ : {u // u ∈ M.unobserved}) ∈ S.biUnion (latentBlockIndex M) := by rw [Finset.mem_biUnion] exact ⟨V, hVS, hmemBlock⟩ have hcoord := hagree ⟨u, (Finset.mem_filter.mp hu).1⟩ hmem simpa using hcoord.symm)).mp hlocal have hmeasU : MeasurableSet[ comap (fun ℓ : M.LatentValues => fun u : latentBlockIndex M U => ℓ u) inferInstance] (E U) := by refine measurableSet_comap_piFinset_of_depends (S := latentBlockIndex M U) _ ?_ intro ℓ ℓ' hagree constructor · intro hℓ simp [E, hU] at hℓ ⊢ intro v hvU hvP have hlocal : M.localConsistent s x v (h𝒞obs U hU hvU) ℓ := hℓ v hvU hvP exact (localConsistent_depends_only_on_latentBlock_of_mem M s x hvU (h𝒞obs U hU hvU) ℓ ℓ' (by intro u hu have hmem : (⟨u, (Finset.mem_filter.mp hu).1⟩ : {u // u ∈ M.unobserved}) ∈ latentBlockIndex M U := (mem_latentBlockIndex_iff M U _).mpr hu have hcoord := hagree ⟨u, (Finset.mem_filter.mp hu).1⟩ hmem simpa using hcoord)).mp hlocal · intro hℓ' simp [E, hU] at hℓ' ⊢ intro v hvU hvP have hlocal : M.localConsistent s x v (h𝒞obs U hU hvU) ℓ' := hℓ' v hvU hvP exact (localConsistent_depends_only_on_latentBlock_of_mem M s x hvU (h𝒞obs U hU hvU) ℓ' ℓ (by intro u hu have hmem : (⟨u, (Finset.mem_filter.mp hu).1⟩ : {u // u ∈ M.unobserved}) ∈ latentBlockIndex M U := (mem_latentBlockIndex_iff M U _).mpr hu have hcoord := hagree ⟨u, (Finset.mem_filter.mp hu).1⟩ hmem simpa using hcoord.symm)).mp hlocal have hinter := hindep.meas_inter (μ := M.latentProduct) hmeasS hmeasU calc M.latentProduct (⋂ V ∈ insert U S, E V) = M.latentProduct ((⋂ V ∈ S, E V) ∩ E U) := by congr 1 ext ℓ simp [E, and_comm] _ = M.latentProduct (⋂ V ∈ S, E V) * M.latentProduct (E U) := by exact hinter _ = (∏ V ∈ S, M.latentProduct (E V)) * M.latentProduct (E U) := by rw [ih hS] _ = ∏ V ∈ insert U S, M.latentProduct (E V) := by rw [Finset.prod_insert hUnot] rw [mul_comm] have hfull := hfactor 𝒞 (fun _ h => h) unfold qLocalMass rw [hevent] rw [hfull] refine Finset.prod_congr rfl ?_ intro U hU simp [E, hU]
    Causalean.SCM.qLocalMass_prod_inter_of_latentBlock_disjoint · Causalean/SCM/ID/Density/QMass.lean:1338
  • qLocalMass_pos_of_positiveObs lemma — Positive observational mass implies nonzero local q-mass.
    M :
    SCM N Ω
    s :
    M.FixedValues
    hpos :
    ID.DiscreteID.PositiveMass (M.obsKernel s)
    ∀ T hT x, M.qLocalMass s T hT x ≠ 0
    Proof (Lean source)
    lemma qLocalMass_pos_of_positiveObs (M : SCM N Ω) (s : M.FixedValues) [MeasurableSingletonClass (ValuesOn M.observed (swigΩ Ω))] (hpos : ID.DiscreteID.PositiveMass (M.obsKernel s)) : ∀ T hT x, M.qLocalMass s T hT x ≠ 0 := by classical intro T hT x have hobs : M.observed ⊆ M.observed := fun ⦃_⦄ hv => hv have hclosed : M.ObsParentClosed M.observed := by refine ⟨hobs, ?_⟩ intro _v _hv _w hw _hedge exact hw have hmass := obsKernel_marginal_singleton_eq_latentProduct_agree M s (P := M.observed) hobs x have hset : {ℓ : M.LatentValues | ∀ v : {v // v ∈ M.observed}, M.evalMap s ℓ ⟨v.val, mem_union_left M.unobserved v.property⟩ = x ⟨v.val, v.property⟩} = {ℓ : M.LatentValues | ∀ v (hv : v ∈ M.observed), M.localConsistent s x v hv ℓ} := by ext ℓ constructor · intro hEval exact (M.evalMap_agree_iff_localConsistent s M.observed hclosed x ℓ).mp (fun v hv => hEval ⟨v, hv⟩) · intro hLocal v exact (M.evalMap_agree_iff_localConsistent s M.observed hclosed x ℓ).mpr hLocal v.val v.property rw [hset] at hmass have hproj_id : (valuesProjection (Ω := swigΩ Ω) hobs : ValuesOn M.observed (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω)) = id := by funext ξ rfl rw [hproj_id, Measure.map_id] at hmass have hfull : M.qLocalMass s M.observed hobs x ≠ 0 := by have hx : (M.obsKernel s) ({x} : Set (ValuesOn M.observed (swigΩ Ω))) ≠ 0 := by simpa [ID.DiscreteID.singletonMass_apply] using hpos x simpa [qLocalMass] using (hmass ▸ hx) have hle : M.qLocalMass s M.observed hobs x ≤ M.qLocalMass s T hT x := M.qLocalMass_anti s (T := T) (T' := M.observed) hT hT hobs x intro hzero exact hfull (le_antisymm (by simpa [hzero] using hle) zero_le)
    Causalean.SCM.qLocalMass_pos_of_positiveObs · Causalean/SCM/ID/Density/QMass.lean:1605
  • prod_filter_div_telescope lemma — Pure ENNReal telescope for products of selected adjacent ratios.
    a :
    ℕ → ENNReal
    m :
    T :
    Finset
    hT :
    T ⊆ range m
    hne :
    ∀ i ≤ m, a i ≠ 0
    hfin :
    ∀ i ≤ m, a i ≠ ⊤
    hconst :
    ∀ i < m
    if
    i ∉ T
    then
    a (i + 1) = a i
    ∏ i ∈ T, a (i + 1) / a i = a m / a 0
    Proof (Lean source)
    lemma prod_filter_div_telescope (a : ℕ → ENNReal) (m : ℕ) (T : Finset ℕ) (hT : T ⊆ range m) (hne : ∀ i ≤ m, a i ≠ 0) (hfin : ∀ i ≤ m, a i ≠ ⊤) (hconst : ∀ i < m, i ∉ T → a (i + 1) = a i) : ∏ i ∈ T, a (i + 1) / a i = a m / a 0 := by classical have hrange_all : ∀ n : ℕ, (∀ i ≤ n, a i ≠ 0) → (∀ i ≤ n, a i ≠ ⊤) → ∏ i ∈ range n, a (i + 1) / a i = a n / a 0 := by intro n hnne hnfin induction n with | zero => simp [ENNReal.div_self (hnne 0 le_rfl) (hnfin 0 le_rfl)] | succ m ih => rw [Finset.prod_range_succ] have hih : ∏ i ∈ range m, a (i + 1) / a i = a m / a 0 := ih (fun i hi => hnne i (Nat.le_trans hi (Nat.le_succ m))) (fun i hi => hnfin i (Nat.le_trans hi (Nat.le_succ m))) rw [hih] rw [div_eq_mul_inv, div_eq_mul_inv, div_eq_mul_inv] rw [show a m * (a 0)⁻¹ * (a (m + 1) * (a m)⁻¹) = a (m + 1) * (a m * (a m)⁻¹) * (a 0)⁻¹ by ac_rfl] rw [ENNReal.mul_inv_cancel (hnne m (Nat.le_succ m)) (hnfin m (Nat.le_succ m))] simp have hrange : ∏ i ∈ range m, a (i + 1) / a i = a m / a 0 := hrange_all m hne hfin have hsubset : ∏ i ∈ T, a (i + 1) / a i = ∏ i ∈ range m, a (i + 1) / a i := by exact Finset.prod_subset hT (by intro i hiRange hiT have hi_lt : i < m := Finset.mem_range.mp hiRange rw [hconst i hi_lt hiT] exact ENNReal.div_self (hne i (le_of_lt hi_lt)) (hfin i (le_of_lt hi_lt))) rw [hsubset, hrange]
    Causalean.SCM.ID.prod_filter_div_telescope · Causalean/SCM/ID/Density/QMass.lean:1776
Mech­CFactor 6 core · 13 supporting The recovery tianDistrictDensity ν_M S =ᵐ cComponentDensityFactor M S used by the density route for ID soundness is, at bottom, the do(X)-invariance of the c-factor Q[S] for a full c-component S. ★ cComponentDensityFactor_eq_mechCFactor★ mechCFactor_fixSet_invariant

Mechanism c-factor Q[S] and its do(X)-invariance (Tian Lemma 4)

The recovery tianDistrictDensity ν_M S =ᵐ cComponentDensityFactor M S used by the density route for ID soundness is, at bottom, the do(X)-invariance of the c-factor Q[S] for a full c-component S. This file isolates the mechanism-level object carrying that content.

mechCFactor M' S is Tian's Q[S] = P_{v∖s}(s) (Eq. 36): intervene on every observed node outside S that is not already fixed in M' (its do-complement) and read off the S-marginal density. The "not already fixed" clause makes the definition apply to the non-standard do-model M.fixSet X (whose fixed set is the fixed copies of X), which is what the invariance step compares against.

Decomposition of the recovery:

* cComponentDensityFactor M S = mechCFactor M S — Tian Lemma 1 (Eq. 37 = Eq. 36): the observational full-prefix product is the do-complement marginal. * mechCFactor (M.fixSet X) S = mechCFactor M S for c-components avoiding X: the c-factor is invariant under interventions outside the component. * tianDistrictDensity ν_M S = mechCFactor (M.fixSet X) S: the district density in the do-law ancestral marginal is the corresponding mechanism c-factor.

Together these results identify the recovered district density with the observational c-component density used by the ID soundness argument.

def mechComplementNames reviewed
Causalean.SCM

Base-node names whose random copy lies in M.observed \ S and whose fixed copy is not already fixed in M — the variables intervened on in Tian's do-complement object Q[S] = P_{v∖s}(s). The "not already fixed" clause lets this apply to non-standard models such as M.fixSet X.

Definition (Lean source)
noncomputable def mechComplementNames (M : SCM N Ω) (S : Finset (SWIGNode N)) : Finset N := Finset.univ.filter fun n => SWIGNode.random n ∈ M.observed \ S ∧ SWIGNode.fixed n ∉ M.fixed
Causalean.SCM.mechComplementNames · Causalean/SCM/ID/Density/MechCFactor.lean:52 · uses SCM , SWIGNode
def mechDoValues reviewed
Causalean.SCM

Fixed-value slice for the do-complement SCM, read from a full observed assignment: keep M's existing fixed slice s and extend it on the do-complement coordinates by projecting x to the random copies in V∖S.

Definition (Lean source)
noncomputable def mechDoValues (M : SCM N Ω) (S : Finset (SWIGNode N)) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) : (M.fixSet (M.mechComplementNames S) (M.mechComplementNames_random_mem_observed S) (M.mechComplementNames_fixed_not_mem S)).FixedValues := M.fixSetExtend (M.mechComplementNames S) (M.mechComplementNames_random_mem_observed S) (M.mechComplementNames_fixed_not_mem S) s (valuesProjection (M.mechComplementNames_image_random_subset_observed S) x)
def QmechMeasure reviewed
Causalean.SCM

Tian's Q[S] measure (Eq. 36 / Eq. 55): the do(observed∖S) marginal on S. Intervene on every not-already-fixed observed node outside S, then project the intervened observational law to the coordinates in S.

Definition (Lean source)
noncomputable def QmechMeasure (M : SCM N Ω) (S : Finset (SWIGNode N)) (hS : S ⊆ M.observed) (sWn : (M.fixSet (M.mechComplementNames S) (M.mechComplementNames_random_mem_observed S) (M.mechComplementNames_fixed_not_mem S)).FixedValues) : Measure (ValuesOn S (swigΩ Ω)) := ((M.fixSet (M.mechComplementNames S) (M.mechComplementNames_random_mem_observed S) (M.mechComplementNames_fixed_not_mem S)).obsKernel sWn).map (valuesProjection (show S ⊆ (M.fixSet (M.mechComplementNames S) (M.mechComplementNames_random_mem_observed S) (M.mechComplementNames_fixed_not_mem S)).observed by simpa [fixSet_observed] using hS))
def mechCFactor reviewed
Causalean.SCM

The mechanism c-factor density Q[S] as a function of a full observed assignment x: read the do-values for V∖S from x (keeping M's fixed slice s), form the do-complement marginal on S, and take its rnDeriv against the product reference on S, evaluated at the S-projection of x.

Definition (Lean source)
noncomputable def mechCFactor (M : SCM N Ω) (ref : ReferenceMeasures Ω) (S : Finset (SWIGNode N)) (hS : S ⊆ M.observed) (s : M.FixedValues) : ValuesOn M.observed (swigΩ Ω) → ENNReal := fun x => (QmechMeasure M S hS (M.mechDoValues S s x)).rnDeriv (jointRef ref S) (valuesProjection hS x)
lemma cComponentDensityFactor_eq_mechCFactor reviewed
Causalean.SCM.ID

(A) Tian Lemma 1 (Eq. 37 = Eq. 36). For a standard causal model M, i.e. one with no fixed nodes, a reference family that is faithful — every coordinate value has nonzero reference mass, and an observational kernel at a fixed-value slice s with full point-mass support (every observed assignment has nonzero probability), fix a node set S contained in the observed coordinates that is a full c-component of the model's SWIG graph. Then the observational full-prefix c-component density cComponentDensityFactor on S equals the mechanism c-factor Q[S] (mechCFactor) — the do-complement marginal density of S.

Formal statement
∀ n, Fintype (Ω n)
M :
SCM N Ω
s :
M.FixedValues
hStd :
M.isStandard
S :
hS :
S ⊆ M.observed
hScomp :
S ∈ M.toSWIGGraph.cComponentSet
href :
hpos :
DiscreteID.PositiveMass (M.obsKernel s)
∀ s' :
M.FixedValues, IsFiniteMeasure (M.obsKernel s')
∀ (k : ℕ) (hk : k < M.observed.card),
StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ (k : ℕ) (hk : k < M.observed.card),
Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ k :
ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))
x :
ValuesOn M.observed (swigΩ Ω)
M.cComponentDensityFactor ref s S x = M.mechCFactor ref S hS s x
Proof (Lean source)
lemma cComponentDensityFactor_eq_mechCFactor [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) (hStd : M.isStandard) (S : Finset (SWIGNode N)) (hS : S ⊆ M.observed) (hScomp : S ∈ M.toSWIGGraph.cComponentSet) (href : ReferenceFaithful ref) (hpos : DiscreteID.PositiveMass (M.obsKernel s)) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [∀ (k : ℕ) (hk : k < M.observed.card), StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M.observed.card), Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))] (x : ValuesOn M.observed (swigΩ Ω)) : M.cComponentDensityFactor ref s S x = M.mechCFactor ref S hS s x := by classical let I : Finset (Fin M.observed.card) := Finset.univ.filter (fun i : Fin M.observed.card => M.toSWIGGraph.cComponentOf (M.observedAt i).val = S) let num : Fin M.observed.card → ENNReal := fun i => M.qLocalMass s (S ∩ M.prefixNodes (i.val + 1)) (fun _ hv => M.prefixNodes_subset_observed (i.val + 1) (mem_of_mem_inter_right hv)) x let den : Fin M.observed.card → ENNReal := fun i => M.qLocalMass s (S ∩ M.prefixNodes i.val) (fun _ hv => M.prefixNodes_subset_observed i.val (mem_of_mem_inter_right hv)) x let atom : Fin M.observed.card → ENNReal := fun i => ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val)) have hsteps : M.cComponentDensityFactor ref s S x = ∏ i ∈ I, (num i / den i) / atom i := by unfold cComponentDensityFactor refine Finset.prod_congr rfl ?_ intro i hi have hiS : M.toSWIGGraph.cComponentOf (M.observedAt i).val = S := (Finset.mem_filter.mp hi).2 exact obsStepCondDensity_eq_component_ratio_div_ref M ref s S hScomp i hiS href hpos x have hatom0 : ∀ i ∈ I, atom i ≠ 0 := by intro i _hi exact href (M.observedAt i).val (x (M.observedAt i)) have hatomtop : ∀ i ∈ I, atom i ≠ ∞ := by intro i _hi exact ne_of_lt (MeasureTheory.measure_lt_top (ref.μ (M.observedAt i).val) ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val))) have hsplit : (∏ i ∈ I, (num i / den i) / atom i) = (∏ i ∈ I, num i / den i) / (∏ i ∈ I, atom i) := ENNReal.prod_div_prod₂ I num den atom hatom0 hatomtop have hnum : (∏ i ∈ I, num i / den i) = M.qLocalMass s S hS x := by simpa [I, num, den] using component_qLocalMass_ratio_product M s S hS hScomp hpos x have hrefprod : (∏ i ∈ I, atom i) = jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω))) := by simpa [I, atom] using component_ref_atom_product_eq_jointRef M ref S hS hScomp x have hanchor : M.mechCFactor ref S hS s x = M.qLocalMass s S hS x / jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω))) := mechCFactor_eq_qLocalMass_div_jointRef M ref s S hS href (standard_fixed_random_edgeless M hStd) x calc M.cComponentDensityFactor ref s S x = ∏ i ∈ I, (num i / den i) / atom i := hsteps _ = (∏ i ∈ I, num i / den i) / (∏ i ∈ I, atom i) := hsplit _ = M.qLocalMass s S hS x / jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω))) := by rw [hnum, hrefprod] _ = M.mechCFactor ref S hS s x := hanchor.symm
lemma mechCFactor_fixSet_invariant reviewed
Causalean.SCM.ID

Do(X)-invariance of the c-factor Q[S] (Tian Lemma 4). Let an intervention set X have random copies that are all observed and fixed copies that are not already fixed in the base model, giving the intervened model M.fixSet X. For a standard base model M, a reference family that is faithful, and a node set S contained in the observed coordinates whose random copies avoid every intervened node in X, if the base assignment x records, at each intervened node, the same value that the intervened model's fixed values sDo assign to the corresponding fixed coordinate, then the S-c-factor Q[S] of the intervened model M.fixSet X at sDo, x equals the S-c-factor of the base model M at the projected fixed values M.fixSetProj X sDo, x.

Formal statement
∀ n, Fintype (Ω n)
M :
SCM N Ω
X :
href :
hStd :
M.isStandard
hObs :
∀ D ∈ X, SWIGNode.random D ∈ M.observed
hFix :
∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
S :
hS :
S ⊆ M.observed
hSX :
∀ n ∈ X, SWIGNode.random n ∉ S
sDo :
(M.fixSet X hObs hFix).FixedValues
x :
ValuesOn M.observed (swigΩ Ω)
hpin :
∀ D (hD : D ∈ X),
x ⟨SWIGNode.random D, hObs D hD⟩
= sDo ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩
(M.fixSet X hObs hFix).mechCFactor ref S (by simpa [fixSet_observed] using hS) sDo x
= M.mechCFactor ref S hS (M.fixSetProj X hObs hFix sDo) x
Proof (Lean source)
lemma mechCFactor_fixSet_invariant [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (ref : ReferenceMeasures Ω) (X : Finset N) (href : ReferenceFaithful ref) (hStd : M.isStandard) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (S : Finset (SWIGNode N)) (hS : S ⊆ M.observed) (hSX : ∀ n ∈ X, SWIGNode.random n ∉ S) (sDo : (M.fixSet X hObs hFix).FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) (hpin : ∀ D (hD : D ∈ X), x ⟨SWIGNode.random D, hObs D hD⟩ = sDo ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩) : (M.fixSet X hObs hFix).mechCFactor ref S (by simpa [fixSet_observed] using hS) sDo x = M.mechCFactor ref S hS (M.fixSetProj X hObs hFix sDo) x := by classical let MX := M.fixSet X hObs hFix let hSXobs : S ⊆ MX.observed := by simpa [MX, fixSet_observed] using hS have hfeX : ∀ n : N, SWIGNode.fixed n ∈ MX.fixed → ∀ v : SWIGNode N, ¬ MX.dag.edge (SWIGNode.random n) v := by simpa [MX] using fixSet_fixed_random_edgeless M X hObs hFix hStd have hfeM : ∀ n : N, SWIGNode.fixed n ∈ M.fixed → ∀ v : SWIGNode N, ¬ M.dag.edge (SWIGNode.random n) v := standard_fixed_random_edgeless M hStd have hq : MX.qLocalMass sDo S hSXobs x = M.qLocalMass (M.fixSetProj X hObs hFix sDo) S hS x := qLocalMass_fixSet_invariant M X hObs hFix sDo S hS hSX x hpin have hnumX : QmechMeasure MX S hSXobs (MX.mechDoValues S sDo x) {valuesProjection hSXobs x} = MX.qLocalMass sDo S hSXobs x := QmechMeasure_singleton_eq_qLocalMass MX S hSXobs hfeX sDo x have hnumM : QmechMeasure M S hS (M.mechDoValues S (M.fixSetProj X hObs hFix sDo) x) {valuesProjection hS x} = M.qLocalMass (M.fixSetProj X hObs hFix sDo) S hS x := QmechMeasure_singleton_eq_qLocalMass M S hS hfeM (M.fixSetProj X hObs hFix sDo) x have hprojPoint : valuesProjection hSXobs x = valuesProjection hS x := by ext v rfl have hden0X : jointRef ref S ({valuesProjection hSXobs x} : Set (ValuesOn S (swigΩ Ω))) ≠ 0 := jointRef_singleton_ne_zero ref href S (valuesProjection hSXobs x) have hdenTopX : jointRef ref S ({valuesProjection hSXobs x} : Set (ValuesOn S (swigΩ Ω))) ≠ ∞ := by exact ne_of_lt (MeasureTheory.measure_lt_top (jointRef ref S) ({valuesProjection hSXobs x} : Set (ValuesOn S (swigΩ Ω)))) have hden0M : jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω))) ≠ 0 := jointRef_singleton_ne_zero ref href S (valuesProjection hS x) have hdenTopM : jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω))) ≠ ∞ := by exact ne_of_lt (MeasureTheory.measure_lt_top (jointRef ref S) ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω)))) unfold mechCFactor rw [rnDeriv_singleton_eq_div _ _ (absolutelyContinuous_jointRef_of_faithful ref href S (QmechMeasure MX S hSXobs (MX.mechDoValues S sDo x))) (valuesProjection hSXobs x) hden0X hdenTopX] rw [rnDeriv_singleton_eq_div _ _ (absolutelyContinuous_jointRef_of_faithful ref href S (QmechMeasure M S hS (M.mechDoValues S (M.fixSetProj X hObs hFix sDo) x))) (valuesProjection hS x) hden0M hdenTopM] rw [hnumX, hnumM, hq, hprojPoint]
13 supporting declarations (lemmas, instances)
  • mechComplementNames_random_mem_observed lemma — Every mechanism-complement variable has its random copy among the observed nodes.
    M :
    SCM N Ω
    S :
    ∀ n ∈ M.mechComplementNames S, SWIGNode.random n ∈ M.observed
    Proof (Lean source)
    lemma mechComplementNames_random_mem_observed (M : SCM N Ω) (S : Finset (SWIGNode N)) : ∀ n ∈ M.mechComplementNames S, SWIGNode.random n ∈ M.observed := by intro n hn exact (Finset.mem_sdiff.mp (Finset.mem_filter.mp hn).2.1).1
    Causalean.SCM.mechComplementNames_random_mem_observed · Causalean/SCM/ID/Density/MechCFactor.lean:61
  • mechComplementNames_fixed_not_mem lemma — Every mechanism-complement variable has a fixed copy that is not already fixed.
    M :
    SCM N Ω
    S :
    ∀ n ∈ M.mechComplementNames S, SWIGNode.fixed n ∉ M.fixed
    Proof (Lean source)
    lemma mechComplementNames_fixed_not_mem (M : SCM N Ω) (S : Finset (SWIGNode N)) : ∀ n ∈ M.mechComplementNames S, SWIGNode.fixed n ∉ M.fixed := by intro n hn exact (Finset.mem_filter.mp hn).2.2
    Causalean.SCM.mechComplementNames_fixed_not_mem · Causalean/SCM/ID/Density/MechCFactor.lean:68
  • mechComplementNames_image_random_subset_observed lemma — The random copies of the mechanism-complement variables form a subset of the observed nodes.
    M :
    SCM N Ω
    S :
    (M.mechComplementNames S).image SWIGNode.random ⊆ M.observed
    Proof (Lean source)
    lemma mechComplementNames_image_random_subset_observed (M : SCM N Ω) (S : Finset (SWIGNode N)) : (M.mechComplementNames S).image SWIGNode.random ⊆ M.observed := by intro v hv rcases Finset.mem_image.mp hv with ⟨n, hn, rfl⟩ exact M.mechComplementNames_random_mem_observed S n hn
    Causalean.SCM.mechComplementNames_image_random_subset_observed · Causalean/SCM/ID/Density/MechCFactor.lean:75
  • QmechMeasure_singleton_eq_qLocalMass theorem — The do-complement Q[S] atom equals the local q-mass on S.
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    S :
    hS :
    S ⊆ M.observed
    hfe :
    ∀ n : N
    if
    SWIGNode.fixed n ∈ M.fixed
    then
    ∀ v : SWIGNode N, ¬ M.dag.edge (SWIGNode.random n) v
    s :
    M.FixedValues
    x :
    ValuesOn M.observed (swigΩ Ω)
    QmechMeasure M S hS (M.mechDoValues S s x) {valuesProjection hS x} = M.qLocalMass s S hS x
    Proof (Lean source)
    theorem QmechMeasure_singleton_eq_qLocalMass [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (S : Finset (SWIGNode N)) (hS : S ⊆ M.observed) (hfe : ∀ n : N, SWIGNode.fixed n ∈ M.fixed → ∀ v : SWIGNode N, ¬ M.dag.edge (SWIGNode.random n) v) (s : M.FixedValues) (x : ValuesOn M.observed (swigΩ Ω)) : QmechMeasure M S hS (M.mechDoValues S s x) {valuesProjection hS x} = M.qLocalMass s S hS x := by classical let W := M.mechComplementNames S let hWobs := M.mechComplementNames_random_mem_observed S let hWfix := M.mechComplementNames_fixed_not_mem S let M' := M.fixSet W hWobs hWfix let s' : M'.FixedValues := M.mechDoValues S s x have hclosed : M'.ObsParentClosed S := by simpa [M', W, hWobs, hWfix] using mechComplement_fixSet_obsParentClosed M S hS hfe let hS' : S ⊆ M'.observed := hclosed.1 have hbridge := obsKernel_marginal_singleton_eq_latentProduct_agree M' s' hS' x have heval_local : {ℓ | ∀ v : {v // v ∈ S}, M'.evalMap s' ℓ ⟨v.val, mem_union_left M'.unobserved (hS' v.property)⟩ = x ⟨v.val, hS' v.property⟩} = {ℓ | ∀ v (hv : v ∈ S), M'.localConsistent s' x v (hS' hv) ℓ} := by ext ℓ constructor · intro hEval exact (M'.evalMap_agree_iff_localConsistent s' S hclosed x ℓ).mp (fun v hv => hEval ⟨v, hv⟩) · intro hLocal v exact (M'.evalMap_agree_iff_localConsistent s' S hclosed x ℓ).mpr hLocal v.val v.property have hobsAgree : ∀ w (hw : w ∈ M.observed), x ⟨w, by simpa [M', W, hWobs, hWfix, fixSet_observed] using hw⟩ = x ⟨w, hw⟩ := by intro w hw rfl have hpin : ∀ D (hD : D ∈ W), x ⟨SWIGNode.random D, hWobs D hD⟩ = s' ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩ := by intro D hD have hnew := M.fixSetExtend_apply_new_fixed W hWobs hWfix s (valuesProjection (M.mechComplementNames_image_random_subset_observed S) x) hD simp only [s', mechDoValues] exact hnew.symm have hproj : M.fixSetProj W hWobs hWfix s' = s := by simpa [s', W, hWobs, hWfix, mechDoValues] using (M.fixSetProj_fixSetExtend W hWobs hWfix s (valuesProjection (M.mechComplementNames_image_random_subset_observed S) x)) have hset_do : {ℓ | ∀ v (hv : v ∈ S), M'.localConsistent s' x v (hS' hv) ℓ} = {ℓ | ∀ v (hv : v ∈ S), M.localConsistent s x v (hS hv) ℓ} := by ext ℓ constructor · intro hLocal v hv have hnot : v ∉ W.image SWIGNode.random := by intro hvW rcases Finset.mem_image.mp hvW with ⟨D, hD, rfl⟩ exact (Finset.mem_sdiff.mp (Finset.mem_filter.mp hD).2.1).2 hv exact (localConsistent_fixSet_iff M W hWobs hWfix s' s x x v (hS' hv) (hS hv) hnot hobsAgree hpin hproj ℓ).mp (hLocal v hv) · intro hLocal v hv have hnot : v ∉ W.image SWIGNode.random := by intro hvW rcases Finset.mem_image.mp hvW with ⟨D, hD, rfl⟩ exact (Finset.mem_sdiff.mp (Finset.mem_filter.mp hD).2.1).2 hv exact (localConsistent_fixSet_iff M W hWobs hWfix s' s x x v (hS' hv) (hS hv) hnot hobsAgree hpin hproj ℓ).mpr (hLocal v hv) calc QmechMeasure M S hS (M.mechDoValues S s x) {valuesProjection hS x} = ((M'.obsKernel s').map (valuesProjection hS')) {valuesProjection hS' x} := by rfl _ = M'.latentProduct {ℓ | ∀ v : {v // v ∈ S}, M'.evalMap s' ℓ ⟨v.val, mem_union_left M'.unobserved (hS' v.property)⟩ = x ⟨v.val, hS' v.property⟩} := hbridge _ = M'.latentProduct {ℓ | ∀ v (hv : v ∈ S), M'.localConsistent s' x v (hS' hv) ℓ} := by rw [heval_local] _ = M.latentProduct {ℓ | ∀ v (hv : v ∈ S), M.localConsistent s x v (hS hv) ℓ} := by rw [hset_do] rfl _ = M.qLocalMass s S hS x := by rfl
    Causalean.SCM.QmechMeasure_singleton_eq_qLocalMass · Causalean/SCM/ID/Density/MechCFactor.lean:170
  • standard_fixed_random_edgeless lemma
    M :
    SCM N Ω
    hStd :
    M.isStandard
    ∀ n : N
    if
    SWIGNode.fixed n ∈ M.fixed
    then
    ∀ v : SWIGNode N, ¬ M.dag.edge (SWIGNode.random n) v
    Proof (Lean source)
    lemma standard_fixed_random_edgeless (M : SCM N Ω) (hStd : M.isStandard) : ∀ n : N, SWIGNode.fixed n ∈ M.fixed → ∀ v : SWIGNode N, ¬ M.dag.edge (SWIGNode.random n) v := by intro n hn rw [SCM.isStandard] at hStd rw [hStd] at hn simp at hn
    Causalean.SCM.standard_fixed_random_edgeless · Causalean/SCM/ID/Density/MechCFactor.lean:259
  • prefixNodes_obsParentClosed lemma — The first k observed nodes in a structural causal model's topological order form a set closed under observed parents.
    M :
    SCM N Ω
    k :
    M.ObsParentClosed (M.prefixNodes k)
    Proof (Lean source)
    lemma prefixNodes_obsParentClosed (M : SCM N Ω) (k : ℕ) : M.ObsParentClosed (M.prefixNodes k) := by classical refine ⟨M.prefixNodes_subset_observed k, ?_⟩ intro v hv w hwObs hEdge rcases (M.mem_prefixNodes_iff k v).mp hv with ⟨hvObs, hvlt⟩ let i : Fin M.observed.card := M.observedIndex ⟨v, hvObs⟩ have hi_eq : (M.observedAt i).val = v := by exact M.observedAt_observedIndex ⟨v, hvObs⟩ have hwPred : w ∈ M.toSWIGGraph.observedPredecessors (M.observedAt i).val := by rw [hi_eq] exact Finset.mem_filter.mpr ⟨hwObs, M.dag.topoOrder_lt w v hEdge⟩ have hwPrefixI : w ∈ M.prefixNodes i.val := by simpa using ((M.observedPredecessors_observedAt i.isLt).symm ▸ hwPred) exact M.prefixNodes_mono (show i.val ≤ k from le_of_lt hvlt) hwPrefixI
    Causalean.SCM.ID.prefixNodes_obsParentClosed · Causalean/SCM/ID/Density/MechCFactor.lean:299
  • qLocalMass_ne_top lemma — Every local q-mass associated with fixed values, an observed node set, and an observed assignment is finite.
    M :
    SCM N Ω
    s :
    M.FixedValues
    T :
    hT :
    T ⊆ M.observed
    x :
    ValuesOn M.observed (swigΩ Ω)
    M.qLocalMass s T hT x ≠ ∞
    Proof (Lean source)
    lemma qLocalMass_ne_top (M : SCM N Ω) (s : M.FixedValues) (T : Finset (SWIGNode N)) (hT : T ⊆ M.observed) (x : ValuesOn M.observed (swigΩ Ω)) : M.qLocalMass s T hT x ≠ ∞ := by exact ne_of_lt (MeasureTheory.measure_lt_top M.latentProduct _)
    Causalean.SCM.ID.qLocalMass_ne_top · Causalean/SCM/ID/Density/MechCFactor.lean:351
  • div_mul_common lemma — Cancelling a common nonzero finite factor preserves a quotient of extended nonnegative reals.
    a b r :
    hr0 :
    r ≠ 0
    hrtop :
    r ≠ ∞
    (a * r) / (b * r) = a / b
    Proof (Lean source)
    lemma ENNReal.div_mul_common {a b r : ENNReal} (hr0 : r ≠ 0) (hrtop : r ≠ ∞) : (a * r) / (b * r) = a / b := by rw [ENNReal.div_eq_inv_mul, ENNReal.div_eq_inv_mul] rw [ENNReal.mul_inv] · rw [show b⁻¹ * r⁻¹ * (a * r) = (r⁻¹ * r) * (b⁻¹ * a) by ac_rfl] rw [ENNReal.inv_mul_cancel hr0 hrtop] simp [mul_comm] · exact inr hrtop · exact inr hr0
    Causalean.SCM.ID.ENNReal.div_mul_common · Causalean/SCM/ID/Density/MechCFactor.lean:360
  • prod_ne_top_of_ne_top lemma — A finite product of finite extended nonnegative reals is finite.
    ι :
    Type*
    s :
    f :
    ι → ENNReal
    hf :
    ∀ i ∈ s, f i ≠ ∞
    (∏ i ∈ s, f i) ≠ ∞
    Proof (Lean source)
    lemma Finset.prod_ne_top_of_ne_top {ι : Type*} [DecidableEq ι] (s : Finset ι) (f : ι → ENNReal) (hf : ∀ i ∈ s, f i ≠ ∞) : (∏ i ∈ s, f i) ≠ ∞ := by classical induction s using Finset.induction_on with | empty => simp | insert a s ha ih => rw [Finset.prod_insert ha] exact ENNReal.mul_ne_top (hf a (mem_insert_self a s)) (ih (by intro i hi; exact hf i (mem_insert_of_mem hi)))
    Causalean.SCM.ID.Finset.prod_ne_top_of_ne_top · Causalean/SCM/ID/Density/MechCFactor.lean:372
  • prod_div_prod lemma — A finite product of quotients is the quotient of the finite products when denominators are nonzero and finite.
    ι :
    Type*
    t :
    f g :
    ι → ENNReal
    hg0 :
    ∀ i ∈ t, g i ≠ 0
    hgtop :
    ∀ i ∈ t, g i ≠ ∞
    (∏ i ∈ t, f i / g i) = (∏ i ∈ t, f i) / (∏ i ∈ t, g i)
    Proof (Lean source)
    lemma ENNReal.prod_div_prod {ι : Type*} [DecidableEq ι] (t : Finset ι) (f g : ι → ENNReal) (hg0 : ∀ i ∈ t, g i ≠ 0) (hgtop : ∀ i ∈ t, g i ≠ ∞) : (∏ i ∈ t, f i / g i) = (∏ i ∈ t, f i) / (∏ i ∈ t, g i) := by classical induction t using Finset.induction_on with | empty => simp | insert a t ha ih => have ih' : (∏ i ∈ t, f i / g i) = (∏ i ∈ t, f i) / (∏ i ∈ t, g i) := ih (by intro i hi; exact hg0 i (mem_insert_of_mem hi)) (by intro i hi; exact hgtop i (mem_insert_of_mem hi)) have hprod0 : (∏ i ∈ t, g i) ≠ 0 := by exact Finset.prod_ne_zero_iff.mpr (by intro i hi exact hg0 i (mem_insert_of_mem hi)) have hprodtop : (∏ i ∈ t, g i) ≠ ∞ := by exact Finset.prod_ne_top_of_ne_top _ g (by intro i hi exact hgtop i (mem_insert_of_mem hi)) rw [Finset.prod_insert ha, Finset.prod_insert ha, Finset.prod_insert ha, ih'] rw [div_eq_mul_inv, div_eq_mul_inv, div_eq_mul_inv] rw [ENNReal.mul_inv] · ac_rfl · exact inr hprodtop · exact inr hprod0
    Causalean.SCM.ID.ENNReal.prod_div_prod · Causalean/SCM/ID/Density/MechCFactor.lean:675
  • mechCFactor_eq_qLocalMass_div_jointRef lemma
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    s :
    M.FixedValues
    S :
    hS :
    S ⊆ M.observed
    href :
    hfe :
    ∀ n : N
    if
    SWIGNode.fixed n ∈ M.fixed
    then
    ∀ v : SWIGNode N, ¬ M.dag.edge (SWIGNode.random n) v
    x :
    ValuesOn M.observed (swigΩ Ω)
    M.mechCFactor ref S hS s x
    = M.qLocalMass s S hS x / jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω)))
    Proof (Lean source)
    lemma mechCFactor_eq_qLocalMass_div_jointRef [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) (S : Finset (SWIGNode N)) (hS : S ⊆ M.observed) (href : ReferenceFaithful ref) (hfe : ∀ n : N, SWIGNode.fixed n ∈ M.fixed → ∀ v : SWIGNode N, ¬ M.dag.edge (SWIGNode.random n) v) (x : ValuesOn M.observed (swigΩ Ω)) : M.mechCFactor ref S hS s x = M.qLocalMass s S hS x / jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω))) := by have hnum : QmechMeasure M S hS (M.mechDoValues S s x) {valuesProjection hS x} = M.qLocalMass s S hS x := QmechMeasure_singleton_eq_qLocalMass M S hS hfe s x have hden0 : jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω))) ≠ 0 := jointRef_singleton_ne_zero ref href S (valuesProjection hS x) have hdenTop : jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω))) ≠ ∞ := by exact ne_of_lt (MeasureTheory.measure_lt_top (jointRef ref S) ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω)))) unfold mechCFactor rw [rnDeriv_singleton_eq_div _ _ (absolutelyContinuous_jointRef_of_faithful ref href S (QmechMeasure M S hS (M.mechDoValues S s x))) (valuesProjection hS x) hden0 hdenTop] rw [hnum]
    Causalean.SCM.ID.mechCFactor_eq_qLocalMass_div_jointRef · Causalean/SCM/ID/Density/MechCFactor.lean:710
  • component_ref_atom_product_eq_jointRef lemma — Multiplying the singleton reference masses for all observed variables in one c-component equals the singleton mass of their joint reference measure.
    M :
    SCM N Ω
    S :
    hS :
    S ⊆ M.observed
    hScomp :
    S ∈ M.toSWIGGraph.cComponentSet
    x :
    ValuesOn M.observed (swigΩ Ω)
    (∏ i ∈ Finset.univ.filter (fun i : Fin M.observed.card => M.toSWIGGraph.cComponentOf (M.observedAt i).val = S), ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val)))
    = jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω)))
    Proof (Lean source)
    lemma component_ref_atom_product_eq_jointRef [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (ref : ReferenceMeasures Ω) (S : Finset (SWIGNode N)) (hS : S ⊆ M.observed) (hScomp : S ∈ M.toSWIGGraph.cComponentSet) (x : ValuesOn M.observed (swigΩ Ω)) : (∏ i ∈ Finset.univ.filter (fun i : Fin M.observed.card => M.toSWIGGraph.cComponentOf (M.observedAt i).val = S), ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val))) = jointRef ref S ({valuesProjection hS x} : Set (ValuesOn S (swigΩ Ω))) := by classical have hprod : (∏ i ∈ Finset.univ.filter (fun i : Fin M.observed.card => M.toSWIGGraph.cComponentOf (M.observedAt i).val = S), ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val))) = ∏ v : {v // v ∈ S}, ref.μ v.val ({(valuesProjection hS x) v} : Set (swigΩ Ω v.val)) := by refine Finset.prod_bij (fun i hi => ⟨(M.observedAt i).val, (mem_cComponent_iff_cComponentOf_eq M.toSWIGGraph (M.observedAt i).property hScomp).mpr (Finset.mem_filter.mp hi).2⟩) ?_ ?_ ?_ ?_ · intro i hi exact Finset.mem_univ _ · intro i _hi j _hj hij have hval : (M.observedAt i).val = (M.observedAt j).val := congrArg (fun v : {v // v ∈ S} => v.val) hij have hsub : M.observedAt i = M.observedAt j := Subtype.ext hval calc i = M.observedIndex (M.observedAt i) := (M.observedIndex_observedAt i).symm _ = M.observedIndex (M.observedAt j) := by rw [hsub] _ = j := M.observedIndex_observedAt j · intro v _hv let i : Fin M.observed.card := M.observedIndex ⟨v.val, hS v.property⟩ have hnode : (M.observedAt i).val = v.val := M.observedAt_observedIndex ⟨v.val, hS v.property⟩ refine ⟨i, ?_, ?_⟩ · rw [mem_filter] refine ⟨Finset.mem_univ _, ?_⟩ have hvcomp : M.toSWIGGraph.cComponentOf v.val = S := (mem_cComponent_iff_cComponentOf_eq M.toSWIGGraph (hS v.property) hScomp).mp v.property simpa [hnode] using hvcomp · exact Subtype.ext hnode · intro i hi simp [valuesProjection] rw [jointRef_singleton_eq_prod] exact hprod
    Causalean.SCM.ID.component_ref_atom_product_eq_jointRef · Causalean/SCM/ID/Density/MechCFactor.lean:856
  • qLocalMass_fixSet_invariant lemma — Local q-mass is invariant under a fixSet intervention when no coordinate in S is one of the intervened random nodes and the full assignment pins each intervened random node to the corresponding fixed value.
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    sDo :
    (M.fixSet X hObs hFix).FixedValues
    S :
    hS :
    S ⊆ M.observed
    hSX :
    ∀ n ∈ X, SWIGNode.random n ∉ S
    x :
    ValuesOn M.observed (swigΩ Ω)
    hpin :
    ∀ D (hD : D ∈ X),
    x ⟨SWIGNode.random D, hObs D hD⟩
    = sDo ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩
    (M.fixSet X hObs hFix).qLocalMass sDo S (by simpa [fixSet_observed] using hS) x
    = M.qLocalMass (M.fixSetProj X hObs hFix sDo) S hS x
    Proof (Lean source)
    lemma qLocalMass_fixSet_invariant (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (sDo : (M.fixSet X hObs hFix).FixedValues) (S : Finset (SWIGNode N)) (hS : S ⊆ M.observed) (hSX : ∀ n ∈ X, SWIGNode.random n ∉ S) (x : ValuesOn M.observed (swigΩ Ω)) (hpin : ∀ D (hD : D ∈ X), x ⟨SWIGNode.random D, hObs D hD⟩ = sDo ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩) : (M.fixSet X hObs hFix).qLocalMass sDo S (by simpa [fixSet_observed] using hS) x = M.qLocalMass (M.fixSetProj X hObs hFix sDo) S hS x := by classical let MX := M.fixSet X hObs hFix let hSXobs : S ⊆ MX.observed := by simpa [MX, fixSet_observed] using hS have hobsAgree : ∀ w (hw : w ∈ M.observed), x ⟨w, by simpa [MX, fixSet_observed] using hw⟩ = x ⟨w, hw⟩ := by intro w hw rfl have hproj : M.fixSetProj X hObs hFix sDo = M.fixSetProj X hObs hFix sDo := rfl unfold qLocalMass congr 1 ext ℓ constructor · intro hLocal v hv have hnot : v ∉ X.image SWIGNode.random := by intro hvX rcases Finset.mem_image.mp hvX with ⟨D, hD, rfl⟩ exact hSX D hD hv exact (localConsistent_fixSet_iff M X hObs hFix sDo (M.fixSetProj X hObs hFix sDo) x x v (hSXobs hv) (hS hv) hnot hobsAgree hpin hproj ℓ).mp (hLocal v hv) · intro hLocal v hv have hnot : v ∉ X.image SWIGNode.random := by intro hvX rcases Finset.mem_image.mp hvX with ⟨D, hD, rfl⟩ exact hSX D hD hv exact (localConsistent_fixSet_iff M X hObs hFix sDo (M.fixSetProj X hObs hFix sDo) x x v (hSXobs hv) (hS hv) hnot hobsAgree hpin hproj ℓ).mpr (hLocal v hv)
    Causalean.SCM.ID.qLocalMass_fixSet_invariant · Causalean/SCM/ID/Density/MechCFactor.lean:1020
Counting­Reference 3 core · 0 supporting On finite node value spaces the canonical reference family is the per-node counting measure. ★ referenceFaithful_countingRef★ dominatedObs_countingRef

The counting reference measure for finite discrete models

On finite node value spaces the canonical reference family is the per-node counting measure. It is faithful — every singleton has counting mass one — so, via absolutelyContinuous_jointRef_of_faithful, every structural causal model is dominated by it. This supplies the domination half of the general density-route identification theorem id_sound, whose model class is DominatedObs · ref ∧ DiscretePositive; the positivity half is supplied by the standard discrete positive model class.

def countingRef reviewed
Causalean.SCM

The counting reference family: each SWIG-node coordinate carries the counting measure. On countable value spaces this is a σ-finite measure.

Definition (Lean source)
noncomputable def countingRef [∀ sn, Countable (swigΩ Ω sn)] [∀ n, MeasurableSingletonClass (Ω n)] : ReferenceMeasures Ω where μ := fun _ => MeasureTheory.Measure.count sigmaFinite := fun _ => by infer_instance
lemma referenceFaithful_countingRef reviewed
Causalean.SCM

The counting reference family is faithful: every singleton coordinate value has counting mass one, in particular nonzero.

Formal statement
∀ sn, Countable (swigΩ Ω sn)
Proof (Lean source)
lemma referenceFaithful_countingRef [∀ sn, Countable (swigΩ Ω sn)] [∀ n, MeasurableSingletonClass (Ω n)] : ReferenceFaithful (countingRef (Ω := Ω)) := by intro v x unfold countingRef rw [MeasureTheory.Measure.count_singleton] exact one_ne_zero
lemma dominatedObs_countingRef reviewed
Causalean.SCM

For every structural causal model M, each of its observational laws is absolutely continuous with respect to the counting reference family's product measure, because a faithful reference dominates every measure on a countable coordinate product. Note this holds for all M, with no positivity or graph hypothesis.

Formal statement
∀ sn, Countable (swigΩ Ω sn)
M :
SCM N Ω
DominatedObs M (countingRef (Ω := Ω))
Proof (Lean source)
lemma dominatedObs_countingRef [∀ sn, Countable (swigΩ Ω sn)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) : DominatedObs M (countingRef (Ω := Ω)) := by intro s exact absolutelyContinuous_jointRef_of_faithful (countingRef (Ω := Ω)) referenceFaithful_countingRef M.observed (M.obsKernel s)
Do­Law­Marginal 2 core · 0 supporting This file collects foundational facts used to identify the Y-marginal of the do-law from observational densities. ★ obsDensity_heq_of_obsKernel_heq★ obsKernel_heq_of_obsDensity_heq

Foundational helpers for the do-law Y-marginal

This file collects foundational facts used to identify the Y-marginal of the do-law from observational densities. It currently provides cross-model density transport: two structural causal models sharing the same SWIG graph and the same observational kernel also share the same observational density, so densities transport across models that agree on those data. This is the step that turns the hypothesis "the two models have the same observational law" into "the two models have the same observational density", from which the recovered c-factors — and hence the identifiable do-law Y-marginal — are read off.

lemma obsDensity_heq_of_obsKernel_heq reviewed
Causalean.SCM

Cross-model density transport. If two structural causal models M₁ and M₂ share the same SWIG graph and have heterogeneously-equal observational kernels, then their observational densities are heterogeneously equal. After unifying the SWIG-graph data the observed-value types coincide, the observational kernels become literally equal, and the density is the Radon–Nikodym derivative of that kernel against a fixed reference measure.

Formal statement
M₁ M₂ :
SCM N Ω
hsg :
M₁.toSWIGGraph = M₂.toSWIGGraph
hobs :
HEq M₁.obsKernel M₂.obsKernel
HEq (M₁.obsDensity ref) (M₂.obsDensity ref)
Proof (Lean source)
lemma obsDensity_heq_of_obsKernel_heq (M₁ M₂ : SCM N Ω) (ref : ReferenceMeasures Ω) (hsg : M₁.toSWIGGraph = M₂.toSWIGGraph) (hobs : HEq M₁.obsKernel M₂.obsKernel) : HEq (M₁.obsDensity ref) (M₂.obsDensity ref) := by obtain ⟨⟨dag₁, fixed₁, observed₁, unobserved₁, fio₁, oi₁, od₁, oou₁, foi₁, fou₁, aic₁, dc₁, foff₁, aco₁⟩, eT₁, iota₁, sf₁, mf₁, lD₁, pL₁⟩ := M₁ obtain ⟨⟨dag₂, fixed₂, observed₂, unobserved₂, fio₂, oi₂, od₂, oou₂, foi₂, fou₂, aic₂, dc₂, foff₂, aco₂⟩, eT₂, iota₂, sf₂, mf₂, lD₂, pL₂⟩ := M₂ cases hsg -- The observed-value types now coincide, so `hobs` is a homogeneous equality. have hk : _ = _ := eq_of_heq hobs -- `obsDensity ref = fun s => (obsKernel s).rnDeriv (jointRef ref observed)`. apply heq_of_eq unfold obsDensity rw [hk]
lemma obsKernel_heq_of_obsDensity_heq reviewed
Causalean.SCM

Cross-model law transport (converse). If two structural causal models M₁ and M₂ are each dominated by the same reference measure, share the same SWIG graph, and have heterogeneously-equal observational densities, then their observational kernels are heterogeneously equal. After unifying the SWIG-graph data the observed-value types coincide and the densities become literally equal; weighting the common joint reference by that density recovers each observational law (withDensity_obsDensity_eq), so the two laws agree. This is the converse of obsDensity_heq_of_obsKernel_heq: under dominance, equal density and equal law are interchangeable, letting the kernel-level identification tools be driven from a density hypothesis.

Formal statement
M₁ M₂ :
SCM N Ω
hsg :
M₁.toSWIGGraph = M₂.toSWIGGraph
hdom₁ :
DominatedObs M₁ ref
hdom₂ :
DominatedObs M₂ ref
hden :
HEq (M₁.obsDensity ref) (M₂.obsDensity ref)
HEq M₁.obsKernel M₂.obsKernel
Proof (Lean source)
lemma obsKernel_heq_of_obsDensity_heq (M₁ M₂ : SCM N Ω) (ref : ReferenceMeasures Ω) (hsg : M₁.toSWIGGraph = M₂.toSWIGGraph) (hdom₁ : DominatedObs M₁ ref) (hdom₂ : DominatedObs M₂ ref) (hden : HEq (M₁.obsDensity ref) (M₂.obsDensity ref)) : HEq M₁.obsKernel M₂.obsKernel := by obtain ⟨⟨dag₁, fixed₁, observed₁, unobserved₁, fio₁, oi₁, od₁, oou₁, foi₁, fou₁, aic₁, dc₁, foff₁, aco₁⟩, eT₁, iota₁, sf₁, mf₁, lD₁, pL₁⟩ := M₁ obtain ⟨⟨dag₂, fixed₂, observed₂, unobserved₂, fio₂, oi₂, od₂, oou₂, foi₂, fou₂, aic₂, dc₂, foff₂, aco₂⟩, eT₂, iota₂, sf₂, mf₂, lD₂, pL₂⟩ := M₂ cases hsg -- The observed-value types now coincide, so `hden` is a homogeneous equality. have hd : _ = _ := eq_of_heq hden apply heq_of_eq refine ProbabilityTheory.Kernel.ext (fun s => ?_) rw [← withDensity_obsDensity_eq _ ref hdom₁ s, ← withDensity_obsDensity_eq _ ref hdom₂ s, hd]
Mass­Bridge 3 core · 7 supporting This file exposes the measure-level identities that turn Radon--Nikodym derivatives and conditional kernels into singleton-mass ratios on finite measurable-singleton spaces. ★ condDistrib_singleton_mass_eq_conditionalMass★ obsCondKernel_singleton_mass_of_ne_zero★ obsStepCondDensity_eq_mass_ratio

Point-mass bridges for finite discrete densities

This file exposes the measure-level identities that turn Radon--Nikodym derivatives and conditional kernels into singleton-mass ratios on finite measurable-singleton spaces. The statements are reference-measure agnostic: they apply to any faithful finite reference family, not only counting measure.

theorem condDistrib_singleton_mass_eq_conditionalMass reviewed
Causalean.SCM

For a measurable map Y and a measurable map Z out of a finite measure space, at a conditioning value z with nonzero pushforward mass under Z, the singleton mass that Mathlib's conditional distribution condDistrib Y Z μ assigns to a value y at z equals the discrete conditional-mass ratio conditionalMass, computed from the joint pushforward law of (Y, Z), evaluated at (y, z).

Formal statement
Y :
α → γ
Z :
α → β
hY :
hZ :
z :
β
y :
γ
hz :
(μ.map Z) ({z} : Set β) ≠ 0
(condDistrib Y Z μ z) ({y} : Set γ)
= conditionalMass (μ.map fun ω => (Y ω, Z ω)) y z
Proof (Lean source)
theorem condDistrib_singleton_mass_eq_conditionalMass {α β γ : Type*} [MeasurableSpace α] [MeasurableSpace β] [MeasurableSpace γ] [StandardBorelSpace γ] [Nonempty γ] [MeasurableSingletonClass β] [MeasurableSingletonClass γ] {μ : Measure α} [IsFiniteMeasure μ] {Y : α → γ} {Z : α → β} (hY : Measurable Y) (hZ : Measurable Z) (z : β) (y : γ) (hz : (μ.map Z) ({z} : Set β) ≠ 0) : (condDistrib Y Z μ z) ({y} : Set γ) = Causalean.SCM.ID.DiscreteID.conditionalMass (μ.map fun ω => (Y ω, Z ω)) y z := by rw [condDistrib_singleton_mass_of_ne_zero hY z y hz] unfold Causalean.SCM.ID.DiscreteID.conditionalMass unfold Causalean.SCM.ID.DiscreteID.singletonMass have hswap : (μ.map (fun ω => (Z ω, Y ω))) ({(z, y)} : Set (β × γ)) = (μ.map (fun ω => (Y ω, Z ω))) ({(y, z)} : Set (γ × β)) := by rw [Measure.map_apply (hZ.prod hY) (MeasurableSet.singleton (z, y))] rw [Measure.map_apply (hY.prod hZ) (MeasurableSet.singleton (y, z))] congr 1 ext ω simp [and_comm] rw [← hswap] rw [Measure.map_map measurable_snd (hY.prod hZ)] rfl
Causalean.SCM.condDistrib_singleton_mass_eq_conditionalMass · Causalean/SCM/ID/Density/MassBridge.lean:160 · uses conditionalMass
theorem obsCondKernel_singleton_mass_of_ne_zero reviewed
Causalean.SCM

For a query coordinate set Y contained in the observed nodes and a conditioning coordinate set CC contained in the observed nodes, at a conditioning value c with nonzero pushforward mass of the observational kernel under projection onto CC, the observational conditional kernel's singleton mass at a value y equals the observational kernel's joint singleton mass at the pair (c, y) divided by its singleton mass at c.

Formal statement
M :
SCM N Ω
Y CC :
hY :
Y ⊆ M.observed
hCC :
CC ⊆ M.observed
Nonempty (ValuesOn Y (swigΩ Ω))
∀ s :
M.FixedValues, IsFiniteMeasure (M.obsKernel s)
s :
M.FixedValues
c :
y :
hc0 :
((M.obsKernel s).map (valuesProjection hCC)) ({c} : Set (ValuesOn CC (swigΩ Ω))) ≠ 0
M.obsCondKernel Y CC hY hCC (s, c) ({y} : Set (ValuesOn Y (swigΩ Ω)))
= ((M.obsKernel s).map (fun ω => (valuesProjection hCC ω, valuesProjection hY ω))) ({(c, y)} : Set (ValuesOn CC (swigΩ Ω) × ValuesOn Y (swigΩ Ω))) / ((M.obsKernel s).map (valuesProjection hCC)) ({c} : Set (ValuesOn CC (swigΩ Ω)))
Proof (Lean source)
theorem obsCondKernel_singleton_mass_of_ne_zero (M : SCM N Ω) (Y CC : Finset (SWIGNode N)) (hY : Y ⊆ M.observed) (hCC : CC ⊆ M.observed) [MeasurableSingletonClass (ValuesOn CC (swigΩ Ω))] [MeasurableSingletonClass (ValuesOn Y (swigΩ Ω))] [StandardBorelSpace (ValuesOn Y (swigΩ Ω))] [Nonempty (ValuesOn Y (swigΩ Ω))] [∀ s : M.FixedValues, IsFiniteMeasure (M.obsKernel s)] [CountableOrCountablyGenerated M.FixedValues (ValuesOn CC (swigΩ Ω))] (s : M.FixedValues) (c : ValuesOn CC (swigΩ Ω)) (y : ValuesOn Y (swigΩ Ω)) (hc0 : ((M.obsKernel s).map (valuesProjection hCC)) ({c} : Set (ValuesOn CC (swigΩ Ω))) ≠ 0) : M.obsCondKernel Y CC hY hCC (s, c) ({y} : Set (ValuesOn Y (swigΩ Ω))) = ((M.obsKernel s).map (fun ω => (valuesProjection hCC ω, valuesProjection hY ω))) ({(c, y)} : Set (ValuesOn CC (swigΩ Ω) × ValuesOn Y (swigΩ Ω))) / ((M.obsKernel s).map (valuesProjection hCC)) ({c} : Set (ValuesOn CC (swigΩ Ω))) := by classical have hpair : M.obsCondPairKernel Y CC hY hCC s = (M.obsKernel s).map (fun ω => (valuesProjection hCC ω, valuesProjection hY ω)) := by unfold obsCondPairKernel exact Kernel.map_apply M.obsKernel ((measurable_valuesProjection hCC).prodMk (measurable_valuesProjection hY)) s have hcomp := M.obsCondPairKernel_apply_eq_compProd Y CC hY hCC s haveI : IsMarkovKernel (M.obsCondKernel Y CC hY hCC) := by unfold obsCondKernel infer_instance have hmass : (M.obsCondPairKernel Y CC hY hCC s) ({(c, y)} : Set (ValuesOn CC (swigΩ Ω) × ValuesOn Y (swigΩ Ω))) = ((M.obsKernel s).map (valuesProjection hCC) ⊗ₘ (M.obsCondKernel Y CC hY hCC).sectR s) ({(c, y)} : Set (ValuesOn CC (swigΩ Ω) × ValuesOn Y (swigΩ Ω))) := by simpa using congrArg (fun ρ : Measure (ValuesOn CC (swigΩ Ω) × ValuesOn Y (swigΩ Ω)) => ρ ({(c, y)} : Set (ValuesOn CC (swigΩ Ω) × ValuesOn Y (swigΩ Ω)))) hcomp rw [compProd_singleton_mass] at hmass rw [hpair] at hmass haveI : IsFiniteMeasure ((M.obsKernel s).map (valuesProjection hCC)) := (M.obsKernel s).isFiniteMeasure_map _ have hctop : ((M.obsKernel s).map (valuesProjection hCC)) ({c} : Set (ValuesOn CC (swigΩ Ω))) ≠ ∞ := measure_ne_top _ _ rw [ENNReal.eq_div_iff hc0 hctop] simpa [Kernel.sectR] using hmass.symm
theorem obsStepCondDensity_eq_mass_ratio reviewed
Causalean.SCM

At the i-th observed coordinate, if the one-step observational conditional kernel is absolutely continuous with respect to the reference measure on that coordinate, and the reference measure's singleton mass at the recorded value is nonzero and finite, then the one-node observational step density obsStepCondDensity equals the conditional kernel's singleton mass at the recorded value divided by the reference measure's singleton mass there.

Formal statement
M :
SCM N Ω
s :
M.FixedValues
i :
Fin M.observed.card
MeasurableSingletonClass (swigΩ Ω (M.observedAt i).val)
∀ s' :
M.FixedValues, IsFiniteMeasure (M.obsKernel s')
StandardBorelSpace (ValuesOn ({(M.observedAt i).val} : Finset (SWIGNode N)) (swigΩ Ω))
Nonempty (ValuesOn ({(M.observedAt i).val} : Finset (SWIGNode N)) (swigΩ Ω))
CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes i.val) (swigΩ Ω))
x :
ValuesOn M.observed (swigΩ Ω)
hac :
(M.obsStepCondKernel i.isLt) (s, valuesProjection (M.prefixNodes_subset_observed i.val) x) ≪ ref.μ (M.observedAt i).val
href0 :
ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val)) ≠ 0
hreftop :
ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val)) ≠ ∞
M.obsStepCondDensity ref s i x
= (M.obsStepCondKernel i.isLt) (s, valuesProjection (M.prefixNodes_subset_observed i.val) x) ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val)) / ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val))
Proof (Lean source)
theorem obsStepCondDensity_eq_mass_ratio (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) (i : Fin M.observed.card) [MeasurableSingletonClass (swigΩ Ω (M.observedAt i).val)] [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [StandardBorelSpace (ValuesOn ({(M.observedAt i).val} : Finset (SWIGNode N)) (swigΩ Ω))] [Nonempty (ValuesOn ({(M.observedAt i).val} : Finset (SWIGNode N)) (swigΩ Ω))] [CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes i.val) (swigΩ Ω))] (x : ValuesOn M.observed (swigΩ Ω)) (hac : (M.obsStepCondKernel i.isLt) (s, valuesProjection (M.prefixNodes_subset_observed i.val) x) ≪ ref.μ (M.observedAt i).val) (href0 : ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val)) ≠ 0) (hreftop : ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val)) ≠ ∞) : M.obsStepCondDensity ref s i x = (M.obsStepCondKernel i.isLt) (s, valuesProjection (M.prefixNodes_subset_observed i.val) x) ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val)) / ref.μ (M.observedAt i).val ({x (M.observedAt i)} : Set (swigΩ Ω (M.observedAt i).val)) := by unfold obsStepCondDensity exact rnDeriv_singleton_eq_div _ _ hac (x (M.observedAt i)) href0 hreftop
7 supporting declarations (lemmas, instances)
QFactor 8 core · 14 supporting This file provides the density-level Tian district objects used by the ID do-law assembly: the topological prefix helpers on a SWIG node set (nodesAt, nodeIndex, prefixIn), tianPrefixStepDensity, tianDistrictDensity (the ★ tianDistrictDensity_eq_mechCFactor_doModel★ tianDistrictDensity_eq_qLocalMass_div_jointRef_district★ tian_full_cComponent_density_recovery_core_direct

Tian district densities and the c-component recovery core

This file provides the density-level Tian district objects used by the ID do-law assembly: the topological prefix helpers on a SWIG node set (nodesAt, nodeIndex, prefixIn), tianPrefixStepDensity, tianDistrictDensity (the S-district prefix-conditional product of a measure on D), and tianDensityProduct, around Tian and Pearl (2002) Eqs. 37 and 70-72.

The keystone is tian_full_cComponent_density_recovery_core_direct: for a district S of the post-intervention ancestral graph that is also a full c-component of M, the S-district factor of the do-law ancestral marginal equals a.e. the full observational c-component factor Q_M[S]. The proof chains the do-model district-density identity, do(X)-invariance of mechanism c-factors, and the observational c-component/mechanism equivalence.

def KernelObsCondIndepOn reviewed
Causalean.SCM.ID

This predicate says that two coordinate blocks are conditionally independent given a third block under a finite-coordinate measure.

Definition (Lean source)
def KernelObsCondIndepOn (D X Y Z : Finset (SWIGNode N)) (hX : X ⊆ D) (hY : Y ⊆ D) (hZ : Z ⊆ D) (μ : Measure (ValuesOn D (swigΩ Ω))) [StandardBorelSpace (ValuesOn D (swigΩ Ω))] [IsFiniteMeasure μ] : Prop := CondIndepFun (comap (valuesProjection hZ) inferInstance) (comap_valuesProjection_le hZ) (valuesProjection hX) (valuesProjection hY) μ
def KernelGlobalMarkovOn reviewed
Causalean.SCM.ID

This predicate says that every graphical separation in a graph gives the corresponding coordinate conditional independence under a finite-coordinate measure.

Definition (Lean source)
def KernelGlobalMarkovOn (H : SWIGGraph N) (D : Finset (SWIGNode N)) (μ : Measure (ValuesOn D (swigΩ Ω))) [StandardBorelSpace (ValuesOn D (swigΩ Ω))] [IsFiniteMeasure μ] : Prop := ∀ X Y Z : Finset (SWIGNode N), ∀ (hX : X ⊆ D) (hY : Y ⊆ D) (hZ : Z ⊆ D), Disjoint X Y → Disjoint X Z → Disjoint Y Z → H.dag.dSep X Y Z → KernelObsCondIndepOn D X Y Z hX hY hZ μ
def tianPrefixStepDensity reviewed
Causalean.SCM.ID

This density is Tian's one-node conditional factor along the topological prefix of a finite node set.

Definition (Lean source)
noncomputable def tianPrefixStepDensity (G : SWIGGraph N) (D : Finset (SWIGNode N)) (μ : Measure (ValuesOn D (swigΩ Ω))) (ref : ReferenceMeasures Ω) (i : Fin D.card) [IsFiniteMeasure μ] [StandardBorelSpace (ValuesOn ({(G.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))] [Nonempty (ValuesOn ({(G.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))] : ValuesOn D (swigΩ Ω) → ENNReal := fun x => ((condDistrib (valuesProjection (show ({(G.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (G.nodesAt D i).property)) (valuesProjection (G.prefixIn_subset D i.val)) μ) (valuesProjection (G.prefixIn_subset D i.val) x)).rnDeriv (jointRef ref ({(G.nodesAt D i).val} : Finset (SWIGNode N))) (valuesProjection (show ({(G.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (G.nodesAt D i).property) x)
def tianDistrictDensity reviewed
Causalean.SCM.ID

Tian's district density multiplies the prefix conditional factors whose nodes lie in one district.

Definition (Lean source)
noncomputable def tianDistrictDensity (G : SWIGGraph N) (D : Finset (SWIGNode N)) (μ : Measure (ValuesOn D (swigΩ Ω))) (ref : ReferenceMeasures Ω) (S : Finset (SWIGNode N)) [IsFiniteMeasure μ] [∀ (k : ℕ) (hk : k < D.card), StandardBorelSpace (ValuesOn ({(G.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < D.card), Nonempty (ValuesOn ({(G.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] : ValuesOn D (swigΩ Ω) → ENNReal := fun x => ∏ i ∈ Finset.univ.filter (fun i : Fin D.card => (G.nodesAt D i).val ∈ S), tianPrefixStepDensity G D μ ref i x
def tianDensityProduct reviewed
Causalean.SCM.ID

Tian's full prefix-chain density multiplies all one-node prefix conditional factors for a finite node set.

Definition (Lean source)
noncomputable def tianDensityProduct (G : SWIGGraph N) (D : Finset (SWIGNode N)) (μ : Measure (ValuesOn D (swigΩ Ω))) (ref : ReferenceMeasures Ω) [IsFiniteMeasure μ] [∀ (k : ℕ) (hk : k < D.card), StandardBorelSpace (ValuesOn ({(G.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < D.card), Nonempty (ValuesOn ({(G.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] : ValuesOn D (swigΩ Ω) → ENNReal := fun x => ∏ i : Fin D.card, tianPrefixStepDensity G D μ ref i x
theorem tianDistrictDensity_eq_mechCFactor_doModel reviewed
Causalean.SCM.ID

(B) Tian Lemma 1 for the do-model ancestral marginal. Consider a structural causal model M with an intervention set X whose random copies are observed and whose fixed copies are not already frozen, an outcome set Y disjoint from the random copies of X, under a faithful reference-measure family, a positive observational kernel at every fixed-value assignment, and the standing assumption that M is a standard model. For a set S that is simultaneously a district of the post-intervention ancestral graph and a full c-component of M, and an extension map that inverts the projection onto the ancestral observed coordinates, the Tian district density read off the do(X)-law ancestral marginal at S agrees with the mechanism c-factor of the post-intervention model at the extended point.

Formal statement
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
M :
SCM N Ω
X :
hObs :
∀ D ∈ X, SWIGNode.random D ∈ M.observed
hFix :
∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
Y :
href :
sDo :
(M.fixSet X hObs hFix).FixedValues
hpos :
∀ s' : M.FixedValues, DiscreteID.PositiveMass (M.obsKernel s')
hYX :
∀ d ∈ X, SWIGNode.random d ∉ Y
hStd :
M.isStandard
S :
hS :
S ∈ fixTruncCComponentSet M X hObs hFix Y
hSfull :
S ∈ M.toSWIGGraph.cComponentSet
∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card),
StandardBorelSpace (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card),
Nonempty (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
extend :
ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω)
hExtend :
∀ xD,
valuesProjection (show fixObservedAncestralSet M X hObs hFix Y ⊆ M.observed from inter_subset_right) (extend xD)
= xD
xD :
ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω)
tianDistrictDensity ((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)) (fixObservedAncestralSet M X hObs hFix Y) (doObsKernelAncestralMarginal M X hObs hFix Y sDo) ref S xD
= (M.fixSet X hObs hFix).mechCFactor ref S (by have hSobs : S ⊆ M.observed := M.toSWIGGraph.cComponentSet_subset_observed S hSfull simpa [SCM.fixSet_observed] using hSobs) sDo (extend xD)
Proof (Lean source)
theorem tianDistrictDensity_eq_mechCFactor_doModel [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (Y : Finset (SWIGNode N)) (ref : ReferenceMeasures Ω) (href : ReferenceFaithful ref) (sDo : (M.fixSet X hObs hFix).FixedValues) (hpos : ∀ s' : M.FixedValues, DiscreteID.PositiveMass (M.obsKernel s')) (hYX : ∀ d ∈ X, SWIGNode.random d ∉ Y) (hStd : M.isStandard) (S : Finset (SWIGNode N)) (hS : S ∈ fixTruncCComponentSet M X hObs hFix Y) (hSfull : S ∈ M.toSWIGGraph.cComponentSet) [IsFiniteMeasure (doObsKernelAncestralMarginal M X hObs hFix Y sDo)] [∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card), StandardBorelSpace (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card), Nonempty (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] (extend : ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω)) (hExtend : ∀ xD, valuesProjection (show fixObservedAncestralSet M X hObs hFix Y ⊆ M.observed from Finset.inter_subset_right) (extend xD) = xD) (xD : ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω)) : tianDistrictDensity ((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)) (fixObservedAncestralSet M X hObs hFix Y) (doObsKernelAncestralMarginal M X hObs hFix Y sDo) ref S xD = (M.fixSet X hObs hFix).mechCFactor ref S (by have hSobs : S ⊆ M.observed := M.toSWIGGraph.cComponentSet_subset_observed S hSfull simpa [SCM.fixSet_observed] using hSobs) sDo (extend xD) := by classical let MX := M.fixSet X hObs hFix let D := fixObservedAncestralSet M X hObs hFix Y let H := MX.toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y) let μ : Measure (ValuesOn D (swigΩ Ω)) := doObsKernelAncestralMarginal M X hObs hFix Y sDo have hDobs : D ⊆ MX.observed := Finset.inter_subset_right have hSdoComp : S ∈ MX.toSWIGGraph.cComponentSet := by exact (fixSet_cComponentSet_mem M X hObs hFix S).mpr hSfull have hSobsMX : S ⊆ MX.observed := MX.toSWIGGraph.cComponentSet_subset_observed S hSdoComp have hSobsM : S ⊆ M.observed := M.toSWIGGraph.cComponentSet_subset_observed S hSfull have hSD : S ⊆ D := by have hSHobs : S ⊆ H.observed := by exact H.cComponentSet_subset_observed S (by simpa [H, MX, fixTruncCComponentSet] using hS) exact hSHobs have hμpos : DiscreteID.PositiveMass μ := by simpa [μ] using doObsKernelAncestralMarginal_positiveMass M X hObs hFix Y hpos hYX sDo have hprefixMass_ne0 : ∀ k, (μ.map (valuesProjection (H.prefixIn_subset D k))) ({valuesProjection (H.prefixIn_subset D k) xD} : Set (ValuesOn (H.prefixIn D k) (swigΩ Ω))) ≠ 0 := by intro k have hmapPos := DiscreteID.PositiveMass.map_valuesProjection (Ω' := swigΩ Ω) hμpos (H.prefixIn_subset D k) simpa [DiscreteID.singletonMass_apply] using hmapPos (valuesProjection (H.prefixIn_subset D k) xD) have hprefixProd_eq : ∀ k, (μ.map (valuesProjection (H.prefixIn_subset D k))) ({valuesProjection (H.prefixIn_subset D k) xD} : Set (ValuesOn (H.prefixIn D k) (swigΩ Ω))) = ∏ C ∈ MX.toSWIGGraph.cComponentSet, MX.qLocalMass sDo (C ∩ H.prefixIn D k) (fun _ hv => hDobs (H.prefixIn_subset D k (mem_of_mem_inter_right hv))) (extend xD) := by intro k simpa [MX, D, H, μ, hDobs] using doObsKernelAncestralMarginal_prefix_singleton_eq_prod_qLocalMass M X hObs hFix Y sDo extend hExtend k xD have hprefixProd_ne0 : ∀ k, (∏ C ∈ MX.toSWIGGraph.cComponentSet, MX.qLocalMass sDo (C ∩ H.prefixIn D k) (fun _ hv => hDobs (H.prefixIn_subset D k (mem_of_mem_inter_right hv))) (extend xD)) ≠ 0 := by intro k hzero exact hprefixMass_ne0 k (by rw [hprefixProd_eq k, hzero]) have hfactor_ne0 : ∀ k C, C ∈ MX.toSWIGGraph.cComponentSet → MX.qLocalMass sDo (C ∩ H.prefixIn D k) (fun _ hv => hDobs (H.prefixIn_subset D k (mem_of_mem_inter_right hv))) (extend xD) ≠ 0 := by intro k C hC exact (Finset.prod_ne_zero_iff.mp (hprefixProd_ne0 k)) C hC have hS_q_ne0 : ∀ k ≤ D.card, MX.qLocalMass sDo (S ∩ H.prefixIn D k) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) ≠ 0 := by intro k _hk simpa [hDobs, hSobsMX] using hfactor_ne0 k S hSdoComp have hpointS : valuesProjection hSobsMX (extend xD) = valuesProjection hSD xD := by have h := valuesProjection_extend_eq_of_subset M (show D ⊆ M.observed from Finset.inter_subset_right) hSD hSobsM extend hExtend xD simpa [MX, SCM.fixSet_observed, hSobsMX, hSobsM] using h have hstep : ∀ i ∈ Finset.univ.filter (fun i : Fin D.card => (H.nodesAt D i).val ∈ S), tianPrefixStepDensity H D μ ref i xD = (MX.qLocalMass sDo (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) / MX.qLocalMass sDo (S ∩ H.prefixIn D i.val) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD)) / jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) xD} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) := by intro i hi have hiS : (H.nodesAt D i).val ∈ S := (Finset.mem_filter.mp hi).2 have hmass := tianPrefixStepDensity_eq_prefix_mass_ratio H D μ ref href i xD (hprefixMass_ne0 i.val) have hrest0 : (∏ C ∈ MX.toSWIGGraph.cComponentSet \ {S}, MX.qLocalMass sDo (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) (extend xD)) ≠ 0 := by exact Finset.prod_ne_zero_iff.mpr (by intro C hC exact hfactor_ne0 i.val C (Finset.mem_sdiff.mp hC).1) have hcancel := prefixIn_qProduct_ratio_eq_component_ratio_of_ne_zero MX H D sDo S hSdoComp i hDobs hiS (extend xD) hrest0 calc tianPrefixStepDensity H D μ ref i xD = (((∏ C ∈ MX.toSWIGGraph.cComponentSet, MX.qLocalMass sDo (C ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) (extend xD)) / (∏ C ∈ MX.toSWIGGraph.cComponentSet, MX.qLocalMass sDo (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) (extend xD))) / jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) xD} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω)))) := by rw [hmass, hprefixProd_eq (i.val + 1), hprefixProd_eq i.val] _ = (MX.qLocalMass sDo (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) / MX.qLocalMass sDo (S ∩ H.prefixIn D i.val) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD)) / jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) xD} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) := by rw [hcancel] let idxS := Finset.univ.filter (fun i : Fin D.card => (H.nodesAt D i).val ∈ S) let qratio : Fin D.card → ENNReal := fun i => MX.qLocalMass sDo (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) / MX.qLocalMass sDo (S ∩ H.prefixIn D i.val) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) let den : Fin D.card → ENNReal := fun i => jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) xD} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) have hden0 : ∀ i ∈ idxS, den i ≠ 0 := by intro i _hi exact jointRef_singleton_ne_zero ref href _ _ have hdentop : ∀ i ∈ idxS, den i ≠ ∞ := by intro i _hi exact ne_of_lt (MeasureTheory.measure_lt_top (jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N))) _) have hqprod : (∏ i ∈ idxS, qratio i) = MX.qLocalMass sDo S hSobsMX (extend xD) := by simpa [idxS, qratio] using component_qLocalMass_ratio_product_prefixIn_of_ne_zero MX H D sDo S hSobsMX hSD (extend xD) hS_q_ne0 have hdenprod : (∏ i ∈ idxS, den i) = jointRef ref S ({valuesProjection hSD xD} : Set (ValuesOn S (swigΩ Ω))) := by have hden_atom : (∏ i ∈ idxS, den i) = ∏ i ∈ idxS, ref.μ (H.nodesAt D i).val ({xD (H.nodesAt D i)} : Set (swigΩ Ω (H.nodesAt D i).val)) := by refine Finset.prod_congr rfl ?_ intro i hi dsimp [den] rw [jointRef_singleton_eq_prod] simp [valuesProjection] rw [hden_atom] simpa [idxS] using component_ref_atom_product_eq_jointRef_prefixIn H D ref S hSD xD have htian : tianDistrictDensity H D μ ref S xD = MX.qLocalMass sDo S hSobsMX (extend xD) / jointRef ref S ({valuesProjection hSD xD} : Set (ValuesOn S (swigΩ Ω))) := by unfold tianDistrictDensity calc (∏ i ∈ Finset.univ.filter (fun i : Fin D.card => (H.nodesAt D i).val ∈ S), tianPrefixStepDensity H D μ ref i xD) = ∏ i ∈ idxS, qratio i / den i := by refine Finset.prod_congr ?_ ?_ · simp [idxS] · intro i hi simpa [idxS, qratio, den] using hstep i (by simpa [idxS] using hi) _ = (∏ i ∈ idxS, qratio i) / (∏ i ∈ idxS, den i) := by exact ENNReal.prod_div_prod idxS qratio den hden0 hdentop -- … truncated; follow the source link for the rest …
theorem tianDistrictDensity_eq_qLocalMass_div_jointRef_district reviewed
Causalean.SCM.ID

Consider an intervention set X whose random copies are observed and whose fixed copies are not already frozen together with an outcome set Y disjoint from the random copies of X, under a faithful reference-measure family and a positive observational kernel at every fixed-value assignment. For any district S of the post-intervention ancestral graph and an extension map inverting the projection onto the ancestral observed coordinates, the Tian district density read off the do(X)-law ancestral marginal at S equals the do-model local q-mass on S divided by the reference atom mass of S.

Formal statement
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
M :
SCM N Ω
X :
hObs :
∀ D ∈ X, SWIGNode.random D ∈ M.observed
hFix :
∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
Y :
href :
sDo :
(M.fixSet X hObs hFix).FixedValues
hpos :
∀ s' : M.FixedValues, DiscreteID.PositiveMass (M.obsKernel s')
hYX :
∀ d ∈ X, SWIGNode.random d ∉ Y
S :
hS :
S ∈ fixTruncCComponentSet M X hObs hFix Y
∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card),
StandardBorelSpace (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card),
Nonempty (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
extend :
ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω)
hExtend :
∀ xD,
valuesProjection (show fixObservedAncestralSet M X hObs hFix Y ⊆ M.observed from inter_subset_right) (extend xD)
= xD
xD :
ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω)
let MX := M.fixSet X hObs hFix let D := fixObservedAncestralSet M X hObs hFix Y let H := MX.toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y) tianDistrictDensity H D (doObsKernelAncestralMarginal M X hObs hFix Y sDo) ref S xD
= MX.qLocalMass sDo S (show S ⊆ MX.observed from by intro v hv have hSHobs : S ⊆ H.observed := H.cComponentSet_subset_observed S (by simpa [H, MX, fixTruncCComponentSet] using hS) have hvD : v ∈ D := by dsimp [H, D, SWIGGraph.induce, fixObservedAncestralSet] at hSHobs ⊢ exact hSHobs hv exact (Finset.mem_inter.mp hvD).2) (extend xD) / jointRef ref S ({valuesProjection (show S ⊆ D from by intro v hv have hSHobs : S ⊆ H.observed := H.cComponentSet_subset_observed S (by simpa [H, MX, fixTruncCComponentSet] using hS) dsimp [H, D, SWIGGraph.induce, fixObservedAncestralSet] at hSHobs ⊢ exact hSHobs hv) xD} : Set (ValuesOn S (swigΩ Ω)))
Proof (Lean source)
theorem tianDistrictDensity_eq_qLocalMass_div_jointRef_district [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (Y : Finset (SWIGNode N)) (ref : ReferenceMeasures Ω) (href : ReferenceFaithful ref) (sDo : (M.fixSet X hObs hFix).FixedValues) (hpos : ∀ s' : M.FixedValues, DiscreteID.PositiveMass (M.obsKernel s')) (hYX : ∀ d ∈ X, SWIGNode.random d ∉ Y) (S : Finset (SWIGNode N)) (hS : S ∈ fixTruncCComponentSet M X hObs hFix Y) [IsFiniteMeasure (doObsKernelAncestralMarginal M X hObs hFix Y sDo)] [∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card), StandardBorelSpace (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card), Nonempty (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] (extend : ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω)) (hExtend : ∀ xD, valuesProjection (show fixObservedAncestralSet M X hObs hFix Y ⊆ M.observed from Finset.inter_subset_right) (extend xD) = xD) (xD : ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω)) : let MX := M.fixSet X hObs hFix let D := fixObservedAncestralSet M X hObs hFix Y let H := MX.toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y) tianDistrictDensity H D (doObsKernelAncestralMarginal M X hObs hFix Y sDo) ref S xD = MX.qLocalMass sDo S (show S ⊆ MX.observed from by intro v hv have hSHobs : S ⊆ H.observed := H.cComponentSet_subset_observed S (by simpa [H, MX, fixTruncCComponentSet] using hS) have hvD : v ∈ D := by dsimp [H, D, SWIGGraph.induce, fixObservedAncestralSet] at hSHobs ⊢ exact hSHobs hv exact (Finset.mem_inter.mp hvD).2) (extend xD) / jointRef ref S ({valuesProjection (show S ⊆ D from by intro v hv have hSHobs : S ⊆ H.observed := H.cComponentSet_subset_observed S (by simpa [H, MX, fixTruncCComponentSet] using hS) dsimp [H, D, SWIGGraph.induce, fixObservedAncestralSet] at hSHobs ⊢ exact hSHobs hv) xD} : Set (ValuesOn S (swigΩ Ω))) := by classical let MX := M.fixSet X hObs hFix let D := fixObservedAncestralSet M X hObs hFix Y let H := MX.toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y) let μ : Measure (ValuesOn D (swigΩ Ω)) := doObsKernelAncestralMarginal M X hObs hFix Y sDo have hDobs : D ⊆ MX.observed := Finset.inter_subset_right have hScomp : S ∈ H.cComponentSet := by simpa [H, MX, fixTruncCComponentSet] using hS have hSobsMX : S ⊆ MX.observed := by intro v hv have hSHobs : S ⊆ H.observed := H.cComponentSet_subset_observed S hScomp have hvD : v ∈ D := by dsimp [H, D, SWIGGraph.induce, fixObservedAncestralSet] at hSHobs ⊢ exact hSHobs hv exact (Finset.mem_inter.mp hvD).2 have hSD : S ⊆ D := by intro v hv have hSHobs : S ⊆ H.observed := H.cComponentSet_subset_observed S hScomp dsimp [H, D, SWIGGraph.induce, fixObservedAncestralSet] at hSHobs ⊢ exact hSHobs hv have hdisj : (↑H.cComponentSet : Set (Finset (SWIGNode N))).Pairwise (fun U U' => Disjoint U U') := by intro U hU V hV hne exact H.cComponentSet_pairwise_disjoint hU hV hne have hμpos : DiscreteID.PositiveMass μ := by simpa [μ] using doObsKernelAncestralMarginal_positiveMass M X hObs hFix Y hpos hYX sDo have hprefixMass_ne0 : ∀ k, (μ.map (valuesProjection (H.prefixIn_subset D k))) ({valuesProjection (H.prefixIn_subset D k) xD} : Set (ValuesOn (H.prefixIn D k) (swigΩ Ω))) ≠ 0 := by intro k have hmapPos := DiscreteID.PositiveMass.map_valuesProjection (Ω' := swigΩ Ω) hμpos (H.prefixIn_subset D k) simpa [DiscreteID.singletonMass_apply] using hmapPos (valuesProjection (H.prefixIn_subset D k) xD) have hprefixProd_eq : ∀ k, (μ.map (valuesProjection (H.prefixIn_subset D k))) ({valuesProjection (H.prefixIn_subset D k) xD} : Set (ValuesOn (H.prefixIn D k) (swigΩ Ω))) = ∏ C ∈ H.cComponentSet, MX.qLocalMass sDo (C ∩ H.prefixIn D k) (fun _ hv => hDobs (H.prefixIn_subset D k (mem_of_mem_inter_right hv))) (extend xD) := by intro k simpa [MX, D, H, μ, hDobs] using doObsKernelAncestralMarginal_prefix_singleton_eq_prod_H_qLocalMass M X hObs hFix Y sDo extend hExtend k xD have hprefixProd_ne0 : ∀ k, (∏ C ∈ H.cComponentSet, MX.qLocalMass sDo (C ∩ H.prefixIn D k) (fun _ hv => hDobs (H.prefixIn_subset D k (mem_of_mem_inter_right hv))) (extend xD)) ≠ 0 := by intro k hzero exact hprefixMass_ne0 k (by rw [hprefixProd_eq k, hzero]) have hfactor_ne0 : ∀ k C, C ∈ H.cComponentSet → MX.qLocalMass sDo (C ∩ H.prefixIn D k) (fun _ hv => hDobs (H.prefixIn_subset D k (mem_of_mem_inter_right hv))) (extend xD) ≠ 0 := by intro k C hC exact (Finset.prod_ne_zero_iff.mp (hprefixProd_ne0 k)) C hC have hS_q_ne0 : ∀ k ≤ D.card, MX.qLocalMass sDo (S ∩ H.prefixIn D k) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) ≠ 0 := by intro k _hk simpa [hDobs, hSobsMX] using hfactor_ne0 k S hScomp have hstep : ∀ i ∈ Finset.univ.filter (fun i : Fin D.card => (H.nodesAt D i).val ∈ S), tianPrefixStepDensity H D μ ref i xD = (MX.qLocalMass sDo (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) / MX.qLocalMass sDo (S ∩ H.prefixIn D i.val) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD)) / jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) xD} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) := by intro i hi have hiS : (H.nodesAt D i).val ∈ S := (Finset.mem_filter.mp hi).2 have hmass := tianPrefixStepDensity_eq_prefix_mass_ratio H D μ ref href i xD (hprefixMass_ne0 i.val) have hrest0 : (∏ C ∈ H.cComponentSet \ {S}, MX.qLocalMass sDo (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) (extend xD)) ≠ 0 := by exact Finset.prod_ne_zero_iff.mpr (by intro C hC exact hfactor_ne0 i.val C (Finset.mem_sdiff.mp hC).1) have hcancel := prefixIn_qProduct_ratio_eq_component_ratio_of_family_of_ne_zero MX H D sDo H.cComponentSet S hScomp (fun C hC hne => hdisj hC hScomp hne) i hDobs hiS (extend xD) hrest0 calc tianPrefixStepDensity H D μ ref i xD = (((∏ C ∈ H.cComponentSet, MX.qLocalMass sDo (C ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) (extend xD)) / (∏ C ∈ H.cComponentSet, MX.qLocalMass sDo (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) (extend xD))) / jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) xD} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω)))) := by rw [hmass, hprefixProd_eq (i.val + 1), hprefixProd_eq i.val] _ = (MX.qLocalMass sDo (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) / MX.qLocalMass sDo (S ∩ H.prefixIn D i.val) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD)) / jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) xD} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) := by rw [hcancel] let idxS := Finset.univ.filter (fun i : Fin D.card => (H.nodesAt D i).val ∈ S) let qratio : Fin D.card → ENNReal := fun i => MX.qLocalMass sDo (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) / MX.qLocalMass sDo (S ∩ H.prefixIn D i.val) (fun _ hv => hSobsMX (mem_of_mem_inter_left hv)) (extend xD) let den : Fin D.card → ENNReal := fun i => jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) xD} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) have hden0 : ∀ i ∈ idxS, den i ≠ 0 := by intro i _hi exact jointRef_singleton_ne_zero ref href _ _ have hdentop : ∀ i ∈ idxS, den i ≠ ∞ := by intro i _hi exact ne_of_lt (MeasureTheory.measure_lt_top (jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N))) _) have hqprod : (∏ i ∈ idxS, qratio i) = MX.qLocalMass sDo S hSobsMX (extend xD) := by simpa [idxS, qratio] using component_qLocalMass_ratio_product_prefixIn_of_ne_zero MX H D sDo S hSobsMX hSD (extend xD) hS_q_ne0 have hdenprod : (∏ i ∈ idxS, den i) = jointRef ref S ({valuesProjection hSD xD} : Set (ValuesOn S (swigΩ Ω))) := by have hden_atom : (∏ i ∈ idxS, den i) = ∏ i ∈ idxS, ref.μ (H.nodesAt D i).val ({xD (H.nodesAt D i)} : Set (swigΩ Ω (H.nodesAt D i).val)) := by refine Finset.prod_congr rfl ?_ intro i hi dsimp [den] rw [jointRef_singleton_eq_prod] simp [valuesProjection] rw [hden_atom] -- … truncated; follow the source link for the rest …
lemma tian_full_cComponent_density_recovery_core_direct reviewed
Causalean.SCM.ID

District recovery (Tian Lemma 4 projection consistency). Consider a standard structural causal model M with an intervention set X whose random copies are observed and whose fixed copies are not already frozen, under a faithful reference-measure family and a positive observational kernel at every fixed-value assignment, for an outcome set Y disjoint from the random copies of X. For a set S that is simultaneously a district of the post-intervention ancestral graph and a full c-component of M, and an extension map that inverts the projection onto the ancestral observed coordinates and reproduces the intervention values sDo on the intervened coordinates, the Tian district density read off the do(X)-law ancestral marginal at S agrees, almost everywhere with respect to the product reference measure on the ancestral observed coordinates, with the observational c-component density factor at S pulled back through the extension.

Formal statement
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
M :
SCM N Ω
X :
hStd :
M.isStandard
hObs :
∀ D ∈ X, SWIGNode.random D ∈ M.observed
hFix :
∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
Y :
href :
sDo :
(M.fixSet X hObs hFix).FixedValues
S :
hS :
S ∈ fixTruncCComponentSet M X hObs hFix Y
hSfull :
S ∈ M.toSWIGGraph.cComponentSet
∀ s' :
M.FixedValues, IsFiniteMeasure (M.obsKernel s')
∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card),
StandardBorelSpace (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card),
Nonempty (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ (k : ℕ) (hk : k < M.observed.card),
StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ (k : ℕ) (hk : k < M.observed.card),
Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ k :
ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))
hpos :
∀ s' : M.FixedValues, DiscreteID.PositiveMass (M.obsKernel s')
hYX :
∀ D ∈ X, SWIGNode.random D ∉ Y
extend :
ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω)
hExtend :
∀ xD,
valuesProjection (show fixObservedAncestralSet M X hObs hFix Y ⊆ M.observed from inter_subset_right) (extend xD)
= xD
hExtendX :
∀ xD (D : N) (hD : D ∈ X),
extend xD ⟨SWIGNode.random D, hObs D hD⟩
= sDo ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩
let D := fixObservedAncestralSet M X hObs hFix Y let H := (M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y) tianDistrictDensity H D (doObsKernelAncestralMarginal M X hObs hFix Y sDo) ref S
=ᵐ[jointRef ref D] fun xD => M.cComponentDensityFactor ref (M.fixSetProj X hObs hFix sDo) S (extend xD)
Proof (Lean source)
lemma tian_full_cComponent_density_recovery_core_direct [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (X : Finset N) (hStd : M.isStandard) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (Y : Finset (SWIGNode N)) (ref : ReferenceMeasures Ω) (href : ReferenceFaithful ref) (sDo : (M.fixSet X hObs hFix).FixedValues) (S : Finset (SWIGNode N)) (hS : S ∈ fixTruncCComponentSet M X hObs hFix Y) (hSfull : S ∈ M.toSWIGGraph.cComponentSet) [IsFiniteMeasure (doObsKernelAncestralMarginal M X hObs hFix Y sDo)] [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card), StandardBorelSpace (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < (fixObservedAncestralSet M X hObs hFix Y).card), Nonempty (ValuesOn ({(((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).nodesAt (fixObservedAncestralSet M X hObs hFix Y) ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M.observed.card), StandardBorelSpace (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < M.observed.card), Nonempty (ValuesOn ({(M.observedAt ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ k : ℕ, CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.prefixNodes k) (swigΩ Ω))] (hpos : ∀ s' : M.FixedValues, DiscreteID.PositiveMass (M.obsKernel s')) (hYX : ∀ D ∈ X, SWIGNode.random D ∉ Y) (extend : ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω)) (hExtend : ∀ xD, valuesProjection (show fixObservedAncestralSet M X hObs hFix Y ⊆ M.observed from inter_subset_right) (extend xD) = xD) (hExtendX : ∀ xD (D : N) (hD : D ∈ X), extend xD ⟨SWIGNode.random D, hObs D hD⟩ = sDo ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩) : let D := fixObservedAncestralSet M X hObs hFix Y let H := (M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y) tianDistrictDensity H D (doObsKernelAncestralMarginal M X hObs hFix Y sDo) ref S =ᵐ[jointRef ref D] fun xD => M.cComponentDensityFactor ref (M.fixSetProj X hObs hFix sDo) S (extend xD) := by classical let D := fixObservedAncestralSet M X hObs hFix Y let H := (M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y) have hSobs : S ⊆ M.observed := M.toSWIGGraph.cComponentSet_subset_observed S hSfull have hSD : S ⊆ D := by have hSHobs : S ⊆ H.observed := by exact H.cComponentSet_subset_observed S (by simpa [H, fixTruncCComponentSet] using hS) exact hSHobs have hSX : ∀ n ∈ X, SWIGNode.random n ∉ S := by intro n hn hnS have hnD : SWIGNode.random n ∈ D := hSD hnS have hnA : SWIGNode.random n ∈ fixAncestralSet M X hObs hFix Y := by simpa [D, fixObservedAncestralSet] using (Finset.mem_inter.mp hnD).1 exact hYX n hn ((random_intervened_mem_fixAncestralSet_iff_mem_Y M X hObs hFix Y hn).mp hnA) filter_upwards with xD have hB : tianDistrictDensity H D (doObsKernelAncestralMarginal M X hObs hFix Y sDo) ref S xD = (M.fixSet X hObs hFix).mechCFactor ref S (by simpa [SCM.fixSet_observed] using hSobs) sDo (extend xD) := by simpa [H, D] using tianDistrictDensity_eq_mechCFactor_doModel M X hObs hFix Y ref href sDo hpos hYX hStd S hS hSfull extend hExtend xD have hC : (M.fixSet X hObs hFix).mechCFactor ref S (by simpa [SCM.fixSet_observed] using hSobs) sDo (extend xD) = M.mechCFactor ref S hSobs (M.fixSetProj X hObs hFix sDo) (extend xD) := by simpa using mechCFactor_fixSet_invariant M ref X href hStd hObs hFix S hSobs hSX sDo (extend xD) (fun D hD => hExtendX xD D hD) have hA : M.mechCFactor ref S hSobs (M.fixSetProj X hObs hFix sDo) (extend xD) = M.cComponentDensityFactor ref (M.fixSetProj X hObs hFix sDo) S (extend xD) := by exact (cComponentDensityFactor_eq_mechCFactor M ref (M.fixSetProj X hObs hFix sDo) hStd S hSobs hSfull href (hpos (M.fixSetProj X hObs hFix sDo)) (extend xD)).symm exact hB.trans (hC.trans hA)
14 supporting declarations (lemmas, instances)
  • prefixIn_obsParentClosed lemma — Topological prefixes of an observed-parent-closed set remain observed-parent-closed.
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    Y :
    k :
    (M.fixSet X hObs hFix).ObsParentClosed (((M.fixSet X hObs hFix).toSWIGGraph.induce (SCM.ID.fixAncestralSet M X hObs hFix Y)).prefixIn (SCM.ID.fixObservedAncestralSet M X hObs hFix Y) k)
    Proof (Lean source)
    lemma prefixIn_obsParentClosed (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (Y : Finset (SWIGNode N)) (k : ℕ) : (M.fixSet X hObs hFix).ObsParentClosed (((M.fixSet X hObs hFix).toSWIGGraph.induce (SCM.ID.fixAncestralSet M X hObs hFix Y)).prefixIn (SCM.ID.fixObservedAncestralSet M X hObs hFix Y) k) := by classical let M' := M.fixSet X hObs hFix let A := SCM.ID.fixAncestralSet M X hObs hFix Y let D := SCM.ID.fixObservedAncestralSet M X hObs hFix Y let H := M'.toSWIGGraph.induce A have hDclosed : M'.ObsParentClosed D := by simpa [M', D] using (SCM.ID.fixObservedAncestralSet_obsParent_closed M X hObs hFix Y) refine ⟨?_, ?_⟩ · intro v hv exact hDclosed.1 (H.prefixIn_subset D k hv) · intro v hv w hwObs hEdge have hvD : v ∈ D := H.prefixIn_subset D k hv have hwD : w ∈ D := hDclosed.2 v hvD w hwObs hEdge rcases Finset.mem_filter.mp hv with ⟨hvD₀, hvIdxLt₀⟩ have hvIdxLt : (H.nodeIndex D ⟨v, hvD⟩).val < k := by have hsub : (⟨v, hvD⟩ : {v // v ∈ D}) = ⟨v, hvD₀⟩ := Subtype.ext rfl simpa [SWIGGraph.prefixIn, hsub, hvD₀] using hvIdxLt₀ have hEdgeH : H.dag.edge w v := by have hwA : w ∈ A := (Finset.mem_inter.mp hwD).1 have hvA : v ∈ A := (Finset.mem_inter.mp hvD).1 have hvObs : v ∈ M'.observed := hDclosed.1 hvD dsimp [H, M', A, SWIGGraph.induce, SWIGGraph.inducedDag, SWIGGraph.inducedEdge] refine ⟨hEdge, ?_, ?_⟩ · exact mem_union_left _ (mem_union_right _ (Finset.mem_inter.mpr ⟨hwA, hwObs⟩)) · exact mem_union_left _ (mem_union_right _ (Finset.mem_inter.mpr ⟨hvA, hvObs⟩)) have hTopo : H.dag.topoOrder w < H.dag.topoOrder v := H.dag.topoOrder_lt w v hEdgeH letI := H.topoLinearOrder have hSubtypeLt : (⟨w, hwD⟩ : {v // v ∈ D}) < ⟨v, hvD⟩ := by change H.dag.topoOrder w < H.dag.topoOrder v exact hTopo have hIndexLt : (H.nodeIndex D ⟨w, hwD⟩).val < (H.nodeIndex D ⟨v, hvD⟩).val := by have hIndexLtFin : H.nodeIndex D ⟨w, hwD⟩ < H.nodeIndex D ⟨v, hvD⟩ := by simpa [SWIGGraph.nodeIndex] using ((D.orderIsoOfFin rfl).symm.strictMono hSubtypeLt) simpa [SWIGGraph.nodeIndex] using hIndexLtFin change w ∈ D.filter (fun v => if h : v ∈ D then (H.nodeIndex D ⟨v, h⟩).val < k else False) exact Finset.mem_filter.mpr ⟨hwD, by simpa [hwD] using lt_trans hIndexLt hvIdxLt⟩
    Causalean.SWIGGraph.prefixIn_obsParentClosed · Causalean/SCM/ID/Density/QFactor.lean:41
  • mem_cComponent_iff_cComponentOf_eq lemma — For an observed node and a c-component listed in cComponentSet, membership in that component is the same as saying that the node's computed c-component is that listed component. This converts Tian's district factor, which filters by membership in a district, into the fiber form needed for finite-product regrouping.
    G :
    v :
    S :
    hv :
    v ∈ G.observed
    hS :
    S ∈ G.cComponentSet
    v ∈ S ↔ G.cComponentOf v = S
    Proof (Lean source)
    lemma mem_cComponent_iff_cComponentOf_eq (G : SWIGGraph N) {v : SWIGNode N} {S : Finset (SWIGNode N)} (hv : v ∈ G.observed) (hS : S ∈ G.cComponentSet) : v ∈ S ↔ G.cComponentOf v = S := by constructor · intro hvS rw [SWIGGraph.cComponentSet, mem_image] at hS obtain ⟨w, hw, rfl⟩ := hS have hwv : G.bidirectedReachable w v := (G.mem_cComponentOf_iff_reachable hw).mp hvS exact (G.cComponentOf_eq_of_reachable hwv).symm · intro hcomp exact hcomp ▸ G.mem_cComponentOf_self hv
    Causalean.SCM.ID.mem_cComponent_iff_cComponentOf_eq · Causalean/SCM/ID/Density/QFactor.lean:211
  • prod_tianDistrictDensity_eq_tianDensityProduct theorem — Tian's full prefix-chain density regroups exactly as the product of the Tian district factors over the graph c-components. This is pure finite-product algebra: each prefix index maps to the c-component of its node, and the district factor is precisely the product over the corresponding fiber.
    H :
    D :
    hD :
    H.observed = D
    μ :
    ∀ (k : ℕ) (hk : k < D.card),
    StandardBorelSpace (ValuesOn ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
    ∀ (k : ℕ) (hk : k < D.card),
    Nonempty (ValuesOn ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
    (fun x => ∏ S ∈ H.cComponentSet, tianDistrictDensity H D μ ref S x)
    = fun x => tianDensityProduct H D μ ref x
    Proof (Lean source)
    theorem prod_tianDistrictDensity_eq_tianDensityProduct (H : SWIGGraph N) (D : Finset (SWIGNode N)) (hD : H.observed = D) (μ : Measure (ValuesOn D (swigΩ Ω))) (ref : ReferenceMeasures Ω) [IsFiniteMeasure μ] [∀ (k : ℕ) (hk : k < D.card), StandardBorelSpace (ValuesOn ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < D.card), Nonempty (ValuesOn ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] : (fun x => ∏ S ∈ H.cComponentSet, tianDistrictDensity H D μ ref S x) = fun x => tianDensityProduct H D μ ref x := by classical funext x have hmaps : ∀ i ∈ (Finset.univ : Finset (Fin D.card)), H.cComponentOf (H.nodesAt D i).val ∈ H.cComponentSet := by intro i _ exact Finset.mem_image.mpr ⟨(H.nodesAt D i).val, hD.symm ▸ (H.nodesAt D i).property, rfl⟩ unfold tianDensityProduct tianDistrictDensity rw [← Finset.prod_fiberwise_of_maps_to hmaps (fun i => tianPrefixStepDensity H D μ ref i x)] refine Finset.prod_congr rfl ?_ intro S hS refine Finset.prod_congr ?_ (fun i _ => rfl) ext i simp only [mem_filter, Finset.mem_univ, true_and] exact mem_cComponent_iff_cComponentOf_eq H (hD.symm ▸ (H.nodesAt D i).property) hS
    Causalean.SCM.ID.prod_tianDistrictDensity_eq_tianDensityProduct · Causalean/SCM/ID/Density/QFactor.lean:230
  • prefixIn_parent_closed_induce_observed lemma — In an induced set of observed variables, every topological prefix contains all parents within that set of each variable it contains.
    M :
    SCM N Ω
    A :
    hA :
    A ⊆ M.observed
    k :
    ∀ v ∈ A,
    ∀ w ∈ (M.toSWIGGraph.induce A).prefixIn A k,
    M.dag.edge v w → v ∈ (M.toSWIGGraph.induce A).prefixIn A k
    Proof (Lean source)
    lemma prefixIn_parent_closed_induce_observed (M : SCM N Ω) (A : Finset (SWIGNode N)) (hA : A ⊆ M.observed) (k : ℕ) : ∀ v ∈ A, ∀ w ∈ (M.toSWIGGraph.induce A).prefixIn A k, M.dag.edge v w → v ∈ (M.toSWIGGraph.induce A).prefixIn A k := by classical intro v hvA w hwPre hEdge let H := M.toSWIGGraph.induce A have hwA : w ∈ A := H.prefixIn_subset A k hwPre have hEdgeH : H.dag.edge v w := by dsimp [H, SWIGGraph.induce] rw [SWIGGraph.inducedDag_edge_iff] refine ⟨hEdge, ?_, ?_⟩ · simp [hvA, hA hvA] · simp [hwA, hA hwA] have hTopo : H.dag.topoOrder v < H.dag.topoOrder w := H.dag.topoOrder_lt v w hEdgeH rcases (mem_prefixIn_iff_qfactor H A k w).mp hwPre with ⟨hwA', hwIdxLt⟩ letI := H.topoLinearOrder have hSubtypeLt : (⟨v, hvA⟩ : {v // v ∈ A}) < ⟨w, hwA'⟩ := by change H.dag.topoOrder v < H.dag.topoOrder w exact hTopo have hIndexLt : (H.nodeIndex A ⟨v, hvA⟩).val < (H.nodeIndex A ⟨w, hwA'⟩).val := by have hIndexLtFin : H.nodeIndex A ⟨v, hvA⟩ < H.nodeIndex A ⟨w, hwA'⟩ := by simpa [SWIGGraph.nodeIndex] using ((A.orderIsoOfFin rfl).symm.strictMono hSubtypeLt) simpa [SWIGGraph.nodeIndex] using hIndexLtFin exact (mem_prefixIn_iff_qfactor H A k v).mpr ⟨hvA, lt_trans hIndexLt hwIdxLt⟩
    Causalean.SCM.ID.prefixIn_parent_closed_induce_observed · Causalean/SCM/ID/Density/QFactor.lean:379
  • prefixIn_qProduct_ratio_eq_component_ratio_of_family lemma — In a product over an abstract pairwise-disjoint family, the prefix-ratio step at a node of S cancels every factor except the S factor.
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    H :
    D :
    s :
    M.FixedValues
    𝒞 :
    S :
    hS𝒞 :
    S ∈ 𝒞
    hdisj :
    ∀ C ∈ 𝒞
    if
    C ≠ S
    then
    i :
    Fin D.card
    hDobs :
    D ⊆ M.observed
    hiS :
    (H.nodesAt D i).val ∈ S
    hpos :
    DiscreteID.PositiveMass (M.obsKernel s)
    x :
    ValuesOn M.observed (swigΩ Ω)
    (∏ C ∈ 𝒞, M.qLocalMass s (C ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x) / (∏ C ∈ 𝒞, M.qLocalMass s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x)
    = M.qLocalMass s (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x / M.qLocalMass s (S ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x
    Proof (Lean source)
    lemma prefixIn_qProduct_ratio_eq_component_ratio_of_family [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (H : SWIGGraph N) (D : Finset (SWIGNode N)) (s : M.FixedValues) (𝒞 : Finset (Finset (SWIGNode N))) (S : Finset (SWIGNode N)) (hS𝒞 : S ∈ 𝒞) (hdisj : ∀ C ∈ 𝒞, C ≠ S → Disjoint C S) (i : Fin D.card) (hDobs : D ⊆ M.observed) (hiS : (H.nodesAt D i).val ∈ S) (hpos : DiscreteID.PositiveMass (M.obsKernel s)) (x : ValuesOn M.observed (swigΩ Ω)) : (∏ C ∈ 𝒞, M.qLocalMass s (C ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x) / (∏ C ∈ 𝒞, M.qLocalMass s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x) = M.qLocalMass s (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x / M.qLocalMass s (S ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x := by classical let f₁ : Finset (SWIGNode N) → ENNReal := fun C => M.qLocalMass s (C ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x let f₀ : Finset (SWIGNode N) → ENNReal := fun C => M.qLocalMass s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x have hrest : ∏ C ∈ 𝒞 \ {S}, f₁ C = ∏ C ∈ 𝒞 \ {S}, f₀ C := by refine Finset.prod_congr rfl ?_ intro C hC have hC𝒞 : C ∈ 𝒞 := (Finset.mem_sdiff.mp hC).1 have hCne : C ≠ S := by intro h exact (Finset.mem_sdiff.mp hC).2 (by simp [h]) simp [f₁, f₀, family_inter_prefixIn_succ_eq_of_ne H D hiS (hdisj C hC𝒞 hCne)] have hsplit₁ : (∏ C ∈ 𝒞, f₁ C) = f₁ S * ∏ C ∈ 𝒞 \ {S}, f₁ C := by exact Finset.prod_eq_mul_prod_diff_singleton S f₁ (by intro h; exact elim (h hS𝒞)) have hsplit₀ : (∏ C ∈ 𝒞, f₀ C) = f₀ S * ∏ C ∈ 𝒞 \ {S}, f₀ C := by exact Finset.prod_eq_mul_prod_diff_singleton S f₀ (by intro h; exact elim (h hS𝒞)) have hr0 : (∏ C ∈ 𝒞 \ {S}, f₀ C) ≠ 0 := by exact Finset.prod_ne_zero_iff.mpr (by intro C _hC exact M.qLocalMass_pos_of_positiveObs s hpos (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x) have hrtop : (∏ C ∈ 𝒞 \ {S}, f₀ C) ≠ ∞ := by exact Finset.prod_ne_top_of_ne_top _ f₀ (by intro C _hC exact qLocalMass_ne_top M s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x) change (∏ C ∈ 𝒞, f₁ C) / (∏ C ∈ 𝒞, f₀ C) = f₁ S / f₀ S rw [hsplit₁, hsplit₀, hrest] exact ENNReal.div_mul_common hr0 hrtop
    Causalean.SCM.ID.prefixIn_qProduct_ratio_eq_component_ratio_of_family · Causalean/SCM/ID/Density/QFactor.lean:545
  • prefixIn_qProduct_ratio_eq_component_ratio_of_family_of_ne_zero lemma — Nonzero-denominator variant of prefixIn_qProduct_ratio_eq_component_ratio_of_family.
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    H :
    D :
    s :
    M.FixedValues
    𝒞 :
    S :
    hS𝒞 :
    S ∈ 𝒞
    hdisj :
    ∀ C ∈ 𝒞
    if
    C ≠ S
    then
    i :
    Fin D.card
    hDobs :
    D ⊆ M.observed
    hiS :
    (H.nodesAt D i).val ∈ S
    x :
    ValuesOn M.observed (swigΩ Ω)
    hrest0 :
    (∏ C ∈ 𝒞 \ {S}, M.qLocalMass s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x)
    ≠ 0
    (∏ C ∈ 𝒞, M.qLocalMass s (C ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x) / (∏ C ∈ 𝒞, M.qLocalMass s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x)
    = M.qLocalMass s (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x / M.qLocalMass s (S ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x
    Proof (Lean source)
    lemma prefixIn_qProduct_ratio_eq_component_ratio_of_family_of_ne_zero [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (H : SWIGGraph N) (D : Finset (SWIGNode N)) (s : M.FixedValues) (𝒞 : Finset (Finset (SWIGNode N))) (S : Finset (SWIGNode N)) (hS𝒞 : S ∈ 𝒞) (hdisj : ∀ C ∈ 𝒞, C ≠ S → Disjoint C S) (i : Fin D.card) (hDobs : D ⊆ M.observed) (hiS : (H.nodesAt D i).val ∈ S) (x : ValuesOn M.observed (swigΩ Ω)) (hrest0 : (∏ C ∈ 𝒞 \ {S}, M.qLocalMass s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x) ≠ 0) : (∏ C ∈ 𝒞, M.qLocalMass s (C ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x) / (∏ C ∈ 𝒞, M.qLocalMass s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x) = M.qLocalMass s (S ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x / M.qLocalMass s (S ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x := by classical let f₁ : Finset (SWIGNode N) → ENNReal := fun C => M.qLocalMass s (C ∩ H.prefixIn D (i.val + 1)) (fun _ hv => hDobs (H.prefixIn_subset D (i.val + 1) (mem_of_mem_inter_right hv))) x let f₀ : Finset (SWIGNode N) → ENNReal := fun C => M.qLocalMass s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x have hrest : ∏ C ∈ 𝒞 \ {S}, f₁ C = ∏ C ∈ 𝒞 \ {S}, f₀ C := by refine Finset.prod_congr rfl ?_ intro C hC have hC𝒞 : C ∈ 𝒞 := (Finset.mem_sdiff.mp hC).1 have hCne : C ≠ S := by intro h exact (Finset.mem_sdiff.mp hC).2 (by simp [h]) simp [f₁, f₀, family_inter_prefixIn_succ_eq_of_ne H D hiS (hdisj C hC𝒞 hCne)] have hsplit₁ : (∏ C ∈ 𝒞, f₁ C) = f₁ S * ∏ C ∈ 𝒞 \ {S}, f₁ C := by exact Finset.prod_eq_mul_prod_diff_singleton S f₁ (by intro h; exact elim (h hS𝒞)) have hsplit₀ : (∏ C ∈ 𝒞, f₀ C) = f₀ S * ∏ C ∈ 𝒞 \ {S}, f₀ C := by exact Finset.prod_eq_mul_prod_diff_singleton S f₀ (by intro h; exact elim (h hS𝒞)) have hrtop : (∏ C ∈ 𝒞 \ {S}, f₀ C) ≠ ∞ := by exact Finset.prod_ne_top_of_ne_top _ f₀ (by intro C _hC exact qLocalMass_ne_top M s (C ∩ H.prefixIn D i.val) (fun _ hv => hDobs (H.prefixIn_subset D i.val (mem_of_mem_inter_right hv))) x) change (∏ C ∈ 𝒞, f₁ C) / (∏ C ∈ 𝒞, f₀ C) = f₁ S / f₀ S rw [hsplit₁, hsplit₀, hrest] exact ENNReal.div_mul_common hrest0 hrtop
    Causalean.SCM.ID.prefixIn_qProduct_ratio_eq_component_ratio_of_family_of_ne_zero · Causalean/SCM/ID/Density/QFactor.lean:684
  • extractDistrict_qLocalMass lemma — Extracting an induced district from the local mass on an ancestral set recovers that district's local q-mass.
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    s :
    M.FixedValues
    A C' :
    hA :
    A ⊆ M.observed
    hC' :
    C' ∈ (M.toSWIGGraph.induce A).cComponentSet
    hpos :
    DiscreteID.PositiveMass (M.obsKernel s)
    x :
    ValuesOn M.observed (swigΩ Ω)
    extractDistrict M.observed (M.toSWIGGraph.induce A) A C' hA (M.qLocalMass s A hA) x
    = M.qLocalMass s C' (fun _ hv => hA (by have hHobs : (M.toSWIGGraph.induce A).observed = A := by simp [SWIGGraph.induce, Finset.inter_eq_left.mpr hA] exact hHobs ▸ (M.toSWIGGraph.induce A).cComponentSet_subset_observed C' hC' hv)) x
    Proof (Lean source)
    lemma extractDistrict_qLocalMass [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (s : M.FixedValues) (A C' : Finset (SWIGNode N)) (hA : A ⊆ M.observed) (hC' : C' ∈ (M.toSWIGGraph.induce A).cComponentSet) (hpos : DiscreteID.PositiveMass (M.obsKernel s)) (x : ValuesOn M.observed (swigΩ Ω)) : extractDistrict M.observed (M.toSWIGGraph.induce A) A C' hA (M.qLocalMass s A hA) x = M.qLocalMass s C' (fun _ hv => hA (by have hHobs : (M.toSWIGGraph.induce A).observed = A := by simp [SWIGGraph.induce, Finset.inter_eq_left.mpr hA] exact hHobs ▸ (M.toSWIGGraph.induce A).cComponentSet_subset_observed C' hC' hv)) x := by classical let H := M.toSWIGGraph.induce A have hHobs : H.observed = A := by simp [H, SWIGGraph.induce, Finset.inter_eq_left.mpr hA] have hCobs : C' ⊆ M.observed := by intro v hv exact hA (hHobs ▸ H.cComponentSet_subset_observed C' hC' hv) have hCA : C' ⊆ A := by intro v hv exact hHobs ▸ H.cComponentSet_subset_observed C' hC' hv have hdisj : (↑H.cComponentSet : Set (Finset (SWIGNode N))).Pairwise (fun U U' => Disjoint U U') := by intro U hU V hV hne exact H.cComponentSet_pairwise_disjoint hU hV hne have hmarg : ∀ k, marginalizeOn M.observed (A \ H.prefixIn A k) (fun _ hv => hA ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s A hA) x = M.qLocalMass s (H.prefixIn A k) (fun _ hv => hA (H.prefixIn_subset A k hv)) x := by intro k simpa [H] using M.qLocalMass_marginalize_ancestralClosed s A (H.prefixIn A k) hA (H.prefixIn_subset A k) (prefixIn_parent_closed_induce_observed M A hA k) x have hprod : ∀ k, M.qLocalMass s (H.prefixIn A k) (fun _ hv => hA (H.prefixIn_subset A k hv)) x = ∏ C ∈ H.cComponentSet, M.qLocalMass s (C ∩ H.prefixIn A k) (fun _ hv => hA (H.prefixIn_subset A k (mem_of_mem_inter_right hv))) x := by intro k simpa [H] using qLocalMass_prefixIn_eq_prod_induce_components M s A hA k x unfold SCM.extractDistrict calc (∏ i ∈ Finset.univ.filter (fun i : Fin A.card => (H.nodesAt A i).val ∈ C'), marginalizeOn M.observed (A \ H.prefixIn A (i.val + 1)) (fun _ hv => hA ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s A hA) x / marginalizeOn M.observed (A \ H.prefixIn A i.val) (fun _ hv => hA ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s A hA) x) = ∏ i ∈ Finset.univ.filter (fun i : Fin A.card => (H.nodesAt A i).val ∈ C'), (∏ C ∈ H.cComponentSet, M.qLocalMass s (C ∩ H.prefixIn A (i.val + 1)) (fun _ hv => hA (H.prefixIn_subset A (i.val + 1) (mem_of_mem_inter_right hv))) x) / (∏ C ∈ H.cComponentSet, M.qLocalMass s (C ∩ H.prefixIn A i.val) (fun _ hv => hA (H.prefixIn_subset A i.val (mem_of_mem_inter_right hv))) x) := by refine Finset.prod_congr rfl ?_ intro i _hi rw [hmarg (i.val + 1), hmarg i.val, hprod (i.val + 1), hprod i.val] _ = ∏ i ∈ Finset.univ.filter (fun i : Fin A.card => (H.nodesAt A i).val ∈ C'), M.qLocalMass s (C' ∩ H.prefixIn A (i.val + 1)) (fun _ hv => hA (H.prefixIn_subset A (i.val + 1) (mem_of_mem_inter_right hv))) x / M.qLocalMass s (C' ∩ H.prefixIn A i.val) (fun _ hv => hA (H.prefixIn_subset A i.val (mem_of_mem_inter_right hv))) x := by refine Finset.prod_congr rfl ?_ intro i hi have hiC : (H.nodesAt A i).val ∈ C' := (Finset.mem_filter.mp hi).2 exact prefixIn_qProduct_ratio_eq_component_ratio_of_family M H A s H.cComponentSet C' hC' (fun C hC hne => hdisj hC hC' hne) i hA hiC hpos x _ = M.qLocalMass s C' hCobs x := by simpa using component_qLocalMass_ratio_product_prefixIn M H A s C' hCobs hCA hpos x _ = M.qLocalMass s C' (fun _ hv => hA (by have hHobs' : (M.toSWIGGraph.induce A).observed = A := by simp [SWIGGraph.induce, Finset.inter_eq_left.mpr hA] exact hHobs' ▸ (M.toSWIGGraph.induce A).cComponentSet_subset_observed C' hC' hv)) x := by rfl
    Causalean.SCM.ID.extractDistrict_qLocalMass · Causalean/SCM/ID/Density/QFactor.lean:938
  • target_subset theorem — The target set of a recursive c-factor reachability certificate is contained in the source set.
    G :
    T C :
    C ⊆ T
    Proof (Lean source)
    theorem CFactorReachableRec.target_subset {G : SWIGGraph N} {T C : Finset (SWIGNode N)} (h : CFactorReachableRec G T C) : C ⊆ T := by cases h with | base _ hCT _ => exact hCT | step _ hCT _ _ _ => exact hCT
    Causalean.SCM.ID.CFactorReachableRec.target_subset · Causalean/SCM/ID/Density/QFactor.lean:1047
  • qLocalMass_obsProof_irrel lemma — The local q-mass of an observed variable set does not depend on which proof establishes that the set is observed.
    M :
    SCM N Ω
    s :
    M.FixedValues
    T :
    hT hT' :
    T ⊆ M.observed
    x :
    ValuesOn M.observed (swigΩ Ω)
    M.qLocalMass s T hT x = M.qLocalMass s T hT' x
    Proof (Lean source)
    lemma qLocalMass_obsProof_irrel (M : SCM N Ω) (s : M.FixedValues) (T : Finset (SWIGNode N)) (hT hT' : T ⊆ M.observed) (x : ValuesOn M.observed (swigΩ Ω)) : M.qLocalMass s T hT x = M.qLocalMass s T hT' x := by unfold SCM.qLocalMass congr 1
    Causalean.SCM.ID.qLocalMass_obsProof_irrel · Causalean/SCM/ID/Density/QFactor.lean:1056
  • identifyMassRec_qLocalMass theorem — The obs-side IDENTIFY recursion recovers the local q-mass of the target district from the local q-mass of any recursively reachable source district.
    ∀ n, Fintype (Ω n)
    M :
    SCM N Ω
    s :
    M.FixedValues
    hpos :
    DiscreteID.PositiveMass (M.obsKernel s)
    T C :
    hT :
    T ⊆ M.observed
    hReach :
    CFactorReachableRec M.toSWIGGraph T C
    x :
    ValuesOn M.observed (swigΩ Ω)
    identifyMassRec M.observed M.toSWIGGraph T C hT (M.qLocalMass s T hT) x
    = M.qLocalMass s C (fun _ hv => hT (hReach.target_subset hv)) x
    Proof (Lean source)
    theorem identifyMassRec_qLocalMass [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (M : SCM N Ω) (s : M.FixedValues) (hpos : DiscreteID.PositiveMass (M.obsKernel s)) (T C : Finset (SWIGNode N)) (hT : T ⊆ M.observed) (hReach : CFactorReachableRec M.toSWIGGraph T C) (x : ValuesOn M.observed (swigΩ Ω)) : identifyMassRec M.observed M.toSWIGGraph T C hT (M.qLocalMass s T hT) x = M.qLocalMass s C (fun _ hv => hT (hReach.target_subset hv)) x := by classical induction hReach generalizing x with | base hne hCT hproject => rename_i T₀ C₀ rw [SCM.identifyMassRec_base M M.toSWIGGraph T₀ C₀ hT (M.qLocalMass s T₀ hT) hproject] have hclosed : ∀ v ∈ T₀, ∀ w ∈ C₀, M.dag.edge v w → v ∈ C₀ := by have hclosedA := inducedAncestral_parent_closed M.toSWIGGraph (T := T₀) (C := C₀) (by simpa using hT) intro v hvT w hwC hEdge have hwA : w ∈ inducedAncestral M.toSWIGGraph T₀ C₀ := by simpa [hproject] using hwC have hvA := hclosedA v hvT w hwA hEdge simpa [hproject] using hvA exact M.qLocalMass_marginalize_ancestralClosed s T₀ C₀ hT hCT hclosed x | step hne hCT hnotC hnotT hrec ih => rename_i T₀ C₀ let A := inducedAncestral M.toSWIGGraph T₀ C₀ let C₁ := containingCComponent (M.toSWIGGraph.induce A) C₀ let hA : A ⊆ M.observed := fun _ hv => hT (inducedAncestral_subset_left M.toSWIGGraph T₀ C₀ hv) let hC₁obs : C₁ ⊆ M.observed := fun _ hv => hT (inducedAncestral_subset_left M.toSWIGGraph T₀ C₀ (containingCComponent_induce_subset M.toSWIGGraph A C₀ hv)) have hCobs : C₀ ⊆ M.toSWIGGraph.observed := by intro v hv simpa using hT (hCT hv) have hCA : C₀ ⊆ A := subset_inducedAncestral M.toSWIGGraph hCT hCobs have hC₁mem : C₁ ∈ (M.toSWIGGraph.induce A).cComponentSet := by simp only [C₁, containingCComponent, dif_pos hne, SWIGGraph.cComponentSet] have hchooseA : hne.choose ∈ A := hCA hne.choose_spec have hchooseObs : hne.choose ∈ M.toSWIGGraph.observed := hCobs hne.choose_spec have hchooseInd : hne.choose ∈ (M.toSWIGGraph.induce A).observed := by simp [SWIGGraph.induce, hchooseA, hchooseObs] exact Finset.mem_image.mpr ⟨hne.choose, hchooseInd, rfl⟩ have hmarg : marginalizeOn M.observed (T₀ \ A) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s T₀ hT) = M.qLocalMass s A hA := by funext y have hclosedA : ∀ v ∈ T₀, ∀ w ∈ A, M.dag.edge v w → v ∈ A := by simpa [A] using inducedAncestral_parent_closed M.toSWIGGraph (T := T₀) (C := C₀) (by simpa using hT) exact M.qLocalMass_marginalize_ancestralClosed s T₀ A hT (inducedAncestral_subset_left M.toSWIGGraph T₀ C₀) hclosedA y have hextract : extractDistrict M.observed (M.toSWIGGraph.induce A) A C₁ hA (M.qLocalMass s A hA) = M.qLocalMass s C₁ hC₁obs := by funext y calc extractDistrict M.observed (M.toSWIGGraph.induce A) A C₁ hA (M.qLocalMass s A hA) y = M.qLocalMass s C₁ (fun _ hv => hA (by have hHobs : (M.toSWIGGraph.induce A).observed = A := by simp [SWIGGraph.induce, Finset.inter_eq_left.mpr hA] exact hHobs ▸ (M.toSWIGGraph.induce A).cComponentSet_subset_observed C₁ hC₁mem hv)) y := by exact extractDistrict_qLocalMass M s A C₁ hA hC₁mem hpos y _ = M.qLocalMass s C₁ hC₁obs y := by exact qLocalMass_obsProof_irrel M s C₁ _ _ y rw [SCM.identifyMassRec_step M M.toSWIGGraph T₀ C₀ hT (M.qLocalMass s T₀ hT) hnotC hnotT] change identifyMassRec M.observed M.toSWIGGraph C₁ C₀ hC₁obs (extractDistrict M.observed (M.toSWIGGraph.induce A) A C₁ hA (marginalizeOn M.observed (T₀ \ A) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) (M.qLocalMass s T₀ hT))) x = _ rw [hmarg, hextract] calc identifyMassRec M.observed M.toSWIGGraph C₁ C₀ hC₁obs (M.qLocalMass s C₁ hC₁obs) x = M.qLocalMass s C₀ (fun _ hv => hC₁obs (hrec.target_subset hv)) x := by exact ih hC₁obs x _ = M.qLocalMass s C₀ (fun _ hv => hT ((CFactorReachableRec.step hne hCT hnotC hnotT hrec).target_subset hv)) x := by exact qLocalMass_obsProof_irrel M s C₀ _ _ x
    Causalean.SCM.ID.identifyMassRec_qLocalMass · Causalean/SCM/ID/Density/QFactor.lean:1066
  • component_ref_atom_product_eq_jointRef_prefixIn lemma — For a subset of an ordered finite graph set, the product of coordinate reference-measure masses at selected values equals the reference measure's mass at their joint singleton outcome.
    H :
    D :
    S :
    hSD :
    S ⊆ D
    xD :
    (∏ i ∈ Finset.univ.filter (fun i : Fin D.card => (H.nodesAt D i).val ∈ S), ref.μ (H.nodesAt D i).val ({xD (H.nodesAt D i)} : Set (swigΩ Ω (H.nodesAt D i).val)))
    = jointRef ref S ({valuesProjection hSD xD} : Set (ValuesOn S (swigΩ Ω)))
    Proof (Lean source)
    lemma component_ref_atom_product_eq_jointRef_prefixIn [∀ n, MeasurableSingletonClass (Ω n)] (H : SWIGGraph N) (D : Finset (SWIGNode N)) (ref : ReferenceMeasures Ω) (S : Finset (SWIGNode N)) (hSD : S ⊆ D) (xD : ValuesOn D (swigΩ Ω)) : (∏ i ∈ Finset.univ.filter (fun i : Fin D.card => (H.nodesAt D i).val ∈ S), ref.μ (H.nodesAt D i).val ({xD (H.nodesAt D i)} : Set (swigΩ Ω (H.nodesAt D i).val))) = jointRef ref S ({valuesProjection hSD xD} : Set (ValuesOn S (swigΩ Ω))) := by classical have hprod : (∏ i ∈ Finset.univ.filter (fun i : Fin D.card => (H.nodesAt D i).val ∈ S), ref.μ (H.nodesAt D i).val ({xD (H.nodesAt D i)} : Set (swigΩ Ω (H.nodesAt D i).val))) = ∏ v : {v // v ∈ S}, ref.μ v.val ({(valuesProjection hSD xD) v} : Set (swigΩ Ω v.val)) := by refine Finset.prod_bij (fun i hi => ⟨(H.nodesAt D i).val, (Finset.mem_filter.mp hi).2⟩) ?_ ?_ ?_ ?_ · intro i hi exact Finset.mem_univ _ · intro i _hi j _hj hij have hval : (H.nodesAt D i).val = (H.nodesAt D j).val := congrArg (fun v : {v // v ∈ S} => v.val) hij have hsub : H.nodesAt D i = H.nodesAt D j := Subtype.ext hval calc i = H.nodeIndex D (H.nodesAt D i) := by simp [SWIGGraph.nodeIndex, SWIGGraph.nodesAt] _ = H.nodeIndex D (H.nodesAt D j) := by rw [hsub] _ = j := by simp [SWIGGraph.nodeIndex, SWIGGraph.nodesAt] · intro v _hv let i : Fin D.card := H.nodeIndex D ⟨v.val, hSD v.property⟩ have hnode : (H.nodesAt D i).val = v.val := by have hround : H.nodesAt D (H.nodeIndex D ⟨v.val, hSD v.property⟩) = ⟨v.val, hSD v.property⟩ := by simp [SWIGGraph.nodeIndex, SWIGGraph.nodesAt] exact congrArg val hround refine ⟨i, ?_, ?_⟩ · rw [mem_filter] exact ⟨Finset.mem_univ _, by simp [hnode, v.property]⟩ · exact Subtype.ext hnode · intro i hi simp [valuesProjection] rw [jointRef_singleton_eq_prod] exact hprod
    Causalean.SCM.ID.component_ref_atom_product_eq_jointRef_prefixIn · Causalean/SCM/ID/Density/QFactor.lean:1170
  • prefix_pair_singleton_mass_eq_succ_prefix_mass lemma — The mass of a realized prefix together with its next coordinate equals the mass of the same realization of the successor prefix under any measure on the ordered graph values.
    H :
    D :
    μ :
    i :
    Fin D.card
    x :
    (μ.map (fun ω : ValuesOn D (swigΩ Ω) => (valuesProjection (H.prefixIn_subset D i.val) ω, valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) ω))) ({(valuesProjection (H.prefixIn_subset D i.val) x, valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) x)} : Set (ValuesOn (H.prefixIn D i.val) (swigΩ Ω) × ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω)))
    = (μ.map (valuesProjection (H.prefixIn_subset D (i.val + 1)))) ({valuesProjection (H.prefixIn_subset D (i.val + 1)) x} : Set (ValuesOn (H.prefixIn D (i.val + 1)) (swigΩ Ω)))
    Proof (Lean source)
    lemma prefix_pair_singleton_mass_eq_succ_prefix_mass [∀ n, MeasurableSingletonClass (Ω n)] (H : SWIGGraph N) (D : Finset (SWIGNode N)) (μ : Measure (ValuesOn D (swigΩ Ω))) (i : Fin D.card) (x : ValuesOn D (swigΩ Ω)) : (μ.map (fun ω : ValuesOn D (swigΩ Ω) => (valuesProjection (H.prefixIn_subset D i.val) ω, valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) ω))) ({(valuesProjection (H.prefixIn_subset D i.val) x, valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) x)} : Set (ValuesOn (H.prefixIn D i.val) (swigΩ Ω) × ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) = (μ.map (valuesProjection (H.prefixIn_subset D (i.val + 1)))) ({valuesProjection (H.prefixIn_subset D (i.val + 1)) x} : Set (ValuesOn (H.prefixIn D (i.val + 1)) (swigΩ Ω))) := by classical let hNodeD : ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D := by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property let pairMap : ValuesOn D (swigΩ Ω) → ValuesOn (H.prefixIn D i.val) (swigΩ Ω) × ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω) := fun ω => (valuesProjection (H.prefixIn_subset D i.val) ω, valuesProjection hNodeD ω) let succMap : ValuesOn D (swigΩ Ω) → ValuesOn (H.prefixIn D (i.val + 1)) (swigΩ Ω) := valuesProjection (H.prefixIn_subset D (i.val + 1)) have hsets : pairMap ⁻¹' ({(valuesProjection (H.prefixIn_subset D i.val) x, valuesProjection hNodeD x)} : Set (ValuesOn (H.prefixIn D i.val) (swigΩ Ω) × ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) = succMap ⁻¹' ({valuesProjection (H.prefixIn_subset D (i.val + 1)) x} : Set (ValuesOn (H.prefixIn D (i.val + 1)) (swigΩ Ω))) := by ext ω constructor · intro hω have hpre : valuesProjection (H.prefixIn_subset D i.val) ω = valuesProjection (H.prefixIn_subset D i.val) x := congrArg Prod.fst hω have hnode : valuesProjection hNodeD ω = valuesProjection hNodeD x := congrArg Prod.snd hω ext v by_cases hvpre : v.val ∈ H.prefixIn D i.val · have h := congrFun hpre ⟨v.val, hvpre⟩ simpa [succMap, valuesProjection] using h · have hvnode : v.val = (H.nodesAt D i).val := by have hvsucc : v.val ∈ H.prefixIn D (i.val + 1) := v.property have hvsucc' : v.val ∈ H.prefixIn D i.val ∪ {(H.nodesAt D i).val} := by simpa [prefixIn_succ_qfactor H D i.isLt] using hvsucc rcases Finset.mem_union.mp hvsucc' with hvold | hvnew · exact elim (hvpre hvold) · simpa using hvnew have h := congrFun hnode ⟨v.val, by simpa [hvnode] using mem_singleton_self (H.nodesAt D i).val⟩ simpa [succMap, valuesProjection, hvnode] using h · intro hω have hsucc : valuesProjection (H.prefixIn_subset D (i.val + 1)) ω = valuesProjection (H.prefixIn_subset D (i.val + 1)) x := hω apply Prod.ext · ext v have hvsucc : v.val ∈ H.prefixIn D (i.val + 1) := prefixIn_mono_qfactor H D (Nat.le_succ i.val) v.property have h := congrFun hsucc ⟨v.val, hvsucc⟩ simpa [pairMap, valuesProjection] using h · ext v have hvnode : v.val = (H.nodesAt D i).val := by exact Finset.mem_singleton.mp v.property have hvsucc : v.val ∈ H.prefixIn D (i.val + 1) := by rw [hvnode, nodesAt_mem_prefixIn_iff_qfactor H D (i.val + 1) i] exact Nat.lt_succ_self i.val have h := congrFun hsucc ⟨v.val, hvsucc⟩ simpa [pairMap, valuesProjection] using h rw [MeasureTheory.Measure.map_apply ((measurable_valuesProjection (H.prefixIn_subset D i.val)).prod (measurable_valuesProjection hNodeD)) (MeasurableSet.singleton _), MeasureTheory.Measure.map_apply (measurable_valuesProjection (H.prefixIn_subset D (i.val + 1))) (MeasurableSet.singleton _), hsets]
    Causalean.SCM.ID.prefix_pair_singleton_mass_eq_succ_prefix_mass · Causalean/SCM/ID/Density/QFactor.lean:1224
  • tianPrefixStepDensity_eq_prefix_mass_ratio lemma — When the preceding prefix has nonzero singleton mass, the one-step Tian density is the ratio of the successive prefix singleton masses, divided by the singleton reference mass of the added variable.
    ∀ n, Fintype (Ω n)
    H :
    D :
    μ :
    href :
    ∀ (k : ℕ) (hk : k < D.card),
    StandardBorelSpace (ValuesOn ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
    ∀ (k : ℕ) (hk : k < D.card),
    Nonempty (ValuesOn ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
    i :
    Fin D.card
    x :
    hprefix0 :
    (μ.map (valuesProjection (H.prefixIn_subset D i.val))) ({valuesProjection (H.prefixIn_subset D i.val) x} : Set (ValuesOn (H.prefixIn D i.val) (swigΩ Ω)))
    ≠ 0
    tianPrefixStepDensity H D μ ref i x
    = ((μ.map (valuesProjection (H.prefixIn_subset D (i.val + 1)))) ({valuesProjection (H.prefixIn_subset D (i.val + 1)) x} : Set (ValuesOn (H.prefixIn D (i.val + 1)) (swigΩ Ω))) / (μ.map (valuesProjection (H.prefixIn_subset D i.val))) ({valuesProjection (H.prefixIn_subset D i.val) x} : Set (ValuesOn (H.prefixIn D i.val) (swigΩ Ω)))) / jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) x} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω)))
    Proof (Lean source)
    lemma tianPrefixStepDensity_eq_prefix_mass_ratio [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (H : SWIGGraph N) (D : Finset (SWIGNode N)) (μ : Measure (ValuesOn D (swigΩ Ω))) (ref : ReferenceMeasures Ω) (href : ReferenceFaithful ref) [IsFiniteMeasure μ] [∀ (k : ℕ) (hk : k < D.card), StandardBorelSpace (ValuesOn ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (k : ℕ) (hk : k < D.card), Nonempty (ValuesOn ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] (i : Fin D.card) (x : ValuesOn D (swigΩ Ω)) (hprefix0 : (μ.map (valuesProjection (H.prefixIn_subset D i.val))) ({valuesProjection (H.prefixIn_subset D i.val) x} : Set (ValuesOn (H.prefixIn D i.val) (swigΩ Ω))) ≠ 0) : tianPrefixStepDensity H D μ ref i x = ((μ.map (valuesProjection (H.prefixIn_subset D (i.val + 1)))) ({valuesProjection (H.prefixIn_subset D (i.val + 1)) x} : Set (ValuesOn (H.prefixIn D (i.val + 1)) (swigΩ Ω))) / (μ.map (valuesProjection (H.prefixIn_subset D i.val))) ({valuesProjection (H.prefixIn_subset D i.val) x} : Set (ValuesOn (H.prefixIn D i.val) (swigΩ Ω)))) / jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property) x} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) := by classical let hNodeD : ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ⊆ D := by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D i).property let nodeMap : ValuesOn D (swigΩ Ω) → ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω) := valuesProjection hNodeD let prefixMap : ValuesOn D (swigΩ Ω) → ValuesOn (H.prefixIn D i.val) (swigΩ Ω) := valuesProjection (H.prefixIn_subset D i.val) have hden0 : jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({nodeMap x} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) ≠ 0 := jointRef_singleton_ne_zero ref href _ (nodeMap x) have hdentop : jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({nodeMap x} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) ≠ ∞ := by exact ne_of_lt (MeasureTheory.measure_lt_top (jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N))) _) have hcond : (condDistrib nodeMap prefixMap μ (prefixMap x)) ({nodeMap x} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω))) = (μ.map (valuesProjection (H.prefixIn_subset D (i.val + 1)))) ({valuesProjection (H.prefixIn_subset D (i.val + 1)) x} : Set (ValuesOn (H.prefixIn D (i.val + 1)) (swigΩ Ω))) / (μ.map prefixMap) ({prefixMap x} : Set (ValuesOn (H.prefixIn D i.val) (swigΩ Ω))) := by rw [condDistrib_singleton_mass_of_ne_zero (μ := μ) (Y := nodeMap) (Z := prefixMap) (measurable_valuesProjection hNodeD) (prefixMap x) (nodeMap x) hprefix0] rw [prefix_pair_singleton_mass_eq_succ_prefix_mass H D μ i x] unfold tianPrefixStepDensity rw [rnDeriv_singleton_eq_div _ _ (absolutelyContinuous_jointRef_of_faithful ref href ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (condDistrib nodeMap prefixMap μ (prefixMap x))) (nodeMap x) hden0 hdentop] simpa [nodeMap, prefixMap, hNodeD] using congrArg (fun a => a / jointRef ref ({(H.nodesAt D i).val} : Finset (SWIGNode N)) ({nodeMap x} : Set (ValuesOn ({(H.nodesAt D i).val} : Finset (SWIGNode N)) (swigΩ Ω)))) hcond
    Causalean.SCM.ID.tianPrefixStepDensity_eq_prefix_mass_ratio · Causalean/SCM/ID/Density/QFactor.lean:1324
  • valuesProjection_extend_eq_of_subset lemma — If an extension preserves all values on a larger observed set, then restricting the extension to any subset gives the same values as restricting the original assignment directly.
    M :
    SCM N Ω
    D S :
    hDobs :
    D ⊆ M.observed
    hSD :
    S ⊆ D
    hSobs :
    S ⊆ M.observed
    extend :
    ValuesOn D (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω)
    hExtend :
    ∀ xD, valuesProjection hDobs (extend xD) = xD
    xD :
    valuesProjection hSobs (extend xD) = valuesProjection hSD xD
    Proof (Lean source)
    lemma valuesProjection_extend_eq_of_subset (M : SCM N Ω) {D S : Finset (SWIGNode N)} (hDobs : D ⊆ M.observed) (hSD : S ⊆ D) (hSobs : S ⊆ M.observed) (extend : ValuesOn D (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω)) (hExtend : ∀ xD, valuesProjection hDobs (extend xD) = xD) (xD : ValuesOn D (swigΩ Ω)) : valuesProjection hSobs (extend xD) = valuesProjection hSD xD := by ext v have h := congrFun (hExtend xD) ⟨v.val, hSD v.property⟩ simpa [valuesProjection] using h
    Causalean.SCM.ID.valuesProjection_extend_eq_of_subset · Causalean/SCM/ID/Density/QFactor.lean:1426
Tian­Mass­Bridge 1 core · 0 supporting This file connects the Tian prefix-density construction to finite point-mass ratios. ★ tianPrefixStepDensityInPrefix_eq_mass_ratio

Tian density point-mass bridges

This file connects the Tian prefix-density construction to finite point-mass ratios. Its public bridge theorem tianPrefixStepDensityInPrefix_eq_mass_ratio says that, on a measurable singleton with nonzero finite reference mass, a Tian one-step Radon--Nikodym density is exactly the conditional singleton mass divided by the corresponding singleton mass of the product reference.

The result is used by the discrete ID soundness lane to translate the measure-theoretic density factorization into the point-mass formulas consumed by finite conditional-mass proofs.

theorem tianPrefixStepDensityInPrefix_eq_mass_ratio reviewed
Causalean.SCM.ID

Fix a step index i earlier than the prefix length k that also lies within the node domain D. Provided the conditional distribution of the i-th coordinate given the shorter prefix is absolutely continuous with respect to the reference measure on that coordinate, and the reference-measure mass of the singleton value at that coordinate is nonzero and finite, then the Tian prefix-step density at index i equals the prefix conditional singleton mass divided by the corresponding singleton mass of the product reference measure.

Formal statement
H :
D :
μ :
∀ (j : ℕ) (hj : j < D.card),
StandardBorelSpace (ValuesOn ({(H.nodesAt D ⟨j, hj⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
∀ (j : ℕ) (hj : j < D.card),
Nonempty (ValuesOn ({(H.nodesAt D ⟨j, hj⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
k i :
hi :
i < k
hcard :
i < D.card
MeasurableSingletonClass (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))
z :
ValuesOn (H.prefixIn D k) (swigΩ Ω)
hac :
(condDistrib (valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D ⟨i, hcard⟩).property)) (valuesProjection (H.prefixIn_subset D i)) μ) (valuesProjection (prefixIn_mono H D (le_of_lt hi)) z) ≪ jointRef ref ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N))
href0 :
jointRef ref ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ H.prefixIn D k from by intro v hv rw [mem_singleton] at hv subst hv rw [nodesAt_mem_prefixIn_iff H D k ⟨i, hcard⟩] exact hi) z} : Set (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω)))
≠ 0
hreftop :
jointRef ref ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ H.prefixIn D k from by intro v hv rw [mem_singleton] at hv subst hv rw [nodesAt_mem_prefixIn_iff H D k ⟨i, hcard⟩] exact hi) z} : Set (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω)))
≠ ∞
= (condDistrib (valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D ⟨i, hcard⟩).property)) (valuesProjection (H.prefixIn_subset D i)) μ) (valuesProjection (prefixIn_mono H D (le_of_lt hi)) z) ({valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ H.prefixIn D k from by intro v hv rw [mem_singleton] at hv subst hv rw [nodesAt_mem_prefixIn_iff H D k ⟨i, hcard⟩] exact hi) z} : Set (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))) / jointRef ref ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ H.prefixIn D k from by intro v hv rw [mem_singleton] at hv subst hv rw [nodesAt_mem_prefixIn_iff H D k ⟨i, hcard⟩] exact hi) z} : Set (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω)))
Proof (Lean source)
theorem tianPrefixStepDensityInPrefix_eq_mass_ratio (H : SWIGGraph N) (D : Finset (SWIGNode N)) (μ : Measure (ValuesOn D (swigΩ Ω))) (ref : ReferenceMeasures Ω) [IsFiniteMeasure μ] [∀ (j : ℕ) (hj : j < D.card), StandardBorelSpace (ValuesOn ({(H.nodesAt D ⟨j, hj⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (j : ℕ) (hj : j < D.card), Nonempty (ValuesOn ({(H.nodesAt D ⟨j, hj⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] (k i : ℕ) (hi : i < k) (hcard : i < D.card) [MeasurableSingletonClass (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] (z : ValuesOn (H.prefixIn D k) (swigΩ Ω)) (hac : (condDistrib (valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D ⟨i, hcard⟩).property)) (valuesProjection (H.prefixIn_subset D i)) μ) (valuesProjection (prefixIn_mono H D (le_of_lt hi)) z) ≪ jointRef ref ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N))) (href0 : jointRef ref ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ H.prefixIn D k from by intro v hv rw [mem_singleton] at hv subst hv rw [nodesAt_mem_prefixIn_iff H D k ⟨i, hcard⟩] exact hi) z} : Set (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))) ≠ 0) (hreftop : jointRef ref ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ H.prefixIn D k from by intro v hv rw [mem_singleton] at hv subst hv rw [nodesAt_mem_prefixIn_iff H D k ⟨i, hcard⟩] exact hi) z} : Set (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))) ≠ ∞) : tianPrefixStepDensityInPrefix H D μ ref k z i = (condDistrib (valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D ⟨i, hcard⟩).property)) (valuesProjection (H.prefixIn_subset D i)) μ) (valuesProjection (prefixIn_mono H D (le_of_lt hi)) z) ({valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ H.prefixIn D k from by intro v hv rw [mem_singleton] at hv subst hv rw [nodesAt_mem_prefixIn_iff H D k ⟨i, hcard⟩] exact hi) z} : Set (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))) / jointRef ref ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ({valuesProjection (show ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) ⊆ H.prefixIn D k from by intro v hv rw [mem_singleton] at hv subst hv rw [nodesAt_mem_prefixIn_iff H D k ⟨i, hcard⟩] exact hi) z} : Set (ValuesOn ({(H.nodesAt D ⟨i, hcard⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))) := by unfold tianPrefixStepDensityInPrefix simp [hi, hcard, rnDeriv_singleton_eq_div _ _ hac _ href0 hreftop]