�
ɍ�Xc@s�ddlTed�Zed�Zed�ZddlTddlmZddlm	Z	ddl
Tdefd��YZd	efd
��YZ
de
efd��YZd
ed�ZdS(i����(t*iii(t FinitelyGeneratedMatrixGroup_gap(tParentLibGAPtMatrixGroup_subgroupcBs eZdZd�Zd�ZRS(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]%}||krtd|��qqWg|D]}t|�^q7}tj|�}|j�}|j�}tj||||�||_dS(s�
Python constructor.

sage: print MatrixGroup_subgroup.__doc__

AUTHOR

- Sebastian Oehms, Sept. 2016

s Generator %s is not in the groupN(t
ValueErrortlibgaptGroupt	base_ringtdegreeRt__init__t_ambient(	tselftambientt
generatorstgt
matrix_gentgap_genst	gap_groupRR((slib/local_matrix_group.pyR	os
cCsd|j|j�fS(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:
sSubgroup of %s generated by:
%s(R
tgens(R((slib/local_matrix_group.pyt_repr_�s(t__name__t
__module__t__doc__R	R(((slib/local_matrix_group.pyR4s9	t local_UnitaryMatrixGroup_genericcBs\eZdZd	Zd�Zd�Zd�Zd�Zd�Z	d�Z
d�Zd�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

- 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

cCsTt|t�rAytj||�}WqPt||�}qPXnt||�}|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
isinstanceRtsubgroupR(RR
tSubGroup((slib/local_matrix_group.pyR�s6cCs
||_dS(sd
This method registers the hermitian form to which should be kept invariant be self
N(t_hermitian_form_(Rthermitian_form((slib/local_matrix_group.pyt__set_hermitian_form__scCs�|jdkr|jS|j�tkrqy |j�j�dj�}Wq�tk
rm|j�j�}q�Xnttttg�}|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

tmatrixN(
RtNoneRt
_sage_const_1tgaptInvariantSesquilinearFormRtAttributeErrortonet
set_immutable(Rtm((slib/local_matrix_group.pytinvariant_bilinear_form%s* 

cCs
|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((slib/local_matrix_group.pytinvariant_form_scCs�t|j�t�r$|j�}nnt|j��r�|j�}x2|j�D]$}|ji||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

(
RRtUniversalCyclotomicFieldt	conjugatetfinite_field_sqrttdicttkeystupdatet	frobeniusR(Rtmattresulttmatconjtind((slib/local_matrix_group.pyt
_conjugateks("cCs|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]
[    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

t�nX�fd�}|jr_|j�tkr_td��n|||�s}td��ndS(s

Check whether the matrix x is unitary. This method overwrites the original sage-method with the same name. In

- 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�|jdks�r�|j|�}|j�}|||}||k}|tkrZ|Sy|j�}Wntk
r�|}nXy|j�}Wntk
r�|}nX||}|j�}|S|j�SdS(s�
This function supports an alternative check to x.is_unitary()
for finite fields or explicit hermitian form
N(	RRR6R'tTrueRR#tis_zerot
check_unitarys&




s matrix must have determinant onesmatrix must be unitaryN(R+RtFalset_specialtdeterminantR t	TypeError(RR:targsRB((RAslib/local_matrix_group.pyt
_check_matrix�sE
!cKs�y|j�}Wntk
r/|j�}nX|t}|j�}|j|�}|j||k�|j|g�}|j|�}|j|j�|k�dS(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(	RR#t
some_elementst
_sage_const_0Rt_testertassert_RR(RtoptionstgenListRtgmttest_check_matrixRt
test_subgroup((slib/local_matrix_group.pyt_test_extensions?s

N(
RRRRRRRR'R(R4R6RHRR(((slib/local_matrix_group.pyR�s.	@		:		4	,	ttlocal_UnitaryMatrixGroup_gapcBseZRS((RR(((slib/local_matrix_group.pyRSgstacCs/t||d|�\}}t|�r[|j�}||kr[t|td|�}q[n|dkr�dj||�}dj|t|��}n6dj|||�}dj|t|�t|��}t|�rdj||�}	t||t	|||	�}
nt
||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

tvartnames,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(tnormalize_args_vectorspacetis_FiniteFieldtcardinalitytGFt
_sage_const_2RtformattlatexRSRCRR(tntRRURRtringtqRVtltxtcmdtUnitaryGroup((slib/local_matrix_group.pytGUos +!
N(tsage.all_cmdlinetIntegerR[R RJtsage.groups.matrix_gps.unitaryt)sage.groups.matrix_gps.finitely_generatedRtsage.groups.libgap_wrapperRtlib.utils_gap_interfaceRtUnitaryMatrixGroup_genericRtNamedMatrixGroup_gapRSRRe(((slib/local_matrix_group.pyt<module>s
*

s��