SCM.ID.Density

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

Chain­Rule­Density 7 core · 18 supporting · 2 submodules The joint density of the observed variables of a structural causal model, with respect to a product of σ-finite reference measures, factorizes along the topological order as the product of one-node conditional densities QMass 8 core · 19 supporting · 4 submodules For a structural causal model with finitely many values per variable, the local q-mass of a set S of observed nodes at an observed assignment is the probability, under the product law of the latent noises, that every str Mech­CFactor 8 core · 15 supporting · 3 submodules Tian's c-factor Q[S] of a set S of observed variables, defined through the causal mechanisms: the density on S of the law obtained by intervening on every observed variable outside S. QFactor 12 core · 26 supporting · 5 submodules The density-level form of Tian's c-component (district) factorization.
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★ 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 u_1
shared
Ω :
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:43
def jointRef reviewed
Causalean.SCM

For a node population with measurable value spaces, a reference-measure family, and a finite node set, the joint reference measure is the finite product of the reference measures assigned to the nodes in that set.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
I :
jointRef ref I :
pi (fun i : {i // i ∈ I} => ref.μ i.val)
def DominatedObs reviewed
Causalean.SCM

For a finite node population with measurable value spaces, a structural causal model, and a reference-measure family, observational domination holds exactly when, for every assignment of fixed-node values, the model's observational law is absolutely continuous with respect to the joint reference measure on its observed nodes.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
M :
SCM N Ω
s :
M.FixedValues
DominatedObs M ref :
Prop
M.obsKernel s ≪ jointRef ref M.observed
def obsDensity reviewed
Causalean.SCM

For a finite node population with measurable value spaces, a structural causal model, a reference-measure family, and fixed-node values, the joint observational density is the Radon--Nikodym derivative of the model's observational law at those fixed-node values with respect to the joint reference measure on the observed nodes.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
M :
SCM N Ω
s :
M.FixedValues
obsDensity M ref s :
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
N :
Type u_1
N → Type u_2
shared
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
N :
Type u_1
N → Type u_2
shared
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)
  • instSigmaFiniteJointRef instance — For a node population with measurable value spaces, a reference-measure family, and a finite set of nodes, the σ-finiteness structure for their joint reference measure asserts that the finite product of the selected coordinate reference measures is σ-finite.
    N :
    Type u_1
    N → Type u_2
    shared
    I :
    instSigmaFiniteJointRef ref I :
    by unfold jointRef infer_instance
    Causalean.SCM.instSigmaFiniteJointRef · Causalean/SCM/ID/Density/ReferenceMeasure.lean:67
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

For any node set with measurable node-value spaces and a family of reference measures, reference faithfulness means that every value at every random or fixed node has nonzero mass under that node's reference measure.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
v :
x :
swigΩ Ω v
ReferenceFaithful ref :
Prop
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
N :
Type u_1
N → Type u_2
shared
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)
@[fun_prop] 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:139
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.Graph.SWIGGraph

For a finite collection of distinguishable base-variable labels and a SWIG graph, the topological linear order orders its nodes by their positions in the graph's topological ordering.

Definition (Lean source)
N :
Type u_1
shared
G :
topoLinearOrder G :
LinearOrder.lift' G.dag.topoOrder G.dag.topoOrder_injective
Causalean.Graph.SWIGGraph.topoLinearOrder · Causalean/SCM/ID/Density/IdentifyMass.lean:42 · uses SWIGGraph , SWIGNode
def nodesAt reviewed
Causalean.Graph.SWIGGraph

For a finite collection of distinguishable base-variable labels, a SWIG graph, a finite set of graph nodes, and a position from zero through one less than the set's size, the node-at-position selector returns the node occupying that position when the set is sorted in graph topological order.

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

For a finite collection of distinguishable base-variable labels, a SWIG graph, a finite set of graph nodes, and a node belonging to that set, the node-position selector returns that node's position when the set is sorted in graph topological order.

