Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/recog/gap/matrix/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 22.0.2025 mit Größe 13 kB image not shown  

SSL matimpr.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, Alice Niemeyer, Á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
##
##
##  Find an imprimitive action of a matrix group.
##  This should better be (and is now) called "LowIndex".
##
#############################################################################

#############################################################################
##
#F  OrbitSubspaceWithLimit( <grp>, <U>, <max> ) . . . . . . orbit of subspace
##
##  Compute the orbit of a subspace but return fail if the orbit has
##  more than <max> elements.
##
# RECOG.OrbitSubspaceWithLimit := function( grp, U, max )

#     local   orb,  orbset, new,  pnt,  img,  gen, gens;

#     gens := GeneratorsOfGroup(grp);

#     # start with the singleton orbit
#     orb := [ U ];
#     orbset := [ U ];

#     # loop over all points found
#     for pnt  in orb  do

#         # apply all generators <gen>
#         for gen  in gens  do
#             img := OnSubspacesByCanonicalBasis( pnt, gen );

#             # add the image <img> to the orbit if it is new
#             # can perhaps be improved (is now)
#             if not img in orbset then
#                 Add( orb, img );
#                 AddSet( orbset, img );
#                 if Length(orb) > max then return fail; fi;
#             fi;

#         od;

#     od;
#     return orbset;
# end;

#
#  Test if the module hm already has a submodule with a
#  short enough orbit.
#  Note: We can tweak what ``short enough" means. I set it to 4d,
#  but if we make it smaller it will speed up the code.
#

RECOG.IndexMaxSub := function( hm, grp, d )
    # Call this function only with a reducible module hm!
    local dim,dimnew,f,i,lastorb,lastsub,orb,sp,spnew,sub,subdim;

    # Here is the invariant subspace
    sub := MTX.ProperSubmoduleBasis(hm);
    sub := MutableCopyMat( sub );  # make mutable copy
    # FIXME: this will be unnecessary:
    ConvertToMatrixRep(sub,hm.field);
    lastsub := fail;
    lastorb := fail;
    repeat
        TriangulizeMat(sub); # Find Hermite Normal Form
        #orb := RECOG.OrbitSubspaceWithLimit(grp, sub, 4 * d );
        orb := Orb(grp,sub,OnSubspacesByCanonicalBasis,
                   rec(storenumbers := true, hashlen := NextPrimeInt(8*d)));
        Enumerate(orb,4*d);
        if not IsClosed(orb) then
            Info(InfoRecog,2,"Did not find nice orbit.");
            if lastsub = fail then
                return fail;
            fi;
            return rec( orb := lastorb,
                        hom := OrbActionHomomorphism(grp,lastorb) );
        fi;
        Info(InfoRecog,2,"Found orbit of length ",Length(orb),
             " of subspaces of dimension ",Length(orb[1]),".");
        subdim := Length(orb[1]);
        if subdim * Length(orb) = d or    # have block system!
           subdim = 1 then                # no hope in this case
            return
                rec(orb := orb,
                    hom := OrbActionHomomorphism(grp,orb));
        fi;
        # we try intersecting the subspaces in the orbit:
        Info(InfoRecog,2,"Calculating intersections...");
        f := hm.field;
        sp := VectorSpace(f,orb[1]);
        dim := Dimension(sp);
        for i in [2..Length(orb)] do
            spnew := Intersection(sp,VectorSpace(f,orb[i]));
            dimnew := Dimension(spnew);
            if dimnew > 0 and dimnew < dim then
                sp := spnew;
                dim := dimnew;
            fi;
        od;
        Info(InfoRecog,2,"Got subspace of dimension ",Dimension(sp));
        if dim = Length(sub) then   # we got nothing new
            Info(InfoRecog,2,"That we already knew, giving up.");
            return
                rec(orb := orb,
                    hom := OrbActionHomomorphism(grp,orb));
        fi;
        lastsub := sub;
        lastorb := orb;
        sub := MutableCopyMat(AsList(Basis(sp)));
        # FIXME: This will vanish:
        ConvertToMatrixRep(sub,hm.field);
    until false;
