Skip to content

Commit

Permalink
ENHANCE: IntermediateSubgroups performance
Browse files Browse the repository at this point in the history
Abvoid getting bugged down in trying to match many short orbits of a subgroup.
Added function to find nonnegative solutions of linear diophantine equation.
Moved combinatorial function into combinat.gi
  • Loading branch information
hulpke committed Apr 20, 2021
1 parent 93568a8 commit b78dc2e
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 49 deletions.
59 changes: 59 additions & 0 deletions lib/combinat.gd
Original file line number Diff line number Diff line change
Expand Up @@ -1512,3 +1512,62 @@ DeclareGlobalFunction("Bernoulli");
## <#/GAPDoc>
##
DeclareAttribute("Permanent", IsMatrix);


#############################################################################
##
#F AllLinearDiophantineSolutions(<n>,<max>,<sum>)
##
## <#GAPDoc Label="AllLinearDiophantineSolutions">
## <ManSection>
## <Func Name="AllLinearDiophantineSolutions" Arg='n,maxx,sum'/>
##
## <Description>
## For a list <A>n</A> of positive integers, an integer <A>sum</A>, and a list
## of nonnegative integers <A>max</A>, this function returns a list of all
## nonnegative coefficient vectors <A>v</A>, such that <M>n\cdot v=sum</M>, and
## <M>v\le max</M> in each entry.
## <P/>
## <Example><![CDATA[
## gap> AllLinearDiophantineSolutions([6,10,15],[10,10,10],57);
## [ [ 7, 0, 1 ], [ 2, 3, 1 ], [ 2, 0, 3 ] ]
## gap> AllLinearDiophantineSolutions([6,10,15],[6,4,4],57);
## [ [ 2, 3, 1 ], [ 2, 0, 3 ] ]
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareGlobalFunction("AllLinearDiophantineSolutions");

#############################################################################
##
#F AllSubsetSummations( <to>,<from> [,<limit>] )
##
## <#GAPDoc Label="AllSubsetSummations">
## <ManSection>
## <Func Name="AllSubsetSummations" Arg='to,from [,limit]'/>
##
## <Description>
## returns a list of all partitions of the entries in <A>from</A> such that the
## entries in each cell sum up to the corresponding entry in <A>to</A>. If a bound
## <A>limit</A> is given, the function stops (and returns <A>fail</A>) if the length
## of the list created would exceed <A>limit</A>.
## <P/>
## <Example><![CDATA[
## gap> AllSubsetSummations([63,672],[21,42,42,42,42,42,168,168,168 ]);
## [ [ [ 1, 2 ], [ 3 .. 9 ] ], [ [ 1, 3 ], [ 2, 4, 5, 6, 7, 8, 9 ] ],
## [ [ 1, 4 ], [ 2, 3, 5, 6, 7, 8, 9 ] ], [ [ 1, 5 ], [ 2, 3, 4, 6, 7, 8, 9 ] ],
## [ [ 1, 6 ], [ 2, 3, 4, 5, 7, 8, 9 ] ] ]
## gap> l:=[21,42,42,42,42,42,168,168,168];;
## gap> Length(AllSubsetSummations([105,210,210,210],l));
## 360
## gap> AllSubsetSummations([105,210,210,210],l,300);
## fail
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareGlobalFunction("AllSubsetSummations");

97 changes: 97 additions & 0 deletions lib/combinat.gi
Original file line number Diff line number Diff line change
Expand Up @@ -2772,3 +2772,100 @@ InstallGlobalFunction(Bernoulli,
end
)
));


InstallGlobalFunction(AllLinearDiophantineSolutions,function(w,count,s)
local g,i,a,sol,l,r,pos;
if Length(w)=0 then return [];fi;
g:=Gcd(w);
if s mod g<>0 then
return [];
fi;
if Length(w)=1 then return [[s/w[1]]];fi;
# kill gcd to keep numbers small
w:=List(w,x->x/g);
s:=s/g;

sol:=[];
l:=0*w; # zero out
r:=s;
pos:=1;
while l[1]>=0 do
a:=Minimum(count[pos],QuoInt(r,w[pos]));
l[pos]:=a;
r:=r-a*w[pos];
if pos=Length(l) then
# solution?
if r=0 then Add(sol,ShallowCopy(l));fi;
# now go back and decrement prior
r:=r+l[pos]*w[pos];
l[pos]:=-1;
while pos>0 and l[pos]<0 do
pos:=pos-1;
if (pos>0 and l[pos]>=0) then
l[pos]:=l[pos]-1;
if l[pos]>=0 then
r:=r+w[pos];
fi;
fi;
od;

if pos>0 then
pos:=pos+1; # next value to calc
fi;

else
pos:=pos+1;
fi;
od;
return sol;
end);

