Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  c6.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of recog, a package for the GAP computer algebra system
##  which provides a collection of methods for the constructive recognition
##  of groups.
##
##  This files's authors include Max Neunhöffer, Ákos Seress.
##
##  Copyright of recog belongs to its developers whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-3.0-or-later
##
##
## TODO: This implementation is probably based on the paper [BNS06].
##
##  Find a subgroup of the normaliser of a symplectic type r group
##
#############################################################################


#    functions related to coordinatization of a group R,
#    where R/Z(R) is a vector space

#    basis(r,n,q,gr)
#    the input gr is the extraspecial group or a subgroup corresponding
#    to a NONSINGULAR subspace (important, otherwise fails), plus possibly
#    scalar matrices
#    output: a list of 4k matrices; the first 2k are generators for gr
#    corresponding to a basis e_1,f_1,...,e_k,f_k of hyperbolic pairs for odd r,
#    and noncommuting pairs for r=2 (in the full extraspecial group k=n);
#    the other 2k matrices contain
#    basis vectors for the eigenspaces of the generators
#
#    exponents(r,n,q,list,x)
#    list must be the output of ``basis''
#    x is an arbitrary element of the extraspecial
#    output: a list of 2k numbers, containing the exponents in the
#    decomposition x=e_1^(a_1) f_1^(b_1) e_2^(a_2) ... f_k^(b_k) z^l
#    (here z is a scalar; its exponent is not computed because we do not
#    need it)
#
#    rewriteones(r,n,q,list,x)
#    list must be the output of ``basis''
#    x is an element of the normalizer of the extraspecial in GL(r^n,q)
#    output: 2k x 2k matrix over GF(r), corresponding to the action of x
#    on the symplectic space, in the basis e_1,f_1,...,f_k




# given the eigenspaces of a hyperbolic pair of group elements
# (or a noncommuting pair in the case r=2) from a basis and
# another group element x, it finds the powers of the basis elements in x
RECOG.whichpower:=function(r,n,q,spa,spb,x)
    local v,w,i,j;

    v:=spa[1]*x;
    w:=SolutionMat(spa,v);
    j:=Position(List(w,y->y<>0*Z(q)),true);
    j:=Int( (j-1)/r ^(n-1));

    v:=spb[1]*x;
    w:=SolutionMat(spb,v);
    i:=Position(List(w,y->y<>0*Z(q)),true);
    i:=Int( (i-1)/r ^(n-1));

    return [i,j];
end;

# blocks is a block system of r subspaces, basis for subspaces listed
# in one big list; x permutes the subspaces
# computes the permutation action of x
# ell is the number of blocks
RECOG.ActionOnBlocks := function(r,n,q,blks,x)

    local w,i,j,perm, ell, blocks;

    ell := blks.ell;
    blocks := blks.blocks * x * blks.blocks^-1;
    perm:=[];
    for i in [1..ell] do
      w:=blocks[1+(i-1)*(Length(blocks)/ell)];
      j:=Position(List(w,y->y<>0*Z(q)),true);
      j:=1+Int( (j-1)/(Length(blocks)/ell));
      perm[i]:=j;
    od;

    return PermList(perm);
end;

RECOG.HomFuncActionOnBlocks := function(data,el)
  return RECOG.ActionOnBlocks(data.r,data.n,data.q,data.blks,el);
end;


RECOG.CommonDiagonal2:=function(r,n,q,rad)
    local xxx,newq,es,nicebasis,blocksizes,i,mat,sum,newblocksizes,newnicebasis,
          x,y,size;

    Info(InfoRecog,3,"C6: enter new diagonalization");
    xxx:=Runtime();

    if r=2 and (q mod 4) =3 then
       newq:=q^2;
    else
       newq:=q;
    fi;
    es:=Eigenspaces(GF(newq),rad[1]);
    nicebasis:=Concatenation(List(es,x->GeneratorsOfVectorSpace(x)));
    MakeImmutable(nicebasis);
    blocksizes:=List(es,x->Dimension(x));
    for i in [2..Length(rad)] do
      if Length(blocksizes) < r^n then
        mat:=nicebasis*rad[i]/nicebasis;
        sum:=0;
        newblocksizes:=[];
        newnicebasis:=[];
        for size in blocksizes do
          if size = 1 then
            Add(newnicebasis,Concatenation(List([1..sum],x->Zero(GF(newq))),
              [One(GF(newq))],List([sum+2..r^n],x->Zero(GF(newq)))));
            sum:=sum+1;
            Add(newblocksizes,1);
          else
            es:=Eigenspaces(GF(newq),mat{[sum+1..sum+size]}{[sum+1..sum+size]});
            for x in es do
              for y in GeneratorsOfVectorSpace(x) do
                Add(newnicebasis,Concatenation(List([1..sum],x->Zero(GF(newq))),
                    y,List([sum+size+1..r^n],x->Zero(GF(newq)))));
              od;
            od;
            Append(newblocksizes,List(es,x->Dimension(x)));
            sum:=sum+size;
          fi;
        od;
        MakeImmutable(newnicebasis);
        nicebasis:=newnicebasis*nicebasis;
        blocksizes:=newblocksizes;
      fi;
    od;

    Info(InfoRecog,3,Runtime()-xxx,"exit new diagonalization");

    return nicebasis;
