diff --git a/lib/twocohom.gi b/lib/twocohom.gi index d504e29dc3..fed35791a1 100644 --- a/lib/twocohom.gi +++ b/lib/twocohom.gi @@ -1277,6 +1277,81 @@ local e,one,m,r,a,c,is,i; return false; end ); +############################################################################# +## +## Permutation degree still considered manageable when representing a group +## extension on the cosets of a module hyperplane. +## +BindGlobal("EXTENSION_COSET_ENUMERATION_MAXDEG",10^5); + +############################################################################# +## +#F ModuleCoreOfSubspace( , ) +## +## Basis of the largest submodule of contained in the subspace +## spanned by , that is of the intersection of the images of this +## subspace under the group. Intersecting with the images under the module +## generators repeatedly reaches this intersection. +## +BindGlobal("ModuleCoreOfSubspace",function(module,bas) +local old,gen; + while not IsEmpty(bas) do + old:=Length(bas); + for gen in module.generators do + bas:=SumIntersectionMat(bas,bas*gen)[2]; + if IsEmpty(bas) then + return bas; + fi; + od; + if Length(bas)=old then + return bas; + fi; + od; + return bas; +end); + +############################################################################# +## +#F SubmoduleFreeSubspace( ) +## +## Basis of a subspace of that contains no nonzero submodule and is +## maximal with this property under greedy extension. In an extension of a +## group by the corresponding subgroup has trivial core -- a normal +## subgroup contained in it lies in the module and thus is a submodule -- so +## the extension acts faithfully on its cosets. For an irreducible module +## this gives a hyperplane, and thus degree |G| times the field size. +## +BindGlobal("SubmoduleFreeSubspace",function(module) +local bas,extend,v,bad; + + extend:=function(v) + local new; + new:=Concatenation(bas,[v]); + if RankMat(new)>Length(bas) + and IsEmpty(ModuleCoreOfSubspace(module,new)) then + bas:=new; + return true; + fi; + return false; + end; + + bas:=[]; + for v in IdentityMat(module.dimension,module.field) do + extend(v); + od; + + # a basis adapted to the module structure can do better than the standard + # one; random vectors are a cheap substitute + bad:=0; + while Length(bas)2 and arg[3]=true then + new:=fail; if IsZero(z) and MTX.IsIrreducible(r.module) then # make SDP directly m:=PermrepSemidirectModule(r.group,r.module:cheap); @@ -1688,6 +1764,44 @@ local r,z,ogens,n,gens,str,dim,i,j,f,rels,new,quot,g,p,collect,m,e,fp,sim, new:=GroupHomomorphismByImages(fp,p,GeneratorsOfGroup(fp), Concatenation(m.ggens,m.basis)); else + # The extension acts faithfully on the cosets of a subspace of the + # module that contains no nonzero submodule, and enumerating them + # costs far less than the quotient lifting below. Every codimension + # of that subspace multiplies the degree by though, and the + # degree reduction afterwards then eats up the gain -- so insist on a + # hyperplane, as an irreducible module provides. (A one-dimensional + # module has none, its cosets are those of the trivial subgroup.) + bas:=SubmoduleFreeSubspace(r.module); + deg:=Size(r.group)*prime; + if Length(bas)>0 and Length(bas)=dim-1 + and deg<=EXTENSION_COSET_ENUMERATION_MAXDEG then + Info(InfoExtReps,2,"Enumerate ",deg," cosets of module subspace"); + tab:=CosetTableFromGensAndRels(gens,RelatorsOfFpGroup(fp), + List(bas,x->LinearCombinationPcgs(gens{[n+1..n+dim]},x)): + silent:=true,max:=Maximum(20*deg,CosetTableDefaultLimit)); + if tab<>fail then + p:=Group(List(tab{[1,3..Length(tab)-1]},PermList)); + StabChain(p,rec(limit:=Size(fp))); + fi; + + if tab<>fail and Size(p)=Size(fp) then + new:=GroupHomomorphismByImagesNC(fp,p,GeneratorsOfGroup(fp), + GeneratorsOfGroup(p)); + + # this degree is far off the optimum, so -- unlike elsewhere -- a + # full reduction pays for itself here + if ValueOption("cheap")<>true then + e:=SmallerDegreePermutationRepresentation(p); + if NrMovedPoints(ImagesSource(e))