@@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
44Authors: Robin Langer
55-/
66import Mathlib.Combinatorics.SimpleGraph.QuotientGraph
7+ import Mathlib.Combinatorics.SimpleGraph.Action
8+ import Mathlib.Combinatorics.SimpleGraph.Representation
79import 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