From 8096b873b7d7c6de3392aaf25cdf85b370d3c6f8 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Mon, 16 Mar 2026 01:05:25 +0100 Subject: [PATCH 01/11] Introduce generalized straight line programs --- doc/bib.xml | 18 +++ doc/gslp.xml | 144 ++++++++++++++++++++++ init.g | 1 + lib/gslp.gd | 329 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/gslp.gi | 280 +++++++++++++++++++++++++++++++++++++++++++ makedoc.g | 1 + read.g | 1 + 7 files changed, 774 insertions(+) create mode 100644 doc/gslp.xml create mode 100644 lib/gslp.gd create mode 100644 lib/gslp.gi diff --git a/doc/bib.xml b/doc/bib.xml index da1640b..f4c6ee6 100644 --- a/doc/bib.xml +++ b/doc/bib.xml @@ -101,4 +101,22 @@ http://magma.maths.usyd.edu.au/magma/ + + + Robert A.Wilson + PeterWalsh + JonathanTripp + IbrahimSuleiman + Richard A.Parker + Simon P.Norton + SimonNickerson + SteveLinton + JohnBray + RachelAbbott + + <C>ATLAS of Finite Group Representations</C> + http://atlas.math.rwth-aachen.de/Atlas/v3 + ATLAS + + diff --git a/doc/gslp.xml b/doc/gslp.xml new file mode 100644 index 0000000..6bfa9f6 --- /dev/null +++ b/doc/gslp.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + +Generalized Straight Line Programs + +The functions described in this chapter have been written by Thomas Breuer, +for version 0.94 of Utils. +

+Generalized straight line programs (in the following abbreviated +as gslps) are a generalization of the straight line programs +that are described in the &GAP; library, +see . +Like the latter objects, gslps describe an efficient way for evaluating +an abstract word at concrete generators. +The difference is that gslps can be built +from existing (generalized) straight line programs. +So the advantages of using gslps are that +

+ + + available objects are reused, + + + the internal structure is retained, and + + + intermediate results of an evaluation are not kept longer than + until the relevant straight line program inside is evaluated. + + +

+A gslp in &GAP; is represented by an object in the category +. +This object has exactly one of the following forms. +

+ + + It is a straight line program, that is, it lies in the + category , + and evaluation at some group elements is defined by + . + + + It is of union kind, that is, the defining data are + a nonempty list of gslps, + and evaluation at some group elements means to evaluate these + defining programs at these group elements, + and to return the concatenation of the results. + + + It is of compose kind, that is, the defining data are + a nonempty list of gslps, + and evaluation at some group elements means + to evaluate the first of them at these elements, + then to evaluate the second of them at the result of the first + evaluations, + and so on, and to return the last result. + + +

+Here are two typical situations where gslps arise. +In both cases, suppose that a list l of standard generators +for a group G is given. +

+ + + Suppose that we know a straight line program for computing generators + l' of a maximal subgroup M of G from l. + For example, these data may be taken from the + ATLAS of Group Representations . + If M is also a group for which the + ATLAS of Group Representations contains generators + and straight line programs, + we may be interested in computing standard generators l'' + for M from l'. +

+ For that, a second straight line program can be needed, + and it makes sense to encode the computation of l'' from + l via a gslp of compose kind. + + + Suppose that we are in fact interested in a downward extension + H of G, and that \pi is the natural epimorphism + from H to G, which maps a list L, say, + of standard generators of H to l. + Then the above gslp for G can be applied to L, + but the result L' may generate a proper subgroup of + \pi^{-1}(M) because some part of the kernel of \pi is + missing. +

+ A list K of generators of the kernel of \pi can be + described by a straight line program that takes L as its + input, and it makes sense to encode the computation of the + concatenation of L' and K from L via a gslp of + union kind. + + +

+ +Gslps can be constructed using . +

+Defining attributes for gslps are + +and . +The probably most interesting operation for gslps is +. +

+Currently we do not intend to provide methods applicable to +generalized straight line programs for all operations that are defined for +straight line programs. +For example, +there is no method +for generalized straight line programs. +

+Special methods applicable to gslps are installed for the operations +, +, +and . + + +

+Functions for Generalized Straight Line Programs + +<#Include Label="IsGeneralizedStraightLineProgram"> +<#Include Label="GeneralizedStraightLineProgram"> +<#Include Label="DataOfGeneralizedStraightLineProgram"> +<#Include Label="NrInputsOfGeneralizedStraightLineProgram"> +<#Include Label="NrOutputsOfGeneralizedStraightLineProgram"> +<#Include Label="ResultOfGeneralizedStraightLineProgram"> +<#Include Label="EquivalentStraightLineProgram"> +<#Include Label="IsInternallyConsistent_gslp"> + +
+ +
diff --git a/init.g b/init.g index 1f9bfb3..8b3b168 100644 --- a/init.g +++ b/init.g @@ -32,6 +32,7 @@ ReadPackage( "utils", "lib/number.gd" ); ReadPackage( "utils", "lib/print.gd" ); ReadPackage( "utils", "lib/record.gd" ); ReadPackage( "utils", "lib/string.gd" ); +ReadPackage( "utils", "lib/gslp.gd" ); if not IsBound( Download ) then ReadPackage( "utils", "lib/download.gd" ); BindGlobal("DOWNLOAD_FROM_UTILS", true); diff --git a/lib/gslp.gd b/lib/gslp.gd new file mode 100644 index 0000000..dfa2c47 --- /dev/null +++ b/lib/gslp.gd @@ -0,0 +1,329 @@ +############################################################################# +## +#W gslp.gd GAP 4 package CTBlocks Thomas Breuer +## +## A remark on the name generalized straight line program: +## We could have taken the viewpoint that these objects are the ones that +## one wants to deal with, +## and that they should therefore be called straight line program, +## whereas &GAP;'s straight line programs could be called +## special straight line programs, +## However, +## several functions are applicable to &GAP;'s straight line programs +## (such as ) +## for which we do not intend to provide methods applicable to +## our generalized straight line programs. +## <#/GAPDoc> +## + + +############################################################################# +## +#C IsGeneralizedStraightLineProgram( ) +## +## <#GAPDoc Label="IsGeneralizedStraightLineProgram"> +## +## +## +## +## Each generalized straight line program in &GAP; lies in the category +## . +## Examples are straight line programs, that is, objects in the category +## . +##

+## gslp:= GeneralizedStraightLineProgram( "union", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); +## +## gap> IsGeneralizedStraightLineProgram( gslp ); +## true +## gap> slp:= StraightLineProgram( [[[1,2]]], 1 ); +## +## gap> IsGeneralizedStraightLineProgram( slp ); +## true +## gap> IsGeneralizedStraightLineProgram( [ slp, slp ] ); +## false +## ]]> +## +## +## <#/GAPDoc> +## +DeclareCategory( "IsGeneralizedStraightLineProgram", IsObject ); + +InstallTrueMethod( IsGeneralizedStraightLineProgram, IsStraightLineProgram ); + + +############################################################################# +## +#A DataOfGeneralizedStraightLineProgram( ) +## +## <#GAPDoc Label="DataOfGeneralizedStraightLineProgram"> +## +## +## +## +## For a generalized straight line program gslp that is not +## a straight line program, +## returns a list of +## length two, +## the first entry being either "union" or "compose" +## and the second being the list of defining generalized straight line +## programs. +##

+## If gslp is a straight line program then this attribute is not +## set in gslp. +## There is no default method to compute the value if it is not stored. +##

+## gslp:= GeneralizedStraightLineProgram( "union", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); +## +## gap> DataOfGeneralizedStraightLineProgram( gslp ); +## [ "union", [ , ] ] +## ]]> +## +## +## <#/GAPDoc> +## +DeclareAttribute( "DataOfGeneralizedStraightLineProgram", + IsGeneralizedStraightLineProgram ); + + +############################################################################# +## +#A NrInputsOfGeneralizedStraightLineProgram( ) +## +## <#GAPDoc Label="NrInputsOfGeneralizedStraightLineProgram"> +## +## +## +## +## For a generalized straight line program gslp, this function +## returns the number of generators that are needed as input. +##

+## If gslp is a straight line program then it may be necessary that +## the value is set in the construction of gslp, +## see . +## If gslp is not a straight line program then the value is +## determined by the (generalized) straight line programs from which +## gslp is constructed. +##

