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


Quelle  norad.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Alexander Hulpke.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
##  This file contains functions that compute normalizers by the
##  fitting-free/solvable radical method. It can be competitive even in the case
##  of certain permutation groups.
##

BindGlobal("TwoLevelStabilizer",
  function(gens,imgs,acts,pcgs,pcgsacts,quot,pnt,domain,act)
local d,orb,len,S,depths,rel,stb,img,pos,i,j,k,ii,po,rep,sg,sf,sfs,fr,first,
      fra,blp,bli,terminate,induce,ind,Sact,gpsz,stabsz,pcgstabsz,stopsz,divs,
      brutelimit,permact,pacthom,good,lpos,actrange;

  first:=true;
  gpsz:=Size(Group(imgs,()))*Product(RelativeOrders(pcgs));
  divs:=Reversed(DivisorsInt(gpsz));
  Add(divs,0); # to deal with factor 1
  stopsz:=First(divs,x->x<gpsz)+1;

  terminate:=ValueOption("terminate");
  induce:=ValueOption("induce");
  actrange:=ValueOption("actrange");
  if not IsList(actrange) then
    actrange:=[1..Length(pcgs)];
  fi;

  pnt:=Immutable(pnt);
  if domain=false then
    d:=NewDictionary(pnt,true,
      DomainForAction(pnt,Concatenation(acts,pcgsacts),act));
  else
    d:=NewDictionary(pnt,true,domain);
  fi;
  orb:=[pnt];
  AddDictionary(d,pnt,1);

  # start with orbit via pcgs

  len := ListWithIdenticalEntries( Length( pcgs ) + 1, 0 );
  len[ Length( len ) ] := 1;
  S := Reversed(pcgs{Difference([1..Length(pcgs)],actrange)});
  Sact := Reversed(pcgsacts{Difference([1..Length(pcgs)],actrange)});
  depths:=[];
  rel := [  ];
  for i  in Reversed( actrange )  do
    Info(InfoFitFree,4,"PcgsOrbit ",i," ",Length(orb));
    img := act( pnt, pcgsacts[ i ] );
    #MakeImmutable(img);
    pos := LookupDictionary( d, img );
    if pos = fail  then

      # The current generator moves the orbit as a block.
      Add( orb, img );
      AddDictionary(d,img,Length(orb));

      for j  in [ 2 .. len[ i + 1 ] ]  do
        img := act( orb[ j ], pcgsacts[ i ] );
        Add( orb, img );
        AddDictionary(d,img,Length(orb));
      od;
      for k  in [ 3 .. RelativeOrders( pcgs )[ i ] ]  do
        for j  in Length( orb ) + [ 1 - len[ i + 1 ] .. 0 ]  do
          img := act( orb[ j ], pcgsacts[ i ] );
          Add( orb, img );
          AddDictionary(d,img,Length(orb));
        od;
      od;

    else

      # The current generator leaves the orbit invariant.
      stb := ListWithIdenticalEntries( Length( pcgs ), 0 );
      stb[ i ] := 1;
      ii := i + 2;
      while pos <> 1  do
        while len[ ii ] >= pos  do
          ii := ii + 1;
        od;
        stb[ ii - 1 ] := -QuoInt( pos - 1, len[ ii ] );
        pos := ( pos - 1 ) mod len[ ii ] + 1;
      od;
      Add( S, LinearCombinationPcgs( pcgs, stb ) );
      Add(Sact,LinearCombinationPcgs(pcgsacts,stb));
      Add(depths,i);
      Add( rel, RelativeOrders( pcgs )[ i ] );
    fi;
    len[ i ] := Length( orb );

  od;
  pcgstabsz:=Product(rel);
  stabsz:=pcgstabsz;

  # now S is the pcgs part of the stabilizer

  # continue forming group orbit
  po:=Length(orb);
  Info(InfoFitFree,3,"solvorb=",po);

  rep:=[[]];
  sg:=[];
  sf:=[];
  sfs:=TrivialSubgroup(Image(quot));

  brutelimit:=infinity;

  if induce<>fail then
    ind:=Action(Group(Sact),induce.obj,induce.action);
#    if Size(ind)>=induce.stop then
#      return rec(byinduced:=true,
#       gens:=sg,imgs:=sf,pcgs:=Reversed(S),orblen:=Length(orb));
#    fi;

    if IsBound(induce.allobj) and induce.allobj<>fail then
      brutelimit:=Length(induce.allobj)*10;
    fi;

  fi;

  i:=1;
  while i<=Length(orb) do

    for j in [1..Length(gens)] do
      img := act(orb[i],acts[j]);
      pos := LookupDictionary(d,img);
      bli:=(i-1)/po+1;
      if pos = fail  then
        # The current generator moves the orbit as a block.
        Add(orb,img);
        AddDictionary(d,img,Length(orb));
        fr:=Concatenation(rep[bli],[j]);
        Add(rep,fr);
        if terminate<>fail and Length(rep)>terminate then
          return fail;
        fi;
        for k in [i+1..i+po-1] do
          img:=act(orb[k],acts[j]);
  #F if LookupDictionary(d,img)<>fail then Error("err3");fi;
          Add(orb,img);
          AddDictionary(d,img,Length(orb));
        od;

        # should we give in?
        if Length(orb)>brutelimit then

          orb:=[];d:=1; #clean memory

          # projective action is fine, as we want to fix space
          Info(InfoFitFree,1,"act on whole space, fix in perm action");
          permact:=Action(GroupWithGenerators(Concatenation(acts,pcgsacts)),
            induce.allobj,induce.allact);
          i:=Concatenation(
            List([1..Length(gens)], x->DirectProductElement([gens[x],imgs[x]])),
            List(pcgs, x->DirectProductElement([x,One(imgs[1])])));
          pacthom:=GroupHomomorphismByImagesNC(GroupWithGenerators(i),permact,i,
                    GeneratorsOfGroup(permact));

          lpos:=List(induce.lvecs,x->Position(induce.allobj,x));

          # we don't care about the actual subgroup, just the inducing elements
          good:=[];
          SubgroupProperty(induce.subact,
                  function(x)
                  local r;
                    r:=RepresentativeAction(permact,lpos,Permuted(lpos,x),OnTuples);
                    if r<>fail then Add(good,r);fi;
                    return r<>fail;
                  end);
          good:=List(good,x->PreImagesRepresentative(pacthom,x));

          good:=Filtered(good,x->not IsOne(x[2]));

          return rec(byinduced:=true,
            gens:=List(good,x->x[1]),imgs:=List(good,x->x[2]),
              pcgs:=Reversed(S));

        fi;

      else
        # get stabilizing element
        blp:=QuoInt((pos-1),po)+1; # which block position are we?

        # now recalculate the representative in factor group
        fr:=One(sfs);
        for k in rep[bli] do
          fr:=fr*imgs[k];
        od;
        fr:=fr*imgs[j];
        for k in Reversed(rep[blp]) do
          fr:=fr/imgs[k];
        od;

        if not fr in sfs then
          # is it a new element for the factor? (If not, we don't need it,
          # since we know the Pcgs-part of the stabilizer.)
          sfs:=ClosureGroup(sfs,fr);
          stabsz:=pcgstabsz*Size(sfs);
          stopsz:=First(divs,x->x<gpsz/stabsz)+1;
#Print("found stab from ",i,":",pos," in ",Length(orb), " vs ",gpsz/stabsz,"\n");
          Add(sf,fr);
          fr:=One(gens[1]);
          for k in rep[bli] do
            fr:=fr*gens[k];
          od;
          fr:=fr*gens[j];
          for k in Reversed(rep[blp]) do
            fr:=fr/gens[k];
          od;

          # now we need to find the correct s-part.
          fra:=One(acts[1]);
          for k in rep[bli] do
            fra:=fra*acts[k];
          od;
          fra:=fra*acts[j];
          for k in Reversed(rep[blp]) do
            fra:=fra/acts[k];
          od;
          img:=act(pnt,fra); # that's where fr now maps it to

          # find correcting pcgs element
          pos:=LookupDictionary(d,img);

          stb := ListWithIdenticalEntries( Length( pcgs ), 0 );
          ii := 1;
          while pos <> 1  do
            while len[ ii ] >= pos  do
              ii := ii + 1;
            od;
            stb[ ii - 1 ] := -QuoInt( pos - 1, len[ ii ] );
            pos := ( pos - 1 ) mod len[ ii ] + 1;
          od;
          # now stb is the exponents of the correcting element.

          fr:=fr*LinearCombinationPcgs(pcgs,stb);
          Add(sg,fr);

          if induce<>fail then
            fra:=fra*LinearCombinationPcgs(pcgsacts,stb);
            ind:=ClosureGroup(ind,Permutation(fra,induce.obj,induce.action));
          fi;
        fi;
      fi;

    od;
    i:=i+po; # can jump in Pcgs-orbit steps, as we always form all p-images

    # ensure at least all generators have been applied
    if induce<>fail and Size(ind)>=induce.stop then

      if ValueOption("orbit")=true then
        return rec(byinduced:=true,
          gens:=sg,imgs:=sf,pcgs:=Reversed(S),orblen:=Length(orb),orbit:=orb);
      else
        return rec(byinduced:=true,
          gens:=sg,imgs:=sf,pcgs:=Reversed(S),orblen:=Length(orb));
      fi;

    elif Length(orb)>stopsz and first=true then
      Info(InfoFitFree,2,"orblen=",gpsz/stabsz,
         ", early break ",Length(orb)," from ",po);
      first:=rec(
        gens:=sg,imgs:=sf,pcgs:=Reversed(S),orblen:=gpsz/stabsz);
      if ValueOption("orbit")=true then
        first.orbit:=orb;
      fi;
      return first;
    fi;
  od;

  Info(InfoFitFree,2,"orblen=",Length(orb)," from ",po);
  S:=rec(gens:=sg,imgs:=sf,pcgs:=Reversed(S),orblen:=Length(orb));
  #if first<>true and first<>S then Error("LEAR"); fi;
  if ValueOption("orbit")=true then
    S.orbit:=orb;
  fi;
  return S;

end);

