diff --git a/gap/base/methods.gi b/gap/base/methods.gi index 41400462..2cf45cc5 100644 --- a/gap/base/methods.gi +++ b/gap/base/methods.gi @@ -86,8 +86,10 @@ end); InstallGlobalFunction(CallRecogMethod, function(m, args) + local f; if not IsRecogMethod(m) then ErrorNoReturn(" must be a RecogMethod, but is ", m); fi; - return CallFuncList(UnpackRecogMethod(m), args); + f := UnpackRecogMethod(m); + return f(ri) end); diff --git a/gap/base/methsel.gd b/gap/base/methsel.gd index 3f91b3e4..e59a22ba 100644 --- a/gap/base/methsel.gd +++ b/gap/base/methsel.gd @@ -43,16 +43,13 @@ DeclareGlobalFunction( "AddMethod" ); ## <#GAPDoc Label="CallMethods"> ## -## +## ## a record ms describing this method selection procedure. ## ## ## The argument db must be a method database in the sense of ## Section . limit must be a non-negative -## integer. furtherargs stands for an arbitrary number of additional -## arguments, which are handed down to the called methods. Of course they -## must fulfill the conventions defined for the methods in the database -## db.

+## integer. Finally ri is a recognition node.

## The function first creates a method selection record keeping track ## of the things that happened during the method trying procedure, ## which is also used during this procedure. Then it calls methods with diff --git a/gap/base/methsel.gi b/gap/base/methsel.gi index 14485ace..364016b6 100644 --- a/gap/base/methsel.gi +++ b/gap/base/methsel.gi @@ -50,7 +50,7 @@ end); # result : either fail or true # -InstallGlobalFunction( "CallMethods", function(db, tolerancelimit, methargs...) +InstallGlobalFunction( "CallMethods", function(db, tolerancelimit, ri) # First argument is a method database, i.e. list of records # describing recognition methods. # Second argument is a number, the tolerance limit. @@ -86,7 +86,7 @@ InstallGlobalFunction( "CallMethods", function(db, tolerancelimit, methargs...) # apply the method Info(InfoMethSel, 3, "Calling rank ", db[i].rank, " method \"", Stamp(db[i].method), "\"..."); - result := CallRecogMethod(db[i].method, methargs); + result := CallRecogMethod(db[i].method, ri); # evaluate the result if result = NeverApplicable then diff --git a/gap/base/recognition.gi b/gap/base/recognition.gi index a75e9ae1..f75cb7b2 100644 --- a/gap/base/recognition.gi +++ b/gap/base/recognition.gi @@ -486,7 +486,7 @@ InstallGlobalFunction( RecogniseGeneric, Assert(0, Length(Set(allmethods, m->m.rank)) = Length(allmethods)); # Find a possible homomorphism (or recognise this group as leaf) - Setfhmethsel(ri, CallMethods( allmethods, 10, ri, H )); + Setfhmethsel(ri, CallMethods( allmethods, 10, ri )); # TODO: extract the value 10 into a named constant, and / or make it # an option parameter to the func diff --git a/gap/matrix.gi b/gap/matrix.gi index 40d4df7b..ed6ab9da 100644 --- a/gap/matrix.gi +++ b/gap/matrix.gi @@ -26,16 +26,16 @@ end; #! @EndChunk BindRecogMethod(FindHomMethodsMatrix, "DiagonalMatrices", "check whether all generators are diagonal matrices", -function(ri, G) +function(ri) local H,d,f,gens,hom,i,isscalars,j,newgens,upperleft; d := ri!.dimension; if d = 1 then Info(InfoRecog,2,"Found dimension 1, going to Scalars method"); - return FindHomMethodsMatrix.Scalar(ri,G); + return FindHomMethodsMatrix.Scalar(ri); fi; - gens := GeneratorsOfGroup(G); + gens := GeneratorsOfGroup(Grp(ri)); if not ForAll(gens, IsDiagonalMat) then return NeverApplicable; fi; @@ -61,13 +61,13 @@ function(ri, G) # Note that we cannot tell the upper levels that they should better # have made some more generators for the kernel! - return FindHomMethodsMatrix.BlockScalar(ri,G); + return FindHomMethodsMatrix.BlockScalar(ri); fi; # Scalar matrices, so go to dimension 1: newgens := List(gens,x->ExtractSubMatrix(x,[1],[1])); H := Group(newgens); - hom := GroupHomByFuncWithData(G,H,RECOG.HomToScalars,rec(poss := [1])); + hom := GroupHomByFuncWithData(Grp(ri),H,RECOG.HomToScalars,rec(poss := [1])); SetHomom(ri,hom); findgensNmeth(ri).method := FindKernelDoNothing; @@ -128,7 +128,7 @@ end; #! @EndChunk BindRecogMethod(FindHomMethodsMatrix, "Scalar", "Hint TODO", -function(ri, G) +function(ri) local f,gcd,generator,gens,i,l,o,pows,q,rep,slp,subset,z; if ri!.dimension > 1 then return NotEnoughInformation; @@ -137,10 +137,10 @@ function(ri, G) # FIXME: FieldOfMatrixGroup f := ri!.field; o := One(f); - gens := List(GeneratorsOfGroup(G),x->x[1,1]); + gens := List(GeneratorsOfGroup(Grp(ri)),x->x[1,1]); subset := Filtered([1..Length(gens)], i -> not IsOne(gens[i])); if subset = [] then - return FindHomMethodsGeneric.TrivialGroup(ri,G); + return FindHomMethodsGeneric.TrivialGroup(ri); fi; gens := gens{subset}; q := Size(f); @@ -163,7 +163,7 @@ function(ri, G) Add(l,rep[i]); fi; od; - slp := StraightLineProgramNC([[l]],Length(GeneratorsOfGroup(G))); + slp := StraightLineProgramNC([[l]],Length(GeneratorsOfGroup(Grp(ri)))); Setslptonice(ri,slp); # this sets the nice generators Setslpforelement(ri,SLPforElementFuncsMatrix.DiscreteLog); ri!.generator := z^gcd; @@ -219,7 +219,7 @@ end; #! @EndChunk BindRecogMethod(FindHomMethodsMatrix, "BlockScalar", "Hint TODO", -function(ri, G) +function(ri) # We assume that ri!.blocks is a list of ranges where the non-trivial # scalar blocks are. Note that their length does not have to sum up to # the dimension, because some blocks at the end might already be trivial. @@ -228,9 +228,9 @@ function(ri, G) if nrblocks <= 2 then # the image is only one block # go directly to scalars in that case: data := rec(poss := ri!.blocks[nrblocks]); - newgens := List(GeneratorsOfGroup(G),x->RECOG.HomToDiagonalBlock(data,x)); + newgens := List(GeneratorsOfGroup(Grp(ri)),x->RECOG.HomToDiagonalBlock(data,x)); H := GroupWithGenerators(newgens); - hom := GroupHomByFuncWithData(G,H,RECOG.HomToDiagonalBlock,data); + hom := GroupHomByFuncWithData(Grp(ri),H,RECOG.HomToDiagonalBlock,data); SetHomom(ri,hom); AddMethod(InitialDataForImageRecogNode(ri).hints, FindHomMethodsMatrix.Scalar, 2000); @@ -255,9 +255,9 @@ function(ri, G) middle := QuoInt(nrblocks,2)+1; # the first one taken topblock := ri!.blocks[nrblocks]; data := rec(poss := [ri!.blocks[middle][1]..topblock[Length(topblock)]]); - newgens := List(GeneratorsOfGroup(G),x->RECOG.HomToDiagonalBlock(data,x)); + newgens := List(GeneratorsOfGroup(Grp(ri)),x->RECOG.HomToDiagonalBlock(data,x)); H := GroupWithGenerators(newgens); - hom := GroupHomByFuncWithData(G,H,RECOG.HomToDiagonalBlock,data); + hom := GroupHomByFuncWithData(Grp(ri),H,RECOG.HomToDiagonalBlock,data); SetHomom(ri,hom); # the image are the last few blocks: @@ -378,11 +378,11 @@ BindRecogMethod(FindHomMethodsMatrix, "ReducibleIso", "use the MeatAxe to find invariant subspaces", # alternative comment: #"use MeatAxe to find a composition series, do base change", -function(ri,G) +function(ri) # First we use the MeatAxe to find an invariant subspace: local H,bc,compseries,f,hom,isirred,m,newgens; - RECOG.SetPseudoRandomStamp(G,"ReducibleIso"); + RECOG.SetPseudoRandomStamp(Grp(ri),"ReducibleIso"); if IsBound(ri!.isabsolutelyirred) and ri!.isabsolutelyirred then # this information is coming from above @@ -409,9 +409,9 @@ function(ri,G) List(bc.blocks,Length)," (dim=",ri!.dimension,")"); # Do the base change: - newgens := List(GeneratorsOfGroup(G),x->bc.base*x*bc.baseinv); + newgens := List(GeneratorsOfGroup(Grp(ri)),x->bc.base*x*bc.baseinv); H := GroupWithGenerators(newgens); - hom := GroupHomByFuncWithData(G,H,RECOG.HomDoBaseChange, + hom := GroupHomByFuncWithData(Grp(ri),H,RECOG.HomDoBaseChange, rec(t := bc.base,ti := bc.baseinv)); # Now report back: @@ -481,17 +481,17 @@ end; #! @EndChunk BindRecogMethod(FindHomMethodsMatrix, "BlockLowerTriangular", "for a group generated by block lower triangular matrices", -function(ri,G) +function(ri) # This is only used coming from a hint, we know what to do: # A base change was done to get block lower triangular shape. # We first do the diagonal blocks, then the lower p-part: local H,data,hom,newgens; data := rec( blocks := ri!.blocks ); - newgens := List(GeneratorsOfGroup(G), + newgens := List(GeneratorsOfGroup(Grp(ri)), x->RECOG.HomOntoBlockDiagonal(data,x)); Assert(0, not fail in newgens); H := GroupWithGenerators(newgens); - hom := GroupHomByFuncWithData(G,H,RECOG.HomOntoBlockDiagonal,data); + hom := GroupHomByFuncWithData(Grp(ri),H,RECOG.HomOntoBlockDiagonal,data); SetHomom(ri,hom); # Now give hints downward: @@ -526,12 +526,12 @@ end); #! @EndChunk BindRecogMethod(FindHomMethodsMatrix, "BlockDiagonal", "for groups generated by block diagonal matrices", -function(ri,G) +function(ri) # This is only called by a hint, so we know what we have to do: # We do all the blocks projectively and thus are left with scalar blocks. # In the projective case we still do the same, the BlocksModScalars # will automatically take care of the projectiveness! - SetHomom(ri, IdentityMapping(G)); + SetHomom(ri, IdentityMapping(Grp(ri))); # Now give hints downward: InitialDataForImageRecogNode(ri).blocks := ri!.blocks; AddMethod(InitialDataForImageRecogNode(ri).hints, FindHomMethodsProjective.BlocksModScalars, 2000); @@ -782,7 +782,7 @@ end; #! @EndChunk BindRecogMethod(FindHomMethodsMatrix, "LowerLeftPGroup", "Hint TODO", -function(ri,G) +function(ri) local f,p; # Do we really have our favorite situation? if not (IsBound(ri!.blocks) and @@ -812,10 +812,10 @@ end); #! @EndChunk BindRecogMethod(FindHomMethodsMatrix, "GoProjective", "divide out scalars and recognise projectively", -function(ri,G) +function(ri) local hom,q; Info(InfoRecog,2,"Going projective..."); - hom := IdentityMapping(G); + hom := IdentityMapping(Grp(ri)); SetHomom(ri,hom); # Now give hints downward: Setmethodsforimage(ri,FindHomDbProjective); @@ -841,8 +841,9 @@ end); #! @EndChunk BindRecogMethod(FindHomMethodsMatrix, "KnownStabilizerChain", "use an already known stabilizer chain for this group", -function(ri,G) - local S,hom; +function(ri) + local S,hom,G; + G := Grp(ri); if HasStoredStabilizerChain(G) then Info(InfoRecog,2,"Already know stabilizer chain, using 1st orbit."); S := StoredStabilizerChain(G); diff --git a/gap/matrix/classical.gi b/gap/matrix/classical.gi index c51ae28c..d574fb85 100644 --- a/gap/matrix/classical.gi +++ b/gap/matrix/classical.gi @@ -144,7 +144,7 @@ end; # TODO: Better comments... BindRecogMethod(FindHomMethodsClassical, "IsGenericParameters", "tests whether group has generic parameters", -function( recognise, grp ) +function( recognise ) local fact, d, q, hint; hint := recognise.hint; @@ -217,7 +217,7 @@ end); BindRecogMethod(FindHomMethodsClassical, "IsGeneric", "tests whether group is generic", -function (recognise, grp) +function(recognise) if recognise.isGeneric = false then return NeverApplicable; fi; @@ -236,7 +236,7 @@ end); #TODO: comments... BindRecogMethod(FindHomMethodsClassical, "RuledOutExtField", "tests whether extension field case is ruled out", -function (recognise, grp) +function(recognise) local differmodfour, d, q, E, b, bx, hint; hint := recognise.hint; @@ -341,7 +341,7 @@ end); BindRecogMethod(FindHomMethodsClassical, "IsNotAlternating", "tests whether alternating groups are ruled out", -function( recognise, grp ) +function(recognise) local V, P, i, g ,q, o; q := recognise.q; @@ -365,7 +365,7 @@ function( recognise, grp ) fi; if q = 2 then - if Size(grp) <> 2520 then # 2520 = 3*4*5*6*7 = |A7| + if Size(recognise.grp) <> 2520 then # 2520 = 3*4*5*6*7 = |A7| Info( InfoClassical, 2, "G is not an alternating group" ); recognise.isNotAlternating := true; return false; @@ -409,7 +409,7 @@ end); BindRecogMethod(FindHomMethodsClassical, "IsNotMathieu", "tests whether Mathieu groups are ruled out", -function( recognise, grp ) +function(recognise) local i, fn, g, d, q, E, ord; d := recognise.d; @@ -480,7 +480,7 @@ end); BindRecogMethod(FindHomMethodsClassical, "IsNotPSL", "tests whether PSL groups are ruled out", -function (recognise, grp) +function(recognise) local i, E, LE, d, p, a, q, str, fn, ord; E := recognise.E; @@ -620,11 +620,11 @@ end; # generate the next random element and its char polynomial BindRecogMethod(FindHomMethodsClassical, "TestRandomElement", "makes new random element and stores it and its char poly", -function(recognise, grp) +function(recognise) local g, ppd, bppd, d, q, cpol, f, deg, facs, r, s, h, gmod, str, ord, bc, phi, kf, o1, o2, cf, i, found, p; - recognise.g := PseudoRandom(grp); + recognise.g := PseudoRandom(recognise.grp); recognise.cpol := CharacteristicPolynomial(recognise.g); recognise.n := recognise.n + 1; @@ -846,7 +846,7 @@ end); # the characteristic polynomial BindRecogMethod(FindHomMethodsClassical, "IsReducible", "tests whether current random element rules out reducible", -function( recognise, grp ) +function(recognise) local deg, dims, g; # compute the degrees of the irreducible factors @@ -876,9 +876,9 @@ end); BindRecogMethod(FindHomMethodsClassical, "NoClassicalForms", "tests whether we can rule out certain forms", -function( recognise, grp ) +function(recognise) local d,field; - PossibleClassicalForms( grp, recognise.g, recognise ); + PossibleClassicalForms( recognise.grp, recognise.g, recognise ); d := recognise.d; field := recognise.field; @@ -899,7 +899,7 @@ end); BindRecogMethod(FindHomMethodsClassical, "ClassicalForms", "Find the invariant forms", -function( recognise, grp) +function(recognise) local field, z, d, i, qq, A, c, I, t, i0, a, l, g, module, forms, dmodule, fmodule, form; @@ -939,7 +939,7 @@ function( recognise, grp) # now try to find an invariant form if recognise.maybeDual then - dmodule := ClassicalForms_GeneratorsWithoutScalarsDual(grp); + dmodule := ClassicalForms_GeneratorsWithoutScalarsDual(recognise.grp); if dmodule <> false then form := ClassicalForms_InvariantFormDual(module,dmodule); if form <> false then @@ -957,7 +957,7 @@ function( recognise, grp) fi; if recognise.maybeFrobenius then - fmodule := ClassicalForms_GeneratorsWithoutScalarsFrobenius(grp); + fmodule := ClassicalForms_GeneratorsWithoutScalarsFrobenius(recognise.grp); if fmodule <> false then form := ClassicalForms_InvariantFormFrobenius(module,fmodule); if form <> false then @@ -987,7 +987,7 @@ end); BindRecogMethod(FindHomMethodsClassical, "MeatAxe", "Test irreducibility", -function( recognise, grp ) +function(recognise) if recognise.n > 15 then recognise.needMeataxe := true; fi; @@ -1015,7 +1015,7 @@ end); ## Main function to test whether group contains SL BindRecogMethod(FindHomMethodsClassical, "IsSLContained", "tests whether group contains SL", -function( recognise, grp ) +function(recognise) if recognise.isGeneric <> true or recognise.isNotExt <> true or recognise.isNotPSL <> true or @@ -1058,7 +1058,7 @@ end); ## Main function to test whether group contains Sp BindRecogMethod(FindHomMethodsClassical, "IsSpContained", "tests whether group contains Sp", -function( recognise, grp ) +function(recognise) local isSpForm; isSpForm := f -> IsSesquilinearForm(f) and IsSymplecticForm(f); @@ -1116,7 +1116,7 @@ end); ## Main function to test whether group contains SU BindRecogMethod(FindHomMethodsClassical, "IsSUContained", "tests whether group contains SU", -function( recognise, grp ) +function(recognise) local f, isHermForm, q0; isHermForm := f -> IsSesquilinearForm(f) and IsHermitianForm(f); @@ -1180,7 +1180,7 @@ end); ## Main function to test whether group contains SO BindRecogMethod(FindHomMethodsClassical, "IsSOContained", "tests whether group contains SO", -function( recognise, grp ) +function(recognise) local f, isParForm, isEllForm, isHypForm; isParForm := f -> IsSesquilinearForm(f) and IsParabolicForm(f); @@ -1292,7 +1292,7 @@ end; ############################################################################/ ## -## NonGenericLinear (recognise, grp) . . . . . . . non-generic linear case +## NonGenericLinear ## ## Recognise non-generic linear matrix groups over finite fields: ## In order to prove that a group G <= GL( 3, 2^s-1) contains SL, we need to @@ -1301,7 +1301,7 @@ end; ## BindRecogMethod(FindHomMethodsClassical, "NonGenericLinear", "tests whether group is non-generic Linear", -function( recognise, grp ) +function(recognise) local CheckFlag; CheckFlag := function( ) @@ -1358,7 +1358,7 @@ end); ## BindRecogMethod(FindHomMethodsClassical, "NonGenericSymplectic", "tests whether group is non-generic Symplectic", -function(recognise, grp) +function(recognise) local d, q, CheckFlag, isSpForm; isSpForm := f -> IsSesquilinearForm(f) and IsSymplecticForm(f); @@ -1429,7 +1429,7 @@ function(recognise, grp) return fail; fi; elif d = 4 and q = 2 then - if Size(grp) mod 720 <> 0 then + if Size(recognise.grp) mod 720 <> 0 then Info(InfoClassical,2,"group does not contain Sp(", recognise.d, ", ", recognise.q, ");"); recognise.isSpContained := false; @@ -1478,7 +1478,7 @@ end); ## BindRecogMethod(FindHomMethodsClassical, "NonGenericUnitary", "tests whether group is non-generic Unitary", -function(recognise, grp) +function(recognise) local d, q, g, f1, f2, o, CheckFlag, isHermForm, str; isHermForm := f -> IsSesquilinearForm(f) and IsHermitianForm(f); @@ -1596,7 +1596,7 @@ function(recognise, grp) return CheckFlag(); fi; elif d = 3 and q = 4 then - if Order(grp) mod 216 = 0 then + if Order(recognise.grp) mod 216 = 0 then return CheckFlag(); else recognise.isSUContained := false; @@ -1610,7 +1610,7 @@ function(recognise, grp) if not Order( recognise.g ) mod 6 = 0 then return fail; fi; - if ForAny( GeneratorsOfGroup(grp), + if ForAny( GeneratorsOfGroup(recognise.grp), h -> not IsOne(Comm(h,recognise.g^3))) then Info( InfoClassical,2, "Cube of element of order div by 6 is not central" ); @@ -1627,7 +1627,7 @@ function(recognise, grp) if not Order(recognise.g) mod 5 = 0 then return fail; fi; - if ForAny(GeneratorsOfGroup(grp), h -> not IsOne(Comm(h,recognise.g))) then + if ForAny(GeneratorsOfGroup(recognise.grp), h -> not IsOne(Comm(h,recognise.g))) then Info( InfoClassical,2, "The element of order 5 is not central" ); recognise.hasSpecialEle := true; @@ -1644,7 +1644,7 @@ function(recognise, grp) return fail; fi; g := recognise.g^(Order(recognise.g)/2); - if ForAny(GeneratorsOfGroup(grp), h -> not IsOne(Comm(h,g))) then + if ForAny(GeneratorsOfGroup(recognise.grp), h -> not IsOne(Comm(h,g))) then Info( InfoClassical,2, "involution in cyclic subgroup of order 8 is not central" ); recognise.hasSpecialEle := true; @@ -1686,7 +1686,7 @@ end); BindRecogMethod(FindHomMethodsClassical, "NonGenericOrthogonalPlus", "tests whether group is non-generic O+", -function(recognise,grp) +function(recognise) local d, q, gp1, gp2, CheckFlag, pgrp, orbs, isHypForm; isHypForm := f -> IsSesquilinearForm(f) and IsHyperbolicForm(f); @@ -1920,7 +1920,7 @@ end); BindRecogMethod(FindHomMethodsClassical, "NonGenericOrthogonalMinus", "tests whether group is non-generic O-", -function(recognise, grp) +function(recognise) local d, q, orbs, pgrp, h, g, ppd, CheckFlag, isEllForm; @@ -2029,7 +2029,7 @@ end); BindRecogMethod(FindHomMethodsClassical, "NonGenericOrthogonalCircle", "tests whether group is non-generic Oo", -function( recognise, grp ) +function(recognise) local d, q, g, s, CheckFlag, isParForm; isParForm := f -> IsSesquilinearForm(f) and IsParabolicForm(f); @@ -2263,6 +2263,7 @@ function( arg ) f := FieldOfMatrixGroup(grp); q := Characteristic(f)^DegreeOverPrimeField(f); recognise := rec( field := f, + grp := grp, d := DimensionOfMatrixGroup(grp), p := Characteristic(f), a := DegreeOverPrimeField(f), @@ -2316,7 +2317,7 @@ function( arg ) ); merkinfolevel := InfoLevel(InfoMethSel); SetInfoLevel(InfoMethSel,0); - ret := CallMethods( ClassicalMethDb, nrrandels, recognise, grp ); + ret := CallMethods( ClassicalMethDb, nrrandels, recognise ); SetInfoLevel(InfoMethSel,merkinfolevel); # fail: bedeutet, dass entnervt aufgegeben wurde # true: bedeutet, dass eine Methode "erfolgreich" war