Skip to content

Commit

Permalink
Unify argument checking for some free objects
Browse files Browse the repository at this point in the history
In particular, unify argument processing/error checking in:
* FreeSemigroup
* FreeMonoid
* FreeMagma
* FreeMagmaWithOne
* FreeGroup

Resolves #1385.
  • Loading branch information
wilfwilson committed May 10, 2021
1 parent fb4174c commit b0a76a4
Show file tree
Hide file tree
Showing 12 changed files with 758 additions and 367 deletions.
2 changes: 1 addition & 1 deletion lib/grpfp.gi
Original file line number Diff line number Diff line change
Expand Up @@ -5729,4 +5729,4 @@ InstallMethod( IndependentGeneratorsOfAbelianGroup,
[ IsFpGroup and IsAbelian ],
IndependentGeneratorsOfMaximalAbelianQuotientOfFpGroup );

BindGlobal("TRIVIAL_FP_GROUP",FreeGroup(0,"TrivGp")/[]);
BindGlobal("TRIVIAL_FP_GROUP", FreeGroup(0) / [] );
90 changes: 13 additions & 77 deletions lib/grpfree.gi
Original file line number Diff line number Diff line change
Expand Up @@ -424,80 +424,18 @@ InstallMethod( GeneratorsSmallest,
##
InstallGlobalFunction( FreeGroup, function ( arg )
local names, # list of generators names
opt,
zarg,
lesy, # filter for letter or syllable words family
F, # family of free group element objects
G; # free group, result
G, # free group, result
processed;

if ValueOption("FreeGroupFamilyType")="syllable" then
lesy:=IsSyllableWordsFamily; # optional -- used in PQ
else
lesy:=IsLetterWordsFamily; # default
fi;
if IsFilter(arg[1]) then
lesy:=arg[1];
zarg:=arg{[2..Length(arg)]};
else
zarg:=arg;
fi;

# Get and check the argument list, and construct names if necessary.
if Length( zarg ) = 1 and zarg[1] = infinity then
names:= InfiniteListOfNames( "f" );
elif Length( zarg ) = 2 and zarg[1] = infinity then
names:= InfiniteListOfNames( zarg[2] );
elif Length( zarg ) = 3 and zarg[1] = infinity then
names:= InfiniteListOfNames( zarg[2], zarg[3] );
elif Length( zarg ) = 1 and IsInt( zarg[1] ) and 0 <= zarg[1] then
names:= List( [ 1 .. zarg[1] ],
i -> Concatenation( "f", String(i) ) );
MakeImmutable( names );
elif Length( zarg ) = 2 and IsInt( zarg[1] ) and 0 <= zarg[1] then
names:= List( [ 1 .. zarg[1] ],
i -> Concatenation( zarg[2], String(i) ) );
elif Length( zarg ) = 1 and IsList( zarg[1] ) and IsEmpty( zarg[1] ) then
names:= zarg[1];
elif 1 <= Length( zarg ) and ForAll( zarg, IsString ) then
names:= zarg;
elif Length( zarg ) = 1 and IsList( zarg[1] )
and ForAll( zarg[1], IsString ) then
names:= zarg[1];
else
Error("usage: FreeGroup(<name1>,<name2>..) or FreeGroup(<rank>)");
fi;

opt:=ValueOption("generatorNames");
if opt<>fail then
if IsString(opt) then
names:= List( [ 1 .. Length(names) ],
i -> Concatenation( opt, String(i) ) );
elif IsList(opt) and ForAll(opt,IsString)
and Length(names)<=Length(opt) then
names:=opt{[1..Length(names)]};
MakeImmutable( names );
else
Error("Cannot process `generatorNames` option");
fi;
fi;

# deal with letter words family types
if lesy=IsLetterWordsFamily then
if Length(names)>127 then
lesy:=IsWLetterWordsFamily;
else
lesy:=IsBLetterWordsFamily;
fi;
elif lesy=IsBLetterWordsFamily and Length(names)>127 then
lesy:=IsWLetterWordsFamily;
fi;
processed := FreeAlgebraCreatorArgumentProcessor( "FreeGroup", "f", arg );
names := processed.names;

# Construct the family of element objects of our group.
F:= NewFamily( "FreeGroupElementsFamily", IsAssocWordWithInverse
and IsElementOfFreeGroup,
CanEasilySortElements, # the free group can.
CanEasilySortElements # the free group can.
and lesy);
F := NewFamily( "FreeGroupElementsFamily",
IsAssocWordWithInverse and IsElementOfFreeGroup,
CanEasilySortElements,
CanEasilySortElements and processed.lesy );

# Install the data (names, no. of bits available for exponents, types).
StoreInfoFreeMagma( F, names, IsAssocWordWithInverse
Expand All @@ -511,22 +449,20 @@ InstallGlobalFunction( FreeGroup, function ( arg )
i -> ObjByExtRep( F, 1, 1, [ i, 1 ] ) ) );
else
G:= GroupByGenerators( InfiniteListOfGenerators( F ) );
SetIsFinitelyGeneratedGroup( G, false );
fi;

# Store the whole group in the family.
SetIsWholeFamily( G, true );
FamilyObj(G)!.wholeGroup := G;
F!.freeGroup:=G;
SetFilterObj(G,IsGroupOfFamily);

# Store whether the group is trivial / abelian / solvable
SetIsFinitelyGeneratedGroup( G, IsFinite ( names ) );
SetIsTrivial( G, Length( names ) = 0 );
SetIsAbelian( G, Length( names ) <= 1 );
SetIsSolvableGroup( G, Length( names ) <= 1 );

# Store the whole group in the family.
FamilyObj(G)!.wholeGroup := G;
F!.freeGroup:=G;
SetFilterObj(G,IsGroupOfFamily);

# Return the free group.
return G;
end );

Expand Down
48 changes: 27 additions & 21 deletions lib/magma.gd
Original file line number Diff line number Diff line change
Expand Up @@ -726,34 +726,40 @@ InParentFOA( "Centralizer", IsMagma, IsObject, DeclareAttribute );
DeclareOperation( "SquareRoots", [ IsMagma, IsMultiplicativeElement ] );


################################################################################
##
DeclareGlobalFunction("FreeAlgebraCreatorArgumentProcessor");


#############################################################################
##
#F FreeMagma( <rank>[, <name>] )
#F FreeMagma( <name1>, <name2>, ... )
#F FreeMagma( <names> )
#F FreeMagma( infinity, <name>, <init> )
#F FreeMagma( [ <wfilt>, ]<rank>[, <name>] )
#F FreeMagma( [ <wfilt>, ]<name1>, <name2>, ... )
#F FreeMagma( [ <wfilt>, ]<names> )
#F FreeMagma( [ <wfilt>, ]infinity[, <name>[, <init>]] )
##
## <#GAPDoc Label="FreeMagma">
## <ManSection>
## <Heading>FreeMagma</Heading>
## <Func Name="FreeMagma" Arg='rank[, name]'
## <Func Name="FreeMagma" Arg='[wfilt, ]rank[, name]'
## Label="for given rank"/>
## <Func Name="FreeMagma" Arg='name1, name2, ...'
## <Func Name="FreeMagma" Arg='[wfilt, ]name1, name2, ...'
## Label="for various names"/>
## <Func Name="FreeMagma" Arg='names'
## <Func Name="FreeMagma" Arg='[wfilt, ]names'
## Label="for a list of names"/>
## <Func Name="FreeMagma" Arg='infinity, name, init'
## <Func Name="FreeMagma" Arg='[wfilt, ]infinity[, name[, init]]'
## Label="for infinitely many generators"/>
##
## <Description>
## Called with a positive integer <A>rank</A>,
## <Ref Func="FreeMagma" Label="for given rank"/> returns
## a free magma on <A>rank</A> generators.
## If the optional argument <A>name</A> is given then the generators are
## If the optional argument <A>name</A> (a string) is given,
## then the generators are
## printed as <A>name</A><C>1</C>, <A>name</A><C>2</C> etc.,
## that is, each name is the concatenation of the string <A>name</A> and an
## integer from <C>1</C> to <A>range</A>.
## The default for <A>name</A> is the string <C>"m"</C>.
## integer from <C>1</C> to <A>rank</A>.
## The default for <A>name</A> is the string <C>"x"</C>.
## <P/>
## Called in the second form,
## <Ref Func="FreeMagma" Label="for various names"/> returns
Expand All @@ -780,21 +786,21 @@ DeclareGlobalFunction( "FreeMagma" );

#############################################################################
##
#F FreeMagmaWithOne( <rank>[, <name>] )
#F FreeMagmaWithOne( <name1>, <name2>, ... )
#F FreeMagmaWithOne( <names> )
#F FreeMagmaWithOne( infinity, <name>, <init> )
#F FreeMagmaWithOne( [ <wfilt>, ]<rank>[, <name>] )
#F FreeMagmaWithOne( [ <wfilt>, ]<name1>, <name2>, ... )
#F FreeMagmaWithOne( [ <wfilt>, ]<names> )
#F FreeMagmaWithOne( [ <wfilt>, ]infinity[, <name>[, <init>]] )
##
## <#GAPDoc Label="FreeMagmaWithOne">
## <ManSection>
## <Heading>FreeMagmaWithOne</Heading>
## <Func Name="FreeMagmaWithOne" Arg='rank[, name]'
## <Func Name="FreeMagmaWithOne" Arg='[wfilt, ]rank[, name]'
## Label="for given rank"/>
## <Func Name="FreeMagmaWithOne" Arg='name1, name2, ...'
## <Func Name="FreeMagmaWithOne" Arg='[wfilt, ]name1, name2, ...'
## Label="for various names"/>
## <Func Name="FreeMagmaWithOne" Arg='names'
## <Func Name="FreeMagmaWithOne" Arg='[wfilt, ]names'
## Label="for a list of names"/>
## <Func Name="FreeMagmaWithOne" Arg='infinity, name, init'
## <Func Name="FreeMagmaWithOne" Arg='[wfilt, ]infinity[, name[, init]]'
## Label="for infinitely many generators"/>
##
## <Description>
Expand All @@ -804,8 +810,8 @@ DeclareGlobalFunction( "FreeMagma" );
## If the optional argument <A>name</A> is given then the generators are
## printed as <A>name</A><C>1</C>, <A>name</A><C>2</C> etc.,
## that is, each name is the concatenation of the string <A>name</A> and an
## integer from <C>1</C> to <A>range</A>.
## The default for <A>name</A> is the string <C>"m"</C>.
## integer from <C>1</C> to <A>rank</A>.
## The default for <A>name</A> is the string <C>"x"</C>.
## <P/>
## Called in the second form,
## <Ref Func="FreeMagmaWithOne" Label="for various names"/> returns
Expand Down
Loading

0 comments on commit b0a76a4

Please sign in to comment.