end;


#for a list of commuting, noncentral elements of the extraspecial group
#times scalars, computes a basis of the vectorspace generated by them
#nicebasis is an r^n x r^n matrix, conjugating the input into diagonal form
#the vector space is a subspace of GF(r)^(r^n)
RECOG.RadBasis:=function(r,n,q,rad)
    local s, i, nicebasis, niceinv, diagrad,  action, blocks, f, xxx, xxy;

    Info(InfoRecog,3,"Reached Radbasis");
    if Length(rad)=0 then
       return [ [],[],[],[] ];
    fi;

    nicebasis := RECOG.CommonDiagonal2(r,n,q,rad);
    niceinv := nicebasis^(-1);
    Info(InfoRecog,3,"checking diagonalization:  ",
         Collected(List(rad,x->IsDiagonalMat(nicebasis*x*niceinv))));
    diagrad:=List(rad,x->DiagonalOfMat(nicebasis*x*niceinv));

    #write each vector in diagrad as scalar times a vector over GF(r)
    action:= [];
    for i in [1..Length(diagrad)] do
        action[i]:=List(diagrad[i],x-> x/diagrad[i][1]);
    od;
        action := TransposedMatMutable(action);

if Length(action) <> Length(nicebasis) then
    ErrorNoReturn("what's wrong?");
fi;

    # The identical rows of action correspond to vectors in
    # a  homogeneous component
    s := Set( action );

if Length(nicebasis) mod Length(s)  <> 0 then
    ErrorNoReturn("what's wrong2?");
fi;
    # all vectors in nicebasis whose rows in action are
    # identical form a block
    f := function (a, b) return Position(s,a) <= Position(s,b); end;
    blocks := ShallowCopy(nicebasis);
    SortParallel( action, blocks, f );

    Info(InfoRecog,3,"Radbasis end");

    return rec( ell := Length(s) , blocks := blocks );

end;


