1-- Group actions: an action act : G ↷ X of a group on a set, written2-- g ·ₐ x, its orbits and stabilizers, the stabilizer a subgroup, the orbit3-- of a point in bijection with the cosets of its stabilizer, so the4-- orbit–stabilizer theorem, the orbits a partition of the set, the fixed5-- points, and the count of the points outside the fixed points6-- 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.Action12import Lagrange13import Homomorphism1415-- act : G ↷ X: a function act : G.carrier × X → X under which the unit16-- acts trivially and a product acts by composition. The form is a17-- transparent guard, so a hypothesis act : G ↷ X also supplies the group G18-- and its operation a * b; the action of g on x is written g ·ₐ x.19predicate Action (act G X : Set) :=20 Group(G) ∧ (act : G.carrier × X → X) ∧21 (∀ x ∈ X, act(G.one, x) = x) ∧22 (∀ g h ∈ G.carrier, ∀ x ∈ X, act(g * h, x) = act(g, act(h, x)))2324notationguard"_ : _ ↷ _"=> Action25notationinfixr73"·ₐ"=> call2(act, _, _) viahypothesis Action(act, G, X) for G.carrier2627-- The orbit of x, its stabilizer, the fixed points of the action, the set28-- of all orbits, and the elements carrying x to y.29def orbit (act G X x : Set) : Set:= { y ∈ X |∃ g ∈ G.carrier, y = act(g, x) }30def stabilizer (act G X x : Set) : Set:= { g ∈ G.carrier | act(g, x) = x }31def fixedPoints (act G X : Set) : Set:=32 { x ∈ X |∀ g ∈ G.carrier, act(g, x) = x }33def orbits (act G X : Set) : Set:=34 { O ∈𝒫(X) |∃ x ∈ X, O = orbit(act, G, X, x) }35def transporters (act G x y : Set) : Set:= { g ∈ G.carrier | act(g, x) = y }3637-- The orbit and the stabilizer of x are written orbit(x) and stabilizer(x)38-- wherever a hypothesis in scope supplies the action.39notation function "orbit(x)"=> orbit(act, G, X, x) viahypothesis Action(act, G, X)40notation function "stabilizer(x)"=> stabilizer(act, G, X, x) viahypothesis Action(act, G, X)4142theorem Action.mk (act G X : Set)43requires group : Group(G)44requires function : act : G.carrier × X → X45requires unit : ∀ x ∈ X, act(G.one, x) = x46requires compatible : ∀ g h ∈ G.carrier, ∀ x ∈ X, act(g * h, x) = act(g, act(h, x))47shows act : G ↷ X48proof49unfold Action50refine⟨group, function, unit, compatible⟩5152theorem orbit.subset (act G X x : Set)53shows orbit(act, G, X, x) ⊆ X54proof55intros y hy56have parts := orbit.membership.forward with hy57exact parts.left5859theorem stabilizer.subset (act G X x : Set)60shows stabilizer(act, G, X, x) ⊆ G.carrier61proof62intros g hg63have parts := stabilizer.membership.forward with hg64exact parts.left6566theorem fixedPoints.subset (act G X : Set)67shows fixedPoints(act, G, X) ⊆ X68proof69intros x hx70have parts := fixedPoints.membership.forward with hx71exact parts.left7273theorem orbits.subset_powerset (act G X : Set)74shows orbits(act, G, X) ⊆𝒫(X)75proof76intros O hO77have parts := orbits.membership.forward with hO78exact parts.left7980theorem orbits.orbit_member (act G X x : Set)81requires hx : x ∈ X82shows orbit(act, G, X, x) ∈ orbits(act, G, X)83proof84have subset := orbit.subset at act, G, X, x85have bounded := powerset.membership_iff.backward with subset86exact orbits.membership.backward with⟨bounded, x, hx, rfl⟩8788section ActionLaws89variable (act G X : Set)90hypothesis action : act : G ↷ X9192theorem Action.group93shows Group(G)94proof95obtain⟨group, rest⟩:= action96exact group9798theorem Action.function99shows act : G.carrier × X → X100proof101obtain⟨group, function, rest⟩:= action102exact function103104theorem one_act (x : Set)105requires hx : x ∈ X106shows G.one ·ₐ x = x107proof108obtain⟨group, function, unit, compatible⟩:= action109exact unit with x, hx110111theorem mul_act (g h : G) (x : Set)112requires hx : x ∈ X113shows (g * h) ·ₐ x = g ·ₐ h ·ₐ x114proof115obtain⟨group, function, unit, compatible⟩:= action116have gIn : g ∈ G byassumption117have hIn : h ∈ G byassumption118exact compatible with g, gIn, h, hIn, x, hx119120-- Closure: the action of an element on a point is a point, so the121-- membership of a compound term is synthesized.122instance Action.act_mem (g : G) (x : Set)123requires hx : x ∈ X124shows g ·ₐ x ∈ X125proof126have function := Action.function with action127have gIn : g ∈ G byassumption128have pair := product.pair at g, x, G.carrier, X with*129unfold call2130exact FunctionBetween.apply_closed with function, pair131132theorem inv_act_cancel (g : G) (x : Set)133requires hx : x ∈ X134shows g⁻¹ ·ₐ g ·ₐ x = x135proof136have group := Action.group with action137have merged : (g⁻¹ * g) ·ₐ x = g⁻¹ ·ₐ g ·ₐ x := mul_act with*138rw [← merged, Group.inv_mul, one_act]139rfl140141theorem act_inv_cancel (g : G) (x : Set)142requires hx : x ∈ X143shows g ·ₐ g⁻¹ ·ₐ x = x144proof145have group := Action.group with action146have merged : (g * g⁻¹) ·ₐ x = g ·ₐ g⁻¹ ·ₐ x := mul_act with*147rw [← merged, Group.mul_inv, one_act]148rfl149150theorem act_left_cancel (g : G) (x y : Set)151requires hx : x ∈ X152requires hy : y ∈ X153requires equal : g ·ₐ x = g ·ₐ y154shows x = y155proof156have group := Action.group with action157calc158 x = g⁻¹ ·ₐ g ·ₐ x :=byrw inv_act_cancel159 _ = g⁻¹ ·ₐ g ·ₐ y :=byrw equal160 _ = y :=byrw inv_act_cancel161162theorem act_eq_iff (g : G) (x y : Set)163requires hx : x ∈ X164requires hy : y ∈ X165shows g ·ₐ x = y ↔ x = g⁻¹ ·ₐ y166proof167have group := Action.group with action168constructor169 . intro equal170rw [← equal, inv_act_cancel]171rfl172 . intro equal173rw [equal, act_inv_cancel]174rfl175176-- Orbits: every point lies in its own orbit, orbits are closed under the177-- action, any member of an orbit generates it, and two orbits are equal or178-- disjoint.179instance orbit.act_mem (g : G) (x : Set)180requires hx : x ∈ X181shows g ·ₐ x ∈ orbit(x)182proof183have moved : g ·ₐ x ∈ X := Action.act_mem with*184have gIn : g ∈ G byassumption185exact orbit.membership.backward with⟨moved, g, gIn, rfl⟩186187theorem orbit.self (x : Set)188requires hx : x ∈ X189shows x ∈ orbit(x)190proof191have group := Action.group with action192have member : G.one ·ₐ x ∈ orbit(x) := orbit.act_mem with*193have fixed : G.one ·ₐ x = x := one_act with*194 rwa fixed at member195196theorem orbit.act_mem_of_mem (g : G) (x y : Set)197requires hx : x ∈ X198requires hy : y ∈ orbit(x)199shows g ·ₐ y ∈ orbit(x)200proof201have group := Action.group with action202obtain⟨yIn, h, hIn, yEq⟩:= orbit.membership.forward with hy203have merged : (g * h) ·ₐ x = g ·ₐ h ·ₐ x := mul_act with*204have member : (g * h) ·ₐ x ∈ orbit(x) := orbit.act_mem with*205rw [yEq, ← merged]206exact member207208theorem orbit.of_member (x y : Set)209requires hx : x ∈ X210requires hy : y ∈ orbit(x)211shows orbit(y) = orbit(x)212proof213have group := Action.group with action214obtain⟨yIn, h, hIn, yEq⟩:= orbit.membership.forward with hy215ext z216constructor217 . intro hz218obtain⟨zIn, g, gIn, zEq⟩:= orbit.membership.forward with hz219have merged : (g * h) ·ₐ x = g ·ₐ h ·ₐ x := mul_act with*220have member : (g * h) ·ₐ x ∈ orbit(x) := orbit.act_mem with*221rw [zEq, yEq, ← merged]222exact member223 . intro hz224obtain⟨zIn, g, gIn, zEq⟩:= orbit.membership.forward with hz225have back : h⁻¹ ·ₐ y = x226rw [yEq, inv_act_cancel]227rfl228have merged : (g * h⁻¹) ·ₐ y = g ·ₐ h⁻¹ ·ₐ y := mul_act with*229have member : (g * h⁻¹) ·ₐ y ∈ orbit(y) := orbit.act_mem with*230rw [zEq, ← back, ← merged]231exact member232233theorem orbit.eq_of_common (x y z : Set)234requires hx : x ∈ X235requires hy : y ∈ X236requires hzx : z ∈ orbit(x)237requires hzy : z ∈ orbit(y)238shows orbit(x) = orbit(y)239proof240have first : orbit(z) = orbit(x) := orbit.of_member with*241have second : orbit(z) = orbit(y) := orbit.of_member with*242 rwa first at second243244theorem orbit.eq_or_disjoint (x y : Set)245requires hx : x ∈ X246requires hy : y ∈ X247shows orbit(x) = orbit(y) ∨ Disjoint(orbit(x), orbit(y))248proof249by_contra neither250apply neither251right252apply Disjoint.iff.backward253intros z hzx hzy254apply neither255left256exact orbit.eq_of_common with*257258theorem orbit.finite (x : Set)259requires finite : Finite(X)260shows Finite(orbit(x))261proof262exact Finite.subset with finite, (orbit.subset at act, G, X, x)263264-- The orbits partition the set.265theorem orbits.cover266shows⋃(orbits(act, G, X)) = X267proof268ext x269constructor270 . intro hx271obtain⟨O, hO, hxO⟩:= union.membership.forward with hx272have bounded := orbits.subset_powerset at act, G, X273have subset := powerset.membership_iff.forward with (bounded with O, hO)274exact subset with x, hxO275 . intro hx276haveself : x ∈ orbit(x) := orbit.self with*277have member := orbits.orbit_member at act, G, X, x with hx278exact union.membership.backward with⟨orbit(x), member, self⟩279280theorem orbits.pairwise_disjoint281shows PairwiseDisjoint(orbits(act, G, X))282proof283intros O hO P hP different284obtain⟨boundO, x, hx, OEq⟩:= orbits.membership.forward with hO285obtain⟨boundP, y, hy, PEq⟩:= orbits.membership.forward with hP286rw [OEq, PEq] at different287rw [OEq, PEq]288havesplit:= orbit.eq_or_disjoint at act, G, X, x, y with*289casessplitwith equal | disjoint290 . exfalso291exact different with equal292 . exact disjoint293294theorem orbits.finite295requires finite : Finite(X)296shows Finite(orbits(act, G, X))297proof298have finitePowerset := Finite.powerset with finite299exact Finite.subset with finitePowerset, (orbits.subset_powerset at act, G, X)300301theorem orbits.member_finite (O : Set)302requires hO : O ∈ orbits(act, G, X)303requires finite : Finite(X)304shows Finite(O)305proof306have bounded := orbits.subset_powerset at act, G, X307have subset := powerset.membership_iff.forward with (bounded with O, hO)308exact Finite.subset with finite, subset309310-- Stabilizers are subgroups.311theorem stabilizer.fixes (g x : Set)312requires hg : g ∈ stabilizer(x)313shows g ·ₐ x = x314proof315have parts := stabilizer.membership.forward with hg316exact parts.right317318theorem stabilizer.of_fixes (g : G) (x : Set)319requires fixed : g ·ₐ x = x320shows g ∈ stabilizer(x)321proof322have gIn : g ∈ G byassumption323exact stabilizer.membership.backward with⟨gIn, fixed⟩324325theorem stabilizer.subgroup (x : Set)326requires hx : x ∈ X327shows Subgroup(stabilizer(x), G)328proof329have group := Action.group with action330have unitIn : G.one ∈ stabilizer(x)331have fixed : G.one ·ₐ x = x := one_act with*332exact stabilizer.of_fixes with*333apply Subgroup.mk with group, (stabilizer.subset at act, G, X, x), unitIn334 . intros g hg h hh335have gIn := stabilizer.subset at act, G, X, x with g, hg336have hIn := stabilizer.subset at act, G, X, x with h, hh337have fixedG : g ·ₐ x = x := stabilizer.fixes with*338have fixedH : h ·ₐ x = x := stabilizer.fixes with*339have fixed : (g * h) ·ₐ x = x340rw [mul_act, fixedH, fixedG]341rfl342exact stabilizer.of_fixes with*343 . intros g hg344have gIn := stabilizer.subset at act, G, X, x with g, hg345have fixedG : g ·ₐ x = x := stabilizer.fixes with*346have fixed : g⁻¹ ·ₐ x = x347calc348 g⁻¹ ·ₐ x = g⁻¹ ·ₐ g ·ₐ x :=byrw fixedG349 _ = x :=byrw inv_act_cancel350exact stabilizer.of_fixes with*351352-- The elements carrying x to g ·ₐ x form the coset of the stabilizer by g.353theorem transporters.eq_coset (g : G) (x : Set)354requires hx : x ∈ X355shows transporters(act, G, x, g ·ₐ x) = g • stabilizer(x)356proof357have group := Action.group with action358have subgroup := stabilizer.subgroup with*359ext h360constructor361 . intro hh362obtain⟨hIn, carries⟩:= transporters.membership.forward with hh363have criterion : h ∈ g • stabilizer(x) ↔ g⁻¹ * h ∈ stabilizer(x) :=364 leftCoset.mem_iff with*365have fixed : (g⁻¹ * h) ·ₐ x = x366rw [mul_act, carries, inv_act_cancel]367rfl368have member : g⁻¹ * h ∈ stabilizer(x) := stabilizer.of_fixes with*369exact criterion.backward with member370 . intro hh371have hIn := leftCoset.subset at G, g, stabilizer(x) with h, hh372have criterion : h ∈ g • stabilizer(x) ↔ g⁻¹ * h ∈ stabilizer(x) :=373 leftCoset.mem_iff with*374have member := criterion.forward with hh375have fixed : (g⁻¹ * h) ·ₐ x = x := stabilizer.fixes with*376have merged : (g * (g⁻¹ * h)) ·ₐ x = g ·ₐ (g⁻¹ * h) ·ₐ x := mul_act with*377rw [mul_inv_cancel_left, fixed] at merged378exact transporters.membership.backward with⟨hIn, merged⟩379380end ActionLaws381382-- Each point of the orbit of x is sent to the coset of the elements383-- carrying x to it.384defgraph orbitCosetMap (act G X x : Set) (y ∈ orbit(act, G, X, x)) :385 leftCosets(G, stabilizer(act, G, X, x)) := transporters(act, G, x, y)386requires action : act : G ↷ X387requires hx : x ∈ X388proof389obtain⟨yIn, g, gIn, yEq⟩:= orbit.membership.forward with member390have coset := transporters.eq_coset with action, hx, gIn391rw [yEq, coset]392exact leftCosets.coset_member with gIn393394section OrbitStabilizer395variable (act G X : Set)396hypothesis action : act : G ↷ X397398theorem orbitCosetMap.injective (x : Set)399requires hx : x ∈ X400shows InjectiveBetween(orbitCosetMap(act, G, X, x), orbit(x),401 leftCosets(G, stabilizer(x)))402proof403have function := orbitCosetMap.function at act, G, X, x with*404constructor405 . exact function406 . intros y hy z hz C hC hyC hzC407have yValue := FunctionBetween.apply_value with function, hy, hyC408have zValue := FunctionBetween.apply_value with function, hz, hzC409have yImage := orbitCosetMap.value at act, G, X, x, y with*410have zImage := orbitCosetMap.value at act, G, X, x, z with*411have same : transporters(act, G, x, y) = transporters(act, G, x, z) bycc412obtain⟨yIn, g, gIn, yEq⟩:= orbit.membership.forward with hy413have carriesY : g ·ₐ x = y414 symm415exact yEq416have carries : g ∈ transporters(act, G, x, y) :=417 transporters.membership.backward with⟨gIn, carriesY⟩418rw same at carries419have parts := transporters.membership.forward with carries420rw← carriesY421exact parts.right422423theorem orbitCosetMap.surjective (x : Set)424requires hx : x ∈ X425shows SurjectiveBetween(orbitCosetMap(act, G, X, x), orbit(x),426 leftCosets(G, stabilizer(x)))427proof428have function := orbitCosetMap.function at act, G, X, x with*429constructor430 . exact function431 . intros C hC432obtain⟨bound, g, gIn, CEq⟩:= leftCosets.membership.forward with hC433have moved : g ·ₐ x ∈ orbit(x) := orbit.act_mem with*434have coset := transporters.eq_coset with action, hx, gIn435have value := orbitCosetMap.value at act, G, X, x, g ·ₐ x with*436have edge := FunctionBetween.relates_apply with function, moved437witness g ·ₐ x438constructor439 . exact moved440 . rw [value, coset, ← CEq] at edge441exact edge442443theorem orbitCosetMap.bijective (x : Set)444requires hx : x ∈ X445shows BijectiveBetween(orbitCosetMap(act, G, X, x), orbit(x),446 leftCosets(G, stabilizer(x)))447proof448constructor449 . exact orbitCosetMap.injective with*450 . exact orbitCosetMap.surjective with*451452theorem orbit.equipotent_cosets (x : Set)453requires hx : x ∈ X454shows orbit(x) ≃ leftCosets(G, stabilizer(x))455proof456witness orbitCosetMap(act, G, X, x)457exact orbitCosetMap.bijective with*458459theorem orbit.finite_of_group (x : Set)460requires hx : x ∈ X461requires finite : Finite(G)462shows Finite(orbit(x))463proof464have group := Action.group with action465have subgroup := stabilizer.subgroup with*466have finiteCosets := leftCosets.finite with*467have equipotent := orbit.equipotent_cosets with*468exact Finite.of_equipotent with469 finiteCosets, (Equipotent.symmetric with equipotent)470471theorem orbit.cardinality_eq_index (x : Set)472requires hx : x ∈ X473requires finite : Finite(G)474shows cardinality(orbit(x)) = index(G, stabilizer(x))475proof476have finiteOrbit := orbit.finite_of_group with*477have bijective := orbitCosetMap.bijective with*478rw index.value479exact cardinality.bijective with finiteOrbit, bijective480481-- The orbit–stabilizer theorem.482theorem orbit_stabilizer (x : Set)483requires hx : x ∈ X484requires finite : Finite(G)485shows cardinality(orbit(x)) * cardinality(stabilizer(x)) = order(G)486proof487have group := Action.group with action488have subgroup := stabilizer.subgroup with*489have count := lagrange with*490have same := orbit.cardinality_eq_index with*491rw [same, count]492rfl493494theorem orbit.cardinality_dvd (x : Set)495requires hx : x ∈ X496requires finite : Finite(G)497shows cardinality(orbit(x)) ∣ order(G)498proof499have group := Action.group with action500have subgroup := stabilizer.subgroup with*501have finiteStabilizer := Subgroup.finite with*502have stabilizerNat := cardinality.nat with finiteStabilizer503have orbitNat := cardinality.nat with (orbit.finite_of_group with*)504witness cardinality(stabilizer(x))505exact orbit_stabilizer with*506507end OrbitStabilizer508509section FixedPoints510variable (act G X : Set)511hypothesis action : act : G ↷ X512513-- A fixed point is a point whose orbit is itself alone.514theorem fixedPoints.fixes (g : G) (x : Set)515requires hx : x ∈ fixedPoints(act, G, X)516shows g ·ₐ x = x517proof518have parts := fixedPoints.membership.forward with hx519have gIn : g ∈ G byassumption520exact parts.right with g, gIn521522theorem fixedPoints.orbit (x : Set)523requires hx : x ∈ fixedPoints(act, G, X)524shows orbit(x) = {x}525proof526have xIn := fixedPoints.subset at act, G, X with x, hx527ext y528constructor529 . intro hy530obtain⟨yIn, g, gIn, yEq⟩:= orbit.membership.forward with hy531have fixed : g ·ₐ x = x := fixedPoints.fixes with*532rw [yEq, fixed]533exact singleton.self534 . intro hy535have equal := singleton.membership.forward with hy536rw equal537exact orbit.self with*538539theorem fixedPoints.of_orbit (x : Set)540requires hx : x ∈ X541requires single : orbit(x) = {x}542shows x ∈ fixedPoints(act, G, X)543proof544apply fixedPoints.membership.backward545refine⟨hx, ?_⟩546intros g gIn547have member : g ·ₐ x ∈ orbit(x) := orbit.act_mem with*548rw single at member549exact singleton.membership.forward with member550551theorem fixedPoints.iff_orbit (x : Set)552requires hx : x ∈ X553shows x ∈ fixedPoints(act, G, X) ↔ orbit(x) = {x}554proof555constructor556 . intro fixed557exact fixedPoints.orbit with*558 . intro single559exact fixedPoints.of_orbit with*560561theorem fixedPoints.finite562requires finite : Finite(X)563shows Finite(fixedPoints(act, G, X))564proof565exact Finite.subset with finite, (fixedPoints.subset at act, G, X)566567end FixedPoints568569-- The orbits not inside the fixed points.570def movedOrbits (act G X : Set) : Set:=571 { O ∈ orbits(act, G, X) |¬(O ⊆ fixedPoints(act, G, X)) }572573theorem movedOrbits.subset (act G X : Set)574shows movedOrbits(act, G, X) ⊆ orbits(act, G, X)575proof576intros O hO577have parts := movedOrbits.membership.forward with hO578exact parts.left579580-- A sum of multiples of d is a multiple of d.581theorem natSum.dvd_of_cardinality (n : Nat)582shows∀ V, ∀ w, ∀ d, Nat(d) → HasCardinality(V, n) → (∀ v ∈ V, w(v) ∈ ℕ) →583 (∀ v ∈ V, d ∣ w(v)) → d ∣ natSum(V, w)584proof585induction n586| zero =>587intros V w d dNat counted weights divisible588have empty := HasCardinality.empty_of_zero at V with counted589rw [empty, natSum.empty]590exact divides.zero at d591| k +1using ih =>592intros V w d dNat counted weights divisible593have hk : k +1= succ(k) := add.right_one with*594rw hk at counted595obtain⟨a, member⟩:= HasCardinality.exists_member with counted596have rest := HasCardinality.remove at V, a, k with counted, member597have fresh : ¬a ∈ V ∖ {a} bysimp [difference.membership, singleton.membership]598have restored := insert.restore with member599have restSubset := difference.subset_left at V, {a}600have restWeights : ∀ v ∈ V ∖ {a}, w(v) ∈ ℕ601intros v hv602exact weights with v, (restSubset with v, hv)603have restDivisible : ∀ v ∈ V ∖ {a}, d ∣ w(v)604intros v hv605exact divisible with v, (restSubset with v, hv)606have restSum := ih with V ∖ {a}, w, d, dNat, rest, restWeights, restDivisible607have restFinite := Finite.from_cardinality with rest608have weight := weights with a, member609have weightA := divisible with a, member610havesplit:= natSum.insert at V ∖ {a}, w, a with611 restFinite, restWeights, weight, fresh612rw restored atsplit613rwsplit614have weightNat := nat.omega.backward with weight615have sumNat := natSum.natural at V ∖ {a}, w with restFinite, restWeights616exact divides.add with restSum, weightA617618theorem natSum.dvd (V w : Set) (d : Nat)619requires finite : Finite(V)620requires weights : ∀ v ∈ V, w(v) ∈ ℕ621requires divisible : ∀ v ∈ V, d ∣ w(v)622shows d ∣ natSum(V, w)623proof624have counted := cardinality.correct with finite625have natV := cardinality.nat with finite626have all := natSum.dvd_of_cardinality at cardinality(V)627exact all with V, w, d, assumption, counted, weights, divisible628629-- A disjoint union of finite sets each of size divisible by d has size630-- divisible by d.631theorem cardinality.big_union_dvd (F : Set) (d : Nat)632requires finite : Finite(F)633requires members : ∀ S ∈ F, Finite(S)634requires disjoint : PairwiseDisjoint(F)635requires sizes : ∀ S ∈ F, d ∣ cardinality(S)636shows d ∣ cardinality(⋃F)637proof638have count := cardinality.big_union_disjoint with finite, members, disjoint639have weights : ∀ S ∈ F, sizeMap(F)(S) ∈ ℕ640intros S hS641have value := sizeMap.value at F, S with members, hS642rw value643exact nat.omega.forward with (cardinality.nat with (members with S, hS))644have divisible : ∀ S ∈ F, d ∣ sizeMap(F)(S)645intros S hS646have value := sizeMap.value at F, S with members, hS647rw value648exact sizes with S, hS649rw count650exact natSum.dvd with finite, weights, divisible651652section MovedPoints653variable (act G X : Set)654hypothesis action : act : G ↷ X655656-- The orbits not inside the fixed points cover exactly the points outside657-- the fixed points, and each is the orbit of such a point.658theorem movedOrbits.cover659shows⋃(movedOrbits(act, G, X)) = X ∖ fixedPoints(act, G, X)660proof661ext x662constructor663 . intro hx664obtain⟨O, hO, hxO⟩:= union.membership.forward with hx665obtain⟨orbitO, moved⟩:= movedOrbits.membership.forward with hO666obtain⟨bound, y, hy, OEq⟩:= orbits.membership.forward with orbitO667have xInOrbit : x ∈ orbit(y)668rw OEq at hxO669exact hxO670have xIn := orbit.subset at act, G, X, y with x, xInOrbit671apply difference.membership.backward672refine⟨xIn, ?_⟩673intro fixed674apply moved675have single : orbit(x) = {x} := fixedPoints.orbit with*676have same : orbit(x) = orbit(y) := orbit.of_member with action, hy, xInOrbit677rw [OEq, ← same, single]678intros z hz679have equal := singleton.membership.forward with hz680rw equal681exact fixed682 . intro hx683obtain⟨xIn, notFixed⟩:= difference.membership.forward with hx684haveself : x ∈ orbit(x) := orbit.self with*685have member := orbits.orbit_member at act, G, X, x with xIn686have moved : ¬(orbit(x) ⊆ fixedPoints(act, G, X))687intro included688exact notFixed with (included with x, self)689have inMoved := movedOrbits.membership.backward at act, G, X, orbit(x) with690⟨member, moved⟩691exact union.membership.backward with⟨orbit(x), inMoved, self⟩692693theorem movedOrbits.representative (O : Set)694requires hO : O ∈ movedOrbits(act, G, X)695shows∃ x ∈ X, ¬x ∈ fixedPoints(act, G, X) ∧ O = orbit(x)696proof697obtain⟨orbitO, moved⟩:= movedOrbits.membership.forward with hO698obtain⟨bound, y, hy, OEq⟩:= orbits.membership.forward with orbitO699witness y700refine⟨hy, ?_, OEq⟩701intro fixed702apply moved703have single : orbit(y) = {y} := fixedPoints.orbit with*704rw [OEq, single]705intros z hz706have equal := singleton.membership.forward with hz707rw equal708exact fixed709710-- If every orbit outside the fixed points has size divisible by d, so has711-- the set of points outside the fixed points.712theorem fixedPoints.difference_dvd (d : Nat)713requires finite : Finite(X)714requires orbitsDivisible : ∀ x ∈ X,715¬x ∈ fixedPoints(act, G, X) → d ∣ cardinality(orbit(x))716shows d ∣ cardinality(X ∖ fixedPoints(act, G, X))717proof718have movedSubset := movedOrbits.subset at act, G, X719have finiteMoved := Finite.subset with (orbits.finite with*), movedSubset720have members : ∀ O ∈ movedOrbits(act, G, X), Finite(O)721intros O hO722exact orbits.member_finite with action, (movedSubset with O, hO), finite723have disjoint := PairwiseDisjoint.subset with724 movedSubset, (orbits.pairwise_disjoint with action)725have sizes : ∀ O ∈ movedOrbits(act, G, X), d ∣ cardinality(O)726intros O hO727obtain⟨x, hx, notFixed, OEq⟩:= movedOrbits.representative with*728rw OEq729exact orbitsDivisible with x, hx, notFixed730have count := cardinality.big_union_dvd with finiteMoved, members, disjoint, sizes731 rwa movedOrbits.cover at count732733end MovedPoints734