1-- The absorption tool on the sphere: for a countable D ⊆ S² off the2-- z-axis some turn(t) carries every positive power of D off D, so that D3-- is absorbed into S² by the rotation group4-- 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.Geometry.Absorption.Sphere10import Separation11import Absorb1213-- Powers of turn(t) in the group SO3 are its matrix powers.14theorem turn.groupPow (t : Real) (n : Nat)15shows groupPow(SO3, turn(t), n) = matrixPow3(turn(t), n)16proof17induction n18| zero =>19have group := SO3.group20have rotation := turn.so3 at t21have unit : groupPow(SO3, turn(t), 0) = Group.one(SO3) := pow_zero with group, rotation22rw [unit, SO3.oneOf, matrixPow3.zero]23rfl24| succ(k) using ih =>25have group := SO3.group26have rotation := turn.so3 at t27have rotationIn : turn(t) ∈ so3Matrices := turn.rotation at t28have step := pow_succ_left at SO3, turn(t), k with group29have succForm : k +1= succ(k) := add.right_one at k30rw succForm at step31have powerIn : groupPow(SO3, turn(t), k) ∈ Group.carrier(SO3) :=32 Group.pow_mem with*33rw SO3.carrierOf at powerIn34havering:= matrixRing.real_ring35have magma := IsSemigroup.magma with36 (IsMonoid.semigroup with (IsRing.multiplicative with (Ring.parts withring)))37have carrierSubset : so3Matrices ⊆ Ring.carrier(matrixRing(realRing, 3))38intros M hM39obtain⟨inRing, orthogonal, unit⟩:= so3Matrices.membership.forward with hM40exact inRing41have closedMul : ClosedBinary(so3Matrices, Ring.mul(matrixRing(realRing, 3)))42intros M hM N hN43have matrixM := so3Matrices.matrix with hM44have matrixN := so3Matrices.matrix with hN45exact so3Matrices.mul_mem with*46have operation := restrictBinary.value at Ring.carrier(matrixRing(realRing, 3)),47 so3Matrices, Ring.mul(matrixRing(realRing, 3)), turn(t), groupPow(SO3, turn(t), k)48with magma, carrierSubset, closedMul, rotationIn, powerIn49have matrixStep := matrixPow3.succ at turn(t), k50rw succForm at matrixStep51rw [step, SO3.mulOf, operation, ih, matrixStep, matrixMul3.graph]52rfl5354-- The separation theorem for the z-axis: for a countable D ⊆ S² off the55-- axis, some turn(t) carries every positive power of D off D.56theorem turn.separates (D : Set)57requires countable : Countable(D)58requires subset : D ⊆ S²59requires offAxis : ∀ d ∈ D, vectorPoint(d) ≠ complexZero60shows∃ t ∈ ℝ, ∀ n ∈ ℕ,61 Disjoint(actImage(sphereAction, groupPow(SO3, turn(t), n +1), D), D)62proof63obtain⟨t, real, outside⟩:= turnBadSet.exists_outside with countable, subset, offAxis64have typed : Real(t) bytypecheck65refine⟨t, real, ?_⟩66intros n hn67have natural := omega.natural with hn68have group := SO3.group69have rotation := turn.so3 at t70apply Disjoint.iff.backward71intros y hy inD72obtain⟨d, hd, moved⟩:= actImage.membership.forward with hy73have powerIn : groupPow(SO3, turn(t), n +1) ∈ Group.carrier(SO3) :=74 Group.pow_mem with*75rw SO3.carrierOf at powerIn76have dIn := subset with d, hd77have applied := sphereAction.apply with powerIn, dIn78have bridge := turn.groupPow at t, n +179rw [applied, bridge] at moved80have bad : t ∈ turnBad(n +1, d, y)81apply turnBad.membership.backward82exact⟨real, moved⟩83have inBadSet := turnBadSet.contains with hd, inD, bad84exact outside with inBadSet85