+## NrInputsOfGeneralizedStraightLineProgram( +## > GeneralizedStraightLineProgram( "union", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); +## 1 +## ]]> +##

+## In order to avoid the introduction of unnecessary filters, +## we define just as +## a synonym of . +## +## +## <#/GAPDoc> +## +DeclareSynonymAttr( "NrInputsOfGeneralizedStraightLineProgram", + NrInputsOfStraightLineProgram ); + + +############################################################################# +## +#A NrOutputsOfGeneralizedStraightLineProgram( ) +## +## <#GAPDoc Label="NrOutputsOfGeneralizedStraightLineProgram"> +## +## +## +## +## For a generalized straight line program gslp, this function +## returns the number of elements returned by +## when gslp +## is evaluated. +##

+## Note that the &GAP; library does not define a corresponding attribute +## for straight line programs. +##

+## NrOutputsOfGeneralizedStraightLineProgram( +## > GeneralizedStraightLineProgram( "union", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); +## 2 +## gap> NrOutputsOfGeneralizedStraightLineProgram( +## > GeneralizedStraightLineProgram( "compose", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ) ); +## 1 +## ]]> +## +## +## <#/GAPDoc> +## +DeclareAttribute( "NrOutputsOfGeneralizedStraightLineProgram", + IsGeneralizedStraightLineProgram ); + + +############################################################################# +## +#F GeneralizedStraightLineProgram( [, ] ) +#F GeneralizedStraightLineProgram( , ) +## +## <#GAPDoc Label="GeneralizedStraightLineProgram"> +## +## GeneralizedStraightLineProgram +## +## +## +## +## In the first form, lines must be a list of lists that defines +## a unique straight line program +## (see ); +## in this case delegates to +## . +##

+## In the second form, kind must be one of the strings "union" +## or "compose", and list must be a nonempty list such that +## each of its entries is either a gslp or a list l, say, +## such that +## applied to and +## l returns a gslp. +##

+## GeneralizedStraightLineProgram( [[[1,2]]], 1 ); +## +## gap> GeneralizedStraightLineProgram( "union", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); +## +## gap> GeneralizedStraightLineProgram( "compose", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); +## +## ]]> +## +## +## <#/GAPDoc> +## +DeclareGlobalFunction( "GeneralizedStraightLineProgram" ); + + +############################################################################# +## +#O ResultOfGeneralizedStraightLineProgram( , ) +## +## <#GAPDoc Label="ResultOfGeneralizedStraightLineProgram"> +## +## +## +## +## evaluates the +## generalized straight line program +## (see ) gslp +## at the group elements in the list gens, as follows. +##

+## +## +## If gslp is a straight line program then the value of +## is returned. +## +## +## If gslp is of union kind then +## is applied to +## each of the involved generalized straight line programs, with +## second argument gens, and the concatenation of the results +## is returned. +## +## +## If gslp is of compose kind then +## is first called +## with the first involved generalized straight line program and +## gens, +## then the operation is called with the second involved +## generalized straight line program and the result of this call, +## and so on; the last such result is returned. +## +## +##

+## gens:= [ (1,2,3,4,5,6) ];; +## gap> gslp:= GeneralizedStraightLineProgram( "union", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); +## +## gap> ResultOfGeneralizedStraightLineProgram( gslp, gens ); +## [ (1,3,5)(2,4,6), (1,4)(2,5)(3,6) ] +## gap> gslp:= GeneralizedStraightLineProgram( "compose", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); +## +## gap> ResultOfGeneralizedStraightLineProgram( gslp, gens ); +## [ () ] +## ]]> +##

+## In order to avoid the introduction of unnecessary operations, +## we define just as +## a synonym of . +## +## +## <#/GAPDoc> +## +DeclareSynonym( "ResultOfGeneralizedStraightLineProgram", + ResultOfStraightLineProgram ); + +DeclareOperation( "ResultOfGeneralizedStraightLineProgram", + [ IsGeneralizedStraightLineProgram, IsHomogeneousList ] ); + + +############################################################################# +## +#A EquivalentStraightLineProgram( ) +## +## <#GAPDoc Label="EquivalentStraightLineProgram"> +## +## +## +## +## For a generalized straight line program gslp, +## returns +## a straight line program such that evaluating gslp and this +## straight line program with +## yields the same +## output, for any list of input elements. +##

