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

Quelle  projective.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
##
##
##  A collection of find homomorphism methods for projective groups.
##
#############################################################################

SLPforElementFuncsProjective.TrivialGroup_BlocksModScalars := function(ri,g)
    if not IsDiagonalMat(g) then
        return fail;
    fi;
    return StraightLineProgramNC( [ [1,0] ], 1 );
end;

#! @BeginChunk BlocksModScalars
#! This method is only called when hinted from above. In this method it is
#! understood that G should <E>neither</E>
#! be recognised as a matrix group <E>nor</E> as a projective group.
#! Rather, it treats all diagonal blocks modulo scalars which means that
#! two matrices are considered to be equal, if they differ only by a scalar
#! factor in <E>corresponding</E> diagonal blocks, and this scalar can
#! be different for each diagonal block. This means that the kernel of
#! the homomorphism mapping to a node which is recognised using this
#! method will have only scalar matrices in all diagonal blocks.
#!
#! This method does the balanced tree approach mapping to subsets of the
#! diagonal blocks and finally using projective recognition to recognise
#! single diagonal block groups.
#! @EndChunk
BindRecogMethod(FindHomMethodsProjective, "BlocksModScalars",
"TODO",
function(ri, G)
  # We assume that ri!.blocks is a list of ranges where the diagonal
  # 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.
  # Note further that in this method it is understood that G should *neither*
  # be recognised as a matrix group *nor* as a projective group. Rather,
  # all "block-scalars" shall be ignored. This method is only used when
  # used as a hint by FindHomMethodsMatrix.BlockDiagonal!
  local H,data,hom,middle,newgens,nrblocks,topblock;
  nrblocks := Length(ri!.blocks);  # this is always >= 1
  if ForAll(ri!.blocks,b->Length(b)=1) then
      # All blocks are projectively trivial, so nothing to do here:
      SetSize(ri,1);
      Setslpforelement(ri, SLPforElementFuncsProjective.TrivialGroup_BlocksModScalars);
      Setslptonice( ri, StraightLineProgramNC([[[1,0]]],
                                              Length(GeneratorsOfGroup(G))));
      SetFilterObj(ri,IsLeaf);
      ri!.comment := "BlocksDim=1";
      return Success;
  fi;

  if nrblocks = 1 then   # in this case the block is everything!
      # no hints for the image, will run into diagonal and notice scalar
      data := rec(poss := ri!.blocks[1]);
      newgens := List(GeneratorsOfGroup(G),x->RECOG.HomToDiagonalBlock(data,x));
      H := GroupWithGenerators(newgens);
      hom := GroupHomByFuncWithData(G,H,RECOG.HomToDiagonalBlock,data);
      SetHomom(ri,hom);
      # The following is already be set, but make it explicit here:
      Setmethodsforimage(ri,FindHomDbProjective);
      # no kernel:
      findgensNmeth(ri).method := FindKernelDoNothing;
      return Success;
  fi;
  # Otherwise more than one block, cut in half:
  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));
  H := GroupWithGenerators(newgens);
  hom := GroupHomByFuncWithData(G,H,RECOG.HomToDiagonalBlock,data);
  SetHomom(ri,hom);

  # the image are the last few blocks:
  # The following is already be set, but make it explicit here:
  Setmethodsforimage(ri,FindHomDbProjective);
  if middle < nrblocks then   # more than one block in image:
      InitialDataForImageRecogNode(ri).blocks := List(ri!.blocks{[middle..nrblocks]},
                                   x->x - (ri!.blocks[middle][1]-1));
      AddMethod(InitialDataForImageRecogNode(ri).hints,
                FindHomMethodsProjective.BlocksModScalars,
                2000);
  fi; # Otherwise the image is to be recognised projectively as usual

  # the kernel is the first few blocks:
  findgensNmeth(ri).args[1] := 10 + nrblocks;
  findgensNmeth(ri).args[2] := 5 + middle - 1;
  # The following is already set, but make it explicit here:
  InitialDataForKernelRecogNode(ri).blocks := ri!.blocks{[1..middle-1]};
  AddMethod(InitialDataForKernelRecogNode(ri).hints, FindHomMethodsProjective.BlocksModScalars, 2000);
  Setimmediateverification(ri,true);
  return Success;
end);

SLPforElementFuncsProjective.StabilizerChainProj := function(ri,x)
  local r;
  r := SiftGroupElementSLP(ri!.stabilizerchain,x);
  return r.slp;
end;

