Identifier
F:ml430-nat-stirlingfirst-eq-zero-of-lt-6f46764f
Proof route
kernel-lean
External status
proved
Axiom footprint
Empty

Recorded description

The proposition declared as `Nat.stirlingFirst_eq_zero_of_lt` in the pinned Mathlib v4.30 source.

Formal statement
∀ {n k : ℕ}, n < k → n.stirlingFirst k = 0

Dependencies

The graph shows direct ledger edges. Follow a node to open its artifact page.

Direct dependencies appear to the left. The current fact is in the center. Facts that depend directly on it appear to the right. Mathlib v4.30 source propositio [generated] kernel theorem Nat. < on the naturals is irreflexiv No successor is <= zero Current fact Mathlib v4.30 source propositio
4 direct dependencies 1 direct dependents

Evidence

kernel-Nat.stirlingFirst_eq_zero_of_lt

Kind
kernel-term
Status
checked

Supports: ((x0 : AxNat) -> ((x1 : AxNat) -> ((x2 : AxNat.lt x0 x1) -> Eq.{1} AxNat (AxNat.stirlingFirst x0 x1) AxNat.zero)))

Checker command
test "$(cargo run -q --release -p axeyum-lean-kernel --example nat_theorem_inventory -- stirlingFirst_eq_zero_of_lt 2>/dev/null | grep -Ec '^Nat\.stirlingFirst_eq_zero_of_lt[[:space:]]')" -ge 1
Evidence notes

`build_nat_prelude` admits `Nat.stirlingFirst_eq_zero_of_lt` through the trusted `Kernel::add_declaration` gate, declared in `nat_prelude/stirling_lemmas.rs`. `nat_theorem_inventory`'s rendered type is `((x0 : AxNat) -> ((x1 : AxNat) -> ((x2 : AxNat.lt x0 x1) -> Eq.{1} AxNat (AxNat.stirlingFirst x0 x1) AxNat.zero)))`, matching this fact's `formal.statement` modulo binder info. The flip is honest under the def-vs-theorem criterion, checked at Mathlib's own source at the pinned commit `c5ea00351c28e24afc9f0f84379aa41082b1188f` (`Mathlib/Combinatorics/Enumerative/Stirling.lean:51` and `:113`) rather than from a paraphrase. Mathlib's `def stirlingFirst` / `def stirlingSecond` are `| 0, 0 => 1 | 0, _+1 => 0 | _+1, 0 => 0 | n+1, k+1 => c * f n (k+1) + f n k` with `c := n` for the first kind and `c := k+1` for the second -- which is `nat_prelude/stirling.rs`'s body verbatim, an outer recursion on the row index yielding a whole row and an inner one selecting the column, the shape Lean's equation compiler produces for those four cases. The strongest evidence that the two are the SAME function rather than merely extensionally equal is that Mathlib proves its own `stirlingFirst_zero`, `stirlingFirst_zero_succ`, `stirlingFirst_succ_zero` and `stirlingFirst_succ_succ` by **`rfl`**: the four defining equations are definitional on Mathlib's side exactly as they are on ours. This is the opposite of `Nat.multichoose`, where our body is Mathlib's THEOREM about a structurally different `def` and the mirrors must stay open. Construction: Induction on the row index with an inner `Nat.rec` on the column used only to expose its SHAPE (the motive is the arrow `Lt _ k -> _`, so each branch re-introduces its own specialized hypothesis) -- the shape `Nat.choose_eq_zero_of_lt` already uses. The `k = 0` arms are vacuous (`Nat.lt_irrefl`, `Nat.not_succ_le_zero`); the `n = succ m`, `k = succ k'` leaf strips one `succ` off the hypothesis with `Nat.le_of_succ_le_succ` and `Nat.le_succ_of_le` to reach the induction hypothesis at BOTH columns the recurrence mentions, then collapses `c * 0 + 0` to `0` by iota. The proof is written once over a `Kind` parameter and instantiated for both triangles: they differ only in the coefficient, and the coefficient is multiplied by zero here. The tool exits non-zero for a name that does not exist, and the `grep -c` count (tested `-ge 1`, consuming the pipe, never `grep -q`) requires the admitted declaration to be printed. Verified both ways, and the negative control is a REAL Mathlib theorem rather than an invented name: this command exits 0 for all ten declared mirrors and exits 1 for `stirlingSecond_self`, which Mathlib proves and this prelude does not declare. Note that `nat_theorem_inventory` matches by PREFIX, so `stirlingFirst_zero` also prints `stirlingFirst_zero_succ`; the grep is anchored `^Nat.<name>[[:space:]]` for exactly that reason. Note also that it keeps only its LAST name argument, so this command passes exactly one, and `[[:space:]]` is used rather than `\t` because GNU grep reads `\t` in ERE as a literal `t`.