+## gslp:= GeneralizedStraightLineProgram( "union", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); +## +## gap> slp:= EquivalentStraightLineProgram( gslp ); +## +## gap> Display( slp ); +## # input: +## r:= [ g1 ]; +## # program: +## # return values: +## [ r[1]^2, r[1]^3 ] +## gap> gslp:= GeneralizedStraightLineProgram( "compose", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] ); +## +## gap> slp:= EquivalentStraightLineProgram( gslp ); +## +## gap> Display( slp ); +## # input: +## r:= [ g1 ]; +## # program: +## r[2]:= r[1]^2; +## r[1]:= r[2]; +## # return values: +## [ r[1]^3 ] +## ]]> +## +## +## <#/GAPDoc> +## +DeclareAttribute( "EquivalentStraightLineProgram", + IsGeneralizedStraightLineProgram ); + + +############################################################################# +## +#E + diff --git a/lib/gslp.gi b/lib/gslp.gi new file mode 100644 index 0000000..f3f569b --- /dev/null +++ b/lib/gslp.gi @@ -0,0 +1,280 @@ +############################################################################# +## +#W gslp.gi GAP 4 package CTBlocks Thomas Breuer +## + + +############################################################################# +## +#V GeneralizedStraightLineProgramsFamily +#V GeneralizedStraightLineProgramsDefaultType +## +BindGlobal( "GeneralizedStraightLineProgramsFamily", + NewFamily( "GeneralizedStraightLineProgramsFamily", + IsGeneralizedStraightLineProgram ) ); + +BindGlobal( "GeneralizedStraightLineProgramsDefaultType", + NewType( GeneralizedStraightLineProgramsFamily, + IsGeneralizedStraightLineProgram and IsAttributeStoringRep ) ); + + +############################################################################# +## +#F GeneralizedStraightLineProgram( [, ] ) +#F GeneralizedStraightLineProgram( , ) +## +InstallGlobalFunction( GeneralizedStraightLineProgram, + function( arg ) + local kind, list, data, i, nin, nout; + + if Length( arg ) = 1 or + ( Length( arg ) = 2 and not IsString( arg[1] ) ) then + # Delegate to `StraightLineProgram'. + return CallFuncList( StraightLineProgram, arg ); + elif Length( arg ) <> 2 then + Error( "usage: GeneralizedStraightLineProgram( [, ] )", + " or GeneralizedStraightLineProgram( , )" ); + fi; + + kind:= arg[1]; + list:= arg[2]; + + if not IsList( list ) or IsEmpty( list ) then + Error( " must be a nonempty list" ); + fi; + + data:= ShallowCopy( list ); + for i in [ 1 .. Length( data ) ] do + if not IsGeneralizedStraightLineProgram( data[i] ) then + data[i]:= CallFuncList( GeneralizedStraightLineProgram, data[i] ); + fi; + od; + + if kind = "union" then + # Check that the inputs are compatible. + nin:= NrInputsOfGeneralizedStraightLineProgram( data[1] ); + nout:= NrOutputsOfGeneralizedStraightLineProgram( data[1] ); + for i in [ 2 .. Length( data ) ] do + if NrInputsOfGeneralizedStraightLineProgram( data[i] ) <> nin then + Error( "all entries of must have the same input number" ); + fi; + nout:= nout + NrOutputsOfGeneralizedStraightLineProgram( data[i] ); + od; + elif kind = "compose" then + # Check that the inputs are compatible. + nin:= NrOutputsOfGeneralizedStraightLineProgram( data[1] ); + for i in [ 2 .. Length( data ) ] do + if NrInputsOfGeneralizedStraightLineProgram( data[i] ) <> nin then + Error( "inputs and outputs for are not compatible" ); + fi; + nin:= NrOutputsOfGeneralizedStraightLineProgram( data[i] ); + od; + nout:= nin; + nin:= NrInputsOfGeneralizedStraightLineProgram( data[1] ); + else + Error( " must be one of \"union\", \"compose\"" ); + fi; + + return ObjectifyWithAttributes( rec(), + GeneralizedStraightLineProgramsDefaultType, + DataOfGeneralizedStraightLineProgram, [ kind, data ], + NrInputsOfGeneralizedStraightLineProgram, nin, + NrOutputsOfGeneralizedStraightLineProgram, nout ); + end ); + + +############################################################################# +## +#M NrOutputsOfGeneralizedStraightLineProgram( ) +## +InstallMethod( NrOutputsOfGeneralizedStraightLineProgram, + [ "IsGeneralizedStraightLineProgram" ], + function( gslp ) + local data; + + if IsStraightLineProgram( gslp ) then + data:= LinesOfStraightLineProgram( gslp ); + data:= data[ Length( data ) ]; + if ForAll( data, IsList ) then + return Length( data ); + else + return 1; + fi; + else + data:= DataOfGeneralizedStraightLineProgram( gslp ); + if data[1] = "union" then + return Sum( List( data[2], + NrOutputsOfGeneralizedStraightLineProgram ), 0 ); + else + data:= data[2]; + data:= data[ Length( data ) ]; + return NrOutputsOfGeneralizedStraightLineProgram( data ); + fi; + fi; + end ); + + +############################################################################# +## +#M ResultOfGeneralizedStraightLineProgram( , ) +## +InstallMethod( ResultOfGeneralizedStraightLineProgram, + [ "IsGeneralizedStraightLineProgram", "IsHomogeneousList" ], + function( gslp, gens ) + local data, result, prg; + + if IsStraightLineProgram( gslp ) then + # This is necessary because the method for slps was installed + # before the implication from gslps increased the rank of the filter + # `IsStraightLineProgram'. + TryNextMethod(); + fi; + + data:= DataOfGeneralizedStraightLineProgram( gslp ); + if data[1] = "union" then + result:= Concatenation( List( data[2], + x -> ResultOfGeneralizedStraightLineProgram( x, gens ) ) ); + else + result:= gens; + for prg in data[2] do + result:= ResultOfGeneralizedStraightLineProgram( prg, result ); + od; + fi; + + return result; + end ); + + +############################################################################# +## +#M EquivalentStraightLineProgram( ) +## +InstallMethod( EquivalentStraightLineProgram, + [ "IsGeneralizedStraightLineProgram" ], + function( gslp ) + local data, result, i; + + if IsStraightLineProgram( gslp ) then + return gslp; + fi; + + data:= DataOfGeneralizedStraightLineProgram( gslp ); + if data[1] = "union" then + result:= IntegratedStraightLineProgram( + List( data[2], EquivalentStraightLineProgram ) ); + else + data:= data[2]; + result:= EquivalentStraightLineProgram( data[1] ); + for i in [ 2 .. Length( data ) ] do + result:= CompositionOfStraightLinePrograms( + EquivalentStraightLineProgram( data[i] ), result ); + od; + fi; + return result; + end ); + + +############################################################################# +## +#M ViewString( ) +#M String( ) +## +## We want that 'View' shows '', +## and that 'Print' shows GAP readable information. +## (See '?Recommendations for the implementation' for the background.) +## +InstallMethod( ViewString, + [ "IsGeneralizedStraightLineProgram" ], + function( gslp ) + if IsStraightLineProgram( gslp ) then + TryNextMethod(); + fi; + return ""; + end ); + +InstallMethod( String, + [ "IsGeneralizedStraightLineProgram" ], + function( gslp ) + local data; + + if IsStraightLineProgram( gslp ) then + TryNextMethod(); + fi; + data:= DataOfGeneralizedStraightLineProgram( gslp ); + return Concatenation( "GeneralizedStraightLineProgram( \"", + data[1], "\", [ ", + JoinStringsWithSeparator( List( data[2], String ), ", " ), + " ] )" ); + end ); + +InstallMethod( String, + [ "IsStraightLineProgram" ], + slp -> Concatenation( "StraightLineProgram( ", + String( LinesOfStraightLineProgram( slp ) ), ", ", + String( NrInputsOfStraightLineProgram( slp ) ), " )" ) ); +#T eventually move this to the GAP library + + +############################################################################# +## +#M IsInternallyConsistent( ) +## +## <#GAPDoc Label="IsInternallyConsistent_gslp"> +## +## +## +## +## For a generalized straight line program gslp, +## it is checked whether all (generalized) straight line programs +## from which gslp is built are internally consistent, +## and whether their numbers of inputs and outputs are consistent and +## compatible with the numbers of inputs and outputs of gslp. +##

+## gslp:= GeneralizedStraightLineProgram( "union", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; +## gap> IsInternallyConsistent( gslp ); +## true +## gap> gslp:= GeneralizedStraightLineProgram( "compose", +## > [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; +## gap> IsInternallyConsistent( gslp ); +## true +## ]]> +## +## +## <#/GAPDoc> +## +InstallMethod( IsInternallyConsistent, + [ "IsGeneralizedStraightLineProgram" ], + function( gslp ) + local data, nrinp, constit; + + if IsStraightLineProgram( gslp ) then + TryNextMethod(); + fi; + data:= DataOfGeneralizedStraightLineProgram( gslp ); + if data[1] = "union" then + nrinp:= NrInputsOfGeneralizedStraightLineProgram( gslp ); + return ForAll( data[2], x -> IsInternallyConsistent( x ) and + NrInputsOfGeneralizedStraightLineProgram( x ) = nrinp ); + elif data[1] = "compose" then + nrinp:= NrInputsOfGeneralizedStraightLineProgram( gslp ); + for constit in data[2] do + if ( not IsInternallyConsistent( constit ) ) or + NrInputsOfGeneralizedStraightLineProgram( constit ) <> nrinp then + return false; + fi; + nrinp:= NrOutputsOfGeneralizedStraightLineProgram( constit ); + od; + return true; + else + return false; + fi; + end ); + + +############################################################################# +## +#E + diff --git a/makedoc.g b/makedoc.g index 21376e7..21d59d1 100644 --- a/makedoc.g +++ b/makedoc.g @@ -18,6 +18,7 @@ AutoDoc( rec( "iterator.xml", "record.xml", "download.xml", + "gslp.xml", "others.xml", "obsolete.xml", "transfer.xml" ], diff --git a/read.g b/read.g index ce85dce..58702c6 100644 --- a/read.g +++ b/read.g @@ -20,6 +20,7 @@ ReadPackage( "utils", "lib/number.gi" ); ReadPackage( "utils", "lib/print.gi" ); ReadPackage( "utils", "lib/record.gi" ); ReadPackage( "utils", "lib/string.gi" ); +ReadPackage( "utils", "lib/gslp.gi" ); if IsBound(DOWNLOAD_FROM_UTILS) then ReadPackage( "utils", "lib/download.gi" ); fi; From c917469290087d510870e102c9da930d83c41ce7 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Mon, 16 Mar 2026 14:23:29 +0100 Subject: [PATCH 02/11] general improvements/fixes - Use `extract_examples` when building the manual in order to create testfiles for the manual examples (and thus to make these examples relevant for code coverage), - adjust some manual examples that were not correct, - turn some not testable manual examples into `` blocks, - move `` blocks into the `` blocks of ``s, - fix a few typos. --- .gitignore | 13 +----------- doc/groups.xml | 54 +++++++++++++++++++++++------------------------ doc/intro.xml | 11 +++++----- doc/iterator.xml | 16 +++++++------- doc/lists.xml | 24 ++++++++++----------- doc/matrix.xml | 4 ++-- doc/number.xml | 28 +++++++++++------------- doc/obsolete.xml | 21 +++++++++--------- doc/others.xml | 30 +++++++++++--------------- doc/print.xml | 4 ++-- doc/record.xml | 55 ++++++++++++++++++++++++------------------------ doc/template.xml | 4 ++-- doc/transfer.xml | 8 +++---- makedoc.g | 1 + 14 files changed, 126 insertions(+), 147 deletions(-) diff --git a/.gitignore b/.gitignore index 39ec836..b5c1b6b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,18 +27,7 @@ /doc/title.xml /doc/utils.xml -tst/cset.g -tst/download.g -tst/groups.g -tst/iterator.g -tst/lcset.g -tst/lists.g -tst/matrix.g -tst/number.g -tst/others.g -tst/print.g -tst/record.g -tst/testing.g +tst/utils*.tst /gh-pages/ diff --git a/doc/groups.xml b/doc/groups.xml index 19844f9..e0cca9e 100644 --- a/doc/groups.xml +++ b/doc/groups.xml @@ -25,8 +25,6 @@ This method has been transferred from package &ResClasses;. It provides a method for Comm when the argument is a list (enclosed in square brackets), and calls the function LeftNormedComm.

