diff --git a/lib/combinat.gd b/lib/combinat.gd index 60a97a20a7..c3640a4ae8 100644 --- a/lib/combinat.gd +++ b/lib/combinat.gd @@ -1512,3 +1512,62 @@ DeclareGlobalFunction("Bernoulli"); ## <#/GAPDoc> ## DeclareAttribute("Permanent", IsMatrix); + + +############################################################################# +## +#F AllLinearDiophantineSolutions(,,) +## +## <#GAPDoc Label="AllLinearDiophantineSolutions"> +## +## +## +## +## For a list n of positive integers, an integer sum, and a list +## of nonnegative integers max, this function returns a list of all +## nonnegative coefficient vectors v, such that n\cdot v=sum, and +## v\le max in each entry. +##

+## 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 ] ] +## ]]> +## +## +## <#/GAPDoc> +## +DeclareGlobalFunction("AllLinearDiophantineSolutions"); + +############################################################################# +## +#F AllSubsetSummations( , [,] ) +## +## <#GAPDoc Label="AllSubsetSummations"> +## +## +## +## +## returns a list of all partitions of the entries in from such that the +## entries in each cell sum up to the corresponding entry in to. If a bound +## limit is given, the function stops (and returns fail) if the length +## of the list created would exceed limit. +##

+## 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 +## ]]> +## +## +## <#/GAPDoc> +## +DeclareGlobalFunction("AllSubsetSummations"); + diff --git a/lib/combinat.gi b/lib/combinat.gi index f1e3c0a479..76bebf9377 100644 --- a/lib/combinat.gi +++ b/lib/combinat.gi @@ -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); + diff --git a/lib/csetgrp.gi b/lib/csetgrp.gi index 19f77e3e93..833ef6d9fb 100644 --- a/lib/csetgrp.gi +++ b/lib/csetgrp.gi @@ -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:=[]; @@ -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 diff --git a/tst/testextra/grplatt.tst b/tst/testextra/grplatt.tst index 510be4ab4c..112bda49aa 100644 --- a/tst/testextra/grplatt.tst +++ b/tst/testextra/grplatt.tst @@ -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);