instantiation-Nat.stirlingFirst_eq_zero_of_lt

Kind
kernel-term
Status
checked

Supports: ((x0 : AxNat) -> ((x1 : AxNat) -> ((x2 : AxNat.lt x0 x1) -> Eq.{1} AxNat (AxNat.stirlingFirst x0 x1) AxNat.zero)))

Checker command
cargo test -p axeyum-lean-kernel --lib nat_prelude::stirling_lemmas_tests
Evidence notes

The kernel gate says the proof term checks; it does not say the STATEMENT is the intended one. `stirling_lemmas_tests.rs` infers each applied theorem's type with `Kernel::infer`/`infer_in` and compares it against an independently built expectation -- symbolically at genuinely free variables in a `LocalContext`, where nothing reduces, AND concretely at the hand-computed entries in `stirling_tests.rs`'s table, because numerals reduce and the two checks fail on disjoint defects. Every negative control was re-derived for the statement it guards rather than copied from a neighbour, and the file records the three that do NOT discriminate: the cross-kind swap is vacuous for `_self` (both triangles are all ones on the diagonal) and for `_succ_self_left` (Mathlib proves the same `choose (n+1) 2` identity for both kinds), and -- caught by the suite on its first run, not by review -- the transposed index `stirlingFirst (k+1) 0 = 0` is vacuous against `stirlingFirst_zero_succ` because BOTH sides reduce to the literal `0` even at a free `k`, so they are one proposition up to defeq. Going symbolic is the usual rescue and does not work here, the collapse being driven by constructor shapes rather than numerals. The controls used instead drop the `succ` (`stirlingFirst 0 k = 0`, `stirlingFirst n 0 = 0`), each false at `0` and each stuck at a free variable, and the suite asserts the counterexample (`stirlingFirst 0 0 = 1`) so a control that stopped discriminating would fail rather than pass quietly. The suite is ungated (no `#![cfg(feature ...)]`) and reports 6 tests.

footprint-Nat.stirlingFirst_eq_zero_of_lt

Kind
exhaustive-enumeration
Status
checked

Supports: axiom_footprint: [] -- the Nat prelude's trusted surface is empty

Checker command
cargo run -q -p axeyum-lean-kernel --example nat_axiom_inventory -- --require-axiom-free nat
Evidence notes

`nat_axiom_inventory --require-axiom-free nat` enumerates the built Nat environment and exits non-zero unless it admits no `Axiom`, `Opaque` or `Quotient` declaration. A theorem cannot depend on a trusted declaration the environment does not contain, so an empty trusted surface bounds every individual theorem's footprint by []. `nat_prelude_tests::every_nat_declaration_is_checked_and_axiom_free` additionally derives its coverage from `kernel.environment()` -- not from a hand list -- and it FIRED on the first run of this lane, naming all ten of these theorems as live but unlisted; they were added to `theorem_names`, where each one's own `Kernel::axiom_footprint` is now checked directly. `prelude_theorem_inventory --include-constructed` prints `nat Nat.stirling... 0` (empty footprint) for all ten.

Provenance

{
  "date": "2026-08-29",
  "established_by": "the `stirling-mirrors` lane, 2026-08-31 (`nat_prelude/stirling_lemmas.rs`)",
  "source": "statement-only extraction of `Nat.stirlingFirst_eq_zero_of_lt` from Mathlib v4.30.0; no proof value was exposed",
  "prior_art": [
    {
      "who": "the Mathlib contributors",
      "what": "the theorem declaration `Nat.stirlingFirst_eq_zero_of_lt`",
      "where": "mathlib4 commit c5ea00351c28e24afc9f0f84379aa41082b1188f (v4.30.0)",
      "year": 2026,
      "attribution": "the proposition was read from the pinned statement-only inventory; the proof term and tactic trace were not consulted"
    }
  ]
}