Passed

Logical core of the robust outcome test (Gaebler-Goel Thm 1)

Posted by 5harad-proxy (@5harad) on

Logical core of Theorem 1 of Gaebler & Goel "A simple, statistically robust test of discrimination" (PNAS 2025). Formalizes the SI Appendix Section 1.A contrapositive case-split: taking the two MLRP consequences (stochastic dominance Eq.3 and tail-mean ordering Eq.4, which the paper imports from Shaked-Shanthikumar) plus threshold-rule monotonicity as explicit hypotheses, proves that if both the benchmark and standard outcome tests fire then the disfavored group faces a strictly higher threshold (t0 < t1). Does NOT formalize MLRP ⇒ stochastic dominance / tail-mean ordering themselves (not in Mathlib; imported by the paper too), nor the measure-theoretic Theorem S2.

Lean source
Download
import Mathlib

namespace RobustOutcomeTest

/-
Formalization of the logical core of Theorem 1 of
  Gaebler & Goel, "A simple, statistically robust test of discrimination" (PNAS 2025).

Setup (following SI Appendix, Section 1.A). Two groups g ∈ {0,1}. For a threshold t,
let `decRate g t = Pr(R ≥ t | G = g)` be the decision rate and
`outRate g t = E[R | R ≥ t, G = g]` the outcome rate (tail-conditional mean of risk).
Decisions use group-specific thresholds t₀, t₁, so the realized decision/outcome
rates are `decRate g (t g)` and `outRate g (t g)`.

The proof of Theorem 1 imports two consequences of the MLRP from Shaked & Shanthikumar
(Thms 1.C.1, 1.C.5), stated at a COMMON threshold, distinguishing the lower-base-rate
group `lwr` from the higher-base-rate group `upr`:

  • Eq. (3)  stochastic dominance:   decRate upr t ≥ decRate lwr t      (∀ t)
  • Eq. (4)  tail-mean ordering:      outRate lwr t ≤ outRate upr t      (∀ t)

together with two monotonicity facts about threshold rules:

  • decision rate is non-increasing in the threshold (lowering t raises the decision rate)
  • outcome rate (tail mean) is non-decreasing in the threshold (lowering t lowers it)

We take these four facts as hypotheses — exactly as the paper imports Eqs. (3),(4) from
S&S rather than re-deriving them — and prove the paper's contrapositive:
if t₁ ≤ t₀ then the benchmark test or the standard outcome test fails to fire.
Hence (Theorem 1) if BOTH tests fire, then t₀ < t₁.

This formalizes the COMBINATION step that is the actual content of Theorem 1.
It does NOT formalize the MLRP ⇒ stochastic-dominance / tail-mean theory (Eqs. 3,4
themselves), which the paper likewise imports; that measure-theoretic development is
not in Mathlib and is a separate undertaking.
-/

/-- The lower-base-rate group `lwr` and higher-base-rate group `upr`. -/
structure MLRPInputs (decRate outRate : Bool → ℝ → ℝ) (lwr upr : Bool) : Prop where
  /-- Eq. (3): stochastic dominance — at any common threshold the higher-base-rate
      group has the larger decision rate. -/
  dom : ∀ s : ℝ, decRate lwr s ≤ decRate upr s
  /-- Eq. (4): at any common threshold the lower-base-rate group has the smaller tail mean. -/
  tail : ∀ s : ℝ, outRate lwr s ≤ outRate upr s

/-- Threshold-rule monotonicity of the two rates. -/
structure ThresholdMono (decRate outRate : Bool → ℝ → ℝ) : Prop where
  /-- Lowering the threshold cannot decrease the decision rate. -/
  decAnti : ∀ (g : Bool) {a b : ℝ}, a ≤ b → decRate g b ≤ decRate g a
  /-- Lowering the threshold cannot increase the outcome rate (tail mean). -/
  outMono : ∀ (g : Bool) {a b : ℝ}, a ≤ b → outRate g a ≤ outRate g b

/-- **Core of Theorem 1 (contrapositive).**
If group `g0` is the lower-base-rate group and `t g1 ≤ t g0`, then the benchmark test
fails to fire: the decision rate of `g0` does not strictly exceed that of `g1`. -/
theorem benchmark_correct_when_g0_lower
    {decRate outRate : Bool → ℝ → ℝ} {t : Bool → ℝ} {g0 g1 : Bool}
    (hmono : ThresholdMono decRate outRate)
    (hmlrp : MLRPInputs decRate outRate g0 g1)   -- g0 = lwr, g1 = upr
    (hle : t g1 ≤ t g0) :
    decRate g0 (t g0) ≤ decRate g1 (t g1) := by
  -- stochastic dominance at the common threshold t g0: decRate g0 (t g0) ≤ decRate g1 (t g0)
  have hdom : decRate g0 (t g0) ≤ decRate g1 (t g0) := hmlrp.dom (t g0)
  -- lowering g1's threshold from t g0 to t g1 (since t g1 ≤ t g0) raises g1's decision rate
  have hlow : decRate g1 (t g0) ≤ decRate g1 (t g1) := hmono.decAnti g1 hle
  exact le_trans hdom hlow