- - Comm( [ (1,2), (2,3) ] ); @@ -37,6 +35,8 @@ gap> Comm(Comm(Comm(Comm((1,2),(2,3)),(3,4)),(4,5)),(5,6)); ## the same (1,5,6) ]]> + + It tests whether two elements in a group commute.

- - D12 := DihedralGroup( 12 ); @@ -58,6 +56,8 @@ gap> IsCommuting( a, b ); false ]]> + + ListOfPowers(g,exp) returns the list [g,g^2,...,g^{exp}] of powers of the element g.

- - ListOfPowers( 2, 20 ); @@ -82,6 +80,8 @@ gap> ListOfPowers( D12.2, 6 ); [ f2, f3, f2*f3, f3^2, f2*f3^2, of ... ] ]]> + + G followed by the inverses of these generators.

- - GeneratorsAndInverses( D12 ); @@ -102,6 +100,8 @@ gap> GeneratorsAndInverses( SymmetricGroup(5) ); [ (1,2,3,4,5), (1,2), (1,5,4,3,2), (1,2) ] ]]> + + @@ -119,30 +119,30 @@ The upper and lower Fitting series and the Fitting length of a solvable group are described here: https://en.wikipedia.org/wiki/Fitting_length.

- - UpperFittingSeries( D12 ); LowerFittingSeries( D12 ); -[ Group([ ]), Group([ f3, f2*f3 ]), Group([ f1, f3, f2*f3 ]) ] +[ Group([ ]), Group([ f3, f2*f3 ]), Group([ f3, f2*f3, f1 ]) ] [ D12, Group([ f3 ]), Group([ ]) ] gap> FittingLength( D12 ); 2 gap> S4 := SymmetricGroup( 4 );; gap> UpperFittingSeries( S4 ); -[ Group(()), Group([ (1,2)(3,4), (1,4)(2,3) ]), Group([ (1,2)(3,4), (1,4) - (2,3), (2,4,3) ]), Group([ (3,4), (2,3,4), (1,2)(3,4) ]) ] +[ Group(()), Group([ (1,2)(3,4), (1,4)(2,3) ]), + Group([ (2,4,3), (1,2)(3,4) ]), Group([ (3,4), (2,4,3), (1,2)(3,4) ]) ] gap> List( last, StructureDescription ); [ "1", "C2 x C2", "A4", "S4" ] gap> LowerFittingSeries( S4 ); -[ Sym( [ 1 .. 4 ] ), Alt( [ 1 .. 4 ] ), Group([ (1,4)(2,3), (1,3) - (2,4) ]), Group(()) ] +[ Sym( [ 1 .. 4 ] ), Alt( [ 1 .. 4 ] ), Group([ (1,4)(2,3), (1,2)(3,4) ]), + Group(()) ] gap> List( last, StructureDescription ); [ "S4", "A4", "C2 x C2", "1" ] gap> FittingLength( S4); 3 ]]> + + @@ -175,8 +175,6 @@ and, if necessary, converting back again to left cosets. G acts on left cosets by OnLeftInverse: (gU)^{g_0} = g_0^{-1}*(gU) = (g_0^{-1}g)U.

- - a4 := Group( (1,2,3), (2,3,4) );; SetName( a4, "a4" ); @@ -201,6 +199,8 @@ gap> lc[2]^(1,3,2) = lc[3]; true ]]> + + Inverse @@ -237,8 +237,6 @@ Its intended use is when G is a free group, and a warning is printed when this is not the case. Note that anything may happen if the resulting map is not a homomorphism!

- - G := Group( (1,2,3), (3,4,5), (5,6,7), (7,8,9) );; @@ -261,6 +259,8 @@ gap> Image( epi, (1,3,2) ); (8,9) ]]> + + @@ -292,8 +292,6 @@ There are no embeddings in this record, but it is possible to use the embeddings into the direct product, see .

- - s4 := Group( (1,2),(2,3),(3,4) );; @@ -322,6 +320,8 @@ gap> a*b in Pfi; true ]]> + + @@ -418,8 +418,6 @@ The operation IdempotentEndomorphisms(G) returns the list of these mappings obtained using IdempotentEndomorphismsData(G). The first of these is the zero map, the second is the identity.

- - gens := [ (1,2,3,4), (1,2)(3,4) ];; @@ -450,6 +448,8 @@ gap> IdempotentEndomorphisms( d8 ); [ (1,2,3,4), (1,2)(3,4) ] -> [ (1,2,3,4), (1,2)(3,4) ] ] ]]> + + The quaternion group q8 is an example of a group with a tail: there is only one subgroup in the lattice which covers the identity subgroup. @@ -471,8 +471,6 @@ Given group homomorphisms f_1 : G_1 \to G_2 and f_2 : H_1 \to H_2, this operation return the product homomorphism f_1 \times f_2 : G_1 \times G_2 \to H_1 \times H_2.

- - c4 := Group( (1,2,3,4) );; @@ -491,6 +489,8 @@ gap> ImageElm( f, (1,4,3,2)(5,7,6) ); (1,2)(3,7,5)(4,8,6) ]]> + + A_1,A_2 be groups of automorphism of groups G_1,G_2 respectively. The output of this function is a group A_1 \times A_2 of automorphisms of G_1 \times G_2.

- - c9 := Group( (1,2,3,4,5,6,7,8,9) );; @@ -522,6 +520,8 @@ gap> ImageElm( a, (1,9,8,7,6,5,4,3,2)(10,14,12,16)(11,17,13,15) ); (1,8,6,4,2,9,7,5,3)(10,16,12,14)(11,15,13,17) ]]> + + diff --git a/doc/intro.xml b/doc/intro.xml index 1c80ae6..1e91a1b 100644 --- a/doc/intro.xml +++ b/doc/intro.xml @@ -22,7 +22,8 @@ This package was first distributed as part of the &GAP; 4.8.2 distribution. The package is loaded with the command LoadPackage( "utils" ); +gap> LoadPackage( "utils" ); +true ]]>

@@ -75,16 +76,16 @@ can be found in the documentation folder. The html versions, with or without &MathJax;, may be rebuilt as follows:

- + ReadPackage( "utils", "makedoc.g" ); ]]> - +

It is possible to check that the package has been installed correctly by running the test files (which terminates the &GAP; session):

- + ReadPackage( "utils", "tst/testall.g" ); Architecture: . . . . . @@ -92,7 +93,7 @@ testing: . . . . . . . . #I No errors detected while testing ]]> - +

Note that functions listed in this manual that are currently diff --git a/doc/iterator.xml b/doc/iterator.xml index 1634ec9..cb105d5 100644 --- a/doc/iterator.xml +++ b/doc/iterator.xml @@ -40,8 +40,6 @@ The operation AllIsomorphismsNumber returns the number of isomorphisms iterated over (this is, of course, just the order of the automorphisms group). The operation AllIsomorphisms produces the list or isomorphisms.

- - G := SmallGroup( 6,1);; @@ -59,6 +57,8 @@ gap> for h in iter do Print( ImageElm( h, G.1 ) = (6,7), ", " ); od; true, false, false, true, false, false, ]]> + + LatticeSubgroups(G) and ConjugacyClassesSubgroups(lat), and then iterates over the entries in these classes.

- - c3c3 := Group( (1,2,3), (4,5,6) );; @@ -88,6 +86,8 @@ Group( [ (1,3,2)(4,5,6) ] ) Group( [ (4,5,6), (1,2,3) ] ) ]]> + + @@ -107,8 +107,6 @@ in the library -- if so, the ones here can be removed in due course. This iterator returns all pairs [x,y] where x is the output of a first iterator and y is the output of a second iterator.

- - it1 := Iterator( [ 1, 2, 3 ] );; @@ -126,6 +124,8 @@ gap> while not IsDoneIterator(iter) do Print(NextIterator(iter),"\n"); od; [ 3, 6 ] ]]> + + L = [1,2,3,\ldots] the pairs are ordered as [1,1],[1,2],[2,2],[1,3],[2,3],[3,3],\ldots.

