SCM.ID.Graphical­Thms

Graphical identification theorems: c-component factorization and related structure results.

Do­GFormula 10 core · 15 supporting This file builds the graph-side objects over which the truncated g-formula for the do-law Y-marginal is assembled. ★ subset_fixObservedAncestralSet

Geometric foundation of the do-law g-formula (Tian, fixing route)

This file builds the graph-side objects over which the truncated g-formula for the do-law Y-marginal is assembled. Intervening on a treatment set X mutilates the SWIG graph to G_X = (M.fixSet X).toSWIGGraph (the monolithic split splitMono X). Tian's identification of P(Y ∣ do(X)) only involves the part of the do-law lying on the ancestors of the query in the mutilated graph, and factorizes that part over the c-components of the induced ancestral subgraph.

* fixAncestralSet — the ancestors of Y (together with Y) in the mutilated graph G_X; the support of the relevant do-law marginal. * fixTruncCComponentSet — the c-components of G_X induced on that ancestral set; the index set of the truncated product.

These are exactly the objects the success certificate idSucceeds ranges over (∀ S ∈ (G_X.induce Ystar).cComponentSet, cFactorReachable G (containingCComponent G S) S), named here for use in the measure-theoretic g-formula. The factorization itself — the do-law Y-marginal equals the product over fixTruncCComponentSet of the recovered full-district c-factors (each a functional of obsDensity via district_id, with the truncation realized by the fixing operation M.fixSet Wn) — is developed by the downstream Tian density and ID soundness layers.

def interventionValid reviewed
Causalean.SCM.ID

The graph-level precondition that the SWIG split by X is valid.

Definition (Lean source)
def interventionValid (X : Finset N) (G : SWIGGraph N) : Prop := (∀ D ∈ X, SWIGNode.random D ∈ G.observed) ∧ (∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed)
Causalean.SCM.ID.interventionValid · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:45 · uses SWIGGraph
def containingCComponent reviewed
Causalean.SCM.ID

The c-component of G containing the finite set S, seeded by an arbitrary member of S; empty S has no containing component and returns .

Definition (Lean source)
noncomputable def containingCComponent (G : SWIGGraph N) (S : Finset (SWIGNode N)) : Finset (SWIGNode N) := if hS : S.Nonempty then G.cComponentOf hS.choose else ∅
Causalean.SCM.ID.containingCComponent · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:50 · uses SWIGGraph , SWIGNode
def cFactorReachable reviewed
Causalean.SCM.ID

Structural c-factor reachability, no-fixing approximation.

Definition (Lean source)
noncomputable def cFactorReachable (G : SWIGGraph N) (T S : Finset (SWIGNode N)) : Prop := S.Nonempty ∧ S ⊆ T ∧ S ∈ G.cComponentSet
def idSucceeds reviewed
Causalean.SCM.ID

Structural success certificate for the no-additional-fixing (full-district) fragment of the Tian–Shpitser ID algorithm.

Definition (Lean source)
noncomputable def idSucceeds (X : Finset N) (Y : Finset (SWIGNode N)) (G : SWIGGraph N) : Prop := ∃ hX : interventionValid X G, let GX := G.splitMono X hX.1 hX.2 let Ystar := GX.dag.ancestralSet Y Y ⊆ G.observed ∧ (∀ d ∈ X, SWIGNode.random d ∉ Y) ∧ ∀ S ∈ (GX.induce Ystar).cComponentSet, cFactorReachable G (containingCComponent G S) S
def fixAncestralSet reviewed
Causalean.SCM.ID

The post-intervention ancestral set of the query. In the graph obtained by intervening on the treatment set X, this is the set consisting of the query nodes Y together with all of their ancestors. It is the support of the part of the do-law that Tian's algorithm identifies: nodes outside it do not influence P(Y ∣ do(X)).

Definition (Lean source)
noncomputable def fixAncestralSet (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)) : Finset (SWIGNode N) := (M.fixSet X hObs hFix).toSWIGGraph.dag.ancestralSet Y
Causalean.SCM.ID.fixAncestralSet · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:92 · uses SCM , SWIGNode
def fixTruncCComponentSet reviewed
Causalean.SCM.ID

The truncated c-component index set. The c-components of the mutilated graph G_X after inducing on the post-intervention ancestral set of the query. This is the index set of the truncated product in the do-law g-formula: the do-law Y-marginal factorizes into one c-factor per element of this set.

Definition (Lean source)
noncomputable def fixTruncCComponentSet (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)) : Finset (Finset (SWIGNode N)) := ((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).cComponentSet
Causalean.SCM.ID.fixTruncCComponentSet · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:104 · uses SCM , SWIGNode
def fixObservedAncestralSet reviewed
Causalean.SCM.ID

The observed part of the post-intervention ancestral support of the query. The post-intervention ancestral set An_{G_X}(Y) is a SWIG-node set and may include fixed intervention nodes, but the observational law is carried only on observed coordinates, so the measure-theoretic support is its intersection with the observed nodes.

Definition (Lean source)
noncomputable def fixObservedAncestralSet (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)) : Finset (SWIGNode N) := fixAncestralSet M X hObs hFix Y ∩ (M.fixSet X hObs hFix).observed
Causalean.SCM.ID.fixObservedAncestralSet · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:125 · uses SCM , SWIGNode
def pinnedExtend reviewed
Causalean.SCM.ID

Extend an assignment on the post-intervention observed ancestral support to the original observed coordinates, pinning intervened random coordinates to the fixed values of the do-slice.

Definition (Lean source)
noncomputable def pinnedExtend [∀ n, Nonempty (Ω 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)) (sDo : (M.fixSet X hObs hFix).FixedValues) : ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω) → ValuesOn M.observed (swigΩ Ω) := fun xD v => 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 if hvD : SWIGNode.random d ∈ fixObservedAncestralSet M X hObs hFix Y then xD ⟨SWIGNode.random d, hvD⟩ else Classical.arbitrary _ | SWIGNode.fixed d => if hvD : SWIGNode.fixed d ∈ fixObservedAncestralSet M X hObs hFix Y then xD ⟨SWIGNode.fixed d, hvD⟩ else Classical.arbitrary _
def doObsKernelAncestralMarginal reviewed
Causalean.SCM.ID

The post-intervention marginal on the observed ancestors of the query: the do-observational law pushed forward to the observed part of Ystar = An_{G_X}(Y). This is the object the truncated g-formula identifies first; the requested Y-marginal is a further projection of it along Y ⊆ Ystar.

Definition (Lean source)
noncomputable def doObsKernelAncestralMarginal (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)) : Kernel (M.fixSet X hObs hFix).FixedValues (ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω)) := (M.fixSet X hObs hFix).obsKernel.map (valuesProjection inter_subset_right)
theorem subset_fixObservedAncestralSet reviewed
Causalean.SCM.ID

For a valid intervention set X (observed, not already fixed) and an outcome set Y contained in the observed nodes, Y is contained in its own post-intervention observed-ancestral closure: it lies in the post-intervention ancestral set (subset_fixAncestralSet) and in the observed nodes.

