Skip to content

Commit d35871e

Browse files
committed
Disallow duplicate names gens for magmas, semigroups, groups, etc
1 parent 658b58a commit d35871e

File tree

12 files changed

+71
-28
lines changed

12 files changed

+71
-28
lines changed

doc/ref/grplib.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ It is possible to influence this naming with the option <C>generatorNames</C>,
106106
see Section&nbsp;<Ref Sect="Function Call With Options"/>.
107107
If this option holds a string, then the generators are named with this
108108
string and sequential numbers starting with <C>1</C>.
109-
If this option holds a list of sufficient length consisting of
109+
If this option holds a list of sufficient length consisting of distinct
110110
nonempty strings, then the generator names are taken from this list, in order.
111111
<P/>
112112
<Example><![CDATA[

lib/algebra.gd

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,7 +1491,8 @@ DeclareOperation( "AsLieAlgebra", [ IsDivisionRing, IsCollection ] );
14911491
## <Description>
14921492
## is a free (nonassociative) algebra of rank <A>rank</A>
14931493
## over the division ring <A>R</A>.
1494-
## Here <A>name</A>, and <A>name1</A>, <A>name2</A>, ... are optional strings
1494+
## Here <A>name</A>, and <A>name1</A>, <A>name2</A>, ... are optional
1495+
## distinct nonempty strings
14951496
## that can be used to provide names for the generators.
14961497
## <Example><![CDATA[
14971498
## gap> A:= FreeAlgebra( Rationals, "a", "b" );
@@ -1523,7 +1524,8 @@ DeclareGlobalFunction( "FreeAlgebra" );
15231524
## <Description>
15241525
## is a free (nonassociative) algebra-with-one of rank <A>rank</A>
15251526
## over the division ring <A>R</A>.
1526-
## Here <A>name</A>, and <A>name1</A>, <A>name2</A>, ... are optional strings
1527+
## Here <A>name</A>, and <A>name1</A>, <A>name2</A>, ... are optional
1528+
## distinct nonempty strings
15271529
## that can be used to provide names for the generators.
15281530
## <Example><![CDATA[
15291531
## gap> A:= FreeAlgebraWithOne( Rationals, 4, "q" );

lib/alglie.gd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,7 @@ DeclareAttribute(
12531253
## <C>FreeLieAlgebra( <A>R</A>, <A>name1</A>, <A>name2</A>,...)</C> returns
12541254
## a free Lie algebra over <A>R</A> with generators named <A>name1</A>,
12551255
## <A>name2</A>, and so on.
1256+
## Note that any provided generator names must be distinct.
12561257
## The elements of a free Lie algebra are written on the Hall-Lyndon
12571258
## basis.
12581259
## <Example><![CDATA[

lib/grpfree.gd

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,14 @@ DeclareSynonym( "IsElementOfFreeGroupFamily",IsAssocWordWithInverseFamily );
7979
## </Item>
8080
## <Mark>2: For given generator names</Mark>
8181
## <Item>
82-
## Called with various nonempty strings,
82+
## Called with various distinct nonempty strings,
8383
## <Ref Func="FreeGroup" Label="for various names"/> returns
8484
## a free group on as many generators as arguments, which are labelled
8585
## <A>name1</A>, <A>name2</A>, etc.
8686
## </Item>
8787
## <Mark>3: For a given list of generator names</Mark>
8888
## <Item>
89-
## Called with a finite list <A>names</A> of
89+
## Called with a finite duplicate-free list <A>names</A> of
9090
## nonempty strings,
9191
## <Ref Func="FreeGroup" Label="for a list of names"/> returns
9292
## a free group on <C>Length(<A>names</A>)</C> generators, whose
@@ -104,11 +104,12 @@ DeclareSynonym( "IsElementOfFreeGroupFamily",IsAssocWordWithInverseFamily );
104104
## The optional argument <A>name</A> must be a string; its default value is
105105
## <C>"f"</C>,
106106
## and the optional argument <A>init</A> must be a finite list of
107-
## nonempty strings; its default value is an empty list.
107+
## distinct nonempty strings; its default value is an empty list.
108108
## The generators are initially labelled according to the list <A>init</A>,
109109
## followed by
110110
## <A>name</A><C>i</C> for each <C>i</C> in the range from
111-
## <C>Length(<A>init</A>)+1</C> to <K>infinity</K>.
111+
## <C>Length(<A>init</A>)+1</C> to <K>infinity</K>; such a label is not
112+
## allowed to appear in <A>init</A>.
112113
## </Item>
113114
## </List>
114115
## If the optional first argument <A>wfilt</A> is given, then it must be either

lib/magma.gd

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -818,15 +818,15 @@ DeclareGlobalFunction("FreeXArgumentProcessor");
818818
## </Item>
819819
## <Mark>2: For given generator names</Mark>
820820
## <Item>
821-
## Called with various (at least one) nonempty strings,
821+
## Called with various (one or more) distinct nonempty strings,
822822
## <Ref Func="FreeMagma" Label="for various names"/> returns
823823
## a free magma on as many generators as arguments, which are labelled
824824
## <A>name1</A>, <A>name2</A>, etc.
825825
## </Item>
826826
## <Mark>3: For a given list of generator names</Mark>
827827
## <Item>
828828
## Called with a finite nonempty list <A>names</A> of
829-
## nonempty strings,
829+
## distinct nonempty strings,
830830
## <Ref Func="FreeMagma" Label="for a list of names"/> returns
831831
## a free magma on <C>Length(<A>names</A>)</C> generators, whose
832832
## <C>i</C>-th generator is labelled <A>names</A><C>[i]</C>.
@@ -843,11 +843,12 @@ DeclareGlobalFunction("FreeXArgumentProcessor");
843843
## The optional argument <A>name</A> must be a string; its default value is
844844
## <C>"x"</C>,
845845
## and the optional argument <A>init</A> must be a finite list of
846-
## nonempty strings; its default value is an empty list.
846+
## distinct nonempty strings; its default value is an empty list.
847847
## The generators are initially labelled according to the list <A>init</A>,
848848
## followed by
849849
## <A>name</A><C>i</C> for each <C>i</C> in the range from
850-
## <C>Length(<A>init</A>)+1</C> to <K>infinity</K>.
850+
## <C>Length(<A>init</A>)+1</C> to <K>infinity</K>; such a label is not
851+
## allowed to appear in <A>init</A>.
851852
## </Item>
852853
## </List>
853854
## <Example><![CDATA[
@@ -931,15 +932,15 @@ DeclareGlobalFunction( "FreeMagma" );
931932
## </Item>
932933
## <Mark>2: For given generator names</Mark>
933934
## <Item>
934-
## Called with various nonempty strings,
935+
## Called with various (one or more) distinct nonempty strings,
935936
## <Ref Func="FreeMagmaWithOne" Label="for various names"/> returns
936937
## a free magma-with-one on as many generators as arguments, which are
937938
## labelled <A>name1</A>, <A>name2</A>, etc.
938939
## </Item>
939940
## <Mark>3: For a given list of generator names</Mark>
940941
## <Item>
941942
## Called with a finite list <A>names</A> of
942-
## nonempty strings,
943+
## distinct nonempty strings,
943944
## <Ref Func="FreeMagmaWithOne" Label="for a list of names"/> returns
944945
## a free magma-with-one on <C>Length(<A>names</A>)</C> generators, whose
945946
## <C>i</C>-th generator is labelled <A>names</A><C>[i]</C>.
@@ -956,11 +957,12 @@ DeclareGlobalFunction( "FreeMagma" );
956957
## The optional argument <A>name</A> must be a string; its default value is
957958
## <C>"x"</C>,
958959
## and the optional argument <A>init</A> must be a finite list of
959-
## nonempty strings; its default value is an empty list.
960+
## distinct nonempty strings; its default value is an empty list.
960961
## The generators are initially labelled according to the list <A>init</A>,
961962
## followed by
962963
## <A>name</A><C>i</C> for each <C>i</C> in the range from
963-
## <C>Length(<A>init</A>)+1</C> to <K>infinity</K>.
964+
## <C>Length(<A>init</A>)+1</C> to <K>infinity</K>; such a label is not
965+
## allowed to appear in <A>init</A>.
964966
## </Item>
965967
## </List>
966968
## <Example><![CDATA[

lib/mgmfree.gi

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ function(
291291
rank, # Length( names )
292292
opt,
293293
init,
294+
word,
294295
x, y1, y2;
295296

296297
# Set up defaults.
@@ -339,13 +340,14 @@ function(
339340
MakeImmutable( names );
340341
elif ( IsList and IsFinite )( opt ) and rank <= Length( opt )
341342
and ForAll( [ 1 .. rank ],
342-
s -> IsString( opt[s] ) and not IsEmpty( opt[s] ) ) then
343+
s -> IsString( opt[s] ) and not IsEmpty( opt[s] ) )
344+
and IsDuplicateFreeList( opt{[ 1 .. rank ]} ) then
343345
names := MakeImmutable( opt{[ 1 .. rank ]} );
344346
else
345347
ErrorNoReturn( Concatenation(
346348
"Cannot process the `generatorNames` option: ",
347349
"the value must be either a single string, or a list ",
348-
"of sufficiently many nonempty strings ",
350+
"of sufficiently many distinct nonempty strings ",
349351
"(at least ", String( rank ), ", in this case)" ) );
350352
fi;
351353

@@ -378,6 +380,8 @@ function(
378380
err := "there must be only finitely many names";
379381
elif not ForAll( names, s -> IsString( s ) and not IsEmpty( s ) ) then
380382
err := "the names must be nonempty strings";
383+
elif not IsDuplicateFreeList( names ) then
384+
err := "the names must be distinct";
381385
fi;
382386

383387
# Validate call of form: func( infinity[, <name>][, <init>] ).
@@ -404,8 +408,22 @@ function(
404408
err := "<name> must be a string";
405409
elif not ( IsList( init ) and IsFinite( init ) ) then
406410
err := "<init> must be a finite list";
411+
elif not IsDuplicateFreeList( init ) then
412+
err := "<init> must be duplicate-free";
407413
elif not ForAll( init, s -> IsString( s ) and not IsEmpty( s ) ) then
408414
err := "<init> must consist of nonempty strings";
415+
else
416+
for word in init do
417+
if StartsWith( word, name ) then
418+
x := word{[ Length( name ) + 1 .. Length( word ) ]};
419+
if not IsEmpty( x ) and ForAll( x, IsDigitChar )
420+
and Int( x ) > Length( init ) then
421+
err := "no member of <init> may repeat any of the infinitely many ";
422+
Append( err, "generators that begin with <name>" );
423+
break;
424+
fi;
425+
fi;
426+
od;
409427
fi;
410428
if IsEmpty( err ) then
411429
names := InfiniteListOfNames( name, init );

lib/monoid.gd

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -231,15 +231,15 @@ DeclareSynonymAttr( "TrivialSubmonoid", TrivialSubmagmaWithOne );
231231
## </Item>
232232
## <Mark>2: For given generator names</Mark>
233233
## <Item>
234-
## Called with various nonempty strings,
234+
## Called with various (one or more) distinct nonempty strings,
235235
## <Ref Func="FreeMonoid" Label="for various names"/> returns
236236
## a free monoid on as many generators as arguments, which are labelled
237237
## <A>name1</A>, <A>name2</A>, etc.
238238
## </Item>
239239
## <Mark>3: For a given list of generator names</Mark>
240240
## <Item>
241241
## Called with a finite list <A>names</A> of
242-
## nonempty strings,
242+
## distinct nonempty strings,
243243
## <Ref Func="FreeMonoid" Label="for a list of names"/> returns
244244
## a free monoid on <C>Length(<A>names</A>)</C> generators, whose
245245
## <C>i</C>-th generator is labelled <A>names</A><C>[i]</C>.
@@ -256,11 +256,12 @@ DeclareSynonymAttr( "TrivialSubmonoid", TrivialSubmagmaWithOne );
256256
## The optional argument <A>name</A> must be a string; its default value is
257257
## <C>"m"</C>,
258258
## and the optional argument <A>init</A> must be a finite list of
259-
## nonempty strings; its default value is an empty list.
259+
## distinct nonempty strings; its default value is an empty list.
260260
## The generators are initially labelled according to the list <A>init</A>,
261261
## followed by
262262
## <A>name</A><C>i</C> for each <C>i</C> in the range from
263-
## <C>Length(<A>init</A>)+1</C> to <K>infinity</K>.
263+
## <C>Length(<A>init</A>)+1</C> to <K>infinity</K>; such a label is not
264+
## allowed to appear in <A>init</A>.
264265
## </Item>
265266
## </List>
266267
##

lib/semigrp.gd

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ DeclareAttribute("CayleyGraphDualSemigroup",IsSemigroup);
300300
## generators, and the labels given to the generators, can be specified in
301301
## several different ways.
302302
## Warning: the labels of generators are only an aid for printing,
303-
## and do not necessarily distinguish generators;
303+
## and do not necessarily distinguish elements of the semigroup;
304304
## see the examples at the end for more information.
305305
## <List>
306306
## <Mark>
@@ -323,15 +323,15 @@ DeclareAttribute("CayleyGraphDualSemigroup",IsSemigroup);
323323
## </Item>
324324
## <Mark>2: For given generator names</Mark>
325325
## <Item>
326-
## Called with various (at least one) nonempty strings,
326+
## Called with various (one or more) distinct nonempty strings,
327327
## <Ref Func="FreeSemigroup" Label="for various names"/> returns
328328
## a free semigroup on as many generators as arguments, which are labelled
329329
## <A>name1</A>, <A>name2</A>, etc.
330330
## </Item>
331331
## <Mark>3: For a given list of generator names</Mark>
332332
## <Item>
333333
## Called with a nonempty finite list <A>names</A> of
334-
## nonempty strings,
334+
## distinct nonempty strings,
335335
## <Ref Func="FreeSemigroup" Label="for a list of names"/> returns
336336
## a free semigroup on <C>Length(<A>names</A>)</C> generators, whose
337337
## <C>i</C>-th generator is labelled <A>names</A><C>[i]</C>.
@@ -417,6 +417,8 @@ DeclareAttribute("CayleyGraphDualSemigroup",IsSemigroup);
417417
## distinguish letters.
418418
## It is possible to create arbitrarily weird situations by choosing strange
419419
## names for the letters.
420+
## However, as a small step to avoiding confusion, it is disallowed to choose
421+
## duplicate generator names.
420422
## <P/>
421423
## <Example><![CDATA[
422424
## gap> f := FreeGroup( "x", "x" );

tst/testinstall/grpfree.tst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ gap> FreeGroup("bacon", "eggs", "beans");
167167
<free group on the generators [ bacon, eggs, beans ]>
168168
gap> FreeGroup("shed");
169169
<free group on the generators [ shed ]>
170+
gap> FreeGroup("shed", "shed");
171+
Error, FreeGroup( <name1>, <name2>, ... ): the names must be distinct
172+
gap> FreeGroup("a", "b", "c", "d", "b", "e", "f");
173+
Error, FreeGroup( <name1>, <name2>, ... ): the names must be distinct
170174
171175
# FreeGroup( [ <name1>, <name2>, ... ] )
172176
gap> FreeGroup(InfiniteListOfNames("a"));

tst/testinstall/mgmfree.tst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ gap> FreeMagma("bacon", "eggs", "beans");
113113
<free magma on the generators [ bacon, eggs, beans ]>
114114
gap> FreeMagma("shed");
115115
<free magma on the generators [ shed ]>
116+
gap> FreeMagma("shed", "shed");
117+
Error, FreeMagma( <name1>, <name2>, ... ): the names must be distinct
118+
gap> FreeMagma("a", "b", "c", "d", "b", "e", "f");
119+
Error, FreeMagma( <name1>, <name2>, ... ): the names must be distinct
116120

117121
# FreeMagma( [ <name1>[, <name2>, ...] ] )
118122
gap> FreeMagma(InfiniteListOfNames("a"));
@@ -238,6 +242,10 @@ gap> FreeMagmaWithOne("bacon", "eggs", "beans");
238242
<free magma-with-one on the generators [ bacon, eggs, beans ]>
239243
gap> FreeMagmaWithOne("shed");
240244
<free magma-with-one on the generators [ shed ]>
245+
gap> FreeMagmaWithOne("shed", "shed");
246+
Error, FreeMagmaWithOne( <name1>, <name2>, ... ): the names must be distinct
247+
gap> FreeMagmaWithOne("a", "b", "c", "d", "b", "e", "f");
248+
Error, FreeMagmaWithOne( <name1>, <name2>, ... ): the names must be distinct
241249

242250
# FreeMagmaWithOne( [ <name1>[, <name2>, ...] ] )
243251
gap> FreeMagmaWithOne(InfiniteListOfNames("a"));

0 commit comments

Comments
 (0)