Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/semigroups/tst/workspaces/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 29.7.2025 mit Größe 410 B image not shown  

Quelle  corefreesub.gi   Sprache: unbekannt

 
#
# corefreesub: A GAP Package for calculating the core-free subgroups and their faithful transitive permutation representations
#
# Implementations
#
#
#
### Testing Functions
BindGlobal( "CF_TESTALL",
  function()
 local tests, doctests, AUTODOC_file_scan_list;
  AUTODOC_file_scan_list := [ "../PackageInfo.g", "../gap/CF_splashfromViz.g", "../gap/corefreesub.gd", "../gap/corefreesub.gi", "../gap/drawftpr.gd", "../gap/drawftpr.gi", "../init.g", "../makedoc.g", "../maketest.g", "../read.g", Filename(DirectoriesPackageLibrary("corefreesub", "doc"),"_Chunks.xml") ];
  LoadPackage( "GAPDoc" );
  doctests := ExtractExamples( DirectoriesPackageLibrary("corefreesub", "doc"), "corefreesub.xml", AUTODOC_file_scan_list, 500 );
  RunExamples( doctests, rec( compareFunction := "uptowhitespace" ) );
  Test(Filename(DirectoriesPackageLibrary( "corefreesub", "tst" )[1],"OtherTest.g"));
end);