#creates a basis for a subgroup g of the extraspecial group
RECOG.basis2:=function(r,n,q,g)
    local xxx,
    a,b,spa,i,j,k,len,gens,list,list2,spb,ainv,binv,powers,posa,rad,
          posb,newq;

    xxx:=Runtime();
    Info(InfoRecog,3,"enter basis2");

    #need a field where characteristic polynomials split into linear factors
    if r=2 and (q mod 4) = 3 then
       newq:=q^2;
    else
       newq:=q;
    fi;

    list  := []; # will contain the generators for the nonsingular part
    list2 := []; # will contain the eigenspace bases for the generators
    rad   := []; # will contain generators for the radical
    len   := Length(GeneratorsOfGroup(g));
    gens  := [];
    for i in [1..len] do
      Add(gens,GeneratorsOfGroup(g)[i]);
    od;

    repeat
       posa:=0;
       posb:=0;
       k:=1;

       repeat
          if IsBound(gens[k]) then
             if gens[k]<>gens[k][1,1]*One(g) then
                a:=gens[k];
                posa:=k;
             else
                k:=k+1;
             fi;
             Unbind(gens[k]);
          else
             k:=k+1;
          fi;
       until posa > 0 or k > len;
       if posa > 0 then
          k:=k+1;
          repeat
            if IsBound(gens[k]) then
               if gens[k] = gens[k][1,1]*One(g) then
                  Unbind(gens[k]);
                  k:=k+1;
               elif gens[k]*a <> a*gens[k] then
                  b:=gens[k];
                  Unbind(gens[k]);
                  posb:=k;
               else
                  k:=k+1;
               fi;
            else
                k:=k+1;
            fi;
          until posb > 0 or k > len;

          if posb > 0 then # found a hyperbolic pair
             Add(list,a);
             Add(list,b);
             spa := Eigenspaces(GF(newq),a)[1];
             spa := List(GeneratorsOfVectorSpace(spa),z->ShallowCopy(z));
             #list bases for other eigenspaces, in the order b permutes them
                     for i in [1..r-1] do
                        for j in [1..r^(n-1)] do
                           spa[i*r^(n-1)+j]:=spa[(i-1)*r^(n-1)+j]*b;
                        od;
                     od;
                     MakeImmutable(spa);
                     Add(list2,spa);

             spb := Eigenspaces(GF(newq),b)[1];
             spb := List(GeneratorsOfVectorSpace(spb),z->ShallowCopy(z));
             for i in [1..r-1] do
                for j in [1..r^(n-1)] do
                   spb[i*r^(n-1)+j]:=spb[(i-1)*r^(n-1)+j]*a;
                od;
             od;
             MakeImmutable(spb);
             Add(list2,spb);

             ainv:=a^(-1);
             binv:=b^(-1);

             for j in [1..len] do
                if IsBound(gens[j]) then
                   powers:=RECOG.whichpower(r,n,q,spa,spb,gens[j]);
                   gens[j]:=gens[j]*(ainv^powers[1])*(binv^powers[2]);
                fi;
             od;
          else # a commutes with everybody
             Add(rad,a);
          fi;
      fi; # posa > 0
    until posa=0;

    Info(InfoRecog,3,"exit basis2");

    if Length(rad) > 0 then
        return rec( basis := rec(), blocks := RECOG.RadBasis(r,n,q,rad) );
    else
        return rec( basis := rec(sympl:=list,es:=list2), blocks := [] );
    fi;

end;


# given the symplectic basis and a group element x, it finds the
# exponents of the symplectic basis elements in the decomposition of x
RECOG.exponents:=function(r,n,q,list2,x)
    local i,len,exp,pair;

    exp:=[];
    len:=Length(list2)/2;
    for i in [1..len] do
      pair:=RECOG.whichpower(r,n,q,list2[2*i-1],list2[2*i],x);
      Add(exp,pair[1]);
      Add(exp,pair[2]);
    od;

    return exp;
end;

# divides out the hyperbolic pair part of the bottom group
# should return something in the radical
RECOG.check:=function(r,n,q,list,x,exp)
    local y,i;

    #Print(exp, "\n");

    y:=One(x);
    for i in [1..Length(list)] do
      y:=y*list[i]^exp[i];
    od;

    return (x/y);
end;

#divides out the radical part of the bottom group
#should return a scalar matrix
RECOG.check2 := function(r,n,q,rad,x,coeffs)

    local y,i;

    #Print(List( coeffs, i-> IntFFE(i)), "\n" );

    y := One(x);
    for i in [1..Length(rad)] do
      y := y*rad[i]^IntFFE(coeffs[i]);
    od;

    return (x/y);
end;


# rewrite an element of the normalizer of the extraspecial group
# as 2n x 2n matrix over GF(r) (or as smaller matrix, if the
# extraspecial group is just a subgroup of r^(1+2n) )

RECOG.rewriteones := function(r,n,q,data,blocks,x)

    local list,rad, mat, i, xx, exp, remain, remain2, coeffs;

    if blocks = [] then
        list  := data.sympl;
        mat   := [];
        for i in [1..Length(list)] do
            xx := list[i]^x;
            exp := RECOG.exponents(r,n,q,data.es,xx);
            remain := RECOG.check(r,n,q,list,xx,exp);
            if remain <> remain[1,1]*One(remain) then
                return fail;
            fi;
            Add(mat, Z(r)^0*exp);
        od;
        ConvertToMatrixRep(mat, r);
        return mat;
    else #we are in type 3 output
        return RECOG.ActionOnBlocks(r,n,q,blocks,x);
    fi;
end;

RECOG.HomFuncrewriteones := function(da,el)
  return RECOG.rewriteones(da.r,da.n,da.q,da.data,[],el);
end;


#   these functions were added by me to help test when
#   an element of the normaliser powers up to a noncentral
#   element of R.

