# This file was *autogenerated* from the file local_permgroup.sage
from sage.all_cmdline import *   # import sage library
_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

"""





####################################################################################################
# Extension to PermutationGroup_generic / PermutationGroup_subgroup
####################################################################################################
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

    """

    # print_time_tb( Text="Begin %s %s %s" %(x, check, try_conv_map), MaxDepth=5, Level=TsLevel.StackInfo )

    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