From b1925b1849664bcc602bff39294e013406d728e2 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 19 Apr 2023 12:06:10 +0900 Subject: [PATCH 1/5] Implementing generic centralizer and subgroup methods; improving center methods. --- src/sage/groups/libgap_mixin.py | 156 ++++++++++++++++++++++- src/sage/groups/matrix_gps/heisenberg.py | 30 +++++ 2 files changed, 180 insertions(+), 6 deletions(-) diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 1a3bb209e24..5f171ee68d4 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -348,7 +348,7 @@ class function on the conjugacy classes, in that order. @cached_method def center(self): """ - Return the center of this linear group as a subgroup. + Return the center of this group as a subgroup. OUTPUT: @@ -356,25 +356,25 @@ def center(self): EXAMPLES:: - sage: G = SU(3,GF(2)) + sage: G = SU(3, GF(2)) sage: G.center() Subgroup with 1 generators ( [a 0 0] [0 a 0] [0 0 a] ) of Special Unitary Group of degree 3 over Finite Field in a of size 2^2 - sage: GL(2,GF(3)).center() + sage: GL(2, GF(3)).center() Subgroup with 1 generators ( [2 0] [0 2] ) of General Linear Group of degree 2 over Finite Field of size 3 - sage: GL(3,GF(3)).center() + sage: GL(3, GF(3)).center() Subgroup with 1 generators ( [2 0 0] [0 2 0] [0 0 2] ) of General Linear Group of degree 3 over Finite Field of size 3 - sage: GU(3,GF(2)).center() + sage: GU(3, GF(2)).center() Subgroup with 1 generators ( [a + 1 0 0] [ 0 a + 1 0] @@ -393,13 +393,157 @@ def center(self): [0 3 0] [0 1 0] [0 0 1], [0 1 1] ) + + sage: GL = groups.matrix.GL(3, ZZ) + sage: GL.center() + Traceback (most recent call last): + ... + NotImplementedError: group must be finite """ + if not self.is_finite(): + raise NotImplementedError("group must be finite") G = self.gap() center = list(G.Center().GeneratorsOfGroup()) - if len(center) == 0: + if not center: center = [G.One()] return self.subgroup(center) + def centralizer(self, g): + r""" + Return the centralizer of ``g`` in ``self``. + + EXAMPLES:: + + sage: G = groups.matrix.GL(2, 3) + sage: g = G([[1,1], [1,0]]) + sage: C = G.centralizer(g); C + Subgroup with 3 generators ( + [1 1] [2 0] [2 1] + [1 0], [0 2], [1 1] + ) of General Linear Group of degree 2 over Finite Field of size 3 + sage: C.order() + 8 + + sage: S = G.subgroup([G([[2,0],[0,2]]), G([[0,1],[2,0]])]); S + Subgroup with 2 generators ( + [2 0] [0 1] + [0 2], [2 0] + ) of General Linear Group of degree 2 over Finite Field of size 3 + sage: G.centralizer(S) + Subgroup with 3 generators ( + [2 0] [0 1] [2 2] + [0 2], [2 0], [1 2] + ) of General Linear Group of degree 2 over Finite Field of size 3 + + sage: H = groups.matrix.Heisenberg(2) + sage: H.centralizer(H.an_element()) + Traceback (most recent call last): + ... + NotImplementedError: group must be finite + """ + if not self.is_finite(): + raise NotImplementedError("group must be finite") + G = self.gap() + centralizer = list(G.Centralizer(g).GeneratorsOfGroup()) + if not centralizer: + centralizer = [G.One()] + return self.subgroup(centralizer) + + def subgroups(self): + r""" + Return a list of all the subgroups of ``self``. + + OUTPUT: + + Each possible subgroup of ``self`` is contained once in the returned + list. The list is in order, according to the size of the subgroups, + from the trivial subgroup with one element on through up to the whole + group. Conjugacy classes of subgroups are contiguous in the list. + + .. WARNING:: + + For even relatively small groups this method can take a very long + time to execute, or create vast amounts of output. Likely both. + Its purpose is instructional, as it can be useful for studying + small groups. + + For faster results, which still exhibit the structure of + the possible subgroups, use :meth:`conjugacy_classes_subgroups`. + + EXAMPLES:: + + sage: G = groups.matrix.GL(2, 2) + sage: G.subgroups() + [Subgroup with 0 generators () of General Linear Group of degree 2 over Finite Field of size 2, + Subgroup with 1 generators ( + [0 1] + [1 0] + ) of General Linear Group of degree 2 over Finite Field of size 2, + Subgroup with 1 generators ( + [1 0] + [1 1] + ) of General Linear Group of degree 2 over Finite Field of size 2, + Subgroup with 1 generators ( + [1 1] + [0 1] + ) of General Linear Group of degree 2 over Finite Field of size 2, + Subgroup with 1 generators ( + [0 1] + [1 1] + ) of General Linear Group of degree 2 over Finite Field of size 2, + Subgroup with 2 generators ( + [0 1] [1 1] + [1 1], [0 1] + ) of General Linear Group of degree 2 over Finite Field of size 2] + + sage: H = groups.matrix.Heisenberg(2) + sage: H.subgroups() + Traceback (most recent call last): + ... + NotImplementedError: group must be finite + """ + if not self.is_finite(): + raise NotImplementedError("group must be finite") + ccs = self.gap().ConjugacyClassesSubgroups() + return [self.subgroup(h.GeneratorsOfGroup()) + for cc in ccs for h in cc.Elements()] + + def conjugacy_classes_subgroups(self): + r""" + Return a complete list of representatives of conjugacy classes of + subgroups in ``self``. + + The ordering is that given by GAP. + + EXAMPLES:: + + sage: G = groups.matrix.GL(2,2) + sage: G.conjugacy_classes_subgroups() + [Subgroup with 0 generators () of General Linear Group of degree 2 over Finite Field of size 2, + Subgroup with 1 generators ( + [1 1] + [0 1] + ) of General Linear Group of degree 2 over Finite Field of size 2, + Subgroup with 1 generators ( + [0 1] + [1 1] + ) of General Linear Group of degree 2 over Finite Field of size 2, + Subgroup with 2 generators ( + [0 1] [1 1] + [1 1], [0 1] + ) of General Linear Group of degree 2 over Finite Field of size 2] + + sage: H = groups.matrix.Heisenberg(2) + sage: H.conjugacy_classes_subgroups() + Traceback (most recent call last): + ... + NotImplementedError: group must be finite + """ + if not self.is_finite(): + raise NotImplementedError("group must be finite") + return [self.subgroup(sub.Representative().GeneratorsOfGroup()) + for sub in self.gap().ConjugacyClassesSubgroups()] + def intersection(self, other): """ Return the intersection of two groups (if it makes sense) as a diff --git a/src/sage/groups/matrix_gps/heisenberg.py b/src/sage/groups/matrix_gps/heisenberg.py index 68832525331..87f3a6dffd4 100644 --- a/src/sage/groups/matrix_gps/heisenberg.py +++ b/src/sage/groups/matrix_gps/heisenberg.py @@ -223,3 +223,33 @@ def order(self): return ZZ(self._ring.cardinality() ** (2*self._n + 1)) cardinality = order + + def center(self): + """ + Return the center of ``self``. + + This is the subgroup generated by the `z`, the matrix with a `1` + in the upper right corner and along the diagonal. + + EXAMPLES:: + + sage: H = groups.matrix.Heisenberg(2) + sage: H.center() + Subgroup with 1 generators ( + [1 0 0 1] + [0 1 0 0] + [0 0 1 0] + [0 0 0 1] + ) of Heisenberg group of degree 2 over Integer Ring + + sage: H = groups.matrix.Heisenberg(3, 4) + sage: H.center() + Subgroup with 1 generators ( + [1 0 0 0 1] + [0 1 0 0 0] + [0 0 1 0 0] + [0 0 0 1 0] + [0 0 0 0 1] + ) of Heisenberg group of degree 3 over Ring of integers modulo 4 + """ + return self.subgroup([self.gens()[-1]]) From 302442635f88f2181e254b77861079c157b9f0d7 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 19 Apr 2023 12:16:27 +0900 Subject: [PATCH 2/5] Adding exponents() method as well. --- src/sage/groups/libgap_mixin.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 5f171ee68d4..17c4eac4844 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -544,6 +544,31 @@ def conjugacy_classes_subgroups(self): return [self.subgroup(sub.Representative().GeneratorsOfGroup()) for sub in self.gap().ConjugacyClassesSubgroups()] + def exponent(self): + r""" + Computes the exponent of the group. + + The exponent `e` of a group `G` is the LCM of the orders of its + elements, that is, `e` is the smallest integer such that `g^e = 1` + for all `g \in G`. + + EXAMPLES:: + + sage: G = groups.matrix.GL(2, 3) + sage: G.exponent() + 24 + + sage: H = groups.matrix.Heisenberg(2) + sage: H.exponent() + Traceback (most recent call last): + ... + NotImplementedError: group must be finite + """ + if not self.is_finite(): + raise NotImplementedError("group must be finite") + from sage.rings.integer import Integer + return Integer(self._libgap_().Exponent()) + def intersection(self, other): """ Return the intersection of two groups (if it makes sense) as a From 61f881eb242b81da20822529cac4235c9d0a1877 Mon Sep 17 00:00:00 2001 From: Daniel Bump <75940445+dwbmscz@users.noreply.github.com> Date: Fri, 21 Apr 2023 22:03:44 -0700 Subject: [PATCH 3/5] edits to the centralizer code --- src/sage/groups/libgap_mixin.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 17c4eac4844..90101a7777c 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -434,7 +434,9 @@ def centralizer(self, g): [2 0] [0 1] [2 2] [0 2], [2 0], [1 2] ) of General Linear Group of degree 2 over Finite Field of size 3 - + sage: G = GL(3,2) + sage: all(G.order()==G.centralizer(x).order()*G.conjugacy_class(x).cardinality() for x in G) + True sage: H = groups.matrix.Heisenberg(2) sage: H.centralizer(H.an_element()) Traceback (most recent call last): @@ -444,10 +446,10 @@ def centralizer(self, g): if not self.is_finite(): raise NotImplementedError("group must be finite") G = self.gap() - centralizer = list(G.Centralizer(g).GeneratorsOfGroup()) - if not centralizer: - centralizer = [G.One()] - return self.subgroup(centralizer) + centralizer_gens = list(G.Centralizer(g).GeneratorsOfGroup()) + if not centralizer_gens: + centralizer_gens = [G.One()] + return self.subgroup(centralizer_gens) def subgroups(self): r""" @@ -569,6 +571,21 @@ def exponent(self): from sage.rings.integer import Integer return Integer(self._libgap_().Exponent()) + def group_id(self): + """ + Return the ID code of this group, which is a list of two integers. + It is a unique identified assigned by GAP for groups in the + SmallGroup library. + + EXAMPLES:: + + sage: PGL(2,3).group_id() + [24, 12] + sage: SymmetricGroup(4).group_id() + [24, 12] + """ + return [Integer(n) for n in self._libgap_().IdGroup()] + def intersection(self, other): """ Return the intersection of two groups (if it makes sense) as a From 7501a4b546b959fb401118607237f295b0d55a6b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 25 Apr 2023 09:23:33 +0900 Subject: [PATCH 4/5] Addressing reviewer changes. --- src/sage/groups/libgap_mixin.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 17c4eac4844..134340ac32d 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -444,10 +444,10 @@ def centralizer(self, g): if not self.is_finite(): raise NotImplementedError("group must be finite") G = self.gap() - centralizer = list(G.Centralizer(g).GeneratorsOfGroup()) - if not centralizer: - centralizer = [G.One()] - return self.subgroup(centralizer) + centralizer_gens = list(G.Centralizer(g).GeneratorsOfGroup()) + if not centralizer_gens: + centralizer_gens = [G.One()] + return self.subgroup(centralizer_gens) def subgroups(self): r""" @@ -544,6 +544,29 @@ def conjugacy_classes_subgroups(self): return [self.subgroup(sub.Representative().GeneratorsOfGroup()) for sub in self.gap().ConjugacyClassesSubgroups()] + def group_id(self): + """ + Return the ID code of ``self``, which is a list of two integers. + + EXAMPLES:: + + sage: G = groups.matrix.GL(2, 2) + sage: G.group_id() + [6, 1] + sage: G = groups.matrix.GL(2, 3) + sage: G.id() + [48, 29] + sage: G = groups.matrix.GL(2, ZZ) + sage: G.group_id() + Traceback (most recent call last): + ... + GAPError: Error, the group identification for groups of size infinity is not available + """ + from sage.rings.integer import Integer + return [Integer(n) for n in self.gap().IdGroup()] + + id = group_id + def exponent(self): r""" Computes the exponent of the group. From 112ca3fa432f1221f76ec06e076d6da6f8337f04 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 25 Apr 2023 09:26:24 +0900 Subject: [PATCH 5/5] Some additional changes and merging commits. --- src/sage/groups/libgap_mixin.py | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 7271bfd97d0..04dacde21c0 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -435,7 +435,8 @@ def centralizer(self, g): [0 2], [2 0], [1 2] ) of General Linear Group of degree 2 over Finite Field of size 3 sage: G = GL(3,2) - sage: all(G.order()==G.centralizer(x).order()*G.conjugacy_class(x).cardinality() for x in G) + sage: all(G.order() == G.centralizer(x).order() * G.conjugacy_class(x).cardinality() + ....: for x in G) True sage: H = groups.matrix.Heisenberg(2) sage: H.centralizer(H.an_element()) @@ -547,17 +548,26 @@ def conjugacy_classes_subgroups(self): for sub in self.gap().ConjugacyClassesSubgroups()] def group_id(self): - """ + r""" Return the ID code of ``self``, which is a list of two integers. + It is a unique identified assigned by GAP for groups in the + ``SmallGroup`` library. + EXAMPLES:: + sage: PGL(2,3).group_id() + [24, 12] + sage: SymmetricGroup(4).group_id() + [24, 12] + sage: G = groups.matrix.GL(2, 2) sage: G.group_id() [6, 1] sage: G = groups.matrix.GL(2, 3) sage: G.id() [48, 29] + sage: G = groups.matrix.GL(2, ZZ) sage: G.group_id() Traceback (most recent call last): @@ -594,21 +604,6 @@ def exponent(self): from sage.rings.integer import Integer return Integer(self._libgap_().Exponent()) - def group_id(self): - """ - Return the ID code of this group, which is a list of two integers. - It is a unique identified assigned by GAP for groups in the - SmallGroup library. - - EXAMPLES:: - - sage: PGL(2,3).group_id() - [24, 12] - sage: SymmetricGroup(4).group_id() - [24, 12] - """ - return [Integer(n) for n in self._libgap_().IdGroup()] - def intersection(self, other): """ Return the intersection of two groups (if it makes sense) as a