#finds the multiplicity of x-1 in x^n-1 factored over GF(p)
RECOG.multiplicity:=function(p,n)
    local  f, one, x, facs, l, i;

   f:=GF(p);
   one:=One(f);
   x:=X(f);
   facs:=Collected( Factors(x^n-one) );
   l:=Length(facs);
   i:=0;
   repeat
      i:=i+1;
   until facs[i][1]=x-one;

   return facs[i][2];
end;

# decompose a vector space into a sum of common eigenspaces
# rad is generator list for an abelian matrix group
RECOG.commondiagonal:=function(q,rad)
    local int, es, int2, vs, nicebasis, i, j, k;

    Info(InfoRecog,3,"enter diagonalization");

    int:=Eigenspaces(GF(q^2),rad[1]);
    for i in [2..Length(rad)] do
        es:=Eigenspaces(GF(q^2),rad[i]);
        int2:=[];
        for j in [1..Length(int)] do
            for k in [1..Length(es)] do
                vs:=Intersection(int[j],es[k]);
                if Dimension(vs)>0 then
                   Add(int2,vs);
                fi;
            od;
        od;
        int:=int2;
    od;
    nicebasis:=Concatenation(List(int,x->GeneratorsOfVectorSpace(x)));
    MakeImmutable(nicebasis);

    Info(InfoRecog,3,"exit diagonalization");
    return nicebasis;
end;

#creates a basis for a subgroup g of the extraspecial group
RECOG.basis:=function(r,n,q,g)
    local xxx,
    a,b,spa,i,j,k,len,gens,list,list2,spb,ainv,binv,powers,posa,rad,
          radoutput;

    Info(InfoRecog,3,"enter basis");


    list:=[]; #this will contain the generators for the nonsingular part
    list2:=[]; #this will contain the eigenspace bases for the generators
    rad:=[]; #this will contain generators for the radical
    len:=Length(GeneratorsOfGroup(g));
    gens:=[];
    for i in [1..len] do
      Add(gens,GeneratorsOfGroup(g)[i]);
    od;
    Add(gens,One(gens[1]));
    len:=len+1;

    repeat
      k:=0;

      repeat
        k:=k+1;
        a:=gens[k];
      until a<>a[1,1]*One(a) or k=len;
      posa:=k;
      if k<len then
        repeat
           k:=k+1;
           b:=gens[k];
        until a*b <> b*a or k=len;
      fi;
      if k<len then #we found a hyperbolic pair
        Add(list,a);
        Add(list,b);

        spa:=Eigenspaces(GF(q^2),a)[1];
        spa:=List(GeneratorsOfVectorSpace(spa),z->ShallowCopy(z));
        #list bases for other eigenspaces, in the order b permutes them
        for i in [1..r-1] do
          for j in [1..r^(n-1)] do
            spa[i*r^(n-1)+j]:=spa[(i-1)*r^(n-1)+j]*b;
          od;
        od;
        MakeImmutable(spa);
        Add(list2,spa);

        spb:=Eigenspaces(GF(q^2),b)[1];
        spb:=List(GeneratorsOfVectorSpace(spb),z->ShallowCopy(z));
        for i in [1..r-1] do
          for j in [1..r^(n-1)] do
            spb[i*r^(n-1)+j]:=spb[(i-1)*r^(n-1)+j]*a;
          od;
        od;
        MakeImmutable(spb);
        Add(list2,spb);

        ainv:=a^(-1);
        binv:=b^(-1);

        for j in [1..len] do
          powers:=RECOG.whichpower(r,n,q,spa,spb,gens[j]);
          gens[j]:=gens[j]*(ainv^powers[1])*(binv^powers[2]);
        od;
      fi;
      if k=len and posa<k then #a is in the center, but not scalar
         Add(rad,a);
         for i in [posa..len-1] do
             gens[i]:=gens[i+1];
         od;
         len:=len-1;
         k:=0;
      fi;
    until k>=len;

    radoutput := RECOG.RadBasis(r,n,q,rad);

    Info(InfoRecog,3,"exit basis");

    return rec(sympl:=list,es:=list2,nicebasis:=radoutput[1],
       niceinv:=radoutput[2], vs:=radoutput[3], rad:=radoutput[4]);

end;



# RECOG.TestAbelianOld := function (n,grp,u)

#     local list, x, y, limu, randlist, randgens;

#         list := [u];
#         if Length(GeneratorsOfGroup(grp)) > 3 then
#             limu := 16 * n;
#     else
#         limu := 13 * n;
#         fi;

