From 0133335af28cebd62cf34d93f8efb7872ced2fe2 Mon Sep 17 00:00:00 2001 From: Sebastian Oehms Date: Sun, 22 Jul 2018 09:02:54 +0200 Subject: [PATCH] implement subgroup / ambient methods for MatrixGroup_base --- src/sage/groups/matrix_gps/matrix_group.py | 121 ++++++++++++++++++++- 1 file changed, 115 insertions(+), 6 deletions(-) diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py index 6debf1c3d95..2681b52e3f0 100644 --- a/src/sage/groups/matrix_gps/matrix_group.py +++ b/src/sage/groups/matrix_gps/matrix_group.py @@ -35,6 +35,8 @@ - Simon King (2010-05): Improve invariant_generators by using GAP for the construction of the Reynolds operator in Singular. + +- Sebastian Oehms (2018-07): Add :meth:`subgroup` and :meth:`ambient` see :trac:`25894` """ #***************************************************************************** @@ -103,6 +105,8 @@ class MatrixGroup_base(Group): method. """ + _ambient = None # internal attribute to register the ambient group in case this instance is a subgroup + def _check_matrix(self, x, *args): """ Check whether the matrix ``x`` defines a group element. @@ -165,6 +169,85 @@ def as_matrix_group(self): from sage.groups.matrix_gps.finitely_generated import MatrixGroup return MatrixGroup(self.gens()) + + def subgroup(self, generators, check=True): + """ + Return the subgroup generated by the given generators. + + INPUT: + + - ``generators`` -- a list/tuple/iterable of group elements of self + - ``check`` -- boolean (optional, default: ``True``). Whether to check that each matrix is invertible. + + OUTPUT: The subgroup generated by ``generators`` as an instance of FinitelyGeneratedMatrixGroup_gap + + EAMPLES:: + + sage: UCF = UniversalCyclotomicField() + sage: G = GL(3, UCF) + sage: e3 = UCF.gen(3); e5 =UCF.gen(5) + sage: m = matrix(UCF, 3,3, [[e3, 1, 0], [0, e5, 7],[4, 3, 2]]) + sage: S = G.subgroup([m]); S + Subgroup of General Linear Group of degree 3 over Universal Cyclotomic Field with 1 generators ( + [E(3) 1 0] + [ 0 E(5) 7] + [ 4 3 2] + ) + + sage: CF3 = CyclotomicField(3) + sage: G = GL(3, CF3) + sage: e3 = CF3.gen() + sage: m = matrix(CF3, 3,3, [[e3, 1, 0], [0, ~e3, 7],[4, 3, 2]]) + sage: S = G.subgroup([m]); S + Subgroup of General Linear Group of degree 3 over Cyclotomic Field of order 3 and degree 2 with 1 generators ( + [ zeta3 1 0] + [ 0 -zeta3 - 1 7] + [ 4 3 2] + ) + + TESTS: + + sage: TestSuite(G).run() + sage: TestSuite(S).run() + """ + # this method enlarges the method with same name of ParentLibGAP to cases where the ambient group is not inheritet from ParentLibGAP. + if isinstance(self, ParentLibGAP): + try: + return ParentLibGAP.subgroup(self, generators) + except: + pass + + for g in generators: + if g not in self: + raise ValueError("Generator %s is not in the group"%(g)) + + from sage.groups.matrix_gps.finitely_generated import MatrixGroup + SubGroup = MatrixGroup(generators, check=check, ambient_group=self) + SubGroup._ambient = self + return SubGroup + + def ambient(self): + """ + Return the ambient group of a subgroup. + + OUTPUT: + + A group containing ``self``. If ``self`` has not been defined + as a subgroup, we just return ``self``. + + EXAMPLES:: + + sage: G = GL(2,QQ) + sage: m = matrix(QQ, 2,2, [[3, 0],[~5,1]]) + sage: S = G.subgroup([m]) + sage: S.ambient() is G + True + """ + if self._ambient is None: + return self + else: + return self._ambient + def _repr_(self): """ Return a string representation. @@ -183,14 +266,40 @@ def _repr_(self): [1 2] [1 1] [4 1], [0 1] ) + + case of being a subroup:: + + sage: CF3 = CyclotomicField(3) + sage: G = GL(2, CF3) + sage: e3 = CF3.gen() + sage: m = matrix(CF3, 2,2, [[e3, 1], [0, ~e3]]) + sage: S = G.subgroup([m]); S + Subgroup of General Linear Group of degree 2 over Cyclotomic Field of order 3 and degree 2 with 1 generators ( + [ zeta3 1] + [ 0 -zeta3 - 1] + ) """ - if self.ngens() > 5: - return 'Matrix group over {0} with {1} generators'.format( - self.base_ring(), self.ngens()) + ambient_group = None + if hasattr(self, '_ambient'): + if not isinstance(self._ambient, ParentLibGAP): # in order not to affect existing code and docs + ambient_group = self._ambient + + if ambient_group == None: + if self.ngens() > 5: + return 'Matrix group over {0} with {1} generators'.format( + self.base_ring(), self.ngens()) + else: + from sage.repl.display.util import format_list + return 'Matrix group over {0} with {1} generators {2}'.format( + self.base_ring(), self.ngens(), format_list(self.gens())) else: - from sage.repl.display.util import format_list - return 'Matrix group over {0} with {1} generators {2}'.format( - self.base_ring(), self.ngens(), format_list(self.gens())) + if self.ngens() > 5: + return 'Subgroup of {0} with {1} generators'.format( + ambient_group, self.ngens()) + else: + from sage.repl.display.util import format_list + return 'Subgroup of {0} with {1} generators {2}'.format( + ambient_group, self.ngens(), format_list(self.gens())) def _repr_option(self, key): """