#! @BeginChunk StabilizerChainProj
#! This method computes a stabiliser chain and a base and strong generating
#! set using projective actions. This is a last resort method since for
#! bigger examples no short orbits can be found in the natural action.
#! The strong generators are the nice generator in this case and expressing
#! group elements in terms of the nice generators ist just sifting along
#! the stabiliser chain.
#! @EndChunk
# TODO: merge FindHomMethodsPerm.StabilizerChainPerm and  FindHomMethodsProjective.StabilizerChainProj ?
BindRecogMethod(FindHomMethodsProjective, "StabilizerChainProj",
"last resort: compute a stabilizer chain (projectively)",
function(ri, G)
  local Gm,S,SS,d,f,fu,opt,perms,q;
  d := ri!.dimension;
  f := ri!.field;
  q := Size(f);
  fu := function() return RandomElm(ri,"StabilizerChainProj",true).el; end;
  opt := rec( Projective := true, RandomElmFunc := fu );
  Gm := GroupWithGenerators(ri!.gensHmem);
  S := StabilizerChain(Gm,opt);
  perms := ActionOnOrbit(S!.orb,ri!.gensHmem);
  SS := StabilizerChain(Group(perms));
  if Size(SS) = Size(S) then
      SetSize(ri,Size(S));
      ri!.stabilizerchain := S;
      Setslptonice(ri,SLPOfElms(StrongGenerators(S)));
      ForgetMemory(S);
      Unbind(S!.opt.RandomElmFunc);
      Setslpforelement(ri,SLPforElementFuncsProjective.StabilizerChainProj);
      SetFilterObj(ri,IsLeaf);
  else
      ForgetMemory(S);
      SetHomom(ri,OrbActionHomomorphism(G,S!.orb));
      Setmethodsforimage(ri,FindHomDbPerm);
  fi;
  return Success;
end);

RECOG.HomProjDet := function(data,m)
  local x;
  x := LogFFE(DeterminantMat(m),data.z);
  if x = fail then
      return fail;
  fi;
  return data.c ^ (x mod data.gcd);
end;

#! @BeginChunk ProjDeterminant
#! The method defines a homomorphism from a projective group <A>G</A><M> \le
#! PGL(d,q)</M> to the cyclic group <M>GF(q)^*/D</M>, where <M>D</M> is the set
#! of <M>d</M>th powers in <M>GF(q)^*</M>. The image of a group
#! element <M>g \in <A>G</A></M> is the determinant of a matrix representative of
#! <M>g</M>, modulo <M>D</M>.
#! @EndChunk
BindRecogMethod(FindHomMethodsProjective, "ProjDeterminant",
"find homomorphism to non-zero scalars mod d-th powers",
function(ri, G)
  local H,c,d,detsadd,f,gcd,hom,newgens,q,z;
  f := ri!.field;
  d := ri!.dimension;
  q := Size(f);
  gcd := GcdInt(q-1,d);
  if gcd = 1 then
      return NeverApplicable;
  fi;
  z := Z(q);
  detsadd := List(GeneratorsOfGroup(G),x->LogFFE(DeterminantMat(x),z) mod gcd);
  if IsZero(detsadd) then
      return NeverApplicable;
  fi;
  Info(InfoRecog,2,"ProjDeterminant: found non-trivial homomorphism.");
  c := PermList(Concatenation([2..gcd],[1]));
  newgens := List(detsadd,x->c^x);
  H := GroupWithGenerators(newgens);
  hom := GroupHomByFuncWithData(G,H,RECOG.HomProjDet,
                                rec(c := c, z := z, gcd := gcd));
  SetHomom(ri,hom);
  Setmethodsforimage(ri,FindHomDbPerm);
  findgensNmeth(ri).args[1] := 8;
  findgensNmeth(ri).args[2] := 5;
  Setimmediateverification(ri,true);
  return Success;
end);

RECOG.IsBlockScalarMatrix := function(blocks, x)
  local b, s;
  if not IsDiagonalMat(x) then
      return false;
  fi;
  for b in blocks do
      s := b[1];
      s := x[s,s];
      if not ForAll(b, pos -> x[pos,pos] = s) then
          return false;
      fi;
  od;
  return true;
end;

# scale the given block-scalar matrix x so that its last block
# is the identity matrix
RECOG.HomNormLastBlock := function(data, x)
  local blocks, pos, s;
  blocks := data!.blocks;
  if not RECOG.IsBlockScalarMatrix(blocks, x) then
      return fail;
  fi;
  pos := blocks[Length(blocks)][1];
  s := x[pos,pos];
  if not IsOne(s) then
      x := s^-1 * x;
  fi;
  return x;
end;

