Skip to content

Commit 64fb6ab

Browse files
RaggedRclaude
andcommitted
feat(Archive): Heawood and MK are Sabidussi coset graphs
Add heawoodSabidussiIso and mkSabidussiIso: both voltage graphs are proved to be coset graphs via the Sabidussi representation theorem. Generators defined by formulas (no lookup tables): - Heawood: Z₇ translation + fibre swap with negation (D₁₄ action) - MK: Z₈ translation + fibre swap with ×5 (D₁₆ action) Adjacency preservation by native_decide, transitivity by explicit witness elements (translation^k and translation^k * swap). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6b271eb commit 64fb6ab

1 file changed

Lines changed: 232 additions & 0 deletions

File tree

Archive/VoltageGraphs.lean

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Robin Langer
55
-/
66
import Mathlib.Combinatorics.SimpleGraph.QuotientGraph
7+
import Mathlib.Combinatorics.SimpleGraph.Action
8+
import Mathlib.Combinatorics.SimpleGraph.Representation
79
import Mathlib.Data.ZMod.Basic
810

911
/-!
@@ -123,3 +125,233 @@ theorem mobiusKantorVoltage_quotient_complete :
123125
(mobiusKantorVoltage.quotientGraph
124126
(Prod.fst : Fin 2 × ZMod 8 → Fin 2)).Adj i j := by
125127
native_decide
128+
129+
/-! ## Sabidussi coset graph representations
130+
131+
Every voltage graph on K₂ is vertex-transitive: the cyclic group acts by
132+
translation on the fibre coordinate, and a fibre-swapping automorphism
133+
makes the action transitive on all vertices. By the Sabidussi representation
134+
theorem, the graph is a coset graph. -/
135+
136+
section HeawoodSabidussi
137+
138+
/-- Z₇ translation: `(i, g) ↦ (i, g + 1)`. -/
139+
private def heawoodTranslation : Equiv.Perm (Fin 2 × ZMod 7) where
140+
toFun p := (p.1, p.2 + 1)
141+
invFun p := (p.1, p.2 - 1)
142+
left_inv := by intro ⟨i, g⟩; simp [add_sub_cancel_right]
143+
right_inv := by intro ⟨i, g⟩; simp [sub_add_cancel]
144+
145+
/-- Fibre swap with negation: `(i, g) ↦ (1 - i, -g)`.
146+
Preserves Heawood adjacency because `-v ∈ {0, 4, 6}` for `v ∈ {0, 4, 6}` in Z₇. -/
147+
private def heawoodSwap : Equiv.Perm (Fin 2 × ZMod 7) where
148+
toFun p := (⟨1 - p.1.val, by omega⟩, -p.2)
149+
invFun p := (⟨1 - p.1.val, by omega⟩, -p.2)
150+
left_inv := by native_decide
151+
right_inv := by native_decide
152+
153+
/-- Translation preserves Heawood adjacency. -/
154+
private theorem heawoodTranslation_adj : ∀ u v : Fin 2 × ZMod 7,
155+
heawoodVoltage.Adj u v → heawoodVoltage.Adj (heawoodTranslation u) (heawoodTranslation v) := by
156+
native_decide
157+
158+
/-- Swap preserves Heawood adjacency. -/
159+
private theorem heawoodSwap_adj : ∀ u v : Fin 2 × ZMod 7,
160+
heawoodVoltage.Adj u v → heawoodVoltage.Adj (heawoodSwap u) (heawoodSwap v) := by
161+
native_decide
162+
163+
/-- The group generated by translation and swap. -/
164+
private def heawoodG : Subgroup (Equiv.Perm (Fin 2 × ZMod 7)) :=
165+
Subgroup.closure ({heawoodTranslation, heawoodSwap} : Set _)
166+
167+
private noncomputable instance : MulAction heawoodG (Fin 2 × ZMod 7) :=
168+
MulAction.compHom _ heawoodG.subtype
169+
170+
private noncomputable instance : GraphAction heawoodG (Fin 2 × ZMod 7) heawoodVoltage where
171+
adj_smul := by
172+
intro ⟨σ, hσ⟩ u v hadj
173+
show heawoodVoltage.Adj (σ u) (σ v)
174+
revert u v; change ∀ u v, heawoodVoltage.Adj u v → heawoodVoltage.Adj (σ u) (σ v)
175+
refine Subgroup.closure_induction
176+
(p := fun σ _ => ∀ u v, heawoodVoltage.Adj u v → heawoodVoltage.Adj (σ u) (σ v))
177+
?_ ?_ ?_ ?_ hσ
178+
· intro x hx
179+
rcases hx with rfl | rfl
180+
· exact heawoodTranslation_adj
181+
· exact heawoodSwap_adj
182+
· intro u v h; simpa
183+
· intro x y _ _ hx hy u v hadj
184+
simp only [Equiv.Perm.mul_apply]; exact hx _ _ (hy u v hadj)
185+
· intro x _ hx u v hadj
186+
let f : { p : (Fin 2 × ZMod 7) × (Fin 2 × ZMod 7) // heawoodVoltage.Adj p.1 p.2 } →
187+
{ p : (Fin 2 × ZMod 7) × (Fin 2 × ZMod 7) // heawoodVoltage.Adj p.1 p.2 } :=
188+
fun ⟨⟨a, b⟩, hab⟩ => ⟨⟨x a, x b⟩, hx a b hab⟩
189+
have hf_surj : Function.Surjective f := Finite.surjective_of_injective (by
190+
intro ⟨⟨a₁, b₁⟩, _⟩ ⟨⟨a₂, b₂⟩, _⟩ h
191+
simp only [f, Subtype.mk.injEq, Prod.mk.injEq] at h
192+
exact Subtype.ext (Prod.ext (x.injective h.1) (x.injective h.2)))
193+
obtain ⟨⟨⟨a, b⟩, hab⟩, heq⟩ := hf_surj ⟨⟨u, v⟩, hadj⟩
194+
simp only [f, Subtype.mk.injEq, Prod.mk.injEq] at heq
195+
rw [show a = x⁻¹ u from by rw [← heq.1]; simp,
196+
show b = x⁻¹ v from by rw [← heq.2]; simp] at hab
197+
exact hab
198+
199+
private def heawoodT_mem : heawoodTranslation ∈ heawoodG :=
200+
Subgroup.subset_closure (Set.mem_insert _ _)
201+
202+
private def heawoodS_mem : heawoodSwap ∈ heawoodG :=
203+
Subgroup.subset_closure (Set.mem_insert_of_mem _ rfl)
204+
205+
/-- Witness element mapping (0,0) to v, as a product of generators. -/
206+
private def heawoodWitElem : Fin 2 × ZMod 7 → Equiv.Perm (Fin 2 × ZMod 7)
207+
| (⟨0, _⟩, g) => heawoodTranslation ^ g.val
208+
| (⟨1, _⟩, g) => heawoodTranslation ^ g.val * heawoodSwap
209+
210+
private theorem heawoodWitElem_correct :
211+
∀ v : Fin 2 × ZMod 7,
212+
heawoodWitElem v ((0 : Fin 2), (0 : ZMod 7)) = v := by native_decide
213+
214+
private theorem heawoodWitElem_mem (v : Fin 2 × ZMod 7) : heawoodWitElem v ∈ heawoodG := by
215+
rcases v with ⟨⟨i, hi⟩, g⟩
216+
interval_cases i
217+
· exact heawoodG.pow_mem heawoodT_mem _
218+
· exact heawoodG.mul_mem (heawoodG.pow_mem heawoodT_mem _) heawoodS_mem
219+
220+
private noncomputable instance : MulAction.IsPretransitive heawoodG (Fin 2 × ZMod 7) where
221+
exists_smul_eq := by
222+
intro x y
223+
have hmem : (heawoodWitElem x).symm.trans (heawoodWitElem y) ∈ heawoodG :=
224+
heawoodG.mul_mem (heawoodWitElem_mem y) (heawoodG.inv_mem (heawoodWitElem_mem x))
225+
exact ⟨⟨_, hmem⟩, by
226+
change ((heawoodWitElem x).symm.trans (heawoodWitElem y)) x = y
227+
simp only [Equiv.trans_apply]
228+
rw [show (heawoodWitElem x).symm x = ((0 : Fin 2), (0 : ZMod 7)) from by
229+
rw [Equiv.symm_apply_eq]; exact (heawoodWitElem_correct x).symm]
230+
exact heawoodWitElem_correct y⟩
231+
232+
/-- **The Heawood graph is a Sabidussi coset graph.**
233+
234+
The dihedral group D₁₄ = ⟨translation, swap⟩ acts vertex-transitively, giving:
235+
`heawoodVoltage ≃g Sab(D₁₄, {1}, D)` (a Cayley graph). -/
236+
noncomputable def heawoodSabidussiIso :
237+
heawoodVoltage ≃g SimpleGraph.cosetGraph
238+
(MulAction.stabilizer heawoodG ((0 : Fin 2), (0 : ZMod 7)))
239+
(connectionSet heawoodG heawoodVoltage ((0 : Fin 2), (0 : ZMod 7)))
240+
(connectionSet.isConnectionSet _) :=
241+
sabidussiIso _
242+
243+
end HeawoodSabidussi
244+
245+
section MKSabidussi
246+
247+
/-- Z₈ translation: `(i, g) ↦ (i, g + 1)`. -/
248+
private def mkTranslation : Equiv.Perm (Fin 2 × ZMod 8) where
249+
toFun p := (p.1, p.2 + 1)
250+
invFun p := (p.1, p.2 - 1)
251+
left_inv := by intro ⟨i, g⟩; simp [add_sub_cancel_right]
252+
right_inv := by intro ⟨i, g⟩; simp [sub_add_cancel]
253+
254+
/-- Fibre swap with multiplication by 5: `(i, g) ↦ (1 - i, 5g)`.
255+
Preserves MK adjacency because `5 · {0, 1, 3} = {0, 5, 15} = {0, 5, 7}` and
256+
the adjacency condition uses `-5v`: `-5 · {0, 1, 3} = {0, 3, 1} = {0, 1, 3}`. -/
257+
private def mkSwap : Equiv.Perm (Fin 2 × ZMod 8) where
258+
toFun p := (⟨1 - p.1.val, by omega⟩, 5 * p.2)
259+
invFun p := (⟨1 - p.1.val, by omega⟩, 5 * p.2) -- 5² = 25 = 1 mod 8
260+
left_inv := by native_decide
261+
right_inv := by native_decide
262+
263+
/-- Translation preserves MK adjacency. -/
264+
private theorem mkTranslation_adj : ∀ u v : Fin 2 × ZMod 8,
265+
mobiusKantorVoltage.Adj u v →
266+
mobiusKantorVoltage.Adj (mkTranslation u) (mkTranslation v) := by
267+
native_decide
268+
269+
/-- Swap preserves MK adjacency. -/
270+
private theorem mkSwap_adj : ∀ u v : Fin 2 × ZMod 8,
271+
mobiusKantorVoltage.Adj u v →
272+
mobiusKantorVoltage.Adj (mkSwap u) (mkSwap v) := by
273+
native_decide
274+
275+
private def mkG : Subgroup (Equiv.Perm (Fin 2 × ZMod 8)) :=
276+
Subgroup.closure ({mkTranslation, mkSwap} : Set _)
277+
278+
private noncomputable instance : MulAction mkG (Fin 2 × ZMod 8) :=
279+
MulAction.compHom _ mkG.subtype
280+
281+
private noncomputable instance : GraphAction mkG (Fin 2 × ZMod 8) mobiusKantorVoltage where
282+
adj_smul := by
283+
intro ⟨σ, hσ⟩ u v hadj
284+
show mobiusKantorVoltage.Adj (σ u) (σ v)
285+
revert u v
286+
change ∀ u v, mobiusKantorVoltage.Adj u v → mobiusKantorVoltage.Adj (σ u) (σ v)
287+
refine Subgroup.closure_induction
288+
(p := fun σ _ => ∀ u v, mobiusKantorVoltage.Adj u v →
289+
mobiusKantorVoltage.Adj (σ u) (σ v))
290+
?_ ?_ ?_ ?_ hσ
291+
· intro x hx
292+
rcases hx with rfl | rfl
293+
· exact mkTranslation_adj
294+
· exact mkSwap_adj
295+
· intro u v h; simpa
296+
· intro x y _ _ hx hy u v hadj
297+
simp only [Equiv.Perm.mul_apply]; exact hx _ _ (hy u v hadj)
298+
· intro x _ hx u v hadj
299+
let f : { p : (Fin 2 × ZMod 8) × (Fin 2 × ZMod 8) //
300+
mobiusKantorVoltage.Adj p.1 p.2 } →
301+
{ p : (Fin 2 × ZMod 8) × (Fin 2 × ZMod 8) //
302+
mobiusKantorVoltage.Adj p.1 p.2 } :=
303+
fun ⟨⟨a, b⟩, hab⟩ => ⟨⟨x a, x b⟩, hx a b hab⟩
304+
have hf_surj : Function.Surjective f := Finite.surjective_of_injective (by
305+
intro ⟨⟨a₁, b₁⟩, _⟩ ⟨⟨a₂, b₂⟩, _⟩ h
306+
simp only [f, Subtype.mk.injEq, Prod.mk.injEq] at h
307+
exact Subtype.ext (Prod.ext (x.injective h.1) (x.injective h.2)))
308+
obtain ⟨⟨⟨a, b⟩, hab⟩, heq⟩ := hf_surj ⟨⟨u, v⟩, hadj⟩
309+
simp only [f, Subtype.mk.injEq, Prod.mk.injEq] at heq
310+
rw [show a = x⁻¹ u from by rw [← heq.1]; simp,
311+
show b = x⁻¹ v from by rw [← heq.2]; simp] at hab
312+
exact hab
313+
314+
private def mkT_mem : mkTranslation ∈ mkG :=
315+
Subgroup.subset_closure (Set.mem_insert _ _)
316+
317+
private def mkS_mem : mkSwap ∈ mkG :=
318+
Subgroup.subset_closure (Set.mem_insert_of_mem _ rfl)
319+
320+
private def mkWitElem : Fin 2 × ZMod 8 → Equiv.Perm (Fin 2 × ZMod 8)
321+
| (⟨0, _⟩, g) => mkTranslation ^ g.val
322+
| (⟨1, _⟩, g) => mkTranslation ^ g.val * mkSwap
323+
324+
private theorem mkWitElem_correct :
325+
∀ v : Fin 2 × ZMod 8,
326+
mkWitElem v ((0 : Fin 2), (0 : ZMod 8)) = v := by native_decide
327+
328+
private theorem mkWitElem_mem (v : Fin 2 × ZMod 8) : mkWitElem v ∈ mkG := by
329+
rcases v with ⟨⟨i, hi⟩, g⟩
330+
interval_cases i
331+
· exact mkG.pow_mem mkT_mem _
332+
· exact mkG.mul_mem (mkG.pow_mem mkT_mem _) mkS_mem
333+
334+
private noncomputable instance : MulAction.IsPretransitive mkG (Fin 2 × ZMod 8) where
335+
exists_smul_eq := by
336+
intro x y
337+
have hmem : (mkWitElem x).symm.trans (mkWitElem y) ∈ mkG :=
338+
mkG.mul_mem (mkWitElem_mem y) (mkG.inv_mem (mkWitElem_mem x))
339+
exact ⟨⟨_, hmem⟩, by
340+
change ((mkWitElem x).symm.trans (mkWitElem y)) x = y
341+
simp only [Equiv.trans_apply]
342+
rw [show (mkWitElem x).symm x = ((0 : Fin 2), (0 : ZMod 8)) from by
343+
rw [Equiv.symm_apply_eq]; exact (mkWitElem_correct x).symm]
344+
exact mkWitElem_correct y⟩
345+
346+
/-- **The Möbius-Kantor graph is a Sabidussi coset graph.**
347+
348+
The dihedral group D₁₆ = ⟨translation, swap⟩ acts vertex-transitively, giving:
349+
`mobiusKantorVoltage ≃g Sab(D₁₆, {1}, D)` (a Cayley graph). -/
350+
noncomputable def mkSabidussiIso :
351+
mobiusKantorVoltage ≃g SimpleGraph.cosetGraph
352+
(MulAction.stabilizer mkG ((0 : Fin 2), (0 : ZMod 8)))
353+
(connectionSet mkG mobiusKantorVoltage ((0 : Fin 2), (0 : ZMod 8)))
354+
(connectionSet.isConnectionSet _) :=
355+
sabidussiIso _
356+
357+
end MKSabidussi

0 commit comments

Comments
 (0)