Shuffles #
A (p, q)-shuffle is an injective monotone map Fin (p + q + 1) → Fin (p + 1) × Fin (q + 1),
i.e. a lattice path from (0, 0) to (p, q) taking unit left and right steps. This file develops
the combinatorics of shuffles needed for the Eilenberg–Zilber shuffle map: inversion counts and
signs, the boundary decomposition of a shuffle into insertions of left/right steps, and the
sign-reversing involution swapDiagonalSteps that cancels the diagonal boundary terms.
Shuffles #
The finite chain object 0 ≤ 1 ≤ ··· ≤ k in PoSet, represented by Fin (k+1).
Equations
- LeanPool.EilenbergZilber.Index k = Fin (k + 1)
Instances For
There are finitely many (p,q)-shuffles: exactly Nat.choose (p + q) p.
Swap the two coordinates of a shuffle, yielding a (q,p)-shuffle.
Equations
- μ.swap = ⟨{ toFun := fun (x : LeanPool.EilenbergZilber.Index (q + p)) => (↑μ ((Fin.castOrderIso ⋯) x)).swap, monotone' := ⋯ }, ⋯⟩
Instances For
Swapping coordinates gives an equivalence Shuffle p q ≃ Shuffle q p.
Equations
- LeanPool.EilenbergZilber.Shuffle.swapEquiv p q = { toFun := LeanPool.EilenbergZilber.Shuffle.swap, invFun := LeanPool.EilenbergZilber.Shuffle.swap, left_inv := ⋯, right_inv := ⋯ }
Instances For
Lattice path structure #
A shuffle path crosses every intermediate snd-level: for i + 1 ≤ q there is a step a
that is a q-step at level i — the second coordinate goes i → i + 1 while the first
coordinate is fixed. This is the degeneracy analog of the face-insertion step lemmas, and is what
lets the Eilenberg–Zilber map carry a one-direction degeneracy to a diagonal one.
The first-coordinate analog of exists_snd_step: for i + 1 ≤ p there is a p-step at
level i — the first coordinate goes i → i + 1 while the second coordinate is fixed. Used for
the outer (horizontal) Eilenberg–Zilber degeneracy kill.
Shuffle (0,0) #
There is exactly one (0,0)-shuffle.
The staircase (r,m)-shuffle k ↦ (min(k,r), k - r): it goes right r steps then up
m steps (the lexicographically smallest shuffle path). Its front-r face and back-m face
recover the identity, so it is the unique shuffle contributing the identity summand to the
diagonal Eilenberg–Zilber/Alexander–Whitney pairing.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The staircase shuffle has no inversions, hence sign 1.
Face-shuffle decomposition (Leibniz rule infrastructure) #
Why "remove step" doesn't work. An earlier attempt defined removeLeftStep μ r
by removing vertex r from the shuffle path whenever step r is a left step.
This is wrong: the face map δ_r removes vertex r, which merges the steps
on either side of r. If those steps have different types (one left, one right),
the merged step is a diagonal (both coordinates increase), which cannot be a
valid shuffle step.
Example: the (1,1)-shuffle (0,0) → (1,0) → (1,1) has step 0 = Left,
step 1 = Right. Removing vertex 1 = (1,0) gives (0,0) → (1,1), a diagonal.
This doesn't factor as ν ≫ (δⱼ × id) for any shuffle ν. The factorization
only works for "LL" vertices (both adjacent steps are left) or "RR" vertices.
The insert approach. Instead of decomposing the LHS face terms, we work from
the RHS and inject into the LHS. Given a (p, q+1)-shuffle ν and a face
index j : Fin (p+2), we construct a (p+1, q+1)-shuffle insertLeftStep ν j
by lifting ν's first coordinate via Fin.succAbove j (skipping value j) and
inserting a new left step where the first coordinate crosses j.
The proof of universalSimplexCrossProduct_boundary then proceeds:
- Show the RHS terms inject into the LHS via
insertLeftStep/insertRightStep. - Show the remaining LHS terms (diagonal terms) cancel via a sign-reversing
involution
swapDiagonalSteps.
Insertion indices #
The vertex index in the (p+1, q)-shuffle's domain where the new left step
was inserted. Removing this vertex via δ recovers the original shuffle.
Equals the number of vertices of ν whose first coordinate is < j.
Instances For
The vertex index where the new right step was inserted.
Equals the number of vertices of ν whose second coordinate is < k.
Instances For
Insertion helpers #
The insertion index satisfies t ≤ j + q: vertices with fst < j have
index ≤ (j-1) + q by coordSum_eq, so there are at most j + q of them.
Insertion maps (RHS → LHS direction) #
The underlying piecewise map for insertLeftStep: before the insertion point,
embed the original vertex via succAbove j; at the insertion point, place (j, t-j);
after the insertion point, embed the shifted-back vertex via succAbove j.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Insert a left step at face index j, turning a (p, q)-shuffle into a
(p+1, q)-shuffle. The original path from (0,0) to (p, q) is embedded
into a path from (0,0) to (p+1, q) by applying Fin.succAbove j to the
first coordinate and inserting a new left step where the first coordinate
crosses j.
Equations
- ν.insertLeftStep j = ⟨{ toFun := ν.insertLeftStepFun j, monotone' := ⋯ }, ⋯⟩
Instances For
The underlying piecewise map for insertRightStep: before the insertion point,
embed the original vertex via succAbove k on the second coordinate; at the
insertion point, place (t-k, k); after the insertion point, embed the
shifted-back vertex via succAbove k.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Insert a right step at face index k, turning a (p, q)-shuffle into a
(p, q+1)-shuffle. Applies Fin.succAbove k to the second coordinate and
inserts a new right step where the second coordinate crosses k.
Equations
- ν.insertRightStep k = ⟨{ toFun := ν.insertRightStepFun k, monotone' := ⋯ }, ⋯⟩
Instances For
Inserting a left step and removing the inserted vertex recovers the original
shuffle with Fin.succAbove j applied to the first coordinate.
(Purely combinatorial: no SimplexCategory or topology needed.)
Inserting a right step and removing the inserted vertex recovers the original
shuffle with Fin.succAbove k applied to the second coordinate.
The insert-left map (j, ν) ↦ (insertLeftStep ν j, insertLeftIndex ν j) is
injective: distinct (j, ν) pairs produce distinct (μ, vertex) pairs.
The insert-right map is injective.
Helper lemmas for sign_insertLeftStep #
The proof reduces to an inversion-count identity: inserting a left step at
position j adds exactly t - j to the inversion count, where
t = insertLeftIndex ν j. We split the invCount sum at t using
Fin.sum_univ_succAbove, match the non-inserted terms against invCount ν,
and compute the contribution of the inserted step directly.
Sign relation for left insertion:
(insertLeftStep ν j).sign * (-1)^(insertLeftIndex ν j) = (-1)^j * ν.sign.
Derived from invCount_insertLeftStep_add via exponent arithmetic:
the identity invCount(μ) + j = invCount(ν) + t gives
(-1)^(invCount(μ) + j) = (-1)^(invCount(ν) + t), hence
sign(μ) * (-1)^j = sign(ν) * (-1)^t, and multiplying both sides
by (-1)^(j+t) (using (-1)^(2k) = 1) yields the result.
Diagonal cancellation #
The LHS terms not in the image of insertLeftStep or insertRightStep are
"diagonal" terms: they arise from vertex removals where the steps on either
side have different types (one left, one right). These cancel pairwise via
a sign-reversing involution that swaps the two steps around the removed vertex.
A (μ, r) pair is a diagonal term if vertex r has one adjacent left
step and one adjacent right step (in either order LR or RL).
Boundary vertices (r = 0 or r = last) are never diagonal.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- μ.decidablePredIsDiagonalVertex r = id (if h : 0 < ↑r then ⋯.mpr (if h_1 : ↑r < p + q then ⋯.mpr inferInstance else ⋯.mpr inferInstance) else ⋯.mpr inferInstance)
Insertion–diagonal interface #
The insertion maps produce exactly the non-diagonal terms of the boundary sum. Each insertion lands in the non-diagonal set, together they cover it, and their images are disjoint.
Left insertion always produces a non-diagonal vertex: the two steps adjacent to the inserted vertex are both left steps (LL pattern).
Right insertion always produces a non-diagonal vertex: the two steps adjacent to the inserted vertex are both right steps (RR pattern).
A vertex r is a "left vertex" if the adjacent steps are both left steps
(or it is a boundary vertex adjacent to a left step).
Equations
- μ.isLeftVertex r = ((∀ (k : Fin (p + q)), k.succ = r → μ.isLeftStep k) ∧ ∀ (k : Fin (p + q)), k.castSucc = r → μ.isLeftStep k)
Instances For
A vertex r is a "right vertex" if the adjacent steps are both right steps.
Equations
- μ.isRightVertex r = ((∀ (k : Fin (p + q)), k.succ = r → ¬μ.isLeftStep k) ∧ ∀ (k : Fin (p + q)), k.castSucc = r → ¬μ.isLeftStep k)
Instances For
Removing a left step at r (assuming isLeftVertex μ r).
Equations
Instances For
Removing a right step at r (assuming isRightVertex μ r).
Equations
Instances For
The shuffle obtained by removing a left step.
Equations
- μ.removeLeft r h = ⟨{ toFun := μ.removeLeftFun r, monotone' := ⋯ }, ⋯⟩
Instances For
The shuffle obtained by removing a right step.
Equations
- μ.removeRight r h = ⟨{ toFun := μ.removeRightFun r, monotone' := ⋯ }, ⋯⟩
Instances For
Left insertion produces a left-type vertex: the step at (or just before)
the inserted vertex is a left step. Here isLeftType checks isLeftStep
at index min r.val ((p+1)+(q)-1).
Right insertion produces a non-left-type vertex: the step at (or just before) the inserted vertex is a right step, not a left step.
Extract the two facts from isDiagonalVertex: 0 < r and r < (p+1)+(q+1).
At a diagonal vertex with a left step at r-1, the shuffle step from
r-1 to r increments fst, giving μ(r).1 ≥ 1.
At a diagonal vertex with a right step at r-1, the shuffle step from
r-1 to r increments snd, giving μ(r).2 ≥ 1.
The underlying function for swapDiagonalSteps: agrees with μ everywhere
except at vertex r, where the step type is swapped.
- LR diagonal (left then right):
μ(r)becomes(μ(r).1 - 1, μ(r).2 + 1) - RL diagonal (right then left):
μ(r)becomes(μ(r).1 + 1, μ(r).2 - 1)
Equations
- One or more equations did not get rendered due to their size.
Instances For
swapDiagonalStepsFun is injective. Follows from monotonicity +
coordinate-sum preservation (same argument as for insertLeftStep).
The sign-reversing involution on diagonal terms. Given a (p+1, q+1)-shuffle
μ and a diagonal vertex r, swap the steps adjacent to r (replacing an LR
corner with RL or vice versa). This produces a new shuffle μ' such that:
μ' ∘ δ_r = μ ∘ δ_r(same underlying map after vertex removal)μ'.sign = -μ.sign(opposite sign, from the inversion count change)
Equations
- μ.swapDiagonalSteps r hr = ⟨{ toFun := μ.swapDiagonalStepsFun r hr, monotone' := ⋯ }, ⋯⟩
Instances For
The swap negates the signed coefficient.
Derives from swapDiagonalSteps_invCount_sum_odd: since the invCount sum is
odd, (-1)^invCount' * (-1)^invCount = -1, and multiplying both sides by
(-1)^invCount (which squares to 1) gives (-1)^invCount' = -(-1)^invCount.
The swap involution is never the identity: swapping two steps of different type always produces a distinct shuffle.