�
ɍ�Xc@s�ddlTed�Zed�Zed�Zed�Zed�ZddlmZddl	Td�Z
d	�Zed
�Z
ed�Zdded�Zddeed
�Zed�Zed�Zd�ZdS(i����(t*iiiii(tParentLibGAPcCsP|dkrLdt|�krL|j�rI|tjd�krFdSqIqLn|S(s�
    this function converts the gap boolean fail into a None object
 
    INPUT:
 
     - an arbtrary gap_element

    OUTPUT:

      the element itself or None if it is the gap-boolean fail.

    tis_booltfailN(tNonetdirRtlibgapteval(tgap_element((slib/utils_gap_interface.pyt
gap_result;s

cCs�y|j�}Wnt|�}nXt|j|��}|dkrZtd|��ny||j��}Wn||�}nX|S(s�
    This function can be used to converts a gap group map which was defined by the gap functions like 
    'GroupHomomorphismByImages' or 'IsomorhismPermGroup' or others having an ImageElm attribute into a 
    sage function object

    If you don't see this well formatted type 

    sage: print gap_group_map.__doc__

    INPUT:

       - "groupEle": an element of the source group, whose image should be obtained, as a sage object.

       - "GroupTo":  the  target group as a sage object

       - "gapHom":   the gap homomorphism which should be applied to groupEle and which has been defined by a gap functions 
                     like 'GroupHomomorphismByImages' or 'IsomorhismPermGroup'

    OUTPUT:

       the value of groupEle under gap_hom as object of GroupTo
       
    RAISE:

      - RuntimeError: "gap cannot compute image of %s" If gap fails to compute the image

    USAGE:

       if you have defined a target group 'my_target_group' in your programm and a gap function 'my_gap_hom' then you
       can obtain a sage function object by setting

       def my_group_map( groupEle ):
            return gap_group_map( groupEle, my_target_group, my_gap_hom )

    EXAMPLE:

       isoToPerm = Group_gap.IsomorphismPermGroup()

       permGens = isoToPerm.Image().GeneratorsOfGroup().sage()
       PermGroup = PermutationGroup( permGens )

       def groupIso( groupEle ):
           return gap_group_map( groupEle, PermGroup, isoToPerm )


    AUTHOR

      - Sebastian Oehms, Sept. 2016

    sgap cannot compute image of %sN(tgapR	tImageElmRtRuntimeErrortsage(tgroupEletGroupTotgapHomtgroupEle_gaptimGroupEle_gapt
imGroupEle((slib/utils_gap_interface.pyt
gap_group_mapVs3cCs�td|�}|jdddtj�yt||�|�}Wn&|}|jdddtj�nXy|j|�Wn |jdddtj�nXy|j|�Wn |jdddtj�nX|jdddtj�|S(	s�
    This function registers the function object GroupMap as a Hom-Object, coerecion and conversion to the sage group 
    GroupTo

    If you don't see this well formatted type 

    sage: print register_hom.__doc__

    INPUT:

       - "GroupFrom": source group as a sage object

       - "GroupTo":   target group as a sage object

       - "GroupMap":  the map to be registered as a sage function object

       - "verbose":   optional keyword to print time stamp debugging messages
                      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__

    OUTPUT:

       the function object groupMap as an element of Hom( GroupFrom, GroupTo )


    AUTHOR

      - Sebastian Oehms, Sept. 2016

    tverbosetTexttBegintLevelsno homsno coercions
no conversiontEnd(tsetupTimeStamptprint_timestamptTsLevelt	StackInfotHomtDebugtregister_coerciontregister_conversion(t	GroupFromRtgroupMapRt	TimeStamptgroupHom((slib/utils_gap_interface.pytregister_hom�s"$cCsNtd|�}|jdddtj�dt|�kr�g}xx|j�D]j}|tkr�|j||t�|jt�qM|tkrM|j||t�|jt�qMqMW|St	|�}d|}t
j|�x9t|�D]+}d|t|tf}t
j|�q�Wdt|t�krKt
d	|t��n|tj�}t|tjjj�tkr�t|tjjj�tkr�t
d
|t��ndt|�kr�|j�}	nt|�}	dt||��kr||�j�}
n||�}
y#g|D]}|j�^q}Wn&g|D]}t
|�^qD}nX|	j|�}
|
j�j|
�}|j�}|j�j�}g}t
jd�}t
jd
�}xht|�D]Z}|||t�j�}|||t�j�t}|j||�|j|�q�W|jdddtj�|S(s�
    variant of the sage word_problem-method which behaves identical for permutation
    groups as well as for matrix-group and other groups

    If you don't see this well formatted type 

    sage: print gap_word_problem.__doc__

    Three sage-classes have got a word_problem method as an implementation of the gap function "EpimorphismFromFreeGroup":

     - GroupElementMixinLibGAP ( sage.groups.libgap_mixin )
     - PermutationGroupElement ( sage.groups.perm_gps.permgroup_element )
     - DualAbelianGroupElement ( sage.groups.abelian_gps.dual_abelian_group_element ) 

    But all three methods behave different and are implemented differently. None of these methods returns the result as
    a list, in order to use it in a function. It seems that the original purpose is only to display the result.
    Also note, that the PermutationGroupElement method displays the result returned by gap in a wrong way, as can be seen 
    from the following example:

    sage: S3=SymmetricGroup(4)
    sage: s1, s2 = S3.gens()
    sage: s = s1**3*s2*s1; s
    (2,3)
    sage:  sw = s.word_problem(S3.gens())
             x2^-1*x1^-1*(x1^-1*x2^-1)^2*x2^-1*x1^-2*x2^-1*x1^-1
             [['(1,2)', -1], ['(1,2,3,4)', -1], ['((1,2,3,4)', -1], ['(1,2)', -1], ['(1,2,3,4)', -2], 
              ['(1,2)', -1], ['(1,2,3,4)', -1]]
    sage: sw
    ('x2^-1*x1^-1*(x1^-1*x2^-1)^2*x2^-1*x1^-2*x2^-1*x1^-1',
     '(1,2)^-1*(1,2,3,4)^-1*((1,2,3,4)^-1*(1,2)^-1)^2*(1,2)^-1*(1,2,3,4)^-2*(1,2)^-1*(1,2,3,4)^-1')

    Here the output displayed in the second line (which is only printed and not returned as result of the function) 
    ignores the brackets (...)**2 (around the expression "x1^-1*x2^-1") returned by gap. 

    The function "gap_word_problem" deals with the same task, but returns the result in list form. Continuing with the
    above example we get

    sage: swg = gap_word_problem(s, S3.gens()); swg
    [(1,2), -1, (1,2,3,4), -2, (1,2), -1, (1,2,3,4), -1, (1,2), -2, (1,2,3,4), -2, (1,2), -1, (1,2,3,4), -1]
    sage: check=S3.one()
    sage: for i in range(len(swg)/2):
              check = check * swg[2*i]**swg[2*i+1]
          ....:     
    sage: check == s
    True


    INPUT:

        - "element": an element in a group to be represented in terms of a set of generators

        - "genList": list of generators in the same group as element, such that element lies in the subgroup generated 
                     by them
        - "verbose": optional keyword to print time stamp debugging messages
                     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__


    OUTPUT:

        a word in the generators in "genList" representing "element" as a list of length 2*l if l is the length of the 
        word. This list has the form (w_1, e_1, w_2, e_2, .... , w_l, e_l) where the w_i in genList are the generators
        in the word expression whereas the e_i are the corresponding exponents, that is
        
           element = w_1**e_1 * w_2**e_2 * .... * w_l**e_  

    RAISE:

        - TypeError: "generator genList[0] must have a parent" if the first element of genList has no attribute "parent"

        - TypeError: "parent of generator genList[0] must be an instance of Group" if the first element of genList does
                     not belong to a group

    EXAMPLE:

    continuing the example above we look at the type returned

        sage: type(sw)
        <type 'tuple'>
        sage: type(sw[1])
        <type 'str'>
        sage: type(sw[0])
        <type 'str'>

        sage: type(swg)
        <type 'list'>
        sage: type(swg[0])
        <type 'sage.groups.perm_gps.permgroup_element.PermutationGroupElement'>
        sage: type(swg[1])
        <type 'sage.rings.integer.Integer'>
        sage: 

    an example of matrix groups

        sage: GL3_3=GL(3,3)
        sage: g1, g2 = GL3_3.gens()
        sage: g1, g2 = GL3_3.gens(); g1, g2
        (
         [2 0 0]  [2 0 1]
         [0 1 0]  [2 0 0]
         [0 0 1], [0 2 0]
        )
        sage: g = g1**2*g2*g1; g
        [1 0 1]
        [1 0 0]
        [0 2 0]
        sage: gwg = gap_word_problem(g, [g1,g2] ); gwg
        [
        [2 0 1]     [2 0 0]    
        [2 0 0]     [0 1 0]    
        [0 2 0], 1, [0 0 1], -1
        ]
        sage: 
        sage: check=GL3_3.one()
        sage: for i in range(len(gwg)/2):
                  check = check * gwg[2*i]**gwg[2*i+1]
              ....:     
        sage: check == g
        True

    an example of fintely preseted groups

        sage: B3 = BraidGroup(3); B3
        Braid group on 3 strands
        sage: b1, b2 = B3.gens()
        sage: b1, b2 = B3.gens(); b1, b2
        (s0, s1)
        sage: 
        sage: 
        sage: b = b1**2*b2*b1; b
        s0^2*s1*s0
        sage: bwg = gap_word_problem(b, [b1,b2] ); bwg
        [s0, 1, s0, 1, s1, 1, s0, 1]
        sage: check=B3.one()
        sage: for i in range(len(bwg)/2):
                  check = check * bwg[2*i]**bwg[2*i+1]
        ....:     
        sage: check == b
        True


    AUTHOR

      - Sebastian Oehms, Sept. 2016

    RRRRtTietzesFg:=FreeGroup(%d);s!x%d := GeneratorsOfGroup(Fg)[%d];tparentsgenerator %s must have a parents3parent of generator %s must be an instance of GroupR
tExponentSyllabletGeneratorSyllableR(RRRRRR't
_sage_const_0tappendt
_sage_const_1tlenRRtranget	TypeErrorR(t
isinstanceR
tgroupstoldtGrouptFalsetgroupR
tSubgrouptEpimorphismFromFreeGrouptPreImagesRepresentativetUnderlyingElementtNumberSyllables(telementtgenListRR$tresulttitntcmdR"tGtgtgentgenList_gaptHtanstans_repltnumtexponent_syllabletgenerator_syllabletexponentt	generator((slib/utils_gap_interface.pytgap_word_problem�s^�

<##cs�td|�}|jdddtj�t|tjjj�t	krst|tjj
j�t	krstd��nt�tjjj�t	kr�t�tjj
j�t	kr�td��n|d
kr�g|D]}||�^q��n|j
��|d
kr&g|D]}�|�^q�n�j
��t��t��krYtd��n���fd�}|jdd	dtj�|S(s(
    expand a map given on generators of GroupFrom into another GroupTo. If the optional keyword GensFrom and GensTo 
    are not set the generators of GroupFrom and GroupTo will be used instead

    Note: it is not checked if this gives a well defined homomorphis. This must be known or checked separately


    If you don't see this well formatted type 

    sage: print expand_map_from_generators.__doc__

    This functin is based on the gap_word_problem function and therefor on the gap function "EpimorphismFromFreeGroup"

    INPUT:

        - "GroupFrom": the source group of the map to be generated 

        - "GroupTo":   the target group of the map to be generated 

        - "GensFrom":  (optional keyword, default = None takes GroupFrom.gens()) set of generators of GroupFrom which
                       should be mapped to the according elements (same order) of GensTo resp. GroupTo.gens()  

        - "GensTo":    (optional keyword, default = None takes Groupo.gens()) set of generators of GroupTo which
                       should be the images of the according elements (same order) of GensFrom resp. GroupFrom.gens()  

        - "verbose": optional keyword to print time stamp debugging messages
                     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__


    OUTPUT:

        a function object of the following form:
        
        INPUT:

          - "Ele" an arbitrary element of GroupFrom

        OUTPUT:

          the corresponding element in GroupTo under the map defined


    RAISE:

        - TypeError: "GroupFrom  must be an instance of Group" 

        - TypeError: "GroupTo  must be an instance of Group" 

        - ValueError: "incompatible length of generator sets" if the list of generators of source and targed have different
                      length

    EXAMPLE:

        sage: S3=SymmetricGroup(4); S3
        Symmetric group of order 4! as a permutation group

        sage: s1, s2 = S3.gens()
        sage: s = s1**3*s2*s1; s
        (2,3) 
        sage: 
        sage: GU3 = GU(3,2); GU3
        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: 
        sage: S3toGU3 = expand_map_from_generators( S3, GU3); S3toGU3
        <function Map at 0x9ac3e0d4>
        sage: g = S3toGU3(s); g
        [1 a a]
        [a a 0]
        [a 0 0]

     note that S3toGU3 is not a group homomorphism

        sage: g1 = S3toGU3(s1); g1
        [a 0 0]
        [0 1 0]
        [0 0 a]
        sage: g2 = S3toGU3(s2); g2
        [    0     0     1]
        [    0     1     1]
        [    1     1 a + 1]
        sage: g_check = g1**3*g2*g1; g_check 
        [0 0 a]
        [0 1 a]
        [a 1 1]
        sage: g == g_check
        False


    AUTHOR

      - Sebastian Oehms, Sept. 2016

    RRRRs'GroupFrom  must be an instance of Groups$GroupTo must be an instance of Groups%incompatible length of generator setscs�t|��}t|�t}�j�}xit|�D][}xR�D]J}|t||krE��j|�}|||t|t}qEqEWq8W|S(N(RNR.t
_sage_const_2toneR/tindexR-(tEletEleGenst	anzLettertToEleR?tfGenttGen(tFgensRtTgens(slib/utils_gap_interface.pytMapHs
%RN(RRRRR1R
R2R3R4R5R6R0RtgensR.t
ValueError(R"RtGensFromtGensToRR$RCRZ((RXRRYslib/utils_gap_interface.pytexpand_map_from_generators�s"g<<""cs=td|�}|jdddtj�t|tjjj�t	krst|tjj
j�t	krstd��nt�tjjj�t	kr�t�tjj
j�t	kr�td��ny|j�}Wn,t|�}|jdddtj
�nXy�j�}Wn,t��}|jdddtj
�nX|dkrW|j�}	ney#g|D]}
|
j�^qa}	Wn?g|D]}
t|
�^q�}	|jdd	dtj
�nX|dkr�|j�}ney#g|D]}
|
j�^q�}Wn?g|D]}
t|
�^q}|jdd
dtj
�nXt|	�t|�krctd��ny�|t	kr�t|j||	|���nt|j||	|����dkr	|t	kr�t|�||d|�}ntd��|jdd
dtj
�n+��fd�}|jdddtj
�WnV|t	kret|�||d|�}ntd��|jdddtj
�nXyd||j��}
|jdddtj
�|
�j�kr�|tkr�td��q�dGHnWntd��nXt|�|d|�}|jdddtj�|S(s�
    This function creates a map from GroupFrom to GroupTo via the GAP-function 'GroupHomomorphismByImages' such that 
    generators GensFrom are mapped to GensTo. If the optional parameter GensFrom and GensTo are not set the generators 
    of GroupFrom and GroupTo will be used instead.

    If GroupHomomorphismByImages fails on the task the function expand_map_from_generators is used for a second try
    This function is based on GAP-function 'EpimorphismFromFreeGroup' (via gap_word_problem). For more information
    on this type

        sage: print expand_map_from_generators.__doc__
        sage: print gap_word_problem.__doc__


    Note: it is not checked if this gives a well defined homomorphism by default. To achieve this set the 
    keyword check = True

    If you don't see this well formatted type 

    sage: print expand_map_from_generators.__doc__

    INPUT:

        - "GroupFrom": the source group of the map to be generated 

        - "GroupTo":   the target group of the map to be generated 

        - "GensFrom":  (optional keyword, default = None takes GroupFrom.gens()) set of generators of GroupFrom which
                       should be mapped to the according elements (same order) of GensTo resp. GroupTo.gens()  

        - "GensTo":    (optional keyword, default = None takes Groupo.gens()) set of generators of GroupTo which
                       should be the images of the according elements (same order) of GensFrom resp. GroupFrom.gens()  

        - "check":     optional boolean, default = False. If set to True the constructed map is tested to be a a well 
                       defined group homomorphism. Depending wether the gap function "GroupHomomorphismByImages"
                       can be used the check is perfomed by gap. In the other case a NotImplemented Exception is raised.

        - "verbose": optional keyword to print time stamp debugging messages
                     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__


    OUTPUT:

        an element of Hom( GroupFrom, GroupTo )


    RAISE:

        - TypeError: "GroupFrom  must be an instance of Group" 

        - TypeError: "GroupTo  must be an instance of Group" 

        - ValueError: "incompatible length of generator sets" if the list of generators of source and targed have different
                      length

        - RuntimeError: "One does not map to one" if check = True, else a warning

        - RuntimeError: "No map definition possible" the test that the contructed map works failed

        - RuntimeError: "gap cannot compute image of ..." occurs when the constructed map is applied: calculation of 
                        the image of a specific element failed 

        - NotImplementedError: "no check for expand_map_from_generators - try again with check = False" occurs if 
                      check is set to True and gap function "GroupHomomorphismByImages" can not be applied


    EXAMPLE:

     
        sage: B3 = BraidGroup(3)
        sage: S3=SymmetricGroup(3)
        sage: Im=[S3((1,2)), S3((2,3))]; Im
        [(1,2), (2,3)]
        sage: b2s = gap_hom( B3, S3, GensTo=Im ); b2s
        Generic morphism:
        From: Braid group on 3 strands
        To:   Symmetric group of order 3! as a permutation group
        sage: b1, b2 = B3.gens(); b1, b2
        (s0, s1)
        sage: b2s(b1*b2*b1)
        (1,3)
        sage: b2s(b2*b1*b2)
        (1,3)

    check if the map is indeed a homomorphism of groups

        sage: b2s_check = gap_hom( B3, S3, GensTo=Im, check=True )
        sage: b2s(b1) == b2s_check(b1)
        True
        sage: b2s(b2) == b2s_check(b2)
        True

    CAUTION: by default it is not checked if the map is well defined nor a homomorphism:

        sage: b2s_wrong = gap_hom( B3, S3 ); b2s_wrong
        Generic morphism:
          From: Braid group on 3 strands
          To:   Symmetric group of order 3! as a permutation group
        sage: 
        sage: b = b1*b2*b1
        sage: bb = b2*b1*b2
        sage: b == bb
        True
        sage: b2s_wrong(b) == b2s_wrong(bb)
        False

    You can check this as follows:

        sage: b2s_wrong = gap_hom( B3, S3, check=True ); b2s_wrong
        ............

        RuntimeError: No map definition possible
        sage: 


    AUTHOR

      - Sebastian Oehms, Sept. 2016

    RRRRs'GroupFrom  must be an instance of Groups$GroupTo must be an instance of Groupsgap(GroupFrom)sgap(GroupTo)slibgap(gen) GensFromslibgap(gen) GensTos%incompatible length of generator setssFno check for expand_map_from_generators - try again with check = Falsesexpand_map_from_generators pos1cst|���S(N(R(R(RtgHom_gap(slib/utils_gap_interface.pyR#stGroupHomomorphissexpand_map_from_generators pos2schecked if groupMap workssOne does not map to ones Warning: one does not map to onesNo map definition possibleRN(RRRRR1R
R2R3R4R5R6R0R
RRtGeneratorsOfGroupRR.R\R	tGroupHomomorphismByImagesNCtGroupHomomorphismByImagesR_tNotImplementedErrorRPtTrueRR&(R"RR]R^tcheckRR$t
GroupFrom_gaptGroupTo_gaptGensFrom_gapRDt
GensTo_gapR#tOneR%((RR`slib/utils_gap_interface.pytgap_hom^sx~<<##cs�td|�}|jdddtj�t�tjjj�t	krst�tjj
j�t	krstd��n�j�s�t
d��ny�j�}Wnt��}nXt|j����d
kr�td��n�j���j�j�j�}t|��|jdddtj���fd	�}��fd
�}|jdddtj�t��|d|�t��|d|�|jdddtj��S(sx
    This function is an extension of the Sage as_permutation_group-method of the classes
 
     - sage.groups.matrix_gps/finitely_generated.FinitelyGeneratedMatrixGroup_gap
     - sage.groups.finitely_presente.FinitelyPresentedGroup

    using the GAP-function 'IsomorphismPermGroup'. It can be applied to other cases of groups.
    Furthermore the isompophism map returned by gap is registered as a conversion map to and from the permutation group
    defined (which is not the case for the above mentioned methods)

    If you don't see this well formatted type 

    sage: print gap_as_permutation_group.__doc__

    INPUT:

       - "Group": the group for which an isomorphism to a permutation group should be found

       - "verbose": optional keyword to print time stamp debugging messages
                    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__

    OUTPUT:

       - an isomporphic permutation group to Group together with the isomorphism registered as conversion maps
         for Group and the returned permutation group

    RAISE:

       - TypeError: "Group  must be an instance of Group"

       - RuntimeError: "gap fails to compute permutation group!"

       - NotImplementedError: "Group must be finite."

    EXAMPLE:

       sage: Sp4 = Sp(4,3); Sp4
       Symplectic Group of degree 4 over Finite Field of size 3
       sage: PSp4 = gap_as_permutation_group( Sp4 ); PSp4
       Permutation Group with generators [(1,2)(3,5)(4,7)(6,10)(8,13)(9,15)(11,18)(12,20)(14,19)(16,24)(17,26)(21,31)
       (22,33)(23,35)(25,32)(27,40)(28,42)(29,44)(30,46)(34,51)(36,53)(37,54)(38,55)(39,50)(43,60)(45,62)(47,56)(48,59)
       (49,64)(57,66)(58,65)(61,63)(69,73)(71,75)(74,78)(76,77), (1,3,6,11,19,29,45,63,72)(2,4,8,14,18,28,43,61,70)
       (5,9,16,25,38,56,62,71,76)(7,12,21,32,49,53,60,69,74)(10,17,27,41,59,68,40,58,44)(13,22,34,52,54,67,51,66,42)
       (15,23,36)(20,30,47)(24,37,55)(26,39,57)(31,48,64)(33,50,65)(73,77,79)(75,78,80)]
       sage: s1, s2 = Sp4.gens(); s1, s2
       (
       [2 0 0 0]  [1 0 1 0]
       [0 1 0 0]  [1 0 0 0]
       [0 0 1 0]  [0 1 0 1]
       [0 0 0 2], [0 2 0 0]
       )
       sage: s = s1*s2**2; s
       [2 2 2 2]
       [1 0 1 0]
       [1 2 0 0]
       [1 0 0 0]
       sage: 
       sage: sp2p = PSp4.convert_map_from( Sp4 )
       sage: p2sp = Sp4.convert_map_from( PSp4 )
       sage: 
       sage: p1 = sp2p( s1 ); p1
       (1,2)(3,5)(4,7)(6,10)(8,13)(9,15)(11,18)(12,20)(14,19)(16,24)(17,26)(21,31)(22,33)(23,35)(25,32)(27,40)(28,42)(29,44)
       (30,46)(34,51)(36,53)(37,54)(38,55)(39,50)(43,60)(45,62)(47,56)(48,59)(49,64)(57,66)(58,65)(61,63)(69,73)(71,75)
       (74,78)(76,77)
       sage: p2 = sp2p( s2 ); p2
       (1,3,6,11,19,29,45,63,72)(2,4,8,14,18,28,43,61,70)(5,9,16,25,38,56,62,71,76)(7,12,21,32,49,53,60,69,74)      
       (10,17,27,41,59,68,40,58,44)(13,22,34,52,54,67,51,66,42)(15,23,36)(20,30,47)(24,37,55)(26,39,57)(31,48,64)(33,50,65)
       (73,77,79)(75,78,80)
       sage: p = sp2p( s ); p
       (1,8,34,42,61)(2,6,27,44,63)(3,16,55,62,72)(4,21,64,60,70)(5,11,43,74,75)(7,14,45,76,73)(9,36,69,79,77)
       (10,19,28,22,65)(12,47,71,80,78)(13,18,29,17,57)(15,25,53,23,35)(20,32,56,30,46)(24,38,37,51,54)(26,41,68,58,50)
       (31,49,48,40,59)(33,52,67,66,39)
       sage: s1 == p2sp( p1 )
       True
       sage: s2 == p2sp( p2 )
       True
       sage: s == p2sp( p)
       True
       sage: 



    AUTHOR

      - Sebastian Oehms, Sept. 2016

    RRRRs#Group  must be an instance of GroupsGroup must be finite.s'gap fails to compute permutation group!sPermutationGroup definedcst|���S(N(R(R(t	PermGroupt	isoToPerm(slib/utils_gap_interface.pytgroupIso�scst|���S(N(R(R(R4tisoToPermInv(slib/utils_gap_interface.pytgroupIsoInv�ssgroupIso definedRN(RRRRR1R
R2R3R4R5R6R0t	is_finiteReR
R	tIsomorphismPermGroupRRtInverseGeneralMappingtImageRbtPermutationGroupRR&(R4RR$t	Group_gaptpermGensRpRr((R4RnRoRqslib/utils_gap_interface.pytgap_as_permutation_groupUs0^<c
Cstd|�}|jdddtj�y|j�}Wnt|�}nXy|j�}Wnt|�}nX|jdddtj�|j|�}|jdddtj�g|j�D]}||�^q�}|jdddtj�|j|�}	|jdddtj�|	S(	s�
    This function returns the centralizer of an Element of the Group using the GAP-function
    'Centralizer'. This extends the use of this GAP-function in sage to Groups which are not
    permutation groups (note that the sage-method centralizer is defined for peremutation group, only)

    If you don't see this well formatted type 

    sage: print gap_centralizer.__doc__

    INPUT:

       - "Group": the group in which the centralizer should be calculated

       - "Element": element in Group which shoul commute with all elements of the centralizer

       - "verbose": optional keyword to print time stamp debugging messages
                    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__

    OUTPUT:

      the maximal subgroup of "Group" whose elements commute with the given "Element" as sage subgroup of "Group" 


    EXAMPLES:
 
       sage: Sp4 = Sp(4,3)
       sage: s1, s2 = Sp4.gens(); s1, s2
       (
       [2 0 0 0]  [1 0 1 0]
       [0 1 0 0]  [1 0 0 0]
       [0 0 1 0]  [0 1 0 1]
       [0 0 0 2], [0 2 0 0]
       )
       sage: s = s1*s2**2; s
       [2 2 2 2]
       [1 0 1 0]
       [1 2 0 0]
       [1 0 0 0]
       sage: CSp4s = gap_centralizer( Sp4, s ); CSp4s
       Matrix group over Finite Field of size 3 with 2 generators (
       [2 2 2 2]  [2 0 0 0]
       [1 0 1 0]  [0 2 0 0]
       [1 2 0 0]  [0 0 2 0]
       [1 0 0 0], [0 0 0 2]
       )
       sage: c1, c2 = CSp4s.gens()
       sage: cs1=Sp4(c1); cs1
       [2 2 2 2]
       [1 0 1 0]
       [1 2 0 0]
       [1 0 0 0]
       sage: cs2=Sp4(c2); cs2
       [2 0 0 0]
       [0 2 0 0]
       [0 0 2 0]
       [0 0 0 2]
       sage: cs1*s == s * cs1
       True
       sage: cs2*s == s * cs2
       True
       sage: 


    AUTHOR

      - Sebastian Oehms, Sept. 2016

    RRRRsCalling Gapssetting sage generator listsdefining subgroupR(	RRRRR
tBodytCentralizerRbtsubgroup(
R4tElementRR$RxtElement_gaptcentralizer_gapRDtGenListtcentralizer((slib/utils_gap_interface.pytgap_centralizer�s$K%cCs�t|t�tkr$td��nddlm}m}ddlm}|�}t	|�}|�}||j
�tkr�|t|j
�tkr�dGHt|j
�tt|j
�t�}n||kr�td|�d||fGHndS(	s�
    extends the minimum GAP workspace to the given value if possible:


    If you don't see this well formatted type 

    sage: print gap_extend_workspace.__doc__

    INPUT:

       - "new_size" the new size in byte to which the gap workspace should be extended

    RAISE:

        TypeError: "new_size must be of type Integer!"

    MESSAGES:

     informational:

        "Note: GAP workspace has been extended: %d -> %d"%(akt_memory_pool_size, new_memory_pool_size)

     warning:

        "Warning: cannont extend the GAP workspace more than half of swap and 4/5 of ram" if new_size is byond the limits
                                                                                          of hardware recources  


    EXAMPLES::

      on an Acer AO Happy under LinuxMint 17.3 Mate with 2 GB RAM:

       sage: oneHundertMB = 100*1024**2
       sage: gap_extend_workspace( 8*oneHundertMB )
       Note: GAP workspace has been extended: 262144000 -> 838860800
       sage: 
       sage: gap_extend_workspace( 13*oneHundertMB )
       Warning: cannont extend the GAP workspace more than half of swap and 4/5 of ram
       Note: GAP workspace has been extended: 262144000 -> 1058121318
       sage: 

    AUTHOR

      - Sebastian Oehms, Sept. 2016

    s!new_size must be of type Integer!i����(tget_gap_memory_pool_sizetset_gap_memory_pool_size(t
MemoryInfosOWarning: cannont extend the GAP workspace more than half of swap and 4/5 of ramtmax_workspace_sizes/Note: GAP workspace has been extended: %d -> %dN(R1tIntegerR5R0tsage.interfaces.gapR�R�tsage.misc.memory_infoR�tinttavailable_swapROt
_sage_const_4t
available_ramt
_sage_const_5tmaxtgap_reset_workspace(tnew_sizeR�R�R�takt_memory_pool_sizetnew_memory_pool_sizetmem((slib/utils_gap_interface.pytgap_extend_workspaceks0		0*
N(tsage.all_cmdlineR�ROR-R+R�R�tsage.groups.libgap_wrapperRt
lib.utils_sysR	RR5R&RNRR_RmRzR�R�(((slib/utils_gap_interface.pyt<module>s 
+
		NJ����l