#     while limu > 0 do
#             limu := limu - 1;
#             x  := RandomSubproduct(list);
#             y  := RandomSubproduct(list);
#         x  := Comm(x,y);
#         if x <> x[1,1] * One(x) then
#         return [false,x];
#         fi;
#             randlist:= RandomSubproduct(list);
#             if randlist <> One(grp) then
#                 if Length(GeneratorsOfGroup(grp)) > 3 then
#                     randgens:= RandomSubproduct(grp);
#                     if randgens <> One(grp) then
#                         Add(list,randlist^randgens);
#                     fi;
#                 else # for short generator lists, conjugate with all gens
#                     for randgens in GeneratorsOfGroup(grp) do
#                         Add(list, randlist^randgens);
#                     od;
#                 fi;
#             fi;
#     od;

#     return [true,u,list];

# end;


#############################################################################
##
#F  TestAbelian(n,grp,u) . . . . . . . . . . . . . . . .
##

RECOG.TestAbelian := function (n,grp,u)

    local list, x, y, h, g, pos, limu, randlist, randgens;

    list := [u];
    limu := Maximum(16,6*n);

    while limu > 0 do
        limu := limu - 1;
        y  := RandomSubproduct(list);
        # check whether y commutes with the element computed
        # in the previous iteration
        x := list[Length(list)];
        h := x * y; g := y * x;
        pos := PositionNonZero( h[1] );
        if g <> g[1][pos]/h[1][pos]   * h then
            # x and y do not commute
             return [ false, g/h ];
        fi;

        x := y^PseudoRandom(grp);
        h := x * y; g := y * x;
        pos := PositionNonZero( h[1] );
        if g <> g[1][pos]/h[1][pos]   * h then
            # x and y do not commute
             return [ false, g/h ];
        fi;
        Add( list, x );

    od;

    return [true,u,list];

 end;



#############################################################################
##
##  fast randomised routine for testing whether <w^grp> is
##  a vector space modulo scalars
##  the input MUST have projective order r
##  2 means <w^grp>/Z(R) is a vector space of dimension > 0
##  3 means Z(R)-coset of w is fixed by grp

#############################################################################
##
#F  BlindDescent() . . . . . . . . . . . . . . . .
##

RECOG.BlindDescent := function(r,n,grp,limit)

    local x, ox, y, oy, z,  p, abel;

    x := PseudoRandom(grp);

    while limit > 0 do
        limit := limit - 1;
        y := PseudoRandom(grp);
        oy := ProjectiveOrder(y)[1];
        if oy mod r = 0  then
            abel := RECOG.TestAbelian(n,grp,y^(oy/r));
            if  abel[1] = true  then
                return [y^(oy/r),abel[3]];
            fi;
        fi;
        for p in Union(List( Collected(Factors(oy)), i->i[1]),[1]) do
            z :=Comm(x,y^(oy/p));
            if z <> z[1,1] * One(z) then
                x := z;
            fi;
        od;
        ox := ProjectiveOrder(x)[1];
        if ox  mod r = 0 then
            abel := RECOG.TestAbelian(n,grp,x^(ox/r));
            if abel[1] = true  then
                return [x^(ox/r),abel[3]];
            else
               x := abel[2];
            fi;
        else
            x :=  RECOG.TestAbelian(n,grp,x)[2];
        fi;
    od;
    return fail;
end;


