diff --git a/gap/base/presentation.gi b/gap/base/presentation.gi new file mode 100644 index 00000000..1088178b --- /dev/null +++ b/gap/base/presentation.gi @@ -0,0 +1,97 @@ +############################################################################# +## +## This file is part of recog, a package for the GAP computer algebra system +## which provides a collection of methods for the constructive recognition +## of groups. +## +## This files's authors include Torben Wiedemann. +## +## Copyright of recog belongs to its developers whose names are too numerous +## to list here. Please refer to the COPYRIGHT file for details. +## +## SPDX-License-Identifier: GPL-3.0-or-later +## +## +## This file provides code for standard presentations of some groups +## (which are not covered by the classicpres package). +## +############################################################################# + +# Returns the presentation Fp (i.e. an FpGroup) of S_n from +# [BLN+03] "A black-box group algorithm for recognizing finite symmetric +# and alternating groups, I", (2.1) +# or an "obvious" presentation of S_n for small n. +# For n=1, Fp is the trivial group. +# For n>1, Fp has a generator Fp.1 which corresponds to (1,2). +# This is the only generator if n=2. +# For n>2, Fp has exactly two generators and Fp.2 corresponds to (1,...,n). +# Note: The claim in [BLN+03] that this presentation can be found in +# [CM80] "Generators and relations for discrete groups" +# is apparently slightly imprecise. In [CM80, (6.26)], +# the same presentation minus the relations +# s^n = 1 and (t*s)^(n-1) but with the additional weaker relation +# s^n = (t*s)^(n-1) appears. Since this presentation defines S_n by [CM80], we +# can add additional relations that are satisfied in S_n without changing the +# presented group, so the presentation in [BLN+03, (2.1)] is correct. +RECOG.SnPresentation := function(n) + local F, rels, s, t, j; + # Edge cases for small n + if n<1 then + return fail; + elif n=1 then + return FreeGroup(0); + elif n=2 then + F := FreeGroup(1); + return F / [ F.1^2 ]; + fi; + # Generic case + F := FreeGroup(2); + t := F.1; # Notation for s and t as in [BLN+03] + s := F.2; + rels := [ s^n, t^2, (s*t)^(n-1) ]; + for j in [2..QuoInt(n,2)] do + Add(rels, (t*s^-j*t*s^j)^2); + od; + return F / rels; +end; + +# Returns the presentation Fp (i.e. an FpGroup) of A_n from +# [BLN+03] "A black-box group algorithm for recognizing finite symmetric +# and alternating groups, I", (2.2), (2.3). +# or an "obvious" presentation of A_n for small n. +# For n in [1,2], Fp is the trivial group. +# For n=3, Fp has a single generator Fp.1. +# For n>3, Fp has exactly two generators: Fp.1 corresponds to (1,2,3) and +# Fp.2 corresponds to +# - (3,...,n) if n is odd, +# - (1,2)(3,...,n) if n is even. +# For odd n, this is the same presentation as in +# [CM80] "Generators and relations for discrete groups", (2.2). +# For even n, it is similar to [CM80, (2.3)]. +RECOG.AnPresentation := function(n) + local F, rels, s, t, k; + # Edge cases for small n + if n<1 then + return fail; + elif n=1 or n=2 then + return FreeGroup(0); + elif n=3 then + F := FreeGroup(1); + return F / [F.1^3]; + fi; + # Generic case + F := FreeGroup(2); + t := F.1; # Notation for s and t as in [BLN+03] + s := F.2; + rels := [ s^(n-2), t^3 ]; + if IsOddInt(n) then + Add(rels, (s*t)^n); + for k in [1..QuoInt(n-3, 2)] do + Add(rels, (t*s^(-k)*t*s^k)^2); + od; + else + Add(rels, (s*t)^(n-1)); + Add(rels, (t^-1*s^-1*t*s)^2); + fi; + return F / rels; +end; diff --git a/gap/generic/SnAnUnknownDegree.gi b/gap/generic/SnAnUnknownDegree.gi index 73478632..594dc787 100644 --- a/gap/generic/SnAnUnknownDegree.gi +++ b/gap/generic/SnAnUnknownDegree.gi @@ -1300,12 +1300,14 @@ function(ri) else Setslpforelement(ri, SLPforElementFuncsGeneric.SnUnknownDegree); fi; + SetStdPresentation(ri, RECOG.SnPresentation(degree)); else if degree < 11 then Setslpforelement(ri, SLPforElementFuncsGeneric.AnSmallDegree); else Setslpforelement(ri, SLPforElementFuncsGeneric.AnUnknownDegree); fi; + SetStdPresentation(ri, RECOG.AnPresentation(degree)); fi; return Success; end); diff --git a/gap/perm/giant.gi b/gap/perm/giant.gi index 25619c71..96d44036 100644 --- a/gap/perm/giant.gi +++ b/gap/perm/giant.gi @@ -851,42 +851,14 @@ function(ri) Setslpforelement(ri,SLPforElementFuncsPerm.Giant); ri!.giantinfo := res; SetFilterObj(ri,IsLeaf); - F := FreeGroup(2); # for presentation - # We set the presentations of Sn and An from - # [CM80] "Generators and relations for discrete groups", (6.21), 6.3. - # They coincide with the ones in - # [BLN+03] "A black-box group algorithm for recognizing finite symmetric - # and alternating groups, I", (2.1), (2.2), (2.3), - # except that one relation in (2.1) and one relation in (2.3) is incorrect. - # Since deg>=8, we do not have to worry about small edge cases. + # Note: Since deg>=8, we are never in the small edge cases of + # AnPresentation/SnPresentation. + SetNiceGens(ri,StripMemory(res.gens)); if res.stamp = "An" then - SetSize(ri,Factorial(Length(mp))/2); - SetIsRecogInfoForSimpleGroup(ri,true); - rels := [ F.2^(deg-2), F.1^3 ]; - if deg mod 2 = 1 then - Add(rels, (F.2*F.1)^deg); - rels := Concatenation( - rels, - List([1..QuoInt(deg-3, 2)], k -> (F.1*F.2^(-k)*F.1*F.2^k)^2) - ); - else - Add(rels, (F.2*F.1)^(deg-1)); - rels := Concatenation( - rels, - List([1..QuoInt(deg-2, 2)], k -> (F.1^((-1)^k)*F.2^-k*F.1*F.2^k)^2) - ); - fi; + SetStdPresentation(ri, RECOG.AnPresentation(deg)); else - SetSize(ri,Factorial(Length(mp))); - SetIsRecogInfoForAlmostSimpleGroup(ri,true); - # Relations on F.1=(1,2), F.2 = (1,...,deg) from [CM80, (6.21)] - rels := [ F.1^2, F.2^deg, (F.1*F.2)^(deg-1), (F.1*(F.1^F.2))^3 ]; - rels := Concatenation( - rels, List([2..QuoInt(deg, 2)], j -> (F.1*(F.1^(F.2^j)))^2) - ); + SetStdPresentation(ri, RECOG.SnPresentation(deg)); fi; - SetNiceGens(ri,StripMemory(res.gens)); - SetStdPresentation(ri,F / rels); return Success; end); diff --git a/read.g b/read.g index 93ae9763..99b1745c 100644 --- a/read.g +++ b/read.g @@ -20,6 +20,7 @@ ReadPackage("recog","gap/base/methsel.gi"); ReadPackage("recog","gap/base/recognition.gi"); ReadPackage("recog","gap/base/kernel.gi"); ReadPackage("recog","gap/base/projective.gi"); +ReadPackage("recog","gap/base/presentation.gi"); # Some tools ReadPackage("recog","gap/utils.gi"); diff --git a/tst/working/quick/presentation.tst b/tst/working/quick/presentation.tst new file mode 100644 index 00000000..9c791ce2 --- /dev/null +++ b/tst/working/quick/presentation.tst @@ -0,0 +1,11 @@ +# +gap> START_TEST("presentation.tst"); +gap> for n in [1..7] do +> if Size(RECOG.SnPresentation(n)) <> Size(SymmetricGroup(n)) then +> Display("Presentation for symmetric group S_", n, " has incorrect size"); +> fi; +> if Size(RECOG.AnPresentation(n)) <> Size(AlternatingGroup(n)) then +> Display("Presentation for alternating group A_", n, " has incorrect size"); +> fi; +> od; +gap> STOP_TEST("verification.tst");