- - L := [6,7,8,9];; @@ -166,6 +164,8 @@ gap> IsDoneIterator( pairs4 ); true ]]> + + diff --git a/doc/lists.xml b/doc/lists.xml index 1dec648..c45b000 100644 --- a/doc/lists.xml +++ b/doc/lists.xml @@ -27,8 +27,6 @@ It takes a list L of length n and outputs the list of length n-1 containing all the differences L[i]-L[i-1].

- - List( [1..12], n->n^3 ); @@ -41,6 +39,8 @@ gap> DifferencesList( last ); [ 6, 6, 6, 6, 6, 6, 6, 6, 6 ] ]]> + + @@ -55,8 +55,6 @@ They take a list L of length n and output the quotients L[i]/L[i-1] of consecutive entries in L. An error is returned if an entry is zero.

- - List( [0..10], n -> Factorial(n) ); @@ -76,6 +74,8 @@ gap> Product( last ); 10. ]]> + + @@ -91,8 +91,6 @@ The idea is that the beginning of the list may be anything, following that the same pattern needs to be repeated several times in order to be recognized as a cycle.

- - L := [1..20];; L[1]:=13;; @@ -122,6 +120,8 @@ gap> Length( C ); DifferencesList( P ); [ 12, 12, 12, 12, 12, 12, 12 ] ]]> + + k-tuple of distinct elements of a set S.

- - ## "6 aus 49" is a common lottery in Germany @@ -141,6 +139,8 @@ gap> RandomCombination( [1..49], 6 ); [ 2, 16, 24, 26, 37, 47 ] ]]> + + @@ -178,8 +178,6 @@ The operation CommonTransversal may be used to provide a common transversal for the sets of left and right cosets of a subgroup H of a group G, although a greedy algorithm is usually quicker. - -

IsCommonTransversal( d16, c4, trans ); true ]]> + + @@ -223,8 +223,6 @@ The result of BlankFreeString( obj ); is a composite of the functions String( obj ) and RemoveCharacters( obj, " " );.

- - gens := GeneratorsOfGroup( DihedralGroup(12) ); @@ -235,6 +233,8 @@ gap> BlankFreeString( gens ); "[f1,f2,f3]" ]]> + + diff --git a/doc/matrix.xml b/doc/matrix.xml index 7459da7..ad0cefa 100644 --- a/doc/matrix.xml +++ b/doc/matrix.xml @@ -38,8 +38,6 @@ with 3 blocks. M_4 is an example with three decompositions, while M_8 = M_4 \oplus M_4 has 16 decompositions (not listed).

- - M6 := [ [1,2,0,0,0,0], [3,4,0,0,0,0], [5,6,0,0,0,0], @@ -112,6 +110,8 @@ gap> L5 := DirectSumDecompositionMatrices( M5 ); [ [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 0 ] ], [ [ 6, 7 ], [ 8, 9 ] ] ] ] ]]> + + diff --git a/doc/number.xml b/doc/number.xml index 4e0770a..624d815 100644 --- a/doc/number.xml +++ b/doc/number.xml @@ -35,8 +35,6 @@ In the alternative form, when L is a list of primes, the function returns the list of all positive integers whose prime factors lie in L.

- - AllSmoothIntegers( 3, 1000 ); @@ -52,6 +50,8 @@ gap> List( [3..20], n -> Length( AllSmoothIntegers( [5,11,17], 10^n ) ) ); 1374, 1595, 1843 ] ]]> + + k entries of the list L. Note that every ordering of the entries is used so that, in the commuting case, there are bound to be repetitions.

- - AllProducts([1..4],3); @@ -79,6 +77,8 @@ gap> AllProducts( [(1,2,3),(2,3,4)], 2 ); [ (2,4,3), (1,2)(3,4), (1,3)(2,4), (1,3,2) ] ]]> + + n into distinct elements of S. Unlike RestrictedPartitions, no repetitions are allowed.

- - RestrictedPartitions( 20, [4..10] ); @@ -106,6 +104,8 @@ gap> RestrictedPartitionsWithoutRepetitions( 10^2, List([1..10], n->n^2 ) ); [ [ 100 ], [ 64, 36 ], [ 49, 25, 16, 9, 1 ] ] ]]> + + n, this function is much faster than NextPrimeInt(n)

- - n := 2^251; 3618502788666131106986593281521497120414687020801267626233049500247285301248 gap> NextProbablyPrimeInt( n ); 3618502788666131106986593281521497120414687020801267626233049500247285301313 -gap> time; -1 -gap> NextPrimeInt( n ); +gap> NextPrimeInt( n ); # same result, just faster 3618502788666131106986593281521497120414687020801267626233049500247285301313 -gap> time; -213 ]]> + + time; This function has been transferred from package &RCWA;.

This function returns an iterator which runs over the prime numbers -n ascending order; it takes an optional argument chunksize +in ascending order; it takes an optional argument chunksize which specifies the length of the interval which is sieved in one go (the default is 10^7), and which can be used to balance runtime vs. memory consumption. It is assumed that chunksize is larger than any gap between two consecutive primes within the range one intends to run the iterator over.

- - iter := PrimeNumbersIterator();; @@ -169,6 +163,8 @@ gap> p; 26861 ]]> + + diff --git a/doc/obsolete.xml b/doc/obsolete.xml index bbbf314..91d1a5f 100644 --- a/doc/obsolete.xml +++ b/doc/obsolete.xml @@ -54,6 +54,7 @@ gap> Perform( L, Display ); IsFinite IsSmallList IsGeneratorsOfMagmaWithInverses +IsAssociative IsGeneratorsOfSemigroup IsSubsetLocallyFiniteGroup gap> Perform( s3, Display ); @@ -79,13 +80,12 @@ which was included in versions from 0.41 to 0.58, has been removed since it was considered superfluous. The example shows how to print out a function.

- - ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 1, 1 ); -#I Searching Method for IsCyclic with 1 arguments: -#I Total: 7 entries -#I Method 4: ``IsCyclic'' at /Applications/gap/gap4r9/lib/grp.gi:30 , value: -36 +#I Searching Method for IsCyclic with 1 argument: +#I Total: 8 entries +#I Method 5: ``IsCyclic'' at GAPROOT/lib/grp.gi: +34 , value: 36 function( G ) ... end gap> Print( last ); function ( G ) @@ -97,13 +97,12 @@ function ( G ) return; end gap> ApplicableMethod( IsCyclic, [ Group((1,2,3),(4,5)) ], 0, 3 ); -function( <1 unnamed arguments> ) ... end +function( obj ) ... end gap> Print( last ); -function ( <> ) - <> +function ( obj ) + <> from GAPROOT/lib/oper1.g:767 end -]]> - +]]> diff --git a/doc/others.xml b/doc/others.xml index 3ccf7ea..f306775 100644 --- a/doc/others.xml +++ b/doc/others.xml @@ -30,18 +30,15 @@ except that the extension *.log is replaced by *.html. There is a sample CSS file in utils/doc/gaplog.css, which you can adjust to your taste.

- - -

- - LogTo( "triv.log" ); gap> a := 33^5; 39135393 gap> LogTo(); gap> Log2HTML( "triv.log" ); -]]> - +]]> + + @@ -50,15 +47,12 @@ gap> Log2HTML( "triv.log" ); &LaTeX; strings - This function has been transferred from package &ResClasses;.

-IntOrInfinityToLaTeX(n) returns the &LaTeX; string for n. -

- - + returns the &LaTeX; string for n.

IntOrInfinityToLaTeX( infinity ); "\\infty" ]]> + + n as a string in &LaTeX; format.

- - -

LaTeXStringFactorsInt( Factorial(12) ); "2^{10} \\cdot 3^5 \\cdot 5^2 \\cdot 7 \\cdot 11" ]]> + + @@ -126,9 +121,6 @@ Hopefully code for other types of group will be added in due course. These functions should be considered experimental, and more testing is desirable.

- - -

## permutation groups @@ -177,6 +169,8 @@ P![ 1,w^3, 2,w^2] gpN := sub

; ]]> + + diff --git a/doc/print.xml b/doc/print.xml index 73989be..518fccc 100644 --- a/doc/print.xml +++ b/doc/print.xml @@ -44,8 +44,6 @@ Alternatively, given two parameters, with the second parameter a list L of positive integers, only the items at positions in L are printed.