end;

RECOG.SmallHomomorphicImageProjectiveGroup := function ( grp )

    local hm, findred, ans, fld, d, i, gens;

    fld := DefaultFieldOfMatrixGroup(grp);
    d := DimensionOfMatrixGroup(grp);

    findred := function( gens )
      local hm,i,j,res;
      i := Length(gens)+1;
      for j in [1..d] do
          gens[i] := PseudoRandom(grp);
          hm := GModuleByMats(gens,fld);
          if not MTX.IsIrreducible(hm) then
              res := RECOG.IndexMaxSub( hm, grp, d );
              if res <> fail then
                  return [res, gens];
              fi;
              if i < LogInt(d,2) then
                  res := findred(gens);
                  if res = false then
                      return false;
                  fi;
                  if res <> fail then
                      return res;
                  fi;
              fi;
          fi;
      od;
      return false;   # go out all the way without success
    end;

    Info(InfoRecog,2,"LowIndex: Trying 10 first elements...");
    for i in [1..10] do   # this is just heuristics!
        gens := [PseudoRandom(grp)];
        hm := GModuleByMats(gens,fld);
        if not MTX.IsIrreducible(hm) then
            ans := findred( gens );
            if ans <> fail and ans <> false then
                return ans;
            fi;
        fi;
        if InfoLevel(InfoRecog) >= 2 then Print(".\c"); fi;
    od;
    if InfoLevel(InfoRecog) >= 2 then Print("\n"); fi;

    return fail;
end;


#! @BeginChunk LowIndex
#! This method is designed for the handling of the Aschbacher class C2
#! (stabiliser of a decomposition of the underlying vector space), but may
#! succeed on other types of input as well. Given <A>G</A> <M> \le PGL(d,q)</M>,
#! the output is either the permutation action of <A>G</A> on a short
#! orbit of subspaces or <K>fail</K>. In the current setup, <Q>short orbit</Q>
#! is defined to have length at most <M>4d</M>.
#! @EndChunk
BindRecogMethod(FindHomMethodsProjective, "LowIndex",
"find an (imprimitive) action on subspaces",
function(ri,G)
  local res;
  RECOG.SetPseudoRandomStamp(G,"LowIndex");
  res := RECOG.SmallHomomorphicImageProjectiveGroup(G);
  if res = fail then
      return fail; # FIXME: fail = TemporaryFailure here really correct?
  else
      res := res[1];
      # Now distinguish between a block system and just an orbit:
      if Length(res.orb) * Length(res.orb[1]) <> ri!.dimension then
          Info(InfoRecog,2,"Found orbit of length ",Length(res.orb),
               " - not a block system.");
      else
          Info(InfoRecog,2,"Found block system with ",Length(res.orb),
               " blocks.");
          # A block system: We do a base change isomorphism:
          InitialDataForKernelRecogNode(ri).t := Concatenation(res.orb);
          InitialDataForKernelRecogNode(ri).blocksize := Length(res.orb[1]);
          AddMethod(InitialDataForKernelRecogNode(ri).hints, FindHomMethodsProjective.DoBaseChangeForBlocks, 2000);
          Setimmediateverification(ri,true);
          findgensNmeth(ri).args[1] := Length(res.orb)+3;
          findgensNmeth(ri).args[2] := 5;
      fi;

      # we are done, report the hom:
      SetHomom(ri,res.hom);
      Setmethodsforimage(ri,FindHomDbPerm);

      return Success;
  fi;
end);

