99AUTHORS:
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
2633from sage .groups .free_group import FreeGroup
2734from sage .groups .finitely_presented import FinitelyPresentedGroup , FinitelyPresentedGroupElement
2835from sage .misc .cachefunc import cached_method
36+ from sage .misc .lazy_attribute import lazy_attribute
2937from sage .rings .infinity import Infinity
3038from sage .structure .richcmp import richcmp , rich_to_bool
3139from sage .structure .unique_representation import UniqueRepresentation
@@ -156,6 +164,155 @@ 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' ):
168+ r"""
169+ Return the Burau matrix of the Artin group element.
170+
171+ Following [BQ2024]_, the (generalized) Burau representation
172+ of an Artin group is defined by deforming the reflection
173+ representation of the corresponding Coxeter group. However,
174+ we substitute `q \mapsto -t` from [BQ2024]_ to match one of
175+ the unitary (reduced) Burau representations of the braid group
176+ (see :meth:`sage.groups.braid.Braid.burau_matrix()` for details.)
177+
178+ More precisely, let `(m_{ij})_{i,j \in I}` be the
179+ :meth:`Coxeter matrix<coxeter_matrix>`. Then the action is
180+ given on the basis `(\alpha_1, \ldots \alpha_n)` (corresponding
181+ to the reflection representation of the corresponding
182+ :meth:`Coxeter group<coxeter_group>`) by
183+
184+ .. MATH::
185+
186+ \sigma_i(\alpha_j) = \alpha_j
187+ - \langle \alpha_i, \alpha_j \rangle_q \alpha_i,
188+ \qquad \text{ where }
189+ \langle \alpha_i, \alpha_j \rangle_q := \begin{cases}
190+ 1 + t^2 & \text{if } i = j, \\
191+ -2 t \cos(\pi/m_{ij}) & \text{if } i \neq j.
192+ \end{cases}.
193+
194+ By convention `\cos(\pi/\infty) = 1`. Note that the inverse of the
195+ generators act by `\sigma_i^{-1}(\alpha_j) = \alpha_j - q^{-2}
196+ \langle \alpha_j, \alpha_i \rangle_q \alpha_i`.
197+
198+ INPUT:
199+
200+ - ``var`` -- string (default: ``'t'``); the name of the
201+ variable in the entries of the matrix
202+
203+ OUTPUT:
204+
205+ The Burau matrix of the Artin group element over the Laurent
206+ polynomial ring in the variable ``var``.
207+
208+ EXAMPLES::
209+
210+ sage: A.<s1,s2,s3> = ArtinGroup(['B',3])
211+ sage: B1 = s1.burau_matrix()
212+ sage: B2 = s2.burau_matrix()
213+ sage: B3 = s3.burau_matrix()
214+ sage: [B1, B2, B3]
215+ [
216+ [-t^2 t 0] [ 1 0 0] [ 1 0 0]
217+ [ 0 1 0] [ t -t^2 a*t] [ 0 1 0]
218+ [ 0 0 1], [ 0 0 1], [ 0 a*t -t^2]
219+ ]
220+ sage: B1 * B2 * B1 == B2 * B1 * B2
221+ True
222+ sage: B2 * B3 * B2 * B3 == B3 * B2 * B3 * B2
223+ True
224+ sage: B1 * B3 == B3 * B1
225+ True
226+ sage: (~s1).burau_matrix() * B1 == 1
227+ True
228+
229+ We verify the example in Theorem 4.1 of [BQ2024]_::
230+
231+ sage: A.<s1,s2,s3,s4> = ArtinGroup(['A', 3, 1])
232+ sage: [g.burau_matrix() for g in A.gens()]
233+ [
234+ [-t^2 t 0 t] [ 1 0 0 0] [ 1 0 0 0]
235+ [ 0 1 0 0] [ t -t^2 t 0] [ 0 1 0 0]
236+ [ 0 0 1 0] [ 0 0 1 0] [ 0 t -t^2 t]
237+ [ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1],
238+ <BLANKLINE>
239+ [ 1 0 0 0]
240+ [ 0 1 0 0]
241+ [ 0 0 1 0]
242+ [ t 0 t -t^2]
243+ ]
244+ sage: a = s3^2 * s4 * s3 * s2 *s1 * ~s3 * s4 * s3 * s2 * s1^-2 * s4
245+ sage: b = s1^2 * ~s2 * s4 * s1 * ~s3 * s2 * ~s4 * s3 * s1 * s4 * s1 * ~s2 * s4^-2 * s3
246+ sage: alpha = a * s3 * ~a
247+ sage: beta = b * s2 * ~b
248+ sage: elm = alpha * beta * ~alpha * ~beta
249+ sage: print(elm.Tietze())
250+ (3, 3, 4, 3, 2, 1, -3, 4, 3, 2, -1, -1, 4, 3, -4, 1, 1, -2, -3,
251+ -4, 3, -1, -2, -3, -4, -3, -3, 1, 1, -2, 4, 1, -3, 2, -4, 3, 1,
252+ 4, 1, -2, -4, -4, 3, 2, -3, 4, 4, 2, -1, -4, -1, -3, 4, -2, 3,
253+ -1, -4, 2, -1, -1, 3, 3, 4, 3, 2, 1, -3, 4, 3, 2, -1, -1, 4,
254+ -3, -4, 1, 1, -2, -3, -4, 3, -1, -2, -3, -4, -3, -3, 1, 1, -2,
255+ 4, 1, -3, 2, -4, 3, 1, 4, 1, -2, -4, -4, 3, -2, -3, 4, 4, 2,
256+ -1, -4, -1, -3, 4, -2, 3, -1, -4, 2, -1, -1)
257+ sage: elm.burau_matrix()
258+ [1 0 0 0]
259+ [0 1 0 0]
260+ [0 0 1 0]
261+ [0 0 0 1]
262+
263+ Next, we show ``elm`` is not the identity by using the embedding of
264+ the affine braid group `\widetilde{B}_n \to B_{n+1}`::
265+
266+ sage: B.<t1,t2,t3,t4> = BraidGroup(5)
267+ sage: D = t1 * t2 * t3 * t4^2
268+ sage: t0 = D * t3 * ~D
269+ sage: t0*t1*t0 == t1*t0*t1
270+ True
271+ sage: t0*t2 == t2*t0
272+ True
273+ sage: t0*t3*t0 == t3*t0*t3
274+ True
275+ sage: T = [t0, t1, t2, t3]
276+ sage: emb = B.prod(T[i-1] if i > 0 else ~T[-i-1] for i in elm.Tietze())
277+ sage: emb.is_one()
278+ False
279+
280+ Since the Burau representation does not respect the group embedding,
281+ the corresponding `B_5` element's Burau matrix is not the identity
282+ (Bigelow gave an example of the representation not being faithful for
283+ `B_5`, but it is still open for `B_4`)::
284+
285+ sage: emb.burau_matrix() != 1
286+ True
287+
288+ We also verify the result using the elements in [BQ2024]_ Remark 4.2::
289+
290+ sage: ap = s3 * s1 * s2 * s1 * ~s3 * s4 * s2 * s3 * s2 * ~s3 * s1^-2 * s4
291+ sage: bp = s1 * ~s4 * s1^2 * s3^-2 * ~s2 * s4 * s1 * ~s3 * s2 * ~s4 * s3 * s1 * s4 * s1 * ~s2 * s4^-2 * s3
292+ sage: alpha = ap * s3 * ~ap
293+ sage: beta = bp * s2 * ~bp
294+ sage: elm = alpha * beta * ~alpha * ~beta
295+ sage: elm.burau_matrix()
296+ [1 0 0 0]
297+ [0 1 0 0]
298+ [0 0 1 0]
299+ [0 0 0 1]
300+
301+ REFERENCES:
302+
303+ - [BQ2024]_
304+ """
305+ gens , invs = self .parent ()._burau_generators
306+ MS = gens [0 ].parent ()
307+ ret = MS .prod (gens [i - 1 ] if i > 0 else invs [- i - 1 ] for i in self .Tietze ())
308+
309+ if var == 't' :
310+ return ret
311+
312+ from sage .rings .polynomial .laurent_polynomial_ring import LaurentPolynomialRing
313+ poly_ring = LaurentPolynomialRing (ret .base_ring ().base_ring (), var )
314+ return ret .change_ring (poly_ring )
315+
159316
160317class FiniteTypeArtinGroupElement (ArtinGroupElement ):
161318 """
@@ -453,7 +610,7 @@ def __classcall_private__(cls, coxeter_data, names=None):
453610 from sage .groups .raag import RightAngledArtinGroup
454611 return RightAngledArtinGroup (coxeter_data .coxeter_graph (), names )
455612 if not coxeter_data .is_finite ():
456- raise NotImplementedError
613+ return super (). __classcall__ ( cls , coxeter_data , names )
457614 if coxeter_data .coxeter_type ().cartan_type ().type () == 'A' :
458615 from sage .groups .braid import BraidGroup
459616 return BraidGroup (coxeter_data .rank ()+ 1 , names )
@@ -476,15 +633,17 @@ def __init__(self, coxeter_matrix, names):
476633 rels = []
477634 # Generate the relations based on the Coxeter graph
478635 I = coxeter_matrix .index_set ()
636+ gens = free_group .gens ()
479637 for ii , i in enumerate (I ):
480- for j in I [ii + 1 :]:
638+ for jj , j in enumerate ( I [ii + 1 :], start = ii + 1 ) :
481639 m = coxeter_matrix [i , j ]
482640 if m == Infinity : # no relation
483641 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 ))
642+ elt = (gens [ii ] * gens [jj ]) ** (m // 2 )
643+ if m % 2 == 1 :
644+ elt = elt * gens [ii ] * ~ gens [jj ]
645+ elt = elt * (~ gens [ii ] * ~ gens [jj ]) ** (m // 2 )
646+ rels .append (elt )
488647 FinitelyPresentedGroup .__init__ (self , free_group , tuple (rels ))
489648
490649 def _repr_ (self ):
@@ -688,6 +847,153 @@ def _standard_lift(self, w):
688847 """
689848 return self (self ._standard_lift_Tietze (w ))
690849
850+ @lazy_attribute
851+ def _burau_generators (self ):
852+ """
853+ The Burau matrices for the generators of ``self`` and their inverses.
854+
855+ EXAMPLES::
856+
857+ sage: A = ArtinGroup(['G',2])
858+ sage: A._burau_generators
859+ [[
860+ [-t^2 a*t] [ 1 0]
861+ [ 0 1], [ a*t -t^2]
862+ ],
863+ [
864+ [ -t^-2 a*t^-1] [ 1 0]
865+ [ 0 1], [a*t^-1 -t^-2]
866+ ]]
867+
868+ sage: A = ArtinGroup(['H',3])
869+ sage: A._burau_generators
870+ [[
871+ [-t^2 t 0] [ 1 0 0]
872+ [ 0 1 0] [ t -t^2 (1/2*a + 1/2)*t]
873+ [ 0 0 1], [ 0 0 1],
874+ <BLANKLINE>
875+ [ 1 0 0]
876+ [ 0 1 0]
877+ [ 0 (1/2*a + 1/2)*t -t^2]
878+ ],
879+ [
880+ [-t^-2 t^-1 0]
881+ [ 0 1 0]
882+ [ 0 0 1],
883+ <BLANKLINE>
884+ [ 1 0 0]
885+ [ t^-1 -t^-2 (1/2*a + 1/2)*t^-1]
886+ [ 0 0 1],
887+ <BLANKLINE>
888+ [ 1 0 0]
889+ [ 0 1 0]
890+ [ 0 (1/2*a + 1/2)*t^-1 -t^-2]
891+ ]]
892+
893+ sage: CM = matrix([[1,4,7], [4,1,10], [7,10,1]])
894+ sage: A = ArtinGroup(CM)
895+ sage: gens = A._burau_generators[0]; gens
896+ [
897+ [ -t^2 (E(8) - E(8)^3)*t (-E(7)^3 - E(7)^4)*t]
898+ [ 0 1 0]
899+ [ 0 0 1],
900+ <BLANKLINE>
901+ [ 1 0 0]
902+ [ (E(8) - E(8)^3)*t -t^2 (E(20) - E(20)^9)*t]
903+ [ 0 0 1],
904+ <BLANKLINE>
905+ [ 1 0 0]
906+ [ 0 1 0]
907+ [(-E(7)^3 - E(7)^4)*t (E(20) - E(20)^9)*t -t^2]
908+ ]
909+ sage: all(gens[i] * A._burau_generators[1][i] == 1 for i in range(3))
910+ True
911+ sage: B1, B2, B3 = gens
912+ sage: (B1 * B2)^2 == (B2 * B1)^2
913+ True
914+ sage: (B2 * B3)^5 == (B3 * B2)^5
915+ True
916+ sage: B1 * B3 * B1 * B3 * B1 * B3 * B1 == B3 * B1 * B3 * B1 * B3 * B1 * B3
917+ True
918+ """
919+ data = self .coxeter_type ()
920+ coxeter_matrix = self .coxeter_matrix ()
921+ n = coxeter_matrix .rank ()
922+
923+ # Determine the base field
924+ if data .is_simply_laced ():
925+ from sage .rings .integer_ring import ZZ
926+ base_ring = ZZ
927+ elif data .is_finite ():
928+ from sage .rings .number_field .number_field import QuadraticField
929+ letter = data .cartan_type ().type ()
930+ if letter in ['B' , 'C' , 'F' ]:
931+ base_ring = QuadraticField (2 )
932+ elif letter == 'G' :
933+ base_ring = QuadraticField (3 )
934+ elif letter == 'H' :
935+ base_ring = QuadraticField (5 )
936+ else :
937+ from sage .rings .universal_cyclotomic_field import UniversalCyclotomicField
938+ base_ring = UniversalCyclotomicField ()
939+ else :
940+ from sage .rings .universal_cyclotomic_field import UniversalCyclotomicField
941+ base_ring = UniversalCyclotomicField ()
942+
943+ # Construct the matrices
944+ from sage .matrix .args import SparseEntry
945+ from sage .matrix .matrix_space import MatrixSpace
946+ from sage .rings .polynomial .laurent_polynomial_ring import LaurentPolynomialRing
947+ import sage .rings .abc
948+ poly_ring = LaurentPolynomialRing (base_ring , 't' )
949+ q = - poly_ring .gen ()
950+ MS = MatrixSpace (poly_ring , n , sparse = True )
951+ one = MS .one ()
952+ # FIXME: Hack because there is no ZZ \cup \{ \infty \}: -1 represents \infty
953+ if isinstance (base_ring , sage .rings .abc .UniversalCyclotomicField ):
954+ E = base_ring .gen
955+
956+ def val (x ):
957+ if x == - 1 :
958+ return 2 * q
959+ elif x == 1 :
960+ return 1 + q ** 2
961+ else :
962+ return q * (E (2 * x ) + ~ E (2 * x ))
963+ elif isinstance (base_ring , sage .rings .abc .NumberField_quadratic ):
964+ from sage .rings .universal_cyclotomic_field import UniversalCyclotomicField
965+ E = UniversalCyclotomicField ().gen
966+
967+ def val (x ):
968+ if x == - 1 :
969+ return 2 * q
970+ elif x == 1 :
971+ return 1 + q ** 2
972+ else :
973+ return q * base_ring ((E (2 * x ) + ~ E (2 * x )).to_cyclotomic_field ())
974+ else :
975+ def val (x ):
976+ if x == - 1 :
977+ return 2 * q
978+ elif x == 1 :
979+ return 1 + q ** 2
980+ elif x == 2 :
981+ return 0
982+ elif x == 3 :
983+ return q
984+ else :
985+ from sage .functions .trig import cos
986+ from sage .symbolic .constants import pi
987+ return q * base_ring (2 * cos (pi / x ))
988+ index_set = data .index_set ()
989+ gens = [one - MS ([SparseEntry (i , j , val (coxeter_matrix [index_set [i ], index_set [j ]]))
990+ for j in range (n )])
991+ for i in range (n )]
992+ invs = [one - q ** - 2 * MS ([SparseEntry (i , j , val (coxeter_matrix [index_set [i ], index_set [j ]]))
993+ for j in range (n )])
994+ for i in range (n )]
995+ return [gens , invs ]
996+
691997 Element = ArtinGroupElement
692998
693999
0 commit comments