# Brute-force algorithms that gives (as indices) all ways how to sum subsets
# of `from` to obtain `to`
InstallGlobalFunction(AllSubsetSummations,function(arg)
local to,from,limit,erg,nerg,perm,i,e,c,sel,sz,dio,part,d,j,k,kk,ac,lc,nc;
to:=arg[1];
from:=arg[2];
if Length(arg)>2 then limit:=arg[3];
else limit:=infinity;fi;
erg:=[[]];
to:=ShallowCopy(to);
perm:=Sortex(to)^-1;
for i in to do
nerg:=[];
for e in erg do
sel:=Filtered(Difference([1..Length(from)],Union(e)),x->from[x]<=i);

sz:=Collected(from{sel});
part:=List(sz,x->Filtered(sel,y->from[y]=x[1]));
dio:=AllLinearDiophantineSolutions(List(sz,x->x[1]),List(sz,x->x[2]),i);
c:=[];
for d in dio do
ac:=[[]];
for j in [1..Length(d)] do
lc:=Combinations(part[j],d[j]);
nc:=[];
for k in ac do
for kk in lc do
Add(nc,Union(k,kk));
od;
od;
ac:=nc;
od;
#Print(Position(erg,e),"/",Length(erg),"d:",d,"->",Length(ac),"\n");
Append(c,ac);
if Length(c)>limit then return fail;fi;
od;

if Length(nerg)+Length(c)>limit then return fail;fi;
for j in c do
Add(nerg,Concatenation(e,[j]));
od;

od;
erg:=nerg;
od;
return List(erg,x->Permuted(x,perm));
end);

76 changes: 27 additions & 49 deletions lib/csetgrp.gi
Original file line number Diff line number Diff line change
Expand Up @@ -81,39 +81,13 @@ local c,i;
end );


# Brute-force algorithms that gives (as indices) all ways how to sum subsets
# of `from` to obtain `to`
BindGlobal("AllSubsetSummations",function(to,from)
local erg,nerg,perm,i,e,c,sel;
erg:=[[]];
to:=ShallowCopy(to);
perm:=Sortex(to)^-1;
for i in to do
nerg:=[];
for e in erg do
sel:=Filtered(Difference([1..Length(from)],Union(e)),x->from[x]<=i);
c:=NrCombinations(sel);
if c>10^7 then
Info(InfoPerformance,1,"Performance warning: Trying ",c,
" combinations");
fi;
for c in Combinations(sel) do
if Sum(from{c})=i then
Add(nerg,Concatenation(e,[c]));
fi;
od;
od;
erg:=nerg;
od;
return List(erg,x->Permuted(x,perm));
end);

# Find element in G to conjugate B into A
# call with G,A,B;
InstallGlobalFunction(DoConjugateInto,function(g,a,b,onlyone)
local cla,clb,i,j,k,imgs,bd,r,rep,b2,ex2,split,dc,
gens,conjugate;

Info(InfoCoset,2,"call DoConjugateInto ",Size(g)," ",Size(a)," ",Size(b));
conjugate:=function(act,asub,genl,nr)
local i,dc,j,z,r,r2,found;
found:=[];
Expand Down Expand Up @@ -182,28 +156,32 @@ local cla,clb,i,j,k,imgs,bd,r,rep,b2,ex2,split,dc,
clb:=List(Orbits(b,MovedPoints(g)),Set);
# no improvement if all orbits of a are fixed
if ForAny(cla,x->ForAny(GeneratorsOfGroup(g),y->OnSets(x,y)<>x)) then
r:=AllSubsetSummations(List(cla,Length),List(clb,Length));
dc:=[];
for i in r do
k:=List(i,x->Union(clb{x}));
k:=RepresentativeAction(g,k,cla,OnTuplesSets);
if k<>fail then
Add(dc,[i,k]);
fi;
od;
if Length(dc)>0 then g:=Stabilizer(g,cla,OnTuplesSets);fi;
rep:=[];
for i in dc do
r:=DoConjugateInto(g,a,b^i[2],onlyone);
if onlyone then
if r<>fail then return i[2]*r;fi;
else
if r<>fail then Append(rep,List(r,x->i[2]*x));fi;
fi;
od;
if onlyone then return fail; #otherwise would have found and stopped
else return rep;fi;

r:=AllSubsetSummations(List(cla,Length),List(clb,Length),10^5);
if r=fail then
Info(InfoCoset,1,"Too many subset combinations");
else
Info(InfoCoset,1,"Testing ",Length(r)," combinations");
dc:=[];
for i in r do
k:=List(i,x->Union(clb{x}));
k:=RepresentativeAction(g,k,cla,OnTuplesSets);
if k<>fail then
Add(dc,[i,k]);
fi;
od;
if Length(dc)>0 then g:=Stabilizer(g,cla,OnTuplesSets);fi;
rep:=[];
for i in dc do
r:=DoConjugateInto(g,a,b^i[2],onlyone);
if onlyone then
if r<>fail then return i[2]*r;fi;
else
if r<>fail then Append(rep,List(r,x->i[2]*x));fi;
fi;
od;
if onlyone then return fail; #otherwise would have found and stopped
else return rep;fi;
fi;
else
# orbits are fixed. Make sure b is so
if ForAny(clb,x->not ForAny(cla,y->IsSubset(y,x))) then
Expand Down
6 changes: 6 additions & 0 deletions tst/testextra/grplatt.tst
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ gap> Length(ConjugacyClassesSubgroups(SymmetricGroup(7):NoPrecomputedData));
#I Using (despite option) data library of perfect groups, as the perfect
#I subgroups otherwise cannot be obtained!
96
gap> g:=SimpleGroup("3D4(2)");;
gap> hs:=List(IsomorphicSubgroups(g,SymmetricGroup(4)),Image);;
gap> h:=First(hs,x->48=Length(Orbits(x,MovedPoints(g))));;
gap> sub:=IntermediateSubgroups(g,h);;
gap> Length(sub.subgroups);
19

# thats all, folks
gap> STOP_TEST( "grplatt.tst", 1);

0 comments on commit b78dc2e

Please sign in to comment.