#! @BeginChunk DoBaseChangeForBlocks
#! TODO
#! @EndChunk
BindRecogMethod(FindHomMethodsProjective, "DoBaseChangeForBlocks",
"Hint TODO",
function(ri,G)
  # Do the base change:
  local H,iso,newgens,ti;

  ti := ri!.t^-1;
  newgens := List(GeneratorsOfGroup(G),x->ri!.t*x*ti);
  H := GroupWithGenerators(newgens);
  iso := GroupHomByFuncWithData(G,H,RECOG.HomDoBaseChange,
                                rec(t := ri!.t,ti := ti));

  # Now report back:
  SetHomom(ri,iso);
  findgensNmeth(ri).method := FindKernelDoNothing;

  # Inform authorities that the image can be recognised easily:
  InitialDataForImageRecogNode(ri).blocksize := ri!.blocksize;
  AddMethod(InitialDataForImageRecogNode(ri).hints, FindHomMethodsProjective.Blocks, 2000);

  return Success;
end);

#! @BeginChunk Blocks
#! TODO
#! @EndChunk
BindRecogMethod(FindHomMethodsProjective, "Blocks",
"Hint TODO",
function(ri,G)
  # Here we use BlocksModScalars and then get a kernel of scalar blocks
  # altogether mod scalars.
  local blocks,d,hom,i;
  hom := IdentityMapping(G);
  SetHomom(ri,hom);
  blocks := [];
  d := ri!.dimension;
  for i in [1..d/ri!.blocksize] do
      Add(blocks,[(i-1)*ri!.blocksize+1..i*ri!.blocksize]);
  od;
  # For the image:
  InitialDataForImageRecogNode(ri).blocks := blocks;
  AddMethod(InitialDataForImageRecogNode(ri).hints, FindHomMethodsProjective.BlocksModScalars, 2000);
  # For the kernel:
  InitialDataForKernelRecogNode(ri).blocks := blocks;
  AddMethod(InitialDataForKernelRecogNode(ri).hints, FindHomMethodsProjective.BlocksBackToMats, 2000);
  return Success;
end);

RECOG.HomBackToMats := function(el)
  # We assume that el is block diagonal with the last block being scalar.
  # This just norms this last block to 1.
  local d;
  d := Length(el);
  return (el[d,d]^-1)*el;
end;

#! @BeginChunk BlocksBackToMats
#! TODO
#! @EndChunk
BindRecogMethod(FindHomMethodsProjective, "BlocksBackToMats",
"Hint TODO",
function(ri,G)
  # This is only called as hint from Blocks, so we know that we in fact
  # have scalar blocks along the diagonal and nothing else.
  local H,hom,newgens;
  newgens := List(GeneratorsOfGroup(G),RECOG.HomBackToMats);
  H := Group(newgens);
  hom := GroupHomomorphismByFunction(G,H,RECOG.HomBackToMats);
  SetHomom(ri,hom);

  # hints for the image:
  Setmethodsforimage(ri,FindHomDbMatrix);
  InitialDataForImageRecogNode(ri).blocks := ri!.blocks{[1..Length(ri!.blocks)-1]};
  AddMethod(InitialDataForImageRecogNode(ri).hints, FindHomMethodsMatrix.BlockScalar, 2000 );

  # This is an isomorphism:
  findgensNmeth(ri).method := FindKernelDoNothing;

  return Success;
end);