- - L := List( [1..20], n -> n^5 );; @@ -80,6 +78,8 @@ gap> PrintSelection( s5, 9, 11, 43 ); 42 : (1,5,2,3,4) ]]> + + diff --git a/doc/record.xml b/doc/record.xml index 9fb2d59..914249b 100644 --- a/doc/record.xml +++ b/doc/record.xml @@ -23,8 +23,6 @@ This function has been transferred from package &RCWA;. It assigns the record components of rec to global variables with the same names.

- - r := rec( a := 1, b := 2, c := 3 );; @@ -35,6 +33,8 @@ gap> [a,b,c]; [ 1, 2, 3 ] ]]> + + @@ -44,8 +44,8 @@ gap> [a,b,c]; - + This functions has been transferred by Chris Jefferson from other packages. It simplifies the handling of records which are intended to be used for expressing configuration options. @@ -64,8 +64,6 @@ If useroptions is an empty list it is treated as an empty record, and if useroptions is a list of length 1 containing a record, this record is used as useroptions.

- - defaults := rec( a := 1, b := 2, c := 3 );; @@ -88,36 +86,35 @@ Error, Too many arguments for function This function is designed to support functions with optional arguments given as a variable record, of the form function(x,y,options...). - +

In the following, very contrived, example function, PrintDimensions, the defaults are given by the variable order which takes values h, w and d having default values 1, 2 and 3. If there is a second argument, then -OptionRecordWithDefaults( order, arg[2] ); is used to cvhange the values. +OptionRecordWithDefaults( order, arg[2] ); is used to change the values. These three values then determine the order in which the three dimensions are printed using a SortParallel command. -

- 1 ) and IsRecord( arg[2] ) then - order := OptionRecordWithDefaults( order, arg[2] ); - fi; - L := [ order!.h, order!.w, order!.d ]; - len := Length( L ); - K := [ 1..len ]; - SortParallel( L, K ); - Print( "dimensions: " ); - Print( V[K[1]], " = ", dim[K[1]], ", " ); - Print( V[K[2]], " = ", dim[K[2]], ", " ); - Print( V[K[3]], " = ", dim[K[3]], "\n" ); -end;; -]]> + PrintDimensions := function( arg ) +> local nargs, dim, order, V, L, len, K, i; +> nargs := Length( arg ); +> dim := [ arg[1]!.height, arg[1]!.width, arg[1]!.depth ]; +> order := rec( h := 1, w := 2, d := 3 ); +> V := [ "height", "width", "depth" ]; +> if ( nargs > 1 ) and IsRecord( arg[2] ) then +> order := OptionRecordWithDefaults( order, arg[2] ); +> fi; +> L := [ order!.h, order!.w, order!.d ]; +> len := Length( L ); +> K := [ 1..len ]; +> SortParallel( L, K ); +> Print( "dimensions: " ); +> Print( V[K[1]], " = ", dim[K[1]], ", " ); +> Print( V[K[2]], " = ", dim[K[2]], ", " ); +> Print( V[K[3]], " = ", dim[K[3]], "\n" ); +> end;; +]]> In the example below the first call to PrintDimensions has just one parameter, mydim, so the default order is used. @@ -135,6 +132,8 @@ gap> PrintDimensions( mydim, rec( h:=3, w:=1, d:=2 ) ); dimensions: width = 31, depth = 17, height = 45 ]]> +
+
diff --git a/doc/template.xml b/doc/template.xml index 4a1dff4..ad3b093 100644 --- a/doc/template.xml +++ b/doc/template.xml @@ -25,12 +25,12 @@ These functions are in the process of being transferred from package &Home;.

They

