kernel-Nat.stirlingFirst_self
- Kind
- kernel-term
- Status
- checked
Supports: ((x0 : AxNat) -> Eq.{1} AxNat (AxNat.stirlingFirst x0 x0) (AxNat.succ AxNat.zero))
test "$(cargo run -q --release -p axeyum-lean-kernel --example nat_theorem_inventory -- stirlingFirst_self 2>/dev/null | grep -Ec '^Nat\.stirlingFirst_self[[:space:]]')" -ge 1 Evidence notes
`build_nat_prelude` admits `Nat.stirlingFirst_self` through the trusted `Kernel::add_declaration` gate, declared in `nat_prelude/stirling_lemmas.rs`. `nat_theorem_inventory`'s rendered type is `((x0 : AxNat) -> Eq.{1} AxNat (AxNat.stirlingFirst x0 x0) (AxNat.succ 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 `n`. The step reduces to `n * stirlingFirst n (n+1) + stirlingFirst n n`, whose first summand's factor dies by `stirlingFirst_eq_zero_of_lt` at `n < n+1` and whose second is the induction hypothesis. The residue `add (n * 0) 1` reduces to `1` by iota alone -- `Nat.add` recurses on its RIGHT argument, so the `succ` is carried out and `mul c 0` collapses -- so the chain closes on `Eq.refl 1` and never needs `zero_add`. 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`.