BindGlobal("TwoLevelSubspaceCentralizer",
  function(ng,nf,ngm,np,npm,factorhom,sub,mpcgs,dual)
local i,stb;

  for i in sub do
    stb:=TwoLevelStabilizer(ng,nf,ngm,np,npm,factorhom,i,false,OnRight);
    ng:=stb.gens;
    nf:=stb.imgs;
    np:=InducedPcgsByPcSequenceNC(np,stb.pcgs);
    stb:=LinearActionLayer(Concatenation(ng,np),mpcgs);
  #F if Length(sub[1])<>Length(stb[1]) then Error("heh!");fi;
    ngm:=stb{[1..Length(ng)]};
    npm:=stb{[Length(ng)+1..Length(stb)]};
    if dual then
      ngm:=List(ngm,x->TransposedMat(x^-1));
      npm:=List(npm,x->TransposedMat(x^-1));
    fi;

  od;
  return rec(gens:=ng,imgs:=nf,pcgs:=np);
end);

BindGlobal("RealizeAffineAction",function(allgens,sub,sel,f,myact)
local expandvec,bassrc,basimg,transl,getbasimg,gettransl,myact2;

  expandvec:=function(v)
    local z;
    z:=ShallowCopy(Zero(sub));
    z{sel}:=v;
    MakeImmutable(z);
    return z;
  end;
  allgens:=ShallowCopy(allgens);
  bassrc:=[];
  basimg:=List(allgens,x->[]);
  transl:=[];
  # lazy evaluators
  getbasimg:=function(a,b)
    if not IsBound(basimg[a][b]) then
      basimg[a][b]:=myact(expandvec(bassrc[b]),allgens[a]){sel}-gettransl(a);
#Print("assign ",a," ",b,"\n");
      MakeImmutable(basimg[a][b]);
    fi;
    return basimg[a][b];
  end;
  gettransl:=function(a)
    if not IsBound(transl[a]) then
      transl[a]:=myact(Zero(sub),allgens[a]){sel};
      MakeImmutable(transl[a]);
    fi;
    return transl[a];
  end;

  myact2:=function(fv,g)
  local p,v,sol,i;
    p:=Position(allgens,g);
    if p=fail then
      #Print("IMAGE\n");
      Add(allgens,g);
      p:=Length(allgens);
    fi;
    if not IsBound(basimg[p]) then
      basimg[p]:=[];
    fi;
    if Length(bassrc)=0 then
      sol:=fail;
    else
      sol:=SolutionMat(bassrc,fv);
    fi;
    if sol=fail then
      Add(bassrc,Immutable(fv));
      sol:=List(bassrc,x->Zero(f));
      sol[Length(bassrc)]:=One(f);
    fi;
    v:=Zero(fv);
#Print("A\n");
    for i in [1..Length(sol)] do
      if not IsZero(sol[i]) then
        v:=v+sol[i]*getbasimg(p,i);
      fi;
    od;
    v:=v+gettransl(p);
    #v:=Sum([1..Length(sol)],x->sol[x]*getbasimg(p,x))+gettransl(p);

    #if v<>myact(expandvec(fv),g){sel} then Error("nonaffine");fi;
    return v;
  end;

  return myact2;
end);