Formal statement
M :
SCM N Ω
X :
hObs :
∀ D ∈ X, SWIGNode.random D ∈ M.observed
hFix :
∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
Y :
hY :
Y ⊆ M.observed
Y ⊆ fixObservedAncestralSet M X hObs hFix Y
Proof (Lean source)
theorem subset_fixObservedAncestralSet (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)) (hY : Y ⊆ M.observed) : Y ⊆ fixObservedAncestralSet M X hObs hFix Y := Finset.subset_inter (subset_fixAncestralSet M X hObs hFix Y) ((SCM.fixSet_observed M X hObs hFix).symm ▸ hY)
15 supporting declarations (lemmas, instances)
  • subset_fixAncestralSet theorem — The post-intervention ancestral set contains the query.
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    Y :
    Y ⊆ fixAncestralSet M X hObs hFix Y
    Proof (Lean source)
    theorem subset_fixAncestralSet (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)) : Y ⊆ fixAncestralSet M X hObs hFix Y := (M.fixSet X hObs hFix).toSWIGGraph.dag.subset_ancestralSet Y
    Causalean.SCM.ID.subset_fixAncestralSet · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:116
  • splitMono_edge_from_unobserved_iff lemma — Under a valid monolithic intervention split, a directed edge from an unobserved node exists exactly when that edge existed in the original graph.
    G :
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ G.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed
    u v :
    hu :
    u ∈ G.unobserved
    (G.splitMono X hObs hFix).dag.edge u v ↔ G.dag.edge u v
    Proof (Lean source)
    lemma splitMono_edge_from_unobserved_iff (G : SWIGGraph N) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ G.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed) {u v : SWIGNode N} (hu : u ∈ G.unobserved) : (G.splitMono X hObs hFix).dag.edge u v ↔ G.dag.edge u v := by obtain ⟨d, rfl⟩ := G.unobserved_is_random u hu have hdX : d ∉ X := by intro hd exact (Finset.disjoint_left.mp G.obs_unobs_disjoint (hObs d hd)) hu simp [SWIGGraph.splitMono, SWIGGraph.splitMonoDAG, SWIGGraph.splitMonoEdgeRel, hdX]
    Causalean.SCM.ID.splitMono_edge_from_unobserved_iff · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:166
  • splitMono_directlyConfounded_iff lemma — Under a valid monolithic intervention split, two nodes are directly confounded exactly when they were directly confounded in the original graph.
    G :
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ G.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed
    v₁ v₂ :
    (G.splitMono X hObs hFix).directlyConfounded v₁ v₂ ↔ G.directlyConfounded v₁ v₂
    Proof (Lean source)
    lemma splitMono_directlyConfounded_iff (G : SWIGGraph N) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ G.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed) (v₁ v₂ : SWIGNode N) : (G.splitMono X hObs hFix).directlyConfounded v₁ v₂ ↔ G.directlyConfounded v₁ v₂ := by constructor · rintro ⟨hne, u, hu, hu₁, hu₂⟩ exact ⟨hne, u, hu, (splitMono_edge_from_unobserved_iff G X hObs hFix hu).mp hu₁, (splitMono_edge_from_unobserved_iff G X hObs hFix hu).mp hu₂⟩ · rintro ⟨hne, u, hu, hu₁, hu₂⟩ exact ⟨hne, u, hu, (splitMono_edge_from_unobserved_iff G X hObs hFix hu).mpr hu₁, (splitMono_edge_from_unobserved_iff G X hObs hFix hu).mpr hu₂⟩
    Causalean.SCM.ID.splitMono_directlyConfounded_iff · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:181
  • splitMono_bidirectedReachable_iff lemma — A valid monolithic intervention split leaves bidirected reachability between any two SWIG nodes unchanged.
    G :
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ G.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed
    v w :
    (G.splitMono X hObs hFix).bidirectedReachable v w ↔ G.bidirectedReachable v w
    Proof (Lean source)
    lemma splitMono_bidirectedReachable_iff (G : SWIGGraph N) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ G.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed) (v w : SWIGNode N) : (G.splitMono X hObs hFix).bidirectedReachable v w ↔ G.bidirectedReachable v w := by constructor · intro h induction h with | refl hv => exact SWIGGraph.bidirectedReachable.refl hv | step hreach hconf ih => exact SWIGGraph.bidirectedReachable.step ih ((splitMono_directlyConfounded_iff G X hObs hFix _ _).mp hconf) · intro h induction h with | refl hv => exact SWIGGraph.bidirectedReachable.refl hv | step hreach hconf ih => exact SWIGGraph.bidirectedReachable.step ih ((splitMono_directlyConfounded_iff G X hObs hFix _ _).mpr hconf)
    Causalean.SCM.ID.splitMono_bidirectedReachable_iff · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:200
  • splitMono_cComponentOf_eq lemma — Under a valid monolithic intervention split, the bidirected component containing any SWIG node is the same as it was before intervention.
    G :
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ G.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed
    v :
    (G.splitMono X hObs hFix).cComponentOf v = G.cComponentOf v
    Proof (Lean source)
    lemma splitMono_cComponentOf_eq (G : SWIGGraph N) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ G.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed) (v : SWIGNode N) : (G.splitMono X hObs hFix).cComponentOf v = G.cComponentOf v := by by_cases hv : v ∈ G.observed · apply Finset.Subset.antisymm · intro w hw rw [G.mem_cComponentOf_iff_reachable hv] exact (splitMono_bidirectedReachable_iff G X hObs hFix v w).mp (((G.splitMono X hObs hFix).mem_cComponentOf_iff_reachable hv).mp hw) · intro w hw rw [(G.splitMono X hObs hFix).mem_cComponentOf_iff_reachable hv] exact (splitMono_bidirectedReachable_iff G X hObs hFix v w).mpr ((G.mem_cComponentOf_iff_reachable hv).mp hw) · simp [SWIGGraph.cComponentOf, SWIGGraph.bidirectedBFS, hv]
    Causalean.SCM.ID.splitMono_cComponentOf_eq · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:223
  • splitMono_cComponentSet_eq lemma — Splitting a graph under a valid monolithic intervention leaves its partition into bidirected connected components unchanged.
    G :
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ G.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed
    (G.splitMono X hObs hFix).cComponentSet = G.cComponentSet
    Proof (Lean source)
    lemma splitMono_cComponentSet_eq (G : SWIGGraph N) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ G.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed) : (G.splitMono X hObs hFix).cComponentSet = G.cComponentSet := by ext C simp [SWIGGraph.cComponentSet, splitMono_cComponentOf_eq G X hObs hFix]
    Causalean.SCM.ID.splitMono_cComponentSet_eq · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:243
  • splitMono_no_edge_from_intervened_random lemma — Under a valid monolithic intervention split, the random copy of an intervened variable has no outgoing directed edge.
    G :
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ G.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed
    d :
    N
    hd :
    d ∈ X
    v :
    ¬ (G.splitMono X hObs hFix).dag.edge (SWIGNode.random d) v
    Proof (Lean source)
    lemma splitMono_no_edge_from_intervened_random (G : SWIGGraph N) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ G.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed) {d : N} (hd : d ∈ X) (v : SWIGNode N) : ¬ (G.splitMono X hObs hFix).dag.edge (SWIGNode.random d) v := by simp [SWIGGraph.splitMono, SWIGGraph.splitMonoDAG, SWIGGraph.splitMonoEdgeRel, hd]
    Causalean.SCM.ID.splitMono_no_edge_from_intervened_random · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:253
  • splitMono_not_isAncestor_from_intervened_random lemma — After a valid monolithic intervention split, the random copy of an intervened variable is not an ancestor of any node.
    G :
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ G.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed
    d :
    N
    hd :
    d ∈ X
    v :
    ¬ (G.splitMono X hObs hFix).dag.isAncestor (SWIGNode.random d) v
    Proof (Lean source)
    lemma splitMono_not_isAncestor_from_intervened_random (G : SWIGGraph N) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ G.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ G.fixed) {d : N} (hd : d ∈ X) (v : SWIGNode N) : ¬ (G.splitMono X hObs hFix).dag.isAncestor (SWIGNode.random d) v := by intro h induction h with | edge he => exact splitMono_no_edge_from_intervened_random G X hObs hFix hd _ he | trans _ _ ih => exact ih
    Causalean.SCM.ID.splitMono_not_isAncestor_from_intervened_random · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:264
  • random_intervened_mem_fixAncestralSet_iff_mem_Y lemma — For an intervened variable, its random copy is a post-intervention ancestor of the query exactly when it is explicitly queried.
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    Y :
    d :
    N
    hd :
    d ∈ X
    SWIGNode.random d ∈ fixAncestralSet M X hObs hFix Y ↔ SWIGNode.random d ∈ Y
    Proof (Lean source)
    lemma random_intervened_mem_fixAncestralSet_iff_mem_Y (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)) {d : N} (hd : d ∈ X) : SWIGNode.random d ∈ fixAncestralSet M X hObs hFix Y ↔ SWIGNode.random d ∈ Y := by constructor · intro h unfold fixAncestralSet at h rcases Finset.mem_union.mp h with hY | hAnc · exact hY · simp only [DAG.ancestorsSet, mem_filter, Finset.mem_univ, true_and] at hAnc obtain ⟨v, hvY, hanc⟩ := hAnc have hno := splitMono_not_isAncestor_from_intervened_random (M.toSWIGGraph) X hObs hFix hd v have hno' : ¬ (M.fixSet X hObs hFix).toSWIGGraph.dag.isAncestor (SWIGNode.random d) v := by simpa [SCM.fixSet, SCM.fixMono] using hno exact elim (hno' hanc) · intro hY exact (M.fixSet X hObs hFix).toSWIGGraph.dag.subset_ancestralSet Y hY
    Causalean.SCM.ID.random_intervened_mem_fixAncestralSet_iff_mem_Y · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:277
  • pinnedExtend_projection_eq lemma — The pinned extension projects back to the ancestral assignment when natural intervened coordinates are excluded from the query.
    ∀ n, Nonempty (Ω n)
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    Y :
    sDo :
    (M.fixSet X hObs hFix).FixedValues
    hYX :
    ∀ D ∈ X, SWIGNode.random D ∉ Y
    ∀ xD,
    valuesProjection (show fixObservedAncestralSet M X hObs hFix Y ⊆ M.observed from inter_subset_right) (pinnedExtend M X hObs hFix Y sDo xD)
    = xD
    Proof (Lean source)
    lemma pinnedExtend_projection_eq [∀ n, Nonempty (Ω 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)) (sDo : (M.fixSet X hObs hFix).FixedValues) (hYX : ∀ D ∈ X, SWIGNode.random D ∉ Y) : ∀ xD, valuesProjection (show fixObservedAncestralSet M X hObs hFix Y ⊆ M.observed from inter_subset_right) (pinnedExtend M X hObs hFix Y sDo xD) = xD := by intro xD funext v rcases v with ⟨v, hv⟩ cases v with | random d => have hvD : SWIGNode.random d ∈ fixObservedAncestralSet M X hObs hFix Y := hv have hnotX : d ∉ X := by intro hd have hAnc : SWIGNode.random d ∈ fixAncestralSet M X hObs hFix Y := (Finset.mem_inter.mp hvD).1 have hYd : SWIGNode.random d ∈ Y := (random_intervened_mem_fixAncestralSet_iff_mem_Y M X hObs hFix Y hd).mp hAnc exact hYX d hd hYd simp [valuesProjection, pinnedExtend, hnotX, hvD] | fixed d => have hvD : SWIGNode.fixed d ∈ fixObservedAncestralSet M X hObs hFix Y := hv simp [valuesProjection, pinnedExtend, hvD]
    Causalean.SCM.ID.pinnedExtend_projection_eq · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:303
  • pinnedExtend_pin_eq lemma — The pinned extension reads intervened random coordinates from the matching fixed coordinate of the do-slice.
    ∀ n, Nonempty (Ω n)
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    Y :
    sDo :
    (M.fixSet X hObs hFix).FixedValues
    ∀ xD (D : N) (hD : D ∈ X),
    pinnedExtend M X hObs hFix Y sDo xD ⟨SWIGNode.random D, hObs D hD⟩
    = sDo ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩
    Proof (Lean source)
    lemma pinnedExtend_pin_eq [∀ n, Nonempty (Ω 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)) (sDo : (M.fixSet X hObs hFix).FixedValues) : ∀ xD (D : N) (hD : D ∈ X), pinnedExtend M X hObs hFix Y sDo xD ⟨SWIGNode.random D, hObs D hD⟩ = sDo ⟨SWIGNode.fixed D, mem_union_right _ (Finset.mem_image.mpr ⟨D, hD, rfl⟩)⟩ := by intro xD D hD simp [pinnedExtend, hD]
    Causalean.SCM.ID.pinnedExtend_pin_eq · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:336
  • fixSet_cComponentSet_eq lemma — Intervening does not change the full c-component partition.
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    (M.fixSet X hObs hFix).toSWIGGraph.cComponentSet = M.toSWIGGraph.cComponentSet
    Proof (Lean source)
    lemma fixSet_cComponentSet_eq (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) : (M.fixSet X hObs hFix).toSWIGGraph.cComponentSet = M.toSWIGGraph.cComponentSet := by simpa [SCM.fixSet, SCM.fixMono] using (splitMono_cComponentSet_eq (M.toSWIGGraph) X hObs hFix)
    Causalean.SCM.ID.fixSet_cComponentSet_eq · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:354
  • fixSet_cComponentSet_mem lemma — Membership in the full c-component partition transports across fixSet.
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    S :
    S ∈ (M.fixSet X hObs hFix).toSWIGGraph.cComponentSet ↔ S ∈ M.toSWIGGraph.cComponentSet
    Proof (Lean source)
    lemma fixSet_cComponentSet_mem (M : SCM N Ω) (X : Finset N) (hObs : ∀ D ∈ X, SWIGNode.random D ∈ M.observed) (hFix : ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed) (S : Finset (SWIGNode N)) : S ∈ (M.fixSet X hObs hFix).toSWIGGraph.cComponentSet ↔ S ∈ M.toSWIGGraph.cComponentSet := by rw [fixSet_cComponentSet_eq M X hObs hFix]
    Causalean.SCM.ID.fixSet_cComponentSet_mem · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:364
  • fixObservedAncestralSet_obsParent_closed lemma — The observed post-intervention ancestral support is closed under observed parents in the do-model.
    M :
    SCM N Ω
    X :
    hObs :
    ∀ D ∈ X, SWIGNode.random D ∈ M.observed
    hFix :
    ∀ D ∈ X, SWIGNode.fixed D ∉ M.fixed
    Y :
    (M.fixSet X hObs hFix).ObsParentClosed (fixObservedAncestralSet M X hObs hFix Y)
    Proof (Lean source)
    lemma fixObservedAncestralSet_obsParent_closed (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)) : (M.fixSet X hObs hFix).ObsParentClosed (fixObservedAncestralSet M X hObs hFix Y) := by refine ⟨Finset.inter_subset_right, ?_⟩ intro v hv w hw hEdge have hvAnc : v ∈ fixAncestralSet M X hObs hFix Y := (Finset.mem_inter.mp hv).1 have hwAnc : w ∈ fixAncestralSet M X hObs hFix Y := by unfold fixAncestralSet at hvAnc ⊢ exact DAG.mem_ancestralSet_of_edge_to_mem (M.fixSet X hObs hFix).toSWIGGraph.dag hEdge hvAnc exact Finset.mem_inter.mpr ⟨hwAnc, hw⟩
    Causalean.SCM.ID.fixObservedAncestralSet_obsParent_closed · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:374
  • instIsMarkovKernel_doObsKernelAncestralMarginal instance — The post-intervention ancestral marginal is a Markov kernel: it is the coordinate pushforward of the (Markov) do-observational kernel, so each slice is a probability measure.
    instance instIsMarkovKernel_doObsKernelAncestralMarginal (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)) : IsMarkovKernel (doObsKernelAncestralMarginal M X hObs hFix Y) := by unfold doObsKernelAncestralMarginal exact ProbabilityTheory.Kernel.IsMarkovKernel.map _ (measurable_valuesProjection inter_subset_right)
    Causalean.SCM.ID.instIsMarkovKernel_doObsKernelAncestralMarginal · Causalean/SCM/ID/GraphicalThms/DoGFormula.lean:406
Do­GFormula­Rec 5 core · 3 supporting The no-fixing certificate cFactorReachable (in DoGFormula) only handles the case where a required district is already a full c-component of the original graph. ★ cFactorReachable_base_toRec★ idSucceeds_toRec

The recursive IDENTIFY certificate (full Tian–Shpitser ID success)

The no-fixing certificate cFactorReachable (in DoGFormula) only handles the case where a required district is already a full c-component of the original graph. The full ID algorithm recovers a target c-factor Q[C] from the c-factor Q[T] of its containing district T by Tian's IDENTIFY subroutine (Shpitser–Pearl, Fig. 3): repeatedly restrict to the ancestral set of C and descend into the c-component of C in that restriction.

This file encodes IDENTIFY as an inductive reachability predicate CFactorReachableRec G T C — a derivation exists iff identify(C, T, ·) returns successfully (no hedge). Using an inductive predicate (rather than a termination_by recursion) makes the downstream soundness proof a clean induction on the derivation, and makes well-foundedness structural.