#! @BeginChunk BlockScalarProj
#! This method is only called by a hint. Alongside with the hint it gets
#! a block decomposition respected by the matrix group <A>G</A> to be recognised
#! and the promise that all diagonal blocks of all group elements
#! will only be scalar matrices. This method simply norms the last diagonal
#! block in all generators by multiplying with a scalar and then
#! delegates to <C>BlockScalar</C> (see <Ref Subsect="BlockScalar"/>)
#! and matrix group mode to do the recognition.
#! @EndChunk
BindRecogMethod(FindHomMethodsProjective, "BlockScalarProj",
"TODO",
function(ri, G)
  # We just norm the last block and go to matrix methods.
  local H,data,hom,newgens,g;
  data := rec( blocks := ri!.blocks );
  newgens := [];
  for g in GeneratorsOfGroup(G) do
      g := RECOG.HomNormLastBlock(data, g);
      if g = fail then
          return NeverApplicable;
      fi;
      Add(newgens, g);
  od;
  H := GroupWithGenerators(newgens);
  hom := GroupHomByFuncWithData(G,H,RECOG.HomNormLastBlock,data);
  SetHomom(ri,hom);

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

  # Switch to matrix mode:
  Setmethodsforimage(ri,FindHomDbMatrix);
  AddMethod(InitialDataForImageRecogNode(ri).hints, FindHomMethodsMatrix.BlockScalar, 2000);
  InitialDataForImageRecogNode(ri).blocks := ri!.blocks{[1..Length(ri!.blocks)-1]};
  return Success;
end);

RECOG.MakeAlternatingMatrixReps := function(deg,f,tens)
  local a,b,gens,gens2,i,m,ogens,r;
  a := AlternatingGroup(deg);
  gens := List(GeneratorsOfGroup(a),x->PermutationMat(x,deg,f));
  ogens := ShallowCopy(gens);
  for i in [1..tens] do
      gens2 := [];
      for i in [1..Length(gens)] do
          Add(gens2,KroneckerProduct(gens[i],ogens[i]));
      od;
      gens := gens2;
  od;
  m := GModuleByMats(gens,f);
  r := MTX.CollectedFactors(m);
  return List(r,x->x[1].generators);
end;

RECOG.MakeSymmetricMatrixReps := function(deg,f,tens)
  local a,b,gens,gens2,i,m,ogens,r;
  a := SymmetricGroup(deg);
  gens := List(GeneratorsOfGroup(a),x->PermutationMat(x,deg,f));
  ogens := ShallowCopy(gens);
  for i in [1..tens] do
      gens2 := [];
      for i in [1..Length(gens)] do
          Add(gens2,KroneckerProduct(gens[i],ogens[i]));
      od;
      gens := gens2;
  od;
  m := GModuleByMats(gens,f);
  r := MTX.CollectedFactors(m);
  return List(r,x->x[1].generators);
end;

# The method installations:

#! @BeginCode AddMethod_Projective_FindHomMethodsGeneric.TrivialGroup
AddMethod(FindHomDbProjective, FindHomMethodsGeneric.TrivialGroup, 3000);
#! @EndCode

AddMethod(FindHomDbProjective, FindHomMethodsProjective.ProjDeterminant, 1300);

AddMethod(FindHomDbPerm, FindHomMethodsGeneric.FewGensAbelian, 1250);

# Note that we *can* in fact use the Matrix method here, because it
# will do the right thing when used in projective mode:
AddMethod(FindHomDbProjective, FindHomMethodsMatrix.ReducibleIso, 1200);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.NotAbsolutelyIrred, 1100);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.ClassicalNatural, 1050);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.Subfield, 1000);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.C3C5, 900);

#AddMethod( FindHomDbProjective, FindHomMethodsProjective.Derived,
#   900, "Derived",
#        "restrict to derived subgroup" );
# Superseded by C3C5.

AddMethod(FindHomDbProjective, FindHomMethodsProjective.C6, 850);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.D247, 840);

# # We can do the following early on since it will quickly fail for
# # non-sporadic groups:
# AddMethod(FindHomDbProjective, FindHomMethodsProjective.SporadicsByOrders, 820);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.AltSymBBByDegree, 810);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.TensorDecomposable, 800);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.FindElmOfEvenNormal, 700);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.LowIndex, 600);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.NameSporadic, 580);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.ComputeSimpleSocle, 550);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.ThreeLargeElOrders, 500);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.LieTypeNonConstr, 400);

AddMethod(FindHomDbProjective, FindHomMethodsProjective.StabilizerChainProj, 100);


# Old methods which are no longer used:

#AddMethod( FindHomDbProjective, FindHomMethodsProjective.FindEvenNormal,
#   825, "FindEvenNormal",
#        "find D2, D4 or D7 by finding reducible normal subgroup" );
#AddMethod( FindHomDbProjective, FindHomMethodsProjective.AlternatingBBByOrders,
#   580, "AlternatingBBByOrders",
#        "generate a few random elements and compute the proj. orders" );

[ Dauer der Verarbeitung: 0.37 Sekunden  (vorverarbeitet)  ]