Skip to content

Commit

Permalink
PERFORMANCE: Permutation Group transversal
Browse files Browse the repository at this point in the history
Rewrite a condition, mapping with inverse permutations, to test for a
small set of numbers rather than a large one. Doing so can give a
substantial speedup for constructing certain right transversals.

Also adjust of storage limits to reflect hardware progress over
20 years.
  • Loading branch information
hulpke committed Apr 5, 2024
1 parent 584b541 commit d06e4eb
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 21 deletions.
4 changes: 2 additions & 2 deletions lib/csetgrp.gi
Original file line number Diff line number Diff line change
Expand Up @@ -988,9 +988,9 @@ local c, flip, maxidx, cano, tryfct, p, r, t,
actlimit, uplimit, badlimit,avoidlimit,start,includestab,quot;

actlimit:=300000; # maximal degree on which we try blocks
uplimit:=10000; # maximal index for up step
uplimit:=500000; # maximal index for up step
avoidlimit:=200000; # beyond this index we want to get smaller
badlimit:=1000000; # beyond this index things might break down
badlimit:=5000000; # beyond this index things might break down

mayflip:=true; # are we allowed to flip?

Expand Down
113 changes: 94 additions & 19 deletions lib/csetperm.gi
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ end );
##
#F RightTransversalPermGroupConstructor( <filter>, <G>, <U> ) . constructor
##
MAX_SIZE_TRANSVERSAL := 100000;
MAX_SIZE_TRANSVERSAL := 1000000;

