from sage.all_cmdline import *
_sage_const_1 = Integer(1); _sage_const_0 = Integer(0)
"""
Local Permutation Groups
This module contains several extensions to classes inherited from sage PermutationGroup_generic classes.
It fills in missing methods resp. functionality
##############################################################################
# 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 contains extensions of the following classes
sage class | extended class
-------------------------------------------------------------------------------
PermutationGroup_subgroup: | local_PermutationGroup_subgroup
PGU | PGU
PSp | PSp
IrreducibleComplexReflectionGroup | IrreducibleComplexReflectionGroup
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
from sage.groups.perm_gps.permgroup import *
from sage.groups.perm_gps.permgroup_named import *
from lib.utils_sys import *
from lib.local_matrix_group import *
def _call_with_conversion_(PermGroup, x, check=True, try_conv_map=True):
"""
This function provides an adaption of the method __call__ of PermutationGroup_generic in order to make conversion_maps
to groups whose class is inherited from PermutationGroup_generic callable by name. This function should be used for
overloading the __call__ - method of such derived classes
If you don't see this well formatted type
sage: print _call_with_conversion_.__doc__
EXAMPLE:
see the applications of this function for PermutationGroup_subgroup and IrreducibleComplexReflectionGroup:
sage: print local_PermutationGroup_subgroup.__call__.__doc__
sage: print IrreducibleComplexReflectionGroup.__call__.__doc__
AUTHOR
- Sebastian Oehms, Sept. 2016
"""
if isinstance(x, (int, long, Integer)) and x == _sage_const_1 :
return PermGroup.identity()
GroupFrom = None
try:
GroupFrom = x.parent()
if GroupFrom is PermGroup:
return x
except AttributeError:
GroupFrom = None
if try_conv_map == False:
return PermGroup._element_class()(x, PermGroup, check=check)
conv_map = None
if GroupFrom != None:
conv_map = PermGroup.coerce_map_from( GroupFrom )
if conv_map == None:
conv_map = PermGroup.convert_map_from( GroupFrom )
try:
return PermGroup._element_class()(x, PermGroup, check=check)
except:
if conv_map != None:
try:
return conv_map(x)
except:
return PermGroup._element_class()(x, PermGroup, check=check)
class local_PermutationGroup_subgroup(PermutationGroup_subgroup):
"""
Since the Method __call__ of PermutationGroup_subgroup(PermutationGroup_generic) does not support coerce_maps between
groups it is overloaded by this class to fill in the lack. Overloaded methods are:
- __call__
If you don't see this well formatted type
sage: print local_PermutationGroup_subgroup.__doc__
To see the docomentation of the original class type
sage: print PermutationGroup_subgroup.__doc__
AUTHOR
- Sebastian Oehms, Okt. 2016
"""
def __call__(self, x, check=True, try_conv_map=True):
"""
This method overloads the __call__-method of the original class since the method __call__ of
PermutationGroup_subgroup(PermutationGroup_generic) does not support coerce_maps between groups
Here is an improvement concerning this lack.
If you don't see this well formatted type
sage: print local_PermutationGroup_subgroup.__call__.__doc__
To see the docomentation of the original method type
sage: print PermutationGroup_subgroup.__call__.__doc__
EXAMPLE:
try to establish the natural projection from the general unitary group onto the projective unitary group.
first try without using the local_PermutationGroup_subgroup class
sage: GU4 = GU(4,2); GU4
General Unitary Group of degree 4 over Finite Field in a of size 2^2
sage: PGU4ambient = PGU(4,2); PGU4ambient
The projective general unitary group of degree 4 over Finite Field of size 2
sage: PGU4 = PGU4ambient.subgroup(PGU4ambient.gens()); PGU4
Subgroup of (The projective general unitary group of degree 4 over Finite Field of size 2) generated by [(3,4,5)
(7,8,9)(11,12,13)(15,16,17)(19,20,21)(26,34,30)(27,35,31)(28,36,32)(29,37,33)(38,70,54)(39,71,55)(40,72,56)
(41,73,57)(42,82,62)(43,83,63)(44,84,64)(45,85,65)(46,74,66)(47,75,67)(48,76,68)(49,77,69)(50,78,58)(51,79,59)
(52,80,60)(53,81,61), (1,6,22,26,43,3)(2,7,38)(4,8,54,30,60,48)(5,9,70,34,77,53)(10,39)(11,23,42)
(12,71,82,68,63,49)(13,55,62,81,83,52)(14,56,78,51,20,41)(15,72,50)(16,24,58,64,33,44)(17,40,18,73,66,47)
(19,57,46)(21,25,74,85,36,45)(28,75,37,29,59,32)(31,76,69)(35,61,80)(67,79)]
sage: isinstance( PGU4, PermutationGroup_subgroup )
True
sage: isinstance( PGU4, local_PermutationGroup_subgroup )
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-10-0dce512ea45e> in <module>()
----> 1 isinstance( PGU4, local_PermutationGroup_subgroup )
NameError: name 'local_PermutationGroup_subgroup' is not defined
sage: GU4_gap = GU4.gap()
sage: PGU4_gap = gap(PGU4)
sage: natProj_gap = GU4_gap.GroupHomomorphismByImagesNC( PGU4_gap, GU4_gap.GeneratorsOfGroup(),
PGU4_gap.GeneratorsOfGroup())
sage: def natProj_map( elem ):
res = natProj_gap.ImageElm( elem.gap() )
return res.sage()
....:
sage: natProj_hom = Hom( GU4, PGU(natProj_map)
sage: PGU4.register_conversion( natProj_hom )
sage: g1, g2 = GU4.gens()
sage: g = g1**3*g2; g
[1 0 1 0]
[1 0 0 0]
[0 1 0 1]
[0 1 0 0]
sage: PGU4(g)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-11-c93f0a431112> in <module>()
----> 1 PGU4(g)
.......................................
TypeError: 'UnitaryMatrixGroup_gap_with_category.element_class' object is not iterable
sage: natProj_hom(g)
(1,6,22,26,43,3)(2,7,38)(4,8,54,30,60,48)(5,9,70,34,77,53)(10,39)(11,23,42)(12,71,82,68,63,49)(13,55,62,81,83,52)
(14,56,78,51,20,41)(15,72,50)(16,24,58,64,33,44)(17,40,18,73,66,47)(19,57,46)(21,25,74,85,36,45)
(28,75,37,29,59,32)(31,76,69)(35,61,80)(67,79)
sage:
now trying the same using the class local_PermutationGroup_subgroup
sage: from lib.local_permgroup import *
sage: GU4 = GU(4,2); GU4
General Unitary Group of degree 4 over Finite Field in a of size 2^2
sage: PGU4ambient = PGU(4,2); PGU4ambient
The projective general unitary group of degree 4 over Finite Field of size 2
sage: PGU4 = PGU4ambient.subgroup(PGU4ambient.gens()); PGU4
Subgroup of (The projective general unitary group of degree 4 over Finite Field of size 2) generated by [(3,4,5)
(7,8,9)(11,12,13)(15,16,17)(19,20,21)(26,34,30)(27,35,31)(28,36,32)(29,37,33)(38,70,54)(39,71,55)(40,72,56)
(41,73,57)(42,82,62)(43,83,63)(44,84,64)(45,85,65)(46,74,66)(47,75,67)(48,76,68)(49,77,69)(50,78,58)(51,79,59)
(52,80,60)(53,81,61), (1,6,22,26,43,3)(2,7,38)(4,8,54,30,60,48)(5,9,70,34,77,53)(10,39)(11,23,42)
(12,71,82,68,63,49)(13,55,62,81,83,52)(14,56,78,51,20,41)(15,72,50)(16,24,58,64,33,44)(17,40,18,73,66,47)
(19,57,46)(21,25,74,85,36,45)(28,75,37,29,59,32)(31,76,69)(35,61,80)(67,79)]
sage: isinstance( PGU4, PermutationGroup_subgroup )
True
sage: isinstance( PGU4, local_PermutationGroup_subgroup )
True
sage: GU4_gap = GU4.gap()
sage: PGU4_gap = gap(PGU4)
sage: natProj_gap = GU4_gap.GroupHomomorphismByImagesNC( PGU4_gap, GU4_gap.GeneratorsOfGroup(),
PGU4_gap.GeneratorsOfGroup())
sage: def natProj_map( elem ):
res = natProj_gap.ImageElm( elem.gap() )
return res.sage()
....:
sage: natProj_hom = Hom(GU4, PGU4)(natProj_map)
sage: PGU4.register_conversion(natProj_hom)
sage: g1, g2 = GU4.gens()
sage: g = g1**3*g2; g
[1 0 1 0]
[1 0 0 0]
[0 1 0 1]
[0 1 0 0]
sage: PGU4(g)
(1,6,22,26,43,3)(2,7,38)(4,8,54,30,60,48)(5,9,70,34,77,53)(10,39)(11,23,42)(12,71,82,68,63,49)(13,55,62,81,83,52)
(14,56,78,51,20,41)(15,72,50)(16,24,58,64,33,44)(17,40,18,73,66,47)(19,57,46)(21,25,74,85,36,45)
(28,75,37,29,59,32)(31,76,69)(35,61,80)(67,79)
sage:
TESTS:
sage: from lib.local_permgroup import *
sage: sage.groups.perm_gps.permgroup.PermutationGroup_subgroup = local_PermutationGroup_subgroup
sage: GU4 = GU(4,2)
sage: PGU4ambient = PGU(4,2)
sage: PGU4 = PGU4ambient.subgroup(PGU4ambient.gens())
sage: TestSuite(PGU4).run()
AUTHOR:
- Sebastian Oehms, Okt. 2016
"""
return _call_with_conversion_(self, x, check=check, try_conv_map=try_conv_map)
def __contains__(self, item):
"""
Returns boolean value of ``item in self``.
This method from PermutationGroup_generic has been overwritten here to avoid recursion loops. This method uses the
__call__ method which has been extended here. But to check if an element is in the group the original version of
__call__ must be applied.
If you don't see this well formatted type
sage: print local_PermutationGroup_subgroup.__contains__.__doc__
To see the docomentation of the original method type
sage: print PermutationGroup_subgroup.__contains__.__doc__
"""
try:
item = self(item, check=True, try_conv_map=False)
except Exception:
return False
return True
def gap(self):
"""
Making the gap conversion accessible via the .gap -method
"""
return gap(self)
class PGU(PGU):
"""
Since the Method __call__ of PermutationGroup_subgroup(PermutationGroup_generic) does not support coerce_maps
it is overwritten by this class to fill in the lack. This is done by overwriting the class name
PermutationGroup_subgroup by local_PermutationGroup_subgroup
which contains the extended version of the __call__ methos
If you don't see this well formatted type
sage: print PGU.__doc__
To see the docomentation of the original class type
sage: print sage.groups.perm_gps.permgroup_named.PGU.__init__.__doc__
AUTHOR:
- Sebastian Oehms, Okt. 2016
"""
sage.groups.perm_gps.permgroup.PermutationGroup_subgroup = local_PermutationGroup_subgroup
class PSp(PSp):
"""
Since the Method __call__ of PermutationGroup_subgroup(PermutationGroup_generic) does not support coerce_maps
it is overwritten by this class to fill in the lack. This is done by overwriting the class name
PermutationGroup_subgroup by local_PermutationGroup_subgroup
which contains the extended version of the __call__ methos
If you don't see this well formatted type
sage: print PSp.__doc__
To see the docomentation of the original class type
sage: print sage.groups.perm_gps.permgroup_named.PSp.__init__.__doc__
AUTHOR:
- Sebastian Oehms, Okt. 2016
"""
sage.groups.perm_gps.permgroup.PermutationGroup_subgroup = local_PermutationGroup_subgroup
try:
from sage.combinat.root_system.reflection_group_complex import ComplexReflectionGroup, IrreducibleComplexReflectionGroup
class IrreducibleComplexReflectionGroup(IrreducibleComplexReflectionGroup):
"""
Since the Method __call__ of IrreducibleComplexReflectionGroup (inherited from PermutationGroup_generic) does not
support coerce_maps between groups it is overloaded by this class to fill in the lack. Overloaded methods are:
- __call__
If you don't see this well formatted type
sage: print IrreducibleComplexReflectionGroup.__doc__
To see the docomentation of the original class type
sage: print sage.combinat.root_system.reflection_group_complex.IrreducibleComplexReflectionGroup.__doc__
AUTHOR:
- Sebastian Oehms, Okt. 2016
"""
def __call__(self, x, check=True, try_conv_map=True):
"""
This method overloads the __call__-method of the original class since the method __call__ of
IrreducibleComplexReflectionGroup (inherited from PermutationGroup_generic) does not support coerce_maps between
groups Here is an improvement concerning this lack.
If you don't see this well formatted type
sage: print IrreducibleComplexReflectionGroup.__call__.__doc__
To see the docomentation of the original method type
sage: print sage.combinat.root_system.reflection_group_complex.IrreducibleComplexReflectionGroup.__call__.__doc__
EXAMPLE:
try to establish the natural projection from the braid group on 4 strands onto the irreducible complex
reflection group $G_{25}$ (Shephard-Todd number).first try without using this modification of the
IrreduclibeComplexReflectionGroup class
sage: from sage.combinat.root_system.reflection_group_complex import ComplexReflectionGroup,
IrreducibleComplexReflectionGroup
sage: G25 = IrreducibleComplexReflectionGroup(tuple([25]))
sage: B4 = BraidGroup(4)
sage: G25_gap = gap(G25)
sage: B4_gap = B4.gap()
sage: natProj_gap = B4_gap.GroupHomomorphismByImagesNC( G25_gap, B4_gap.GeneratorsOfGroup(),
G25_gap.GeneratorsOfGroup() )
sage: def natProj_map(elem):
res = natProj_gap.ImageElm( elem.gap() )
return res.sage()
....:
sage:
sage: natProj_hom = Hom( B4, G25)(natProj_map)
sage: G25.register_conversion(natProj_hom)
sage:
sage: b1, b2, b3 = B4.gens()
sage: ele = b1*b2*b1**(-1)
sage: G25(ele)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-9d71a15c3419> in <module>()
----> 1 G25(ele)
...........
TypeError: 'BraidGroup_class_with_category.element_class' object is not iterable
sage:
now trying the same using this modification of the IrreduclibeComplexReflectionGroup class
sage: from lib.local_permgroup import *
sage: G25 = IrreducibleComplexReflectionGroup(tuple([25]))
sage: B4 = BraidGroup(4)
sage: G25_gap = gap(G25)
sage: B4_gap = B4.gap()
sage: natProj_gap = B4_gap.GroupHomomorphismByImagesNC( G25_gap, B4_gap.GeneratorsOfGroup(),
G25_gap.GeneratorsOfGroup() )
sage: def natProj_map(elem):
res = natProj_gap.ImageElm( elem.gap() )
return res.sage()
....:
sage:
sage: natProj_hom = Hom( B4, G25)(natProj_map)
sage: G25.register_conversion(natProj_hom)
sage:
sage: b1, b2, b3 = B4.gens()
sage: ele = b1*b2*b1**(-1)
sage: G25(ele)
(1,5,16)(2,50,26)(3,34,47)(4,20,31)(6,9,32)(7,10,25)(11,70,60)(12,67,14)(15,21,61)(17,28,30)(18,49,52)
(19,22,55)(23,53,72)(27,33,66)(36,64,39)(37,45,69)(40,48,63)(42,68,46)(56,62,58)(57,71,65)
TESTS:
sage: from lib.local_permgroup import *
sage: G25 = IrreducibleComplexReflectionGroup(tuple([25]))
sage: TestSuite(G25).run()
AUTHOR:
- Sebastian Oehms, Mar 2017
"""
return _call_with_conversion_(self, x, check=check, try_conv_map=try_conv_map)
def __contains__(self, item):
"""
Returns boolean value of ``item in self``.
This method from PermutationGroup_generic has been overwritten here to avoid recursion loops. This method uses
the __call__ method which has been extended here. But to check if an element is in the group the original
version of __call__ must be applied.
If you don't see this well formatted type
sage: print local_PermutationGroup_subgroup.__contains__.__doc__
To see the docomentation of the original method type
sage: print PermutationGroup_subgroup.__contains__.__doc__
"""
try:
item = self(item, check=True, try_conv_map=False)
except Exception:
return False
return True
def as_matrix_group( self ):
"""
This method implements an extension of the IrreducibleComplexReflectionGroup_class.
It retuns a realization of the reflection group as a matrix group or (if possible) as a subgroup of the unitary
group over the universal cyclotomic field together with conversion maps to and from the refelection group
itselfe. To this purpose it uses the matrix-method of the IrreduclibleComplexReflectionGroup applied to the
genarators of self.
If you don't see this well formatted type
sage: print IrreducibleComplexReflectionGroup.as_matrix_group.__doc__
INPUT: --
OUTPUT:
A subgroup of the general linear (or unitary) group as instance of FinitelyGeneratedMatrixGroup_gap. The
instance of its ambient group is of the UnitaryMatrixGroup class (if possible) or again of
FinitelyGeneratedMatrixGroup_gap
EXAMPLES:
sage: print IrreducibleComplexReflectionGroup.as_unitary_group.__doc__
sage: G14 = IrreducibleComplexReflectionGroup(tuple([14]))
sage: U14 = G14.as_unitary_group()
sage:
sage: U14
Subgroup of General Unitary Group of degree 2 over Universal Cyclotomic Field generated by:
([ 1 0]
[ 0 -1],
[ 1/2*E(24) - 1/2*E(24)^16 + 1/2*E(24)^19 1/2*E(3)^2]
[ -1/2*E(3)^2 -1/2*E(24) - 1/2*E(24)^16 - 1/2*E(24)^19])
sage:
sage: isinstance( U14, FinitelyGeneratedMatrixGroup_gap)
True
sage: isinstance( U14.ambient(), UnitaryMatrixGroup_generic)
True
Conversion of Elements:
sage: g1, g2 = G14.gens()
sage: U14(g1*g2)
[1/2*E(24) - 1/2*E(24)^16 + 1/2*E(24)^19 1/2*E(3)^2]
[ 1/2*E(3)^2 1/2*E(24) + 1/2*E(24)^16 + 1/2*E(24)^19]
sage: gu = U14(g1*g2); gu
[1/2*E(24) - 1/2*E(24)^16 + 1/2*E(24)^19 1/2*E(3)^2]
[ 1/2*E(3)^2 1/2*E(24) + 1/2*E(24)^16 + 1/2*E(24)^19]
sage: g = G14(gu); g
(1,7,19,39,69,89,110,116,119,114,73,23,3,5,17,37,67,90,109,115,120,113,71,21)
(2,8,20,40,70,74,24,4,6,18,38,68,91,101,42,10,14,34,65,98,52,60,72,2 2)
(9,13,33,64,97,51,59,96,105,117,102,43,11,15,35,66,99,49,57,95,106,118,100,41)
(12,16,36,48,56,50,58,76,26,30,62,79,84,81,87,103,46,54,93,104,78,28,32,44)
(25,29,61,83,111,80,86,45,53,92,108,77,27,31,63,85,112,82,88,47,55,94,107,75)
sage: g == g1*g2
True
None unitary realization:
sage: G15 = IrreducibleComplexReflectionGroup(tuple([15]))
sage: M15 = G15.as_matrix_group(); M15
Matrix group over Universal Cyclotomic Field with 3 generators (
[-1/3*E(24) + 1/3*E(24)^11 + 1/3*E(24)^17 - 1/3*E(24)^19 1/3*E(24) + 1/6*E(24)^11 + 1/6*E(24)^17 + 1/3*E(24)^19]
[-1/3*E(24) - 2/3*E(24)^11 - 2/3*E(24)^17 - 1/3*E(24)^19 1/3*E(24) - 1/3*E(24)^11 - 1/3*E(24)^17 + 1/3*E(24)^19],
[ 1 0] [-1/3*E(12)^7 + 1/3*E(12)^11 1/3*E(12)^7 - 1/3*E(12)^11]
[ 0 E(3)], [ 2/3*E(12)^7 - 2/3*E(12)^11 1/3*E(12)^7 - 1/3*E(12)^11]
)
sage: isinstance( M15, FinitelyGeneratedMatrixGroup_gap )
True
sage: isinstance( M15.ambient(), FinitelyGeneratedMatrixGroup_gap )
True
AUTHOR:
- Sebastian Oehms, Mar 2017
"""
genList = [ gen.matrix() for gen in self.gens() ]
BaseRing = genList[_sage_const_0 ].base_ring()
BaseGroup = GU( self.rank(), BaseRing )
try:
MatGroup = BaseGroup.subgroup( genList )
except:
MatGroup = MatrixGroup( genList )
homToMat = gap_hom( self, MatGroup )
homFromMat = gap_hom( MatGroup, self )
return MatGroup
except:
pass