�
ɍ�Xc@s�ddlTed�Zed�Zed�ZddlTddlmZddlm	Z	ddl
Tdefd��YZd	efd
��YZ
de
efd��YZd
ed�ZdS(i����(t*iii(t FinitelyGeneratedMatrixGroup_gap(tParentLibGAPtMatrixGroup_subgroupcBs eZdZd�Zd�ZRS(s�
    This class can be used to create subgroups of matrix_groups beeing generated by a finite list of generators in the 
    ambient group. It is an analogy to the PermutationGroup_subgroup class It can be used in cases of matrix groups
    which don't pocess a subgroup attribute.

    If you don't see this well formatted type 

    sage: print MatrixGroup_subgroup.__doc__
     
    This class has two methods overwriting the corresponding methods of FinitelyGeneratedMatrixGroup_gap class.

      - "__init__": to register the information corresponding to the ambient group

      - "_repr_:    to print a representing string containing the ambient group


    INPUT (to the constructor):

      - "ambient": the matrix group for which the subgroup shoul be craeted

      - "generators": list of elements in the ambient group generating the subgroup to be defined


    EXAMPLE:

        sage: UCF = UniversalCyclotomicField()
        sage: G = GL(2, UCF)
        sage: M = matrix( UCF, [[1, E(12)], [0,-1]] ); M
        [       1 -E(12)^7]
        [       0       -1]
        sage: S = G.subgroup([M])
        ---------------------------------------------------------------------------
        AttributeError                            Traceback (most recent call last)
        .......
        AttributeError: 'LinearMatrixGroup_generic_with_category' object has no attribute 'subgroup'
        sage: 
        sage: from lib.local_matrix_group import *
        sage: S = MatrixGroup_subgroup(G, [M])
        sage: S
        Subgroup of General Linear Group of degree 2 over Universal Cyclotomic Field generated by ([       1 -E(12)^7]
        [       0       -1],)
        sage: 

    TESTS:

        sage: UCF = UniversalCyclotomicField()
        sage: G = GL(2, UCF)
        sage: M = matrix( UCF, [[1, E(12)], [0,-1]]  )
        sage: S = MatrixGroup_subgroup(G, [M])
        sage: TestSuite(S).run()

    AUTHOR

      - Sebastian Oehms, Okt. 2016


    c	Cs�x-|D]%}||krtd|��qqWg|D]}t|�^q7}tj|�}|j�}|j�}tj||||�||_dS(s�
        Python constructor.

        for more information type

        sage: print MatrixGroup_subgroup.__doc__ 
    

        AUTHOR

          - Sebastian Oehms, Sept. 2016

        s Generator %s is not in the groupN(t
ValueErrortlibgaptGroupt	base_ringtdegreeRt__init__t_ambient(	tselftambientt
generatorstgt
matrix_gentgap_genst	gap_groupRR((slib/local_matrix_group.pyR	os
cCsd|j|j�fS(s[
        Return a string representation

        If you don't see this well formatted type 

        sage: print MatrixGroup_subgroup._repr_.__doc__

        OUTPUT:

        String decribing self

        TESTS:

           sage: UCF = UniversalCyclotomicField()
           sage: G = GL(2, UCF)
           sage: M = matrix( UCF, [[1, E(12)], [0,-1]] )
           sage: S = MatrixGroup_subgroup(G, [M])
           sage: S
           Subgroup of General Linear Group of degree 2 over Universal Cyclotomic Field generated by ([       1 -E(12)^7]
           [       0       -1],)
           sage: 
        sSubgroup of %s generated by:
%s(R
tgens(R((slib/local_matrix_group.pyt_repr_�s(t__name__t
__module__t__doc__R	R(((slib/local_matrix_group.pyR4s9	t local_UnitaryMatrixGroup_genericcBs\eZdZd	Zd�Zd�Zd�Zd�Zd�Z	d�Z
d�Zd�ZRS(
s�
    This class is an extension of the sage class UnitaryMatrixGroup_generic 

    If you don't see this well formatted type 

    sage: print local_UnitaryMatrixGroup_generic.__doc__

    This class contains the following additional methods

      - _conjugate
      - _adjoined

      - subgroup 
      - invariant_bilinear_form / invariant_form

    Furthermore the original method 

      - _check_matrix 
  
    has been overwritten since the original one does not behave correctly in the case of finite fields
     
    EXAMPLES:

        See the method documentation. For instance, type:

        sage: print local_UnitaryMatrixGroup_generic.subgroup.__doc__
        sage: print local_UnitaryMatrixGroup_generic.invariant_bilinea_form.__doc__
       

    TESTS:

        sage: G34 = GU(3,4)
        sage: TestSuite(G33).run()
        sage: UCF = UniversalCyclotomicField()
        sage: G3UCF = GU(3, UCF)
        sage: TestSuite(G3UCF).run()
        sage: h=matrix(UCF, 3,3,[[0,0,1],[0,1,0],[1,0,0]] )
        sage: G3h = GU(3, UCF, hermitian_form=h)
        sage: TestSuite(G3h).run()
           

    AUTHOR

      - Sebastian Oehms, Sept. 2016

    cCsTt|t�rAytj||�}WqPt||�}qPXnt||�}|S(sM
        Return the subgroup generated by the given generators

        If you don't see this well formatted type 

        sage: print local_UnitaryMatrixGroup_generic.subgroup.__doc__

        In case where self is an instance of ParentLibGAP this method is identical to the corresponding method of that class.
        In all other cases an instance of the class MatrixGroup_subgroup is returned

        INPUT:

        - ``generators`` -- a list/tuple/iterable of group elements of self

        OUTPUT:

          The subgroup generated by ``generators`` as an in instance of

          - FinitelyGeneratedMatrixGroup_gap  if self is an instance of ParentLibGAP

          - MatrixGroup_subgroup  elsewise

        EAMPLE:

         sage: from lib.local_matrix_group import *
         sage: UCF = UniversalCyclotomicField()
         sage: M = matrix( UCF, [[0, 1], [1,0]] )
         sage: GU2=GU(2,UCF, hermitian_form=M); GU2
         General Unitary Group of degree 2 over Universal Cyclotomic Field with respect to hermitian form [0 1]
         [1 0]
         sage: S = GU2.subgroup( [M] ); S
         Subgroup of General Unitary Group of degree 2 over Universal Cyclotomic Field with respect to hermitian form [0 1]
         [1 0] generated by ([0 1]
         [1 0],)
         sage: isinstance( GU3, ParentLibGAP)
         False
         sage: isinstance( S, ParentLibGAP)
         True
         sage: isinstance( S, MatrixGroup_subgroup )
         True
         sage: 

        TESTS:

           see the tests for the class
           
        AUTHOR:

          - Sebastian Oehms, Sept. 2016


        (t
isinstanceRtsubgroupR(RR
tSubGroup((slib/local_matrix_group.pyR�s6cCs
||_dS(sd
        This method registers the hermitian form to which should be kept invariant be self
        N(t_hermitian_form_(Rthermitian_form((slib/local_matrix_group.pyt__set_hermitian_form__scCs�|jdkr|jS|j�tkrqy |j�j�dj�}Wq�tk
rm|j�j�}q�Xnttttg�}|j	�|S(s
        Return the sesquilinear form preserved by the unitary group. 

        If you don't see this well formatted type 

        sage: print local_UnitaryMatrixGroup_generic.invariant_bilinear_form.__doc__

        If a hermitian_form has been set explicitely by the method __set_hermitian_form__ it will be returned.
        Elsewise the gap function "InvariantSesquilinearForm" is used.

        Compare the corresponding methods with respect to the orthogonal groups

        OUTPUT:

           the hermitian form as a matrix with entries in the base_ring 

        EXAMPLES:

           sage: GU25 = GU(2,5)
           sage: GU52.invariant_bilinear_form()
           [0 0 0 0 1]
           [0 0 0 1 0]
           [0 0 1 0 0]
           [0 1 0 0 0]
           [1 0 0 0 0]
           sage: GU3Q = GU(3,QQ)
           sage: GU3Q.invariant_bilinear_form()
           [1 0 0]
           [0 1 0]
           [0 0 1]


        TESTS:

           see the tests for the class
           
        AUTHOR

          - Sebastian Oehms, Sept. 2016

        tmatrixN(
RtNoneRt
_sage_const_1tgaptInvariantSesquilinearFormRtAttributeErrortonet
set_immutable(Rtm((slib/local_matrix_group.pytinvariant_bilinear_form%s* 

cCs
|j�S(sV
        Return the sesquilinear form preserved by the unitary group. Compare the corresponding methods with respect to the 
        symplectic groups. It is identical to invariant_bilinear_form (duplicate names in sage). For more information type

        sage: print local_UnitaryMatrixGroup_generic.invariant_bilinear_form.__doc__
        (R'(R((slib/local_matrix_group.pytinvariant_form_scCs�t|j�t�r$|j�}nnt|j��r�|j�}x2|j�D]$}|ji||j�|6�qOWt	|�}n|j�}|S(s�
        This internal method calculates the elementwise conjugate of the matrix mat
        
        INPUT:

          - mat matrix with entries from the base_ring of self

        OUTPUT:

          - the conjugate of mat as matrix of the same type

        EXAMPLES:

            sage: from lib.local_matrix_group import *
            sage: GU52 = GU(5,2)
            sage: gl = GU52.some_elements()
            sage: g = gl[0]; g
            [1 0 0 0 0]
            [0 a 0 0 0]
            [0 0 1 0 0]
            [0 0 0 a 0]
            [0 0 0 0 1]
            sage: GU52._conjugate( g.matrix() )
            [    1     0     0     0     0]
            [    0 a + 1     0     0     0]
            [    0     0     1     0     0]
            [    0     0     0 a + 1     0]
            [    0     0     0     0     1]
            sage:  

        TESTS:

           see the tests for the class
           
        AUTHOR

          - Sebastian Oehms, Sept. 2016
  
        (
RRtUniversalCyclotomicFieldt	conjugatetfinite_field_sqrttdicttkeystupdatet	frobeniusR(Rtmattresulttmatconjtind((slib/local_matrix_group.pyt
_conjugateks("cCs|j|j��}|S(s�
        Return the adjoint (conjugate and transpose) matrix of mat. 
        
        INPUT:

          - mat matrix with entries from the base_ring of self

        OUTPUT:

          - the conjugate and transpose of mat as matrix of the same type

        EXAMPLES:

            sage: from lib.local_matrix_group import *
            sage: GU52 = GU(5,2)
            sage: gl = GU52.gens()
            sage: g = gl[1]; g
            [0 1 0 0 0]
            [a 0 1 0 1]
            [1 0 1 0 0]
            [1 0 0 0 0]
            [0 0 0 1 0]
            sage: GU52._adjoint( g.matrix() )
            [    0 a + 1     1     1     0]
            [    1     0     0     0     0]
            [    0     1     1     0     0]
            [    0     0     0     0     1]
            [    0     1     0     0     0]
            sage: 

        TESTS:

           see the tests for the class
           
        AUTHOR

          - Sebastian Oehms, Sept. 2016

        (R4t	transpose(RR0R1((slib/local_matrix_group.pyt_adjoint�s(cs�yt|j���Wn
t�nX�fd�}|jr_|j�tkr_td��n|||�s}td��ndS(s

        Check whether the matrix ``x`` is unitary. This method overwrites the original sage-method with the same name. In 
        addition to it
 
           - it takes into acount a special user defined hermitian form
           - it works well in the case of a finite field (which is not the case for the original version)

        If you don't see this well formatted type 

        sage: print local_UnitaryMatrixGroup_generic._check_matrix.__doc__

        To read the original docstring type:
 
        sage: print sage.groups.matrix_gps.unitary.UnitaryMatrixGroup_generic._check_matrix.__doc__

        Description of the bug wich should be avoided by this variation of the original method:

        If an element of a finite unitary group is converted to the underlying matrix class it can not be converted
        back to the unitary group since the method unitary for the matrix gives false (see example below)
        Note: the unitary method attached to the matrix is not changed. It continues to returns false for elements of finite
        unitary groups. 
        

        INPUT:

          same as for the original method

        OUTPUT:

          same as for the original method

        EXAMPLES: 

         First try with the original method to convert an element of a unitary group to a matrix and back:
          
          sage: G32=GU(3,2)
          sage: g1, g2 =G32.gens()
          sage: g1m = g1.matrix(); g1m
          [a 0 0]
          [0 1 0]
          [0 0 a]
          sage: g1m.is_unitary()
          False
          sage: g1m in G32
          False

         Now, do the same thing using local_UnitaryMatrixGroup_generic._check_matrix.__doc__:

          sage: from lib.local_matrix_group import *
          sage: G32=GU(3,2)
          sage: g1, g2 = G32.gens()
          sage: g1m=g1.matrix()
          sage: g1m.is_unitary()
          False
          sage: g1m in G32
          True

        TESTS:

           see the tests for the class
           

        AUTHOR

          - Sebastian Oehms, Sept. 2016

        c	s�|jdks�r�|j|�}|j�}|||}||k}|tkrZ|Sy|j�}Wntk
r�|}nXy|j�}Wntk
r�|}nX||}|j�}|S|j�SdS(s�
            This function supports an alternative check to x.is_unitary() 
            for finite fields or explicit hermitian form
            N(	RRR6R'tTrueRR#tis_zerot
is_unitary(	RtxtxadjointtFtxadFxR1tFmattxadFxmattdiff(tfinite_field(slib/local_matrix_group.pyt
check_unitarys&




s matrix must have determinant onesmatrix must be unitaryN(R+RtFalset_specialtdeterminantR t	TypeError(RR:targsRB((RAslib/local_matrix_group.pyt
_check_matrix�sE
!cKs�y|j�}Wntk
r/|j�}nX|t}|j�}|j|�}|j||k�|j|g�}|j|�}|j|j�|k�dS(sG
        Method called by TestSuite

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class._test_constructions.__doc__

        the following is checked:
           - if _check_matrix works
           - if subgroup works

        AUTHOR

          - Sebastian Oehms, Sept. 2016

        N(	RR#t
some_elementst
_sage_const_0Rt_testertassert_RR(RtoptionstgenListRtgmttest_check_matrixRt
test_subgroup((slib/local_matrix_group.pyt_test_extensions?s

N(
RRRRRRRR'R(R4R6RHRR(((slib/local_matrix_group.pyR�s.	@		:		4	,	ttlocal_UnitaryMatrixGroup_gapcBseZRS((RR(((slib/local_matrix_group.pyRSgstacCs/t||d|�\}}t|�r[|j�}||kr[t|td|�}q[n|dkr�dj||�}dj|t|��}n6dj|||�}dj|t|�t|��}t|�rdj||�}	t||t	|||	�}
nt
||t	||�}
|
j|�|
S(	sO 
    This function overwrites the sage-Funtion with the same name. It uses the extended classes 
    local_UnitaryMatrixGroup_gap and local_UnitaryMatrixGroup_generic in stead of the original classes 
    UnitaryMatrixGroup_gap and UnitaryMatrixGroup_generic additional features are:
  
        - use a special hermitain form via keyword-paremeter: "hermitian_form= ..."
        - ask for the hermitian form to which GU is related via method "invariant_form"
        - define a subgroup of GU to a list of generators via method "subgroup"

    to read to original docstring of GU type:
 
    sage print sage.groups.matrix_gps.unitary.GU.__doc__ 

    EXAMPLES:

      sage: from lib.local_matrix_group import *
      sage: K=UniversalCyclotomicField()
      sage: h=matrix(K, 3,3,[[0,0,1],[0,1,0],[1,0,0]] )
      sage: GU3h=GU(3, K, hermitian_form=h); GU3h
      Unitary Group of degree 3 over Universal Cyclotomic Field with respect to hermitian form
      [0 0 1]
      [0 1 0]
      [1 0 0]
      sage: GU3=GU(3, K); GU3
      General Unitary Group of degree 3 over Universal Cyclotomic Field
      sage: GU3 == GU3h
      False
      sage: x=matrix(K, 3,3,[[0,1,0],[0,0,1],[1,0,0]] ); x
      [0 1 0]
      [0 0 1]
      [1 0 0]
      sage: x in GU3h
      False
      sage: x in GU3
      True

    AUTHOR

      - Sebastian Oehms, Sept. 2016    

    tvartnames,General Unitary Group of degree {0} over {1}s\text{{GU}}_{{{0}}}({1})sGUnitary Group of degree {0} over {1} with respect to hermitian form
{2}s\text{{GU}}_{{{0}}}({1},{2})sGU({0}, {1})N(tnormalize_args_vectorspacetis_FiniteFieldtcardinalitytGFt
_sage_const_2RtformattlatexRSRCRR(tntRRURRtringtqRVtltxtcmdtUnitaryGroup((slib/local_matrix_group.pytGUos +!
N(tsage.all_cmdlinetIntegerR[R RJtsage.groups.matrix_gps.unitaryt)sage.groups.matrix_gps.finitely_generatedRtsage.groups.libgap_wrapperRtlib.utils_gap_interfaceRtUnitaryMatrixGroup_genericRtNamedMatrixGroup_gapRSRRe(((slib/local_matrix_group.pyt<module>s
*

s��