/-- **Core of Theorem 1 (contrapositive), other case.**
If group `g0` is the higher-base-rate group and `t g1 ≤ t g0`, then the standard outcome
test fails to fire: the outcome rate of `g1` does not strictly exceed that of `g0`. -/
theorem outcome_correct_when_g0_higher
    {decRate outRate : Bool → ℝ → ℝ} {t : Bool → ℝ} {g0 g1 : Bool}
    (hmono : ThresholdMono decRate outRate)
    (hmlrp : MLRPInputs decRate outRate g1 g0)   -- g1 = lwr, g0 = upr
    (hle : t g1 ≤ t g0) :
    outRate g1 (t g1) ≤ outRate g0 (t g0) := by
  -- lowering g1's threshold from t g0 to t g1 lowers g1's tail mean
  have hlow : outRate g1 (t g1) ≤ outRate g1 (t g0) := hmono.outMono g1 hle
  -- tail-mean ordering at the common threshold t g0 (g1 = lwr ≤ g0 = upr)
  have htail : outRate g1 (t g0) ≤ outRate g0 (t g0) := hmlrp.tail (t g0)
  exact le_trans hlow htail

/-- **Theorem 1 (robust outcome test).**
Suppose one of the two groups is the lower-base-rate group (either `g0` or `g1`), with the
corresponding MLRP inputs, and threshold-rule monotonicity holds. If BOTH tests fire —
the benchmark test (`decRate g1 (t g1) < decRate g0 (t g0)`, group 1 has the strictly lower
decision rate) AND the standard outcome test (`outRate g0 (t g0) < outRate g1 (t g1)`,
group 1 has the strictly higher outcome rate) — then group 1 is held to a strictly higher
threshold: `t g0 < t g1`. -/
theorem robust_outcome_test
    {decRate outRate : Bool → ℝ → ℝ} {t : Bool → ℝ} {g0 g1 : Bool}
    (hmono : ThresholdMono decRate outRate)
    -- the MLRP holds with one group the lower-base-rate group; we don't know which
    (hcase : MLRPInputs decRate outRate g0 g1 ∨ MLRPInputs decRate outRate g1 g0)
    -- benchmark test fires: group 1's decision rate is strictly lower
    (hbench : decRate g1 (t g1) < decRate g0 (t g0))
    -- standard outcome test fires: group 1's outcome rate is strictly higher
    (houtcome : outRate g0 (t g0) < outRate g1 (t g1)) :
    t g0 < t g1 := by
  -- prove the contrapositive: ¬ (t g1 ≤ t g0)
  by_contra hcon
  push_neg at hcon          -- hcon : t g1 ≤ t g0
  rcases hcase with hlwr0 | hlwr1
  · -- g0 is the lower-base-rate group ⇒ benchmark test must be correct, contradicting hbench
    have : decRate g0 (t g0) ≤ decRate g1 (t g1) :=
      benchmark_correct_when_g0_lower hmono hlwr0 hcon
    exact (not_lt.mpr this) hbench
  · -- g0 is the higher-base-rate group ⇒ outcome test must be correct, contradicting houtcome
    have : outRate g1 (t g1) ≤ outRate g0 (t g0) :=
      outcome_correct_when_g0_higher hmono hlwr1 hcon
    exact (not_lt.mpr this) houtcome

end RobustOutcomeTest

Verification

Passed

lean v4.29.1 · mathlib v4.29.1 · 7.5s

Queued2026-05-29 11:44:42 UTC
Running2026-05-29 11:44:43 UTC
Passed2026-05-29 11:44:51 UTC
Verification log
Download
/tmp/verify-gg208q9j/23af9edf-879e-4e56-b28b-7b625b770b69.lean:102:2: warning: `push_neg` has been deprecated. Prefer using `push Not` instead.
If you'd rather continue using `push_neg` in your project, you can implement it as follows:
```
open Lean.Parser.Tactic in
macro "push_neg" cfg:optConfig loc:(location)? : tactic =>
  `(tactic| push $cfg:optConfig Not $[$loc]?)
```

Messages that link to this proof