# main normalizer routine
InstallGlobalFunction(NormalizerViaRadical,function(G,U)
local sus,ser,len,factorhom,uf,n,d,up,mran,nran,mpcgs,pcgs,pcisom,nf,ng,np,sub,
  central,f,ngm,npm,no2pcgs,part,stb,mods,famo,nopcgs,uff,ufg,prev,
  ufr,dims,vecs,ovecs,vecsz,l,prop,properties,clusters,clusterspaces,
  fs,i,v1,o1,p1,
  orblens,stabilizespaceandupdate,dual,myact,bound,boundbas,ranges,j,module,sumos,
  minimalsubs,localinduce,lmpcgs,nonzero,sel,myact2,tailnum,lfamo;

#timer:=List([1..15],x->0);
  localinduce:=function(seq)
    if Length(seq)=Length(pcgs) then
      return pcgs;
    else
      return InducedPcgsByPcSequenceNC(pcgs,seq);
    fi;
  end;

  stabilizespaceandupdate:=function(space)
  local localgl,stb,glhom,glperm,glact,clu,stabsz,cent,lvecs,idx,
        localclust,subact,xlvecs;
    localgl:=GL(Dimension(space),f);
    subact:=fail; lvecs:=fail;xlvecs:=fail;
    if Size(localgl)=1 or vecs=fail then
      localclust:=[];
      stabsz:=Size(localgl);
    else
      lvecs:=NormedRowVectors(f^Dimension(space));
      clu:=BasisVectors(Basis(space));
      xlvecs:=List(lvecs,x->OnLines(x*clu,One(npm[1])));
      # for each local vector the position in vecs
      idx:=List(xlvecs,x->Position(vecs,x));

      # clusters as relevant for this subspace
      localclust:=List(clusters,x->Filtered([1..Length(lvecs)],y->idx[y] in x));
      SortBy(localclust, Length);

      glhom:=IsomorphismPermGroup(localgl);
      glperm:=Image(glhom);
      glact:=ActionHomomorphism(glperm,lvecs,
        GeneratorsOfGroup(glperm),
        List(GeneratorsOfGroup(glperm),
          x->PreImagesRepresentative(glhom,x)),
        OnLines,"surjective");
      stb:=Image(glact);
      for clu in localclust do
        stb:=Stabilizer(stb,clu,OnSets);
      od;
      subact:=stb;
      stb:=PreImage(glact,stb);
      stabsz:=Size(stb);
    fi;
    Info(InfoFitFree,3,"clustersub=",Collected(List(localclust,Length)),
      stabsz);

    # act on subspace but use maximal induced action size as terminator
    stb:=TwoLevelStabilizer(ng,nf,ngm,np,npm,factorhom,
          Concatenation(TriangulizedMat(BasisVectors(Basis(space)))),
          false,
          OnSubspacesByCanonicalBasisConcatenations:
        induce:=rec(obj:=AsSSortedList(space),
                    subact:=subact,allobj:=ovecs,allact:=OnLines,
                    lvecs:=xlvecs,
                    action:=OnRight,
                    stop:=stabsz));


    if IsBound(stb.byinduced) then
      Info(InfoFitFree,2,"early stop by induced action ",stabsz);

      # add centralizing elements in factor (don't need pcgs part
      # since we always compute full pcgs orbit and thus have it)
      # in (unlikely) case they are missing.
      cent:=TwoLevelSubspaceCentralizer(ng,nf,ngm,np,npm,
                factorhom,BasisVectors(Basis(space)),lmpcgs,dual:induce:=fail);
      nf:=Group(stb.imgs,One(Image(factorhom)));
      np:=Filtered([1..Length(cent.imgs)],x->not x in nf);
      Info(InfoFitFree,2,"added centralizers ",np);
      Append(stb.gens,cent.gens{np});
      Append(stb.imgs,cent.imgs{np});
    fi;
    ng:=stb.gens;
    nf:=stb.imgs;
    np:=localinduce(stb.pcgs);
  end;

#timer[1]:=Runtime()-timer[1];

  ovecs:=fail;

  sus:=FittingFreeSubgroupSetup(G,U);
  ser:=sus.parentffs;
  factorhom:=ser.factorhom;

  # first work in radical factor
  #TODO use socle of radical factor

  uf:=Image(sus.rest);
  ufr:=SolvableRadical(uf);
  Info(InfoFitFree,1,"Radsize= ",Size(ufr)," index ",Index(uf,ufr));

  uff:=SmallGeneratingSet(uf);
  ufg:=List(uff,x->PreImagesRepresentative(sus.rest,x));

  n:=Normalizer(Image(factorhom),uf);

  pcgs:=ser.pcgs;
  pcisom:=ser.pcisom;
  len:=Length(pcgs);

  # generators of derived subgroup help with quickly getting stabilizers
  if not IsPerfectGroup(n) then
    d:=Reversed(DerivedSeriesOfGroup(n));
    nf:=[];
    l:=TrivialSubgroup(n);
    for i in d do
      for j in SmallGeneratingSet(i) do
        if not j in l then
          Add(nf,j);
          l:=ClosureGroup(l,j);
        fi;
      od;
    od;
  else
    nf:=SmallGeneratingSet(n);
  fi;

  ng:=List(nf,x->PreImagesRepresentative(factorhom,x));
  np:=pcgs;

  up:=sus.pcgs;

  prev:=ser.pcgs;

  mods:=[]; # collect modulo pcgs for up steps -- they are to be used again

  for d in [2..Length(ser.depths)] do

    # number of pcgs generators in the kernel
    tailnum:=Maximum(0,Length(pcgs)-ser.depths[d]);

    mran:=[ser.depths[d-1]..len];
    nopcgs:=InducedPcgsByPcSequenceNC(pcgs,pcgs{mran});
    nran:=[ser.depths[d]..len];
    no2pcgs:=InducedPcgsByPcSequenceNC(pcgs,pcgs{nran});

    mpcgs:=nopcgs mod no2pcgs;
    mods[d]:=mpcgs;

    f:=GF(RelativeOrders(mpcgs)[1]);

    central:= ForAll(GeneratorsOfGroup(G),
                i->ForAll(mpcgs,
                  j->DepthOfPcElement(pcgs,Comm(i,j))>=ser.depths[d]));

    # abelian factor, use affine methods
    Info(InfoFitFree,1,"abelian factor ",d,": ",
      Product(RelativeOrders(ser.pcgs){mran}), "->",
      Product(RelativeOrders(ser.pcgs){nran})," central:",central);

    # step up via depths
    for j in [d-1,d-2..1] do

      # the part of U-pcgs in this step
      part:=up{[sus.serdepths[j]..sus.serdepths[d]-1]};


      if j=d-1 then
        Info(InfoFitFree,2,"down");
        # down step -- stabilize the subspace

        # determine layer action
        stb:=LinearActionLayer(Concatenation(ng,np),mpcgs);
        ngm:=stb{[1..Length(ng)]};
        npm:=stb{[Length(ng)+1..Length(stb)]};

        # work in quotient modules first
        module:=GModuleByMats(Concatenation(ngm,npm),f);
        sumos:=Reversed(MTX.BasesCompositionSeries(module));
        Info(InfoFitFree,2,"module layers ",List(sumos,Length));
        sumos:=sumos{[2..Length(sumos)]};

        for fs in sumos do
          if Length(fs)=0 then
            # whole module
            lmpcgs:=mpcgs;
          else
            lmpcgs:=nopcgs mod InducedPcgsByGeneratorsNC(pcgs,
              Concatenation(no2pcgs,
                List(fs,x->PcElementByExponentsNC(mpcgs,x))));
          fi;

          # avoid duplication if irreducible
          if Length(sumos)>1 then
            # determine layer action
            stb:=LinearActionLayer(Concatenation(ng,np),lmpcgs);
            ngm:=stb{[1..Length(ng)]};
            npm:=stb{[Length(ng)+1..Length(stb)]};
          fi;

          # determine subspace
          sub:=List(part,x->ExponentsOfPcElement(lmpcgs,x)*One(f));
          TriangulizeMat(sub);
          sub:=Filtered(sub,x->not IsZero(x));

          Info(InfoFitFree,2,"module of dimension ",Length(lmpcgs),
               " subspace ",Length(sub));

          if Length(sub)>0 and Length(sub)<Length(lmpcgs) then

            dual:=false;
            if Length(sub)>Length(sub[1])/2 then
              # dualize to act on smaller objects
              Info(InfoFitFree,2,"dualize");
              dual:=true;
              sub:=List(NullspaceMat(TransposedMat(sub)),ShallowCopy);
              TriangulizeMat(sub);
              ngm:=List(ngm,x->TransposedMat(x^-1));
              npm:=List(npm,x->TransposedMat(x^-1));
            fi;
            # stabilize the subspace
            sub:=ImmutableMatrix(f,sub);

            module:=GModuleByMats(Concatenation(ngm,npm),f);
            minimalsubs:=
              List(MTX.BasesMinimalSubmodules(module),x->VectorSpace(f,x));

            if GaussianCoefficient(Length(sub[1]),Length(sub),Size(f))>5*10^5
              and Size(f)^Length(sub)/(Size(f)-1)<10000
              and Size(f)^Length(sub)/(Size(f)-1)<2000 then

              # is the calculation potentially expensive?

              # first try the naive way
              stb:=TwoLevelStabilizer(ng,nf,ngm,np,npm,factorhom,
                    Concatenation(sub),false,
                    OnSubspacesByCanonicalBasisConcatenations:terminate:=200,
                    actrange:=[1..Length(np)-tailnum]);

              if stb=fail then

                # it failed. Now get vectors
                Info(InfoFitFree,2,"use vectors of ",Size(f)^Length(sub));

                # 1-dim subspaces
                vecs:=NormedRowVectors(VectorSpace(f,sub));
                if Size(f)^Length(sub[1])/(Size(f)-1)<500000 then
                  ovecs:=NormedRowVectors(f^Length(sub[1]));
                fi;

                properties:=[];
                orblens:=[];
                for l in [1..Length(vecs)] do
                  prop:=[];
                  if IsBound(orblens[l]) then
                    Add(prop,orblens[l]);
                  else
                    o1:=TwoLevelStabilizer(ng,nf,ngm,np,npm,factorhom,vecs[l],
                          false, OnLines:orbit,
                          actrange:=[1..Length(np)-tailnum]);
                    Add(prop,o1.orblen);
                    for v1 in o1.orbit do
                      p1:=Position(vecs,v1);
                      if p1<>fail then
                        orblens[p1]:=o1.orblen;
                      fi;
                    od;

                  fi;
                  Add(prop,Filtered([1..Length(minimalsubs)],
                    y->vecs[l] in minimalsubs[y]));
                  if Length(fs)=0 and Length(nran)=0 and dual=false then
                    # subspace is proper subgroup
                    if IsPermGroup(G) then
                      Add(prop,
                        CycleStructurePerm(PcElementByExponentsNC(mpcgs,vecs[l])));
                    fi;
                  fi;
                  Add(properties,prop);
                od;

                prop:=Set(properties);
                clusters:=List(prop,x->Filtered([1..Length(vecs)],
                  y->properties[y]=x));

                if Length(vecs)>10 and Minimum(List(clusters,Length))>1 then
                  # refine clusters by using the additive structure of the vector
                  # space: test for each element x how often x+c*y lies in which
                  # cluster where y runs through the elements in some cluster and c
                  # running through all nonzero scalars.

                  # reverse lookup list
                  nonzero:=Difference(AsSSortedList(f),[Zero(f)]);
                  dims:=List([1..Length(vecs)],
                    x->PositionProperty(clusters,y->x in y));
                  Info(InfoFitFree,3,"clusters=",
                    Collected(List(clusters,Length)));

                  # sum could be 0
                  vecsz:=Concatenation(vecs,[Zero(vecs[1])]);
                  Add(dims,-1);

                  i:=1;
                  while i<=Length(clusters) do
                    l:=i;
                    while l<=Length(clusters) do
                      # try sums of i with j for split
                      prop:=[];
                      for v1 in clusters[i] do
                        Add(prop,Collected(Concatenation(List(clusters[l],x->
                          List(nonzero,nz->
                            dims[Position(vecsz,
                              NormedRowVector(vecs[v1]+nz*vecs[x]))])))));
                      od;
                      if Length(Set(prop))>1 then
                        # split up using this multiplication data
                        prop:=List(Set(prop),
                          x->Filtered([1..Length(prop)],y->prop[y]=x));
                        SortBy(prop, Length);
                        Info(InfoFitFree,5,"split ",clusters[i]," with ",l,":",prop);
                        clusters:=Concatenation(clusters{[1..i-1]},
                                  List(prop,x->clusters[i]{x}),
                                  clusters{[i+1..Length(clusters)]});
                        # don't increment l as we try again
                      else
                        l:=l+1;
                      fi;

                    od;
                    i:=i+1;
                  od;
                  Info(InfoFitFree,3,"refined clusters=",
                    Collected(List(clusters,Length)));
                fi;

                clusterspaces:=List([1..Length(clusters)],x->
                  VectorSpace(f,vecs{clusters[x]}));
                dims:=List(clusterspaces,Dimension);
                SortParallel(dims,clusterspaces);

                for l in Filtered(clusterspaces,x->Dimension(x)<Length(sub)) do
                  Info(InfoFitFree,2,
                      "first stabilize subspace of dimension ",
                      Dimension(l)," of ",Length(sub)," in ",Length(sub[1]));

                  stabilizespaceandupdate(l);

                  stb:=LinearActionLayer(Concatenation(ng,np),lmpcgs);
                  ngm:=stb{[1..Length(ng)]};
                  npm:=stb{[Length(ng)+1..Length(stb)]};
                  if dual then
                    ngm:=List(ngm,x->TransposedMat(x^-1));
                    npm:=List(npm,x->TransposedMat(x^-1));
                  fi;
                od;
              else
                vecs:=fail;
              fi;
              Info(InfoFitFree,2,
                  "now stabilize full space of dimension ",
                  Length(sub)," in ",Length(sub[1]));

              # proper space stabilizer
              stabilizespaceandupdate(VectorSpace(f,sub));

            else
              vecs:=fail;
              Info(InfoFitFree,2,
                  "Only stabilize space of dimension ",
                  Length(sub)," in ",Length(sub[1]));
              stabilizespaceandupdate(VectorSpace(f,sub));
            fi;
          fi;
        od;

        # calculate modulo pcgs for ``mpcgs mod part'' for following up steps


        part:=CanonicalPcgs(InducedPcgsByGeneratorsNC(pcgs,Concatenation(up,no2pcgs)));
        if Length(part)>0 then
          famo:=prev mod part;
          IndicesEANormalSteps(NumeratorOfModuloPcgs(famo));
        else
          famo:=prev;
        fi;
        prev:=part;

      else
        # up step

        part:=CanonicalPcgs(InducedPcgsByPcSequenceNC(pcgs,part));

        #add: for any depth changed from last time.
        if Length(part)>0 and Length(famo)>0 and
          DepthOfPcElement(pcgs,part[1])<ser.depths[j+1]
          then

          # Act on complements by action on 1-cohomology group

          ranges:=List([1..Length(part)],
            x->[(x-1)*Length(famo)+1..x*Length(famo)]);

          sub:=Concatenation(List(part,a->List(famo,x->Zero(f))));

          # coboundaries
          boundbas:=List(famo,x->Concatenation(List(part,
                   y->ExponentsOfPcElement(famo,Comm(y,x))*One(f))));
          boundbas:=ImmutableMatrix(f,boundbas);
          bound:=List(boundbas,ShallowCopy);
          TriangulizeMat(bound);
          bound:=Basis(VectorSpace(f,bound));

          if Length(bound)<Length(sub) then
            Info(InfoFitFree,2,"up ",j,":",
              Product(RelativeOrders(part))," on ",
              Product(RelativeOrders(famo))," cobounds:",Size(f)^Length(bound)
              );

            myact:=function(l,gen)
              l:=List([1..Length(part)],
                x->part[x]*PcElementByExponentsNC(famo,l{ranges[x]}));
              l:=List([1..Length(part)],x->l[x]^gen);

              l:=CanonicalPcgs(InducedPcgsByGeneratorsNC(pcgs,l));

              l:=List([1..Length(part)],
                x->ExponentsOfPcElement(famo, LeftQuotient(part[x],l[x]))*One(f));
              l:=Concatenation(l);
              l:=SiftedVector(bound,l);
              ConvertToVectorRep(l,Size(f));
              MakeImmutable(l);
              return l;
            end;

            sub:=myact(sub,One(famo[1])); # standardize -- force compression

            if Length(bound)>0 then
              sel:=Filtered([1..Length(sub)],x->bound!.heads[x]=0);
            else
              sel:=[1..Length(sub)];
            fi;
            myact2:=RealizeAffineAction(Concatenation(ng,np),sub,sel,f,myact);

            # stabilize in cohomology group
            stb:=TwoLevelStabilizer(ng,nf,ng,np,np,factorhom,
                  sub{sel},f^Length(sel),myact2:
                            actrange:=[1..Length(np)-tailnum]);

            Info(InfoFitFree,2,"orblen=",stb.orblen);

            ng:=stb.gens;
            nf:=stb.imgs;
            np:=localinduce(stb.pcgs);
          fi;


          if Length(bound)>0 then
            #nontrivial blocks -- now correct

            myact:=function(l,gen)
              l:=List([1..Length(part)],
                x->part[x]*PcElementByExponentsNC(famo,List(l{ranges[x]},Int)));
              l:=List([1..Length(part)],x->l[x]^gen);
              l:=CanonicalPcgs(InducedPcgsByGeneratorsNC(pcgs,l));

              l:=List([1..Length(part)],
                x->ExponentsOfPcElement(famo,
                  LeftQuotient(part[x],l[x]))*One(f));
              l:=Concatenation(l);
              ConvertToVectorRep(l,Size(f));
              MakeImmutable(l);
              return l;
            end;

            # as corrections involve only pcgs parts, the images in the
            # radical factor are not affected.
            ng:=List(ng,x->x/PcElementByExponents(famo,
              SolutionMat(boundbas,myact(sub,x))));

            np:=InducedPcgsByGeneratorsNC(pcgs,
                  Concatenation(
                    List(np{[1..Length(np)-tailnum]},
                      x->x/PcElementByExponents(famo,
                         SolutionMat(boundbas,myact(sub,x)))),
              np{[Length(np)-tailnum+1..Length(np)]}));
            Assert(1,ForAll(ng,x->myact(sub,x)=sub));
            Assert(1,ForAll(np,x->myact(sub,x)=sub));


          fi;

        fi;

      fi;


    od;

    # act on cohomology in topmost step

    part:=ufg;

    if Length(part)>0 and Length(famo)>0 then

      #old: lfamo:=famo;

      # calculate cohomology for quotient modules first to reduce orbit lengths
      module:=GModuleByMats(LinearActionLayer(Concatenation(ng,np),famo),f);
      sumos:=Reversed(MTX.BasesCompositionSeries(module));
      sumos:=sumos{[2..Length(sumos)]};
      Info(InfoFitFree,2,"Module layers ",List(sumos,Length));

      p1:=0;
      o1:=1;
      repeat
        p1:=p1+1;
        while p1<Length(sumos) and Length(sumos[o1])-Length(sumos[p1+1])<10 do
          p1:=p1+1;
        od;

        sub:=List(sumos[p1],x->PcElementByExponents(famo,x));
        sub:=InducedPcgsByGeneratorsNC(NumeratorOfModuloPcgs(famo),Concatenation(DenominatorOfModuloPcgs(famo),sub));
        lfamo:=NumeratorOfModuloPcgs(famo) mod sub;

        Info(InfoFitFree,3,"Factor ",p1," Module ",Length(lfamo));

        ranges:=List([1..Length(part)],
          x->[(x-1)*Length(lfamo)+1..x*Length(lfamo)]);

        sub:=Concatenation(List(part,a->List(lfamo,x->Zero(f))));

        # coboundaries
        boundbas:=List(lfamo,x->Concatenation(List(part,
                  y->ExponentsOfPcElement(lfamo,Comm(y,x))*One(f))));
        boundbas:=ImmutableMatrix(f,boundbas);
        bound:=List(boundbas,ShallowCopy);
        TriangulizeMat(bound);
        bound:=List(bound,Zero);
        bound:=Basis(VectorSpace(f,bound));

        #TODO: unify with later code, requires slight change in print statement
        # and action
        Info(InfoFitFree,2,"up 0:", " on ",
          Product(RelativeOrders(lfamo))," cobounds:",Size(f)^Length(bound));

        myact:=function(l,gen)
          local pos,map;

          # make l  the conjugated generator list
          l:=List([1..Length(part)],
            x->part[x]*PcElementByExponentsNC(lfamo,l{ranges[x]}));
          l:=List([1..Length(part)],x->l[x]^gen);

          # when acting with radical elements, it centralizes in the factor
          pos:=Position(np,gen);
          if pos=fail then
            # not in the radical. There might be an induced automorphism of
            # the factor which we'll have to undo

            # find out what the images in the factor are by conjugating in the
            # factor. This is intended to avoid image calculations
            # (because we do not have `CanonicalPcgs')
            pos:=Position(ng,gen);
            if pos=fail then
              # nonstandard generator, must use image instead
              map:=ImagesRepresentative(ser.factorhom,gen);
              map:=List(uff,x->x^map);
            else
              map:=List(uff,x->x^nf[pos]);
            fi;

            # construct the map reps->preimages and map the gens we want (to work
            # in the right coordinates)
            map:=GroupGeneralMappingByImagesNC(uf,G,map,l);
            l:=List(uff,x->ImagesRepresentative(map,x));
          fi;

          #l:=List([1..Length(part)],x->LeftQuotient(part[x],l[x]));
          #l:=List(l,x->ExponentsOfPcElement(famo,x)*One(f));

          l:=List([1..Length(part)],
            x->ExponentsOfPcElement(lfamo, LeftQuotient(part[x],l[x]))*One(f));

          l:=Concatenation(l);
          l:=SiftedVector(bound,l);
          l:=ImmutableVector(f,l);
          return l;
        end;
        sub:=myact(sub,One(np[1])); # standardize -- force compression

        if Length(bound)>0 then
          sel:=Filtered([1..Length(sub)],x->bound!.heads[x]=0);
        else
          sel:=[1..Length(sub)];
        fi;
        myact2:=RealizeAffineAction(Concatenation(ng,np),sub,sel,f,myact);

        # stabilize in cohomology group
        stb:=TwoLevelStabilizer(ng,nf,ng,np,np,factorhom,sub{sel},
                f^Length(sel),myact2:
                actrange:=[1..Length(np)-tailnum]);

        Info(InfoFitFree,2,"orblen=",stb.orblen);

        ng:=stb.gens;
        nf:=stb.imgs;
        np:=localinduce(stb.pcgs);

        if Length(bound)>0 then
          #nontrivial blocks -- now correct

          myact:=function(l,gen)
            local pos,map;

            # make l  the conjugated generator list
            l:=List([1..Length(part)],
              x->part[x]*PcElementByExponentsNC(famo,l{ranges[x]}));
            l:=List([1..Length(part)],x->l[x]^gen);

            # when acting with radical elements, it centralizes in the factor
            pos:=Position(np,gen);
            if pos=fail then
              # not in the radical. There might be an induced automorphism of
              # the factor which we'll have to undo

              # find out what the images in the factor are by conjugating in the
              # factor. This is intended to avoid image calculations
              pos:=Position(ng,gen);
              if pos=fail then

                # must use image instead
                map:=ImagesRepresentative(ser.factorhom,gen);
                map:=List(uff,x->x^map);
              else
                map:=List(uff,x->x^nf[pos]);
              fi;

              # construct the map reps->preimages and map the gens we want (to work
              # in the right coordinates)
              map:=GroupGeneralMappingByImagesNC(uf,G,map,l);
              l:=List(uff,x->ImagesRepresentative(map,x));
            fi;

            l:=List([1..Length(part)],x->LeftQuotient(part[x],l[x]));
            l:=List(l,x->ExponentsOfPcElement(famo,x)*One(f));
            l:=Concatenation(l);
            return l;
          end;

          # as corrections involve only pcgs parts, the images in the
          # radical factor are not affected.
          ng:=List(ng,x->x/PcElementByExponents(famo,
            SolutionMat(boundbas,myact(sub,x))));
          np:=InducedPcgsByGeneratorsNC(pcgs,
            Concatenation(
              List(np{[1..Length(np)-tailnum]},x->x/PcElementByExponents(famo,
              SolutionMat(boundbas,myact(sub,x)))),
              np{[Length(np)-tailnum+1..Length(np)]}));
          Assert(1,ForAll(ng,x->myact(sub,x)=sub));
          Assert(1,ForAll(np,x->myact(sub,x)=sub));

        fi;

        o1:=p1;
      until p1=Length(sumos);

    fi;
  od;

  return SubgroupByFittingFreeData(G,ng,nf,np);

end);

InstallMethod( NormalizerOp,"solvable radical", IsIdenticalObj,
  [ IsGroup and CanComputeFittingFree, IsGroup],
  -1, # deliberate lower ranking to make sure this method only runs in cases
  # in which no more specialized method is installed. Once the method has
  # been used more broadly, and performance is better understood, this can
  # be changed to 0
function(G,U)
  # small pc groups fall back on generic -- don't trigger here!
  if IsPcGroup(G) then TryNextMethod();fi;
  return NormalizerViaRadical(G,U);
end);


[ Dauer der Verarbeitung: 0.44 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