#FindHomMethodsProjective.BalTreeForBlocks := function(ri,G)
#  local H,cut,dim,hom,newgens,nrblocks,subdim,gen;
#  dim := ri!.dimension;
#  nrblocks := dim / ri!.blocksize;   # this we know from above
#  if nrblocks = 1 then     # this might happen during the descent into the tree
#      return false;
#  fi;
#  cut := QuoInt(nrblocks,2);  # this is now at least 1
#  subdim := cut * ri!.blocksize;
#
#  # Project onto image:
#  newgens := List(GeneratorsOfGroup(G),
#                  x->ExtractSubMatrix(x,[subdim+1..dim],[subdim+1..dim]));
#  for gen in newgens do
#      ConvertToMatrixRep(gen);
#  od;
#  H := GroupWithGenerators(newgens);
#  hom := GroupHomByFuncWithData(G,H,RECOG.HomInducedOnFactor,
#                                rec(subdim := subdim));
#  SetHomom(ri,hom);
#
#  # Create some more kernel generators:
#  findgensNmeth(ri).args[1] := 20 + nrblocks;
#
#  # Pass the block information on to the image:
#  InitialDataForImageRecogNode(ri).blocksize := ri!.blocksize;
#  AddMethod(InitialDataForImageRecogNode(ri).hints, FindHomMethodsProjective.BalTreeForBlocks, 2000);
#
#  # Inform authorities that the kernel can be recognised easily:
#  InitialDataForKernelRecogNode(ri).subdim := subdim;
#  InitialDataForKernelRecogNode(ri).blocksize := ri!.blocksize;
#  AddMethod(InitialDataForKernelRecogNode(ri).hints, FindHomMethodsProjective.BalTreeForBlocksProjKernel, 2000);
#
#  # Verify the kernel immediately after its recognition:
#  Setimmediateverification(ri,true);
#
#  return Success;
#end;
#
#RECOG.HomInducedOnSubspace := function(data,el)
#  local m;
#  m := ExtractSubMatrix(el,[1..data.subdim],[1..data.subdim]);
#  # FIXME: no longer necessary, as soon as the new interface is in place
#  ConvertToMatrixRep(m);
#  return m;
#end;

#FindHomMethodsMatrix.InducedOnSubspace := function(ri,G)
#  local H,dim,gens,hom,newgens,gen,data;
#  # Are we applicable?
#  if not IsBound(ri!.subdim) then
#      return NotEnoughInformation;
#  fi;
#
#  # Project onto subspace:
#  gens := GeneratorsOfGroup(G);
#  data := rec(subdim := ri!.subdim);
#  newgens := List(gens, x->RECOG.HomInducedOnSubspace(data,x));
#  H := Group(newgens);
#  hom := GroupHomByFuncWithData(G,H,RECOG.HomInducedOnSubspace,data);
#
#  # Now report back:
#  SetHomom(ri,hom);
#
#  # We know that the kernel is a GF(p) vectorspace and thus may need
#  # quite some generators. Therefore we generate them in a non-standard
#  # way such that we can be reasonably sure that we got enough:
#  findgensNmeth(ri).method := FindKernelLowerLeftPGroup;
#  findgensNmeth(ri).args := [];
#
#  # Inform authorities that the kernel can be recognised easily:
#  InitialDataForKernelRecogNode(ri).subdim := ri!.subdim;
#  AddMethod(InitialDataForKernelRecogNode(ri).hints, FindHomMethodsMatrix.LowerLeftPGroup, 2000);
#
#  return Success;
#end;

#FindHomMethodsProjective.BalTreeForBlocksProjKernel := function(ri,G)
#  # We just have to project onto the upper left corner, see
#  local H,gen,hom,newgens;
#
#  newgens := List(GeneratorsOfGroup(G),x->x{[1..ri!.subdim]}{[1..ri!.subdim]});
#  for gen in newgens do ConvertToMatrixRep(gen); od;
#  H := Group(newgens);
#  hom := GroupHomByFuncWithData(G,H,RECOG.HomInducedOnSubspace,
#                                rec(subdim := ri!.subdim));
#  SetHomom(ri,hom);
#
#  findgensNmeth(ri).method := FindKernelDoNothing;
#
#  # But pass on the information on blocks:
#  InitialDataForImageRecogNode(ri).blocksize := ri!.blocksize;
#  AddMethod(InitialDataForImageRecogNode(ri).hints, FindHomMethodsProjective.BalTreeForBlocks, 2000);
#
#  return Success;
#end;

[ Verzeichnis aufwärts0.50unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]