1-- Piece maps: the function a decomposition realises, carrying each point2-- of a piece by the element of that piece. It is an injection of the3-- decomposed set whose image is the union of the moved pieces, and4-- cutting the pieces down to a subset decomposes the subset onto its5-- image under the piece map6-- Part of Cumulus, the Grace17 mathematics library.7-- Copyright (c) 2026 Grant Passmore.8-- Released under the Apache License 2.0. See LICENSE in the repository root.9-- Authors: Grant Passmore1011module Grace.Cumulus.Algebra.Group.Paradox.PieceMaps12import Algebra.Group.Paradox1314-- The piece map of a family F: x is carried to act(g, x) when x lies in15-- the piece of (S, g).16def pieceMap (act X F : Set) : Set:=17 { q ∈ X × X |∃ p ∈ F, fst(q) ∈ fst(p) ∧ snd(q) = act(snd(p), fst(q)) }1819-- Every piece cut down to C, carried by the same element.20defgraph cutPair (X G C : Set) (p ∈𝒫(X) × Group.carrier(G)) :21𝒫(X) × Group.carrier(G) :=22 (fst(p) ∩ C, snd(p))23proof24obtain⟨bound, S, hS, g, hg, shape⟩:= product.membership.forward with member25have subset := powerset.membership_iff.forward with hS26have cut : S ∩ C ⊆ X :=27 Subset.transitive with (intersection.subset_left at S, C), subset28have cutIn := powerset.membership_iff.backward with cut29rw [shape, fst.pair, snd.pair]30exact product.pair with cutIn, hg3132theorem pieceMap.relates (act X F x y : Set)33shows relates(pieceMap(act, X, F), x, y) ↔34 (x, y) ∈ X × X ∧∃ p ∈ F, x ∈ fst(p) ∧ y = act(snd(p), x)35proof36unfold relates37constructor38 . intro h39obtain⟨pair, p, hp, inP, equal⟩:= pieceMap.membership.forward with h40rw fst.pair at inP41rw [fst.pair, snd.pair] at equal42exact⟨pair, p, hp, inP, equal⟩43 . intro h44obtain⟨pair, p, hp, inP, equal⟩:= h45apply pieceMap.membership.backward46refine⟨pair, p, hp, ?_, ?_⟩47 . rw fst.pair48exact inP49 . rw [fst.pair, snd.pair]50exact equal5152-- The two coordinates of a piece: a subset of X and a group element.53theorem piece.parts (G X p : Set)54requires hp : p ∈𝒫(X) × Group.carrier(G)55shows fst(p) ⊆ X ∧ snd(p) ∈ Group.carrier(G)56proof57obtain⟨bound, S, hS, g, hg, shape⟩:= product.membership.forward with hp58have subset := powerset.membership_iff.forward with hS59rw [shape, fst.pair, snd.pair]60exact⟨subset, hg⟩6162theorem cutPair.shape (act G X C p : Set)63requires hp : p ∈𝒫(X) × Group.carrier(G)64shows fst(cutPair(X, G, C)(p)) = fst(p) ∩ C ∧65 moved(act, X, cutPair(X, G, C)(p)) = translate(act, X, snd(p), fst(p) ∩ C)66proof67have value := cutPair.value at X, G, C, p with hp68rw [value, fst.pair, moved.value]69exact⟨rfl, rfl⟩7071section PieceMaps72variable (act G X : Set)73hypothesis action : act : G ↷ X7475theorem pieceMap.relates_of (F p x : Set)76requires bounded : F ⊆𝒫(X) × G.carrier77requires hp : p ∈ F78requires hx : x ∈ fst(p)79shows relates(pieceMap(act, X, F), x, act(snd(p), x))80proof81obtain⟨subset, gIn⟩:= piece.parts with (bounded with p, hp)82have xIn := subset with x, hx83have moved : snd(p) ·ₐ x ∈ X := Action.act_mem with action, gIn, xIn84have pair := product.pair with xIn, moved85exact pieceMap.relates.backward with⟨pair, p, hp, hx, rfl⟩8687-- The piece map is a function on the decomposed set.88theorem pieceMap.function (A F : Set)89requires bounded : F ⊆𝒫(X) × G.carrier90requires pieces : Pieces(A, F)91shows pieceMap(act, X, F) : A → X92proof93obtain⟨piecesBounded, piecesCover, piecesDisjoint⟩:= pieces94refine⟨?_, ?_, ?_⟩95 . intros q hq96obtain⟨qIn, p, hp, inPiece, equal⟩:= pieceMap.membership.forward with hq97obtain⟨bound, x, hx, y, hy, shape⟩:= product.membership.forward with qIn98rw [shape, fst.pair] at inPiece99have xIn := piecesBounded with p, hp, x, inPiece100rw shape101exact product.pair with xIn, hy102 . intros x y hxy z hxz103obtain⟨pairY, p, hp, inP, yEq⟩:= pieceMap.relates.forward with hxy104obtain⟨pairZ, q, hq, inQ, zEq⟩:= pieceMap.relates.forward with hxz105havesplit : p = q ∨ p ≠ q bytauto106casessplitwith same | apart107 . rw [yEq, zEq, same]108rfl109 . exfalso110have disjoint := piecesDisjoint with p, hp, q, hq, apart111have absent := Disjoint.iff.forward with disjoint112exact absent with x, inP, inQ113 . intros x hx114obtain⟨p, hp, inP⟩:= piecesCover with x, hx115obtain⟨subset, gIn⟩:= piece.parts with (bounded with p, hp)116have xIn := subset with x, inP117have moved : snd(p) ·ₐ x ∈ X := Action.act_mem with action, gIn, xIn118have related := pieceMap.relates_of with action, bounded, hp, inP119witness act(snd(p), x)120exact⟨moved, related⟩121122theorem pieceMap.apply (A F p x : Set)123requires bounded : F ⊆𝒫(X) × G.carrier124requires pieces : Pieces(A, F)125requires hp : p ∈ F126requires hx : x ∈ fst(p)127shows pieceMap(act, X, F)(x) = snd(p) ·ₐ x128proof129obtain⟨piecesBounded, piecesCover, piecesDisjoint⟩:= pieces130have function := pieceMap.function with action, bounded, pieces131have xIn := piecesBounded with p, hp, x, hx132have related := pieceMap.relates_of with action, bounded, hp, hx133exact FunctionBetween.apply_value with function, xIn, related134135-- The value at a point of a piece lies in the moved piece.136theorem pieceMap.apply_mem (A F p x : Set)137requires bounded : F ⊆𝒫(X) × G.carrier138requires pieces : Pieces(A, F)139requires hp : p ∈ F140requires hx : x ∈ fst(p)141shows pieceMap(act, X, F)(x) ∈ moved(act, X, p)142proof143obtain⟨subset, gIn⟩:= piece.parts with (bounded with p, hp)144have value := pieceMap.apply with action, bounded, pieces, hp, hx145have member : snd(p) ·ₐ x ∈ translate(act, X, snd(p), fst(p)) :=146 translate.act_mem with action, subset, hx147rw [value, moved.unfold]148exact member149150-- With the moved pieces inside B, the piece map lands in B.151theorem pieceMap.codomain (A B F : Set)152requires bounded : F ⊆𝒫(X) × G.carrier153requires pieces : Pieces(A, F)154requires movedBounded : ∀ p ∈ F, moved(act, X, p) ⊆ B155shows pieceMap(act, X, F) : A → B156proof157obtain⟨piecesBounded, piecesCover, piecesDisjoint⟩:= pieces158have function := pieceMap.function with action, bounded, pieces159apply FunctionBetween.codomain_of_values with function160intros x hx161obtain⟨p, hp, inP⟩:= piecesCover with x, hx162have member := pieceMap.apply_mem with action, bounded, pieces, hp, inP163exact movedBounded with p, hp, pieceMap(act, X, F)(x), member164165-- Disjoint moved pieces make the piece map injective.166theorem pieceMap.injective (A B F : Set)167requires bounded : F ⊆𝒫(X) × G.carrier168requires pieces : Pieces(A, F)169requires movedBounded : ∀ p ∈ F, moved(act, X, p) ⊆ B170requires movedDisjoint : ∀ p q ∈ F, p ≠ q →171 Disjoint(moved(act, X, p), moved(act, X, q))172shows InjectiveBetween(pieceMap(act, X, F), A, B)173proof174have group := Action.group with action175obtain⟨piecesBounded, piecesCover, piecesDisjoint⟩:= pieces176have function := pieceMap.codomain with action, bounded, pieces, movedBounded177apply Injective.of_pointwise with function178intros x hx y hy same179obtain⟨p, hp, inP⟩:= piecesCover with x, hx180obtain⟨q, hq, inQ⟩:= piecesCover with y, hy181have memberX := pieceMap.apply_mem with action, bounded, pieces, hp, inP182have memberY := pieceMap.apply_mem with action, bounded, pieces, hq, inQ183have valueX := pieceMap.apply with action, bounded, pieces, hp, inP184have valueY := pieceMap.apply with action, bounded, pieces, hq, inQ185havesplit : p = q ∨ p ≠ q bytauto186casessplitwith equal | apart187 . obtain⟨subset, gIn⟩:= piece.parts with (bounded with p, hp)188have xIn := subset with x, inP189rw← equal at inQ190have yIn := subset with y, inQ191rw [valueX, valueY] at same192rw← equal at same193have backX : snd(p)⁻¹ ·ₐ snd(p) ·ₐ x = x := inv_act_cancel with*194have backY : snd(p)⁻¹ ·ₐ snd(p) ·ₐ y = y := inv_act_cancel with*195have step : snd(p)⁻¹ ·ₐ snd(p) ·ₐ x = snd(p)⁻¹ ·ₐ snd(p) ·ₐ y196rw same197rfl198rw [backX, backY] at step199exact step200 . exfalso201have disjoint := movedDisjoint with p, hp, q, hq, apart202have absent := Disjoint.iff.forward with disjoint203rw same at memberX204exact absent with pieceMap(act, X, F)(y), memberX, memberY205206-- Moved pieces covering B make the piece map onto B.207theorem pieceMap.surjective (A B F : Set)208requires bounded : F ⊆𝒫(X) × G.carrier209requires pieces : Pieces(A, F)210requires movedPieces : MovedPieces(act, X, B, F)211shows SurjectiveBetween(pieceMap(act, X, F), A, B)212proof213obtain⟨piecesBounded, piecesCover, piecesDisjoint⟩:= pieces214obtain⟨movedBounded, movedCover, movedDisjoint⟩:= movedPieces215have function := pieceMap.codomain with action, bounded, pieces, movedBounded216constructor217 . exact function218 . intros y hy219obtain⟨p, hp, member⟩:= movedCover with y, hy220rw moved.unfold at member221obtain⟨yIn, x, hx, yEq⟩:= translate.membership.forward with member222have xIn := piecesBounded with p, hp, x, hx223have related := pieceMap.relates_of with action, bounded, hp, hx224witness x225rw yEq226exact⟨xIn, related⟩227228theorem pieceMap.bijective (A B F : Set)229requires bounded : F ⊆𝒫(X) × G.carrier230requires pieces : Pieces(A, F)231requires movedPieces : MovedPieces(act, X, B, F)232shows BijectiveBetween(pieceMap(act, X, F), A, B)233proof234obtain⟨movedBounded, movedCover, movedDisjoint⟩:= movedPieces235constructor236 . exact pieceMap.injective with action, bounded, pieces, movedBounded,237 movedDisjoint238 . exact pieceMap.surjective with action, bounded, pieces, movedPieces239240-- Restriction: cutting the pieces down to C ⊆ A decomposes C onto its241-- image under the piece map.242theorem Equidecomposable.restrict (A B C F : Set)243requires finite : Finite(F)244requires bounded : F ⊆𝒫(X) × G.carrier245requires pieces : Pieces(A, F)246requires movedBounded : ∀ p ∈ F, moved(act, X, p) ⊆ B247requires movedDisjoint : ∀ p q ∈ F, p ≠ q →248 Disjoint(moved(act, X, p), moved(act, X, q))249requires subset : C ⊆ A250shows Equidecomposable(act, G, X, C, functionImage(pieceMap(act, X, F), C, B))251proof252obtain⟨piecesBounded, piecesCover, piecesDisjoint⟩:= pieces253have cutFunction := cutPair.function at X, G, C254have cuts : ∀ p ∈ F, fst(cutPair(X, G, C)(p)) = fst(p) ∩ C ∧255 moved(act, X, cutPair(X, G, C)(p)) = translate(act, X, snd(p), fst(p) ∩ C)256intros p hp257exact cutPair.shape at act, G, X, C, p with (bounded with p, hp)258have movedCut : ∀ p ∈ F, moved(act, X, cutPair(X, G, C)(p)) ⊆ moved(act, X, p)259intros p hp260obtain⟨first, second⟩:= cuts with p, hp261have inner := intersection.subset_left at fst(p), C262rw [second, moved.unfold]263exact translate.monotone at act, X, snd(p), fst(p) ∩ C, fst(p) with inner264apply Equidecomposable.of_reindex with cutFunction, finite, bounded265 . intros p hp266obtain⟨first, second⟩:= cuts with p, hp267rw first268exact intersection.subset_right at fst(p), C269 . intros x hx270obtain⟨p, hp, inP⟩:= piecesCover with x, (subset with x, hx)271obtain⟨first, second⟩:= cuts with p, hp272have both := intersection.membership.backward at fst(p), C, x with⟨inP, hx⟩273witness p274rw first275exact⟨hp, both⟩276 . intros p hp q hq different277obtain⟨firstP, secondP⟩:= cuts with p, hp278obtain⟨firstQ, secondQ⟩:= cuts with q, hq279have disjoint := piecesDisjoint with p, hp, q, hq, different280have innerP := intersection.subset_left at fst(p), C281have innerQ := intersection.subset_left at fst(q), C282have step := Disjoint.of_subset_left with disjoint, innerP283rw [firstP, firstQ]284exact Disjoint.of_subset_right with step, innerQ285 . intros p hp286obtain⟨first, second⟩:= cuts with p, hp287rw second288intros y hy289obtain⟨yIn, x, hx, yEq⟩:= translate.membership.forward with hy290obtain⟨inP, inC⟩:= intersection.membership.forward with hx291have value := pieceMap.apply with action, bounded, pieces, hp, inP292have member := pieceMap.apply_mem with action, bounded, pieces, hp, inP293rw [value, ← yEq] at member294have inB := movedBounded with p, hp, y, member295apply functionImage.membership.backward296refine⟨inB, x, inC, ?_⟩297rw [value, yEq]298rfl299 . intros y hy300obtain⟨inB, x, hx, yEq⟩:= functionImage.membership.forward with hy301obtain⟨p, hp, inP⟩:= piecesCover with x, (subset with x, hx)302obtain⟨first, second⟩:= cuts with p, hp303obtain⟨subsetP, gIn⟩:= piece.parts with (bounded with p, hp)304have value := pieceMap.apply with action, bounded, pieces, hp, inP305have inner := intersection.subset_left at fst(p), C306have cutBounded : fst(p) ∩ C ⊆ X := Subset.transitive with inner, subsetP307have both := intersection.membership.backward at fst(p), C, x with⟨inP, hx⟩308have member : snd(p) ·ₐ x ∈ translate(act, X, snd(p), fst(p) ∩ C) :=309 translate.act_mem with action, cutBounded, both310witness p311rw [second, yEq, value]312exact⟨hp, member⟩313 . intros p hp q hq different314have disjoint := movedDisjoint with p, hp, q, hq, different315have step := Disjoint.of_subset_left with disjoint, (movedCut with p, hp)316exact Disjoint.of_subset_right with step, (movedCut with q, hq)317318end PieceMaps319