Definition (Lean source)
N :
Type u_1
shared
G :
D :
v :
{v // v ∈ D}
nodeIndex G D v :
Fin D.card
by classical letI := G.topoLinearOrder exact (D.orderIsoOfFin rfl).symm v
Causalean.Graph.SWIGGraph.nodeIndex · Causalean/SCM/ID/Density/IdentifyMass.lean:53 · uses SWIGGraph , SWIGNode
def prefixIn reviewed
Causalean.Graph.SWIGGraph

For a finite collection of distinguishable base-variable labels, a SWIG graph, a finite set of graph nodes, and a nonnegative integer, the topological prefix consists of the nodes in that set whose topological positions are strictly less than nn.

Definition (Lean source)
N :
Type u_1
shared
G :
D :
n :
ℕ
prefixIn G D n :
D.filter (fun v => if h : v ∈ D then (G.nodeIndex D ⟨v, h⟩).val < n else False)
Causalean.Graph.SWIGGraph.prefixIn · Causalean/SCM/ID/Density/IdentifyMass.lean:60 · uses SWIGGraph , SWIGNode
def marginalizeOn reviewed
Causalean.SCM

For an ambient set of graph nodes, a subset of coordinates to eliminate that is contained in the ambient set, and a nonnegative extended-real mass function on assignments to the ambient set, the marginalized mass function maps each ambient assignment to the sum of the mass function over all assignments on the eliminated coordinates, replacing those coordinates in the evaluation point.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
∀ n, Fintype (Ω n)
O W :
hW :
W ⊆ O
q :
marginalizeOn O W hW q :
fun x => ∑ y : ValuesOn W (swigΩ Ω), q (overrideOn x y)
def extractDistrict reviewed
Causalean.SCM

For an ambient node set, a SWIG graph, a node set, a district node set, the condition that the node set is contained in the ambient set, and a nonnegative extended-real mass function on ambient assignments, the district factor maps each ambient assignment to the product, over the nodes of the district in graph topological order, of the ratio of the two adjacent prefix marginals obtained by summing out the remaining nodes of AA.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
∀ n, Fintype (Ω n)
O :
G' :
A C' :
hA :
A ⊆ O
q :
extractDistrict O G' A C' hA q :
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

For an ambient node set and a SWIG graph, the mass-level IDENTIFY recursion maps every target node set, district node set, proof that the target set is contained in the ambient set, and nonnegative extended-real mass function on ambient assignments to a mass function on ambient assignments. It first forms the induced ancestral set and its containment proof, then returns the marginal eliminating the target coordinates outside the district when that ancestral set equals the district, returns the original mass function when it equals the target set, and otherwise recurses after extracting the containing district factor from the appropriate marginal.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
∀ n, Fintype (Ω n)
O :
G :
T C :
hT :
T ⊆ O
q :
identifyMassRec O G T C hT q :
| 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 :
Type u_1
N → Type u_2
shared
∀ 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 :
Type u_1
N → Type u_2
shared
∀ 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 :
Type u_1
N → Type u_2
shared
∀ 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

For a finite collection of distinguishable node labels with measurable value spaces, a structural causal model, a full assignment of its observed node values, a natural-number bound nn, an index m<nm<n, and evidence that this index is within the observed topological order, the previous-value reader returns from the assignment the value of the mm-th observed node in that order.

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

For a finite collection of distinguishable node labels with measurable value spaces, a structural causal model and a candidate node set, the latent block is the set of all unobserved nodes having a directed edge into at least one member of that set.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
M :
SCM N Ω
C :
latentBlock M C :
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
N :
Type u_1
N → Type u_2
shared
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

For a finite collection of distinguishable node labels with measurable value spaces, a structural causal model, a fixed-node assignment, an observed-node assignment, an observed node with evidence that it is observed, and a latent-node assignment, local consistency at that node holds exactly when its structural function, is indexed by that node's canonical observed-order position and, fed the corresponding fixed, latent, and earlier observed parent values, equals its assigned observed value.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
M :
SCM N Ω
s :
M.FixedValues
x :
ValuesOn M.observed (swigΩ Ω)
v :
hv :
v ∈ M.observed
ℓ :
M.LatentValues
localConsistent M s x v hv ℓ :
Prop
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
N :
Type u_1
N → Type u_2
shared
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

For a finite collection of distinguishable node labels with measurable value spaces, a structural causal model and a finite node set, the observed-parent-closure condition holds exactly when every member of the set is observed and every observed parent of each member also belongs to the set.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
M :
SCM N Ω
P :
ObsParentClosed M P :
Prop
clause 1
P ⊆ M.observed
clause 2
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
N :
Type u_1
N → Type u_2
shared
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.
    N :
    Type u_1
    N → Type u_2
    shared
    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:79
  • latentBlock_pairwise_disjoint_fixSet_induce_components lemma — Do-model specialization of induced-component latent-block disjointness.
    N :
    Type u_1
    N → Type u_2
    shared
    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:113
  • localConsistent_depends_only_on_block lemma — Local consistency at v depends only on the latent block of v's c-component.
    N :
    Type u_1
    N → Type u_2
    shared
    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:146
  • observedAt_observedIndex_subtype lemma — Taking an observed node to its topological index and back recovers the same observed-node subtype value.
    N :
    Type u_1
    N → Type u_2
    shared
    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:210
  • prevFromObservedValues_apply_observed lemma — For a structural causal model and observed assignment, an observed parent that precedes the current node in topological order is read by the previous-value function as its value in the assignment.
    N :
    Type u_1
    N → Type u_2
    shared
    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:217
  • parentMap_prevFromObservedValues_eq_dispatch lemma — Given a finite structural causal model, fixed, observed, and latent assignments, an observed-node index, and one of that node's parents, the parent map built from preceding observed values returns the latent value for an unobserved parent, the fixed value for a fixed parent, and the observed value otherwise.
    N :
    Type u_1
    N → Type u_2
    shared
    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:241
  • localConsistent_iff_structFun_dispatch lemma — Given a finite structural causal model, fixed, observed, and latent assignments, and an observed node, local consistency at that node holds exactly when its structural function, supplied latent, fixed, or observed parent values as appropriate, equals its observed value.
    N :
    Type u_1
    N → Type u_2
    shared
    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:397
  • 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.
    N :
    Type u_1
    N → Type u_2
    shared
    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:448
  • 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.
    N :
    Type u_1
    N → Type u_2
    shared
    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:506
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

For a finite node set with measurable node-value spaces, a structural causal model, a family of reference measures, an assignment to the model's fixed nodes, and a set of SWIG nodes, assuming every observational law is finite, every singleton observed-node value space is standard Borel and nonempty, and every fixed-node space together with every observed-node prefix space satisfies the stated countability condition, the per-c-component density factor maps a full observed-node assignment to the product of its one-node conditional density factors over precisely those observed nodes whose c-component is the given set.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
M :
SCM N Ω
s :
M.FixedValues
C :
∀ 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Ω Ω))
cComponentDensityFactor M ref s C :
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
N :
Type u_1
N → Type u_2
shared
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.
    N :
    Type u_1
    N → Type u_2
    shared
    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:103
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