BindGlobal("CoreFreeConjugacyClassesSubgroupsCyclicExtension",
        function(arg)
  local G,                 # group
        func,              # test function
        zuppofunc,         # test fct for zuppos
        noperf,            # discard perfect groups
        lattice,           # lattice (result)
        factors,           # factorization of <G>'s size
        zuppos,            # generators of prime power order
        zupposPrime,       # corresponding prime
        zupposPower,       # index of power of generator
        ZupposSubgroup,    # function to compute zuppos for subgroup
        zuperms,           # permutation of zuppos by group
        Gimg,              # grp image under zuperms
        nrClasses,         # number of classes
        classes,           # list of all classes
        classesZups,       # zuppos blist of classes
        classesExts,       # extend-by blist of classes
        perfect,           # classes of perfect subgroups of <G>
        perfectNew,        # this class of perfect subgroups is new
        perfectZups,       # zuppos blist of perfect subgroups
        layerb,            # begin of previous layer
        layere,            # end of previous layer
        H,                 # representative of a class
        Hzups,             # zuppos blist of <H>
        Hexts,             # extend blist of <H>
        C,                 # class of <I>
        I,                 # new subgroup found
        Ielms,             # elements of <I>
        Izups,             # zuppos blist of <I>
        N,                 # normalizer of <I>
        Nzups,             # zuppos blist of <N>
        Jzups,             # zuppos of a conjugate of <I>
        Kzups,             # zuppos of a representative in <classes>
        reps,              # transversal of <N> in <G>
        corefreedegrees,
        ac,
        transv,
        factored,
        mapped,
        expandmem,
        h,i,k,l,ri,rl,r;      # loop variables

  G:=arg[1];
  noperf:=false;
  zuppofunc:=false;
  if Length(arg)>1 and (IsFunction(arg[2]) or IsList(arg[2])) then
    func:=arg[2];
    Info(InfoLattice,1,"lattice discarding function active!");
    if IsList(func) then
      zuppofunc:=func[2];
      func:=func[1];
    fi;
    if Length(arg)>2 and IsBool(arg[3]) then
      noperf:=arg[3];
    fi;
  else
    func:=false;
  fi;

  expandmem:=ValueOption("Expand")=true;

  # if store is true, an element list will be kept in `Ielms' if possible
  ZupposSubgroup:=function(U,store)
    local elms,zups;
    if Size(U)=Size(G) then
      if store then Ielms:=fail;fi;
      zups:=BlistList([1..Length(zuppos)],[1..Length(zuppos)]);
    elif Size(U)>10^4 then
      # the group is very big - test the zuppos with `in'
      Info(InfoLattice,3,"testing zuppos with `in'");
      if store then Ielms:=fail;fi;
      zups:=List(zuppos,i->i in U);
      IsBlist(zups);
    else
      elms:=AsSSortedListNonstored(U);
      if store then Ielms:=elms;fi;
      zups:=BlistList(zuppos,elms);
    fi;
    return zups;
  end;

  # compute the factorized size of <G>
  factors:=Factors(Size(G));

  # compute a system of generators for the cyclic sgr. of prime power size
  if zuppofunc<>false then
    zuppos:=Zuppos(G,zuppofunc);
  else
    zuppos:=Zuppos(G);
  fi;

  Info(InfoLattice,1,"<G> has ",Length(zuppos)," zuppos");

  # compute zuppo permutation
  if IsPermGroup(G) then
    zuppos:=List(zuppos,SmallestGeneratorPerm);
    zuppos:=AsSSortedList(zuppos);
    zuperms:=List(GeneratorsOfGroup(G),
                  i->Permutation(i,zuppos,function(x,a)
      return SmallestGeneratorPerm(x^a);
    end));
    if NrMovedPoints(zuperms)<200*NrMovedPoints(G) then
      zuperms:=GroupHomomorphismByImagesNC(G,Group(zuperms),
                       GeneratorsOfGroup(G),zuperms);
      # force kernel, also enforces injective setting
      Gimg:=Image(zuperms);
      if Size(KernelOfMultiplicativeGeneralMapping(zuperms))=1 then
        SetSize(Gimg,Size(G));
      fi;
    else
      zuperms:=fail;
    fi;
  else
    zuppos:=AsSSortedList(zuppos);
    zuperms:=fail;
  fi;

  # compute the prime corresponding to each zuppo and the index of power
  zupposPrime:=[];
  zupposPower:=[];
  for r  in zuppos  do
    i:=SmallestRootInt(Order(r));
    Add(zupposPrime,i);
    k:=0;
    while k <> false  do
      k:=k + 1;
      if GcdInt(i,k) = 1  then
        l:=Position(zuppos,r^(i*k));
        if l <> fail  then
          Add(zupposPower,l);
          k:=false;
        fi;
      fi;
    od;
  od;
  Info(InfoLattice,1,"powers computed");

  if func<>false and
     (noperf or func in SOLVABILITY_IMPLYING_FUNCTIONS) then
    Info(InfoLattice,1,"Ignoring perfect subgroups");
    perfect:=[];
  else
    if IsPermGroup(G) then
      # trigger potentially better methods
      IsNaturalSymmetricGroup(G);
      IsNaturalAlternatingGroup(G);
    fi;
    perfect:=RepresentativesPerfectSubgroups(G);
    perfect:=Filtered(perfect,i->Size(i)>1 and Size(i)<Size(G));
    if func<>false then
      perfect:=Filtered(perfect,func);
    fi;
    perfect:=List(perfect,i->AsSubgroup(Parent(G),i));
  fi;

  perfectZups:=[];
  perfectNew :=[];
  for i  in [1..Length(perfect)]  do
    I:=perfect[i];
    #perfectZups[i]:=BlistList(zuppos,AsSSortedListNonstored(I));
    perfectZups[i]:=ZupposSubgroup(I,false);
    perfectNew[i]:=true;
  od;
  Info(InfoLattice,1,"<G> has ",Length(perfect),
       " representatives of perfect subgroups");

  # initialize the classes list
  nrClasses:=1;
  classes:=ConjugacyClassSubgroups(G,TrivialSubgroup(G));
  SetSize(classes,1);
  classes:=[classes];
  corefreedegrees := [Size(G)];
  classesZups:=[BlistList(zuppos,[One(G)])];
  classesExts:=[DifferenceBlist(BlistList(zuppos,zuppos),classesZups[1])];
  layerb:=1;
  layere:=1;

  # loop over the layers of group (except the group itself)
  for l  in [1..Length(factors)-1]  do
    Info(InfoLattice,1,"doing layer ",l,",",
         "previous layer has ",layere-layerb+1," classes");

    # extend representatives of the classes of the previous layer
    for h  in [layerb..layere]  do

      # get the representative,its zuppos blist and extend-by blist
      H:=Representative(classes[h]);
      Hzups:=classesZups[h];
      Hexts:=classesExts[h];
      Info(InfoLattice,2,"extending subgroup ",h,", size = ",Size(H));

      # loop over the zuppos whose <p>-th power lies in <H>
      for i  in [1..Length(zuppos)]  do

        if Hexts[i] and Hzups[zupposPower[i]]  then

          # make the new subgroup <I>
          # NC is safe -- all groups are subgroups of Parent(H)
          I:=ClosureSubgroupNC(H,zuppos[i]);
          #Subgroup(Parent(G),Concatenation(GeneratorsOfGroup(H),
          #                           [zuppos[i]]));
          if IsCoreFree(G,I) and (func=false or func(I)) then

            SetSize(I,Size(H) * zupposPrime[i]);

            # compute the zuppos blist of <I>
            #Ielms:=AsSSortedListNonstored(I);
            #Izups:=BlistList(zuppos,Ielms);
            if zuperms=fail then
              Izups:=ZupposSubgroup(I,true);
            else
              Izups:=ZupposSubgroup(I,false);
            fi;

            # compute the normalizer of <I>
            N:=Normalizer(G,I);
            #AH 'NormalizerInParent' attribute ?
            Info(InfoLattice,2,"found new class ",nrClasses+1,
                 ", size = ",Size(I)," length = ",Size(G)/Size(N));

            # make the new conjugacy class
            C:=ConjugacyClassSubgroups(G,I);
            SetSize(C,Size(G) / Size(N));
            SetStabilizerOfExternalSet(C,N);
            nrClasses:=nrClasses + 1;
            classes[nrClasses]:=C;
            Add(corefreedegrees,Index(G,I));

            # store the extend by list
            if l < Length(factors)-1  then
              classesZups[nrClasses]:=Izups;
              #Nzups:=BlistList(zuppos,AsSSortedListNonstored(N));
              Nzups:=ZupposSubgroup(N,false);
              SubtractBlist(Nzups,Izups);
              classesExts[nrClasses]:=Nzups;
            fi;

            # compute the right transversal
            # (but don't store it in the parent)
            if expandmem and zuperms<>fail then
              if Index(G,N)>400 then
                ac:=AscendingChainOp(G,N); # do not store
                while Length(ac)>2 and Index(ac[3],ac[1])<100 do
                  ac:=Concatenation([ac[1]],ac{[3..Length(ac)]});
                od;
                if Length(ac)>2 and
                   Maximum(List([3..Length(ac)],x->Index(ac[x],ac[x-1])))<500
                   then

                  # mapped factorized transversal
                  Info(InfoLattice,3,"factorized transversal ",
                       List([2..Length(ac)],x->Index(ac[x],ac[x-1])));
                  transv:=[];
                  ac[Length(ac)]:=Gimg;
                  for ri in [Length(ac)-1,Length(ac)-2..1] do
                    ac[ri]:=Image(zuperms,ac[ri]);
                    if ri=1 then
                      transv[ri]:=List(RightTransversalOp(ac[ri+1],ac[ri]),
                                       i->Permuted(Izups,i));
                    else
                      transv[ri]:=AsList(RightTransversalOp(ac[ri+1],ac[ri]));
                    fi;
                  od;
                  mapped:=true;
                  factored:=true;
                  reps:=Cartesian(transv);
                  Unbind(ac);
                  Unbind(transv);
                else
                  reps:=RightTransversalOp(Gimg,Image(zuperms,N));
                  mapped:=true;
                  factored:=false;
                fi;
              else
                reps:=RightTransversalOp(G,N);
                mapped:=false;
                factored:=false;
              fi;
            else
              reps:=RightTransversalOp(G,N);
              mapped:=false;
              factored:=false;
            fi;

            # loop over the conjugates of <I>
            for ri in [1..Length(reps)] do
              CompletionBar(InfoLattice,3,"Coset loop: ",ri/Length(reps));
              r:=reps[ri];

              # compute the zuppos blist of the conjugate
              if zuperms<>fail then
                # we know the permutation of zuppos by the group
                if mapped then
                  if factored then
                    Jzups:=r[1];
                    for rl in [2..Length(r)] do
                      Jzups:=Permuted(Jzups,r[rl]);
                    od;
                  else
                    Jzups:=Permuted(Izups,r);
                  fi;
                else
                  if factored then
                    Error("factored");
                  else
                    Jzups:=Image(zuperms,r);
                    Jzups:=Permuted(Izups,Jzups);
                  fi;
                fi;
              elif r = One(G)  then
                Jzups:=Izups;
              elif Ielms<>fail then
                Jzups:=BlistList(zuppos,OnTuples(Ielms,r));
              else
                Jzups:=ZupposSubgroup(I^r,false);
              fi;

              # loop over the already found classes
              for k  in [h..layere]  do
                Kzups:=classesZups[k];

                # test if the <K> is a subgroup of <J>
                if IsSubsetBlist(Jzups,Kzups)  then
                  # don't extend <K> by the elements of <J>
                  SubtractBlist(classesExts[k],Jzups);
                fi;

              od;

            od;
            CompletionBar(InfoLattice,3,"Coset loop: ",false);

            # now we are done with the new class
            Unbind(Ielms);
            Unbind(reps);
            Info(InfoLattice,2,"tested inclusions");

          else
            Info(InfoLattice,1,"discarded!");
          fi; # if condition fulfilled

        fi; # if Hexts[i] and Hzups[zupposPower[i]]  then ...
      od; # for i  in [1..Length(zuppos)]  do ...

      # remove the stuff we don't need any more
      Unbind(classesZups[h]);
      Unbind(classesExts[h]);
    od; # for h  in [layerb..layere]  do ...

    # add the classes of perfect subgroups
    for i  in [1..Length(perfect)]  do
      if    perfectNew[i]
            and IsPerfectGroup(perfect[i])
            and Length(Factors(Size(perfect[i]))) = l
            and IsCoreFree(G,perfect[i])
            then

        # make the new subgroup <I>
        I:=perfect[i];

        # compute the zuppos blist of <I>
        #Ielms:=AsSSortedListNonstored(I);
        #Izups:=BlistList(zuppos,Ielms);
        if zuperms=fail then
          Izups:=ZupposSubgroup(I,true);
        else
          Izups:=ZupposSubgroup(I,false);
        fi;

        # compute the normalizer of <I>
        N:=Normalizer(G,I);
        # AH: NormalizerInParent ?
        Info(InfoLattice,2,"found perfect class ",nrClasses+1,
             " size = ",Size(I),", length = ",Size(G)/Size(N));

        # make the new conjugacy class
        C:=ConjugacyClassSubgroups(G,I);
        SetSize(C,Size(G)/Size(N));
        SetStabilizerOfExternalSet(C,N);
        nrClasses:=nrClasses + 1;
        classes[nrClasses]:=C;
        Add(corefreedegrees,Index(G,I));
        # store the extend by list
        if l < Length(factors)-1  then
          classesZups[nrClasses]:=Izups;
          #Nzups:=BlistList(zuppos,AsSSortedListNonstored(N));
          Nzups:=ZupposSubgroup(N,false);
          SubtractBlist(Nzups,Izups);
          classesExts[nrClasses]:=Nzups;
        fi;

        # compute the right transversal
        # (but don't store it in the parent)
        reps:=RightTransversalOp(G,N);

        # loop over the conjugates of <I>
        for r  in reps  do

          # compute the zuppos blist of the conjugate
          if zuperms<>fail then
            # we know the permutation of zuppos by the group
            Jzups:=Image(zuperms,r);
            Jzups:=Permuted(Izups,Jzups);
          elif r = One(G)  then
            Jzups:=Izups;
          elif Ielms<>fail then
            Jzups:=BlistList(zuppos,OnTuples(Ielms,r));
          else
            Jzups:=ZupposSubgroup(I^r,false);
          fi;

          # loop over the perfect classes
          for k  in [i+1..Length(perfect)]  do
            Kzups:=perfectZups[k];

            # throw away classes that appear twice in perfect
            if Jzups = Kzups  then
              perfectNew[k]:=false;
              perfectZups[k]:=[];
            fi;

          od;

        od;

        # now we are done with the new class
        Unbind(Ielms);
        Unbind(reps);
        Info(InfoLattice,2,"tested equalities");

        # unbind the stuff we dont need any more
        perfectZups[i]:=[];

      fi;
      # if IsPerfectGroup(I) and Length(Factors(Size(I))) = layer the...
    od; # for i  in [1..Length(perfect)]  do

    # on to the next layer
    layerb:=layere+1;
    layere:=nrClasses;

  od; # for l  in [1..Length(factors)-1]  do ...

  # add the whole group to the list of classes
  Info(InfoLattice,1,"doing layer ",Length(factors),",",
       " previous layer has ",layere-layerb+1," classes");

  # return the list of classes
  Info(InfoLattice,1,"<G> has ",nrClasses," classes,",
       " and ",Sum(classes,Size)," subgroups");
  Sort(corefreedegrees);
  Sort(classes,function(a,b)
    return Size(Representative(a))<Size(Representative(b));
  end);
  G!.coreFreeConjugacyClassesSubgroups := classes;
  G!.coreFreeDegrees := Unique(corefreedegrees);
  return G!.coreFreeConjugacyClassesSubgroups;
end);