#############################################################################
##
#F  RecogniseC6() . . . . . . . . . . . . . . . .
## the algorithm to recognise, constructively, when <grp> is a subgroup
## of the normaliser of symplectic type r-group.
## the output is a record having the following fields:
##  .<igens> = the image of the given gens for <grp> in the classical group
##  .<basis> = 2n gens for the r-group that <grp> normalises,
##             and a standard basis for corresponding classical module
##  .<r>     = the r for the symplectic type r-group
##  .<n>     = r^n is the dimension of <grp>
##  .<q>     = field size of given representation
## or fail to indicate (possibly temporary) failure or false to indicate
## that it failed forever, so there is no point to call it again.
RECOG.New2RecogniseC6 := function(grp)

    local   type, blocks, spaces, xxx, d, b, ppi,
            r, n, q, u, rgrp, grpbasis, igens, list, i, grp1;

    d := DimensionOfMatrixGroup(grp);
    q := Size(FieldOfMatrixGroup(grp));
    ppi := PrimePowersInt(d);
    r := ppi[1];
    n := ppi[2];
    if not Length(ppi) = 2 then
        return NeverApplicable;
    fi;
    if (q-1) mod r <> 0 then
        return NeverApplicable;
    fi;

    ## first find a non-central element of the <r>-core of <grp>
    b := RECOG.BlindDescent(r,n,grp,100);
    if b = fail then
        return TemporaryFailure;
    fi;
    Info(InfoRecog,3,"Finished blind descent");

    u := b[1];

    ## take enough conjugates to generate the <r>-core
    rgrp := Group(b[2]);
    ## try to find a set of standard gens for <rgrp>
    grpbasis := RECOG.basis2(r,n,q,rgrp);

    ## construct image of <grp> in classical group
    Info(InfoRecog,3,"enter image computation");
    igens := List(GeneratorsOfGroup(grp),
               x->RECOG.rewriteones(r,n,q,grpbasis.basis,grpbasis.blocks,x));
    Info(InfoRecog,3,"exit image computation");
    if Position(igens,fail) = fail then
        return rec( igens := igens, basis := grpbasis,
                    r := r, n := n, q := q );
    else
        return TemporaryFailure;
    fi;

end;

#! @BeginChunk C6
#! This method is designed for the handling of the Aschbacher class C6
#! (normaliser of an extraspecial group). If the input <A>G</A><M>\le PGL(d,q)</M>
#! does not satisfy <M>d=r^n</M> and <M>r|q-1</M> for some prime <M>r</M>
#! and integer <M>n</M> then the method
#! returns <K>NeverApplicable</K>. Otherwise, it returns either a homomorphism of
#! <A>G</A> into <M>Sp(2n,r)</M>, or a homomorphism into the C2 permutation
#! action of <A>G</A> on a decomposition of <M>GF(q)^d</M>, or <K>fail</K>.
#! @EndChunk
BindRecogMethod(FindHomMethodsProjective, "C6",
"find either an (imprimitive) action or a symplectic one",
function(ri, G)
    local r,re,hom;

    RECOG.SetPseudoRandomStamp(G,"C6");

    re := RECOG.New2RecogniseC6(G);
    if re = TemporaryFailure or re = NeverApplicable then
        return re;
    fi;

    if re.basis.basis = rec() then
        Info(InfoRecog,2,"C6: Found block system.");
        hom := GroupHomByFuncWithData(G,GroupWithGenerators(re.igens),
                 RECOG.HomFuncActionOnBlocks,
                 rec(r := re.r,n := re.n,q := re.q,blks := re.basis.blocks));
        InitialDataForKernelRecogNode(ri).t := re.basis.blocks.blocks;
        InitialDataForKernelRecogNode(ri).blocksize := ri!.dimension / re.basis.blocks.ell;
        AddMethod(InitialDataForKernelRecogNode(ri).hints,
                  FindHomMethodsProjective.DoBaseChangeForBlocks,
                  2000);
        Setimmediateverification(ri,true);
        findgensNmeth(ri).args[1] := re.basis.blocks.ell + 3;
        findgensNmeth(ri).args[2] := 5;
        Setmethodsforimage(ri,FindHomDbPerm);
    else
        Info(InfoRecog,2,"C6: Found homomorphism.");
        hom := GroupHomByFuncWithData(G,GroupWithGenerators(re.igens),
                 RECOG.HomFuncrewriteones,
                 rec(r := re.r,n := re.n,q := re.q,data := re.basis.basis));
        findgensNmeth(ri).args[1] := 3 + re.n;
        findgensNmeth(ri).args[2] := 5;
        Setimmediateverification(ri,true);
        Setmethodsforimage(ri,FindHomDbMatrix);
    fi;
    SetHomom(ri,hom);

    return Success;
end);

#
# Inputs are g a group of matrices preserving a symplectic form
#            over another group of matrices preserving the same symplectic form
#                 and acting absolutely irreducibly
#            p a prime
#
#            Suppose g <= over <= Sp(2k,r) this function will return a
#            group of r^k x r^k matrices in characteristic p with a
#            normal subgroup R of type r^{1+2k} preserving the set of
#            one-spaces generated by the basis and quotient isomorphic
#            to g
#
#            over is needed when g does not act absolutely
#            irreducibly, as a convenient way to specify the symplectic
#            form in question
#
#      The algorithm is based on the technique used by Walsh in
#      the construction of the Monster
#

