1-- Restricting far-wall faces to the lower cube is a bijection onto the2-- completely labelled simplices there, so the two counts agree3-- Part of Cumulus, the Grace17 mathematics library.4-- Copyright (c) 2026 Grant Passmore.5-- Released under the Apache License 2.0. See LICENSE in the repository root.6-- Authors: Grant Passmore78module Grace.Cumulus.FixedPoint.KuhnWallCount9import KuhnLift1011defgraph wallRestrict (p m lab : Set) (f ∈ topWallFaces(p, m, lab)) : 𝒫(functionSpace(m, succ(p))) :=12 functionImage(cubeRestrict(m, p), f, functionSpace(m, succ(p)))13proof14exact powerset.membership_iff.backward with (functionImage.subset at cubeRestrict(m, p), f, functionSpace(m, succ(p)))1516theorem topWallFaces.cube (m p : Nat) (lab f : Set)17requires hf : f ∈ topWallFaces(p, m, lab)18shows f ⊆ functionSpace(succ(m), succ(p)) ∧∀ x ∈ f, x(m) = p19proof20obtain⟨fIn, top⟩:= topWallFaces.membership.forward with hf21have parts := labelledFaces.membership.forward with fIn22constructor23 . exact powerset.membership_iff.forward with parts.left24 . exact top2526theorem wallRestrict.subset_of_image (m p : Nat) (f g : Set)27requires fCube : f ⊆ functionSpace(succ(m), succ(p))28requires fTop : ∀ x ∈ f, x(m) = p29requires gCube : g ⊆ functionSpace(succ(m), succ(p))30requires gTop : ∀ x ∈ g, x(m) = p31requires inclusion : functionImage(cubeRestrict(m, p), f, functionSpace(m, succ(p))) ⊆32 functionImage(cubeRestrict(m, p), g, functionSpace(m, succ(p)))33shows f ⊆ g34proof35have function := cubeRestrict.function at m, p with*36intros x hx37have xIn := fCube with x, hx38have value := cubeRestrict.value with xIn39have inImage : cubeRestrict(m, p)(x) ∈ functionImage(cubeRestrict(m, p), f, functionSpace(m, succ(p)))40apply functionImage.membership.backward41constructor42 . exact FunctionBetween.apply_closed with function, xIn43 . witness x44constructor45 . exact hx46 . rfl47have inG := inclusion with inImage48obtain⟨yIn, x2, hx2, shape⟩:= functionImage.membership.forward with inG49have x2In := gCube with x2, hx250have value2 := cubeRestrict.value with x2In51rw [value, value2] at shape52have back := cubeRestrict.extend with xIn, (fTop with hx)53have back2 := cubeRestrict.extend with x2In, (gTop with hx2)54 rwa [← back, shape, back2]5556theorem wallRestrict.injective (m p : Nat) (lab : Set)57shows InjectiveBetween(wallRestrict(p, m, lab), topWallFaces(p, m, lab), 𝒫(functionSpace(m, succ(p))))58proof59have function := wallRestrict.function at p, m, lab60apply Injective.of_cancel with function61intros f hf g hg same62have fValue := wallRestrict.value with hf63have gValue := wallRestrict.value with hg64rw [fValue, gValue] at same65obtain⟨fCube, fTop⟩:= topWallFaces.cube with hf66obtain⟨gCube, gTop⟩:= topWallFaces.cube with hg67have forward : functionImage(cubeRestrict(m, p), f, functionSpace(m, succ(p))) ⊆ functionImage(cubeRestrict(m, p), g, functionSpace(m, succ(p)))68rw same69intros y hy70exact hy71have backward : functionImage(cubeRestrict(m, p), g, functionSpace(m, succ(p))) ⊆ functionImage(cubeRestrict(m, p), f, functionSpace(m, succ(p)))72rw same73intros y hy74exact hy75apply Subset.antisymmetric76 . exact wallRestrict.subset_of_image with fCube, fTop, gCube, gTop, forward77 . exact wallRestrict.subset_of_image with gCube, gTop, fCube, fTop, backward7879-- The restriction of a far-wall face is a completely labelled simplex of the80-- lower cube.81theorem wallRestrict.complete (m p : Nat) (lab L f : Set)82requires labFunction : lab : functionSpace(succ(m), succ(p)) → L83requires fullWall : ∀ x ∈ functionSpace(succ(m), succ(p)), ∀ j ∈ succ(m), x(j) = p → lab(x)(j) =184requires hf : f ∈ topWallFaces(p, m, lab)85shows wallRestrict(p, m, lab)(f) ∈ completeSimplices(p, m, wallLabels(m, p, lab, L))86proof87have value := wallRestrict.value with hf88rw value89obtain⟨fIn, top⟩:= topWallFaces.membership.forward with hf90have fParts := labelledFaces.membership.forward with fIn91have fCube := powerset.membership_iff.forward with fParts.left92obtain⟨s, hs, a, ha, shape⟩:= fParts.right.left93have labels := fParts.right.right94obtain⟨b, baseFunction, bounds, u, updBijective, sShape⟩:= kuhnSimplices.shape with hs95have updInjective := Bijective.injective with updBijective96rw sShape at ha97rw sShape at shape98have mIn := bootstrap.succ.self at m99have zeroLess : 0 < succ(m) byarith100have positive := membership.of_Less with zeroLess101have zeroLess2 : 0 < succ(succ(m)) byarith102have zeroIn := membership.of_Less with zeroLess2103obtain⟨inSpace, i, hi, aShape⟩:= kuhnSimplex.membership.forward with ha104have flat : ∀ x ∈ kuhnSimplex(succ(m), b, u) ∖ {kuhnVertex(succ(m), b, u)(i)}, x(m) = p105rwunder← aShape106 rwa under← shape107have below := bounds with mIn108have bottom := kuhnSimplex.full_face_bottom with baseFunction, updBijective, hi, mIn, below, flat109rw bottom at aShape110rw aShape at shape111have oneLess : succ(0) < succ(succ(m)) byarith112have oneIn := membership.of_Less with oneLess113have oneMember := kuhnVertex.member at succ(m), b, u, succ(0) with baseFunction, oneIn114have oneInFace : kuhnVertex(succ(m), b, u)(succ(0)) ∈ kuhnSimplex(succ(m), b, u) ∖ {kuhnVertex(succ(m), b, u)(0)}115apply difference.singleton_membership.backward116constructor117 . exact oneMember118 . intro equal119have same := kuhnVertex.injective with baseFunction, updInjective, oneIn, zeroIn, equal120arith121rw← shape at oneInFace122have oneTop := top with oneInFace123have first : u(0) = m124have coordinate := kuhnVertex.coordinate_succ with baseFunction, updInjective, positive, mIn125have zeroValue := kuhnVertex.zero_coordinate at succ(m), b, u, m with baseFunction, mIn126rw [coordinate, zeroValue] at oneTop127have baseNat := nat.omega.backward with (FunctionBetween.apply_closed with baseFunction, mIn)128by_contra different129have zero := indicator.singleton_other with different130rw zero at oneTop131arith132have face := kuhnSimplex.wall_face with baseFunction, bounds, updBijective, first133have imageEq : functionImage(cubeRestrict(m, p), f, functionSpace(m, succ(p))) =134 kuhnSimplex(m, restrict(b, m), wallPerm(m, u))135 rwa shape136rw imageEq137apply completeSimplices.membership.backward138constructor139 . have mSubset := successor.subset at m140have restrictedBase := restrict.domain_function with baseFunction, mSubset141have restrictedBounds : ∀ j ∈ m, restrict(b, m)(j) < p142intros j hj143have baseValue := restrict.domain_apply with baseFunction, mSubset, hj144rw baseValue145exact bounds with (membership.into_successor with hj)146have wallBijective := wallPerm.bijective with updBijective, first147exact kuhnSimplex.in_family with restrictedBase, wallBijective, restrictedBounds148 . have transfer := labelImage.restrict_wall with labFunction, fullWall, fCube, top149 rwa [imageEq, labels] at transfer150151-- Every completely labelled simplex of the lower cube is the restriction of152-- a far-wall face.153theorem wallRestrict.onto (m q : Nat) (lab L t : Set)154requires labFunction : lab : functionSpace(succ(m), succ(succ(q))) → L155requires fullWall : ∀ x ∈ functionSpace(succ(m), succ(succ(q))), ∀ j ∈ succ(m), x(j) = succ(q) → lab(x)(j) =1156requires ht : t ∈ completeSimplices(succ(q), m, wallLabels(m, succ(q), lab, L))157shows∃ f ∈ topWallFaces(succ(q), m, lab), wallRestrict(succ(q), m, lab)(f) = t158proof159obtain⟨tIn, complete⟩:= completeSimplices.membership.forward with ht160obtain⟨b, baseFunction, bounds, u, updBijective, tShape⟩:= kuhnSimplices.shape with tIn161have liftFunction := liftBase.function at m, q, b with baseFunction162have lifted := liftPerm.bijective with updBijective163have zero := liftPerm.zero with updBijective164have liftBounds : ∀ j ∈ succ(m), liftBase(m, q, b)(j) < succ(q)165intros j hj166havesplit:= bootstrap.succ.membership.forward with hj167casessplitwith below | same168 . have value := liftBase.apply_below at m, q, b, j with baseFunction, below169rw value170exact bounds with below171 . rw same172have value := liftBase.apply_top at m, q, b with baseFunction173rw value174arith175have sIn := kuhnSimplex.lift_in_family with baseFunction, bounds, updBijective176have face := kuhnSimplex.wall_face with liftFunction, liftBounds, lifted, zero177have restrictBase := liftBase.restrict at m, q, b with baseFunction178have restrictPerm := wallPerm.lift with updBijective179rw [restrictBase, restrictPerm, ← tShape] at face180have zeroLess : 0 < succ(succ(m)) byarith181have zeroIn := membership.of_Less with zeroLess182have bottomMember := kuhnVertex.member at succ(m), liftBase(m, q, b), liftPerm(m, u), 0with liftFunction, zeroIn183have faceCube : kuhnSimplex(succ(m), liftBase(m, q, b), liftPerm(m, u)) ∖ {kuhnVertex(succ(m), liftBase(m, q, b), liftPerm(m, u))(0)} ⊆ functionSpace(succ(m), succ(succ(q)))184intros x hx185have parts := difference.singleton_membership.forward with hx186obtain⟨inSpace, i, hi, xShape⟩:= kuhnSimplex.membership.forward with parts.left187rw xShape188exact kuhnVertex.into_cube with liftFunction, liftBounds, hi189have faceTop : ∀ x ∈ kuhnSimplex(succ(m), liftBase(m, q, b), liftPerm(m, u)) ∖ {kuhnVertex(succ(m), liftBase(m, q, b), liftPerm(m, u))(0)}, x(m) = succ(q)190intros x hx191exact kuhnSimplex.lift_top_wall with baseFunction, updBijective, hx192have faceIn : kuhnSimplex(succ(m), liftBase(m, q, b), liftPerm(m, u)) ∖ {kuhnVertex(succ(m), liftBase(m, q, b), liftPerm(m, u))(0)} ∈ topWallFaces(succ(q), m, lab)193apply topWallFaces.membership.backward194constructor195 . apply labelledFaces.membership.backward196constructor197 . exact powerset.membership_iff.backward with faceCube198 . constructor199 . witness kuhnSimplex(succ(m), liftBase(m, q, b), liftPerm(m, u))200constructor201 . exact sIn202 . witness kuhnVertex(succ(m), liftBase(m, q, b), liftPerm(m, u))(0)203constructor204 . exact bottomMember205 . rfl206 . have transfer := labelImage.restrict_wall with labFunction, fullWall, faceCube, faceTop207rw [face, complete] at transfer208 symm209exact transfer210 . exact faceTop211witness kuhnSimplex(succ(m), liftBase(m, q, b), liftPerm(m, u)) ∖ {kuhnVertex(succ(m), liftBase(m, q, b), liftPerm(m, u))(0)}212constructor213 . exact faceIn214 . have value := wallRestrict.value at succ(q), m, lab, kuhnSimplex(succ(m), liftBase(m, q, b), liftPerm(m, u)) ∖ {kuhnVertex(succ(m), liftBase(m, q, b), liftPerm(m, u))(0)} with faceIn215 rwa value216217theorem topWallFaces.count (m q : Nat) (lab L : Set)218requires labFunction : lab : functionSpace(succ(m), succ(succ(q))) → L219requires fullWall : ∀ x ∈ functionSpace(succ(m), succ(succ(q))), ∀ j ∈ succ(m), x(j) = succ(q) → lab(x)(j) =1220shows cardinality(topWallFaces(succ(q), m, lab)) =221 cardinality(completeSimplices(succ(q), m, wallLabels(m, succ(q), lab, L)))222proof223have injective := wallRestrict.injective at m, succ(q), lab224have function := wallRestrict.function at succ(q), m, lab225have selfSubset : topWallFaces(succ(q), m, lab) ⊆ topWallFaces(succ(q), m, lab)226intros f hf227exact hf228have finite : Finite(topWallFaces(succ(q), m, lab))229have inside : topWallFaces(succ(q), m, lab) ⊆ labelledFaces(succ(q), succ(m), lab)230intros f hf231have parts := topWallFaces.membership.forward with hf232exact parts.left233exact Finite.subset with (labelledFaces.finite at succ(m), succ(q), lab), inside234have count := cardinality.injective_image with injective, selfSubset, finite235have same : functionImage(wallRestrict(succ(q), m, lab), topWallFaces(succ(q), m, lab), 𝒫(functionSpace(m, succ(succ(q))))) =236 completeSimplices(succ(q), m, wallLabels(m, succ(q), lab, L))237ext t238constructor239 . intro ht240obtain⟨tIn, f, hf, shape⟩:= functionImage.membership.forward with ht241rw shape242exact wallRestrict.complete with labFunction, fullWall, hf243 . intro ht244obtain⟨f, hf, shape⟩:= wallRestrict.onto with labFunction, fullWall, ht245apply functionImage.membership.backward246constructor247 . rw← shape248exact FunctionBetween.apply_closed with function, hf249 . witness f250constructor251 . exact hf252 . symm253exact shape254rw same at count255 symm256exact count257