BindGlobal( "CoreFreeConjugacyClassesSubgroupsNiceMonomorphism",
        function(G)
  local hom, classes,NiceO;
  hom:= NiceMonomorphism( G );
  NiceO := NiceObject(G);
  classes:= List( CoreFreeConjugacyClassesSubgroups( NiceO ),
                  C -> ConjugacyClassSubgroups( G,
                          PreImage( hom, Representative( C ) ) ) );
  Sort(classes,function(a,b)
    return Size(Representative(a))<Size(Representative(b));
  end);
  G!.coreFreeConjugacyClassesSubgroups := classes;
  return G!.coreFreeConjugacyClassesSubgroups;
end );

BindGlobal( "CoreFreeConjugacyClassesSubgroupsOfSolvableGroup",
  #### The function "CoreFreeConjugacyClassesSubgroupsOfSolvableGroup" is a modified version from "FiniteSubgroupClassesBySeries" 
  #### from "Polycyclic" version 2.16 GAP Package, under GNU General Public License v2 or above.
    function(G)
    local s,i,c,k,CoreFreeClasses,map,GI, PCPGI, map2, pcps,
     pcpG, grps, grp, cfgrps, pcp, rels, act, new, newcore, C, tmp ;

    if not IsPcGroup(G) or IsPermGroup(G) then
        map:=IsomorphismPcGroup(G);
        GI:=Image(map,G);
    else
        map:=fail;
        GI:=G;
    fi;
    map2 := IsomorphismPcpGroup(GI);
    PCPGI := Image(map2,GI);
    
    pcps:= PcpsOfEfaSeries(PCPGI);

    pcpG := Pcp( PCPGI );
    grps := [ rec( repr := PCPGI , norm := PCPGI) ];
    cfgrps := [];
    for pcp in pcps do
        rels := RelativeOrdersOfPcp( pcp );
        act := OperationAndSpaces( pcpG, pcp );
        new := [];
        newcore := [];
        for i in [1..Length( grps ) ] do
            grp := grps[i];
            Info( InfoPcpGrp, 1, "  group number ", i );

            # set up class record
            C := rec( );
            C.group  := grp.repr;
            C.super  := Pcp( grp.norm, grp.repr );
            C.factor := Pcp( grp.repr, GroupOfPcp( pcp ) );
            C.normal := pcp;

            # add extension info
            AddFieldCR( C );
            AddRelatorsCR( C );

            # add action
            TranslateAction( C, pcpG, act.mats );

            # if it is free abelian, compute complements
            if C.char = 0 then
                AddInversesCR( C );
                tmp := ComplementClassesCR( C );
                Info( InfoPcpGrp, 1, "  computed ", Length(tmp),
                    " complements");
            else
                if IsBound( act.spaces ) then C.spaces := act.spaces; fi;
                tmp := SupplementClassesCR( C );
                Info( InfoPcpGrp, 1, "  computed ", Length(tmp),
                    " supplements");
            fi;

            Append( new, tmp );
            for k in [1 .. Size(tmp)] do
              if IsCoreFree(GI,PreImage(map2,tmp[k].repr)) then
                Append( newcore, [tmp[k]] );
              fi;
            od;
        od;
        Append( cfgrps, newcore);
        if C.char = 0 then
            grps := ShallowCopy( new );
        else
            Append( grps, new );
        fi;
    od;


    CoreFreeClasses := [];
    # translate to classes and return

    for i in [1..Length(cfgrps)] do
        if map=fail then
        c:=ConjugacyClassSubgroups(G,PreImage(map2,cfgrps[i].repr));
        SetStabilizerOfExternalSet(c,PreImage(map2,cfgrps[i].norm));
        Add(CoreFreeClasses,c);
        else
        c:=ConjugacyClassSubgroups(G,PreImage(map,PreImage(map2,cfgrps[i].repr)));
        SetStabilizerOfExternalSet(c,PreImage(map,PreImage(map2,cfgrps[i].norm)));
        Add(CoreFreeClasses,c);
        fi;
    od;
    

    Sort(CoreFreeClasses,function(a,b)
        return Size(Representative(a))<Size(Representative(b));
    end);
    G!.coreFreeConjugacyClassesSubgroups := CoreFreeClasses;
    return G!.coreFreeConjugacyClassesSubgroups;
end);

