Causal inferenceChapter 13
Partial identification
Manski worst-case bounds, sharpness, and identified sets in a finite population.
Contents
When the observed data and assumptions do not determine a unique average treatment effect, the estimand is partially identified. Its identified set contains the effects of all populations consistent with the observations and the maintained assumptions.
This chapter derives Manski’s bounds for bounded outcomes. It distinguishes a valid outer bound from a sharp characterization of the identified set. A proof of sharpness must show that every value in the proposed interval is attained by some compatible population; proving only containment is insufficient.
The identified set is a Set ℝ
Two ingredients. First, what it means for a population to be compatible with what you observed:
def ConsistentWith (z : Assignment n) (y : Fin n → ℝ) (P : Population n) : Prop :=
Yobs P z = yYobs P z = y is an equality of functions Fin n → ℝ. There is no
probability here and no estimator: z is the assignment that was run, y is
the vector that came back, and ConsistentWith z y P says that P, run under
z, would have produced y exactly. Chapter 6 made the point that many
populations satisfy this; the arithmetic is that consistency constrains
Free, but not unconstrained, if you are willing to say something about the outcome’s range:
def Bounded (a b : ℝ) (P : Population n) : Prop :=
∀ i, a ≤ P.y1 i ∧ P.y1 i ≤ b ∧ a ≤ P.y0 i ∧ P.y0 i ≤ bRead Bounded slowly, because the quantifier is over P.y1 i and P.y0 i —
both potential outcomes, for every unit, including the one that was never
observed. That is what makes it an assumption rather than a description of the
sample. A bounded outcome is common enough (a proportion, a score on a fixed
scale, a duration censored at the end of follow-up), and it is exactly the kind
of claim a subject-matter expert can make without knowing anything about the
experiment.
Put the two together and you get the object of interest:
def identifiedSet (z : Assignment n) (y : Fin n → ℝ) (a b : ℝ) : Set ℝ :=
{ t | ∃ P : Population n, ConsistentWith z y P ∧ Bounded a b P ∧ P.tau = t }identifiedSet z y a b : Set ℝ. Not an estimator, not an interval, not a
number: a set of reals, defined by an existential. Point identification is the
special case in which the set happens to be a singleton, and the theorem below
says that with at least one unit and Bounded alone it never is, unless
One hypothesis will appear throughout, and it is about the data rather than the
population: InRange a b y, i.e. ∀ i, a ≤ y i ∧ y i ≤ b. It is not an extra
assumption smuggled in — it is a consequence of the others, and proving that
is the first exercise:
ExerciseIn-range data (warm-up)
If some bounded population is consistent with the data, the data themselves
are in range: InRange a b y.
theorem InRange.of_consistentWith {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ}
{P : Population n} (hcon : ConsistentWith z y P) (hb : Bounded a b P) :
InRange a b y := by
sorryHint
by_cases hi : i ∈ z splits on whether unit i was treated. In the treated
branch, hcon.y1_eq hi : P.y1 i = y i lets you rewrite the goal
a ≤ y i ∧ y i ≤ b into a statement about P.y1 i, which is the first half of
hb i; the control branch is the same with y0. Note the direction of the
rewrite: you want rw [← hcon.y1_eq hi], replacing y i by P.y1 i.
Show solution
theorem InRange.of_consistentWith {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ}
{P : Population n} (hcon : ConsistentWith z y P) (hb : Bounded a b P) :
InRange a b y := by
intro i
obtain ⟨h1, h2, h3, h4⟩ := hb i
by_cases hi : i ∈ z
· rw [← hcon.y1_eq hi]
exact ⟨h1, h2⟩
· rw [← hcon.y0_eq hi]
exact ⟨h3, h4⟩The reason to care: if the data are not in range, no consistent bounded
population exists and identifiedSet z y a b = ∅. The main theorem below would
then be equating the empty set with a non-empty interval, so InRange is
necessary rather than decorative. This distinction matters when the theorem
statement arrives — it is the first thing to check.
Manski’s worst-case bounds
Informally. Fix the data. For a treated unit you saw
Formally.
noncomputable def manskiLower (z : Assignment n) (y : Fin n → ℝ) (a b : ℝ) : ℝ :=
mean fun i => Z z i * (y i - b) + (1 - Z z i) * (a - y i)
noncomputable def manskiUpper (z : Assignment n) (y : Fin n → ℝ) (a b : ℝ) : ℝ :=
mean fun i => Z z i * (y i - a) + (1 - Z z i) * (b - y i)The definitions are written with the real indicator Z z i rather than an
if i ∈ z then … else …, for the reason given in chapter 6: indicator algebra
is ordinary field algebra, so ring closes almost every step below. The
case-split form is available as manskiLower_eq_mean_ite when you want to read
it as a statistician would.
Notice what the endpoints depend on: z, y, a, b. No design, no
population, no estimator. They are computable from the data by anybody who
accepts the range.
The easy half
Proposition (the bounds are bounds). Let
The mean is monotone, so it suffices to bound each unit’s effect below by the
corresponding summand of
Let
The upper bound is the mirror image, using the other two halves of the
boundedness assumption:
Notice which half of boundedness each inequality consumed: only the constraint on the outcome that was not observed. The observed one needs no assumption at all, because consistency has already pinned it down.∎
theorem manskiLower_le_tau {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ} {P : Population n}
(hcon : ConsistentWith z y P) (hb : Bounded a b P) : manskiLower z y a b ≤ P.tau := by
rw [manskiLower, Population.tau]
refine mean_le_mean fun i => ?_
obtain ⟨h1, _, _, h4⟩ := hb i
simp only [Population.effect]
by_cases hi : i ∈ z
· rw [Z_of_mem hi, hcon.y1_eq hi]
linarith
· rw [Z_of_not_mem hi, hcon.y0_eq hi]
linarith
theorem tau_le_manskiUpper {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ} {P : Population n}
(hcon : ConsistentWith z y P) (hb : Bounded a b P) : P.tau ≤ manskiUpper z y a b := by
rw [manskiUpper, Population.tau]
refine mean_le_mean fun i => ?_
obtain ⟨_, h2, h3, _⟩ := hb i
simp only [Population.effect]
by_cases hi : i ∈ z
· rw [Z_of_mem hi, hcon.y1_eq hi]
linarith
· rw [Z_of_not_mem hi, hcon.y0_eq hi]
linarithBoth theorems have the same nine-line shape; here is the lower one.
rw [manskiLower, Population.tau]Unfold both sides to the means they are.
Population.tauismean P.effectandmanskiLoweris the mean of the pointwise lower bound, so the goal is now an inequality between twomeans — the shape the monotonicity lemma wants.Goal⊢ (mean fun i => Z z i * (y i - b) + (1 - Z z i) * (a - y i)) ≤ mean P.effectrefine mean_le_mean fun i => ?_mean_le_meanis the monotonicity of the mean proved above: from∀ i, u i ≤ v iit concludesmean u ≤ mean v. Supplying its argument asfun i => ?_reduces the whole inequality to one arbitrary unit — the “unit by unit” of the informal proof.Goali : Fin n ⊢ Z z i * (y i - b) + (1 - Z z i) * (a - y i) ≤ P.effect iobtain ⟨h1, _, _, h4⟩ := hb iBounded a b Pis a four-fold conjunction at each unit. Destructuring it here names only the two components this branch needs —h1 : a ≤ P.y1 iandh4 : P.y0 i ≤ b— and discards the other two with underscores, which is the formal record of “only the unobserved half is used”. The followingsimp only [Population.effect]replacesP.effect ibyP.y1 i - P.y0 i.Goalh1 : a ≤ P.y1 i left✝¹ : P.y1 i ≤ b left✝ : a ≤ P.y0 i h4 : P.y0 i ≤ b ⊢ Z z i * (y i - b) + (1 - Z z i) * (a - y i) ≤ P.y1 i - P.y0 iby_cases hi : i ∈ zSplit on whether unit
iwas treated. This is the case distinction the informal proof makes, and it is the only case distinction in the file:Z z iis1in one branch and0in the other.rw [Z_of_mem hi, hcon.y1_eq hi]The treated branch.
Z_of_memrewrites the indicatorZ z ito1, andhcon.y1_eq hi : P.y1 i = y i— consistency at a treated unit — replaces the population’s treated outcome on the right by the observed number. Both sides now speak ofy iand the single unknownP.y0 i.Goalhi : i ∈ z ⊢ 1 * (y i - b) + (1 - 1) * (a - y i) ≤ y i - P.y0 ilinarithThe goal is linear in
y i,a,bandP.y0 i: after cancelling the(1 - 1)term it readsy i - b ≤ y i - P.y0 i, which follows fromh4 : P.y0 i ≤ b.linarithfinds that combination.rw [Z_of_not_mem hi, hcon.y0_eq hi]The control branch.
Z_of_not_memrewrites the indicator to0, andhcon.y0_eq hi : P.y0 i = y ireplaces the control outcome by the observed number. The goal reduces toa - y i ≤ P.y1 i - y i, and the closinglinarithgets it fromh1 : a ≤ P.y1 i.Goalhi : i ∉ z ⊢ 0 * (y i - b) + (1 - 0) * (a - y i) ≤ P.y1 i - y i
tau_le_manskiUpper is the same proof with the other two components of hb
named (obtain ⟨_, h2, h3, _⟩) and manskiUpper in place of manskiLower;
the two linarith calls then use P.y1 i ≤ b and a ≤ P.y0 i.
mean_le_mean is worth a look, because at n = 0 it is doing something quietly
sensible:
ExerciseMeans are monotone (core)
If u i ≤ v i for every unit then mean u ≤ mean v. Deliberately not
assuming 0 < n: at n = 0 both means are 0 / 0 = 0 and the inequality is
0 ≤ 0.
theorem mean_le_mean {u v : Fin n → ℝ} (h : ∀ i, u i ≤ v i) : mean u ≤ mean v := by
sorryHint
Two lemmas and no case analysis. Finset.sum_le_sum needs
∀ i ∈ Finset.univ, u i ≤ v i, which is fun i _ => h i; then
div_le_div_of_nonneg_right divides both sides by (n : ℝ), whose
non-negativity is Nat.cast_nonneg n. One exact.
Show solution
theorem mean_le_mean {u v : Fin n → ℝ} (h : ∀ i, u i ≤ v i) : mean u ≤ mean v := by
exact div_le_div_of_nonneg_right (Finset.sum_le_sum fun i _ => h i) (Nat.cast_nonneg n)From the pointwise bracket, one inclusion of the main theorem is two lines:
ExerciseThe bounds contain the identified set (core)
Every ATE in the identified set lies in the Manski interval — the easy inclusion of the main theorem.
theorem identifiedSet_subset_Icc (z : Assignment n) (y : Fin n → ℝ) (a b : ℝ) :
identifiedSet z y a b ⊆ Set.Icc (manskiLower z y a b) (manskiUpper z y a b) := by
sorryHint
rintro t ⟨P, hcon, hb, rfl⟩ does three things at once: it introduces t,
destructs the existential in identifiedSet, and — this is the rfl pattern —
uses P.tau = t to substitute P.tau for t everywhere. Membership in
Set.Icc unfolds definitionally to a conjunction of two inequalities, so the
anonymous constructor ⟨_, _⟩ closes the goal with manskiLower_le_tau and
tau_le_manskiUpper.
Show solution
theorem identifiedSet_subset_Icc (z : Assignment n) (y : Fin n → ℝ) (a b : ℝ) :
identifiedSet z y a b ⊆ Set.Icc (manskiLower z y a b) (manskiUpper z y a b) := by
rintro t ⟨P, hcon, hb, rfl⟩
exact ⟨manskiLower_le_tau hcon hb, tau_le_manskiUpper hcon hb⟩The hard half: sharpness
The sharpness result states more than ”
The construction is a single family. Impute the missing halves and see what you get:
noncomputable def imputePop (z : Assignment n) (y u v : Fin n → ℝ) : Population n where
y1 := fun i => Z z i * y i + (1 - Z z i) * u i
y0 := fun i => Z z i * v i + (1 - Z z i) * y iu i is the treated outcome handed to a control unit, v i the control outcome
handed to a treated unit. Every population consistent with the data is of this
form, which is why one definition suffices for the whole theorem.
Lemma. For any imputed vectors
Take a unit
theorem imputePop_consistentWith (z : Assignment n) (y u v : Fin n → ℝ) :
ConsistentWith z y (imputePop z y u v) := by
funext i
simp only [Yobs, imputePop_y1, imputePop_y0]
linear_combination (2 * y i - u i - v i) * Z_mul_self z iThe Lean proof does not case-split, and that is worth watching, because it
shows what the real indicator Z is for.
funext iConsistentWith z y Pis the equality of functionsYobs P z = y, so the proof opens by reducing it to agreement at an arbitrary uniti.Goal⊢ Yobs (imputePop z y u v) z i = y isimp only [Yobs, imputePop_y1, imputePop_y0]Unfold everything.
Yobsis itself written with the indicator —Z z i * y1 i + (1 - Z z i) * y0 i— and the twoimputePop_*lemmas replace those potential outcomes by their definitions, which are again indicator combinations. The result is a quadratic inZ z i.Goal⊢ Z z i * (Z z i * y i + (1 - Z z i) * u i) + (1 - Z z i) * (Z z i * v i + (1 - Z z i) * y i) = y ilinear_combination (2 * y i - u i - v i) * Z_mul_self z iExpand the quadratic and subtract
y i: everything cancels except , and because an indicator is idempotent.Z_mul_selfis that idempotence, andlinear_combination c * hcloses a goalL = Rby checking withringthatL - Ris exactlyctimesh’s ownlhs - rhs. It isringwith a certificate, and much more robust than hunting for the right rewrite.
That is the dividend of writing the indicator as a real number rather than as
an if: a fact that would need two branches becomes one polynomial identity.
Two choices of (u, v) give the endpoints: (a, b) gives manskiLower,
(b, a) gives manskiUpper. Everything in between comes from mixing them.
Proposition. Suppose the data are in range. For every
Impute every missing treated outcome at
It is also bounded. Both imputed values are convex combinations of
Finally, the average treatment effect is affine in the imputed outcomes. A
treated unit of
Those two facts — that
theorem mix_mem_identifiedSet {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ}
(hy : InRange a b y) {lam : ℝ} (h0 : 0 ≤ lam) (h1 : lam ≤ 1) :
(1 - lam) * manskiLower z y a b + lam * manskiUpper z y a b ∈ identifiedSet z y a b := by
refine ⟨imputePop z y (fun _ => (1 - lam) * a + lam * b) (fun _ => (1 - lam) * b + lam * a),
imputePop_consistentWith z y _ _, ?_, ?_⟩
· refine imputePop_bounded hy (fun i => ?_) (fun i => ?_) <;>
· have hab : a ≤ b := le_trans (hy i).1 (hy i).2
constructor <;>
linarith [mul_nonneg h0 (sub_nonneg.mpr hab),
mul_nonneg (sub_nonneg.mpr h1) (sub_nonneg.mpr hab)]
· rw [tau_imputePop, manskiLower, manskiUpper, ← mean_const_mul, ← mean_const_mul, ← mean_add]
exact mean_congr fun i => by ringrefine ⟨imputePop z y (fun _ => (1 - lam) * a + lam * b) (fun _ => (1 - lam) * b + lam * a), imputePop_consistentWith z y _ _, ?_, ?_⟩Membership in
identifiedSetis an existential over populations with three components, so the proof supplies the witness and the first component in one anonymous constructor: consistency isimputePop_consistentWith, already proved for everyuandv. Two goals remain, exactly the last two paragraphs of the informal proof.Goalcase refine_1 ⊢ Bounded a b (imputePop z y (fun x => (1 - lam) * a + lam * b) fun x => (1 - lam) * b + lam * a) case refine_2 ⊢ (imputePop z y (fun x => (1 - lam) * a + lam * b) fun x => (1 - lam) * b + lam * a).tau = (1 - lam) * manskiLower z y a b + lam * manskiUpper z y a brefine imputePop_bounded hy (fun i => ?_) (fun i => ?_)imputePop_boundedreduces boundedness of the imputed population to three conditions: the data are in range (that ishy), and each of the two imputed vectors is in range. Both imputed vectors are constant, so the two remaining goals say the same thing at every unit — but a unit is still bound, which the next line needs. In the source a<;> ·runs one shared script against both goals rather than repeating it.Goal⊢ a ≤ (1 - lam) * a + lam * b ∧ (1 - lam) * a + lam * b ≤ bhave hab : a ≤ b := le_trans (hy i).1 (hy i).2Convexity needs
a ≤ b, which the statement never assumed — and cannot, since atn = 0there is nothing to derive it from. With a unitiin hand it comes from the data:a ≤ y i ≤ b.constructor <;> linarith [mul_nonneg h0 (sub_nonneg.mpr hab), mul_nonneg (sub_nonneg.mpr h1) (sub_nonneg.mpr hab)]constructorsplits the conjunction into the two inequalities, and<;>applies the same closing tactic to both. The two hints handed tolinarithare and ; adding the first toagives the lower bound and subtracting the second frombgives the upper one. That is convexity of , written as two linear facts.rw [tau_imputePop]The second goal.
tau_imputePopcomputes the ATE of an imputed population unit by unit: a treated unit contributesy i - v iand a control unitu i - y i. The left-hand side is now amean.Goal⊢ (mean fun i => Z z i * (y i - ((1 - lam) * b + lam * a)) + (1 - Z z i) * ((1 - lam) * a + lam * b - y i)) = (1 - lam) * manskiLower z y a b + lam * manskiUpper z y a brw [manskiLower, manskiUpper, ← mean_const_mul, ← mean_const_mul, ← mean_add]Four rewrites that push the convex combination inside the mean on the right, so that both sides are means of explicit functions.
manskiLowerandmanskiUpperunfold the two endpoints;mean_const_mul, used right-to-left twice, turnsc * mean vintomean (fun i => c * v i);mean_add, also right-to-left, turns the sum of two means into the mean of the sum. Nothing has been proved yet — the goal is still an equation — but it is now an equation between two means.Goal⊢ (mean fun i => Z z i * (y i - ((1 - lam) * b + lam * a)) + (1 - Z z i) * ((1 - lam) * a + lam * b - y i)) = mean fun i => (1 - lam) * (Z z i * (y i - b) + (1 - Z z i) * (a - y i)) + lam * (Z z i * (y i - a) + (1 - Z z i) * (b - y i))exact mean_congr fun i => by ringmean_congrsays two vectors that agree entrywise have the same mean, which is how one rewrites underneath afun i => …binder. At each unit the two summands differ by rearrangement only, soringverifies them: this is the “averaging” step of the informal proof.
With the segment in hand, sharpness is a matter of picking
ExerciseSharpness (stretch)
Every point of the Manski interval is the ATE of some population that fits the data and respects the range — the inclusion an autoformalization tends to leave out.
theorem mem_identifiedSet_of_mem_Icc {z : Assignment n} {y : Fin n → ℝ} {a b t : ℝ}
(hy : InRange a b y) (ht : t ∈ Set.Icc (manskiLower z y a b) (manskiUpper z y a b)) :
t ∈ identifiedSet z y a b := by
sorryHint
The only real content is choosing the mixing weight. If L = U the interval is
a point and mix_mem_identifiedSet at lam = 0 already gives it (simpa
cleans up). Otherwise L < U, and the weight that lands on t is
lam = (t - L) / (U - L): div_nonneg and div_le_one give 0 ≤ lam ≤ 1, and
div_mul_cancel₀ _ hne : (t - L) / (U - L) * (U - L) = t - L is the one fact
linarith needs to see that (1 - lam) * L + lam * U = t. set L := … before
you start, or the goals become unreadable.
Show solution
theorem mem_identifiedSet_of_mem_Icc {z : Assignment n} {y : Fin n → ℝ} {a b t : ℝ}
(hy : InRange a b y) (ht : t ∈ Set.Icc (manskiLower z y a b) (manskiUpper z y a b)) :
t ∈ identifiedSet z y a b := by
obtain ⟨htl, htu⟩ := ht
set L := manskiLower z y a b
set U := manskiUpper z y a b
rcases eq_or_lt_of_le (htl.trans htu) with hEq | hLt
· have hte : t = L := le_antisymm (hEq ▸ htu) htl
have hmix := mix_mem_identifiedSet (z := z) (y := y) (a := a) (b := b) hy
(lam := 0) le_rfl zero_le_one
simpa [hte] using hmix
· have hd : (0 : ℝ) < U - L := sub_pos.mpr hLt
have hne : U - L ≠ 0 := ne_of_gt hd
have h0 : 0 ≤ (t - L) / (U - L) := div_nonneg (by linarith) hd.le
have h1 : (t - L) / (U - L) ≤ 1 := (div_le_one hd).mpr (by linarith)
have hmix := mix_mem_identifiedSet (z := z) (y := y) (a := a) (b := b) hy h0 h1
have hcancel : (t - L) / (U - L) * (U - L) = t - L := div_mul_cancel₀ _ hne
have heq : (1 - (t - L) / (U - L)) * L + (t - L) / (U - L) * U = t := by linarith
rwa [heq] at hmixTheorem (Manski). Suppose the observed outcomes lie in
In words: under a bounded outcome and nothing else, the set of average treatment effects consistent with the observed data is precisely the interval whose endpoints impute every missing potential outcome at the worse, respectively better, end of the range.
Two inclusions. Any consistent bounded population has its ATE in the interval,
by the bracketing proposition. Conversely, any point
theorem identifiedSet_eq_Icc {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ} (hy : InRange a b y) :
identifiedSet z y a b = Set.Icc (manskiLower z y a b) (manskiUpper z y a b) :=
Set.ext fun _ =>
⟨fun ht => identifiedSet_subset_Icc z y a b ht, fun ht => mem_identifiedSet_of_mem_Icc hy ht⟩Set.ext fun _ => ⟨_, _⟩No tactic block: the whole proof is a term.
Set.extis the extensionality principle for sets — two sets are equal when they have the same members — so it wants, for each real numbert, anIffbetween the two membership statements. The anonymous constructor⟨_, _⟩supplies thatIffas its two implications, which are the two inclusions of the informal proof.fun ht => identifiedSet_subset_Icc z y a b htThe forward implication, from the exercise above: any ATE in the identified set is bracketed. Note it needs no hypothesis on the data.
fun ht => mem_identifiedSet_of_mem_Icc hy htThe reverse implication, from the sharpness exercise, and the only place
hyis used: without in-range data the identified set can be empty while the interval is not.
This is the shape to look for when someone hands you a
formalized identification result. An equality of sets proved by Set.ext from
two inclusions is a sharpness claim. A lone ⊆ is a bound, and a bound is worth
much less: identifiedSet z y a b ⊆ Set.Icc (a - b) (b - a) is also true and
says essentially nothing.
Having the equality, the order-theoretic vocabulary comes for free:
theorem isLeast_identifiedSet {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ} (hy : InRange a b y) :
IsLeast (identifiedSet z y a b) (manskiLower z y a b) := by
rw [identifiedSet_eq_Icc hy]
exact isLeast_Icc (manskiLower_le_manskiUpper hy)
theorem isGreatest_identifiedSet {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ}
(hy : InRange a b y) :
IsGreatest (identifiedSet z y a b) (manskiUpper z y a b) := by
rw [identifiedSet_eq_Icc hy]
exact isGreatest_Icc (manskiLower_le_manskiUpper hy)
theorem csInf_identifiedSet {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ} (hy : InRange a b y) :
sInf (identifiedSet z y a b) = manskiLower z y a b :=
(isLeast_identifiedSet hy).csInf_eq
theorem csSup_identifiedSet {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ} (hy : InRange a b y) :
sSup (identifiedSet z y a b) = manskiUpper z y a b :=
(isGreatest_identifiedSet hy).csSup_eqrw [identifiedSet_eq_Icc hy]Both order-theoretic statements begin the same way: replace the identified set by the interval it equals. After this rewrite nothing about populations survives, and the goal is a fact about
Set.Icc.exact isLeast_Icc (manskiLower_le_manskiUpper hy)isLeast_Iccis Mathlib’s statement that the left endpoint of a non-empty closed interval is its least element. Its one hypothesis is non-emptiness,manskiLower ≤ manskiUpper, which is the exercise at the end of the chapter.isGreatest_identifiedSetis the same two lines withisGreatest_Icc.(isLeast_identifiedSet hy).csInf_eqIsLeast.csInf_eqconverts “least element” into “conditional infimum”: ifxis the least element ofSthensInf S = x.csSup_identifiedSetis the mirror image throughIsGreatest.csSup_eq. Both are one term, because the work was done by the theorem above.
IsLeast S x is x ∈ S ∧ ∀ y ∈ S, x ≤ y — membership and minimality. That
conjunction is the honest formal rendering of “this is the sharp lower bound”,
and it is strictly stronger than ∀ y ∈ S, x ≤ y alone. IsLeast.csInf_eq
then hands you sInf (identifiedSet …) = manskiLower …, which is the statement
an econometrics paper would write. Note that going through IsLeast is not
laziness: sInf on ℝ is a conditional infimum and returns 0 for an
unbounded or empty set, so sInf S = L on its own does not imply that L
is attained, or even that S is non-empty.
The width of the interval is the range of the outcome
Proposition. For every assignment, every data vector and every
Compare the two endpoints unit by unit. A treated unit contributes
The proof used neither the data nor the assignment, and that is the content of
the result: every unit is missing exactly one number, and the arm it landed in
changes which endpoint imputes which, not how much is unknown. A textbook would
not state the hypothesis
ExerciseThe width fact (core)
The width of the worst-case interval is exactly b - a: it does not depend on
the data, on the assignment, or on n. 0 < n is the only hypothesis; in
particular the identity holds whether or not the data are in range.
theorem manskiUpper_sub_manskiLower (hn : 0 < n) (z : Assignment n) (y : Fin n → ℝ) (a b : ℝ) :
manskiUpper z y a b - manskiLower z y a b = b - a := by
sorryHint
Unfold manskiUpper and manskiLower, then ← mean_sub turns the difference
of two means into the mean of the pointwise difference; mean_congr fun i => by ring observes that that difference is the constant b - a — the indicator
cancels identically, which is the whole point — and mean_const hn evaluates
the mean of a constant, which is the only place 0 < n enters.
Show solution
theorem manskiUpper_sub_manskiLower (hn : 0 < n) (z : Assignment n) (y : Fin n → ℝ) (a b : ℝ) :
manskiUpper z y a b - manskiLower z y a b = b - a := by
have h : manskiUpper z y a b - manskiLower z y a b = mean (fun _ : Fin n => b - a) := by
rw [manskiUpper, manskiLower, ← mean_sub]
exact mean_congr fun i => by ring
rw [h, mean_const hn]Three consequences:
- the worst-case interval has width
for every data set; - it does not shrink as
grows; - it is not a confidence interval, and reporting it as one is a category error. Sampling error goes to zero; identification failure does not.
A companion fact makes the same point in a way that stings more.
Proposition. If the observed outcomes lie in
Impute each unit’s missing outcome to equal its observed one. The resulting
population is consistent with the data, its outcomes all lie in
Equivalently, and this is the route the formal proof takes: each summand of
theorem zero_mem_identifiedSet {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ}
(hy : InRange a b y) : (0 : ℝ) ∈ identifiedSet z y a b := by
rw [identifiedSet_eq_Icc hy]
exact ⟨manskiLower_nonpos hy, manskiUpper_nonneg hy⟩rw [identifiedSet_eq_Icc hy]Trade the identified set for the interval. This is what makes the short route available: with the sharpness theorem in hand, exhibiting a population is no longer necessary — membership in the interval suffices.
Goal⊢ 0 ∈ Set.Icc (manskiLower z y a b) (manskiUpper z y a b)exact ⟨manskiLower_nonpos hy, manskiUpper_nonneg hy⟩Membership in
Set.Iccunfolds definitionally to a pair of inequalities, so the anonymous constructor takes the two one-sided facts directly.manskiLower_nonposandmanskiUpper_nonnegare each proved by comparing the endpoint with the mean of the zero vector, onemean_le_meanand twomul_nonnegs apiece.
Compare chapter 12, where the sharp null can be rejected — at the price of assuming it, in order to impute the missing outcomes, before computing the null distribution. Fisher’s test and Manski’s bounds are the same imputation problem answered with opposite temperaments.
Four units, and nothing learned
The general statements are easier to believe against numbers. Four units, two treated, a binary outcome, and the cleanest possible result: both treated units responded, neither control unit did.
def yEx : Fin 4 → ℝ := ![1, 1, 0, 0]
def zEx : Assignment 4 := {0, 1}
@[simp] theorem yEx_zero : yEx 0 = 1 := rfl
@[simp] theorem yEx_one : yEx 1 = 1 := rfl
@[simp] theorem yEx_two : yEx 2 = 0 := rfl
@[simp] theorem yEx_three : yEx 3 = 0 := rfl
@[simp] theorem Z_zEx_zero : Z zEx 0 = 1 := Z_of_mem (by decide)
@[simp] theorem Z_zEx_one : Z zEx 1 = 1 := Z_of_mem (by decide)
@[simp] theorem Z_zEx_two : Z zEx 2 = 0 := Z_of_not_mem (by decide)
@[simp] theorem Z_zEx_three : Z zEx 3 = 0 := Z_of_not_mem (by decide)
theorem inRange_yEx : InRange 0 1 yEx := by
intro i
fin_cases i <;> simp@[simp] theorem yEx_zero : yEx 0 = 1 := rflFour of these.
yExis aMatrix.of-style literal![1, 1, 0, 0], and evaluating it at a numeral is definitional, so each entry isrfl. Marking them@[simp]puts the data into the simp set, which is what makes the arithmetic below one word.@[simp] theorem Z_zEx_zero : Z zEx 0 = 1 := Z_of_mem (by decide)Four more, and these are not
rfl:Zis defined by a case split on membership, so each value needs a membership proof.Z_of_memturnsi ∈ zintoZ z i = 1andZ_of_not_memturnsi ∉ zintoZ z i = 0; membership in a literalFinset (Fin 4)is decidable, soby decidesupplies the proof by evaluation.intro iInRange 0 1 yExis a∀ i, so the proof ofinRange_yExopens by taking an arbitrary unit.Goali : Fin 4 ⊢ 0 ≤ yEx i ∧ yEx i ≤ 1fin_cases i <;> simpfin_casesreplaces the arbitraryi : Fin 4by its four possible values, leaving four concrete goals;<;> simpthen discharges each with the eight@[simp]facts above. The range check is arithmetic on numerals, which is why nothing cleverer is needed.Goalcase «0» ⊢ 0 ≤ yEx ((fun i => i) ⟨0, ⋯⟩) ∧ yEx ((fun i => i) ⟨0, ⋯⟩) ≤ 1 case «1» ⊢ 0 ≤ yEx ((fun i => i) ⟨1, ⋯⟩) ∧ yEx ((fun i => i) ⟨1, ⋯⟩) ≤ 1 case «2» ⊢ 0 ≤ yEx ((fun i => i) ⟨2, ⋯⟩) ∧ yEx ((fun i => i) ⟨2, ⋯⟩) ≤ 1 case «3» ⊢ 0 ≤ yEx ((fun i => i) ⟨3, ⋯⟩) ∧ yEx ((fun i => i) ⟨3, ⋯⟩) ≤ 1
Difference in means is
theorem DiM_data {P : Population 4} (hP : ConsistentWith zEx yEx P) : DiM P zEx = 1 := by
rw [DiM_eq_observed, Finset.sum_congr rfl fun i _ => hP.apply i,
Finset.sum_congr rfl fun i _ => hP.apply i,
show zExᶜ = ({2, 3} : Finset (Fin 4)) from by decide,
show zEx = ({0, 1} : Finset (Fin 4)) from rfl,
Finset.sum_insert (by decide), Finset.sum_singleton,
Finset.sum_insert (by decide), Finset.sum_singleton,
Finset.card_insert_of_notMem (by decide), Finset.card_singleton,
Finset.card_insert_of_notMem (by decide), Finset.card_singleton]
norm_numThe proof is a single rw chain, and the chain is the hand computation:
rw [DiM_eq_observed]DiMis defined on a population;DiM_eq_observedrewrites it as the difference of two averages of the observed vector, which is the form in which consistency can be used. This is the step that makes the estimate depend on the data alone.Goal⊢ (∑ i ∈ zEx, Yobs P zEx i) / ↑(#zEx) - (∑ i ∈ zExᶜ, Yobs P zEx i) / ↑(#zExᶜ) = 1rw [Finset.sum_congr rfl fun i _ => hP.apply i, Finset.sum_congr rfl fun i _ => hP.apply i]Finset.sum_congrrewrites a sum termwise: with the same index set (rfl) andhP.apply i : Yobs P zEx i = yEx iat each term, both sums become sums of the data. It appears twice because there are two sums, the treated and the control. This is where “the estimator only touches what the assignment revealed” becomes a formal step.Goal⊢ Finset.sum zEx yEx / ↑(#zEx) - zExᶜ.sum yEx / ↑(#zExᶜ) = 1rw [show zExᶜ = ({2, 3} : Finset (Fin 4)) from by decide, show zEx = ({0, 1} : Finset (Fin 4)) from rfl]Two
show … from …terms supply small facts inline: the complement of the treated set is{2, 3}(a computation, hencedecide), andzExis{0, 1}(a definition, hencerfl). Both index sets are now literals.Goal⊢ {0, 1}.sum yEx / ↑(#{0, 1}) - {2, 3}.sum yEx / ↑(#{2, 3}) = 1rw [Finset.sum_insert (by decide), Finset.sum_singleton, Finset.sum_insert (by decide), Finset.sum_singleton]Expand the sums.
Finset.sum_insertpeels the first element off{0, 1}— its side condition, that0 ∉ {1}, isby decide— andFinset.sum_singletonfinishes the remaining one-element sum. Twice, once per group.Goal⊢ (yEx 0 + yEx 1) / ↑(#{0, 1}) - (yEx 2 + yEx 3) / ↑(#{2, 3}) = 1rw [Finset.card_insert_of_notMem (by decide), Finset.card_singleton, Finset.card_insert_of_notMem (by decide), Finset.card_singleton]The same peeling for the two denominators:
card_insert_of_notMemgives#{0, 1} = #{1} + 1andcard_singletongives#{1} = 1.Goal⊢ (yEx 0 + yEx 1) / ↑(1 + 1) - (yEx 2 + yEx 3) / ↑(1 + 1) = 1norm_numWhat is left is
over the reals, with the four data values supplied by the@[simp]lemmas of the previous snippet.norm_numevaluates it.
And the bounds:
theorem manskiLower_data : manskiLower zEx yEx 0 1 = 0 := by
simp only [manskiLower, mean, Fin.sum_univ_four, Z_zEx_zero, Z_zEx_one, Z_zEx_two,
Z_zEx_three, yEx_zero, yEx_one, yEx_two, yEx_three]
norm_num
theorem manskiUpper_data : manskiUpper zEx yEx 0 1 = 1 := by
simp only [manskiUpper, mean, Fin.sum_univ_four, Z_zEx_zero, Z_zEx_one, Z_zEx_two,
Z_zEx_three, yEx_zero, yEx_one, yEx_two, yEx_three]
norm_num
theorem identifiedSet_data : identifiedSet zEx yEx 0 1 = Set.Icc 0 1 := by
rw [identifiedSet_eq_Icc inRange_yEx, manskiLower_data, manskiUpper_data]
theorem zero_mem_identifiedSet_data : (0 : ℝ) ∈ identifiedSet zEx yEx 0 1 := by
rw [identifiedSet_data]
exact Set.mem_Icc.mpr ⟨le_refl 0, by norm_num⟩simp only [manskiLower, mean, Fin.sum_univ_four, Z_zEx_zero, Z_zEx_one, Z_zEx_two, Z_zEx_three, yEx_zero, yEx_one, yEx_two, yEx_three]One pass that leaves nothing symbolic.
manskiLowerandmeanunfold the definition to a sum overFin 4divided by4;Fin.sum_univ_fourwrites that sum out as four explicit terms; and the eight data lemmas replace every indicator and every outcome by a numeral. What remains is arithmetic.Goal⊢ (1 * (1 - 1) + (1 - 1) * (0 - 1) + (1 * (1 - 1) + (1 - 1) * (0 - 1)) + (0 * (0 - 1) + (1 - 0) * (0 - 0)) + (0 * (0 - 1) + (1 - 0) * (0 - 0))) / ↑4 = 0norm_numEach treated unit contributes
and each control unit , so the lower endpoint is .manskiUpper_datais the same two lines: there the treated units contribute and the control units , giving .rw [identifiedSet_eq_Icc inRange_yEx, manskiLower_data, manskiUpper_data]identifiedSet_dataneeds no work of its own: the sharpness theorem turns the identified set into an interval, and the two computations above name its endpoints. The result isSet.Icc 0 1, andrwcloses the goal by reflexivity.rw [identifiedSet_data] exact Set.mem_Icc.mpr ⟨le_refl 0, by norm_num⟩And
0 ∈ Set.Icc 0 1is0 ≤ 0—le_refl— together with0 ≤ 1, whichnorm_numsupplies. The point is not the arithmetic but that the sameidentifiedSetappears in the statement about this data set and in the general theorem.
The identified set is
That is not a pathology of the example, and no cleverer data set escapes it.
manskiUpper_sub_manskiLower fixes the width at manskiLower_nonpos together with manskiUpper_nonneg puts
Monotone treatment response
def MTR (P : Population n) : Prop := ∀ i, P.y0 i ≤ P.y1 iMTR says nobody is hurt by treatment. It is a statement about every unit
separately and is strictly stronger than
ExerciseMTR implies a non-negative ATE (warm-up)
Under MTR the ATE is non-negative: an average of non-negative numbers is non-negative.
theorem tau_nonneg_of_MTR {P : Population n} (h : MTR P) : 0 ≤ P.tau := by
sorryHint
Say it through mean_le_mean against the zero vector rather than by hand, so
that the n = 0 case takes care of itself: sub_nonneg.mpr (h i) turns
P.y0 i ≤ P.y1 i into 0 ≤ P.y1 i - P.y0 i, which is 0 ≤ P.effect i after
simpa [Population.effect]. Finish with simpa [mean] to evaluate
mean (fun _ => 0).
Show solution
theorem tau_nonneg_of_MTR {P : Population n} (h : MTR P) : 0 ≤ P.tau := by
have hz : mean (fun _ : Fin n => (0 : ℝ)) ≤ P.tau :=
mean_le_mean fun i => by simpa [Population.effect] using sub_nonneg.mpr (h i)
simpa [mean] using hzWhat does MTR buy? For a treated unit, y0 i ≤ y1 i = y i, so its missing
outcome is confined to y1 i ≥ y0 i = y i and the same happens. Pointwise, the lower bound becomes
zero at every unit, so the new interval is
Theorem. Suppose the observed outcomes lie in
For the inclusion, a population satisfying MTR has every effect non-negative,
so
For sharpness, take
theorem mtrIdentifiedSet_eq_Icc {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ}
(hy : InRange a b y) :
mtrIdentifiedSet z y a b = Set.Icc 0 (manskiUpper z y a b) := by
refine Set.ext fun t => ⟨?_, ?_⟩
· rintro ⟨P, hcon, hb, hmtr, rfl⟩
exact ⟨tau_nonneg_of_MTR hmtr, tau_le_manskiUpper hcon hb⟩
· rintro ⟨ht0, htU⟩
obtain ⟨lam, h0, h1, hlam⟩ :
∃ lam : ℝ, 0 ≤ lam ∧ lam ≤ 1 ∧ lam * manskiUpper z y a b = t := by
rcases eq_or_lt_of_le (manskiUpper_nonneg hy) with hU | hU
· exact ⟨0, le_rfl, zero_le_one, by
have : t = 0 := le_antisymm (hU ▸ htU) ht0
simp [this]⟩
· exact ⟨t / manskiUpper z y a b, div_nonneg ht0 hU.le, (div_le_one hU).mpr htU,
by field_simp⟩
refine ⟨imputePop z y (fun i => (1 - lam) * y i + lam * b)
(fun i => (1 - lam) * y i + lam * a), imputePop_consistentWith z y _ _, ?_, ?_, ?_⟩
· refine imputePop_bounded hy (fun i => ?_) (fun i => ?_) <;>
· obtain ⟨hy1, hy2⟩ := hy i
have hb1 : (0 : ℝ) ≤ lam * (b - a) := mul_nonneg h0 (by linarith)
have hb2 : (0 : ℝ) ≤ (1 - lam) * (y i - a) := mul_nonneg (by linarith) (by linarith)
have hb3 : (0 : ℝ) ≤ (1 - lam) * (b - y i) := mul_nonneg (by linarith) (by linarith)
constructor <;> linarith
· intro i
obtain ⟨hy1, hy2⟩ := hy i
by_cases hi : i ∈ z
· simp only [imputePop_y1, imputePop_y0, Z_of_mem hi]
linarith [mul_nonneg h0 (sub_nonneg.mpr hy1)]
· simp only [imputePop_y1, imputePop_y0, Z_of_not_mem hi]
linarith [mul_nonneg h0 (sub_nonneg.mpr hy2)]
· rw [tau_imputePop, ← hlam, manskiUpper, ← mean_const_mul]
exact mean_congr fun i => by ringThe Lean repeats the pattern of the Manski proof, which is the point of showing it twice; only the family being swept has changed.
refine Set.ext fun t => ⟨?_, ?_⟩Sharpness again, so extensionality again: the goal becomes two implications at an arbitrary
t.rintro ⟨P, hcon, hb, hmtr, rfl⟩The easy inclusion.
rintrodestructures membership inmtrIdentifiedSet— which is a five-fold existential — in one move, and the finalrflsubstitutesP.taufortthroughout, which is why the goal below mentionsP.tauand nott.GoalP : Population n hcon : ConsistentWith z y P hb : Bounded a b P hmtr : MTR P ⊢ P.tau ∈ Set.Icc 0 (manskiUpper z y a b)exact ⟨tau_nonneg_of_MTR hmtr, tau_le_manskiUpper hcon hb⟩Membership in
Set.Iccis a pair of inequalities, and the two components are exactly the two sentences of the informal proof: MTR gives0 ≤ P.tau, and the bracketing proposition gives the upper half.obtain ⟨lam, h0, h1, hlam⟩ : ∃ lam : ℝ, 0 ≤ lam ∧ lam ≤ 1 ∧ lam * manskiUpper z y a b = tThe mixing weight, produced before the population that uses it. Inside, a case split
rcases eq_or_lt_of_le (manskiUpper_nonneg hy)on whether the upper endpoint is zero: if it is,t = 0is forced andlam = 0works; otherwiselam = t / manskiUpper …, withdiv_nonneganddiv_le_onefor the two bounds andfield_simpfor the product. The degenerate branch exists solely because dividing bymanskiUpperneeds it to be non-zero.refine ⟨imputePop z y (fun i => (1 - lam) * y i + lam * b) (fun i => (1 - lam) * y i + lam * a), imputePop_consistentWith z y _ _, ?_, ?_, ?_⟩The witness, with consistency discharged as before. Note the imputed values now depend on
i— they mix the observed outcome with an endpoint, rather than mixing the two endpoints as in the Manski proof. That is the whole difference between the two constructions. Three goals remain: bounded, MTR, and the value of the ATE.Goalcase refine_2.refine_1 ⊢ Bounded a b (imputePop z y (fun i => (1 - lam) * y i + lam * b) fun i => (1 - lam) * y i + lam * a) case refine_2.refine_2 ⊢ MTR (imputePop z y (fun i => (1 - lam) * y i + lam * b) fun i => (1 - lam) * y i + lam * a) case refine_2.refine_3 ⊢ (imputePop z y (fun i => (1 - lam) * y i + lam * b) fun i => (1 - lam) * y i + lam * a).tau = trefine imputePop_bounded hy (fun i => ?_) (fun i => ?_)Boundedness, reduced as before to the two imputed vectors being in range. The three
mul_nonneghypotheseshb1,hb2,hb3that follow are , and , andconstructor <;> linarithassembles each of the four bounds from them.simp only [imputePop_y1, imputePop_y0, Z_of_mem hi]The MTR goal, treated branch, after
intro iandby_cases hi : i ∈ z. Unfolding the two potential outcomes and resolving the indicator to1leaves an inequality between the imputed control outcome and the observed one.Goalhi : i ∈ z ⊢ 1 * ((1 - lam) * y i + lam * a) + (1 - 1) * y i ≤ 1 * y i + (1 - 1) * ((1 - lam) * y i + lam * b)linarith [mul_nonneg h0 (sub_nonneg.mpr hy1)]The hint is
, which is exactly the effect of the treated unit under this imputation; the control branch uses in the same way. Non-negative effects at every unit is what MTR asks for.rw [tau_imputePop, ← hlam, manskiUpper, ← mean_const_mul]The last goal.
tau_imputePopcomputes the ATE unit by unit;← hlamreplaces the targettbylam * manskiUpper …, which is the form that can be matched;manskiUpperunfolds that endpoint into a mean; andmean_const_mulright-to-left pushes the scalarlaminside it.Goal⊢ (mean fun i => Z z i * (y i - ((1 - lam) * y i + lam * a)) + (1 - Z z i) * ((1 - lam) * y i + lam * b - y i)) = mean fun i => lam * (Z z i * (y i - a) + (1 - Z z i) * (b - y i))exact mean_congr fun i => by ringBoth sides are now means of explicit functions that agree at each unit, and
ringchecks the pointwise identity: the effect of unitiunder the swept imputation islamtimes its worst-case contribution.
This is what a partial-identification result looks like in general: an assumption, a shorter interval, and a proof that the shorter interval is still exactly attained. If the third part is missing you have a bound, not an identified set, and you cannot tell whether the assumption was worth making.
Bounds under a design
Everything above is deterministic. Reintroduce the design and the endpoints become statistics — functions of the assignment, computed from the data that assignment produced:
noncomputable def manskiLowerHat (P : Population n) (a b : ℝ) (z : Assignment n) : ℝ :=
manskiLower z (Yobs P z) a b
noncomputable def manskiUpperHat (P : Population n) (a b : ℝ) (z : Assignment n) : ℝ :=
manskiUpper z (Yobs P z) a btheorem manskiHat_brackets {a b : ℝ} {P : Population n} (hb : Bounded a b P)
(z : Assignment n) :
manskiLowerHat P a b z ≤ P.tau ∧ P.tau ≤ manskiUpperHat P a b z :=
⟨manskiLower_le_tau rfl hb, tau_le_manskiUpper rfl hb⟩Not “with probability z.
⟨manskiLower_le_tau rfl hb, tau_le_manskiUpper rfl hb⟩A term, not a tactic block, and the whole content is in the two
rfls. The bracketing proposition wants a population consistent with the data; here the data areYobs P z, the outcomes this very population produced under this very assignment, so consistency is the equalityYobs P z = Yobs P zand holds by reflexivity. The two components of the anonymous constructor are the two halves of the conjunction, andhbis the same boundedness assumption in both.
Taking expectations is then monotonicity and nothing else:
ExerciseBounds in expectation (core)
Under any design, the expectation of the estimated lower bound is still a
lower bound on P.tau.
theorem expect_manskiLowerHat_le (D : Design n) {a b : ℝ} {P : Population n}
(hb : Bounded a b P) : D.expect (manskiLowerHat P a b) ≤ P.tau := by
sorryHint
Two steps, no computation. Design.expect_mono (from chapter 7) turns the
pointwise inequality of manskiHat_brackets into an inequality of expectations
against the constant statistic fun _ => P.tau, and Design.expect_const
evaluates that expectation. A calc block reads best; note that expect_mono
takes its two statistics explicitly, so the call is D.expect_mono _ _ h.
Show solution
theorem expect_manskiLowerHat_le (D : Design n) {a b : ℝ} {P : Population n}
(hb : Bounded a b P) : D.expect (manskiLowerHat P a b) ≤ P.tau := by
calc D.expect (manskiLowerHat P a b)
≤ D.expect (fun _ => P.tau) := D.expect_mono _ _ fun z => (manskiHat_brackets hb z).1
_ = P.tau := D.expect_const _And now the sentence this chapter exists for.
Proposition. Let
By linearity, the left-hand side is
theorem expect_manskiHat_width (hn : 0 < n) (D : Design n) (P : Population n) (a b : ℝ) :
D.expect (manskiUpperHat P a b) - D.expect (manskiLowerHat P a b) = b - a := by
rw [← D.expect_sub,
D.expect_congr (f := fun z => manskiUpperHat P a b z - manskiLowerHat P a b z)
(g := fun _ => b - a) fun z => manskiUpper_sub_manskiLower hn z (Yobs P z) a b]
exact D.expect_const _rw [← D.expect_sub]Design.expect_substates ; used right-to-left it collects the two expectations into one. Linearity, and the only property of the design the proof uses.Goal⊢ (D.expect fun z => manskiUpperHat P a b z - manskiLowerHat P a b z) = b - aD.expect_congr (f := fun z => manskiUpperHat P a b z - manskiLowerHat P a b z) (g := fun _ => b - a) fun z => manskiUpper_sub_manskiLower hn z (Yobs P z) a bDesign.expect_congrreplaces the statistic inside an expectation by any statistic equal to it pointwise. The pointwise equality supplied here is the width identity, instantiated at each assignmentzand at the dataYobs P zthat assignment produced. After this rewrite the integrand is a constant, and the design has vanished from the goal.Goal⊢ (D.expect fun x => b - a) = b - aexact D.expect_const _The expectation of a constant is that constant — because the design’s probabilities sum to one, which is the one axiom a
Designcarries.
D : Design n is universally quantified, and the only hypothesis is 0 < n —
the same one every statement about a mean carries, since at
theorem dim_expect_mem_bounds {n₁ : ℕ} (hle : n₁ ≤ n) (P : Population n) (hpos : 0 < n₁)
(hlt : n₁ < n) {a b : ℝ} (hb : Bounded a b P) :
(completeRandomization n n₁ hle).expect (DiM P) ∈
Set.Icc ((completeRandomization n n₁ hle).expect (manskiLowerHat P a b))
((completeRandomization n n₁ hle).expect (manskiUpperHat P a b)) := by
rw [DiM_unbiased_completeRandomization hle P hpos hlt]
exact ⟨expect_manskiLowerHat_le _ hb, le_expect_manskiUpperHat _ hb⟩rw [DiM_unbiased_completeRandomization hle P hpos hlt]Unbiasedness, from chapter 8: under complete randomization with
the expectation of the difference in means is . Rewriting with it replaces the estimator’s expectation in the goal by itself, so what is left to show is that lies between the two expected bounds.exact ⟨expect_manskiLowerHat_le _ hb, le_expect_manskiUpperHat _ hb⟩Which is the exercise above and its mirror image, as the two components of a
Set.Iccmembership. Two theorems from two different chapters meeting in one anonymous constructor is the whole point of the statement.
Randomization buys point identification — an estimator whose expectation is
Attrition
The one place where the distinction bites in a real experiment. Randomization
fixes selection into treatment; it does nothing about selection into being
measured. If a unit does not respond, neither of its potential outcomes is
observed, and all you know about its effect is that it lies in
noncomputable def attritionLower (z : Assignment n) (R : Finset (Fin n)) (y : Fin n → ℝ)
(a b : ℝ) : ℝ :=
mean fun i => Z R i * (Z z i * (y i - b) + (1 - Z z i) * (a - y i)) + (1 - Z R i) * (a - b)
noncomputable def attritionUpper (z : Assignment n) (R : Finset (Fin n)) (y : Fin n → ℝ)
(a b : ℝ) : ℝ :=
mean fun i => Z R i * (Z z i * (y i - a) + (1 - Z z i) * (b - y i)) + (1 - Z R i) * (b - a)R : Finset (Fin n) is the set of responders. Because Assignment n is
Finset (Fin n), the indicator Z R i of the response set is the same function
Z used for treatment — no new machinery, which is a small dividend of the
representation choice made in chapter 6.
Proposition. Let
Unit by unit again, and now four cases.
If
If
theorem attrition_brackets {z : Assignment n} {R : Finset (Fin n)} {y : Fin n → ℝ} {a b : ℝ}
{P : Population n} (hb : Bounded a b P) (hr : ∀ i ∈ R, Yobs P z i = y i) :
attritionLower z R y a b ≤ P.tau ∧ P.tau ≤ attritionUpper z R y a b := by
constructor
· rw [attritionLower, Population.tau]
refine mean_le_mean fun i => ?_
obtain ⟨h1, _, _, h4⟩ := hb i
simp only [Population.effect]
by_cases hiR : i ∈ R
· rw [Z_of_mem hiR]
by_cases hi : i ∈ z
· rw [Z_of_mem hi, ← hr i hiR, Yobs_of_mem hi]
linarith
· rw [Z_of_not_mem hi, ← hr i hiR, Yobs_of_not_mem hi]
linarith
· rw [Z_of_not_mem hiR]
linarith
· rw [attritionUpper, Population.tau]
refine mean_le_mean fun i => ?_
obtain ⟨_, h2, h3, _⟩ := hb i
simp only [Population.effect]
by_cases hiR : i ∈ R
· rw [Z_of_mem hiR]
by_cases hi : i ∈ z
· rw [Z_of_mem hi, ← hr i hiR, Yobs_of_mem hi]
linarith
· rw [Z_of_not_mem hi, ← hr i hiR, Yobs_of_not_mem hi]
linarith
· rw [Z_of_not_mem hiR]
linarithThe hypothesis is deliberately weak: y has to agree with the population’s
observed outcome only on R. Off R the vector y may be anything at all,
because it is never used. That is the formal content of “we do not know what the
non-respondents would have shown”.
constructorThe conclusion is a conjunction of the two bracketing inequalities, so the proof splits into two halves at once. Everything below is the first half; the second is the same thirteen lines with the other two components of
hb.rw [attritionLower, Population.tau] refine mean_le_mean fun i => ?_The same opening as the Manski bracket: unfold both sides to means, then use monotonicity of the mean to reduce to one arbitrary unit. After
obtain ⟨h1, _, _, h4⟩ := hb iandsimp only [Population.effect]the goal compares the unit’s assigned summand withP.y1 i - P.y0 i.Goal⊢ Z R i * (Z z i * (y i - b) + (1 - Z z i) * (a - y i)) + (1 - Z R i) * (a - b) ≤ P.y1 i - P.y0 iby_cases hiR : i ∈ RThe outer split, and the one the Manski proof did not need: did this unit respond? Note that it comes first. A non-responder’s summand does not look at the treatment indicator at all, so there is nothing to split further.
rw [Z_of_mem hiR]The responder branch. Resolving the response indicator to
1kills the(1 - Z R i) * (a - b)term and leaves precisely the Manski summand, which is the formal statement of “responders contribute exactly what they would have contributed with no attrition”.GoalhiR : i ∈ R ⊢ 1 * (Z z i * (y i - b) + (1 - Z z i) * (a - y i)) + (1 - 1) * (a - b) ≤ P.y1 i - P.y0 irw [Z_of_mem hi, ← hr i hiR, Yobs_of_mem hi]Responder, treated. Three rewrites: the treatment indicator becomes
1; then← hr i hiRreplaces the observed numbery ibyYobs P z i— note the direction, away from the data and back to the population, because the hypothesis only holds onR; andYobs_of_mem hievaluates that toP.y1 i. Now everything is in the population’s own vocabulary andlinarithcloses it fromh4 : P.y0 i ≤ b.Goalhi : i ∈ z ⊢ 1 * (1 * (P.y1 i - b) + (1 - 1) * (a - P.y1 i)) + (1 - 1) * (a - b) ≤ P.y1 i - P.y0 irw [Z_of_not_mem hi, ← hr i hiR, Yobs_of_not_mem hi]Responder, control. The same three moves with the indicator resolving to
0andYobs_of_not_memgivingP.y0 i; the closinglinarithusesh1 : a ≤ P.y1 i.Goalhi : i ∉ z ⊢ 1 * (0 * (P.y0 i - b) + (1 - 0) * (a - P.y0 i)) + (1 - 1) * (a - b) ≤ P.y1 i - P.y0 irw [Z_of_not_mem hiR]The non-responder branch, and no treatment split. The Manski part of the summand is multiplied by
0and disappears; what is left isa - b, andlinarithgetsa - b ≤ P.y1 i - P.y0 ifromh1 : a ≤ P.y1 iandh4 : P.y0 i ≤ b. The data vectoryis never touched, which is exactly why the hypothesis could be weakened toR.GoalhiR : i ∉ R ⊢ 0 * (Z z i * (y i - b) + (1 - Z z i) * (a - y i)) + (1 - 0) * (a - b) ≤ P.y1 i - P.y0 i
attritionUpper_sub_attritionLower prices the damage: the width is
ExerciseFull response (warm-up)
A sanity check on the definition: with Finset.univ as the response set —
everybody answers — the attrition bounds are the Manski bounds.
theorem attritionLower_univ (z : Assignment n) (y : Fin n → ℝ) (a b : ℝ) :
attritionLower z Finset.univ y a b = manskiLower z y a b := by
sorryHint
Work one unit at a time with refine mean_congr fun i => ?_; then
Z_of_mem (Finset.mem_univ i) rewrites Z univ i to 1, and ring finishes
the summand.
Show solution
theorem attritionLower_univ (z : Assignment n) (y : Fin n → ℝ) (a b : ℝ) :
attritionLower z Finset.univ y a b = manskiLower z y a b := by
refine mean_congr fun i => ?_
rw [Z_of_mem (Finset.mem_univ i)]
ringExercises
The exercises above run through the chapter; three more that are worth doing in order.
ExerciseConstants pull out of a mean (warm-up)
The mean is homogeneous: mean (fun i => c * v i) = c * mean v. Needed twice
in mix_mem_identifiedSet, in the ← direction, to push a convex combination
inside a mean.
theorem mean_const_mul (c : ℝ) (v : Fin n → ℝ) :
mean (fun i => c * v i) = c * mean v := by
sorryHint
Finset.mul_sum moves the constant into the sum (used right-to-left) and
mul_div_assoc moves the division out; one simp only with both, plus mean,
does it.
Show solution
theorem mean_const_mul (c : ℝ) (v : Fin n → ℝ) :
mean (fun i => c * v i) = c * mean v := by
simp only [mean, ← Finset.mul_sum, mul_div_assoc]ExerciseThe interval is non-empty (core)
The lower bound really is below the upper bound whenever the data are in
range. (The theorem needs InRange rather than a bare a ≤ b: with no units
there is nothing to derive a ≤ b from.)
theorem manskiLower_le_manskiUpper {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ}
(hy : InRange a b y) : manskiLower z y a b ≤ manskiUpper z y a b := by
sorryHint
mean_le_mean, then a single have key : … = b - a := by ring computing the
pointwise difference of the two integrands, then linarith. You will need
a ≤ b, which is le_trans (hy i).1 (hy i).2 — available only inside the
fun i => ….
Show solution
theorem manskiLower_le_manskiUpper {z : Assignment n} {y : Fin n → ℝ} {a b : ℝ}
(hy : InRange a b y) : manskiLower z y a b ≤ manskiUpper z y a b := by
refine mean_le_mean fun i => ?_
have hab : a ≤ b := le_trans (hy i).1 (hy i).2
have key : Z z i * (y i - a) + (1 - Z z i) * (b - y i)
- (Z z i * (y i - b) + (1 - Z z i) * (a - y i)) = b - a := by ring
linarithExercise (stretch, on paper). Suppose the design treats 90% of the units. The treated units’ missing outcomes are then 90% of the missing information — so why does the width of the worst-case interval not depend on that fraction?
Reading autoformalized Lean
Three failures, in decreasing order of how often you will meet them.
Two smaller checks, both specific to this chapter. First, Set.Icc is the
closed interval; Set.Ico and Set.Ioo are one and two endpoints short, and a
partial-identification theorem stated with Set.Ioo is asserting that the
extreme populations do not fit the data — the opposite of sharpness. Second,
manskiUpper_sub_manskiLower needs 0 < n and nothing else: it is an algebraic
identity that holds even when the data are out of range and the identified set
is empty. A formalization that attaches InRange to the width theorem is not
wrong, but it is a hint that the author did not know which hypothesis was doing
what — and hypotheses that are not doing anything are where vacuity hides.