* inducedAncestral G T C — the observed ancestors of C within the subgraph of G induced on T (Tian's An(C)_{G_T}, the observed part). * CFactorReachableRec G T C — the IDENTIFY success predicate. * cFactorReachable_base_toRec / idSucceeds_toRec — the no-fixing certificate is the base case, so idSucceedsRec generalizes idSucceeds (and the recursive soundness id_sound_rec will subsume the no-fixing id_sound).

def inducedAncestral reviewed
Causalean.SCM.ID

Observed ancestors of C within the subgraph induced on T. Tian's An(C)_{G_T}: restrict G to the node set T, take the ancestors of C in that restricted graph, and keep the observed nodes. This is the set the IDENTIFY subroutine compares against C (project) and T (hedge / fail).

Definition (Lean source)
def inducedAncestral (G : SWIGGraph N) (T C : Finset (SWIGNode N)) : Finset (SWIGNode N) := (G.induce T).dag.ancestralSet C ∩ (G.induce T).observed
inductive CFactorReachableRec reviewed
Causalean.SCM.ID

Recursive IDENTIFY reachability (full Tian–Shpitser success certificate). CFactorReachableRec G T C holds when identify(C, T, Q[T]) succeeds, i.e. the c-factor Q[C] is recoverable from Q[T].

Definition (Lean source)
inductive CFactorReachableRec (G : SWIGGraph N) : Finset (SWIGNode N) → Finset (SWIGNode N) → Prop where | base {T C : Finset (SWIGNode N)} (hne : C.Nonempty) (hCT : C ⊆ T) (hproject : inducedAncestral G T C = C) : CFactorReachableRec G T C | step {T C : Finset (SWIGNode N)} (hne : C.Nonempty) (hCT : C ⊆ T) (hnotC : inducedAncestral G T C ≠ C) (hnotT : inducedAncestral G T C ≠ T) (hrec : CFactorReachableRec G (containingCComponent (G.induce (inducedAncestral G T C)) C) C) : CFactorReachableRec G T C
def idSucceedsRec reviewed
Causalean.SCM.ID

Full recursive success certificate for the ID algorithm. As idSucceeds, but each c-component S of the post-intervention ancestral graph need only be recursively reachable from its containing district (CFactorReachableRec), not already a full c-component. This is the honest Tian–Shpitser ID success condition (for the soundness direction).

Definition (Lean source)
noncomputable def idSucceedsRec (X : Finset N) (Y : Finset (SWIGNode N)) (G : SWIGGraph N) : Prop := ∃ hX : interventionValid X G, let GX := G.splitMono X hX.1 hX.2 let Ystar := GX.dag.ancestralSet Y Y ⊆ G.observed ∧ (∀ d ∈ X, SWIGNode.random d ∉ Y) ∧ ∀ S ∈ (GX.induce Ystar).cComponentSet, CFactorReachableRec G (containingCComponent G S) S
theorem cFactorReachable_base_toRec reviewed
Causalean.SCM.ID

The no-fixing certificate is the base case of the recursive one. For a SWIG graph G and a district S, if S is already reachable from its containing district under the plain no-fixing certificate, then S is recursively reachable from its containing district — which, since S is a full c-component, is S itself.

Formal statement
Proof (Lean source)
theorem cFactorReachable_base_toRec (G : SWIGGraph N) (S : Finset (SWIGNode N)) (h : cFactorReachable G (containingCComponent G S) S) : CFactorReachableRec G (containingCComponent G S) S := by obtain ⟨hne, _hsub, hmem⟩ := h rw [containingCComponent_of_mem_cComponentSet G S hmem] exact CFactorReachableRec.base hne (refl _) (inducedAncestral_self_of_mem_cComponentSet G S hmem)
theorem idSucceeds_toRec reviewed
Causalean.SCM.ID

idSucceedsRec generalizes idSucceeds. For an intervention target set X, an outcome node set Y, and a SWIG graph G, if the plain no-fixing ID certificate succeeds for X, Y on G, then the full recursive ID certificate also succeeds for X, Y on G, so soundness proved for idSucceedsRec subsumes the no-fixing headline.

Formal statement
X :
Y :
G :
h :
Proof (Lean source)
theorem idSucceeds_toRec (X : Finset N) (Y : Finset (SWIGNode N)) (G : SWIGGraph N) (h : idSucceeds X Y G) : idSucceedsRec X Y G := by obtain ⟨hX, hYobs, hdisj, hreach⟩ := h refine ⟨hX, hYobs, hdisj, ?_⟩ intro S hS exact cFactorReachable_base_toRec G S (hreach S hS)
3 supporting declarations (lemmas, instances)
  • inducedAncestral_parent_closed theorem — The induced ancestral set is closed under observed parents inside the ambient district T.
    G :
    T C :
    hT :
    T ⊆ G.observed
    ∀ v ∈ T, ∀ w ∈ inducedAncestral G T C, G.dag.edge v w → v ∈ inducedAncestral G T C
    Proof (Lean source)
    theorem inducedAncestral_parent_closed (G : SWIGGraph N) {T C : Finset (SWIGNode N)} (hT : T ⊆ G.observed) : ∀ v ∈ T, ∀ w ∈ inducedAncestral G T C, G.dag.edge v w → v ∈ inducedAncestral G T C := by classical intro v hvT w hw hEdge unfold inducedAncestral at hw ⊢ rcases Finset.mem_inter.mp hw with ⟨hwAnc, hwIndObs⟩ have hvIndObs : v ∈ (G.induce T).observed := by simp [SWIGGraph.induce, hvT, hT hvT] have hwIndObs' : w ∈ T ∩ G.observed := by simpa [SWIGGraph.induce] using hwIndObs have hEdgeInd : (G.induce T).dag.edge v w := by rw [SWIGGraph.induce] rw [SWIGGraph.inducedDag_edge_iff] refine ⟨hEdge, ?_, ?_⟩ · simp [hvT, hT hvT] · simp [(Finset.mem_inter.mp hwIndObs').1, (Finset.mem_inter.mp hwIndObs').2] have hvAnc : v ∈ (G.induce T).dag.ancestralSet C := by rcases Finset.mem_union.mp hwAnc with hwC | hwA · exact (G.induce T).dag.mem_ancestralSet_of_isAncestor hwC (DAG.isAncestor.edge hEdgeInd) · apply mem_union_right simp only [DAG.ancestorsSet, mem_filter, Finset.mem_univ, true_and] at hwA ⊢ obtain ⟨c, hcC, hwc⟩ := hwA exact ⟨c, hcC, (G.induce T).dag.isAncestor_trans (DAG.isAncestor.edge hEdgeInd) hwc⟩ exact Finset.mem_inter.mpr ⟨hvAnc, hvIndObs⟩
    Causalean.SCM.ID.inducedAncestral_parent_closed · Causalean/SCM/ID/GraphicalThms/DoGFormulaRec.lean:43
  • containingCComponent_of_mem_cComponentSet theorem — When S is a full c-component of G, its containing district is S itself.
    G :
    S :
    hS :
    S ∈ G.cComponentSet
    Proof (Lean source)
    theorem containingCComponent_of_mem_cComponentSet (G : SWIGGraph N) (S : Finset (SWIGNode N)) (hS : S ∈ G.cComponentSet) : containingCComponent G S = S := by simp only [SWIGGraph.cComponentSet] at hS obtain ⟨v, hv, rfl⟩ := Finset.mem_image.mp hS have hne : (G.cComponentOf v).Nonempty := ⟨v, G.mem_cComponentOf_self hv⟩ simp only [containingCComponent, dif_pos hne] have hreach : G.bidirectedReachable v hne.choose := (G.mem_cComponentOf_iff_reachable hv).mp hne.choose_spec exact (G.cComponentOf_eq_of_reachable hreach).symm
    Causalean.SCM.ID.containingCComponent_of_mem_cComponentSet · Causalean/SCM/ID/GraphicalThms/DoGFormulaRec.lean:113
  • inducedAncestral_self_of_mem_cComponentSet theorem — The observed ancestors of a full c-component S within G_S are S itself.
    G :
    S :
    hS :
    S ∈ G.cComponentSet
    Proof (Lean source)
    theorem inducedAncestral_self_of_mem_cComponentSet (G : SWIGGraph N) (S : Finset (SWIGNode N)) (hS : S ∈ G.cComponentSet) : inducedAncestral G S S = S := by have hSobs : S ⊆ G.observed := G.cComponentSet_subset_observed S hS have hobs : (G.induce S).observed = S := by change S ∩ G.observed = S exact Finset.inter_eq_left.mpr hSobs rw [inducedAncestral, hobs] apply Finset.Subset.antisymm · exact inter_subset_right · intro x hx exact Finset.mem_inter.mpr ⟨(G.induce S).dag.subset_ancestralSet S hx, hx⟩
    Causalean.SCM.ID.inducedAncestral_self_of_mem_cComponentSet · Causalean/SCM/ID/GraphicalThms/DoGFormulaRec.lean:126
CComponent­Factor 3 core · 1 supporting This file develops Tian's c-component factor setup for structural causal models and connects it to the per-node observational chain-rule product. ★ c_component_factorization

C-Component Factorization

This file develops Tian's c-component factor setup for structural causal models and connects it to the per-node observational chain-rule product.

The public API names the conditioning set for a component factor, SWIGGraph.qFactorParents C = (⋃ v ∈ C, Pa⁺_G(v)) \ C, proves that these conditioning coordinates are observed, and defines SCM.qFactor M C s as the conditional-kernel proxy for Q[C] at a fixed slice. The theorem c_component_factorization records the continuous-safe foundation: the observational kernel is the chain-rule product of one-node conditional kernels along the topological order of observed nodes.

Grouping that chain-rule product into Tian c-component factors is theorem content supplied by downstream density and q-factor identity files; it is not a definitional property of qFactor.

def qFactorParents reviewed
Causalean.SWIGGraph

The conditioning set of the c-component factor Q[C]:

Definition (Lean source)
noncomputable def qFactorParents (C : Finset (SWIGNode N)) : Finset (SWIGNode N) := (C.biUnion G.observedPredecessors) \ C
def qFactor reviewed
Causalean.SCM

Conditional-kernel proxy for a Tian c-component factor.

Definition (Lean source)
noncomputable def qFactor (M : SCM N Ω) (C : Finset (SWIGNode N)) (hC : C ⊆ M.observed) [StandardBorelSpace (ValuesOn C (swigΩ Ω))] [Nonempty (ValuesOn C (swigΩ Ω))] (s : M.FixedValues) [∀ s' : M.FixedValues, IsFiniteMeasure (M.obsKernel s')] [CountableOrCountablyGenerated M.FixedValues (ValuesOn (M.toSWIGGraph.qFactorParents C) (swigΩ Ω))] : Kernel (ValuesOn (M.toSWIGGraph.qFactorParents C) (swigΩ Ω)) (ValuesOn C (swigΩ Ω)) := (M.obsCondKernel C (M.toSWIGGraph.qFactorParents C) hC (M.toSWIGGraph.qFactorParents_subset_observed C)).comap (fun c => (s, c)) (prodMk measurable_const measurable_id)
theorem c_component_factorization reviewed
Causalean.SCM

Theorem (Tian 2002, per-node chain-rule factorization). For a structural causal model M, at a fixed assignment s, its observational kernel equals the full chain-rule product of one-node conditional kernels along the topological order of observed nodes. Tian's Pa⁺(V) is interpreted as the full observed history before V, so this statement is the ordinary iterated-disintegration factorization and does not use graphical Markov or do-calculus reasoning.

Formal statement
M :
SCM N Ω
s :
M.FixedValues
∀ (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Ω Ω))
M.obsKernel s = M.qFactorProduct s
Proof (Lean source)
theorem c_component_factorization (M : SCM N Ω) (s : M.FixedValues) [∀ (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Ω Ω))] : M.obsKernel s = M.qFactorProduct s := M.obsKernel_eq_qFactorProduct s
1 supporting declaration (lemmas, instances)
  • qFactorParents_subset_observed lemma — qFactorParents C consists of observed nodes outside C.
    C :
    G.qFactorParents C ⊆ G.observed
    Proof (Lean source)
    lemma qFactorParents_subset_observed (C : Finset (SWIGNode N)) : G.qFactorParents C ⊆ G.observed := by intro w hw rcases Finset.mem_sdiff.mp hw with ⟨hw_union, _⟩ rcases Finset.mem_biUnion.mp hw_union with ⟨v, _, hw_pred⟩ exact G.observedPredecessors_subset_observed v hw_pred
    Causalean.SWIGGraph.qFactorParents_subset_observed · Causalean/SCM/ID/GraphicalThms/CComponentFactor.lean:87
Do­GFormula­Tian 6 core · 22 supporting This file states the Tian density factorization used by the graphical ID algorithm: the post-intervention law on the observed ancestors of the query is identified by a product of district factors recovered from the obser ★ markov_tian_cfactorization_density★ doAncestralDistrictDensity_recovered_from_obs★ doObsKernelAncestralMarginal_tian_cfactorization_density

Tian density assembly for the ID do-law g-formula

This file states the Tian density factorization used by the graphical ID algorithm: the post-intervention law on the observed ancestors of the query is identified by a product of district factors recovered from the observational density.

The statements avoid SCM.induce for the post-intervention ancestral law: all district factors of the do-law marginal are defined from the marginal measure itself, using Tian's prefix-ratio/conditional construction on D = An_{G_X}(Y) ∩ observed.

The main results are:

* rnDeriv_eq_tianDensityProduct, a measure-only chain rule expressing a dominated finite law's density as a product of one-coordinate conditional densities in graph order. * markov_tian_cfactorization_density, which regroups that product into Tian district factors for a globally Markov finite law. * doObsKernelAncestralMarginal_globalMarkovOn, the SCM-to-measure Markov bridge for the ancestral do-law marginal. * doAncestralDistrictDensity_recovered_from_obs and doObsKernelAncestralMarginal_tian_cfactorization_density, the ID-specific recovery and factorization statements used by the discrete soundness layer.

def extendTianPrefix reviewed
Causalean.SCM.ID

Extend a D-prefix assignment by the next singleton coordinate.

Definition (Lean source)
noncomputable def extendTianPrefix (H : SWIGGraph N) (D : Finset (SWIGNode N)) {n : ℕ} (hn : n < D.card) : ValuesOn (H.prefixIn D n) (swigΩ Ω) × ValuesOn ({(H.nodesAt D ⟨n, hn⟩).val} : Finset (SWIGNode N)) (swigΩ Ω) → ValuesOn (H.prefixIn D (n + 1)) (swigΩ Ω) := fun p => (valuesEquivOfEq (Ω := swigΩ Ω) (prefixIn_succ H D hn).symm) (valuesUnionMk p.1 p.2)
def tianPrefixDensityProductInPrefix reviewed
Causalean.SCM.ID

Recursive Tian prefix density product on an intermediate prefix.

Definition (Lean source)
noncomputable def tianPrefixDensityProductInPrefix (H : SWIGGraph N) (D : Finset (SWIGNode N)) (μ : 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Ω Ω))] : (k : ℕ) → ValuesOn (H.prefixIn D k) (swigΩ Ω) → ENNReal | 0, _ => 1 | k + 1, z => tianPrefixDensityProductInPrefix H D μ ref k (valuesProjection (prefixIn_mono H D (Nat.le_succ k)) z) * if hk : k < D.card then ((condDistrib (valuesProjection (show ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) ⊆ D from by intro v hv rw [mem_singleton] at hv exact hv ▸ (H.nodesAt D ⟨k, hk⟩).property)) (valuesProjection (H.prefixIn_subset D k)) μ) (valuesProjection (prefixIn_mono H D (Nat.le_succ k)) z)).rnDeriv (jointRef ref ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N))) (valuesProjection (show ({(H.nodesAt D ⟨k, hk⟩).val} : Finset (SWIGNode N)) ⊆ H.prefixIn D (k + 1) from by intro v hv rw [mem_singleton] at hv subst hv rw [nodesAt_mem_prefixIn_iff H D (k + 1) ⟨k, hk⟩] exact Nat.lt_succ_self k) z) else 1
def tianPrefixStepDensityInPrefix reviewed
Causalean.SCM.ID

One-step Tian density read from a k-prefix assignment.

Definition (Lean source)
noncomputable def tianPrefixStepDensityInPrefix (H : SWIGGraph N) (D : Finset (SWIGNode N)) (μ : Measure (ValuesOn D (swigΩ Ω))) (ref : ReferenceMeasures Ω) [IsFiniteMeasure μ] [∀ (i : ℕ) (hi : i < D.card), StandardBorelSpace (ValuesOn ({(H.nodesAt D ⟨i, hi⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] [∀ (i : ℕ) (hi : i < D.card), Nonempty (ValuesOn ({(H.nodesAt D ⟨i, hi⟩).val} : Finset (SWIGNode N)) (swigΩ Ω))] (k : ℕ) (z : ValuesOn (H.prefixIn D k) (swigΩ Ω)) (i : ℕ) : ENNReal := if hi : i < k then if hcard : i < D.card then ((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)).rnDeriv (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) else 1 else 1
theorem markov_tian_cfactorization_density reviewed
Causalean.SCM.ID

Density form of the Markov-to-c-factorization theorem. Let H be a pure SWIG graph, D a finite set of SWIG nodes, μ a finite (probability) measure on the assignments to D, and ref a family of reference measures. If D is exactly the observed-node set of H and μ is absolutely continuous with respect to the product reference measure on D, then the Radon–Nikodym density of μ against that product reference equals, almost everywhere, the product over the c-components of H of their Tian district-density factors.

Formal statement
H :
D :
hD :
H.observed = D
μ :
∀ n, Fintype (Ω n)
∀ (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Ω Ω))
hdom :
μ ≪ jointRef ref D
μ.rnDeriv (jointRef ref D)
=ᵐ[jointRef ref D] fun x => ∏ S ∈ H.cComponentSet, tianDistrictDensity H D μ ref S x
Proof (Lean source)
theorem markov_tian_cfactorization_density (H : SWIGGraph N) (D : Finset (SWIGNode N)) (hD : H.observed = D) (μ : Measure (ValuesOn D (swigΩ Ω))) (ref : ReferenceMeasures Ω) [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] [StandardBorelSpace (ValuesOn D (swigΩ Ω))] [IsProbabilityMeasure μ] [∀ (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Ω Ω))] (hdom : μ ≪ jointRef ref D) : μ.rnDeriv (jointRef ref D) =ᵐ[jointRef ref D] fun x => ∏ S ∈ H.cComponentSet, tianDistrictDensity H D μ ref S x := by exact (rnDeriv_eq_tianDensityProduct H D μ ref hdom).trans (Filter.EventuallyEq.of_eq (prod_tianDistrictDensity_eq_tianDensityProduct H D hD μ ref).symm)
theorem doAncestralDistrictDensity_recovered_from_obs reviewed
Causalean.SCM.ID

T2, abstract density recovery statement. Fix a standard structural causal model M and an intervention target set X for which every targeted node is currently a random observed node and none of its fixed copies is already fixed, an output set Y, and a reference-measure family faithful to the graph. For a district S of the truncated c-component set of the post-intervention ancestral graph and a c-component C of the base graph that is factor-reachable from S, assume every fixed-value assignment gives an observational kernel with everywhere-positive point masses, no intervention target's random form lies in Y, and that an extension map from ancestral assignments to full observed assignments restricts back to the identity and agrees with the intervention values sDo on the targeted coordinates. Then the district factor of S computed from the density of the do-law's ancestral marginal equals, almost everywhere, the full-graph c-component density factor of C evaluated at the extension of the ancestral assignment.

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 C :
hS :
S ∈ fixTruncCComponentSet M X hObs hFix Y
hReach :
cFactorReachable M.toSWIGGraph C S
hCmem :
C ∈ 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) C (extend xD)
Proof (Lean source)
theorem doAncestralDistrictDensity_recovered_from_obs [∀ 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 C : Finset (SWIGNode N)) (hS : S ∈ fixTruncCComponentSet M X hObs hFix Y) (hReach : cFactorReachable M.toSWIGGraph C S) (hCmem : C ∈ 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) C (extend xD) := by exact doAncestralDistrictDensity_recovered_from_obs_core M X hStd hObs hFix Y ref href sDo S C hS hReach hCmem hpos hYX extend hExtend hExtendX
theorem doObsKernelAncestralMarginal_tian_cfactorization_density reviewed
Causalean.SCM.ID

ID-specific T1 wrapper. For an intervention target set X where every targeted node is currently a random observed node with no fixed copy already fixed, if the ancestral marginal of the do-law ν_M = (M.fixSet X).obsKernel.map π_D is absolutely continuous with respect to the product reference measure on the ancestral observed set, then its Radon–Nikodym density equals, almost everywhere, the product over the c-components of the induced post-intervention ancestral graph G_X[D] of their Tian district-density factors.

Formal statement
∀ n, Nonempty (swigΩ Ω 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 :
s :
(M.fixSet X hObs hFix).FixedValues
StandardBorelSpace (M.fixSet X hObs hFix).RandomValues
StandardBorelSpace (M.fixSet X hObs hFix).ObservedValues
∀ s' :
(M.fixSet X hObs hFix).FixedValues, IsFiniteMeasure ((M.fixSet X hObs hFix).jointKernel s')
(M.fixSet X hObs hFix).FixedValues, IsFiniteMeasure ((M.fixSet X hObs hFix).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Ω Ω))
hdomD :
doObsKernelAncestralMarginal M X hObs hFix Y s ≪ jointRef ref (fixObservedAncestralSet M X hObs hFix Y)
let D := fixObservedAncestralSet M X hObs hFix Y let H := (M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y) (doObsKernelAncestralMarginal M X hObs hFix Y s).rnDeriv (jointRef ref D)
=ᵐ[jointRef ref D] fun x => ∏ S ∈ H.cComponentSet, tianDistrictDensity H D (doObsKernelAncestralMarginal M X hObs hFix Y s) ref S x
Proof (Lean source)
theorem doObsKernelAncestralMarginal_tian_cfactorization_density [∀ n, StandardBorelSpace (swigΩ Ω n)] [∀ n, Nonempty (swigΩ Ω 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 Ω) (s : (M.fixSet X hObs hFix).FixedValues) [StandardBorelSpace (ValuesOn (fixObservedAncestralSet M X hObs hFix Y) (swigΩ Ω))] [StandardBorelSpace (M.fixSet X hObs hFix).RandomValues] [StandardBorelSpace (M.fixSet X hObs hFix).ObservedValues] [∀ s' : (M.fixSet X hObs hFix).FixedValues, IsFiniteMeasure ((M.fixSet X hObs hFix).jointKernel s')] [∀ s' : (M.fixSet X hObs hFix).FixedValues, IsFiniteMeasure ((M.fixSet X hObs hFix).obsKernel s')] [IsFiniteMeasure (doObsKernelAncestralMarginal M X hObs hFix Y 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Ω Ω))] (hdomD : doObsKernelAncestralMarginal M X hObs hFix Y s ≪ jointRef ref (fixObservedAncestralSet M X hObs hFix Y)) : let D := fixObservedAncestralSet M X hObs hFix Y let H := (M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y) (doObsKernelAncestralMarginal M X hObs hFix Y s).rnDeriv (jointRef ref D) =ᵐ[jointRef ref D] fun x => ∏ S ∈ H.cComponentSet, tianDistrictDensity H D (doObsKernelAncestralMarginal M X hObs hFix Y s) ref S x := by intro D H exact markov_tian_cfactorization_density H D rfl (doObsKernelAncestralMarginal M X hObs hFix Y s) ref hdomD
22 supporting declarations (lemmas, instances)
IDAlgorithm 2 core · 8 supporting This file records the graph-side success certificate for the ID algorithm and states that the certificate identifies the interventional outcome kernel. ★ doKernelY_eq_cfactor_decomposition★ id_sound

ID Algorithm Soundness for the No-Fixing Fragment

This file records the graph-side success certificate for the ID algorithm and states that the certificate identifies the interventional outcome kernel. The proved soundness theorem combines branch alignment for the total query's well-formedness predicate with the Tian c-factor decomposition for the valid branch.

The success predicate is structural. It computes the ancestors of the requested outcomes after splitting the treatment variables in the SWIG, induces the ancestral subgraph, and checks its c-components against c-components already available in the original graph. This is the no-additional-fixing case of the Tian/Shpitser reachability condition; the general fixing-sequence predicate is deferred here rather than encoded as a circular appeal to identifiability.

theorem doKernelY_eq_cfactor_decomposition reviewed
Causalean.SCM.ID

Valid-branch kernel equality under a successful no-fixing ID certificate. For two finite structural causal models M₁, M₂ that share the same SWIG graph G, are each dominated by a reference-measure family ref that is faithful to the graph, satisfy discrete positivity of their observational kernels, and have heterogeneously equal observational kernels, if the total interventional query on outcome set Y under intervention X is well formed in both models and X, Y admit a successful no-fixing ID certificate on G, then the two models' post-intervention outcome kernels for Y are heterogeneously equal.

Formal statement
∀ n, StandardBorelSpace (Ω n)
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
X :
Y :
G :
href :
_hID :
M₁ M₂ :
SCM N Ω
_hsg₁ :
M₁.toSWIGGraph = G
_hsg₂ :
M₂.toSWIGGraph = G
_hdom₁ :
DominatedObs M₁ ref
_hdom₂ :
DominatedObs M₂ ref
hpos₁ :
DiscreteID.DiscretePositive M₁
hpos₂ :
DiscreteID.DiscretePositive M₂
_hobs :
HEq M₁.obsKernel M₂.obsKernel
hvalid₁ :
hvalid₂ :
M₁.doKernelY X hvalid₁.1 hvalid₁.2.1 Y hvalid₁.2.2.1 (standardFixedValues M₁ hvalid₁.2.2.2)
= M₂.doKernelY X hvalid₂.1 hvalid₂.2.1 Y hvalid₂.2.2.1 (standardFixedValues M₂ hvalid₂.2.2.2)
Proof (Lean source)
theorem doKernelY_eq_cfactor_decomposition [∀ n, StandardBorelSpace (Ω n)] [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (X : Finset N) (Y : Finset (SWIGNode N)) (G : SWIGGraph N) (ref : ReferenceMeasures Ω) (href : ReferenceFaithful ref) (_hID : idSucceeds X Y G) (M₁ M₂ : SCM N Ω) (_hsg₁ : M₁.toSWIGGraph = G) (_hsg₂ : M₂.toSWIGGraph = G) (_hdom₁ : DominatedObs M₁ ref) (_hdom₂ : DominatedObs M₂ ref) (hpos₁ : DiscreteID.DiscretePositive M₁) (hpos₂ : DiscreteID.DiscretePositive M₂) (_hobs : HEq M₁.obsKernel M₂.obsKernel) (hvalid₁ : interventionalQueryValid X Y M₁) (hvalid₂ : interventionalQueryValid X Y M₂) : M₁.doKernelY X hvalid₁.1 hvalid₁.2.1 Y hvalid₁.2.2.1 (standardFixedValues M₁ hvalid₁.2.2.2) = M₂.doKernelY X hvalid₂.1 hvalid₂.2.1 Y hvalid₂.2.2.1 (standardFixedValues M₂ hvalid₂.2.2.2) := by have hsg : M₁.toSWIGGraph = M₂.toSWIGGraph := _hsg₁.trans _hsg₂.symm exact doKernelY_eq_of_doObsKernel_heq X Y M₁ M₂ hsg hvalid₁.1 hvalid₁.2.1 hvalid₂.1 hvalid₂.2.1 hvalid₁.2.2.1 hvalid₂.2.2.1 (standardFixedValues M₁ hvalid₁.2.2.2) (standardFixedValues M₂ hvalid₂.2.2.2) (standardFixedValues_heq M₁ M₂ (congrArg SWIGGraph.fixed hsg) hvalid₁.2.2.2) (doObsKernelYMarginal_heq_of_obsKernel_heq X Y G ref href _hID M₁ M₂ _hsg₁ _hsg₂ _hdom₁ _hdom₂ hpos₁ hpos₂ _hobs hvalid₁ hvalid₂)
theorem id_sound reviewed
Causalean.SCM.ID

Soundness of the no-fixing ID algorithm. Fix an intervention target set X, an outcome node set Y, a SWIG graph G, and a reference-measure family ref that is faithful to the graph. Then whenever the no-fixing ID certificate succeeds for X, Y on G, the interventional query mapping X to Y is identifiable within the class of models dominated by ref with discretely positive observational kernels: any two such models that share graph G and observational kernel agree on the query.

Formal statement
∀ n, StandardBorelSpace (Ω n)
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
X :
Y :
G :
href :
idSucceeds X Y G → IdentifiableUnder (Ω := Ω) G (fun _ => True) (fun M => DominatedObs M ref ∧ DiscreteID.DiscretePositive M) (interventionalQuery (Ω := Ω) X Y)
Proof (Lean source)
theorem id_sound [∀ n, StandardBorelSpace (Ω n)] [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (X : Finset N) (Y : Finset (SWIGNode N)) (G : SWIGGraph N) (ref : ReferenceMeasures Ω) (href : ReferenceFaithful ref) : idSucceeds X Y G → IdentifiableUnder (Ω := Ω) G (fun _ => True) (fun M => DominatedObs M ref ∧ DiscreteID.DiscretePositive M) (interventionalQuery (Ω := Ω) X Y) := by classical intro hID M₁ M₂ hsg₁ hsg₂ _ _ hM₁ hM₂ hobs have hYX : ∀ D ∈ X, SWIGNode.random D ∉ Y := by rcases hID with ⟨_hX, hIDrest⟩ exact hIDrest.2.1 have hvalid_iff : interventionalQueryValid X Y M₁ ↔ interventionalQueryValid X Y M₂ := interventionalQueryValid_iff_of_toSWIGGraph_eq (Ω := Ω) X Y M₁ M₂ (hsg₁.trans hsg₂.symm) by_cases hvalid₁ : interventionalQueryValid X Y M₁ · have hvalid₂ : interventionalQueryValid X Y M₂ := hvalid_iff.mp hvalid₁ rw [interventionalQuery_eq_doKernelY_of_valid (Ω := Ω) X Y M₁ hvalid₁, interventionalQuery_eq_doKernelY_of_valid (Ω := Ω) X Y M₂ hvalid₂] exact doKernelY_eq_cfactor_decomposition (Ω := Ω) X Y G ref href hID M₁ M₂ hsg₁ hsg₂ hM₁.1 hM₂.1 hM₁.2 hM₂.2 hobs hvalid₁ hvalid₂ · have hvalid₂ : ¬ interventionalQueryValid X Y M₂ := by intro h exact hvalid₁ (hvalid_iff.mpr h) rw [interventionalQuery_eq_default_of_not_valid (Ω := Ω) X Y M₁ hvalid₁, interventionalQuery_eq_default_of_not_valid (Ω := Ω) X Y M₂ hvalid₂]
8 supporting declarations (lemmas, instances)
IDAlgorithm­Rec 8 core · 7 supporting id_sound (in GraphicalThms.IDAlgorithm) proves soundness for the *no-fixing* certificate idSucceeds, where every post-intervention ancestral district is already a full c-component of the original graph. ★ doAncestralDistrictDensity_recovered_from_obs_rec★ doKernelY_eq_cfactor_decomposition_rec★ id_sound_rec★ id_sound_rec_discrete

Soundness of the full (recursive) Tian–Shpitser ID algorithm

id_sound (in GraphicalThms.IDAlgorithm) proves soundness for the no-fixing certificate idSucceeds, where every post-intervention ancestral district is already a full c-component of the original graph. This file lifts soundness to the full recursive certificate idSucceedsRec: each district need only be recursively reachable (CFactorReachableRec) from its containing district via Tian's IDENTIFY fixing sequence.

Since idSucceeds → idSucceedsRec (idSucceeds_toRec), id_sound_rec subsumes id_sound, and id_sound_rec_discrete subsumes the frozen id_sound_discrete.

Proof architecture for id_sound_rec

The assembly mirrors id_sound: the do-law Y-marginal factorizes over the c-components of the post-intervention ancestral graph H, and it suffices to show each district factor tianDistrictDensity H D (do-law marginal) ref S is a functional of the observational kernel. The ONLY change from id_sound is the per-district recovery step (id_sound uses doAncestralDistrictDensity_recovered_from_obs, which needs S to be a full c-component). The recursive version is:

* M4a (per-step Lemma 12). For W ancestrally closed inside a district T, the W-marginal of the Q[T]-density equals the Q[W]-density. At the measure level this is q_factor_marginal_fixing applied inside M_T := M.fixSet (observed ∖ T); transport to densities via the DoLawMarginal / FiniteReference bridges used by id_sound's base recovery. * M4b (recursive recovery). By induction on the CFactorReachableRec C S derivation: the base case (inducedAncestral G C S = S) is a marginalization of the full-district obs-side factor cComponentDensityFactor ref C (whose recovery is the existing doAncestralDistrictDensity_recovered_from_obs at the containing full c-component C); each step composes one M4a fixing step. The recovered value is a functional of obsKernel, so equal observational kernels give equal district factors — exactly as in id_sound's cComponentDensityFactor_heq_of_obsKernel_heq step. * M4c (assembly). Feed the recursive per-district equality into the same Finset.prod induction as id_sound.

Everything downstream of the per-district recovery is verbatim id_sound.

def marginalizeOnObserved reviewed
Causalean.SCM.ID

Observed-set form of SCM.marginalizeOn, used only to expose that the recursive mass functional is independent of the rest of the SCM record.

Definition (Lean source)
noncomputable def marginalizeOnObserved [∀ 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 extractDistrictObserved reviewed
Causalean.SCM.ID

Observed-set form of SCM.extractDistrict.

Definition (Lean source)
noncomputable def extractDistrictObserved [∀ 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'), marginalizeOnObserved O (A \ G'.prefixIn A (i.val + 1)) (fun _ hv => hA ((Finset.mem_sdiff.mp hv).1)) q x / marginalizeOnObserved O (A \ G'.prefixIn A i.val) (fun _ hv => hA ((Finset.mem_sdiff.mp hv).1)) q x
def identifyMassRecObserved reviewed
Causalean.SCM.ID

Observed-set form of SCM.identifyMassRec.

Definition (Lean source)
noncomputable def identifyMassRecObserved [∀ 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 := inducedAncestral G T C let hA : A ⊆ O := fun _ hv => hT (inducedAncestral_subset_left G T C hv) if _hAC : A = C then marginalizeOnObserved O (T \ C) (fun _ hv => hT ((Finset.mem_sdiff.mp hv).1)) q else if _hAT : A = T then q else let C₁ := containingCComponent (G.induce A) C let hC₁ : C₁ ⊆ O := fun _ hv => hT (inducedAncestral_subset_left G T C (containingCComponent_induce_subset G A C hv)) identifyMassRecObserved O G C₁ C hC₁ (extractDistrictObserved O (G.induce A) A C₁ hA (marginalizeOnObserved 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 := inducedAncestral_subset_left G T C have hAssubT : A ⊂ T := Finset.ssubset_iff_subset_ne.mpr ⟨hAsubT, _hAT⟩ have hC₁subA : C₁ ⊆ A := containingCComponent_induce_subset G A C exact Nat.lt_of_le_of_lt (Finset.card_le_card hC₁subA) (Finset.card_lt_card hAssubT)
def recoveredFactorRec reviewed
Causalean.SCM.ID

Obs-side recursive recovered factor for a target district.

Definition (Lean source)
@[irreducible] noncomputable def recoveredFactorRec (M : SCM N Ω) (ref : ReferenceMeasures Ω) (s : M.FixedValues) (C S : Finset (SWIGNode N)) [hfin : ∀ n, Fintype (Ω 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 => if hC : C ⊆ M.observed then if hSobs : S ⊆ M.observed then SCM.identifyMassRec M.observed M.toSWIGGraph C S hC (fun x' => (∏ i ∈ Finset.univ.filter (fun i : Fin M.observed.card => (M.observedAt i).val ∈ C), M.obsStepCondDensity ref s i x') * jointRef ref C ({valuesProjection hC x'} : Set (ValuesOn C (swigΩ Ω)))) x / jointRef ref S ({valuesProjection hSobs x} : Set (ValuesOn S (swigΩ Ω))) else 0 else 0
theorem doAncestralDistrictDensity_recovered_from_obs_rec reviewed
Causalean.SCM.ID

Recursive district-density recovery from the observational kernel. Fix a standard structural causal model M and an intervention target set X for which every targeted node is currently a random observed node and none of its fixed copies is already fixed, an output set Y, and a reference-measure family faithful to the graph. For a district S of the truncated c-component set of the post-intervention ancestral graph and a c-component C of the base graph that is recursively factor-reachable from S, assume every fixed-value assignment gives an observational kernel with everywhere-positive point masses, no intervention target's random form lies in Y, and that an extension map from ancestral assignments to full observed assignments restricts back to the identity and agrees with the intervention values sDo on the targeted coordinates. Then the district factor of S computed from the density of the do-law's ancestral marginal equals, almost everywhere, the full-graph c-component density factor of C evaluated at the extension of the ancestral assignment.

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 C :
hS :
S ∈ fixTruncCComponentSet M X hObs hFix Y
hReach :
CFactorReachableRec M.toSWIGGraph C S
hCmem :
C ∈ 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 => recoveredFactorRec M ref (M.fixSetProj X hObs hFix sDo) C S (extend xD)
Proof (Lean source)
theorem doAncestralDistrictDensity_recovered_from_obs_rec [∀ 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 C : Finset (SWIGNode N)) (hS : S ∈ fixTruncCComponentSet M X hObs hFix Y) (hReach : CFactorReachableRec M.toSWIGGraph C S) (hCmem : C ∈ 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 => recoveredFactorRec M ref (M.fixSetProj X hObs hFix sDo) C S (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 sObs := M.fixSetProj X hObs hFix sDo have hCobs : C ⊆ M.observed := by simpa using M.toSWIGGraph.cComponentSet_subset_observed C hCmem have hSobs : S ⊆ M.observed := fun _ hv => hCobs (hReach.target_subset hv) have hSD : S ⊆ D := by have hScomp : S ∈ H.cComponentSet := by change S ∈ ((M.fixSet X hObs hFix).toSWIGGraph.induce (fixAncestralSet M X hObs hFix Y)).cComponentSet simpa [fixTruncCComponentSet] using hS have hSHobs : S ⊆ H.observed := H.cComponentSet_subset_observed S hScomp -- `H.observed` is `fixAncestralSet … ∩ MX.observed` only after delta-unfolding -- `SWIGGraph.induce`, whose body is `let`-structured: simp will not do it, and -- the folded/unfolded pair is defeq only at default transparency. 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 hproj : valuesProjection hSobs (extend xD) = valuesProjection hSD xD := by ext v have h := congrFun (hExtend xD) ⟨v.val, hSD v.property⟩ simpa [valuesProjection] using h have hdo : MX.qLocalMass sDo S (by simpa [MX, SCM.fixSet_observed] using hSobs) (extend xD) = M.qLocalMass sObs S hSobs (extend xD) := by simpa [MX, sObs] using qLocalMass_fixSet_invariant M X hObs hFix sDo S hSobs hSX (extend xD) (fun D hD => hExtendX xD D hD) have hseed : (fun x' => (∏ i ∈ Finset.univ.filter (fun i : Fin M.observed.card => (M.observedAt i).val ∈ C), M.obsStepCondDensity ref sObs i x') * jointRef ref C ({valuesProjection hCobs x'} : Set (ValuesOn C (swigΩ Ω)))) = M.qLocalMass sObs C hCobs := by funext x' have hprod : (∏ i ∈ Finset.univ.filter (fun i : Fin M.observed.card => (M.observedAt i).val ∈ C), M.obsStepCondDensity ref sObs i x') = M.cComponentDensityFactor ref sObs C x' := by unfold cComponentDensityFactor refine Finset.prod_congr ?_ ?_ · ext i simp only [mem_filter, Finset.mem_univ, true_and] exact (mem_cComponent_iff_cComponentOf_eq M.toSWIGGraph (M.observedAt i).property hCmem) · intro i _hi rfl let atom := jointRef ref C ({valuesProjection hCobs x'} : Set (ValuesOn C (swigΩ Ω))) have hatom0 : atom ≠ 0 := by exact jointRef_singleton_ne_zero ref href C (valuesProjection hCobs x') have hatomtop : atom ≠ (⊤ : ENNReal) := by exact ne_of_lt (MeasureTheory.measure_lt_top (jointRef ref C) ({valuesProjection hCobs x'} : Set (ValuesOn C (swigΩ Ω)))) have hmech : M.mechCFactor ref C hCobs sObs x' = M.qLocalMass sObs C hCobs x' / atom := by simpa [atom] using mechCFactor_eq_qLocalMass_div_jointRef M ref sObs C hCobs href (standard_fixed_random_edgeless M hStd) x' calc (∏ i ∈ Finset.univ.filter (fun i : Fin M.observed.card => (M.observedAt i).val ∈ C), M.obsStepCondDensity ref sObs i x') * jointRef ref C ({valuesProjection hCobs x'} : Set (ValuesOn C (swigΩ Ω))) = M.cComponentDensityFactor ref sObs C x' * atom := by rw [hprod] _ = M.mechCFactor ref C hCobs sObs x' * atom := by rw [cComponentDensityFactor_eq_mechCFactor M ref sObs hStd C hCobs hCmem href (hpos sObs) x'] _ = (M.qLocalMass sObs C hCobs x' / atom) * atom := by rw [hmech] _ = M.qLocalMass sObs C hCobs x' := by exact ENNReal.div_mul_cancel hatom0 hatomtop have hidentify : SCM.identifyMassRec M.observed M.toSWIGGraph C S hCobs (fun x' => (∏ i ∈ Finset.univ.filter (fun i : Fin M.observed.card => (M.observedAt i).val ∈ C), M.obsStepCondDensity ref sObs i x') * jointRef ref C ({valuesProjection hCobs x'} : Set (ValuesOn C (swigΩ Ω)))) (extend xD) = M.qLocalMass sObs S hSobs (extend xD) := by rw [hseed] exact identifyMassRec_qLocalMass M sObs (hpos sObs) C S hCobs hReach (extend xD) have hkey := tianDistrictDensity_eq_qLocalMass_div_jointRef_district M X hObs hFix Y ref href sDo hpos hYX S hS extend hExtend xD calc tianDistrictDensity H D (doObsKernelAncestralMarginal M X hObs hFix Y sDo) ref S xD = MX.qLocalMass sDo S (show S ⊆ MX.observed from by simpa [MX, SCM.fixSet_observed] using hSobs) (extend xD) / jointRef ref S ({valuesProjection hSD xD} : Set (ValuesOn S (swigΩ Ω))) := by simpa [H, D, MX] using hkey _ = M.qLocalMass sObs S hSobs (extend xD) / jointRef ref S ({valuesProjection hSD xD} : Set (ValuesOn S (swigΩ Ω))) := by rw [hdo] _ = M.qLocalMass sObs S hSobs (extend xD) / jointRef ref S ({valuesProjection hSobs (extend xD)} : Set (ValuesOn S (swigΩ Ω))) := by rw [hproj] _ = recoveredFactorRec M ref sObs C S (extend xD) := by unfold recoveredFactorRec rw [dif_pos hCobs, dif_pos hSobs, hidentify]
theorem doKernelY_eq_cfactor_decomposition_rec reviewed
Causalean.SCM.ID

Recursive valid-branch kernel equality. For two finite structural causal models M₁, M₂ that share the same SWIG graph G, are each dominated by a reference-measure family ref that is faithful to the graph, satisfy discrete positivity of their observational kernels, and have heterogeneously equal observational kernels, if the total interventional query on outcome set Y under intervention X is well formed in both models and X, Y admit a successful full recursive ID certificate on G, then the two models' post-intervention outcome kernels for Y are heterogeneously equal. This is the same transport as doKernelY_eq_cfactor_decomposition, with the recursive Y-marginal wrapper in place of the no-fixing one.

Formal statement
∀ n, StandardBorelSpace (Ω n)
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
X :
Y :
G :
href :
_hID :
M₁ M₂ :
SCM N Ω
_hsg₁ :
M₁.toSWIGGraph = G
_hsg₂ :
M₂.toSWIGGraph = G
_hdom₁ :
DominatedObs M₁ ref
_hdom₂ :
DominatedObs M₂ ref
hpos₁ :
DiscreteID.DiscretePositive M₁
hpos₂ :
DiscreteID.DiscretePositive M₂
_hobs :
HEq M₁.obsKernel M₂.obsKernel
hvalid₁ :
hvalid₂ :
M₁.doKernelY X hvalid₁.1 hvalid₁.2.1 Y hvalid₁.2.2.1 (standardFixedValues M₁ hvalid₁.2.2.2)
= M₂.doKernelY X hvalid₂.1 hvalid₂.2.1 Y hvalid₂.2.2.1 (standardFixedValues M₂ hvalid₂.2.2.2)
Proof (Lean source)
theorem doKernelY_eq_cfactor_decomposition_rec [∀ n, StandardBorelSpace (Ω n)] [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (X : Finset N) (Y : Finset (SWIGNode N)) (G : SWIGGraph N) (ref : ReferenceMeasures Ω) (href : ReferenceFaithful ref) (_hID : idSucceedsRec X Y G) (M₁ M₂ : SCM N Ω) (_hsg₁ : M₁.toSWIGGraph = G) (_hsg₂ : M₂.toSWIGGraph = G) (_hdom₁ : DominatedObs M₁ ref) (_hdom₂ : DominatedObs M₂ ref) (hpos₁ : DiscreteID.DiscretePositive M₁) (hpos₂ : DiscreteID.DiscretePositive M₂) (_hobs : HEq M₁.obsKernel M₂.obsKernel) (hvalid₁ : interventionalQueryValid X Y M₁) (hvalid₂ : interventionalQueryValid X Y M₂) : M₁.doKernelY X hvalid₁.1 hvalid₁.2.1 Y hvalid₁.2.2.1 (standardFixedValues M₁ hvalid₁.2.2.2) = M₂.doKernelY X hvalid₂.1 hvalid₂.2.1 Y hvalid₂.2.2.1 (standardFixedValues M₂ hvalid₂.2.2.2) := by have hsg : M₁.toSWIGGraph = M₂.toSWIGGraph := _hsg₁.trans _hsg₂.symm exact doKernelY_eq_of_doObsKernel_heq X Y M₁ M₂ hsg hvalid₁.1 hvalid₁.2.1 hvalid₂.1 hvalid₂.2.1 hvalid₁.2.2.1 hvalid₂.2.2.1 (standardFixedValues M₁ hvalid₁.2.2.2) (standardFixedValues M₂ hvalid₂.2.2.2) (standardFixedValues_heq M₁ M₂ (congrArg SWIGGraph.fixed hsg) hvalid₁.2.2.2) (doObsKernelYMarginal_heq_of_obsKernel_heq_rec X Y G ref href _hID M₁ M₂ _hsg₁ _hsg₂ _hdom₁ _hdom₂ hpos₁ hpos₂ _hobs hvalid₁ hvalid₂)
theorem id_sound_rec reviewed
Causalean.SCM.ID

Soundness of the full recursive ID algorithm for finite discrete-positive models. Fix an intervention target set X, an outcome node set Y, a SWIG graph G, and a reference-measure family ref that is faithful to the graph. Then whenever the full recursive Tian–Shpitser IDENTIFY certificate succeeds for X, Y on G, the interventional query mapping X to Y is identifiable within the class of models dominated by ref with discretely positive observational kernels: any two such models that share graph G and observational kernel agree on the query. This generalizes id_sound from the no-fixing fragment to the full Tian-Shpitser IDENTIFY recursion; see the module docstring for the proof architecture.

Formal statement
∀ n, StandardBorelSpace (Ω n)
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
X :
Y :
G :
href :
idSucceedsRec X Y G → IdentifiableUnder (Ω := Ω) G (fun _ => True) (fun M => DominatedObs M ref ∧ DiscreteID.DiscretePositive M) (interventionalQuery (Ω := Ω) X Y)
Proof (Lean source)
theorem id_sound_rec [∀ n, StandardBorelSpace (Ω n)] [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (X : Finset N) (Y : Finset (SWIGNode N)) (G : SWIGGraph N) (ref : ReferenceMeasures Ω) (href : ReferenceFaithful ref) : idSucceedsRec X Y G → IdentifiableUnder (Ω := Ω) G (fun _ => True) (fun M => DominatedObs M ref ∧ DiscreteID.DiscretePositive M) (interventionalQuery (Ω := Ω) X Y) := by classical intro hID M₁ M₂ hsg₁ hsg₂ _ _ hM₁ hM₂ hobs have hvalid_iff : interventionalQueryValid X Y M₁ ↔ interventionalQueryValid X Y M₂ := interventionalQueryValid_iff_of_toSWIGGraph_eq (Ω := Ω) X Y M₁ M₂ (hsg₁.trans hsg₂.symm) by_cases hvalid₁ : interventionalQueryValid X Y M₁ · have hvalid₂ : interventionalQueryValid X Y M₂ := hvalid_iff.mp hvalid₁ rw [interventionalQuery_eq_doKernelY_of_valid (Ω := Ω) X Y M₁ hvalid₁, interventionalQuery_eq_doKernelY_of_valid (Ω := Ω) X Y M₂ hvalid₂] exact doKernelY_eq_cfactor_decomposition_rec (Ω := Ω) X Y G ref href hID M₁ M₂ hsg₁ hsg₂ hM₁.1 hM₂.1 hM₁.2 hM₂.2 hobs hvalid₁ hvalid₂ · have hvalid₂ : ¬ interventionalQueryValid X Y M₂ := by intro h exact hvalid₁ (hvalid_iff.mpr h) rw [interventionalQuery_eq_default_of_not_valid (Ω := Ω) X Y M₁ hvalid₁, interventionalQuery_eq_default_of_not_valid (Ω := Ω) X Y M₂ hvalid₂]
theorem id_sound_rec_discrete reviewed
Causalean.SCM.ID

Discrete soundness of the full recursive ID algorithm (on-contract). For an intervention target set X, an outcome node set Y, and a SWIG graph G, if the full recursive Tian–Shpitser IDENTIFY certificate succeeds for X, Y on G, then the interventional query mapping X to Y is identifiable within the standard discrete positive model class. Obtained from id_sound_rec at the counting reference by collapsing DominatedObs · countingRef to StandardDiscretePositive, exactly as id_sound_discrete is obtained from id_sound. This subsumes id_sound_discrete (via idSucceeds_toRec).

Formal statement
∀ n, StandardBorelSpace (Ω n)
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
X :
Y :
G :
h :
Proof (Lean source)
theorem id_sound_rec_discrete [∀ n, StandardBorelSpace (Ω n)] [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (X : Finset N) (Y : Finset (SWIGNode N)) (G : SWIGGraph N) (h : idSucceedsRec X Y G) : IdentifiableUnder G (fun _ => True) StandardDiscretePositive (interventionalQuery (Ω := Ω) X Y) := by have hdom := id_sound_rec X Y G (countingRef (Ω := Ω)) referenceFaithful_countingRef h exact identifiableUnder_mono G (fun _ => True) (fun _ => True) (fun M => DominatedObs M (countingRef (Ω := Ω)) ∧ DiscretePositive M) StandardDiscretePositive (interventionalQuery (Ω := Ω) X Y) (fun _ h => h) (fun M hM => ⟨dominatedObs_countingRef M, hM.2⟩) hdom
7 supporting declarations (lemmas, instances)
IDSound­Discrete 1 core · 0 supporting GraphicalThms.IDAlgorithm.id_sound concludes over the model class fun M => DominatedObs M ref ∧ DiscretePositive M, parameterised by an arbitrary faithful reference family. ★ id_sound_discrete

On-contract discrete soundness of the graphical ID assembly

GraphicalThms.IDAlgorithm.id_sound concludes over the model class fun M => DominatedObs M ref ∧ DiscretePositive M, parameterised by an arbitrary faithful reference family. Instantiating that reference at the counting measure and using that the counting reference dominates every model (dominatedObs_countingRef), the model class collapses to the frozen discrete-positive class StandardDiscretePositive with no graph side conditions — this is the discrete identification headline the checker soundness theorem will wrap.

theorem id_sound_discrete reviewed
Causalean.SCM.ID

Discrete soundness of the ID assembly for the no-additional-fixing (full-district) fragment (on-contract). For treatment nodes X, outcome nodes Y, and a SWIG graph G, a successful idSucceeds certificate implies that the interventional query is identified from the observational distribution within the standard discrete positive model class.

Formal statement
∀ n, StandardBorelSpace (Ω n)
∀ n, Nonempty (Ω n)
∀ n, Fintype (Ω n)
X :
Y :
G :
h :
Proof (Lean source)
theorem id_sound_discrete [∀ n, StandardBorelSpace (Ω n)] [∀ n, Nonempty (Ω n)] [∀ n, Fintype (Ω n)] [∀ n, MeasurableSingletonClass (Ω n)] (X : Finset N) (Y : Finset (SWIGNode N)) (G : SWIGGraph N) (h : idSucceeds X Y G) : IdentifiableUnder G (fun _ => True) StandardDiscretePositive (interventionalQuery (Ω := Ω) X Y) := by have hdom := id_sound X Y G (countingRef (Ω := Ω)) referenceFaithful_countingRef h exact identifiableUnder_mono G (fun _ => True) (fun _ => True) (fun M => DominatedObs M (countingRef (Ω := Ω)) ∧ DiscretePositive M) StandardDiscretePositive (interventionalQuery (Ω := Ω) X Y) (fun _ h => h) (fun M hM => ⟨dominatedObs_countingRef M, hM.2⟩) hdom
Induced­Subgraph 5 core · 7 supporting This file provides graph-level utilities for restricting a SWIG to selected observed nodes in graphical identification arguments. ★ properDescIn_union_nonDescIn_eq_erase

Induced Subgraphs for Identification

This file provides graph-level utilities for restricting a SWIG to selected observed nodes in graphical identification arguments. It defines SWIGGraph.isAncestrallyClosed, the InducedFrom abbreviation for G.induce R, and the descendant/non-descendant sets properDescIn and nonDescIn used in Tian-style fixing arguments, together with their basic disjointness and coverage lemmas.

def isAncestrallyClosed reviewed
Causalean.SWIGGraph

A graph is ancestrally closed when every observed parent of an observed node is also observed.

Definition (Lean source)
def isAncestrallyClosed : Prop := ∀ v ∈ G.observed, ∀ u ∈ G.dag.parents v, (∃ n : N, u = SWIGNode.random n) → u ∈ G.observed
Causalean.SWIGGraph.isAncestrallyClosed · Causalean/SCM/ID/GraphicalThms/InducedSubgraph.lean:46 · uses SWIGGraph
abbrev InducedFrom reviewed
Causalean

The induced subgraph restricts a SWIG graph to the selected observed nodes.

Definition (Lean source)
abbrev InducedFrom (G : SWIGGraph N) (R : Finset (SWIGNode N)) : SWIGGraph N := G.induce R
def properDescIn reviewed
Causalean.SWIGGraph

This set contains the proper descendants of a node inside an induced SWIG subgraph.

Definition (Lean source)
def properDescIn (R : Finset (SWIGNode N)) (v₀ : SWIGNode N) : Finset (SWIGNode N) := (G.induce R).dag.descendants v₀
def nonDescIn reviewed
Causalean.SWIGGraph

This set contains selected nodes excluding the target and its proper descendants.

Definition (Lean source)
def nonDescIn (R : Finset (SWIGNode N)) (v₀ : SWIGNode N) : Finset (SWIGNode N) := (R.erase v₀) \ (G.induce R).dag.descendants v₀
lemma properDescIn_union_nonDescIn_eq_erase reviewed
Causalean.SWIGGraph

Within a selected node set R of a SWIG graph G, the proper descendants of a node v₀ together with its non-descendants exhaust the selected nodes other than v₀ itself.

Formal statement
G :
R :
v₀ :
G.properDescIn R v₀ ∪ G.nonDescIn R v₀ = R.erase v₀
Proof (Lean source)
lemma properDescIn_union_nonDescIn_eq_erase (G : SWIGGraph N) (R : Finset (SWIGNode N)) (v₀ : SWIGNode N) : G.properDescIn R v₀ ∪ G.nonDescIn R v₀ = R.erase v₀ := by ext x simp only [mem_union, Finset.mem_erase, properDescIn, nonDescIn, DAG.mem_descendants, mem_sdiff] constructor · -- (⊆): both parts are subsets of R.erase v₀ intro hx rcases hx with hx | ⟨⟨hne, hxR⟩, _⟩ · exact ⟨fun heq => DAG.isAncestor_irrefl _ v₀ (heq ▸ hx), (Finset.mem_inter.mp (G.induce_isAncestor_mem_R R hx)).1⟩ · exact ⟨hne, hxR⟩ · -- (⊇): x ∈ R.erase v₀ → in properDescIn or nonDescIn intro ⟨hne, hxR⟩ by_cases hdesc : (G.induce R).dag.isAncestor v₀ x · left; exact hdesc · right exact ⟨⟨hne, hxR⟩, hdesc⟩
7 supporting declarations (lemmas, instances)
QFactor­Identity 6 core · 3 supporting This file proves the structural identities behind district-based identification in the Tian-Pearl style. ★ q_factor_identity★ district_id

Q-Factor Identity

This file proves the structural identities behind district-based identification in the Tian-Pearl style. The main results are the marginal fixing helper q_factor_marginal_fixing, Tian's conditional q_factor_identity, the intervention-order simplification intervention_target_simp, and the full-SCM district specialization district_id. These relate c-component factors, induced subgraphs, and post-fixing kernels so later ID soundness proofs can reuse a common theorem frame.

def QFactorMarginalFixingConclusion reviewed
Causalean.SCM.ID

The proven marginal fixing helper behind Tian's fixing lemma.

Definition (Lean source)
def QFactorMarginalFixingConclusion (M : SCM N Ω) (R : Finset (SWIGNode N)) (T : Finset (SWIGNode N)) (Wn : Finset N) : Prop := ∀ (hR_ac : M.isAncestrallyClosedSCM R) (hT_induce : T ⊆ (M.induce R hR_ac).observed) (_hWn_obs : ∀ D ∈ Wn, SWIGNode.random D ∈ M.observed) (_hWn_fixed : ∀ D ∈ Wn, SWIGNode.fixed D ∉ M.fixed) (_hNoDesc : ∀ z ∈ Wn, ∀ v ∈ T, ¬ (M.fixSet Wn _hWn_obs _hWn_fixed).dag.isAncestor (SWIGNode.fixed z) v) (s' : (M.fixSet Wn _hWn_obs _hWn_fixed).FixedValues), ((M.fixSet Wn _hWn_obs _hWn_fixed).obsKernel s').map (valuesProjection ((fixSet_observed M Wn _hWn_obs _hWn_fixed).symm ▸ (show T ⊆ M.observed from fun v hv => (Finset.mem_inter.mp (show v ∈ R ∩ M.observed from hT_induce hv)).2))) = ((M.induce R hR_ac).obsKernel (valuesProjection (filter_subset _ _) (M.fixSetProj Wn _hWn_obs _hWn_fixed s'))).map (valuesProjection hT_induce)
Causalean.SCM.ID.QFactorMarginalFixingConclusion · Causalean/SCM/ID/GraphicalThms/QFactorIdentity.lean:69 · uses SCM , SWIGNode
def QFactorIdentityConclusion reviewed
Causalean.SCM.ID

The conditional conclusion of Tian's fixing lemma (Prop 2.19).

Definition (Lean source)
def QFactorIdentityConclusion (M : SCM N Ω) (R : Finset (SWIGNode N)) (T : Finset (SWIGNode N)) (Wn : Finset N) : Prop := ∀ (hR_ac : M.isAncestrallyClosedSCM R) (hT_induce : T ⊆ (M.induce R hR_ac).observed) (_hWn_obs : ∀ D ∈ Wn, SWIGNode.random D ∈ M.observed) (_hWn_fixed : ∀ D ∈ Wn, SWIGNode.fixed D ∉ M.fixed) (_hNoDesc : ∀ z ∈ Wn, ∀ v ∈ T ∪ (M.induce R hR_ac).toSWIGGraph.qFactorParents T, ¬ (M.fixSet Wn _hWn_obs _hWn_fixed).dag.isAncestor (SWIGNode.fixed z) v), let MI : SCM N Ω := M.induce R hR_ac let Mdo : SCM N Ω := M.fixSet Wn _hWn_obs _hWn_fixed let P : Finset (SWIGNode N) := MI.toSWIGGraph.qFactorParents T ∀ [StandardBorelSpace (ValuesOn T (swigΩ Ω))] [Nonempty (ValuesOn T (swigΩ Ω))] [∀ sI : MI.FixedValues, IsFiniteMeasure (MI.obsKernel sI)] [∀ sD : Mdo.FixedValues, IsFiniteMeasure (Mdo.obsKernel sD)] [CountableOrCountablyGenerated MI.FixedValues (ValuesOn P (swigΩ Ω))] [CountableOrCountablyGenerated Mdo.FixedValues (ValuesOn P (swigΩ Ω))] (s' : Mdo.FixedValues), let sInduce : MI.FixedValues := valuesProjection (filter_subset _ _) (M.fixSetProj Wn _hWn_obs _hWn_fixed s') ∀ᵐ c ∂((MI.obsKernel sInduce).map (valuesProjection (MI.toSWIGGraph.qFactorParents_subset_observed T))), (MI.qFactor T hT_induce sInduce) c = (((Mdo.obsCondKernel T P (show T ⊆ Mdo.observed from by intro v hv have hvM : v ∈ M.observed := by exact (Finset.mem_inter.mp (show v ∈ R ∩ M.observed from hT_induce hv)).2 simpa [Mdo, fixSet_observed] using hvM) (show P ⊆ Mdo.observed from by intro v hv have hvMI : v ∈ MI.observed := MI.toSWIGGraph.qFactorParents_subset_observed T hv have hvM : v ∈ M.observed := by exact (Finset.mem_inter.mp (show v ∈ R ∩ M.observed from hvMI)).2 simpa [Mdo, fixSet_observed] using hvM)).comap (fun c => (s', c)) (prodMk measurable_const measurable_id)) c)
Causalean.SCM.ID.QFactorIdentityConclusion · Causalean/SCM/ID/GraphicalThms/QFactorIdentity.lean:106 · uses SCM , SWIGNode
theorem q_factor_identity reviewed
Causalean.SCM.ID

Proposition 2.19 (Q-factor identity / Tian's lemma). For an ancestrally-closed node set R and a c-component T of the induced subgraph on R in a structural causal model M, after intervening on a node set Wn, the structurally-defined c-factor on T equals, almost everywhere, the conditional of T given its q-factor parents extracted from that intervention. See QFactorIdentityConclusion for the precise hypothesis frame.

Formal statement
M :
SCM N Ω
R :
T :
Wn :
Proof (Lean source)
theorem q_factor_identity (M : SCM N Ω) (R : Finset (SWIGNode N)) (T : Finset (SWIGNode N)) (Wn : Finset N) : QFactorIdentityConclusion M R T Wn := by classical intro hR_ac hT_induce hWn_obs hWn_fixed hNoDesc dsimp only intro _ _ _ _ _ _ s' -- The conditional-kernel uniqueness argument first proves the joint identity on -- `T ∪ qFactorParents T` by combining the marginal helper with Rule 3 at that -- larger target, then applies `Kernel.disintegrate`/`condKernel` uniqueness to -- identify the two conditional kernels a.e. under the common parent marginal. have hMarginal : QFactorMarginalFixingConclusion M R T Wn := q_factor_marginal_fixing M R T Wn have _hT_marginal := hMarginal hR_ac hT_induce hWn_obs hWn_fixed (by intro z hz v hv exact hNoDesc z hz v (Finset.mem_union_left _ hv)) s' let MI : SCM N Ω := M.induce R hR_ac let Mdo : SCM N Ω := M.fixSet Wn hWn_obs hWn_fixed let P : Finset (SWIGNode N) := MI.toSWIGGraph.qFactorParents T let sInduce : MI.FixedValues := valuesProjection (filter_subset _ _) (M.fixSetProj Wn hWn_obs hWn_fixed s') have hP_induce : P ⊆ MI.observed := by simpa [P, MI] using (MI.toSWIGGraph.qFactorParents_subset_observed T) have hT_base : T ⊆ M.observed := by intro v hv exact (Finset.mem_inter.mp (show v ∈ R ∩ M.observed from hT_induce hv)).2 have hP_base : P ⊆ M.observed := by intro v hv have hvMI : v ∈ MI.observed := hP_induce hv exact (Finset.mem_inter.mp (show v ∈ R ∩ M.observed from hvMI)).2 have hT_do : T ⊆ Mdo.observed := by simpa [Mdo, fixSet_observed] using hT_base have hP_do : P ⊆ Mdo.observed := by simpa [Mdo, fixSet_observed] using hP_base let U : Finset (SWIGNode N) := T ∪ P have hU_induce : U ⊆ MI.observed := by intro v hv rcases Finset.mem_union.mp hv with hvT | hvP · exact hT_induce hvT · exact hP_induce hvP have hU_base : U ⊆ M.observed := by intro v hv rcases Finset.mem_union.mp hv with hvT | hvP · exact hT_base hvT · exact hP_base hvP have hU_do : U ⊆ Mdo.observed := by simpa [Mdo, fixSet_observed] using hU_base have hMI_obs_base : MI.observed ⊆ M.observed := by exact Finset.inter_subset_right have hRule3U : (Mdo.obsKernel s').map (valuesProjection hU_do) = (M.obsKernel (M.fixSetProj Wn hWn_obs hWn_fixed s')).map (valuesProjection hU_base) := by simpa [Mdo, U] using condDistrib_intervention_ancestral_eq M Wn hWn_obs hWn_fixed U hU_base (by intro z hz v hv exact hNoDesc z hz v (by simpa [U, P, MI] using hv)) s' have hInduced : MI.obsKernel sInduce = (M.obsKernel (M.fixSetProj Wn hWn_obs hWn_fixed s')).map (valuesProjection hMI_obs_base) := by simpa [MI, sInduce] using induce_marginal_compat M R hR_ac (M.fixSetProj Wn hWn_obs hWn_fixed s') have hJointU : (Mdo.obsKernel s').map (valuesProjection hU_do) = (MI.obsKernel sInduce).map (valuesProjection hU_induce) := by rw [hRule3U, hInduced] rw [MeasureTheory.Measure.map_map (measurable_valuesProjection hU_induce) (measurable_valuesProjection hMI_obs_base)] rw [← valuesProjection_comp hU_induce hMI_obs_base] have hP_U : P ⊆ U := by intro v hv exact Finset.mem_union_right T hv have hT_U : T ⊆ U := by intro v hv exact Finset.mem_union_left P hv let pairU : ValuesOn U (swigΩ Ω) → ValuesOn P (swigΩ Ω) × ValuesOn T (swigΩ Ω) := fun ω => (valuesProjection hP_U ω, valuesProjection hT_U ω) have hpairU_meas : Measurable pairU := by exact (measurable_valuesProjection hP_U).prodMk (measurable_valuesProjection hT_U) have hPair_do_comp : pairU ∘ valuesProjection hU_do = (fun ω : Mdo.ObservedValues => (valuesProjection hP_do ω, valuesProjection hT_do ω)) := by funext ω apply Prod.ext · exact congrFun (valuesProjection_comp hP_U hU_do).symm ω · exact congrFun (valuesProjection_comp hT_U hU_do).symm ω have hPair_induce_comp : pairU ∘ valuesProjection hU_induce = (fun ω : MI.ObservedValues => (valuesProjection hP_induce ω, valuesProjection hT_induce ω)) := by funext ω apply Prod.ext · exact congrFun (valuesProjection_comp hP_U hU_induce).symm ω · exact congrFun (valuesProjection_comp hT_U hU_induce).symm ω have hPairMeasure : MI.obsCondPairKernel T P hT_induce hP_induce sInduce = Mdo.obsCondPairKernel T P hT_do hP_do s' := by unfold SCM.obsCondPairKernel rw [ProbabilityTheory.Kernel.map_apply _ ((measurable_valuesProjection hP_induce).prodMk (measurable_valuesProjection hT_induce))] rw [ProbabilityTheory.Kernel.map_apply _ ((measurable_valuesProjection hP_do).prodMk (measurable_valuesProjection hT_do))] rw [← hPair_induce_comp, ← hPair_do_comp] rw [← MeasureTheory.Measure.map_map hpairU_meas (measurable_valuesProjection hU_induce)] rw [← MeasureTheory.Measure.map_map hpairU_meas (measurable_valuesProjection hU_do)] exact congrArg (map pairU) hJointU.symm have hAE := obsCondKernel_slice_ae_eq_of_pairMeasure_eq MI Mdo T P hT_induce hP_induce hT_do hP_do sInduce s' hPairMeasure exact hAE
def InterventionTargetSimpConclusion reviewed
Causalean.SCM.ID

The conclusion of fact4 (intervention target simplification), stated as a structural equivalence of gSCMs.

Definition (Lean source)
def InterventionTargetSimpConclusion (M : SCM N Ω) (Dn Yn : Finset N) : Prop := ∀ (hD_obs : ∀ D ∈ Dn, SWIGNode.random D ∈ M.observed) (hD_fixed : ∀ D ∈ Dn, SWIGNode.fixed D ∉ M.fixed) (hY_obs : ∀ D ∈ Yn, SWIGNode.random D ∈ (M.fixSet Dn hD_obs hD_fixed).observed) (hY_fixed : ∀ D ∈ Yn, SWIGNode.fixed D ∉ (M.fixSet Dn hD_obs hD_fixed).fixed) (hUnion_obs : ∀ D ∈ Dn ∪ Yn, SWIGNode.random D ∈ M.observed) (hUnion_fixed : ∀ D ∈ Dn ∪ Yn, SWIGNode.fixed D ∉ M.fixed) (_hDY_disjoint : Disjoint Dn Yn), SCM.Equiv ((M.fixSet Dn hD_obs hD_fixed).fixSet Yn hY_obs hY_fixed) (M.fixSet (Dn ∪ Yn) hUnion_obs hUnion_fixed)
Causalean.SCM.ID.InterventionTargetSimpConclusion · Causalean/SCM/ID/GraphicalThms/QFactorIdentity.lean:435 · uses SCM
def DistrictIdConclusion reviewed
Causalean.SCM.ID

The conclusion of district identification: for T ∈ C(G), the c-factor Q[T] of the full SCM equals a.e. the matching do-side conditional after fixing Wn. Special case R = M.observed of QFactorIdentityConclusion.

Definition (Lean source)
def DistrictIdConclusion (M : SCM N Ω) (T : Finset (SWIGNode N)) (Wn : Finset N) : Prop := QFactorIdentityConclusion M M.observed T Wn
Causalean.SCM.ID.DistrictIdConclusion · Causalean/SCM/ID/GraphicalThms/QFactorIdentity.lean:622 · uses SCM , SWIGNode
theorem district_id reviewed
Causalean.SCM.ID

Corollary (District identification). For a structural causal model M, a c-component T of M's full graph, and an intervention set Wn, the c-factor of T equals, almost everywhere, the observational conditional obtained by intervening on Wn.

Formal statement
M :
SCM N Ω
T :
Wn :
Proof (Lean source)
theorem district_id (M : SCM N Ω) (T : Finset (SWIGNode N)) (Wn : Finset N) : DistrictIdConclusion M T Wn := q_factor_identity M M.observed T Wn
3 supporting declarations (lemmas, instances)
  • q_factor_marginal_fixing theorem — Marginal fixing form of Tian's Q-factor identity.
    M :
    SCM N Ω
    R :
    T :
    Wn :
    Proof (Lean source)
    theorem q_factor_marginal_fixing (M : SCM N Ω) (R : Finset (SWIGNode N)) (T : Finset (SWIGNode N)) (Wn : Finset N) : QFactorMarginalFixingConclusion M R T Wn := by classical intro hR_ac hT_induce hWn_obs hWn_fixed hNoDesc s' let sTilde : M.FixedValues := M.fixSetProj Wn hWn_obs hWn_fixed s' let MI : SCM N Ω := M.induce R hR_ac have hT_base : T ⊆ M.observed := by intro v hv exact (Finset.mem_inter.mp (show v ∈ R ∩ M.observed from hT_induce hv)).2 have hMI_obs_base : MI.observed ⊆ M.observed := by exact Finset.inter_subset_right have hRule3 : ((M.fixSet Wn hWn_obs hWn_fixed).obsKernel s').map (valuesProjection ((fixSet_observed M Wn hWn_obs hWn_fixed).symm ▸ hT_base)) = (M.obsKernel sTilde).map (valuesProjection hT_base) := by simpa [sTilde] using condDistrib_intervention_ancestral_eq M Wn hWn_obs hWn_fixed T hT_base hNoDesc s' have hInduced : MI.obsKernel (valuesProjection (filter_subset _ _) sTilde) = (M.obsKernel sTilde).map (valuesProjection hMI_obs_base) := by simpa [MI] using induce_marginal_compat M R hR_ac sTilde rw [hRule3, hInduced] rw [MeasureTheory.Measure.map_map (measurable_valuesProjection hT_induce) (measurable_valuesProjection hMI_obs_base)] rw [← valuesProjection_comp hT_induce hMI_obs_base]
    Causalean.SCM.ID.q_factor_marginal_fixing · Causalean/SCM/ID/GraphicalThms/QFactorIdentity.lean:162
  • obsCondKernel_slice_ae_eq_of_pairMeasure_eq theorem — Equal pair laws give equal conditional-kernel slices a.e.
    M₁ M₂ :
    SCM N Ω
    Y CC :
    hY₁ :
    Y ⊆ M₁.observed
    hCC₁ :
    CC ⊆ M₁.observed
    hY₂ :
    Y ⊆ M₂.observed
    hCC₂ :
    CC ⊆ M₂.observed
    Nonempty (ValuesOn Y (swigΩ Ω))
    ∀ s :
    M₁.FixedValues, IsFiniteMeasure (M₁.obsKernel s)
    M₂.FixedValues, IsFiniteMeasure (M₂.obsKernel s)
    CountableOrCountablyGenerated M₁.FixedValues (ValuesOn CC (swigΩ Ω))
    CountableOrCountablyGenerated M₂.FixedValues (ValuesOn CC (swigΩ Ω))
    s₁ :
    M₁.FixedValues
    s₂ :
    M₂.FixedValues
    hPair :
    M₁.obsCondPairKernel Y CC hY₁ hCC₁ s₁ = M₂.obsCondPairKernel Y CC hY₂ hCC₂ s₂
    (fun c => (M₁.obsCondKernel Y CC hY₁ hCC₁).sectR s₁ c)
    =ᵐ[(M₁.obsKernel s₁).map (valuesProjection hCC₁)] fun c => (M₂.obsCondKernel Y CC hY₂ hCC₂).sectR s₂ c
    Proof (Lean source)
    theorem obsCondKernel_slice_ae_eq_of_pairMeasure_eq (M₁ M₂ : SCM N Ω) (Y CC : Finset (SWIGNode N)) (hY₁ : Y ⊆ M₁.observed) (hCC₁ : CC ⊆ M₁.observed) (hY₂ : Y ⊆ M₂.observed) (hCC₂ : CC ⊆ M₂.observed) [StandardBorelSpace (ValuesOn Y (swigΩ Ω))] [Nonempty (ValuesOn Y (swigΩ Ω))] [∀ s : M₁.FixedValues, IsFiniteMeasure (M₁.obsKernel s)] [∀ s : M₂.FixedValues, IsFiniteMeasure (M₂.obsKernel s)] [CountableOrCountablyGenerated M₁.FixedValues (ValuesOn CC (swigΩ Ω))] [CountableOrCountablyGenerated M₂.FixedValues (ValuesOn CC (swigΩ Ω))] (s₁ : M₁.FixedValues) (s₂ : M₂.FixedValues) (hPair : M₁.obsCondPairKernel Y CC hY₁ hCC₁ s₁ = M₂.obsCondPairKernel Y CC hY₂ hCC₂ s₂) : (fun c => (M₁.obsCondKernel Y CC hY₁ hCC₁).sectR s₁ c) =ᵐ[(M₁.obsKernel s₁).map (valuesProjection hCC₁)] fun c => (M₂.obsCondKernel Y CC hY₂ hCC₂).sectR s₂ c := by classical let μ₁ : Measure (ValuesOn CC (swigΩ Ω)) := (M₁.obsKernel s₁).map (valuesProjection hCC₁) let μ₂ : Measure (ValuesOn CC (swigΩ Ω)) := (M₂.obsKernel s₂).map (valuesProjection hCC₂) let κ₁ : Kernel (ValuesOn CC (swigΩ Ω)) (ValuesOn Y (swigΩ Ω)) := (M₁.obsCondKernel Y CC hY₁ hCC₁).sectR s₁ let κ₂ : Kernel (ValuesOn CC (swigΩ Ω)) (ValuesOn Y (swigΩ Ω)) := (M₂.obsCondKernel Y CC hY₂ hCC₂).sectR s₂ haveI : IsMarkovKernel (M₁.obsCondKernel Y CC hY₁ hCC₁) := by unfold SCM.obsCondKernel infer_instance haveI : IsMarkovKernel (M₂.obsCondKernel Y CC hY₂ hCC₂) := by unfold SCM.obsCondKernel infer_instance haveI : IsMarkovKernel κ₁ := by dsimp [κ₁] infer_instance haveI : IsMarkovKernel κ₂ := by dsimp [κ₂] infer_instance have h₁ : M₁.obsCondPairKernel Y CC hY₁ hCC₁ s₁ = μ₁ ⊗ₘ κ₁ := by simpa [μ₁, κ₁] using SCM.obsCondPairKernel_apply_eq_compProd M₁ Y CC hY₁ hCC₁ s₁ have h₂ : M₂.obsCondPairKernel Y CC hY₂ hCC₂ s₂ = μ₂ ⊗ₘ κ₂ := by simpa [μ₂, κ₂] using SCM.obsCondPairKernel_apply_eq_compProd M₂ Y CC hY₂ hCC₂ s₂ have hComp : μ₁ ⊗ₘ κ₁ = μ₂ ⊗ₘ κ₂ := by rw [← h₁, ← h₂] exact hPair have hμ : μ₁ = μ₂ := by have hfst := congrArg fst hComp simpa [MeasureTheory.Measure.fst_compProd] using hfst have hComp' : μ₁ ⊗ₘ κ₁ = μ₁ ⊗ₘ κ₂ := by simpa [hμ] using hComp exact ProbabilityTheory.Kernel.ae_eq_of_compProd_eq hComp'
    Causalean.SCM.ID.obsCondKernel_slice_ae_eq_of_pairMeasure_eq · Causalean/SCM/ID/GraphicalThms/QFactorIdentity.lean:206
  • intervention_target_simp theorem — Proposition (fact4 — intervention target simplification).
    M :
    SCM N Ω
    Dn Yn :
    Proof (Lean source)
    theorem intervention_target_simp (M : SCM N Ω) (Dn Yn : Finset N) : InterventionTargetSimpConclusion M Dn Yn := by classical refine Finset.induction_on Yn ?_ ?_ · intro hD_obs hD_fixed hY_obs hY_fixed hUnion_obs hUnion_fixed _hDY_disjoint have hEmpty : SCM.Equiv ((M.fixSet Dn hD_obs hD_fixed).fixSet ∅ hY_obs hY_fixed) (M.fixSet Dn hD_obs hD_fixed) := fixSet_empty_equiv (M.fixSet Dn hD_obs hD_fixed) have hRhs : SCM.Equiv (M.fixSet Dn hD_obs hD_fixed) (M.fixSet (Dn ∪ ∅) hUnion_obs hUnion_fixed) := by simpa [union_empty] using fixSet_equiv_congr (SCM.Equiv.refl M) Dn hD_obs hD_fixed exact SCM.Equiv.trans hEmpty hRhs · intro y Ys hyYs ih hD_obs hD_fixed hY_obs hY_fixed hUnion_obs hUnion_fixed hDY_disjoint let M₀ : SCM N Ω := M.fixSet Dn hD_obs hD_fixed have hYs_obs : ∀ D ∈ Ys, SWIGNode.random D ∈ M₀.observed := by intro D hD exact hY_obs D (mem_insert_of_mem hD) have hYs_fixed : ∀ D ∈ Ys, SWIGNode.fixed D ∉ M₀.fixed := by intro D hD exact hY_fixed D (mem_insert_of_mem hD) have hUnionYs_obs : ∀ D ∈ Dn ∪ Ys, SWIGNode.random D ∈ M.observed := by intro D hD exact hUnion_obs D (by rcases Finset.mem_union.mp hD with hD | hD · exact mem_union_left _ hD · exact mem_union_right _ (mem_insert_of_mem hD)) have hUnionYs_fixed : ∀ D ∈ Dn ∪ Ys, SWIGNode.fixed D ∉ M.fixed := by intro D hD exact hUnion_fixed D (by rcases Finset.mem_union.mp hD with hD | hD · exact mem_union_left _ hD · exact mem_union_right _ (mem_insert_of_mem hD)) have hDYs_disjoint : Disjoint Dn Ys := by exact hDY_disjoint.mono_right (by intro D hD; exact mem_insert_of_mem hD) have hyDn : y ∉ Dn := by intro hyD have hyMeet : y ∈ Dn ∩ insert y Ys := Finset.mem_inter.mpr ⟨hyD, Finset.mem_insert_self y Ys⟩ have hyBot : y ∈ (⊥ : Finset N) := hDY_disjoint.le_bot hyMeet simp at hyBot have hIH : SCM.Equiv (M₀.fixSet Ys hYs_obs hYs_fixed) (M.fixSet (Dn ∪ Ys) hUnionYs_obs hUnionYs_fixed) := ih hD_obs hD_fixed hYs_obs hYs_fixed hUnionYs_obs hUnionYs_fixed hDYs_disjoint have hy_single_obs₀ : ∀ D ∈ ({y} : Finset N), SWIGNode.random D ∈ (M₀.fixSet Ys hYs_obs hYs_fixed).observed := by intro D hD have hDy : D = y := by simpa using hD rw [hDy] simpa [M₀, fixSet_observed] using hY_obs y (Finset.mem_insert_self y Ys) have hy_single_fixed₀ : ∀ D ∈ ({y} : Finset N), SWIGNode.fixed D ∉ (M₀.fixSet Ys hYs_obs hYs_fixed).fixed := by intro D hD hmem have hDy : D = y := by simpa using hD rw [hDy] at hmem rw [fixSet_fixed] at hmem rcases Finset.mem_union.mp hmem with hM | hImg · exact hY_fixed y (Finset.mem_insert_self y Ys) hM · rcases Finset.mem_image.mp hImg with ⟨z, hz, hzy⟩ have hzy' : z = y := SWIGNode.fixed.inj hzy exact hyYs (by simpa [hzy'] using hz) have hStepL : SCM.Equiv (M₀.fixSet (insert y Ys) hY_obs hY_fixed) ((M₀.fixSet Ys hYs_obs hYs_fixed).fixSet ({y} : Finset N) hy_single_obs₀ hy_single_fixed₀) := (swigInterventionSet_insert_equiv M₀ Ys y hyYs hY_obs hY_fixed).symm have hy_single_obs₁ : ∀ D ∈ ({y} : Finset N), SWIGNode.random D ∈ (M.fixSet (Dn ∪ Ys) hUnionYs_obs hUnionYs_fixed).observed := by intro D hD have hDy : D = y := by simpa using hD rw [hDy] simpa [fixSet_observed] using hUnion_obs y (mem_union_right _ (Finset.mem_insert_self y Ys)) have hy_single_fixed₁ : ∀ D ∈ ({y} : Finset N), SWIGNode.fixed D ∉ (M.fixSet (Dn ∪ Ys) hUnionYs_obs hUnionYs_fixed).fixed := by intro D hD hmem have hDy : D = y := by simpa using hD rw [hDy] at hmem rw [fixSet_fixed] at hmem rcases Finset.mem_union.mp hmem with hM | hImg · exact hUnion_fixed y (mem_union_right _ (Finset.mem_insert_self y Ys)) hM · rcases Finset.mem_image.mp hImg with ⟨z, hz, hzy⟩ have hzy' : z = y := SWIGNode.fixed.inj hzy rcases Finset.mem_union.mp hz with hyD | hyY · exact hyDn (by simpa [hzy'] using hyD) · exact hyYs (by simpa [hzy'] using hyY) have hStepMid : SCM.Equiv ((M₀.fixSet Ys hYs_obs hYs_fixed).fixSet ({y} : Finset N) hy_single_obs₀ hy_single_fixed₀) ((M.fixSet (Dn ∪ Ys) hUnionYs_obs hUnionYs_fixed).fixSet ({y} : Finset N) hy_single_obs₁ hy_single_fixed₁) := fixSet_equiv_congr hIH ({y} : Finset N) hy_single_obs₀ hy_single_fixed₀ have hInsertUnion_obs : ∀ D ∈ insert y (Dn ∪ Ys), SWIGNode.random D ∈ M.observed := by intro D hD rcases Finset.mem_insert.mp hD with hEq | hD · rw [hEq] exact hUnion_obs y (mem_union_right _ (Finset.mem_insert_self y Ys)) · exact hUnion_obs D (by rcases Finset.mem_union.mp hD with hD | hD · exact mem_union_left _ hD · exact mem_union_right _ (mem_insert_of_mem hD)) have hInsertUnion_fixed : ∀ D ∈ insert y (Dn ∪ Ys), SWIGNode.fixed D ∉ M.fixed := by intro D hD rcases Finset.mem_insert.mp hD with hEq | hD · rw [hEq] exact hUnion_fixed y (mem_union_right _ (Finset.mem_insert_self y Ys)) · exact hUnion_fixed D (by rcases Finset.mem_union.mp hD with hD | hD · exact mem_union_left _ hD · exact mem_union_right _ (mem_insert_of_mem hD)) have hStepR : SCM.Equiv ((M.fixSet (Dn ∪ Ys) hUnionYs_obs hUnionYs_fixed).fixSet ({y} : Finset N) hy_single_obs₁ hy_single_fixed₁) (M.fixSet (insert y (Dn ∪ Ys)) hInsertUnion_obs hInsertUnion_fixed) := swigInterventionSet_insert_equiv M (Dn ∪ Ys) y (by intro hyUnion rcases Finset.mem_union.mp hyUnion with hyD | hyY · exact hyDn hyD · exact hyYs hyY) hInsertUnion_obs hInsertUnion_fixed have hAll := SCM.Equiv.trans hStepL (SCM.Equiv.trans hStepMid hStepR) simpa [M₀, Finset.insert_union, Finset.union_insert, union_assoc, union_comm, Finset.union_left_comm] using hAll
    Causalean.SCM.ID.intervention_target_simp · Causalean/SCM/ID/GraphicalThms/QFactorIdentity.lean:462