BindGlobal( "RightTransversalPermGroupConstructor", function( filter, G, U )
local GC, UC, noyet, orbs, domain, GCC, UCC, ac, nc, bpt, enum, i;
Expand All @@ -62,7 +62,7 @@ BindGlobal( "RightTransversalPermGroupConstructor", function( filter, G, U )
#Print(SizeStabChain(GCC),"/",SizeStabChain(UCC),":",
# SizeStabChain(GCC)/SizeStabChain(UCC),"\n");
if noyet and (
(SizeStabChain(GCC)/SizeStabChain(UCC)*10 >MAX_SIZE_TRANSVERSAL) or
(SizeStabChain(GCC)/SizeStabChain(UCC) >MAX_SIZE_TRANSVERSAL) or
(Length(UCC.genlabels)=0 and
SizeStabChain(GCC)>MAX_SIZE_TRANSVERSAL)
) then
Expand Down Expand Up @@ -158,7 +158,8 @@ end );
InstallGlobalFunction( AddCosetInfoStabChain, function( G, U, maxmoved )
local orb, pimg, img, vert, s, t, index,
block, B, blist, pos, sliced, lenflock, i, j,
ss, tt,t1,t1lim,found,tl,vimg;
ss, tt,t1,t1lim,found,tl,vimg,
sel,shortsel,gorpo,pisel,prepi,transinv;

# iterated image
vimg:=function(point,list)
Expand Down Expand Up @@ -251,13 +252,85 @@ InstallGlobalFunction( AddCosetInfoStabChain, function( G, U, maxmoved )
t1lim:=50;
fi;

sel:=Filtered([1..Maximum(G.orbit)],x->IsBound(U.translabels[x]));
shortsel:=Length(sel)<t1lim;

if shortsel then
# inverse transversal elements
t1:=ShallowCopy(G.generators);
Add(t1,G.identity);
vert:=List(t1,x->x^-1);
# inverses of transversal, stored compact
# TODO: Instead of `Position`, use translabels entry
#transinv:=List(G.transversal,x->vert[Position(t1,x)]);
transinv:=[];
for i in [1..Length(G.transversal)] do
if IsBound(G.transversal[i]) then
t:=Position(t1,G.transversal[i]);
if t=fail then
Add(t1,G.transversal[i]);
Add(vert,G.transversal[i]^-1);
t:=Length(t1);
fi;
transinv[i]:=vert[t];
fi;
od;
# Position in orbit
gorpo:=[];
for i in [1..Length(G.orbit)] do
gorpo[G.orbit[i]]:=i;
od;
fi;

orb := G.orbit{ [ 1 .. U.lenblock ] };
pimg := [ ];
while index < U.index do

pimg{ orb } := CosetNumber( G.stabilizer, U.stabilizer, s,
orb );
t := 2;
while t <= U.lenblock and index < U.index do

if shortsel then

# test for the few wrong values, mapping backwards

pisel:=Filtered([1..Length(pimg)],
x->IsBound(pimg[x]) and pimg[x] in sel);

while t <= U.lenblock and index < U.index do

# For this point in the block, find the images of the
# earlier points under the representative.
vert := G.orbit{ [ 1 .. t-1 ] };
img := G.orbit[ t ];
tl:=[];
while img <> G.orbit[ 1 ] do
Add(tl,transinv[img]);
img := img ^ G.transversal[ img ];
od;
prepi:=pisel;
for t1 in [Length(tl),Length(tl)-1..1] do
prepi:=OnTuples(prepi,tl[t1]);
od;

# If $Ust = Us't'$ then $1t'/t/s in 1U$. Also if $1t'/t/s
# in 1U$ then $st/t' = u.g_1$ with $u in U, g_1 in G_1$
# and $g_1 = u_1.s'$ with $u_1 in U_1, s' in S_1$, so
# $Ust = Us't'$.
#if ForAll( [ 1 .. t-1 ], i -> not
# vert[ i ] in prepi ) then
if not ForAny(gorpo{prepi},x->x>=1 and x<=t-1) then
U.repsStab[ t ][ s ] := true;
index := index + lenflock;

fi;

t := t + 1;
od;

else

while t <= U.lenblock and index < U.index do

# do not test all points first if not necessary
# (test only at most t1lim points, if the test succeeds,
Expand All @@ -269,25 +342,25 @@ InstallGlobalFunction( AddCosetInfoStabChain, function( G, U, maxmoved )
vert := G.orbit{ [ 1 .. t1 ] };
img := G.orbit[ t ];
while img <> G.orbit[ 1 ] do
vert := OnTuples( vert, G.transversal[ img ] );
img := img ^ G.transversal[ img ];
vert := OnTuples( vert, G.transversal[ img ] );
img := img ^ G.transversal[ img ];
od;

# If $Ust = Us't'$ then $1t'/t/s in 1U$. Also if $1t'/t/s
# in 1U$ then $st/t' = u.g_1$ with $u in U, g_1 in G_1$
# and $g_1 = u_1.s'$ with $u_1 in U_1, s' in S_1$, so
# $Ust = Us't'$.
if ForAll( [ 1 .. t1 ], i -> not IsBound
( U.translabels[ pimg[ vert[ i ] ] ] ) ) then
( U.translabels[ pimg[ vert[ i ] ] ] ) ) then

# do all points
if t1<t-1 then
img := G.orbit[ t ];
if t<=10*t1lim then
vert := G.orbit{ [ 1 .. t - 1 ] };
while img <> G.orbit[ 1 ] do
vert := OnTuples( vert, G.transversal[ img ] );
img := img ^ G.transversal[ img ];
vert := OnTuples( vert, G.transversal[ img ] );
img := img ^ G.transversal[ img ];
od;
found:=ForAll( [ t1+1 .. t - 1 ], i -> not IsBound
( U.translabels[ pimg[ vert[ i ] ] ] ) );
Expand All @@ -298,26 +371,28 @@ InstallGlobalFunction( AddCosetInfoStabChain, function( G, U, maxmoved )
# long a list, failure will happen quickly.
tl:=[];
while img <> G.orbit[ 1 ] do
Add(tl,G.transversal[img]);
img := img ^ G.transversal[ img ];
Add(tl,G.transversal[img]);
img := img ^ G.transversal[ img ];
od;
found:=ForAll( [ t1+1 .. t - 1 ], i -> not IsBound
( U.translabels[ pimg[ vimg(G.orbit[ i ],tl) ] ] ) );
fi;

if found then
if found then
U.repsStab[ t ][ s ] := true;
index := index + lenflock;
fi;
fi;

else
U.repsStab[ t ][ s ] := true;
index := index + lenflock;
else
U.repsStab[ t ][ s ] := true;
index := index + lenflock;
fi;
fi;
fi;

t := t + 1;
od;
t := t + 1;
od;
fi;

s := s + 1;
od;

Expand Down

0 comments on commit d06e4eb

Please sign in to comment.