RECOG.MakeC6Group := function(g,over,p)
    local   f,  r,  gm,  M,  k,  chis,  ws,  space,  i,  chi,  w,  x,
            basis,  newgens,  labels,  q,  zeta,  Ts,  Ds,  result,
            us,  vs,  o,  vmos,  allvs,  toprow, b, m;
    #
    # preliminaries
    #
    f := DefaultFieldOfMatrixGroup(g);
    r := Characteristic(f);
    if Size(f) <> r then
        ErrorNoReturn("Must be over prime field");
    fi;
    if p = r then
        ErrorNoReturn("Must be another characteristic");
    fi;
    if p =2 or r =2 then
        ErrorNoReturn("Odd characteristics only please");
    fi;
    q := p;
    while (q-1) mod r <> 0 do
        q := q*p;
    od;
    if q > 65536 then
        ErrorNoReturn("field too big");
    fi;
    zeta := Z(q)^((q-1)/r);
    #
    # Find the form
    #
    gm := GModuleByMats(GeneratorsOfGroup(over),f);
    M := MTX.InvariantBilinearForm(gm);
    if TransposedMat(M) <> -M then
        ErrorNoReturn("form not symplectic");
    fi;
    #
    # Now convert that into the "standard" symplectic form
    #
    # ( 0 I)
    # (-I 0)
    #
    #  where I is a k x k identity matrix
    #
    #  chis are the basis of the first part of the space
    #  ws the basis of the second part
    #
    k := DimensionOfMatrixGroup(g)/2;
    chis := [];
    ws := [];
    #
    # space will the space orthogonal to all the chis and ws
    #
    space := FullRowSpace(f,2*k);
    for i in [1..k] do
        repeat
            chi := Random(space);
        until not IsZero(chi);
        repeat
            w := Random(space);
        until not IsZero(w) and not IsZero(chi*M*w);
        x := chi*M*w;
        if not IsOne(x) then
            w := w/x;
        fi;
        Add(chis,chi);
        Add(ws,w);
        if i <> k then
            b := GeneratorsOfLeftModule(space);
            space := Submodule(space,NullspaceMat(b*M*TransposedMat([chi,w]))*b);
        fi;
    od;
    #
    # OK, now rewrite the group so that it preserves our favourite
    # symplectic form
    #
    basis := Concatenation(chis,ws);
    newgens := List(GeneratorsOfGroup(g), x->basis*x*basis^-1);
    #
    # Now thw basis will be in bijection with F_r^k
    #
    labels := Elements(FullRowSpace(f,k));
    basis := CanonicalBasis(FullRowSpace(f,k));
    #
    # Make the 2k generators of the extra-special group, which will be
    # in bijection with our favourite symplectic basis
    #
    Ts := List([1..k], i->
                  PermutationMat(PermListList(labels, List(labels,l->l+basis[i])),r^k,GF(q)));
    Ds :=  List([1..k], i->
                DiagonalMat(List(labels,l->zeta^IntFFE(basis [i]*l))));
    MakeImmutable(Ts);
    MakeImmutable(Ds);
    result := Concatenation(Ts,Ds);
    for m in result do
        ConvertToMatrixRep(m,q);
    od;

    #
    # Finally, lift the generators of g, see the Monster paper for
    #  explanation of this
    #
    for x in newgens do
        #
        # The us and vs are the images of the Ts and Ds under x
        #
        us := List([1..k], i->
                   Product([1..k], j-> Ts[j]^IntFFE(x[i,j]))*
                   Product([1..k], j-> Ds[j]^IntFFE(x[i,j+k])));
        vs := List([1..k], i->
                   Product([1..k], j-> Ts[j]^IntFFE(x[i+k,j]))*
                   Product([1..k], j-> Ds[j]^IntFFE(x[i+k,j+k])));
        #
        # Now we want the vector fixed by the all the vs
        #
        o := One(vs[1]);
        vmos := List(vs, v->v-o);
        allvs := List([1..r^k], i->Concatenation(vmos{[1..k]}[i]));
        toprow := NullspaceMat(allvs)[1];
        #
        # Finally we make the rest of the matrix using the action of
        # the us -- this could be done more economically
        #
        Add( result, List(labels, l -> toprow*Product([1..k],j-> us[j]^IntFFE(l[j]))));
    od;
    return [Group(result), SubgroupNC(~[1],result{[1..2*k]})];
end;

[ Dauer der Verarbeitung: 0.26 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge