Skip to content

Commit de91281

Browse files
committed
Implementation of the general Burau representation for Artin groups.
1 parent dc99dc8 commit de91281

File tree

3 files changed

+329
-8
lines changed

3 files changed

+329
-8
lines changed

src/doc/en/reference/references/index.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,10 @@ REFERENCES:
568568
Springer Verlag 2006; pre-print available at
569569
http://eprint.iacr.org/2005/200
570570
571+
.. [BQ2024] Asilata Bapat and Hoel Queffelec.
572+
*Some remarks about the faithfulness of the Burau representation
573+
of Artin-Tits groups*. Preprint, 2024. :arxiv:`2409.00144`.
574+
571575
.. [BBS1982] \L. Blum, M. Blum, and M. Shub. Comparison of Two
572576
Pseudo-Random Number Generators. *Advances in Cryptology:
573577
Proceedings of Crypto '82*, pp.61--78, 1982.

src/sage/groups/artin.py

Lines changed: 290 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,17 @@
99
AUTHORS:
1010
1111
- Travis Scrimshaw (2018-02-05): Initial version
12+
- Travis Scrimshaw (2025-01-30): Allowed general construction; implemented
13+
general Burau representation
14+
15+
.. TODO::
16+
17+
Implement affine type Artin groups with their well-known embeddings into
18+
the classical braid group.
1219
"""
1320

1421
# ****************************************************************************
15-
# Copyright (C) 2018 Travis Scrimshaw <tcscrims at gmail.com>
22+
# Copyright (C) 2018-2025 Travis Scrimshaw <tcscrims at gmail.com>
1623
#
1724
# This program is free software: you can redistribute it and/or modify
1825
# it under the terms of the GNU General Public License as published by
@@ -26,6 +33,7 @@
2633
from sage.groups.free_group import FreeGroup
2734
from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement
2835
from sage.misc.cachefunc import cached_method
36+
from sage.misc.lazy_attribute import lazy_attribute
2937
from sage.rings.infinity import Infinity
3038
from sage.structure.richcmp import richcmp, rich_to_bool
3139
from sage.structure.unique_representation import UniqueRepresentation
@@ -156,6 +164,132 @@ def coxeter_group_element(self, W=None):
156164
In = W.index_set()
157165
return W.prod(s[In[abs(i)-1]] for i in self.Tietze())
158166

167+
def burau_matrix(self, var='t', reduced=False):
168+
r"""
169+
Return the Burau matrix of the Artin group element.
170+
171+
Following [BQ2024]_, the (generalized) Burau representation of an
172+
Artin group is defined by deforming the reflection representation
173+
of the corresponding Coxeter group. However, we substitute
174+
`q \mapsto -t` from [BQ2024]_ to match the unitary
175+
176+
INPUT:
177+
178+
- ``var`` -- string (default: ``'t'``); the name of the
179+
variable in the entries of the matrix
180+
181+
OUTPUT:
182+
183+
The Burau matrix of the Artin group element over the Laurent
184+
polynomial ring in the variable ``var``.
185+
186+
EXAMPLES::
187+
188+
sage: A.<s1,s2,s3> = ArtinGroup(['B',3])
189+
sage: B1 = s1.burau_matrix()
190+
sage: B2 = s2.burau_matrix()
191+
sage: B3 = s3.burau_matrix()
192+
sage: [B1, B2, B3]
193+
[
194+
[-t^2 t 0] [ 1 0 0] [ 1 0 0]
195+
[ 0 1 0] [ t -t^2 a*t] [ 0 1 0]
196+
[ 0 0 1], [ 0 0 1], [ 0 a*t -t^2]
197+
]
198+
sage: B1 * B2 * B1 == B2 * B1 * B2
199+
True
200+
sage: B2 * B3 * B2 * B3 == B3 * B2 * B3 * B2
201+
True
202+
sage: B1 * B3 == B3 * B1
203+
True
204+
sage: (~s1).burau_matrix() * B1 == 1
205+
True
206+
207+
We verify the example in Theorem 4.1 of [BQ2024]_::
208+
209+
sage: A.<s1,s2,s3,s4> = ArtinGroup(['A', 3, 1])
210+
sage: [g.burau_matrix() for g in A.gens()]
211+
[
212+
[-t^2 t 0 t] [ 1 0 0 0] [ 1 0 0 0]
213+
[ 0 1 0 0] [ t -t^2 t 0] [ 0 1 0 0]
214+
[ 0 0 1 0] [ 0 0 1 0] [ 0 t -t^2 t]
215+
[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1],
216+
<BLANKLINE>
217+
[ 1 0 0 0]
218+
[ 0 1 0 0]
219+
[ 0 0 1 0]
220+
[ t 0 t -t^2]
221+
]
222+
sage: a = s3^2 * s4 * s3 * s2 *s1 * ~s3 * s4 * s3 * s2 * s1^-2 * s4
223+
sage: b = s1^2 * ~s2 * s4 * s1 * ~s3 * s2 * ~s4 * s3 * s1 * s4 * s1 * ~s2 * s4^-2 * s3
224+
sage: alpha = a * s3 * ~a
225+
sage: beta = b * s2 * ~b
226+
sage: elm = alpha * beta * ~alpha * ~beta
227+
sage: print(elm.Tietze())
228+
(3, 3, 4, 3, 2, 1, -3, 4, 3, 2, -1, -1, 4, 3, -4, 1, 1, -2, -3,
229+
-4, 3, -1, -2, -3, -4, -3, -3, 1, 1, -2, 4, 1, -3, 2, -4, 3, 1,
230+
4, 1, -2, -4, -4, 3, 2, -3, 4, 4, 2, -1, -4, -1, -3, 4, -2, 3,
231+
-1, -4, 2, -1, -1, 3, 3, 4, 3, 2, 1, -3, 4, 3, 2, -1, -1, 4,
232+
-3, -4, 1, 1, -2, -3, -4, 3, -1, -2, -3, -4, -3, -3, 1, 1, -2,
233+
4, 1, -3, 2, -4, 3, 1, 4, 1, -2, -4, -4, 3, -2, -3, 4, 4, 2,
234+
-1, -4, -1, -3, 4, -2, 3, -1, -4, 2, -1, -1)
235+
sage: elm.burau_matrix()
236+
[1 0 0 0]
237+
[0 1 0 0]
238+
[0 0 1 0]
239+
[0 0 0 1]
240+
241+
Next, we show ``elm`` is not the identity by using the embedding of
242+
the affine braid group `\widetilde{B}_n \to B_{n+1}`::
243+
244+
sage: B.<t1,t2,t3,t4> = BraidGroup(5)
245+
sage: D = t1 * t2 * t3 * t4^2
246+
sage: t0 = D * t3 * ~D
247+
sage: t0*t1*t0 == t1*t0*t1
248+
True
249+
sage: t0*t2 == t2*t0
250+
True
251+
sage: t0*t3*t0 == t3*t0*t3
252+
True
253+
sage: T = [t0, t1, t2, t3]
254+
sage: emb = B.prod(T[i-1] if i > 0 else ~T[-i-1] for i in elm.Tietze())
255+
sage: emb.is_one()
256+
False
257+
258+
Since the Burau representation does not respect the group embedding,
259+
the corresponding `B_5` element's Burau matrix is not the identity
260+
(Bigelow gave an example of the representation not being faithful for
261+
`B_5`, but it is still open for `B_4`)::
262+
263+
sage: emb.burau_matrix() != 1
264+
True
265+
266+
We also verify the result using the elements in [BQ2024]_ Remark 4.2::
267+
268+
sage: ap = s3 * s1 * s2 * s1 * ~s3 * s4 * s2 * s3 * s2 * ~s3 * s1^-2 * s4
269+
sage: bp = s1 * ~s4 * s1^2 * s3^-2 * ~s2 * s4 * s1 * ~s3 * s2 * ~s4 * s3 * s1 * s4 * s1 * ~s2 * s4^-2 * s3
270+
sage: alpha = ap * s3 * ~ap
271+
sage: beta = bp * s2 * ~bp
272+
sage: elm = alpha * beta * ~alpha * ~beta
273+
sage: elm.burau_matrix()
274+
[1 0 0 0]
275+
[0 1 0 0]
276+
[0 0 1 0]
277+
[0 0 0 1]
278+
279+
REFERENCES:
280+
281+
- [BQ2024]_
282+
"""
283+
gens, invs = self.parent()._burau_generators
284+
MS = gens[0].parent()
285+
ret = MS.prod(gens[i-1] if i > 0 else invs[-i-1] for i in self.Tietze())
286+
287+
if var == 't':
288+
return ret
289+
from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing
290+
poly_ring = LaurentPolynomialRing(ret.base_ring().base_ring(), var)
291+
return ret.change_ring(poly_ring)
292+
159293

160294
class FiniteTypeArtinGroupElement(ArtinGroupElement):
161295
"""
@@ -453,7 +587,7 @@ def __classcall_private__(cls, coxeter_data, names=None):
453587
from sage.groups.raag import RightAngledArtinGroup
454588
return RightAngledArtinGroup(coxeter_data.coxeter_graph(), names)
455589
if not coxeter_data.is_finite():
456-
raise NotImplementedError
590+
return super().__classcall__(cls, coxeter_data, names)
457591
if coxeter_data.coxeter_type().cartan_type().type() == 'A':
458592
from sage.groups.braid import BraidGroup
459593
return BraidGroup(coxeter_data.rank()+1, names)
@@ -476,15 +610,17 @@ def __init__(self, coxeter_matrix, names):
476610
rels = []
477611
# Generate the relations based on the Coxeter graph
478612
I = coxeter_matrix.index_set()
613+
gens = free_group.gens()
479614
for ii, i in enumerate(I):
480-
for j in I[ii + 1:]:
615+
for jj, j in enumerate(I[ii + 1:], start=ii+1):
481616
m = coxeter_matrix[i, j]
482617
if m == Infinity: # no relation
483618
continue
484-
elt = [i, j] * m
485-
for ind in range(m, 2*m):
486-
elt[ind] = -elt[ind]
487-
rels.append(free_group(elt))
619+
elt = (gens[ii] * gens[jj]) ** (m // 2)
620+
if m % 2 == 1:
621+
elt = elt * gens[ii] * ~gens[jj]
622+
elt = elt * (~gens[ii] * ~gens[jj]) ** (m // 2)
623+
rels.append(elt)
488624
FinitelyPresentedGroup.__init__(self, free_group, tuple(rels))
489625

490626
def _repr_(self):
@@ -688,6 +824,153 @@ def _standard_lift(self, w):
688824
"""
689825
return self(self._standard_lift_Tietze(w))
690826

827+
@lazy_attribute
828+
def _burau_generators(self):
829+
"""
830+
The Burau matrices for the generators of ``self`` and their inverses.
831+
832+
EXAMPLES::
833+
834+
sage: A = ArtinGroup(['G',2])
835+
sage: A._burau_generators
836+
[[
837+
[-t^2 a*t] [ 1 0]
838+
[ 0 1], [ a*t -t^2]
839+
],
840+
[
841+
[ -t^-2 a*t^-1] [ 1 0]
842+
[ 0 1], [a*t^-1 -t^-2]
843+
]]
844+
845+
sage: A = ArtinGroup(['H',3])
846+
sage: A._burau_generators
847+
[[
848+
[-t^2 t 0] [ 1 0 0]
849+
[ 0 1 0] [ t -t^2 (1/2*a + 1/2)*t]
850+
[ 0 0 1], [ 0 0 1],
851+
<BLANKLINE>
852+
[ 1 0 0]
853+
[ 0 1 0]
854+
[ 0 (1/2*a + 1/2)*t -t^2]
855+
],
856+
[
857+
[-t^-2 t^-1 0]
858+
[ 0 1 0]
859+
[ 0 0 1],
860+
<BLANKLINE>
861+
[ 1 0 0]
862+
[ t^-1 -t^-2 (1/2*a + 1/2)*t^-1]
863+
[ 0 0 1],
864+
<BLANKLINE>
865+
[ 1 0 0]
866+
[ 0 1 0]
867+
[ 0 (1/2*a + 1/2)*t^-1 -t^-2]
868+
]]
869+
870+
sage: CM = matrix([[1,4,7], [4,1,10], [7,10,1]])
871+
sage: A = ArtinGroup(CM)
872+
sage: gens = A._burau_generators[0]; gens
873+
[
874+
[ -t^2 (E(8) - E(8)^3)*t (-E(7)^3 - E(7)^4)*t]
875+
[ 0 1 0]
876+
[ 0 0 1],
877+
<BLANKLINE>
878+
[ 1 0 0]
879+
[ (E(8) - E(8)^3)*t -t^2 (E(20) - E(20)^9)*t]
880+
[ 0 0 1],
881+
<BLANKLINE>
882+
[ 1 0 0]
883+
[ 0 1 0]
884+
[(-E(7)^3 - E(7)^4)*t (E(20) - E(20)^9)*t -t^2]
885+
]
886+
sage: all(gens[i] * A._burau_generators[1][i] == 1 for i in range(3))
887+
True
888+
sage: B1, B2, B3 = gens
889+
sage: (B1 * B2)^2 == (B2 * B1)^2
890+
True
891+
sage: (B2 * B3)^5 == (B3 * B2)^5
892+
True
893+
sage: B1 * B3 * B1 * B3 * B1 * B3 * B1 == B3 * B1 * B3 * B1 * B3 * B1 * B3
894+
True
895+
"""
896+
data = self.coxeter_type()
897+
coxeter_matrix = self.coxeter_matrix()
898+
n = coxeter_matrix.rank()
899+
900+
# Determine the base field
901+
if data.is_simply_laced():
902+
from sage.rings.integer_ring import ZZ
903+
base_ring = ZZ
904+
elif data.is_finite():
905+
from sage.rings.number_field.number_field import QuadraticField
906+
letter = data.cartan_type().type()
907+
if letter in ['B', 'C', 'F']:
908+
base_ring = QuadraticField(2)
909+
elif letter == 'G':
910+
base_ring = QuadraticField(3)
911+
elif letter == 'H':
912+
base_ring = QuadraticField(5)
913+
else:
914+
from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField
915+
base_ring = UniversalCyclotomicField()
916+
else:
917+
from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField
918+
base_ring = UniversalCyclotomicField()
919+
920+
# Construct the matrices
921+
from sage.matrix.args import SparseEntry
922+
from sage.matrix.matrix_space import MatrixSpace
923+
from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing
924+
import sage.rings.abc
925+
poly_ring = LaurentPolynomialRing(base_ring, 't')
926+
q = -poly_ring.gen()
927+
MS = MatrixSpace(poly_ring, n, sparse=True)
928+
one = MS.one()
929+
# FIXME: Hack because there is no ZZ \cup \{ \infty \}: -1 represents \infty
930+
if isinstance(base_ring, sage.rings.abc.UniversalCyclotomicField):
931+
E = base_ring.gen
932+
933+
def val(x):
934+
if x == -1:
935+
return 2 * q
936+
elif x == 1:
937+
return 1 + q**2
938+
else:
939+
return q * (E(2*x) + ~E(2*x))
940+
elif isinstance(base_ring, sage.rings.abc.NumberField_quadratic):
941+
from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField
942+
E = UniversalCyclotomicField().gen
943+
944+
def val(x):
945+
if x == -1:
946+
return 2 * q
947+
elif x == 1:
948+
return 1 + q**2
949+
else:
950+
return q * base_ring((E(2 * x) + ~E(2 * x)).to_cyclotomic_field())
951+
else:
952+
def val(x):
953+
if x == -1:
954+
return 2 * q
955+
elif x == 1:
956+
return 1 + q**2
957+
elif x == 2:
958+
return 0
959+
elif x == 3:
960+
return q
961+
else:
962+
from sage.functions.trig import cos
963+
from sage.symbolic.constants import pi
964+
return q * base_ring(2 * cos(pi / x))
965+
index_set = data.index_set()
966+
gens = [one - MS([SparseEntry(i, j, val(coxeter_matrix[index_set[i], index_set[j]]))
967+
for j in range(n)])
968+
for i in range(n)]
969+
invs = [one - q**-2 * MS([SparseEntry(i, j, val(coxeter_matrix[index_set[i], index_set[j]]))
970+
for j in range(n)])
971+
for i in range(n)]
972+
return [gens, invs]
973+
691974
Element = ArtinGroupElement
692975

693976

0 commit comments

Comments
 (0)