BindGlobal("CoreFreeSubgroupsTrivialFitting",function(G)
  local s,a,n,fac,iso,types,t,p,i,map,go,gold,nf,tom,sub,len,pos_list_cf;

  n:=DirectFactorsFittingFreeSocle(G);

  # is it almost simple and stored?
  if Length(n)=1 then
    tom:=TomDataAlmostSimpleRecognition(G);
    if tom<>fail then
      go:=ImagesSource(tom[1]);
      len:=LengthsTom(tom[2]);
      pos_list_cf := Filtered([1..Length(len)], x -> IsCoreFree(go,RepresentativeTom(tom[2],x)));
      sub:=List(pos_list_cf,x->PreImage(tom[1],RepresentativeTom(tom[2],x)));
      return sub;
    fi;
  fi;

  s:=Socle(G);

  a:=TrivialSubgroup(G);
  fac:=[];
  nf:=[];
  types:=[];
  gold:=[];
  iso:=[];
  for i in n do
    if not IsSubgroup(a,i) then
      a:=ClosureGroup(a,i);
      if not IsNonabelianSimpleGroup(i) then
        Error("The subgroups are abelian or not simple groups in CoreFreeSubgroupsTrivialFitting");
      fi;
      t:=ClassicalIsomorphismTypeFiniteSimpleGroup(i);
      p:=Position(types,t);
      if p=fail then
        Add(types,t);

        # fetch subgroup data from tom library, if possible
        tom:=TomDataAlmostSimpleRecognition(i);
        if tom<>fail then
          go:=ImagesSource(tom[1]);
          if tom[2]<>fail then
            len:=LengthsTom(tom[2]);
            # different than above -- no preimage. We're setting subgroups
            # of go
            sub:=List([1..Length(len)],x->RepresentativeTom(tom[2],x));
            sub:=List(sub,x->ConjugacyClassSubgroups(go,x));
            SetConjugacyClassesSubgroups(go,sub);
          fi;
        fi;

        if tom=fail then
          go:=SimpleGroup(t);
        fi;
        Add(gold,go);

        p:=Length(types);
      fi;
      Add(iso,IsomorphismGroups(i,gold[p]));
      Add(fac,gold[p]);
      Add(nf,i);
    fi;
  od;

  if a<>s then
    Error("The closure group is not trivial in CoreFreeSubgroupsTrivialFitting");
  fi;

  if Length(fac)=1 then
    map:=iso[1];
    a:=CoreFreeConjugacyClassesSubgroups(gold[1]);
    a:=List(a,x->PreImage(map,Representative(x)));
  else
    n:=DirectProduct(fac);

    # map to direct product
    a:=[];
    map:=[];
    for i in [1..Length(fac)] do
      Append(a,GeneratorsOfGroup(nf[i]));
      Append(map,List(GeneratorsOfGroup(nf[i]),
        x->Image(Embedding(n,i),Image(iso[i],x))));
    od;
    map:=GroupHomomorphismByImages(s,n,a,map);

    a:=SubdirectSubgroups(n);
    a:=List(a,x->PreImage(map,x[1]));
  fi;

  s:=Filtered(ExtendSubgroupsOfNormal(G,s,a), i -> IsCoreFree(G,i));
  return s;
end);

