1-- Kuhn's lemma: a labelling of the grid points of a cube that respects its2-- walls has a completely labelled Kuhn simplex, so some cell carries, in3-- every coordinate, two points with different labels4-- Part of Cumulus, the Grace17 mathematics library.5-- Copyright (c) 2026 Grant Passmore.6-- Released under the Apache License 2.0. See LICENSE in the repository root.7-- Authors: Grant Passmore89module Grace.Cumulus.FixedPoint.KuhnInduction10import KuhnWallCount1112theorem successor.zero_member (k : Set)13requires hk : k ∈ succ(0)14shows k =015proof16havesplit:= bootstrap.succ.membership.forward with hk17casessplitwith below | same18 . exfalso19have kNat := natural.member at succ(0) with hk20have less := Less.of_membership with below21arith22 . exact same2324-- In dimension zero the only simplex is the single empty function.25theorem kuhnSimplices.zero_subset (p : Nat) (s : Set)26requires hs : s ∈ kuhnSimplices(p, 0)27shows s = {∅}28proof29have parts := kuhnSimplices.membership.forward with hs30have inCube := powerset.membership_iff.forward with parts.left31have cubeEq : functionSpace(0, succ(p)) = {∅}32rw nat.zero33exact functionSpace.empty_domain34rw cubeEq at inCube35obtain⟨base, baseFunction, bounds, upd, updBijective, shape⟩:= kuhnSimplices.shape with hs36have zeroIn := bootstrap.succ.self at037have vertexIn : kuhnVertex(0, base, upd)(0) ∈ s38rw shape39exact kuhnVertex.member with baseFunction, zeroIn40have vertexSingleton := inCube with vertexIn41have vertexEq := singleton.membership.forward with vertexSingleton42apply Subset.antisymmetric43 . exact inCube44 . intros x hx45have xEq := singleton.membership.forward with hx46 rwa [xEq, ← vertexEq]4748theorem kuhnSimplices.zero_member (p : Nat)49shows {∅} ∈ kuhnSimplices(p, 0)50proof51have emptyFunction := FunctionBetween.empty at ℕ52have baseFunction : ∅ : 0→ ℕ by rwa nat.zero53have bounds : ∀ j ∈0, apply(∅, j) < p54intros j hj55exfalso56have jNat := natural.member at0with hj57have less := Less.of_membership with hj58arith59have updBijective := identity.bijective at060have member := kuhnSimplex.in_family with baseFunction, updBijective, bounds61have same := kuhnSimplices.zero_subset with member62 rwa same at member6364theorem kuhnSimplices.zero (p : Nat)65shows kuhnSimplices(p, 0) = {{∅}}66proof67apply Subset.antisymmetric68 . intros s hs69apply singleton.membership.backward70exact kuhnSimplices.zero_subset with hs71 . intros s hs72have same := singleton.membership.forward with hs73rw same74exact kuhnSimplices.zero_member7576theorem completeSimplices.zero (p : Nat) (lab : Set)77shows completeSimplices(p, 0, lab) = kuhnSimplices(p, 0)78proof79apply Subset.antisymmetric80 . intros s hs81have parts := completeSimplices.membership.forward with hs82exact parts.left83 . intros s hs84apply completeSimplices.membership.backward85constructor86 . exact hs87 . have same := kuhnSimplices.zero_subset with hs88apply Subset.antisymmetric89 . intros k hk90have parts := labelImage.membership.forward with hk91exact parts.left92 . intros k hk93have kEq := successor.zero_member with hk94have emptyIn : ∅∈ s95rw same96apply singleton.membership.backward97rfl98have bound := reduced.bound at0, lab, ∅99have reducedEq := successor.zero_member with bound100apply labelImage.membership.backward101constructor102 . exact hk103 . witness∅104constructor105 . exact emptyIn106 . rw [kEq, reducedEq]107rfl108109theorem kuhn.base (p : Nat) (lab : Set)110shows Odd(cardinality(completeSimplices(p, 0, lab)))111proof112have complete := completeSimplices.zero at p, lab113have family := kuhnSimplices.zero at p114have one := cardinality.singleton at {∅}115rw [complete, family, one]116have shape : 1= succ(add(0, 0)) bycompute117rw shape118exact Odd.double_successor119120-- Kuhn's combinatorial lemma: the number of completely labelled simplices121-- is odd, by induction on the dimension.122theorem kuhn.combinatorial (q n : Nat)123shows∀ lab, ∀ L, FunctionBetween(lab, functionSpace(n, succ(succ(q))), L) →124 (∀ x ∈ functionSpace(n, succ(succ(q))), ∀ j ∈ n, x(j) =0→ lab(x)(j) =0) →125 (∀ x ∈ functionSpace(n, succ(succ(q))), ∀ j ∈ n, x(j) = succ(q) → lab(x)(j) =1) →126 Odd(cardinality(completeSimplices(succ(q), n, lab)))127proof128induction n129| zero =>130intros lab L labFunction zeroWall fullWall131exact kuhn.base at succ(q), lab132| succ(m) using ih =>133intros lab L labFunction zeroWall fullWall134have boundaryEq := boundaryDoors.top_wall at m, succ(q), lab with zeroWall, fullWall135have count := topWallFaces.count at m, q, lab, L with labFunction, fullWall136have wallFunction := wallLabels.function at m, succ(q), lab, L with*137have wallZero := wallLabels.zero_wall at m, succ(q), lab, L with labFunction, zeroWall138have wallFull := wallLabels.full_wall at m, succ(q), lab, L with labFunction, fullWall139have lower := ih with wallFunction, wallZero, wallFull140have zeroLess : 0 < succ(m) byarith141have positive := membership.of_Less with zeroLess142apply kuhn.parity at succ(m), succ(q), lab with positive143rw [boundaryEq, count]144exact lower145146-- Kuhn's lemma: some cell of the grid carries, for every coordinate, two147-- points whose labels there differ.148theorem kuhn.lemma (q n : Nat) (lab L : Set)149requires labFunction : lab : functionSpace(n, succ(succ(q))) → L150requires zeroWall : ∀ x ∈ functionSpace(n, succ(succ(q))), ∀ j ∈ n, x(j) =0→ lab(x)(j) =0151requires fullWall : ∀ x ∈ functionSpace(n, succ(succ(q))), ∀ j ∈ n, x(j) = succ(q) → lab(x)(j) =1152shows∃ base ∈ functionSpace(n, ℕ), (∀ j ∈ n, base(j) < succ(q)) ∧153∀ i ∈ n, ∃ u ∈ functionSpace(n, succ(succ(q))), ∃ v ∈ functionSpace(n, succ(succ(q))),154 (∀ j ∈ n, base(j) ≤ u(j) ∧ u(j) ≤ base(j) +1) ∧ (∀ j ∈ n, base(j) ≤ v(j) ∧ v(j) ≤ base(j) +1) ∧155 lab(u)(i) =0∧ lab(v)(i) ≠0156proof157have all := kuhn.combinatorial at q, n158have odd := all with labFunction, zeroWall, fullWall159have inhabited : ∃ s, s ∈ completeSimplices(succ(q), n, lab)160by_contra none161have empty : completeSimplices(succ(q), n, lab) =∅162apply Subset.antisymmetric163 . intros s hs164exfalso165apply none166witness s167exact hs168 . intros s hs169exfalso170 simpa using hs171rw [empty, ← nat.zero] at odd172have zero := cardinality.natural at0173rw zero at odd174obtain⟨k, kIn, shape⟩:= odd175have kNat := nat.omega.backward with kIn176haveself:= bootstrap.succ.self at add(k, k)177rw [← shape, nat.zero] atself178 simpa usingself179obtain⟨s, hs⟩:= inhabited180obtain⟨sIn, complete⟩:= completeSimplices.membership.forward with hs181obtain⟨base, baseFunction, bounds, upd, updBijective, sShape⟩:= kuhnSimplices.shape with sIn182have sParts := kuhnSimplices.membership.forward with sIn183have sCube := powerset.membership_iff.forward with sParts.left184witness base185constructor186 . exact functionSpace.mem_iff.backward with baseFunction187 . constructor188 . exact bounds189 . intros i hi190have iNat := natural.member at n with hi191have iLess := Less.of_membership with hi192have iIn := membership.into_successor with hi193have sLess : succ(i) < succ(n) byarith194have succIn := membership.of_Less with sLess195have upperIn : succ(i) ∈ labelImage(n, lab, s) by rwa complete196have lowerIn : i ∈ labelImage(n, lab, s) by rwa complete197obtain⟨uBound, u, hu, uShape⟩:= labelImage.membership.forward with upperIn198obtain⟨vBound, v, hv, vShape⟩:= labelImage.membership.forward with lowerIn199have uCube := sCube with u, hu200have vCube := sCube with v, hv201have uBetween : ∀ j ∈ n, base(j) ≤ u(j) ∧ u(j) ≤ base(j) +1202intros j hj203rw sShape at hu204obtain⟨inSpace, k, hk, uVertex⟩:= kuhnSimplex.membership.forward with hu205rw uVertex206exact kuhnVertex.between with baseFunction, hk, hj207have vBetween : ∀ j ∈ n, base(j) ≤ v(j) ∧ v(j) ≤ base(j) +1208intros j hj209rw sShape at hv210obtain⟨inSpace, k, hk, vVertex⟩:= kuhnSimplex.membership.forward with hv211rw vVertex212exact kuhnVertex.between with baseFunction, hk, hj213witness u214constructor215 . exact uCube216 . witness v217constructor218 . exact vCube219 . constructor220 . exact uBetween221 . constructor222 . exact vBetween223 . constructor224 . have inReduced : i ∈ reduced(n, lab, u)225rw← uShape226exact bootstrap.succ.self227exact reduced.below with inReduced228 . have stop := reduced.stop at n, lab, v229rw← vShape at stop230cases stop with top | nonzero231 . exfalso232rw top at hi233exact membership.irreflexive with hi234 . exact nonzero235