For a collection of nodes with a measurable outcome space for each node, a finite set of target coordinates, a finite set of replacement coordinates, an assignment on the target coordinates, and an assignment on the replacement coordinates, the overridden target-coordinate assignment uses the replacement assignment at every target coordinate that is also a replacement coordinate, and otherwise uses the original target-coordinate assignment.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
x :
y :
overrideOn x y :
fun i => if h : i.val ∈ W then y ⟨i.val, h⟩ else x i
def unionSumEquiv reviewed
Causalean.SCM

For a collection of nodes, two finite sets of nodes, and their disjointness, the index equivalence between their tagged sum and their union maps each tagged node to that same node regarded as a member of the union.

Definition (Lean source)
N :
Type u_1
shared
hDisj :
unionSumEquiv hDisj :
({a // a ∈ A} ⊕ {b // b ∈ B}) ≃ {i // i ∈ A ∪ B}
clause 1
toFun := elim (fun a => ⟨a.val, mem_union_left _ a.property⟩) (fun b => ⟨b.val, mem_union_right _ b.property⟩)
clause 2
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⟩
clause 3
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]
clause 4
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
N :
Type u_1
N → Type u_2
shared
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)
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

For any node set with measurable node-value spaces, provided every random or fixed node has a countable value space and every base-node singleton is measurable, the counting reference family assigns counting measure to every random and fixed node coordinate and records that each such measure is σ-finite.

Definition (Lean source)
N :
Type u_1
N → Type u_2
shared
∀ sn, Countable (swigΩ Ω sn)
countingRef :
clause 1
μ := fun _ => count
clause 2
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
N :
Type u_1
N → Type u_2
shared
∀ 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
N :
Type u_1
N → Type u_2
shared
∀ 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
N :
Type u_1
N → Type u_2
shared
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
N :
Type u_1
N → Type u_2
shared
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:167 · 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
N :
Type u_1
N → Type u_2
shared
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
N :
Type u_1
N → Type u_2
shared
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)
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
N :
Type u_1
N → Type u_2
shared
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 [Finset.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 [Finset.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 [Finset.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 [Finset.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 [Finset.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 [Finset.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 [Finset.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 [Finset.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 [Finset.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 [Finset.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 [Finset.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 [Finset.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]