BindGlobal( "CoreFreeConjugacyClassesSubgroupsViaRadical",
  function(G)
  local H,HN,HNI,ser,pcgs,u,hom,f,c,nu,nn,nf,a,e,kg,k,mpcgs,gf,
  act,nts,orbs,n,ns,nim,fphom,as,p,isns,lmpc,npcgs,ocr,v,
  com,cg,i,j,w,ii,first,cgs,presmpcgs,select,fselect,
  makesubgroupclasses,cefastersize,cfccs, cfccsdeg, new_nu;

  #group order below which cyclic extension is usually faster
  # WORKAROUND: there is a disparity between the data format returned
  # by CE and what this code expects. This could be resolved properly,
  # but since most people will have tomlib loaded anyway, this doesn't
  # seem worth the effort.
  #if IsPackageMarkedForLoading("tomlib","")=true then
    cefastersize:=1;
  #else
  #  cefastersize:=40000;
  #fi;

  makesubgroupclasses:=function(g,l)
  local i,m,c;
    m:=[];
    for i in l do
      c:=ConjugacyClassSubgroups(g,i);
      if IsBound(i!.GNormalizer) then
        SetStabilizerOfExternalSet(c,i!.GNormalizer);
        Unbind(i!.GNormalizer);
      fi;
      Add(m,c);
    od;
    return m;
  end;

  ser:=PermliftSeries(G:limit:=300); # do not form too large spaces as they
                                     # clog up memory
  pcgs:=ser[2];
  ser:=ser[1];
  if Index(G,ser[1])=1 then
    Info(InfoWarning,3,"group is solvable");
    hom:=NaturalHomomorphismByNormalSubgroup(G,G);
    hom:=hom*IsomorphismFpGroup(Image(hom));
    u:=[[G],[G],[hom]];
    cfccs := [];
    cfccsdeg := [];
  elif Size(ser[1])=1 then
    if (HasIsSimpleGroup(G) and IsSimpleGroup(G)) then
      if IsNonabelianSimpleGroup(G) then
        c:=TomDataSubgroupsAlmostSimple(G);
        if c<>fail then
          if Size(c[Size(c)]) = Size(G) then
            c:= c{[1..Size(c)-1]};
          else
            Remove(c,Position(c,G));
          fi;
          c:=makesubgroupclasses(G,c);
          G!.coreFreeConjugacyClassesSubgroups := c;
          return G!.coreFreeConjugacyClassesSubgroups;
        fi;
      fi;
      
      return CoreFreeConjugacyClassesSubgroupsCyclicExtension(G);
    else
      if Length(ser) = 1 then
        c:=CoreFreeSubgroupsTrivialFitting(G);
        cfccs:=makesubgroupclasses(G,c);
        if not ForAny(c,x->Size(x)=1) then Add(cfccs,ConjugacyClassSubgroups(G,TrivialSubgroup(G))); fi;
        G!.coreFreeConjugacyClassesSubgroups := cfccs;
        return G!.coreFreeConjugacyClassesSubgroups;
      fi;
      c:=SubgroupsTrivialFitting(G);
      c:=makesubgroupclasses(G,c);
      u:=[List(c,Representative),List(c,StabilizerOfExternalSet)];
      cfccs := CoreFreeSubgroupsTrivialFitting(G);
    fi;
  else
    hom:=NaturalHomomorphismByNormalSubgroupNC(G,ser[1]);
    f:=Image(hom,G);
    fselect:=fail;
    c:=SubgroupsTrivialFitting(f);
    c:=makesubgroupclasses(f,c);
    nu:=[];
    nn:=[];
    nf:=[];
    kg:=GeneratorsOfGroup(KernelOfMultiplicativeGeneralMapping(hom));
    for i in c do
      a:=Representative(i);
      #k:=PreImage(hom,a);
      # make generators of homomorphism fit nicely to presentation
      gf:=IsomorphismFpGroup(a);
      e:=List(MappingGeneratorsImages(gf)[1],x->PreImagesRepresentative(hom,x));
      # we cannot guarantee that the parent contains e, so no
      # ClosureSubgroup.
      k:=ClosureGroup(KernelOfMultiplicativeGeneralMapping(hom),e);
      Add(nu,k);
      Add(nn,PreImage(hom,Stabilizer(i)));
      Add(nf,GroupHomomorphismByImagesNC(k,Range(gf),Concatenation(e,kg),
             Concatenation(MappingGeneratorsImages(gf)[2],
                List(kg,x->One(Range(gf))))));
    od;
    u:=[nu,nn,nf];
    cfccs := makesubgroupclasses(G,Filtered(u[1], i -> IsCoreFree(G,i)));
    cfccsdeg := List(cfccs, i -> Index(G,i[1]));
  fi;


  for i in [2..Length(ser)] do
    Info(InfoLattice,1,"Step ",i," : ",Index(ser[i-1],ser[i]));
    if pcgs=false then
      mpcgs:=ModuloPcgs(ser[i-1],ser[i]);
    else
      mpcgs:=pcgs[i-1] mod pcgs[i];
    fi;
    presmpcgs:=mpcgs;

    if Length(mpcgs)>0 then
      gf:=GF(RelativeOrders(mpcgs)[1]);
      act:=ActionSubspacesElementaryAbelianGroup(G,mpcgs);
    else
      gf:=GF(Factors(Index(ser[i-1],ser[i]))[1]);
      act:=[[ser[i]],GroupHomomorphismByImagesNC(G,Group(()),
           GeneratorsOfGroup(G),
           List(GeneratorsOfGroup(G),i->()))];
    fi;
    nts:=act[1];
    act:=act[2];
    if IsGroupGeneralMappingByImages(act) then
      Size(Source(act));
      Size(Range(act));
    fi;
    nu:=[];
    nn:=[];
    nf:=[];
    # Determine which ones we need and keep old ones
    orbs:=[];
    for j in [1..Length(u[1])] do
      a:=u[1][j];
      n:=u[2][j];

      # find indices of subgroups normal under a and form orbits under the
      # normalizer
      if act<>fail then
        ns:=Difference([1..Length(nts)],MovedPoints(Image(act,a)));
        nim:=Image(act,n);
        ns:=Orbits(nim,ns);
      else
        nim:=Filtered([1..Length(nts)],x->IsNormal(a,nts[x]));
        ns:=[];
        for k in [1..Length(nim)] do
          if not ForAny(ns,x->nim[k] in x) then
            p:=Orbit(n,nts[k]);
            p:=List(p,x->Position(nts,x));
            p:=Filtered(p,x->x<>fail and x in nim);
            Add(ns,p);
          fi;
        od;
      fi;
      if Size(a)>Size(ser[i-1]) then
        # keep old groups
        Add(nu,a);Add(nn,n);
        if Size(ser[i])>1 then
          fphom:=LiftFactorFpHom(u[3][j],a,ser[i],presmpcgs);
          Add(nf,fphom);
        fi;
        orbs[j]:=ns;
      else # here a is the trivial subgroup in the factor. (This will never
           # happen if we look for perfect or simple groups!)
        orbs[j]:=[];
        # previous kernel -- there the orbits are classes of subgroups in G
        for k in ns do
          Add(nu,nts[k[1]]);
          Add(nn,PreImage(act,Stabilizer(nim,k[1])));
          if Size(ser[i])>1 then
            fphom:=IsomorphismFpGroupByChiefSeriesFactor(nts[k[1]],"x",ser[i]);
            Add(nf,fphom);
          fi;
        od;
      fi;
    od;

    # run through nontrivial subspaces (greedy test whether they are needed)
    for j in [1..Length(nts)] do
      if Size(nts[j])<Size(ser[i-1]) then
        as:=[];
        for k in [1..Length(orbs)] do
          p:=PositionProperty(orbs[k],z->j in z);
          if p<>fail then
            # remove orbit
            orbs[k]:=orbs[k]{Difference([1..Length(orbs[k])],[p])};
            Add(as,k);
          fi;
        od;
        if Length(as)>0 then
          Info(InfoLattice,2,"Normal subgroup ",j,", Size ",Size(nts[j]),": ",
               Length(as)," subgroups to consider");
          # there are subgroups that will complement with this kernel.
          # Construct the modulo pcgs and the action of the largest subgroup
          # (which must be the normalizer)
          isns:=1;
          for k in as do
            if Size(u[1][k])>isns then
              isns:=Size(u[1][k]);
            fi;
          od;

          if pcgs=false then
            lmpc:=ModuloPcgs(ser[i-1],nts[j]);
            if Size(nts[j])=1 and Size(ser[i])=1 then
              # avoid degenerate case
              npcgs:=Pcgs(nts[j]);
            else
              npcgs:=ModuloPcgs(nts[j],ser[i]);
            fi;
          else
            if IsTrivial(nts[j]) then
              lmpc:=pcgs[i-1];
              npcgs:="not used";
            else
              c:=InducedPcgs(pcgs[i-1],nts[j]);
              lmpc:=pcgs[i-1] mod c;
              npcgs:=c mod pcgs[i];
            fi;
          fi;

          for k in as do
            a:=u[1][k];
            if IsNormal(u[2][k],nts[j]) then
              n:=u[2][k];
            else
              n:=Normalizer(u[2][k],nts[j]);
            fi;
            if Length(GeneratorsOfGroup(n))>3 then
              w:=Size(n);
              n:=Group(SmallGeneratingSet(n));
              SetSize(n,w);
            fi;
            ocr:=rec(group:=a,
                    modulePcgs:=lmpc);
            ocr.factorfphom:=u[3][k];

            OCOneCocycles(ocr,true);
            if IsBound(ocr.complement) then
              v:=BaseSteinitzVectors(
                BasisVectors(Basis(ocr.oneCocycles)),
                BasisVectors(Basis(ocr.oneCoboundaries)));
              v:=VectorSpace(gf,v.factorspace,Zero(ocr.oneCocycles));
              com:=[];
              cgs:=[];
              first:=false;
              if Size(v)>100 and Size(ser[i])=1
                 and HasElementaryAbelianFactorGroup(a,nts[j]) then
                com:=VectorspaceComplementOrbitsLattice(n,a,ser[i-1],nts[j]);
                Info(InfoLattice,4,"Subgroup ",Position(as,k),"/",Length(as),
                      ", ",Size(v)," local complements, ",Length(com)," orbits");
                for c in com do
                  Add(nu,c.representative);
                  Add(nn,c.normalizer);
                od;
              else
                for w in Enumerator(v) do
                  cg:=ocr.cocycleToList(w);
                  for ii in [1..Length(cg)] do
                    cg[ii]:=ocr.complementGens[ii]*cg[ii];
                  od;
                  if first then
                    # this is clearly kept -- so calculate a stabchain
                    c:=ClosureSubgroup(nts[j],cg);
                  first:=false;
                  else
                    c:=SubgroupNC(G,Concatenation(SmallGeneratingSet(nts[j]),cg));
                  fi;
                  Assert(1,Size(c)=Index(a,ser[i-1])*Size(nts[j]));
                  SetSize(c,Index(a,ser[i-1])*Size(nts[j]));
                  Add(cgs,cg);
                  #c!.comgens:=cg;
                  Add(com,c);
                od;
                w:=Length(com);
                com:=SubgroupsOrbitsAndNormalizers(n,com,false:savemem:=true);
                Info(InfoLattice,3,"Subgroup ",Position(as,k),"/",Length(as),
                      ", ",w," local complements, ",Length(com)," orbits");
                for w in com do
                  c:=w.representative;
                  if fselect=fail or fselect(c) then
                    Add(nu,c);
                    Add(nn,w.normalizer);
                    if Size(ser[i])>1 then
                      # need to lift presentation
                      fphom:=ComplementFactorFpHom(ocr.factorfphom,
                      ser[i-1],nts[j],c,
                      ocr.generators,cgs[w.pos]);

                      Assert(1,KernelOfMultiplicativeGeneralMapping(fphom)=nts[j]);
                      if Size(nts[j])>Size(ser[i]) then
                        fphom:=LiftFactorFpHom(fphom,c,ser[i],npcgs);
                        Assert(1,
                          KernelOfMultiplicativeGeneralMapping(fphom)=ser[i]);
                      fi;
                      Add(nf,fphom);
                    fi;
                  fi;

                od;
              fi;

              ocr:=false;
              cgs:=false;
              com:=false;
            fi;
          od;
        fi;
      fi;
    od;

    u:=[nu,nn,nf];
    new_nu := Filtered(nu, j -> not true in List(cfccs, k -> j in k) );
    Append(cfccs, makesubgroupclasses(G,Filtered(new_nu, i -> IsCoreFree(G,i))));
    cfccs := Unique(cfccs);
    cfccsdeg := List(cfccs, i -> Index(G,i[1]));
  od;
  
  # some `select'ions remove the trivial subgroup
  if not ForAny(cfccs,x->Size(x[1])=1) then
    Add(cfccs,ConjugacyClassSubgroups(G,TrivialSubgroup(G)));
  fi;
  Sort(cfccs,function(a,b)
    return Size(Representative(a))<Size(Representative(b));
  end);
  G!.coreFreeConjugacyClassesSubgroups := cfccs;
  return G!.coreFreeConjugacyClassesSubgroups;
end);


