from sage.all_cmdline import *
_sage_const_3 = Integer(3); _sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_7 = Integer(7); _sage_const_6 = Integer(6); _sage_const_5 = Integer(5); _sage_const_4 = Integer(4); _sage_const_100 = Integer(100); _sage_const_1024 = Integer(1024); _sage_const_32 = Integer(32); _sage_const_12 = Integer(12); _sage_const_11 = Integer(11); _sage_const_648 = Integer(648); _sage_const_155520 = Integer(155520); _sage_const_25 = Integer(25); _sage_const_24 = Integer(24); _sage_const_48 = Integer(48)
r"""
#####################################################################################################################
# Cubic factor groups of braid groups
#####################################################################################################################
##############################################################################
# Copyright (C) 2016 Sebastian Oehms <[email protected]>
#
# Distributed under the terms of the GNU General Public License (GPL)
#
# The full text of the GPL is available at:
#
# http://www.gnu.org/licenses/
##############################################################################
This module is devoted for factor groups of the Artin braid groups, such that the images $s_i$ of the braid generators have order three:
$s_i^3=1$
In general these groups have firstly been investigated by Coxeter, H.S.M in: "Factor groups of the braid groups, Proceedings of the Fourth Candian Mathematical Congress (Vancover 1957), pp. 95-122".
Coxeter showed, that these groups are finite as long as the number of strands is less than 6 and infinite elsewise. More explicitely the factor group on three strand braids is isomorphic to $SL(2,3)$, on four strand braids to $GU(3,2)$ and on five strand braids to $Sp(4,3) x C_3$. Today, these groups are known as irreducible complex reflection groups enumerated in the Shephard-Todd classification as $G_{4}$, $G_{25}$ and $G_{32}$.
Coxeter realized these groups as subgroups of unitary groups with respect to a certain hermitian form over the complex numbers (in fact over $\QQ$ adjoined with a primitive 12-th root of unity).
In "Einige endliche Faktorgruppen der Zopfgruppen" (Math. Z., 163 (1978), 291-302) J. Assion considered two series $S(m)$ and $U(m)$ of finite dimensional factors of these groups. The additional relations on the braid group generators $\{ s_1, \cdot , s_{m-1}\}$ are
S) $s_3 s_1 t_2 s_1 t_2^{-1} t_3 t_2 s_1 t_2^{-1} t_3^{-1) = 1$ for $m >= 5$ in case $S(m)$
U) $t_1 t_3 = 1$ for $m >= 5$ in case $U(m)$
where $t_i = (s_i s_{i+1})^3$. He showed that each series of finite cubic braid group factors must be an epimorphic image of one of his two series, as long as the groups with less than 5 strands are the full cubic braid groups, whereas the group on 5 strands is not. He realized the groups $S(m)$ as symplectic groups over $GF(3)$ (resp. subgroups therein) and $U(m)$ as general unitary groups over $GF(4)$ (resp. subgroups therein).
This class implements all the groups conidered by Coxeter and Assion as finitely presented groups (via the gap interface) together with the classical realizations given by the authors. It also contains the coercion maps between the two ways of
realization. In addition the user can construct other realizations and maps to matrix groups with help of the burau representation. In case gap3 and CHEVIE are installed under sage version 7.2 (or later) the reflection groups via the gap3
interface are availlable, too. The methods for all this functionality are:
- as_classical_group
- as_matrix_group
- as_reflection_group (needs sage version 7.2 up and gap3 + CHEVIE)
- as_permutation_group
Further methods are:
- order
- pre_image_braid_group
- cubic_braid_subgroup
- character_table
For more information and EXAMPLES type
sage: print CubicBraidGroup_class.__doc__
AUTHOR:
Sebastian Oehms, Sept. 2016
"""
from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement
from sage.misc.decorators import options, rename_keyword
from sage.groups.braid import *
from lib.utils_sys import *
from lib.utils_gap_interface import *
from lib.local_permgroup import *
from lib.local_braid import *
from lib.local_matrix_group import *
class CubicBraidElement(FinitelyPresentedGroupElement):
"""
This class models elements of cubic factor groups of the braid group. It is the element class of
the CubicBraidGroup_class
If you don't see this well formatted type
sage: print CubicBraidElement.__doc__
It is realized as a particular case of elements of a finitely presented group (inherited from
FinitelyPresentedGroupElement)
EXAMPLES:
sage: C4.<c1,c2,c3> = CubicBraidGroup(4)
sage: C4
Cubic Braid group on 4 strands
sage: ele1 = c1*c2*c3^-1*c2^-1; type(ele1)
<class 'lib.cubic_braid.CubicBraidGroup_class_with_category.element_class'>
sage: ele2 = C4((1, 2, -3, -2))
sage: ele1 == ele2
True
For more information see the parent class typing
sage: print CubicBraidGroup_class.__doc__
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
def braid(self):
"""
Return the canonical braid preimage of self as Object of the class Braid,
If you don't see this well formatted type
sage: print CubicBraidElement.braid.__doc__
OUTPUT:
the preimage of self as instance of the Braid class which is the element class of the BraidGroup_class
EXAMPLES::
sage: C3.<c1, c2> = CubicBraidGroup(3)
sage: c1.parent()
Cubic Braid group on 3 strands
sage: c1.braid().parent()
Braid group on 3 strands
For information type
sage: print CubicBraidGroup_class.__doc__
"""
pre_image_braid_grp = self.parent().pre_image_braid_group()
pre_image_braid = pre_image_braid_grp( self )
return pre_image_braid
def cubic_writhe( self ):
"""
Return the exponent_sum of the preimage braid modulo 3
If you don't see this well formatted type
sage: print CubicBraidElement.cubic_writhe.__doc__
OUTPUT:
Integer 0, 1, 2 giving the exponent_sum modulo 3 in a word in the braid generators representig self
EXAMPLES::
sage: S4.<s1,s2,s3>=AssionGroupS(4)
sage: s=s1*s2*s3*s2
sage: s.cubic_writhe()
1
sage:
AUTHOR:
- Sebastian Oehms, Sept. 2016
"""
exp_sum = self.braid().exponent_sum()
return exp_sum % _sage_const_3
def _burau_matrix_(self, rootBur = None, Domain = None, characteristic = None, reduced=False, version='default'):
"""
Return the Burau matrix of the cubic braid coset.
If you don't see this well formatted type
sage: print CubicBraidElement._burau_matrix_.__doc_
This is the internal version of the "burau_matrix" method which returns more information than the main method
for more information on the main method "burau_matrix" type
sage: print CubicBraidElement.burau_matrix.__doc_
The only difference to that method is this:
OUTPUT:
a pair consisting of
- The Burau matrix of the cubic braid coset with entries in the domain given by the options
- the value of rootBur which is used. If the keyword rootBur has been set, this value is identical to this.
Otherwise, the value which has been calculated from the other parameters is returned
EXAMPLES:
sage: S3.<s1,s2>=AssionGroupS(3)
sage: s2.burau_matrix( characteristic=2, version='unitary' )
[ 1 0]
[rI + 1 rI]
sage: s2._burau_matrix_( characteristic=2, version='unitary' )
(
[ 1 0]
[rI + 1 rI], rI + 1
)
sage:
AUTHOR:
- Sebastian Oehms, Sept. 2016
"""
pre_image_braid = self.braid( )
BurauOri = pre_image_braid.burau_matrix( var='tt', reduced = reduced, version=version )
d = BurauOri.dimensions()
if Domain != None:
if isinstance( Domain, UniversalCyclotomicField):
if rootBur == None:
if version == 'unitary':
rootBur = Domain.gen(_sage_const_12 )
else:
rootBur = Domain.gen(_sage_const_6 )
if rootBur == None:
tT = var('tT')
if version == 'unitary':
minPolRootBur = tT**_sage_const_4 -tT**_sage_const_2 +_sage_const_1
else:
minPolRootBur = tT**_sage_const_2 -tT +_sage_const_1
if Domain == None:
if (characteristic == None):
characteristic = _sage_const_0
try:
characteristic = Integer( characteristic )
except:
raise ValueError('characteristic must be in integer')
if characteristic <> _sage_const_0 and not characteristic.is_prime():
raise ValueError('characteristic must be a prime')
if characteristic == _sage_const_0 :
if version == 'unitary':
PDomain = CyclotomicField(_sage_const_12 )
else:
PDomain = CyclotomicField(_sage_const_3 )
else:
PDomain = GF( characteristic )
minPolRootBur = PDomain[tT]( minPolRootBur )
rootList = minPolRootBur.roots()
if len(rootList) == _sage_const_0 :
Domain = minPolRootBur.splitting_field(names=('rI',)); (rI,) = Domain._first_ngens(1)
minPolRootBur = Domain[tT]( minPolRootBur )
else:
Domain = PDomain
rootList = minPolRootBur.roots()
for root in rootList:
if root[_sage_const_0 ] == _sage_const_0 :
continue
rootBur = root[_sage_const_0 ]
if root[_sage_const_1 ] == _sage_const_1 :
break
else:
if characteristic == None:
characteristic = Domain.characteristic()
elif characteristic <> Domain.characteristic():
raise ValueError('characteristic of Domain does not match given characteristic')
minPolRootBur = Domain[tT]( minPolRootBur )
rootList = minPolRootBur.roots()
if len(rootList) == _sage_const_0 :
print "Warning: Domain extended to splitting field of", minPolRootBur
Domain = minPolRootBur.splitting_field(names=('rI',)); (rI,) = Domain._first_ngens(1)
minPolRootBur = Domain[tT]( minPolRootBur )
rootList = minPolRootBur.roots()
for root in rootList:
if root[_sage_const_0 ] == _sage_const_0 :
continue
rootBur = root[_sage_const_0 ]
if root[_sage_const_1 ] == _sage_const_1 :
break
else:
if Domain == None:
Domain = rootBur.parent()
if characteristic == None:
characteristic = Domain.characteristic()
elif characteristic <> Domain.characteristic():
raise ValueError('characteristic of Domain does not match given characteristic')
if _sage_const_1 not in Domain:
raise ValueError('rootBur must belong to a domain containing 1')
if version == 'unitary':
testRootBur = Domain(rootBur**_sage_const_4 -rootBur**_sage_const_2 +_sage_const_1 )
if testRootBur <> _sage_const_0 :
raise ValueError('rootBur must vanish on x**4-x**2+1')
else:
testRootBur = Domain(rootBur**_sage_const_2 -rootBur +_sage_const_1 )
if testRootBur <> _sage_const_0 :
raise ValueError('rootBur must vanish on x**2-x+1')
def conv2Domain ( LaurPol ):
PolConst = LaurPol.polynomial_construction()
R = Domain['tt']; (tt,) = R._first_ngens(1)
p1 = R( PolConst[_sage_const_0 ] )
p2 = rootBur**(PolConst[_sage_const_1 ])
erg = p1.substitute( tt = rootBur ) * p2
return erg
BurauMat = matrix(d[_sage_const_0 ],d[_sage_const_1 ], lambda i,j: conv2Domain(BurauOri[i,j] ) )
return BurauMat, rootBur
def burau_matrix(self, rootBur = None, Domain = None, characteristic = None, reduced=False, version='default'):
r"""
Return the Burau matrix of the cubic braid coset.
If you don't see this well formatted type
sage: print CubicBraidElement.burau_matrix.__doc_
This method uses the same method belonging to the Braid class, but reduces the parameter to a primitive six
root of unity, respectivly an element vanishing on the polynomial $x^2-x+1$
INPUT: (all parameters are optional by keyword )
- "rootBur": six root of unity in some field (default six root of unity over $\QQ$)
- "Domain": base_ring for the burau matrix (default is Cyclotomic Field of order 3 and degree 2, resp. the
domain of rootBur if given)
- "reduced": boolean (default: False); whether to return the reduced or unreduced Burau representation
(see Braid class )
- "characteristic": integer giving the characteristic of the domain (default is 0 or the characteristic of
the doamain if given)
- "version": values:
'unitary': gives the unitary form according to Squier (see Braid._unitary_burau_matrix_() )
'default': the method behaves like the original one of the Braid -class
any value else: gives the reduced form given on wikipedia
OUTPUT:
The Burau matrix of the cubic braid coset with entries in the domain given by the options
If you need the values of the reconstructed keywords "rootBur", "Domain" or "characteristic" use the internal
version _burau_matrix_ of this method
RAISE:
- ValueError: 'characteristic must be in integer'
- ValueError: 'characteristic must be a prime'
- ValueError: 'characteristic of Domain does not match given characteristic'
- ValueError: 'rootBur must belong to a domain containing 1'
- ValueError: 'rootBur must vanish on $x^2-x+1$ default case
- ValueError: 'rootBur must vanish on $x^4-x^2+1$ in case of call with version = 'unitary'
EXAMPLES::
sage: C3.<c1, c2> = CubicBraidGroup(3)
sage: ele1 = c1*c2*c1
sage: BurauTest = ele1.burau_matrix(); print BurauTest
[ -zeta3 1 zeta3]
[ -zeta3 zeta3 + 1 0]
[ 1 0 0]
sage: BurauTest.base_ring()
Cyclotomic Field of order 3 and degree 2
sage:
sage: BurauTest = ele1.burau_matrix( characteristic = 0 ); print BurauTest
[ -zeta3 1 zeta3]
[ -zeta3 zeta3 + 1 0]
[ 1 0 0]
sage: BurauTest.base_ring()
Cyclotomic Field of order 3 and degree 2
sage:
sage: BurauTest = ele1.burau_matrix( Domain = QQ ); print BurauTest
Warning: Domain extended to splitting field of tT^2 - tT + 1
[-rI + 1 1 rI - 1]
[-rI + 1 rI 0]
[ 1 0 0]
sage: BurauTest.base_ring()
Number Field in rI with defining polynomial tT^2 - tT + 1
sage:
sage: BurauTest = ele1.burau_matrix( Domain = QQ[I, sqrt(3)] ); print BurauTest
[ 1/2*sqrt3*I + 1/2 1 -1/2*sqrt3*I - 1/2]
[ 1/2*sqrt3*I + 1/2 -1/2*sqrt3*I + 1/2 0]
[ 1 0 0]
sage: BurauTest.base_ring()
Number Field in I with defining polynomial x^2 + 1 over its base field
sage:
sage: BurauTest = ele1.burau_matrix( characteristic = 7 ); print BurauTest
[3 1 4]
[3 5 0]
[1 0 0]
sage: BurauTest.base_ring()
Finite Field of size 7
sage:
sage: BurauTest = ele1.burau_matrix( characteristic = 2 ); print BurauTest
[rI + 1 1 rI + 1]
[rI + 1 rI 0]
[ 1 0 0]
sage: BurauTest.base_ring()
Finite Field in rI of size 2^2
sage:
sage:
sage: F4.<r64> = GF(4)
sage: BurauTest = ele1.burau_matrix( rootBur=r64 ); print BurauTest
[r64 + 1 1 r64 + 1]
[r64 + 1 r64 0]
[ 1 0 0]
sage: BurauTest.base_ring()
Finite Field in r64 of size 2^2
sage:
sage: BurauTest = ele1.burau_matrix( Domain = GF(5) ); print BurauTest
Warning: Domain extended to splitting field of tT^2 + 4*tT + 1
[2*rI + 2 1 3*rI + 3]
[2*rI + 2 3*rI + 4 0]
[ 1 0 0]
sage: BurauTest.base_ring()
Finite Field in rI of size 5^2
sage:
sage: BurauTest = ele1.burau_matrix( version = 'unitary' ); print BurauTest
[ 0 -zeta12^3]
[-zeta12^3 0]
sage: BurauTest.base_ring()
Cyclotomic Field of order 12 and degree 4
sage:
sage: BurauTest = ele1.burau_matrix( Domain = QQ[I, sqrt(3)], version = 'unitary' ); print BurauTest
[ 0 -I]
[-I 0]
sage: BurauTest.base_ring()
Number Field in I with defining polynomial x^2 + 1 over its base field
AUTHOR:
- Sebastian Oehms, Sept. 2016
REFERENCES:
- :wikipedia: "Burau_representation"
for more inormation type
sage: print Braid.burau_matrix.__doc__
sage: print local_Braid.burau_matrix.__doc__
sage: print local_Braid.__burau_matrix_wikipedia__.__doc__
sage: print local_Braid.__burau_matrix_unitary__.__doc__
"""
res = self._burau_matrix_( rootBur = rootBur, Domain = Domain, characteristic = characteristic, reduced = reduced,
version = version)[_sage_const_0 ]
return res
class CubicBraidGroup_class(FinitelyPresentedGroup):
r"""
Class to handel cubic factors of braid group on n strands
If you don't see this well formatted type
sage: print CubicBraidGroup_class.__doc__
This class implements quotient groups of the braid group mapping their generators to elements of order 3
(see the module header for more informations on these groups)
These groups are implemented as a particular case of finitely presented groups similar to the BraidGroup class
A cubic braid group can be created by giving the number of strands, and the name of the generators in a similar
way as it works for the BraidGroup class.
INPUT (to the constructor):
- "names": (see the BraidGroup_class docomentation)
- "AdditionalRelation": (keyword, explantaion see below)
- "verbose": (keyword, explantaion see below)
RAISE (on init):
- ValueError: "the number of strands must be an integer larger than one"
Setting the keyword 'AdditionalRelation' to one on the values 'S' or 'U' the additional relations due to
Assion are added:
'S': $s_3 s_1 t_2 s_1 t_2^{-1} t_3 t_2 s_1 t_2^{-1} t_3^{-1) = 1$ for $m >= 5$
'U': $t_1 t_3 = 1$ for $m >= 5$
where $t_i = (s_i s_{i+1})^3$. If AdditionalRelation='C' (default) only the cubic relation on the generators is
active (Coxeters case of investigation). Note that for n=2,3,4 the groups do not differ between the three possible
values of AdditionalRelation (as finitely presented groups). But anyway, the classes for 'C', 'S' and 'U' are
different, since they have different classical realizations implemented .
Setting the keyword verbose it is possible to print time stamp messages in order to do a performance or
call stack debugging. This keyword uses the timeStampControl class. For more information on this type
print setupTimeStamp.__doc__
print timeStampControl.__doc__
print timeStampControl.print_timestamp.__doc__
print print_time_tb.__doc__
The creation of instances of this class can also be done more easy by help of the functions CubicBraidGroup,
AssionGroupS and AssionGroupU (similar to the function BraidGroup with respect to the BraidGroup_class)
EXAMPLES:
sage: from cubic_braid import *
sage: U3 = CubicBraidGroup(3, AdditionalRelation = 'U'); U3
Assion group on 3 strands of type U
sage: U3.gens()
(c0, c1)
alternate possibilities defining U3:
sage: U3 = AssionGroupU(3); U3
Assion group on 3 strands of type U
sage: U3.gens()
(u0, u1)
sage: U3.<u1,u2> = AssionGroupU(3); U3
Assion group on 3 strands of type U
sage: U3.gens()
(u1, u2)
alternates naming the generators:
sage: U3 = AssionGroupU(3, 'a, b'); U3
Assion group on 3 strands of type U
sage: U3.gens()
(a, b)
sage: C3 = CubicBraidGroup(3, 't'); C3
Cubic Braid group on 3 strands
sage: C3.gens()
(t0, t1)
sage: U3.is_isomorphic( C3 )
True
sage: U3.as_classical_group()
Subgroup of (The projective general unitary group of degree 3 over Finite Field of size 2) generated by
[(1,7,6) (3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)]
sage: C3.as_classical_group()
Subgroup of General Unitary Group of degree 2 over Universal Cyclotomic Field with respect to hermitian form
[-E(12)^7 + E(12)^11 -1]
[ -1 -E(12)^7 + E(12)^11]
generated by (
[ E(3) E(12)^11]
[ 0 1],
[ 1 0]
[E(12)^11 E(3)])
using verbose mode:
sage: C3.<c1,c2> = CubicBraidGroup(3, verbose=True); C3
L: StackInfo Elapse: 0, Total: 0 Ident: C3 In: __init__ Line: 403
L: StackInfo Elapse: 197, Total: 0 Begin In: __create_classical_realization__ Line: 910
L: StackInfo Elapse: 8, Total: 0 Begin In: as_matrix_group Line: 1031
L: Body Elapse: 92, Total: 0 genList prepared In: as_matrix_group Line: 1038
L: Body Elapse: 52, Total: 0 MatGroup defined In: as_matrix_group Line: 1054
L: StackInfo Elapse: 356, Total: 0 Begin In: gap_hom Line: 143
L: Debug Elapse: 8, Total: 0 GroupHomomorphis In: gap_hom Line: 188
L: Debug Elapse: 17, Total: 0 checked if groupMap works In: gap_hom Line: 199
L: StackInfo Elapse: 8, Total: 0 End In: gap_hom Line: 226
L: StackInfo Elapse: 44, Total: 0 Begin In: __check_homomorphism__ Line: 60
L: StackInfo Elapse: 52, Total: 0 End In: __check_homomorphism__ Line: 625
L: Body Elapse: 3, Total: 0 Hom from self defined In: as_matrix_group Line: 1064
L: StackInfo Elapse: 62, Total: 0 Begin In: gap_hom Line: 143
L: Debug Elapse: 4, Total: 0 GroupHomomorphis In: gap_hom Line: 188
L: Debug Elapse: 20, Total: 0 checked if groupMap works In: gap_hom Line: 199
L: StackInfo Elapse: 4, Total: 0 End In: gap_hom Line: 226
L: Body Elapse: 35, Total: 0 Section to self defined In: as_matrix_group Line: 1077
L: StackInfo Elapse: 3, Total: 0 Ende In: as_matrix_group Line: 1102
L: StackInfo Elapse: 3, Total: 0 End In: __create_classical_realization__ Line: 975
L: StackInfo Elapse: 12, Total: 0 Ident: C3 In: __init__ Line: 472
Cubic Braid group on 3 strands
sage:
sage:
sage: C3.<c1,c2> = CubicBraidGroup(3, verbose=30); C3
L: StackInfo Elapse: 62, Total: 0 (truncated 1) Begin In: __create_classical_realization__ Line: 910
---> __init__ In: lib/cubic_braid.py Line: 471
---> __classcall__ In: /opt/sage/sage-6.9-i686-Linux/local/lib/python2.7/site-packages/sage/structure
/unique_representation.py Line: 1021
---> CubicBraidGroup In: lib/cubic_braid.py Line: 1231
L: StackInfo Elapse: 405, Total: 0 Begin In: as_matrix_group Line: 1031
---> __create_classical_realization__ In: lib/cubic_braid.py Line: 968
---> __init__ In: lib/cubic_braid.py Line: 471
---> __classcall__ In: /opt/sage/sage-6.9-i686-Linux/local/lib/python2.7/site-packages/sage/structure
/unique_representation.py Line: 1021
L: Body Elapse: 145, Total: 0 genList prepared In: as_matrix_group Line: 1038
---> __create_classical_realization__ In: lib/cubic_braid.py Line: 968
---> __init__ In: lib/cubic_braid.py Line: 471
---> __classcall__ In: /opt/sage/sage-6.9-i686-Linux/local/lib/python2.7/site-packages/sage/structure
/unique_representation.py Line: 1021
Cubic Braid group on 3 strands
sage:
TESTS:
sage: C4 = CubicBraidGroup(4)
sage: TestSuite(C4).run()
sage: C5 = CubicBraidGroup(5)
sage: TestSuite(C5).run()
sage: C6 = CubicBraidGroup(6)
sage: TestSuite(C6).run()
sage: S3 = AssionGroupS(3)
sage: TestSuite(S3).run()
sage: S4 = AssionGroupS(4)
sage: TestSuite(S5).run()
sage: U3 = AssionGroupU(3)
sage: TestSuite(U3).run()
sage: U4 = AssionGroupU(4)
sage: TestSuite(U4).run()
sage: U5 = AssionGroupU(5)
sage: TestSuite(U5).run()
METHODS (implemented / overwriten here):
- as_classical_group(): type
sage: print CubicBraidGroup_class.as_classical_group.__doc__
- as_matrix_group(): type
sage: print CubicBraidGroup_class.as_matrix_group.__doc__
- as_refection_group(): type
sage: print CubicBraidGroup_class.as_refection_group.__doc__
- as_permutation_group(): type
sage: print CubicBraidGroup_class.as_permutation_group.__doc__
- pre_image_braid_group: type
sage: print CubicBraidGroup_class.pre_image_braid_group.__doc__
- cubic_braid_subgroup(): type
sage: print CubicBraidGroup_class.cubic_braid_subgroup.__doc__
- centralizing_element(): type
sage: print CubicBraidGroup_class.centralizing_element.__doc__
- order(): type
sage: print CubicBraidGroup_class.order.__doc__
- character_table(): type
sage: print CubicBraidGroup_class.character_table.__doc__
AUTHOR
- Sebastian Oehms, Sept. 2016
REFERENCES:
- Coxeter, H.S.M: "Factor groups of the braid groups, Proceedings of the Fourth Candian Mathematical Congress
(Vancover 1957), pp. 95-122".
- J. Assion: "Einige endliche Faktorgruppen der Zopfgruppen" (Math. Z., 163 (1978), 291-302)
"""
Element = CubicBraidElement
def __init__(self, names, AdditionalRelation = 'C', verbose = False ):
"""
Python constructor.
for more information type
sage: print CubicBraidGroup_class.__doc__
AUTHOR
- Sebastian Oehms, Sept. 2016!@!@
"""
self._AdditionalRelation_ = AdditionalRelation
self._verbose_ = verbose
n = Integer(len(names))
self._nstrands_ = n+_sage_const_1
self._ident_ = self._AdditionalRelation_ + self._nstrands_.str()
self._TimeStamp_ = setupTimeStamp( verbose = verbose, Offset = _sage_const_2 , ShowDateTime = False )
self._TimeStampSub_ = setupTimeStamp( verbose = verbose, Offset = _sage_const_1 , ShowDateTime = False )
self.__print_timestamp__( "Ident: %s" %(self._ident_), TsLevel.StackInfo )
b = []
bi = []
t = []
ti = []
sage.groups.braid.BraidGroup_class = local_BraidGroup_class
self._pre_image_braid_group_ = BraidGroup( names )
if n<_sage_const_1 :
raise ValueError("the number of strands must be an integer larger than one")
free_group = FreeGroup(names)
oneHundertMB = _sage_const_100 *_sage_const_1024 **_sage_const_2
work_space_needed = {'C5':_sage_const_5 , 'C6':_sage_const_48 , 'U6':_sage_const_24 , 'S6':_sage_const_24 }
if self._ident_ in work_space_needed.keys():
gap_extend_workspace( work_space_needed[self._ident_]*oneHundertMB )
for i in range(_sage_const_1 , n+_sage_const_1 ):
b.append(free_group([i]))
bi.append(free_group([-i]))
if i < n:
tt = free_group([i, i+_sage_const_1 ])**_sage_const_3
t.append(tt)
tt = free_group([-i, -i-_sage_const_1 ])**_sage_const_3
ti.append(tt)
rels = list(self._pre_image_braid_group_.relations())
for i in range(_sage_const_0 , n):
rels.append(b[i]**_sage_const_3 )
if n>_sage_const_3 :
for i in range(_sage_const_0 , n-_sage_const_3 ):
if AdditionalRelation == 'U':
rels.append((t[i]*t[i+_sage_const_2 ])**_sage_const_3 )
elif AdditionalRelation == 'S':
rels.append(b[i+_sage_const_2 ]*b[i]*t[i+_sage_const_1 ]*b[i]*ti[i+_sage_const_1 ]*t[i+_sage_const_2 ]*t[i+_sage_const_1 ]*b[i]*ti[i+_sage_const_1 ]*ti[i+_sage_const_2 ])
FinitelyPresentedGroup.__init__(self, free_group, tuple(rels))
self._nstrands_ = n+_sage_const_1
self._ident_ = self._AdditionalRelation_ + self._nstrands_.str()
self._b_ = b
self._bi_ = bi
self._t_ = t
self._ti_ = ti
self._free_group_ = free_group
self._checked_homomorphism_=[]
self._classical_group_ = None
self._classical_group_gens_ = None
self._classical_base_group_ = None
self._classical_base_group_gens_ = None
self._centralizing_matrix_ = None
self._centralizing_element_ = None
self._classical_embedding_ = None
self.__create_classical_realization__()
self.__print_timestamp__( "Ident: %s" %(self._ident_), TsLevel.StackInfo )
return
def __reduce__(self):
"""
Checks or unity
If you don't see this well formatted type
sage: print CubicBraidGroup_class.__recuce__.__doc__
TESTS:
sage: C3=CubicBraidGroup(3)
sage: C3.__reduce__()
(<class 'lib.cubic_braid.CubicBraidGroup_class'>, (('c0', 'c1'), 'C', False))
sage: U3.<u1,u2>=AssionGroupU(3, verbose=100)
sage: U3.__reduce__()
(<class 'lib.cubic_braid.CubicBraidGroup_class'>, (('u1', 'u2'), 'U', 100))
"""
return (CubicBraidGroup_class, (self.variable_names(), self._AdditionalRelation_, self._verbose_,))
def _repr_(self):
"""
Return a string representation
If you don't see this well formatted type
sage: print CubicBraidGroup_class._repr_.__doc__
OUTPUT:
String decribing self
TESTS:
sage: C5 = CubicBraidGroup(5)
sage: C5 # indirect doctest
CubicBraid group on 5 strands
"""
if self._AdditionalRelation_ == 'C':
return "Cubic Braid group on %s strands"%(self._nstrands_)
else:
return "Assion group on %s strands of type %s"%(self._nstrands_ ,self._AdditionalRelation_)
def _test_constructions(self, **options):
"""
Method called by TestSuite
If you don't see this well formatted type
sage: print CubicBraidGroup_class._test_constructions.__doc__
the following is checked:
- construction of classical group was faithfull
- construction of permutation groups attached to self is faithful
- coercion maps to and from classical group exist and are inverse to each other
- coercion maps to and from permutatiobn group exist and are inverse to each other
- existence of some examples of matrix representations and commutativity between coercion maps
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
self.__print_timestamp__( "Begin", TsLevel.StackInfo )
Cl=self.as_classical_group()
homToClass = Cl.coerce_map_from( self )
homToClassNotNone = self._tester(**options)
homToClassNotNone.assert_( homToClass != None )
homToClassCheck = self._tester(**options)
self.__print_timestamp__ ("Check hom to classical", TsLevel.Body )
homToClassCheck.assert_( self.__check_homomorphism__( homToClass ) == True )
self.__print_timestamp__ ("Section from classical", TsLevel.Body )
sectFromClass = self.coerce_map_from( Cl )
sectFromClassNotNone = self._tester(**options)
sectFromClassNotNone.assert_( sectFromClass != None )
self.__print_timestamp__ ("Testing inverse", TsLevel.Body )
Clgen1 = Cl.gens()[_sage_const_0 ]
Clgen1Braid = self(Clgen1)
Clgen1Back = Cl(Clgen1Braid)
testClgen1Back = self._tester(**options)
testClgen1Back.assert_( Clgen1Back == Clgen1 )
self.__print_timestamp__ ("Testing order", TsLevel.Body )
orderForm = self.order()
orderCalc = self.order( by_formula = False )
testOrder = self._tester(**options)
testOrder.assert_( orderForm == orderCalc )
F3 = GF(_sage_const_3 ); r63=F3(_sage_const_2 ); F4 = GF(_sage_const_4 , names=('r64',)); (r64,) = F4._first_ngens(1)
self.__print_timestamp__ ("Testing permutation and matrix group", TsLevel.Body )
def test_attached_group( AttGroup, EleClass, EleSelf ):
"""
local function in CubicBraidGroup_class._test_constructions.__doc__
it tests conversion maps from self and the classical group to the given attached Group which must have
been defined using the as_matrix_group or as_ermutation_group methods
INPUT:
- "AttGroup": attached group (matrix group or permutation group) to be tested
- "EleSelf": element of self used to perform the test
- "EleClass": element of the classical group of self used to perform the test
"""
self.__print_timestamp__("Begin", TsLevel.StackInfo)
AttEleSelf = AttGroup(EleSelf)
self.__print_timestamp__ ("rightHandSide", TsLevel.BodySub1)
AttEleClass = AttGroup(EleClass)
self.__print_timestamp__ ("leftHandSide", TsLevel.BodySub1)
AttComute = self._tester(**options)
AttComute.assert_(AttEleSelf == AttEleClass)
self.__print_timestamp__("End", TsLevel.StackInfo)
self.__print_timestamp__ ("reflection group", TsLevel.BodySub1)
try:
Refl = self.as_reflection_group()
except:
Refl = None
if Refl != None:
test_attached_group(Refl, Clgen1, Clgen1Braid)
self.__print_timestamp__ ("permutation group", TsLevel.BodySub1)
Perm = self.as_permutation_group()
test_attached_group(Perm, Clgen1, Clgen1Braid)
self.__print_timestamp__ ("native permutation group", TsLevel.BodySub1)
if self._nstrands_ < _sage_const_4 :
PermN = self.as_permutation_group(native=True)
test_attached_group(PermN, Clgen1, Clgen1Braid)
self.__print_timestamp__ ("Default MatrixGroup", TsLevel.BodySub1)
MatDEF = self.as_matrix_group()
test_attached_group(MatDEF, Clgen1, Clgen1Braid)
self.__print_timestamp__ ("MatrixGroup over GF(3)", TsLevel.BodySub1)
if self._AdditionalRelation_ != 'U' or self._nstrands_ < _sage_const_5 :
MatF3 = self.as_matrix_group(rootBur=r63)
test_attached_group(MatF3, Clgen1, Clgen1Braid)
self.__print_timestamp__ ("MatrixGroup over GF(4)", TsLevel.BodySub1)
if self._AdditionalRelation_ != 'S' or self._nstrands_ < _sage_const_5 :
MatF4 = self.as_matrix_group(rootBur=r64)
test_attached_group(MatF4, Clgen1, Clgen1Braid)
self.__print_timestamp__ ("MatrixGroup over GF(5)", TsLevel.BodySub1)
if self._nstrands_ < _sage_const_5 or self._AdditionalRelation_ == 'C':
MatF5 = self.as_matrix_group(characteristic = _sage_const_5 )
test_attached_group(MatF5, Clgen1, Clgen1Braid)
self.__print_timestamp__ ("MatrixGroup over GF(7)", TsLevel.BodySub1)
MatF7 = self.as_matrix_group(Domain=GF(_sage_const_7 ))
test_attached_group(MatF7, Clgen1, Clgen1Braid)
self.__print_timestamp__("End", TsLevel.StackInfo)
return
def __print_timestamp__( self, Text, Level ):
"""
Method to print time stamped logging messages
If you don't see this well formatted type
sage: print CubicBraidGroup_class.__print_timestamp__.__doc__
This method uses the timeStampControl class. For more information on this type
print timeStampControl.__doc__
print timeStampControl.print_timestamp.__doc__
print print_time_tb.__doc__
INPUT:
- "Text": Text to be printed in the log message
- "Level": indicates the level (importance) of the message. The following values are posible
0 TsLevel.Silent to be pinted independent on any verbose mode
1 TsLevel.StackInfo classifies messages on entry and exit of subroutines
2 TsLevel.Body to be used in the body of a function
3 TsLevel.BodySub1 subordinary message to TsLevel.Body
4 TsLevel.BodySub2 subordinary message to TsLevel.Body1
5 TsLevel.Debug to print debug information
Note, that the higher levels include the for comming lower ones.
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
self._TimeStamp_.print_timestamp( Text = Text, Level = Level )
def __check_homomorphism__(self, test_map ):
"""
Method to check if the given map is well defined with respect to the relations of self
If you don't see this well formatted type
sage: print CubicBraidGroup_class.__check_homomorphism__.__doc__
INPUT:
- "test_map": the map from self to another group to be tested
OUTPUT:
boolean True if test_map vanishes on all relations of self, else false
WARNINGS:
"Warning: homomorphism not well defined for relation %s giving: %s" n case the result is False
EXAMPLES:
sage: S4.<s1,s2,s3>=AssionGroupS(4); S4
Assion group on 4 strands of type S
sage: S4Cl = S4.as_classical_group()
sage: f = S4Cl.convert_map_from( S4 )
sage: S4.__check_homomorphism__(f)
True
Note, the following may be an irritation: The generators of S4 and S4Cl are the same as set but in different order
sage: ClassGens=S4Cl.gens(); ClassGens
[(5,8,11)(6,9,12)(7,10,13)(23,26,29)(24,27,30)(25,28,31)(32,38,35)(33,39,36)(34,40,37),
(2,11,8)(3,13,9)(4,12,10)(17,35,26)(18,36,27)(19,37,28)(20,29,38)(21,30,39)(22,31,40),
(1,25,24)(2,29,26)(3,27,31)(6,16,33)(7,34,15)(8,20,35)(9,36,22)(11,38,17)(13,18,40)]
sage: S4Cl(s1)
(2,11,8)(3,13,9)(4,12,10)(17,35,26)(18,36,27)(19,37,28)(20,29,38)(21,30,39)(22,31,40)
sage: S4Cl(s2)
(5,8,11)(6,9,12)(7,10,13)(23,26,29)(24,27,30)(25,28,31)(32,38,35)(33,39,36)(34,40,37)
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
self.__print_timestamp__( "Begin", TsLevel.StackInfo )
check_needed = True
checked_homomorphism = list(self._checked_homomorphism_)
if checked_homomorphism != None:
if test_map in checked_homomorphism:
check_needed = False
if (check_needed == False ):
return True
self.__print_timestamp__( "check_needed", TsLevel.Body )
for relation in list(self.relations()):
self.__print_timestamp__( "relation %s"%(relation), TsLevel.Debug )
relVal = test_map(relation)
self.__print_timestamp__( "relation tested", TsLevel.Debug )
if relVal.is_one() == False:
print "Warning: homomorphism not well defined for relation %s giving: %s"%(relation, relVal )
return False
self.__print_timestamp__( "check_ok", TsLevel.Body )
checked_homomorphism.append( test_map )
self.__print_timestamp__( "check_registerd", TsLevel.Body )
self._checked_homomorphism_ = checked_homomorphism
self.__print_timestamp__( "End", TsLevel.StackInfo )
return True
def __create_classical_realization__(self):
"""
internal method to create the classical groups attached to self
If you don't see this well formatted type
sage: print CubicBraidGroup_class.__create_classical_realization__.__doc__
INPUT:
no
OUTPUT:
no
this methods sets the following global parameters of self:
- self._classical_group_ This is the classical group returned by as_classical_group method
- self._classical_group_gens_ generators of the former group
- self._classical_base_group_ this only differs in special cases for AssionGroup from the former
- self._classical_base_group_gens_ generators of the former group
- self._centralizing_matrix_ for AssionGroup: element in classical base group commuting with self
- self._centralizing_element_ image under natural map of the former one in the projective classical group
- self._classical_embedding_ as subgroup of classical base group (if different from class. group)
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
def create_hom_to_classical( self, Group, ImList ):
"""
internal method to create the homomorphism from self to classical group
this is a local function in CubicBraidGroup_class.__create_classical_realization__ using
gap_hom
see also:
sage: print gap_hom.__doc__
INPUT:
- "Group": target of the map
- "ImList": list of the images of the braid generators
OUTPUT:
the created homomorphism.
The created homomorphism is registered as coercion and conversion map for Group
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
self.__print_timestamp__( "Begin", TsLevel.StackInfo )
if ImList[_sage_const_0 ] in Group:
homToGroup = gap_hom( self, Group, GensTo = ImList, verbose = self._TimeStampSub_ )
else:
GroupImage = ImList[_sage_const_0 ].parent()
homToImage = gap_hom( self, GroupImage, GensTo = ImList, verbose = self._TimeStampSub_ )
homToGroup = homToImage
if Group.has_coerce_map_from( GroupImage ):
incl = Group.coerce_map_from( GroupImage )
homToGroup = incl * homToImage
Group.register_coercion( homToGroup )
self.__print_timestamp__( "End", TsLevel.StackInfo )
return homToGroup
def SetUpClassicalGroup( self, m, n, BaseGroup, ProjGroup, centralizing_vector, transvec2mat, transvecList ):
"""
internal method to create classical group for Assion groups
this is a local function in CubicBraidGroup_class.__create_classical_realization__
It handels the common part of symplectic and unitary version and creates all conversion map using gap_hom
see also:
sage: print gap_hom.__doc__
INPUT:
- "BaseGroup": The symplectic or unitary groups Sp(m,3) resp. GU(m,2)
- "ProjGroup": The projeective imaged of these group
- "centralizing_vector": The centralizing vector described by Assion
- "transvec2mat": Function to create the transection map from transvection vector
- "transvecList": List of transvection vectors
OUTPUT:
the function sets the global parameters of self decribed under
sage: print CubicBraidGroup_class.__create_classical_realization__.__doc__
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
self.__print_timestamp__( "Begin", TsLevel.StackInfo )
centralizing_matrix = BaseGroup(transvec2mat(centralizing_vector, fact=_sage_const_1 ))
centralizing_element = None
natHom = gap_hom( BaseGroup, ProjGroup, verbose = self._TimeStampSub_ )
ClGenList=[]
centralizing_element = natHom( centralizing_matrix )
anz_tv=_sage_const_0
BaseClGenList=[]
for v in transvecList:
anz_tv=anz_tv+_sage_const_1
if anz_tv >= n:
break
transvecMat = transvec2mat( v )
BaseClGenList.append( BaseGroup(transvecMat) )
if m == n:
projTransvecMat = natHom( transvecMat )
ClGenList.append( projTransvecMat )
else:
ClGenList.append( BaseGroup(transvecMat) )
ClassicalGroup = BaseGroup
if m == n:
ClassicalGroup = ProjGroup.subgroup( ClGenList )
for gen in ClGenList:
if gen * centralizing_element != centralizing_element *gen:
print "Internal Error! centralzier property failed for:", gen, centralizing_element
Embedding = None
if ClassicalGroup == BaseGroup:
create_hom_to_classical( self, ClassicalGroup, ClGenList )
gap_hom( ClassicalGroup, self, GensFrom = ClGenList, verbose = self._TimeStampSub_ )
else:
Embedding = BaseGroup.subgroup( BaseClGenList )
create_hom_to_classical( self, ClassicalGroup, ClGenList )
create_hom_to_classical( self, Embedding, BaseClGenList )
try:
gap_hom( ClassicalGroup, self, GensFrom = ClGenList, verbose = self._TimeStampSub_ )
except:
print "Warning: no map back from classical group (gap overflow)"
gap_hom( Embedding, self, GensFrom = BaseClGenList, verbose = self._TimeStampSub_ )
self._classical_group_ = ClassicalGroup
self._classical_group_gens_ = ClGenList
self._classical_base_group_ = BaseGroup
self._classical_base_group_gens = BaseClGenList
self._centralizing_matrix_ = centralizing_matrix
self._centralizing_element_ = centralizing_element
self._classical_embedding_ = Embedding
self.__print_timestamp__( "End", TsLevel.StackInfo )
return
def create_transvecListSympl( self, m ):
"""
internal method to create classical group for symplectic Assion groups (type 'S' )
this is a local function in CubicBraidGroup_class.__create_classical_realization__
INPUT
- m the dimension of the classical groups vectorspace of operation
The routine calculates the central vector and the transvections as vector as given by Assion and then uses
SetUpClassicalGroup to complete the construction
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
self.__print_timestamp__( "Begin", TsLevel.StackInfo )
BaseGroup = Sp( m, _sage_const_3 )
ProjGroup = PSp( m, _sage_const_3 )
bform = BaseGroup.invariant_form()
n = self._nstrands_
bas =bform.column_space().basis()
if m % _sage_const_2 == _sage_const_0 :
mhalf = m/_sage_const_2
else:
mhalf = (m-_sage_const_1 )/_sage_const_2
xbas =[]
ybas =[]
for i in range(mhalf):
xbas.append( bas[mhalf -i -_sage_const_1 ] )
ybas.append( bas[mhalf +i ] )
transvecList =[xbas[_sage_const_0 ]]
for i in range(mhalf-_sage_const_1 ):
transvecList.append(ybas[i])
transvecList.append(xbas[i] + xbas[i+_sage_const_1 ] )
transvecList.append(ybas[mhalf-_sage_const_1 ] )
def transvec2mat( v, bas=bas, bform=bform, fact=_sage_const_1 ):
t = []
for x in bas:
t.append( x + fact*(x * bform * v) * v )
Mt = matrix( bform.base_ring(), t )
return Mt
central_vector = xbas[mhalf-_sage_const_1 ]
SetUpClassicalGroup( self, m, n, BaseGroup, ProjGroup, central_vector, transvec2mat, transvecList )
self.__print_timestamp__( "End", TsLevel.StackInfo )
return
def create_transvecListUnitar( self, m ):
"""
internal method to create classical group for unitary Assion groups (type 'U' )
this is a local function in CubicBraidGroup_class.__create_classical_realization__
INPUT
- m the dimension of the classical groups vectorspace of operation
The routine calculates the central vector and the transvections as vector as given by Assion and then uses
SetUpClassicalGroup to complete the construction
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
self.__print_timestamp__( "Begin", TsLevel.StackInfo )
BaseGroup = GU( m, _sage_const_2 )
ProjGroup = PGU( m, _sage_const_2 )
oneMat = BaseGroup.one().matrix()
n = self._nstrands_
bform = matrix( m,m, lambda i,j: oneMat[i, m-_sage_const_1 -j] )
bas = bform.column_space().basis()
BasR = bform.base_ring()
vA = BasR.gen()
if m % _sage_const_3 == _sage_const_1 :
mthird = (m-_sage_const_1 )/_sage_const_3
elif m % _sage_const_3 == _sage_const_2 :
mthird = (m-_sage_const_2 )/_sage_const_3
else:
mthird = m/_sage_const_3
xbas =[]
for i in range(m):
if _sage_const_2 *i == m-_sage_const_1 :
xbas.append(bas[i])
else:
xbas.append( vA*bas[i] + vA.frobenius()*bas[m-_sage_const_1 -i])
transvecList =[xbas[_sage_const_0 ]]
if m > _sage_const_1 :
transvecList.append(xbas[_sage_const_0 ]+xbas[_sage_const_1 ]+xbas[_sage_const_2 ] )
for j in range(mthird):
pos = _sage_const_3 *(j+_sage_const_1 ) -_sage_const_1
transvecList.append(xbas[pos-_sage_const_1 ])
if pos +_sage_const_1 < m:
transvecList.append(xbas[pos-_sage_const_1 ]+xbas[pos]+xbas[pos+_sage_const_1 ] )
if pos +_sage_const_3 < m:
transvecList.append(xbas[pos+_sage_const_1 ]+xbas[pos+_sage_const_2 ]+xbas[pos+_sage_const_3 ] )
def transvec2mat( v, bas=bas, bform=bform, fact=vA ):
def conjVec( vec ):
erg = list(vec)
for i in range(len(vec)):
erg[i] = erg[i].frobenius()
return vector(erg)
t = []
for x in bas:
t.append( x + fact *(x * bform * conjVec(v)) * v )
Mt = matrix( bform.base_ring(), t )
return Mt
central_vector = xbas[m-_sage_const_2 ]+xbas[m-_sage_const_1 ]
SetUpClassicalGroup( self, m, n, BaseGroup, ProjGroup, central_vector, transvec2mat, transvecList )
self.__print_timestamp__( "End", TsLevel.StackInfo )
return
self.__print_timestamp__( "Begin", TsLevel.StackInfo )
n = self._nstrands_
anz_gen = n-_sage_const_1
if n == _sage_const_1 :
ClassicalGroup = AbelianGroup([_sage_const_1 ])
self._classical_group_ = ClassicalGroup
self._classical_group_gens_ = ClassicalGroup.gens()
self._classical_base_group_ = ClassicalGroup
self._classical_base_group_gens_ = ClassicalGroup.gens()
elif n == _sage_const_2 and self._AdditionalRelation_ =='C':
ClassicalGroup = AbelianGroup([_sage_const_3 ])
self._classical_group_ = ClassicalGroup
self._classical_group_gens_ = ClassicalGroup.gens()
self._classical_base_group_ = ClassicalGroup
self._classical_base_group_gens_ = ClassicalGroup.gens()
else:
dim_sympl_group = n-_sage_const_1
dim_unitary_group = n-_sage_const_1
if n % _sage_const_2 == _sage_const_0 :
dim_sympl_group = n
if n % _sage_const_3 == _sage_const_0 :
dim_unitary_group = n
if self._AdditionalRelation_ =='S':
create_transvecListSympl( self, dim_sympl_group )
elif self._AdditionalRelation_ =='U':
create_transvecListUnitar( self, dim_unitary_group )
else:
UCF = UniversalCyclotomicField()
z12inverse = UCF.gen(_sage_const_12 ,_sage_const_11 )
ClassicalGroup = self.as_matrix_group( rootBur=z12inverse, Domain=UCF, version='unitary', check=False )
self._classical_group_ = ClassicalGroup
self._classical_group_gens_ = ClassicalGroup.gens()
self._classical_base_group_ = ClassicalGroup
self._classical_base_group_gens_ = ClassicalGroup.gens()
self._classical_embedding_ = ClassicalGroup
self.__print_timestamp__( "End", TsLevel.StackInfo )
return
def change_debug_options(self, verbose = None, for_subroutine = False, ShowDateTime = False ):
"""
Changes the options for timestamp debug log messages
If you don't see this well formatted type
sage: print CubicBraidGroup_class.change_debug_options.__doc__
The verbose -mode which has been set in the constructor can be modified here. It is possible set the mode
separately for main routines (this module) and routines from external modules.
Furthermore the printing of the datetime-string in the messages can be turned on
INPUT (all optional keywords):
- "verbose" (default = unchanged) the new verbose mode to be set. For more informati9on on the possible
values type sage: print CubicBraidGroup_class.__doc__
- "for_subroutine" boolean (default = False): decides wether to apply the setting to log messages of this module
(False) or to subroutines from external modules (True) such as lib.utils_gap_interface
- "ShowDateTime" boolean (default = False): decides wether to print a datetime-string in the msages
EXAMPLES:
sage: from cubic_braid import *
sage: C3 = CubicBraidGroup(3)
sage: C3.change_debug_options(verbose=True)
sage: C5c5= C3.as_matrix_group( characteristic=5)
L: StackInfo : Elapse: 4711, Total: 4 Begin In: as_matrix_group Line: 1789
L: Body : Elapse: 685, Total: 5 genList prepared In: as_matrix_group Line: 1805
L: Body : Elapse: 147, Total: 5 MatGroup defined In: as_matrix_group Line: 1830
L: StackInfo : Elapse: 38, Total: 5 Begin In: __check_homomorphism__ Line: 1058
L: Body : Elapse: 2, Total: 5 check_needed In: __check_homomorphism__ Line: 1069
L: Debug : Elapse: 2, Total: 5 relation c0*c1*c0*c1^-1*c0^-1*c1^-1 In: __check_homomorphism__ Line:
1072
L: Debug : Elapse: 6, Total: 5 relation tested In: __check_homomorphism__ Line: 1074
L: Debug : Elapse: 6, Total: 5 relation c0^3 In: __check_homomorphism__ Line: 1072
L: Debug : Elapse: 5, Total: 5 relation tested In: __check_homomorphism__ Line: 1074
L: Debug : Elapse: 6, Total: 5 relation c1^3 In: __check_homomorphism__ Line: 1072
L: Debug : Elapse: 6, Total: 5 relation tested In: __check_homomorphism__ Line: 1074
L: Body : Elapse: 8, Total: 5 check_ok In: __check_homomorphism__ Line: 1079
L: Body : Elapse: 3, Total: 5 check_registerd In: __check_homomorphism__ Line: 1083
L: StackInfo : Elapse: 5, Total: 5 End In: __check_homomorphism__ Line: 1086
L: Body : Elapse: 2, Total: 5 Hom from self defined In: as_matrix_group Line: 1840
L: Body : Elapse: 904, Total: 6 Section to self defined In: as_matrix_group Line: 1853
L: Body : Elapse: 4, Total: 6 section to classical group defined In: as_matrix_group Line: 1873
L: StackInfo : Elapse: 367, Total: 6 Ende In: as_matrix_group Line: 1893
sage:
sage: C3.change_debug_options(ShowDateTime = True)
sage: C5c5= C3.as_matrix_group( characteristic=5)
L: StackInfo : 2017-01-26 18:01:50.782780 Elapse: 2986, Total: 2 Begin In: as_matrix_group Line: 1789
L: Body : 2017-01-26 18:01:50.859565 Elapse: 77, Total: 3 genList prepared In: as_matrix_group Line:
1805
L: Body : 2017-01-26 18:01:50.889521 Elapse: 29, Total: 3 MatGroup defined In: as_matrix_group Line:
1830
L: StackInfo : 2017-01-26 18:01:50.908706 Elapse: 19, Total: 3 Begin In: __check_homomorphism__ Line: 1058
..........................................
L: Body : 2017-01-26 18:01:51.370860 Elapse: 3, Total: 3 section to classical group defined In:
as_matrix_group Line: 1873
L: StackInfo : 2017-01-26 18:01:51.373498 Elapse: 2, Total: 3 Ende In: as_matrix_group Line: 1893
sage:
AUTHOR
- Sebastian Oehms, Jan. 2017
"""
if verbose == None:
verbose = self._verbose_
if for_subroutine == False:
self._verbose_ = verbose
self._TimeStamp_ = setupTimeStamp( verbose = verbose, Offset = _sage_const_2 , ShowDateTime = ShowDateTime )
else:
self._TimeStampSub_ = setupTimeStamp( verbose = verbose, Offset = _sage_const_1 , ShowDateTime = ShowDateTime )
def pre_image_braid_group(self):
"""
Return an Objekt of the class BraidGroup with identical generators, such that there exists an epimorhism to self
If you don't see this well formatted type
sage: print CubicBraidGroup_class.pre_image_braid_group.__doc__
OUTPUT:
Instance of the class BraidGroup having conversion maps to and from self (which is just a section in the
latter case)
EXAMPLES:
sage: from cubic_braid import *
sage: U5=AssionGroupU(5); U5
Assion group on 5 strands of type U
sage: B5=U5.pre_image_braid_group(); B5
Braid group on 5 strands
sage: b=B5([4,3,2,-4,1])
sage: u=U5([4,3,2,-4,1])
sage: u == b
False
sage: b.burau_matrix()
[ 1 - t t 0 0 0]
[ 1 - t 0 t 0 0]
[ 1 - t 0 0 0 t]
[ 1 - t 0 0 1 -1 + t]
[ 1 0 0 0 0]
sage: u.burau_matrix()
[ -zeta3 zeta3 + 1 0 0 0]
[ -zeta3 0 zeta3 + 1 0 0]
[ -zeta3 0 0 0 zeta3 + 1]
[ -zeta3 0 0 1 zeta3]
[ 1 0 0 0 0]
sage: bU = U5(b)
sage: uB = B5(u)
sage:
sage: bU == u
True
sage: uB == b
True
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
return self._pre_image_braid_group_
def as_matrix_group(self, rootBur=None, Domain=None, characteristic=None, reduced=False,
version='default', section=True, check=True):
"""
creates an epimorphic image of self as a matrix group by use of the burau representation
If you don't see this well formatted type
sage: print CubicBraidGroup_class.as_matrix_group.__doc__
INPUT: (all parameters are optional by keyword )
- "rootBur": six root of unity in some field (default six root of unity over QQ)
- "Domain": base_ring for the burau matrix (default is Cyclotomic Field of order 3 and degree 2, resp. the
domain of rootBur if given)
- "characteristic": integer giving the characteristic of the domain (default is 0 or the characteristic of
the doamain if given). If none of the keywords "rootBur", "Domain" and "characteristic" is given
the default characteristic is 3 (resp. 2) if self is of Assion type 'S' (resp. 'U')
- "reduced": boolean (default: False); whether to return the reduced or unreduced Burau representation (see
Braid class )
- "version": values:
'unitary': gives the unitary form according to Squier (see Braid._unitary_burau_matrix_() )
'default': the method behaves like the original one of the Braid -class
- any value else gives the reduced form given on wikipedia
- "section"; boolean (default: True) Setting this to False creates a map back to self only in the case of
isomorphism. By default the map is created as a section in any case.
compare the INPUT of
sage: print CubicBraidElement.burau_matrix.__doc_
OUTPUT:
an instance of the class FinitelyGeneratedMatrixGroup_gap according to the Input parameters together with a map
from an to self and the classical group the map backwards (in both cases) is given if the the matrix group is
isomorphic to self or if the keyword section = True (default)
RAISE:
- ValueError: "matrix group fails to be an epimorphic image of %s" if the burau map does not vanish on the
relation of self see example with U5 below
EXAMPLES:
sage: from cubic_braid import *
sage: C5=CubicBraidGroup(5)
sage:
sage: M5ch5 = C5.as_matrix_group(characteristic=5); M5ch5
Matrix group over Finite Field in rI of size 5^2 with 4 generators (
[2*rI + 2 3*rI + 4 0 0 0]
[ 1 0 0 0 0]
[ 0 0 1 0 0]
[ 0 0 0 1 0]
[ 0 0 0 0 1],
[ 1 0 0 0 0]
[ 0 2*rI + 2 3*rI + 4 0 0]
[ 0 1 0 0 0]
[ 0 0 0 1 0]
[ 0 0 0 0 1],
[ 1 0 0 0 0]
[ 0 1 0 0 0]
[ 0 0 2*rI + 2 3*rI + 4 0]
[ 0 0 1 0 0]
[ 0 0 0 0 1],
[ 1 0 0 0 0]
[ 0 1 0 0 0]
[ 0 0 1 0 0]
[ 0 0 0 2*rI + 2 3*rI + 4]
[ 0 0 0 1 0]
)
sage:
sage: c=C5([3,4,-2,-3,1]); c
c2*c1^-1*c0*c3*c2^-1
sage:
sage: cM=M5ch5(c); cM
[2*rI + 2 3*rI + 4 0 0 0]
[ 0 0 0 1 0]
[2*rI + 1 0 2*rI + 2 3*rI 3*rI + 3]
[2*rI + 2 0 0 3*rI + 4 0]
[ 0 0 2*rI + 2 3*rI + 4 0]
sage:
sage: mC=C5(cM)
sage: mC == c
True
sage: C5Cl=C5.as_classical_group()
sage:
sage: mCl=C5Cl(cM); mCL
[ E(3) E(12)^11 0 0]
[ -E(12)^11 1 -E(4) -E(3)^2]
[ E(3) E(12)^11 E(3)^2 -2*E(12)^7 - E(12)^11]
[ 0 1 E(12)^7 -E(3)^2]
sage:
sage: cCl=C5Cl(c)
sage: mCl == cCl
True
sage:
sage: cClM=M5ch5(cCl)
sage: cClM == cM
True
sage: U5=AssionGroupU(5); U5
Assion group on 5 strands of type U
sage: M5ch3 = U5.as_matrix_group(characteristic=3)
Warning: homomorphism not well defined for relation ((u0*u1)^3*(u2*u3)^3)^3 giving: [1 1 2 1 2]
[2 0 2 1 2]
[2 1 1 1 2]
[2 1 2 0 2]
[2 1 2 1 1]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
......................
ValueError: matrix group fails to be an epimorphic image of Assion group on 5 strands of type U
sage:
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
self.__print_timestamp__("Begin", TsLevel.StackInfo)
if rootBur == None and Domain == None and characteristic == None:
if self._AdditionalRelation_ == 'S':
characteristic = _sage_const_3
elif self._AdditionalRelation_ == 'U':
characteristic = _sage_const_2
else:
characteristic = _sage_const_0
self.__print_timestamp__("default characteristic set to %d" %(characteristic), TsLevel.Debug)
genList =[]
for braidGen in list(self.gens()):
burMat = braidGen._burau_matrix_(rootBur=rootBur, Domain=Domain, characteristic=characteristic, reduced=reduced,
version=version)
if rootBur == None:
rootBur = burMat[_sage_const_1 ]
if Domain == None:
Domain = rootBur.parent()
if characteristic == None:
characteristic = Domain.characteristic()
genList.append(burMat[_sage_const_0 ])
self.__print_timestamp__("genList prepared", TsLevel.Body)
avoid_gap_worspace_error = False
if self.order() == infinity:
avoid_gap_worspace_error = True
if version == 'unitary':
hermFormBraid = self.pre_image_braid_group().__unitary_form__()
d = hermFormBraid.dimensions()[_sage_const_0 ]
s = hermFormBraid.base_ring().gen()
hermForm = matrix(d,d, lambda i, j: Domain(hermFormBraid[i,j].subs({s:rootBur})))
if is_FiniteField(Domain):
if hermForm.determinant() == _sage_const_0 :
print "Warning: hermitian form %s is degenerated" %(hermForm)
BaseGroup = GU(d, Domain, var=Domain.gen(), hermitian_form=hermForm)
else:
BaseGroup = GU(d, Domain, hermitian_form=hermForm)
self.__print_timestamp__("Base Group %s defined" %(BaseGroup), TsLevel.Debug)
MatGroup = BaseGroup.subgroup(genList)
else:
MatGroup = MatrixGroup(genList)
self.__print_timestamp__("MatGroup defined", TsLevel.Body)
homToMat = gap_hom(self, MatGroup, verbose=self._TimeStampSub_)
if check == True:
if self.__check_homomorphism__(homToMat) == False:
raise ValueError( "matrix group fails to be an epimorphic image of %s"%(self._repr_()) )
self.__print_timestamp__("Hom from self defined", TsLevel.Body)
homFromMat = None
if avoid_gap_worspace_error == True:
print "Warning: no section back from matrix group over (gap overflow)", MatGroup.base_ring()
elif section == True:
try:
homFromMat = gap_hom( MatGroup, self, verbose = self._TimeStampSub_)
self.__print_timestamp__("Section to self defined", TsLevel.Body)
except:
print "Warning: no section back from matrix group over", MatGroup.base_ring()
else:
try:
homFromMat = gap_hom(MatGroup, self, check=True, verbose=self._TimeStampSub_)
self.__print_timestamp__("Homomorphism to self defined", TsLevel.Body)
except:
print "Warning: no homomorphism back from matrix group over", MatGroup.base_ring()
ClassicalGroup = self._classical_group_
if ClassicalGroup != None:
if homFromMat != None:
homToClass = ClassicalGroup.coerce_map_from(self)
if homToClass != None:
ClassicalGroup.register_coercion(homToClass * homFromMat)
self.__print_timestamp__("section to classical group defined", TsLevel.Body)
else:
print "Warning: no map from matrix group over"
print MatGroup.base_ring(), "to classical group", ClassicalGroup
ClassicalEmbedding = self._classical_embedding_
if ClassicalEmbedding != None and ClassicalEmbedding != ClassicalGroup:
if homFromMat != None:
homToEmb = ClassicalEmbedding.coerce_map_from(self)
if homToEmb != None:
ClassicalEmbedding.register_coercion(homToEmb * homFromMat)
self.__print_timestamp__("section to classical embedding defined", TsLevel.Body)
else:
print "Warning: no map from matrix group over"
print MatGroup.base_ring(), "to classical embedded roup", ClassicalEmbeding
self.__print_timestamp__("Ende", TsLevel.StackInfo)
return MatGroup
def as_permutation_group(self, native=False ):
"""
This method returns the permutation group corresponding to self together with conversion maps to and from
self and the classical realization of self
INPUT:
- "native" boolean as optional keyword, default = False. If you set this True the permutation group is
calculated with repsect to self as finitely presented group. By default the permutation group is
taken from the classical group realization.
CAUTION: setting native = True may cause a segmentation fault if you use the sage coercion functionality
afterwards (in other context, even though the coercions for the permutation group work fine).
The reason for this is not clear!
OUTPUT:
instance of a subgroup of the symmetric group (PermutationGroup_subgroup) together with conversion maps to
and from self and the classical groups.
RAISE:
- ValueError: "permutation group fails to be an epimorphic image of %s"
EXAMPLE:
sage: C3=CubicBraidGroup(3)
sage:
sage: PC3=C3.as_permutation_group(); PC3
Subgroup of (Symmetric group of order 8! as a permutation group) generated by [(2,3,5)(4,6,8), (1,2,4)(5,7,6)]
sage:
sage: PC3n=C3.as_permutation_group(native=True); PC3n
Subgroup of (Symmetric group of order 24! as a permutation group) generated by [(1,2,3)(4,10,11)(5,12,13)
(6,14,15)(7,16,17)(8,18,19)(9,20,21)(22,23,24),
(1,4,5)(2,6,7)(3,8,9)(10,14,18)(11,22,20)(12,15,23)(13,17,21)(16,19,24)]
sage: C3Cl = C3.as_classical_group()
sage: c=C3([2,1-2]); c
c1*c0^-1
sage: lc=C3Cl(c); lc
[ E(3)^2 -E(12)^7]
[ E(12)^7 -E(3)^2]
sage: pc=PC3(c); pc
(1,5,7,4)(2,8,6,3)
sage: pcn=PC3n(c); pcn
(1,11,24,7)(2,15,22,9)(3,19,23,5)(4,13,16,18)(6,17,20,10)(8,21,12,14)
sage:
sage: clc = C3(lc); clc == c
True
sage: cpc = C3(pc); cpc == c
True
sage: cpcn = C3(pcn); cpcn == c
True
sage: lpc = C3Cl(pc); lpc == lc
True
sage: lpcn = C3Cl(pcn); lpcn == lc
True
sage: plc = PC3(lc); plc == pc
True
sage: plcn = PC3n(lc); plcn == pcn
True
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
self.__print_timestamp__( "Begin", TsLevel.StackInfo )
ClassicalGroup = self.as_classical_group()
Domain = None
c2s = self.convert_map_from( ClassicalGroup )
s2c = ClassicalGroup.convert_map_from( self )
s2po = None; po2s = None; c2po = None; po2c = None;
s2p = None; p2s = None; c2p = None; p2c = None;
if native == True or self._nstrands_ < _sage_const_3 :
PermGroupOri = gap_as_permutation_group(self, verbose = self._TimeStampSub_ )
s2po = PermGroupOri.convert_map_from( self )
po2s = self.convert_map_from( PermGroupOri )
SortGenList = [ s2po(gen) for gen in self.gens() ]
else:
if isinstance( ClassicalGroup, PermutationGroup_generic):
PermGroupOri = ClassicalGroup
c2po = Hom( ClassicalGroup, PermGroupOri).identity()
po2c = Hom( PermGroupOri, ClassicalGroup).identity()
else:
PermGroupOri = gap_as_permutation_group( ClassicalGroup, verbose = self._TimeStampSub_ )
c2po = PermGroupOri.convert_map_from( ClassicalGroup )
po2c = ClassicalGroup.convert_map_from( PermGroupOri )
SortGenList = [ c2po(ClassicalGroup(gen)) for gen in self.gens() ]
Domain = SymmetricGroup( len( PermGroupOri.domain() ) )
PermGroup = Domain.subgroup( SortGenList )
po2p = PermGroup.convert_map_from( PermGroupOri )
p2po = PermGroupOri.convert_map_from( PermGroup )
self.__print_timestamp__( "subgroup of %s"%(Domain), TsLevel.Body )
s2p_hom = None
c2p_hom = None
if c2p == None and c2po != None and po2p != None:
c2p = po2p * c2po
if c2p != None:
c2p_hom = register_hom( ClassicalGroup, PermGroup, c2p, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "c2p_hom defined pos 1", TsLevel.Debug )
if s2p == None and s2po != None and po2p != None:
s2p = po2p * s2po
if s2p != None:
s2p_hom = register_hom( self, PermGroup, s2p, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "s2p_hom defined pos 1", TsLevel.Debug )
if c2p == None and s2p_hom != None:
c2p = s2p_hom * c2s
if native == True:
c2p_hom = c2p
else:
c2p_hom = register_hom( ClassicalGroup, PermGroup, c2p, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "c2p_hom defined pos 2", TsLevel.Debug )
if s2p == None and c2p_hom != None:
s2p = c2p_hom * s2c
s2p_hom = register_hom( self, PermGroup, s2p, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "s2p_hom defined pos 2", TsLevel.Debug )
if s2p_hom == None:
print "Warning: no map from self to permutation group defined"
if c2p_hom == None:
print "Warning: no map from classical group to permutation group defined"
self.__print_timestamp__( "homToPerm defined", TsLevel.Debug )
p2s_hom = None
p2c_hom = None
if p2c == None and po2c != None and p2po != None:
p2c = po2c * p2po
if p2c != None:
p2c_hom = register_hom( PermGroup, ClassicalGroup, p2c, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "p2c_hom defined pos 1", TsLevel.Debug )
if p2s == None and po2s != None and p2po != None:
p2s = po2s * p2po
if p2s != None:
p2s_hom = register_hom( PermGroup, self, p2s, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "p2s_hom defined pos 1", TsLevel.Debug )
if p2c == None and p2s_hom != None:
p2c = s2c * p2s_hom
p2c_hom = register_hom( PermGroup, ClassicalGroup, p2c, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "p2c_hom defined pos 2", TsLevel.Debug )
if p2s == None and p2c_hom != None:
p2s = c2s * p2c_hom
p2s_hom = register_hom( PermGroup, self, p2s, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "p2s_hom defined pos 2", TsLevel.Debug )
if p2s_hom == None:
print "Warning: no map from permutation group to self defined"
if c2p_hom == None:
print "Warning: no map from permutation group to classical group defined"
self.__print_timestamp__( "homFromPerm defined", TsLevel.Debug )
if s2p_hom != None:
self.__print_timestamp__( "checking homToPerm", TsLevel.Body )
if self.__check_homomorphism__( s2p_hom ) == False:
raise ValueError( "permutation group fails to be an epimorphic image of %s"%(self._repr_()) )
self.__print_timestamp__( "check homToPerm finished", TsLevel.Body )
self.__print_timestamp__( "End", TsLevel.StackInfo )
return PermGroup
def as_classical_group(self, embedded=False):
"""
creates an isomorphic image of self as a classical group according to the construction given by Coxeter resp. Assion
If you don't see this well formatted type
sage: print CubicBraidGroup_class.as_classical_group.__doc__
INPUT: (optional as keyword)
- "embedded": boolean (default = False). This boolean does effect the cases of AssionGroups where they are
realized as projective groups, only. More precisely: if self is of type 'S' (for example) and the
number of strands n is even, than its classical group is a subgroup of PSp(n,3) (being
centralized by the element self.centralizing_element( projective = True)). By default this group
will be given. Setting embedded = True the classical realization is given as subgroup of its
classical enlargement with one more stand (in this case as subgroup of Sp(n-1,3))
OUTPUT:
depending on the type of self and the number of strands an instance of Sp(n-1,3), GU(n-1,2), Subgroup of
PSp(n,3), PGU(n,2) or a subgroup of GU(n-1, UCF) (type 'C' ) with respect to a certain hermitian form
attached to the burau representation (used by Coxeter and Squier). Here UCF stands for the universal
cyclotomic field.
RAISE:
- ValueError: "no classical group defined" if the construction was not possible
- ValueError: "no classical embedding defined" if the construction was not possible
EXAMPLES:
sage: from cubic_braid import *
sage: U3 = AssionGroupU(3)
sage: U3Cl = U3.as_classical_group(); U3Cl
Subgroup of (The projective general unitary group of degree 3 over Finite Field of size 2) generated by
[(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20),
(1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)]
sage: U3Clemb = U3.as_classical_group(embedded=True); U3Clemb
Matrix group over Finite Field in a of size 2^2 with 2 generators (
[0 0 a] [a + 1 a a]
[0 1 0] [ a a + 1 a]
[a 0 a], [ a a a + 1]
)
sage: u = U3([-2,1,-2,1]); u
(u1^-1*u0)^2
sage: uCl = U3Cl(u); uCl
(1,16)(2,9)(3,10)(4,19)(6,12)(7,20)(13,21)(14,15)
sage:
sage: uCle = U3Clemb(u); uCle
[a + 1 a + 1 1]
[a + 1 0 a]
[ 1 a a]
sage:
sage: U3(uCl) == u
True
sage: U3(uCle) == u
True
sage: U4 = AssionGroupU(4)
sage: U4Cl = U4.as_classical_group(); U4Cl
General Unitary Group of degree 3 over Finite Field in a of size 2^2 with respect to hermitian form [0 0 1]
[0 1 0]
[1 0 0]
sage: uCle in U4Cl
True
sage: C4 = CubicBraidGroup(4)
sage: C4Cl = C4.as_classical_group(); C4Cl
Subgroup of General Unitary Group of degree 3 over Universal Cyclotomic Field with respect to hermitian form
[-E(12)^7 + E(12)^11 -1 0]
[ -1 -E(12)^7 + E(12)^11 -1]
[ 0 -1 -E(12)^7 + E(12)^11]
generated by (
[ E(3) E(12)^11 0]
[ 0 1 0]
[ 0 0 1],
[ 1 0 0]
[E(12)^11 E(3) E(12)^11]
[ 0 0 1],
[ 1 0 0]
[ 0 1 0]
[ 0 E(12)^11 E(3)])
sage: type(C4Cl)
<class 'lib.local_matrix_group.MatrixGroup_subgroup_with_category'>
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
if embedded == False or self._classical_embedding_ == None or self._classical_group_ == self._classical_embedding_:
if self._classical_group_ == None:
raise ValueError( "no classical group defined")
else:
return self._classical_group_
else:
if self._classical_embedding_ == None:
raise ValueError( "no classical embedding defined")
else:
return self._classical_embedding_
def as_reflection_group(self, check=False ):
"""
creates an isomorphic image of self as irreducible complex reflection group. This is possible only for the finite
cubic braid groups of type 'C'
If you don't see this well formatted type
sage: print CubicBraidGroup_class.as_classical_group.__doc__
This method uses the sage implementation of reflection group via the gap3 CHEVIE package. To use this methode
you must have sage from version 7.2 up and gap3 with CHEVIE installed
INPUT (optional):
-check : boolean (default false): can be set to force a check of well definiteness of the morphism from self
OUTPUT:
an object of the class IrreducibleComplexReflectionGroup (from sage.combinat.root_system.reflection_group_complex)
together with isomorphism to and from self and self.as_classical_group()
RAISE:
- ValueError: "no refection group defined" if the construction was not possible
- ImportError: "cannot import name IrreducibleComplexReflectionGroup" means:Sage Version 7.2 up is needed for
this functionality"
EXAMPLES:
sage: from lib.cubic_braid import *
sage: C3.<c1,c2> = CubicBraidGroup(3)
sage: R3 = C3.as_reflection_group(); R3
Irreducible complex reflection group of rank 2 and type ST4
sage: type(R3)
<class 'lib.local_permgroup.IrreducibleComplexReflectionGroup_with_category'>
sage:
sage: R3.cartan_matrix()
[-2*E(3) - E(3)^2 E(3)^2]
[ -E(3)^2 -2*E(3) - E(3)^2]
sage: R3.simple_roots()
Finite family {1: (0, -2*E(3) - E(3)^2), 2: (2*E(3)^2, E(3)^2)}
sage: R3.simple_coroots()
Finite family {1: (0, 1), 2: (1/3*E(3) - 1/3*E(3)^2, 1/3*E(3) - 1/3*E(3)^2)}
sage:
Conversion maps:
sage:
sage: C3Cl = C3.as_classical_group()
sage: ele = c1*c2**2; ele
c1*c2^2
sage: rele = R3(ele); rele
(1,14,12,18)(2,15,24,16)(3,22,19,4)(5,6,17,20)(7,10,23,21)(8,11,9,13)
sage: rele.matrix()
[-1/3*E(3) + 1/3*E(3)^2 1/3*E(3) + 2/3*E(3)^2]
[-4/3*E(3) - 2/3*E(3)^2 1/3*E(3) - 1/3*E(3)^2]
sage: clele = C3Cl(ele); clele
[ -E(3)^2 E(12)^7]
[-E(12)^7 E(3)^2]
sage: clrele = C3Cl(rele); clrele
[ -E(3)^2 E(12)^7]
[-E(12)^7 E(3)^2]
sage: C3(rele)
c1*c2^-1
The refelection groups can also be viewed as subgroups of unitary groups over the universal cyclotomic field. This
functionality is availlable just in the context of cubic braid groups in addition to the basic functionality of the
IrreducibleComplexReflectionGroup_class. Note that the unitary group corresponding to the reflection group is
isomorphic but diferent from the classical group due to different hermitian forms for the unitary groups they live in.
sage: C4=CubicBraidGroup(4)
sage: R4=C4.as_reflection_group()
sage: R4Cl=R4.as_unitary_group(); R4Cl
Subgroup of General Unitary Group of degree 3 over Universal Cyclotomic Field generated by:
([ 1 0 0]
[ 0 1 0]
[ 0 0 E(3)],
[-1/3*E(3) - 2/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2]
[ 2/3*E(3) + 1/3*E(3)^2 -1/3*E(3) - 2/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2]
[ 2/3*E(3) + 1/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2 -1/3*E(3) - 2/3*E(3)^2],
[ 1 0 0]
[ 0 E(3) 0]
[ 0 0 1])
sage: C4Cl=C4.as_classical_group(); C4Cl
Subgroup of Unitary Group of degree 3 over Universal Cyclotomic Field with respect to hermitian form
[-E(12)^7 + E(12)^11 -1 0]
[ -1 -E(12)^7 + E(12)^11 -1]
[ 0 -1 -E(12)^7 + E(12)^11] generated by:
([ E(3) E(12)^11 0]
[ 0 1 0]
[ 0 0 1],
[ 1 0 0]
[E(12)^11 E(3) E(12)^11]
[ 0 0 1],
[ 1 0 0]
[ 0 1 0]
[ 0 E(12)^11 E(3)])
sage: C4ClAmbient = C4Cl.ambient(); C4ClAmbient
Unitary Group of degree 3 over Universal Cyclotomic Field with respect to hermitian form
[-E(12)^7 + E(12)^11 -1 0]
[ -1 -E(12)^7 + E(12)^11 -1]
[ 0 -1 -E(12)^7 + E(12)^11]
sage: R4ClAmbient = R4Cl.ambient(); R4ClAmbient
General Unitary Group of degree 3 over Universal Cyclotomic Field
sage: C4ClAmbient == R4ClAmbient
False
AUTHOR:
- Sebastian Oehms, Mar. 2017
"""
if self._AdditionalRelation_ != 'C' or self._nstrands_ > _sage_const_5 or self._nstrands_ < _sage_const_2 :
raise ValueError( "no reflection group defined")
self.__print_timestamp__( "Begin", TsLevel.StackInfo )
ReflectGroup = None
from lib.local_permgroup import IrreducibleComplexReflectionGroup
def ReflectionGroup( *args,**kwds):
"""
This local Function overloads the corresponding function of sage.combinat.root_system.reflection_group_real
in order to make "call by name conversion" availlable via the local_permgroup module
"""
RefGroup = IrreducibleComplexReflectionGroup(tuple(args),
index_set=kwds.get('index_set', None),
hyperplane_index_set=kwds.get('hyperplane_index_set', None),
reflection_index_set=kwds.get('reflection_index_set', None))
return RefGroup
if self._nstrands_ == _sage_const_2 :
ReflectGroup = ReflectionGroup( [_sage_const_2 ,_sage_const_1 ,_sage_const_1 ] )
elif self._nstrands_ == _sage_const_3 :
ReflectGroup = ReflectionGroup( _sage_const_4 )
elif self._nstrands_ == _sage_const_4 :
ReflectGroup = ReflectionGroup( _sage_const_25 )
elif self._nstrands_ == _sage_const_5 :
ReflectGroup = ReflectionGroup( _sage_const_32 )
self.__print_timestamp__( "ReflectGroup %s defined" %(ReflectGroup), TsLevel.Body )
homToRefl = gap_hom( self, ReflectGroup, verbose = self._TimeStampSub_ )
if check == True:
if self.__check_homomorphism__( homToRefl ) == False:
raise ValueError( "refection group fails to be an epimorphic image of %s"%(self._repr_()) )
self.__print_timestamp__( "Hom from self defined", TsLevel.Body )
try:
homFromRefl = gap_hom( ReflectGroup, self, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "Hom to self defined", TsLevel.Body )
except:
print "Warning: no section back from reflection group"
ClassicalGroup = self.as_classical_group()
c2s = self.convert_map_from( ClassicalGroup )
s2c = ClassicalGroup.convert_map_from( self )
r2c = s2c * homFromRefl
r2c_hom = register_hom( ReflectGroup, ClassicalGroup, r2c, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "r2c_hom defined", TsLevel.Debug )
c2r = homToRefl * c2s
c2r_hom = register_hom( ClassicalGroup, ReflectGroup, c2r, verbose = self._TimeStampSub_ )
self.__print_timestamp__( "c2r_hom defined", TsLevel.Debug )
self.__print_timestamp__( "End", TsLevel.StackInfo )
return ReflectGroup
def centralizing_element(self, projective=False ):
"""
returns the centralizing element defined in the work of Assion (Hilfssatz 1.1.3 and 1.2.3)
If you don't see this well formatted type
sage: print CubicBraidGroup_class.centralizing_element.__doc__
INPUT: (optional as keyword)
- "projective": boolean (default = False). This boolean does effect the cases of AssionGroups where they are
realized as projective groups, only. More precisely: if self is of type 'S' (for example) and
the number of strands n is even, than its classical group is a subgroup of
PSp(n,3) (being centralized by this element). By default this group will be given.
Setting embedded = True the classical realization is given as subgroup of its classical
enlargement with one more stand (in this case as subgroup of Sp(n,3))
OUTPUT:
depending on the optional keyword a permutation as an element of PSp(n,3) (type S) or PGU(n,2) (type U) if
projective = True and n == 0 mod 2 (type S) reps. n == 0 mod 3 (type U) is returned. Elsewise the
centralizing element is a matrix belonging to Sp(n,3) reps. GU(n,2).
RAISE:
- ValueError: "no centralizing element defined"
EXAMPLES:
sage: U3=AssionGroupU(3); U3
Assion group on 3 strands of type U
sage:
sage: U3Cl = U3.as_classical_group(); U3Cl
Subgroup of (The projective general unitary group of degree 3 over Finite Field of size 2) generated by
[(1,7,6) (3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)]
sage:
sage: U3Clem = U3.as_classical_group(embedded=True); U3Clem
Matrix group over Finite Field in a of size 2^2 with 2 generators (
[0 0 a] [a + 1 a a]
[0 1 0] [ a a + 1 a]
[a 0 a], [ a a a + 1]
)
sage:
sage: u3cent = U3.centralizing_element(); u3cent
[a + 1 a + 1 1]
[a + 1 0 a]
[ 1 a a]
sage: u3cent in U3Cl
False
sage: u3centP in U3Cl
True
sage: u3cent in U3Clem
True
sage: u3centP in U3Clem
False
considering u3cent as element in AssionGroupU(4)
sage: U4=AssionGroupU(4); U4
Assion group on 4 strands of type U
sage:
sage: U4Cl = U4.as_classical_group(); U4Cl
General Unitary Group of degree 3 over Finite Field in a of size 2^2 with respect to hermitian form [0 0 1]
[0 1 0]
[1 0 0]
sage: u3cent in U4Cl
True
sage: U4(u3cent)
(u0*u1^-1)^2
sage:
sage: # calculating the centralizer of u3cent in U4Cl via GAP functions in order to
sage: # check if U3Clem is a subgroup of the centralizer of u3cent in U4Cl
sage:
sage: CentU4u3cent = gap_centralizer( U4Cl, u3cent ); CentU4u3cent
Matrix group over Finite Field in a of size 2^2 with 4 generators (
[a + 1 a + 1 1] [a + 1 0 0] [ 1 1 a + 1] [1 0 1]
[a + 1 0 a] [ 0 a + 1 0] [ 0 a a] [0 a 0]
[ 1 a a], [ 0 0 a + 1], [ 0 0 1], [1 0 0]
)
sage:
sage: CentU4u3cent.gens()[0] in U3Clem
True
sage: CentU4u3cent.gens()[1] in U3Clem
False
sage: CentU4u3cent.gens()[2] in U3Clem
True
sage: CentU4u3cent.gens()[3] in U3Clem
False
sage:
sage: CentU4u3cent.order()
72
sage: U3Clem.order()
24
check that U3Clem is a subgroup of index 3 in CentU4u3cent
sage: U3Clem.gens()[0] in CentU4u3cent
True
sage: U3Clem.gens()[1] in CentU4u3cent
True
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
if self._centralizing_matrix_ == None:
raise ValueError( "no centralizing element defined")
else:
if projective == True:
return self._centralizing_element_
else:
return self._centralizing_matrix_
def order(self, by_formula = True ):
"""
to avoid long waittime on calculations the order will be obtained by formular resp. direct value
If you don't see this well formatted type
sage: print CubicBraidGroup_class.order.__doc__
INPUT:
- "by_formula": (optional keyword) boolean (default = True). In the default case the order is calculated from
formulas for simple group of Lie typ. If set to false the order is calculated by native function with
respect to the classical group (in the cases where this is finite).
OUTPUT:
size of the group as Integer ore infinity
EXAMPLES:
sage: S6=AssionGroupS(6)
sage: S6.order()
12597120
sage: S6.order(by_formula=False)
12597120
sage:
sage: C6=CubicBraidGroup(6)
sage: C6.order()
+Infinity
AUTHOR
- Sebastian Oehms, Sept. 2016
REFERENCES:
- Carter, R.W.: "Simple groups of Lie type", John Wiley & Sons (London 1989)
"""
n = self._nstrands_
if by_formula == False:
if self._AdditionalRelation_ == 'C' and n > _sage_const_5 :
order = infinity
else:
order = self.as_classical_group().order()
return order
m = n -_sage_const_1
order = _sage_const_0
if n == _sage_const_1 :
order = _sage_const_1
elif n == _sage_const_2 :
order = _sage_const_3
elif n == _sage_const_3 :
order = _sage_const_24
elif n == _sage_const_4 :
order = _sage_const_648
if self._AdditionalRelation_ == 'S':
q = _sage_const_3
if n % _sage_const_2 != _sage_const_0 :
l = m/_sage_const_2
order = _sage_const_1
for i in range(l):
order = order * (q**(_sage_const_2 *(i+_sage_const_1 ))-_sage_const_1 )
order = order * q**l**_sage_const_2
elif self._AdditionalRelation_ == 'U':
q = _sage_const_2
if n % _sage_const_3 != _sage_const_0 :
order = _sage_const_1
for i in range(m-_sage_const_1 ):
order = order * (q**(i+_sage_const_2 ) - (-_sage_const_1 )**(i+_sage_const_2 ))
order = order * (q+_sage_const_1 )*q**(m*(m-_sage_const_1 )/_sage_const_2 )
elif self._AdditionalRelation_ == 'C':
if order > _sage_const_0 :
pass
elif n == _sage_const_5 :
order = _sage_const_155520
else:
order = infinity
if order == _sage_const_0 :
order = self.as_classical_group().order()
return order
def cubic_braid_subgroup( self, nstrands = None ):
"""
creates a CubicBraidGroup as subgroup of self on the first "n_strands" strands
If you don't see this well formatted type
sage: print CubicBraidGroup_class.order.__doc__
INPUT:
- "nstrands": Integer > 0 and < self._nstrands_ giving the number of strand for the subgroup.
the default is one strand less than self
OUTPUT:
an instance of the this class realizing the subgroup
EXAMPLES:
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
if nstrands == None:
nstrands = self._nstrands_ -_sage_const_1
n = self._nstrands_
try:
nstrands = Integer( nstrands )
except:
raise TypeError( "nstrands must be an integer" )
if nstrands >= n or nstrands <= _sage_const_0 :
raise ValueError( "nstrands must be positive and less than %s" %(self._nstrands_) )
Gens = self.gens()
GensRed = tuple( [ Gens[i] for i in range(nstrands -_sage_const_1 ) ])
SGrp = CubicBraidGroup( names = GensRed, AdditionalRelation = self._AdditionalRelation_, verbose = self._verbose_ )
def embed( ele ):
return self( ele.Tietze() )
register_hom( SGrp, self, embed, verbose = self._TimeStampSub_ )
return SGrp
def character_table( self ):
"""
calculates the character_table of the cubic braid group via the gap interface
OUTPUT:
Character table as matrix (instance of sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense)
EXAMPLE:
sage: U3=AssionGroupU(3); U3
Assion group on 3 strands of type U
sage: U3ct=U3.character_table(); U3ct
[ 1 1 1 1 1 1 1]
[ 1 -zeta3 - 1 zeta3 1 zeta3 -zeta3 - 1 1]
[ 1 zeta3 -zeta3 - 1 1 -zeta3 - 1 zeta3 1]
[ 2 -1 -1 0 1 1 -2]
[ 2 -zeta3 zeta3 + 1 0 -zeta3 - 1 zeta3 -2]
[ 2 zeta3 + 1 -zeta3 0 zeta3 -zeta3 - 1 -2]
[ 3 0 0 -1 0 0 3]
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
PermGroup = self.as_permutation_group()
CharTab = PermGroup.character_table()
return CharTab
def CubicBraidGroup(n=None, names='c', AdditionalRelation = 'C', verbose = False ):
"""
Constructs cubic quotients of braid groups as instance of the CubicBraidGroup_class
If you don't see this well formatted type
sage: print CubicBraidGroup.__doc__
for more information about the CubicBraidGroup_class type
sage: print CubicBraidGroup_class.__doc__
INPUT:
- "n": integer or None (default). The number of strands. If not specified the "names" are counted and the group is
assumed to have one more strand than generators.
- "names": string or list/tuple/iterable of strings (default:'c'). The generator names or name prefix.
The entry can be either a string with the names of the generators, or the number of generators and the prefix
of the names to be given. The default prefix is 'c'
- "AdditionalRelation": (optional keyword, default = 'C') is passed to the corresponding keyword parameter of
the constructor of the CubicBraidGroup_class. For more information type
sage: print CubicBraidGroup_class.__doc__
- "verbose": (optional keyword, default = False) is passed to the corresponding keyword parameter of
the constructor of the CubicBraidGroup_class. For more information type
sage: print CubicBraidGroup_class.__doc__
This function is adapted from the BraidGroup function!
EXAMPLES:
sage: C3=CubicBraidGroup(3); C3.generators()
(c0, c1)
sage: CubicBraidGroup(3, 'g').generators()
(g0, g1)
sage: U3.<u1,u2>=CubicBraidGroup(3, AdditionalRelation = 'U'); U3.generators()
(u1, u2)
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
if n is not None:
try:
n = Integer(n)-_sage_const_1
except TypeError:
names = n
n = None
if n is None:
if isinstance(names, six.string_types):
n = len(names.split(','))
else:
names = list(names)
n = len(names)
try:
from sage.structure.category_object import normalize_names
except:
from sage.structure.parent import normalize_names
names = tuple(normalize_names(n, names))
return CubicBraidGroup_class(names, AdditionalRelation, verbose )
def AssionGroupS(n=None, names='s', verbose = False ):
"""
Constructs cubic quotients of braid groups as instance of the CubicBraidGroup_class which have been investigated
by J.Assion under the notation S(m)
If you don't see this well formatted type
sage: print AssionGroupS.__doc__
for more information about the CubicBraidGroup_class type
sage: print CubicBraidGroup_class.__doc__
This function is a short hand cut for the CubicBraidGroup function setting AdditionalRelation ='S' and
default names='s'
INPUT:
- "n": integer or None (default). The number of strands. This parameter is passed to the corresponding parameter
of the CubicBraidGroup function For more information type
sage: print CubicBraidGroup.__doc__
- "names": string or list/tuple/iterable of strings (default:'s'). This parameter is passed to the corresponding
parameter of the CubicBraidGroup function For more information type
sage: print CubicBraidGroup.__doc__
- "verbose": (optional keyword, default = False) is passed to the corresponding keyword parameter of
the constructor of the CubicBraidGroup_class. For more information type
sage: print CubicBraidGroup_class.__doc__
EXAMPLES:
sage: S3=AssionGroupS(3); S3
Assion group on 3 strands of type S
sage: S3x=CubicBraidGroup(3, names='s', AdditionalRelation = 'S'); S3x
Assion group on 3 strands of type S
sage: S3 == S3x
True
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
return CubicBraidGroup(n = n, names = names, AdditionalRelation = 'S', verbose = verbose )
def AssionGroupU(n=None, names='u', verbose = False ):
"""
Constructs cubic quotients of braid groups as instance of the CubicBraidGroup_class which have been investigated
by J.Assion under the notation U(m)
If you don't see this well formatted type
sage: print AssionGroupU.__doc__
for more information about the CubicBraidGroup_class type
sage: print CubicBraidGroup_class.__doc__
This function is a short hand cut for the CubicBraidGroup function setting AdditionalRelation ='U' and
default names='u'
INPUT:
- "n": integer or None (default). The number of strands. This parameter is passed to the corresponding parameter
of the CubicBraidGroup function For more information type
sage: print CubicBraidGroup.__doc__
- "names": string or list/tuple/iterable of strings (default:'u'). This parameter is passed to the corresponding
parameter of the CubicBraidGroup function For more information type
sage: print CubicBraidGroup.__doc__
- "verbose": (optional keyword, default = False) is passed to the corresponding keyword parameter of
the constructor of the CubicBraidGroup_class. For more information type
sage: print CubicBraidGroup_class.__doc__
EXAMPLES:
sage: U3=AssionGroupU(3); U3
Assion group on 3 strands of type U
sage: U3x=CubicBraidGroup(3, names='u', AdditionalRelation = 'U'); U3x
Assion group on 3 strands of type U
sage: U3 == U3x
True
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
return CubicBraidGroup(n = n, names = names, AdditionalRelation = 'U', verbose = verbose )