- - + + diff --git a/doc/transfer.xml b/doc/transfer.xml index 9358ea5..17b8754 100644 --- a/doc/transfer.xml +++ b/doc/transfer.xml @@ -55,7 +55,7 @@ removed, and to specify &Utils; as a required package. (&Utils;:) Add strings "home" and "m.n" to the list UtilsPackageVersions in the file utils/lib/start.gd. - + - + While the transfers are being made, it is essential that any new versions of &Home; should be tested with the latest version of &Utils; before they are released, so as to avoid loading failures. @@ -73,7 +73,7 @@ before they are released, so as to avoid loading failures. (&Utils;:) Include the function declaration and implementation sections in suitable files, enclosed within a conditional clause of the form: - + - + OKtoReadFromUtils The function OKtoReadFromUtils returns true only if there is an installed version of &Home; diff --git a/makedoc.g b/makedoc.g index 21d59d1..09541f4 100644 --- a/makedoc.g +++ b/makedoc.g @@ -7,6 +7,7 @@ LoadPackage( "GAPDoc" ); LoadPackage( "AutoDoc" ); AutoDoc( rec( + extract_examples := true, scaffold := rec( ## MainPage := false, includes := [ "intro.xml", From f2b8d087ff0707f9408847e1ce9db260392c4133 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Mon, 16 Mar 2026 16:05:48 +0100 Subject: [PATCH 03/11] update manual tests in `testall.g` I take this as an argument that it would be better to use GAPDoc's `ExtractExamples`/`RunExamples` directly, without the need to create testfiles. --- tst/testall.g | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tst/testall.g b/tst/testall.g index 994e667..680c70c 100755 --- a/tst/testall.g +++ b/tst/testall.g @@ -14,6 +14,9 @@ if not UtilsLoadingComplete then ReadPackage( "utils", "tst/loadall.g" ); fi; +# Create/update the testfiles containing the manual examples. +ReadPackage( "utils", "makedoc.g" ); + dir := DirectoriesPackageLibrary( "utils", "tst" ); TestDirectory(dir, rec(exitGAP := true, testOptions:=rec(compareFunction := "uptowhitespace"))); From 0cb93df2c5e5b34a5f76aae36cf676aaf7ed0562 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Mon, 16 Mar 2026 16:43:50 +0100 Subject: [PATCH 04/11] make a test more robust Different GAP versions choose different generating sets for a group. --- doc/groups.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/groups.xml b/doc/groups.xml index e0cca9e..e631033 100644 --- a/doc/groups.xml +++ b/doc/groups.xml @@ -121,9 +121,12 @@ group are described here:

UpperFittingSeries( D12 ); LowerFittingSeries( D12 ); -[ Group([ ]), Group([ f3, f2*f3 ]), Group([ f3, f2*f3, f1 ]) ] -[ D12, Group([ f3 ]), Group([ ]) ] +gap> upp:= UpperFittingSeries( D12 );; +gap> List( upp, StructureDescription ); +[ "1", "C6", "D12" ] +gap> low:= LowerFittingSeries( D12 );; +gap> List( low, StructureDescription ); +[ "D12", "C3", "1" ] gap> FittingLength( D12 ); 2 gap> S4 := SymmetricGroup( 4 );; From 61ea22efeda132419d717174f9491d0ed5e07dd8 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Mon, 16 Mar 2026 20:44:30 +0100 Subject: [PATCH 05/11] adjust three example outputs The output depends on the set of loaded packages. Under the conditions of the CI tests, the output chosen now appears. --- doc/groups.xml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/doc/groups.xml b/doc/groups.xml index e631033..39b225d 100644 --- a/doc/groups.xml +++ b/doc/groups.xml @@ -401,9 +401,9 @@ true -An endomorphism f : G \to G is idempotent if f^2=f. -It has an image R \leqslant G; -is the identity map when restricted to R; +An endomorphism f\colon G \to G is idempotent if f^2 = f. +It has an image R \leq G, +is the identity map when restricted to R, and has a kernel N which has trivial intersection with R and has size |G|/|R|.

@@ -415,11 +415,11 @@ The attribute IdempotentEndomorphismsData(G) returns a record data with fields data.gens, a fixed generating set for G, and data.images a list of the non-empty outputs of IdempotentEndomorphismsWithImage(genG,R) -obtained by iterating over all subgroups of G. +obtained by iterating over all subgroups R of G.

The operation IdempotentEndomorphisms(G) returns the list of these mappings obtained using IdempotentEndomorphismsData(G). -The first of these is the zero map, the second is the identity. +The first of these is the zero map, the last is the identity.

d8 := Group( gens );; gap> SetName( d8, "d8" ); gap> c2 := Subgroup( d8, [ (2,4) ] );; gap> IdempotentEndomorphismsWithImage( gens, c2 ); -[ [ (), (2,4) ], [ (2,4), () ] ] +[ [ (2,4), () ], [ (), (2,4) ] ] gap> IdempotentEndomorphismsData( d8 ); rec( gens := [ (1,2,3,4), (1,2)(3,4) ], - images := [ [ [ (), () ] ], [ [ (), (2,4) ], [ (2,4), () ] ], - [ [ (), (1,3) ], [ (1,3), () ] ], - [ [ (), (1,2)(3,4) ], [ (1,2)(3,4), (1,2)(3,4) ] ], - [ [ (), (1,4)(2,3) ], [ (1,4)(2,3), (1,4)(2,3) ] ], + images := [ [ [ (), () ] ], [ [ (2,4), () ], [ (), (2,4) ] ], + [ [ (1,3), () ], [ (), (1,3) ] ], + [ [ (1,2)(3,4), (1,2)(3,4) ], [ (), (1,2)(3,4) ] ], + [ [ (1,4)(2,3), (1,4)(2,3) ], [ (), (1,4)(2,3) ] ], [ [ (1,2,3,4), (1,2)(3,4) ] ] ] ) gap> List( last.images, L -> Length(L) ); [ 1, 2, 2, 2, 2, 1 ] gap> IdempotentEndomorphisms( d8 ); [ [ (1,2,3,4), (1,2)(3,4) ] -> [ (), () ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (2,4) ], [ (1,2,3,4), (1,2)(3,4) ] -> [ (2,4), () ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (1,3) ], + [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (2,4) ], [ (1,2,3,4), (1,2)(3,4) ] -> [ (1,3), () ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (1,2)(3,4) ], + [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (1,3) ], [ (1,2,3,4), (1,2)(3,4) ] -> [ (1,2)(3,4), (1,2)(3,4) ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (1,4)(2,3) ], + [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (1,2)(3,4) ], [ (1,2,3,4), (1,2)(3,4) ] -> [ (1,4)(2,3), (1,4)(2,3) ], + [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (1,4)(2,3) ], [ (1,2,3,4), (1,2)(3,4) ] -> [ (1,2,3,4), (1,2)(3,4) ] ] ]]> From 3e4e5380ab7c8dbf4a005c9101929b5412c3b929 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Tue, 17 Mar 2026 11:35:40 +0100 Subject: [PATCH 06/11] change a manual example such that the output does not depend on which packages are loaded --- doc/groups.xml | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/doc/groups.xml b/doc/groups.xml index bf77903..d2b8005 100644 --- a/doc/groups.xml +++ b/doc/groups.xml @@ -408,28 +408,22 @@ gap> gens := [ (1,2,3,4), (1,2)(3,4) ];; gap> d8 := Group( gens );; gap> SetName( d8, "d8" ); gap> c2 := Subgroup( d8, [ (2,4) ] );; -gap> IdempotentEndomorphismsWithImage( gens, c2 ); -[ [ (2,4), () ], [ (), (2,4) ] ] -gap> IdempotentEndomorphismsData( d8 ); -rec( gens := [ (1,2,3,4), (1,2)(3,4) ], - images := [ [ [ (), () ] ], [ [ (2,4), () ], [ (), (2,4) ] ], - [ [ (1,3), () ], [ (), (1,3) ] ], - [ [ (1,2)(3,4), (1,2)(3,4) ], [ (), (1,2)(3,4) ] ], - [ [ (1,4)(2,3), (1,4)(2,3) ], [ (), (1,4)(2,3) ] ], - [ [ (1,2,3,4), (1,2)(3,4) ] ] ] ) -gap> List( last.images, L -> Length(L) ); +gap> SortedList( IdempotentEndomorphismsWithImage( gens, c2 ) ); +[ [ (), (2,4) ], [ (2,4), () ] ] +gap> data:= IdempotentEndomorphismsData( d8 );; +gap> data.images[1]; +[ [ (), () ] ] +gap> List( data.images, Length ); [ 1, 2, 2, 2, 2, 1 ] -gap> IdempotentEndomorphisms( d8 ); -[ [ (1,2,3,4), (1,2)(3,4) ] -> [ (), () ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (2,4), () ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (2,4) ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (1,3), () ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (1,3) ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (1,2)(3,4), (1,2)(3,4) ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (1,2)(3,4) ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (1,4)(2,3), (1,4)(2,3) ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (), (1,4)(2,3) ], - [ (1,2,3,4), (1,2)(3,4) ] -> [ (1,2,3,4), (1,2)(3,4) ] ] +gap> all:= IdempotentEndomorphisms( d8 );; +gap> Length( all ); +10 +gap> all[1]; +[ (1,2,3,4), (1,2)(3,4) ] -> [ (), () ] +gap> Size( Image( all[1] ) ); +1 +gap> Last( all ) = IdentityMapping( d8 ); +true ]]> From 042eefb90bf34ee11d8f05bad7a25f3dc7a82b4e Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Tue, 17 Mar 2026 14:55:16 +0100 Subject: [PATCH 07/11] increase code coverage --- lib/gslp.gi | 38 +++++++++++--------------------- tst/gslp.tst | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 26 deletions(-) create mode 100644 tst/gslp.tst diff --git a/lib/gslp.gi b/lib/gslp.gi index f3f569b..3ead097 100644 --- a/lib/gslp.gi +++ b/lib/gslp.gi @@ -93,23 +93,16 @@ InstallMethod( NrOutputsOfGeneralizedStraightLineProgram, local data; if IsStraightLineProgram( gslp ) then - data:= LinesOfStraightLineProgram( gslp ); - data:= data[ Length( data ) ]; + # The value is in general not set in the construction. + data:= Last( LinesOfStraightLineProgram( gslp ) ); if ForAll( data, IsList ) then return Length( data ); else return 1; fi; else - data:= DataOfGeneralizedStraightLineProgram( gslp ); - if data[1] = "union" then - return Sum( List( data[2], - NrOutputsOfGeneralizedStraightLineProgram ), 0 ); - else - data:= data[2]; - data:= data[ Length( data ) ]; - return NrOutputsOfGeneralizedStraightLineProgram( data ); - fi; + # The value should get set in the construction. + Error( "attribute value got lost?" ); fi; end ); @@ -123,12 +116,8 @@ InstallMethod( ResultOfGeneralizedStraightLineProgram, function( gslp, gens ) local data, result, prg; - if IsStraightLineProgram( gslp ) then - # This is necessary because the method for slps was installed - # before the implication from gslps increased the rank of the filter - # `IsStraightLineProgram'. - TryNextMethod(); - fi; + # We may assume that the 'IsStraightLineProgram' method has higher rank. + Assert( 1, not IsStraightLineProgram( gslp ) ); data:= DataOfGeneralizedStraightLineProgram( gslp ); if data[1] = "union" then @@ -185,21 +174,18 @@ InstallMethod( EquivalentStraightLineProgram, ## InstallMethod( ViewString, [ "IsGeneralizedStraightLineProgram" ], - function( gslp ) - if IsStraightLineProgram( gslp ) then - TryNextMethod(); - fi; - return ""; - end ); + gslp -> "" ); + +InstallMethod( ViewString, + [ "IsStraightLineProgram" ], + slp -> "" ); +#T eventually move this to the GAP library InstallMethod( String, [ "IsGeneralizedStraightLineProgram" ], function( gslp ) local data; - if IsStraightLineProgram( gslp ) then - TryNextMethod(); - fi; data:= DataOfGeneralizedStraightLineProgram( gslp ); return Concatenation( "GeneralizedStraightLineProgram( \"", data[1], "\", [ ", diff --git a/tst/gslp.tst b/tst/gslp.tst new file mode 100644 index 0000000..5d4f7bf --- /dev/null +++ b/tst/gslp.tst @@ -0,0 +1,61 @@ +#@local prg, data +############################################################################ +## +#W gslp.tst Utils Package Thomas Breuer +## +#Y Copyright (C) 2026, The GAP Group +## +gap> START_TEST( "gslp.tst" ); + +# +gap> ReadPackage( "utils", "tst/loadall.g" );; +gap> UtilsLoadingComplete; +true + +# test inconsistent input for `GeneralizedStraightLineProgram` +gap> GeneralizedStraightLineProgram( "union", [[[1,2]]], 1 ); +Error, usage: GeneralizedStraightLineProgram( [, ] ) or General\ +izedStraightLineProgram( , ) +gap> GeneralizedStraightLineProgram( "union", [] ); +Error, must be a nonempty list +gap> GeneralizedStraightLineProgram( "union", +> [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 2 ] ] ); +Error, all entries of must have the same input number +gap> GeneralizedStraightLineProgram( "compose", +> [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 2 ] ] ); +Error, inputs and outputs for are not compatible +gap> GeneralizedStraightLineProgram( "other", [[[1,2]]] ); +Error, must be one of "union", "compose" + +# test cases of `NrOutputsOfGeneralizedStraightLineProgram` +gap> prg:= StraightLineProgram( [ [1,2,2,3], [3,-1] ], 2 );; +gap> NrOutputsOfGeneralizedStraightLineProgram( prg ); +1 + +# test `false` cases of `IsInternallyConsistent` +gap> prg:= GeneralizedStraightLineProgram( "compose", +> [ [ [[[1,2]]], 1 ], [ [[[1,3]]], 1 ] ] );; +gap> ResetFilterObj( prg, HasNrInputsOfGeneralizedStraightLineProgram ); +gap> SetNrInputsOfGeneralizedStraightLineProgram( prg, 3 ); +gap> IsInternallyConsistent( prg ); +false +gap> data:= ShallowCopy( DataOfGeneralizedStraightLineProgram( prg ) );; +gap> data[1]:= "other";; +gap> ResetFilterObj( prg, HasDataOfGeneralizedStraightLineProgram ); +gap> SetDataOfGeneralizedStraightLineProgram( prg, data ); +gap> IsInternallyConsistent( prg ); +false + +# `ViewString` and `String` +gap> ViewString( StraightLineProgram( [[[1,2]]], 1 ) ); +"" +gap> ViewString( GeneralizedStraightLineProgram( "union", [ [[[1,2]]] ] ) ); +"" +gap> String( StraightLineProgram( [[[1,2]]], 1 ) ); +"StraightLineProgram( [ [ [ 1, 2 ] ] ], 1 )" +gap> String( GeneralizedStraightLineProgram( "union", [ [[[1,2]]] ] ) ); +"GeneralizedStraightLineProgram( \"union\", [ StraightLineProgram( [ [ 1, 2 ] \ +], 1 ) ] )" + +# +gap> STOP_TEST( "gslp.tst" ); From 5aa3b08aac9508dfd649a4e28e0be37986435009 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Tue, 17 Mar 2026 21:58:05 +0100 Subject: [PATCH 08/11] remove a duplicate test (Perhaps this helps to avoid the test failures.) --- tst/download.tst | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/tst/download.tst b/tst/download.tst index 4718e44..cb19c10 100644 --- a/tst/download.tst +++ b/tst/download.tst @@ -5,7 +5,9 @@ ## #Y Copyright (C) 2022, The GAP Group ## +gap> START_TEST( "download.tst" ); +## gap> ReadPackage( "utils", "tst/loadall.g" );; gap> UtilsLoadingComplete; true @@ -97,19 +99,5 @@ gap> res1:= Download( "https://httpbun.com/delay/3", rec( maxTime:= 5 ) );; gap> res1.success = true; true -## the example 9.1.1 from the manual -gap> url:= "https://www.gap-system.org/index.html";; -gap> res1:= Download( url );; -gap> res1.success; -true -gap> IsBound( res1.result ) and IsString( res1.result ); -true -gap> res2:= Download( Concatenation( url, "xxx" ) );; -gap> res2.success; -false -gap> IsBound( res2.error ) and IsString( res2.error ); -true - -############################################################################# ## -#E +gap> STOP_TEST( "download.tst" ); From 6a5467b29a7e96f0acd868782b19ff0038a8e213 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Thu, 19 Mar 2026 23:07:31 +0100 Subject: [PATCH 09/11] address comments --- doc/gslp.xml | 38 ++++++++++++++++++++++---------------- lib/gslp.gd | 2 +- lib/gslp.gi | 2 +- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/doc/gslp.xml b/doc/gslp.xml index 6bfa9f6..95fe2c9 100644 --- a/doc/gslp.xml +++ b/doc/gslp.xml @@ -2,7 +2,7 @@ - + @@ -11,8 +11,8 @@ Generalized Straight Line Programs -The functions described in this chapter have been written by Thomas Breuer, -for version 0.94 of Utils. +The functions described in this chapter have been written by Thomas Breuer, +they are available since Utils 0.94.

Generalized straight line programs (in the following abbreviated as gslps) are a generalization of the straight line programs @@ -21,19 +21,25 @@ see . Like the latter objects, gslps describe an efficient way for evaluating an abstract word at concrete generators. The difference is that gslps can be built -from existing (generalized) straight line programs. -So the advantages of using gslps are that +from existing (generalized) straight line programs, +whereas a straight line program is given by an explicit list of +instructions (see ). +So the advantages of using a gslp instead of constructing an equivalent +straight line program (see ) +are that

- available objects are reused, + available objects (the building blocks of the gslp) are reused, - the internal structure is retained, and + the internal structure of the gslp is retained + (one can access the building blocks if one wants), and - intermediate results of an evaluation are not kept longer than - until the relevant straight line program inside is evaluated. + in the evaluation of a gslp, the intermediate results that arise in + a building block of the gslp can be garbage collected + as soon as the evaluation of this building block has finished.

@@ -50,9 +56,9 @@ This object has exactly one of the following forms. It is of union kind, that is, the defining data are - a nonempty list of gslps, - and evaluation at some group elements means to evaluate these - defining programs at these group elements, + a nonempty list l of gslps, + and evaluation at some group elements means to evaluate the + gslps in l at these group elements, and to return the concatenation of the results. @@ -61,7 +67,7 @@ This object has exactly one of the following forms. and evaluation at some group elements means to evaluate the first of them at these elements, then to evaluate the second of them at the result of the first - evaluations, + evaluation, and so on, and to return the last result. @@ -82,10 +88,10 @@ for a group G is given. we may be interested in computing standard generators l'' for M from l'.

- For that, a second straight line program can be needed, + For that, a second straight line program may be needed, and it makes sense to encode the computation of l'' from l via a gslp of compose kind. - + Suppose that we are in fact interested in a downward extension H of G, and that \pi is the natural epimorphism @@ -107,7 +113,7 @@ for a group G is given. Gslps can be constructed using . -

+

Defining attributes for gslps are and . diff --git a/lib/gslp.gd b/lib/gslp.gd index dfa2c47..78c0a0b 100644 --- a/lib/gslp.gd +++ b/lib/gslp.gd @@ -1,6 +1,6 @@ ############################################################################# ## -#W gslp.gd GAP 4 package CTBlocks Thomas Breuer +#W gslp.gd GAP 4 package utils Thomas Breuer ## ## A remark on the name generalized straight line program: ## We could have taken the viewpoint that these objects are the ones that diff --git a/lib/gslp.gi b/lib/gslp.gi index 3ead097..ef78548 100644 --- a/lib/gslp.gi +++ b/lib/gslp.gi @@ -1,6 +1,6 @@ ############################################################################# ## -#W gslp.gi GAP 4 package CTBlocks Thomas Breuer +#W gslp.gi GAP 4 package utils Thomas Breuer ## From 94b612b85cfd29fb59b94bae1fe77c1c4bd981df Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Thu, 19 Mar 2026 23:17:04 +0100 Subject: [PATCH 10/11] fix a typo --- doc/gslp.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gslp.xml b/doc/gslp.xml index 95fe2c9..191854f 100644 --- a/doc/gslp.xml +++ b/doc/gslp.xml @@ -23,7 +23,7 @@ an abstract word at concrete generators. The difference is that gslps can be built from existing (generalized) straight line programs, whereas a straight line program is given by an explicit list of -instructions (see ). +instructions (see ). So the advantages of using a gslp instead of constructing an equivalent straight line program (see ) are that From cbcf781ba128ae69eeb9be493110d13dfc84a3b4 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Wed, 25 Mar 2026 13:21:04 +0100 Subject: [PATCH 11/11] address a comment that I had missed --- doc/gslp.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/gslp.xml b/doc/gslp.xml index 191854f..00d40fa 100644 --- a/doc/gslp.xml +++ b/doc/gslp.xml @@ -63,10 +63,10 @@ This object has exactly one of the following forms. It is of compose kind, that is, the defining data are - a nonempty list of gslps, + a nonempty list l of gslps, and evaluation at some group elements means - to evaluate the first of them at these elements, - then to evaluate the second of them at the result of the first + to evaluate l[1] at these elements, + then to evaluate l[2] at the result of the first evaluation, and so on, and to return the last result.