#############################################################################################

InstallGlobalFunction( IsCoreFree,
        function(G,H)
  if IsSubgroup(G,H) then   
    if Size(Core(G,H)) = 1 then return true; else return false; fi; 
  else
    Error("The subgroup given is not a subgroup of the given group");
  fi;
end);

InstallGlobalFunction( CoreFreeConjugacyClassesSubgroups,
        function(G)
  local iso, H, n, i, classes;
  if IsGroup(G) and IsFinite(G) then
    if IsBound(G!.coreFreeConjugacyClassesSubgroups) then
      return G!.coreFreeConjugacyClassesSubgroups;
    elif IsTrivial(G) then
      G!.coreFreeConjugacyClassesSubgroups := [ConjugacyClassSubgroups(G,G)];
      G!.coreFreeDegrees := [1];
      return G!.coreFreeConjugacyClassesSubgroups;
    elif HasIsHandledByNiceMonomorphism(G) then
      return CoreFreeConjugacyClassesSubgroupsNiceMonomorphism(G);
    elif IsSolvableGroup(G) then
      return CoreFreeConjugacyClassesSubgroupsOfSolvableGroup(G);
    elif not IsPermGroup(G) then
      iso := IsomorphismPermGroup(G);
      H := Image(iso);
      classes := List(CoreFreeConjugacyClassesSubgroups(H), i -> ConjugacyClassSubgroups(G,PreImage(iso,Representative(i))) );
      G!.coreFreeConjugacyClassesSubgroups := classes;
      G!.coreFreeDegrees := H!.coreFreeDegrees;
      return G!.coreFreeConjugacyClassesSubgroups;
    elif CanComputeFittingFree(G) then
      return CoreFreeConjugacyClassesSubgroupsViaRadical(G);
    else
      return CoreFreeConjugacyClassesSubgroupsCyclicExtension(G);
    fi;
  elif IsGroup(G) and not IsFinite(G) then
    Error("Group should be finite");
  else
    Error("Argument has to be a Group"); 
  fi;
end );

InstallGlobalFunction( AllCoreFreeSubgroups,
        function(G)
  local i, j;
  if IsBound(G!.coreFreeConjugacyClassesSubgroups) then
    return Flat(List(G!.coreFreeConjugacyClassesSubgroups, i -> List(i, j -> j)));
  else
    return Flat(List(CoreFreeConjugacyClassesSubgroups(G), i -> List(i, j -> j)));
  fi;
end );

InstallGlobalFunction( CoreFreeDegrees,
        function(G)
  local n, cfd;
  if IsBound(G!.coreFreeDegrees) then
    return G!.coreFreeDegrees;
  elif IsBound(G!.coreFreeConjugacyClassesSubgroups) then
    G!.coreFreeDegrees := Unique(List(G!.coreFreeConjugacyClassesSubgroups, n -> Index(G,n[1])));
    return G!.coreFreeDegrees;
  else
    cfd := Unique(List(CoreFreeConjugacyClassesSubgroups(G), n -> Index(G,n[1])));
    Sort(cfd);
    G!.coreFreeDegrees := cfd;
    return G!.coreFreeDegrees;
  fi;
end );


InstallMethod( MinimalFaithfulTransitivePermutationRepresentation, [IsGroup], 
        function(G)
  local core_free_ccs;
  if Index(G,Reversed(CoreFreeConjugacyClassesSubgroups(G))[1][1]) = MinimumList(CoreFreeDegrees(G)) then
    return FactorCosetAction(G,Reversed(CoreFreeConjugacyClassesSubgroups(G))[1][1]);
  else 
    Error("Core-free subgroups are not being ordered correctly");
  fi;
end );

InstallOtherMethod( MinimalFaithfulTransitivePermutationRepresentation, [IsGroup, IsBool], 
        function(G,bool) #bool here is either "we want all minimal degree FTPRs" - true , or "only one of the minimal degree FTPR"
  local core_free_ccs;
  if bool then
    core_free_ccs := Reversed(CoreFreeConjugacyClassesSubgroups(G));
    return List(Filtered(core_free_ccs, i -> Index(G,i[1]) = MinimumList(CoreFreeDegrees(G)) ), j -> FactorCosetAction(G,j[1]));
  else
    return MinimalFaithfulTransitivePermutationRepresentation(G);
  fi;
end );


InstallGlobalFunction( MinimalFaithfulTransitivePermutationDegree,
        function(G)
  local n;
  return Minimum(CoreFreeDegrees(G));
end );

InstallMethod( FaithfulTransitivePermutationRepresentations, [IsGroup], 
        function(G)
  return List(CoreFreeDegrees(G), i -> FactorCosetAction(G,First(CoreFreeConjugacyClassesSubgroups(G), j -> Index(G,j[1]) = i)[1]));
end );

InstallOtherMethod( FaithfulTransitivePermutationRepresentations, [IsGroup, IsBool]
        function(G,bool) #bool here is either "we want all FTPRs" - true, or "only one for each degree"
  if bool then
    return List(CoreFreeConjugacyClassesSubgroups(G), i -> FactorCosetAction(G,i[1]));
  else
    return FaithfulTransitivePermutationRepresentations(G);
  fi;
end );

InstallMethod( FaithfulTransitivePermutationRepresentationsOfDegree, [IsGroup, IsInt], 
        function(G,ind)
  if not ind in CoreFreeDegrees(G) then
    Error("There are no Core-free subgroups with index ", ind);
  fi;
  return FactorCosetAction(G,First(CoreFreeConjugacyClassesSubgroups(G), j -> Index(G,j[1]) = ind)[1]);
end );

InstallOtherMethod( FaithfulTransitivePermutationRepresentationsOfDegree, [IsGroup, IsInt, IsBool], 
        function(G,ind,bool) #bool here is either "we want all FTPRs" - true, or "only one for each degree"
  if not ind in CoreFreeDegrees(G) then
    Error("There are no Core-free subgroups with index ", ind);
  fi;
  if bool then
    return List(Filtered(CoreFreeConjugacyClassesSubgroups(G), j -> Index(G,j[1]) = ind), i -> FactorCosetAction(G,i[1]));
  else
    return FaithfulTransitivePermutationRepresentationsOfDegree(G);
  fi;
end );


[ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ]