Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/permut/lib/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 11.0.2024 mit Größe 80 kB image not shown  

Quelle  permut.gi   Sprache: unbekannt

 
#############################################################################
##
#W  permut.gi              Permutability GAP library              ABB&ECL&RER
##
##
#Y  Copyright (C)  2000-2018 Adolfo Ballester-Bolinches, Enric Cosme-Ll\'opez
#Y                           and Ramon Esteban-Romero
##
##  This file contains methods for permutability
##

#############################################################################
##
#V  PermutMaxTries
##
##  Maximum number of random attempts of permutability checks before trying
##  general methods
##

PermutMaxTries:=10;


#############################################################################
##
#M  ArePermutableSubgroups( <G>, <U>, <V> ) . . . . for finite groups
##
##  Returns true if <U> and <V> permute, false otherwise.
##

InstallMethod(ArePermutableSubgroups, "with three arguments <G>, <U>, <V>, where <U> and <V> are subgroups of <G>",
        [IsGroup and IsFinite,IsGroup and IsFinite,IsGroup and IsFinite],
        function(G,U,V)
    local bool1, bool2;
    if not IsSubgroup(G,U)
       or not IsSubgroup(G,V)
       then
        Error("<U> and <V> must be subgroups of <G>");
    fi;
    bool1:=HasParent(U) and IsSubgroup(Parent(U),G);
    bool2:=HasParent(V) and IsSubgroup(Parent(V),G);
        #
        # a shortcut when one of the subgroups is normal in its parent
        # 
    if (bool1 and HasIsNormalInParent(U) and IsNormalInParent(U))
       or (bool2 and  HasIsNormalInParent(V) and IsNormalInParent(V))
       then
        return true;
        
        #
        # a shortcut when one of the subgroups is permutable in its parent
        # 
    elif (bool1 and HasIsPermutableInParent(U) and IsPermutableInParent(U))
      or (bool2 and HasIsPermutableInParent(V) and IsPermutableInParent(V))
      then
        return true;
        # 
        # a shortcut when one of the subgroups is contained in the other
        #
    elif IsSubgroup(U,V) or IsSubgroup(V,U)
      then
        return true;
        #
        # the general case
        #
    else
        return Size(U)*Size(V)=Size(Intersection(U,V))*
               Size(Subgroup(G,Union(GeneratorsOfGroup(U),
                       GeneratorsOfGroup(V))));
    fi;
end);

#
## With two parameters, both groups must be subgroups of a common group.
#

InstallOtherMethod(ArePermutableSubgroups, "with two arguments",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(U,V)
    local G;
    if IsIdenticalObj(Parent(U), Parent(V))
       then
        return ArePermutableSubgroups(Parent(U),U,V);
    else
        return ArePermutableSubgroups(ClosureGroup(U,V),U,V);
    fi;
end);

#############################################################################
##
#M  Permutizer( <G>, <U> ) . . . . for finite groups
##
##  Computes the permutizer of a subgroup U in G.  This is the
## subgroup generated by all the cyclic subgroups of G which permute with U.
##
InstallMethod(PermutizerOp,"for finite groups", [IsGroup and IsFinite,
        IsGroup and IsFinite],
        function(g,h)
    local ele, llista,z,bool1, n,x;
    if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    bool1:=IsSubgroup(Parent(h),g);
    #
    # If h is normal or permutable in g, it is easy to compute the permutizer.
    #
    if bool1 and HasIsNormalInParent(h) and IsNormalInParent(h)
       then
        return g;
    fi;
    if bool1 and HasIsPermutableInParent(h) and IsPermutableInParent(h)
       then
        return g;
    fi;
    if IsNormal(g,h)
       then 
        return g; 
    fi;
    if IsPermutable(g,h)
       then
        return g;
    fi;
    # We start with the normaliser, then we add elements
    n:=Normalizer(g,h);
    for x in g do
        if not x in n and ArePermutableSubgroups(g,h,Subgroup(g,[x]))
           then
            n:=ClosureSubgroup(n,Subgroup(g,[x]));
        fi;
        # if n=g, we stop adding elements.
        if n=g 
           then
            break;
        fi;
    od;
           
    return n;
end);

#############################################################################
##
#M  AllSubnormalSubgroups( <G> ) . . . . for a finite group
##
##  The default method constructs the lattice of subnormal subgroups.
##
InstallMethod(AllSubnormalSubgroups, "for a finite group",
        [IsGroup and IsFinite],
        function(G)
    local sn0,asn,sn1,x;
    sn0:=NormalSubgroups(G);
    asn:=ShallowCopy(sn0);
    repeat
        sn1:=[];
        for x in sn0 
          do
            Append(sn1, Filtered(NormalSubgroups(x), 
                    x-> not x in asn and not x in sn1));
        od;
        sn0:=sn1;
        Append(asn,sn1);
    until sn1=[];
    return asn;
end
);



#############################################################################
##
#F  AllGeneratorsCyclicPGroup( <x>, p ) . . . . for a p-element <x> of a group
##
##  This operation computes all generators of the cyclic group
##  generated by the p-element <x>.
## 
##

InstallGlobalFunction(AllGeneratorsCyclicPGroup,function(x,p)
    local z,t;
    return List(Filtered([1..Order(x)], z->(z mod p)<>0),
                t->x^t);
end
  );

                   

#############################################################################
##
#M  IsPermutable( <G>, <H> ) . . . . for groups
##
##  This operation returns true if H is permutable in G, false otherwise.
##  H is permutable in G when H permutes with all subgroups of G.
##
InstallMethod(IsPermutableOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and
         IsFinite],
        function(g,h)
    local elg,z,P,hg,epi,g1,h1,h1q,gensh1q,r,gensr,x,y,g1q,q,bool1,bool2,
          ccsg1q,ccsh1q,u,su,i;
    
    if not IsSubgroup(g,h) 
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    #
    # If the Why function has been computed, then use it.
    #
    bool1:=IsSubgroup(Parent(h), g);
    bool2:=IsSubgroup(g, Parent(h));
    if bool1 and HasOneSubgroupNotPermutingWithInParent(h)
       and OneSubgroupNotPermutingWithInParent(h)=fail
       then
        return true;
    elif
      bool2 and HasOneSubgroupNotPermutingWithInParent(h)
      and OneSubgroupNotPermutingWithInParent(h)<>fail
      then
        return false;
    fi;
    
    #
    # immediate methods: permutability is inherited by subgroups
    # and normal subgroups are permutable
    #    
    if bool1
       and ((HasIsNormalInParent(h) and IsNormalInParent(h)) or
            (HasIsPermutableInParent(h) and IsPermutableInParent(h)))
       then
        return true;
    fi;
    if bool2
       and (HasIsPermutableInParent(h) and not IsPermutableInParent(h))
       then
        return false;
    fi;
    
    #
    # permutable subgroups are subnormal, S-permutable, and conjugate-permutable
    #
    if bool1
       then
        if (HasIsSPermutableInParent(h) and  not IsSPermutableInParent(h)) or
           (HasIsConjugatePermutableInParent(h)
            and not IsConjugatePermutableInParent(h))
           then
            return false;
        fi;
    fi;
    #
    # normal subgroups are permutable. This check is cheaper than ours.
    #
    if IsNormal(g,h)
       then
        return true;
    fi;
    #
    # subgroups of Iwasawa nilpotent groups are permutable
    #
    if (IsPGroup(g) and (HasIsPTGroup(g) and IsPTGroup(g) or
               HasIsPTGroup(SylowSubgroup(g,PrimePGroup(g)))
               and IsPTGroup(SylowSubgroup(g,PrimePGroup(g)))))
       or
       (IsNilpotentGroup(g) and HasIsPTGroup(g) and IsPTGroup(g))
       or
       (IsNilpotentGroup(g) and
        ForAll(PrimesDividingSize(g),
               q->HasIsPTGroup(SylowSubgroup(g,q)) and 
               IsPTGroup(SylowSubgroup(g,q))))
       then
        return true;
    fi;
    
    #
    # we check whether the subgroup permute with some random cyclic
    # subgroups
    # 
    
    for i in [1..PermutMaxTries] do
        u:=Random(g);
        su:=Subgroup(g,[u]);
        if not ArePermutableSubgroups(g, su, h)
           then
            if bool1
               then
                SetOneSubgroupNotPermutingWithInParent(h, su);
            fi;
            return false;
        fi;
    od;
    
    
    #
    # permutable subgroups are subnormal
    #
    if not(IsSubnormal(g,h))
       then
        return false;
    fi;
    
    hg:=Core(g,h);
    epi:=NaturalHomomorphismByNormalSubgroup(g,hg);
    g1:=Image(epi);
    h1:=Image(epi,h);
    UseFactorRelation(g,hg,g1);
    
    #
    # permutable subgroups mod core are nilpotent (not difficult to check)
    #
    if not IsNilpotent(h1)
       then
        return false;
    fi;
    # permutable subgroups are hypercentrally embedded;
    # we check that the Sylow q-subgroup of h/h_g centralises
    # the Sylow r-subgroups of g/h_G for r <> q
    for q in PrimesDividingSize(h1)
      do
        h1q:=SylowSubgroup(h1,q);
        g1q:=SylowSubgroup(g1,q);
        UseFactorRelation(SylowSubgroup(g,q),hg,g1q);
        r:=PResidual(g1,q);
        gensh1q:=GeneratorsOfGroup(h1q);
        gensr:=GeneratorsOfGroup(r);
        #        if not ForAll(gensh1q,x->ForAll(gensh1q,y->y^x=y))
                if not ForAll(gensr,x->ForAll(gensh1q,y->y^x=y))
           then 
            return false;
        fi;
    od;
    ### Now we check that the Sylow $p$-subgroups of H/H_G
    ### permute with all cyclic $p$-subgroups of G/H_G
    
    for q in PrimesDividingSize(h1)
      do
        h1q:=SylowSubgroup(h1,q);
        g1q:=SylowSubgroup(g1,q);
        if not (HasIsPTGroup(g1q) and IsPTGroup(g1q)) then
            ccsg1q:=ConjugacyClassSubgroups(g1,g1q);
            ccsh1q:=ConjugacyClassSubgroups(g1,h1q);
            if Size(ccsg1q)<Size(ccsh1q) then
                elg:=Difference(Union(AsList(ccsg1q)),h1q);
                while elg<>[] do
                    x:=elg[1];
                    if not ArePermutableSubgroups(g1,h1q,Subgroup(g1,[x]))
                       then
                        return false;
                    fi;
                    elg:=Difference(elg,AllGeneratorsCyclicPGroup(x,q));
                od;
            else
                elg:=AsList(g1q);
                while elg<>[] do
                    x:=elg[1];
                    if not ForAll(ccsh1q, 
                               zz->ArePermutableSubgroups(g1,
                                       zz,Subgroup(g1,[x])))
                       then
                        return false;
                    fi;
                    elg:=Difference(elg,AllGeneratorsCyclicPGroup(x,q));
                od;
            fi;
        fi;
    od;
    return true;
    
      
end);


#############################################################################
##
#M  OneSubgroupNotPermutingWith( <G>, <H> ) . . . . for groups
##
## This operation finds a subgroup of G which does not permute with H
## if such a subgroup exists, otherwise it returns fail.
##
##
InstallMethod(OneSubgroupNotPermutingWithOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(g,h)
    local csg,z,w,bool1,bool2;
    if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    bool1:=IsSubgroup(Parent(h),g);
    bool2:=IsSubgroup(g,Parent(h));
    if bool1 and bool2 then
        if HasOneSylowSubgroupNotPermutingWithInParent(h) and
           OneSylowSubgroupNotPermutingWithInParent(h)<>fail
           then
            return OneSylowSubgroupNotPermutingWithInParent(h);
        fi;
        if HasOneConjugateSubgroupNotPermutingWithInParent(h) and
           OneConjugateSubgroupNotPermutingWithInParent(h)<>fail
           then
            return OneConjugateSubgroupNotPermutingWithInParent(h);
        fi;
    fi;
    if bool1 and HasOneSubgroupNotPermutingWithInParent(h)
       and OneSubgroupNotPermutingWithInParent(h)=fail
       then
        SetIsPermutableInParent(h,true);
        return fail;
    fi;
    if bool2 and HasOneSubgroupNotPermutingWithInParent(h)
       and OneSubgroupNotPermutingWithInParent(h)<>fail
       then
        SetIsPermutableInParent(h,false);
        return OneSubgroupNotPermutingWithInParent(h);
    fi;
    
    
    
    w:=First(Zuppos(g),z->not ArePermutableSubgroups(g,h,Subgroup(g,[z])));
    if bool1 and bool2
       then SetIsPermutableInParent(h,w=fail);
    fi;
    if w=fail
       then
        return fail;
    fi;
    return Subgroup(g,[w]);
end);


#############################################################################
##
#M  PrimesDividingSize( <G> ) . . . . for groups
##
##  This attribute gives a list of primes dividing the size of G. It
##  has been borrowed from the GAP manual.
##
InstallMethod(PrimesDividingSize, "for finite groups", [IsGroup and
        IsFinite],
        G -> PrimeDivisors(Size(G)));


#############################################################################
##
#M  OneFSubgroupNotPermutingWith( <G>, <H>, <F> ) . . . . for groups
##
##  This operation returns fail if H permutes with all members of F
##  (a list of subgroups of G); otherwise it returns a member of F which 
##  does not permute with H.
##

InstallGlobalFunction( OneFSubgroupNotPermutingWith, function(g, h, f)
    local t,bool1,bool2,cex;
        if not IsSubgroup(g,h) 
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    
    if not IsList(f) or ForAny(f, t->not IsSubgroup(g,t))
       then
        Error("<f> must be a list of subgroups of <g>");
    fi;
    
    bool1:=IsSubgroup(Parent(h),g);
    if bool1
       and
       (
        (HasIsPermutableInParent(h) and IsPermutableInParent(h))
        or
        (HasOneSubgroupNotPermutingWithInParent(h)
         and OneSubgroupNotPermutingWithInParent(h)=fail)
        )
       then
        return fail;
    fi;
    cex:=First(f, t->not ArePermutableSubgroups(g, h, t));
    bool2:=IsSubgroup(g,Parent(h));
    if cex<>fail and bool2 then
        if not HasIsPermutableInParent(h)
           then
            SetIsPermutableInParent(h,false);
        fi;
        if not HasOneSubgroupNotPermutingWithInParent(h)
           then
            SetOneSubgroupNotPermutingWithInParent(h,cex);
        fi;
    fi;
    return cex;
end
  );

     
#############################################################################
##
#M  IsFPermutable( <G>, <H>, <F> ) . . . . for groups
##
##  This operation returns true if a subgroup H of G permutes
##  with all the members of F, where F is a list of subgroups of G.
##

InstallGlobalFunction( IsFPermutable, function(g,h,f)
    return OneFSubgroupNotPermutingWith(g,h,f)=fail;
end
  );

#############################################################################
##
#M  SylowSubgroups( <G> ) . . . . for groups
##
##  This attribute gives a list of one Sylow subgroup for every prime
##  dividing  the size of G
##

#For soluble groups, we get a Sylow system.
InstallMethod(SylowSubgroups, "for finite soluble groups",
        [IsGroup and IsFinite and IsSolvableGroup],
        function(g)
    return SylowSystem(g);
end);

# Otherwise, we simply compute a Sylow subgroup for each prime
# dividing the order of the group.
InstallMethod(SylowSubgroups, "for finite groups", [IsGroup and
        IsFinite],
        function(g)
    return List(PrimesDividingSize(g),p->SylowSubgroup(g,p));
end);


#############################################################################
##
#M  OneSylowSubgroupNotPermutingWith( <G>, <H> ) . . . . for groups
##
## This operation finds a Sylow subgroup of G which does not permute 
## with H if such a subgroup exists, otherwise it returns false.
##
##
InstallMethod(OneSylowSubgroupNotPermutingWithOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(g,h)
    local sylows,z,r,x,y;
    if not IsSubgroup(g,h) 
       then
        Error("<h> must be a subgroup of <g>");
    fi;

    if IsNilpotentGroup(g)
       then
        SetIsPSTGroup(g,true);
        return fail ;
    elif HasIsPSTGroup(g) and IsPSTGroup(g) and IsSubnormal(g,h)
      then
        return fail;
    elif HasIsNormalInParent(h) and IsNormalInParent(h)
      then
        return fail;
    elif IsNormal(g,h)
      then
        return fail;
    elif HasIsPermutableInParent(h) and IsPermutableInParent(h)
      then
        return fail;
    elif IsPGroup(h) # h cannot be trivial at this stage
      then
        r:=PResidual(g,PrimePGroup(h));
        if  ForAll(GeneratorsOfGroup(r),
                   x->ForAll(GeneratorsOfGroup(h),y->y^x in h))
            then
            return fail;
        fi;
    fi;
    sylows:=Union(List(SylowSubgroups(g),z->ConjugateSubgroups(g,z)));
    return First(sylows,z->not ArePermutableSubgroups(g,h,z));
end);

#############################################################################
##
#M  OneSystemNormalizerNotPermutingWith( <G>, <H> ) . . . . for groups
##
##  This operation finds a system normalizer of the soluble groups G
##  which does not permute with H if such a subgroup exists, fail otherwise.
##
##
InstallMethod(OneSystemNormalizerNotPermutingWithOp, "for finite soluble groups",
        [IsGroup and IsFinite and IsSolvableGroup, IsGroup and IsFinite],
        function(g,h)
    local sysnor,sysnors,z,bool1;
    if not IsSubgroup(g,h) 
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    
    bool1:=IsSubset(Parent(h),g);
    if HasIsPermutableInParent(h) and IsPermutableInParent(h) and bool1
       then
        return fail;
    else
 sysnor:=SystemNormalizer(g);
        sysnors:=AsList(ConjugacyClassSubgroups(g,sysnor));
        return First(sysnors,z->not ArePermutableSubgroups(g,h,z));
    fi;
end);

#############################################################################
##
#M  IsSPermutable( <G>, <H> ) . . . . for groups
##
##  This operation returns true if a subgroup H of G is S-permutable,
##  and false otherwise. 
##
InstallMethod(IsSPermutableOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and
         IsFinite],
        function(g,h)
    local sylows,z,cex,hg,pi,hhg,hp,hghp,p,gens,gensp,gensr,r,y,x;
    if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");        
    elif not(IsSubnormal(g,h))
       then
        return false;
    fi;
    if IsNormal(g,h)
       then
        return true;
    fi;
    if IsSubgroup(Parent(g),h) and HasIsPermutableInParent(h)
       and IsPermutableInParent(h)
       then
        return true;
    else
        hg:=Core(g,h);
        hhg:=h/hg;
        pi:=PrimesDividingSize(hhg);
        if not IsNilpotent(hhg)
           then
            return false;
        fi;
        for p in pi
          do
            hp:=SylowSubgroup(h,p);
            r:=PResidual(g,p);
            gensr:=GeneratorsOfGroup(r);
            gensp:=GeneratorsOfGroup(hp);
            gens:=Union(GeneratorsOfGroup(hg),gensp);
            hghp:=Subgroup(h,gens);
            if not ForAll(gensp,x->ForAll(gensr,y->x^y in hghp))
               then
                return false;
            fi;
        od;
        return true;
    fi;
end);

#############################################################################
##
#M  IsSNPermutable( <G>, <H> ) . . . . for groups
##
##  This operation returns true a subgroup H of a soluble group G
##  is SN-permutable, and false otherwise. 
##  H is SN-permutable in G when H permutes with all system normalizers of G.
##
InstallMethod(IsSNPermutableOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and
         IsFinite],
        function(g,h)
    local sylows,z,cex;
    if not IsSolvableGroup(g)
       then
        Error("<g> must be a solvable group");
    fi;
    if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    #
    # SN-permutable subgroups are subnormal.
    #
    if not(IsSubnormal(g,h)) then
        return false;
    fi;
    #
    # Permutable subgroups are SN-permutable.
    #
    if HasIsPermutableInParent(g) and IsPermutableInParent(g)
       then
        return true;
    else
        cex:=OneSystemNormalizerNotPermutingWith(g,h);
        return cex=fail;
    fi;
end);


#############################################################################
##
#M  OneConjugateSubgroupNotPermutingWith( <G>, <H> ) . . . . for groups
##
##  This operation finds a conjugate subgroup of H which does not permute
##  with H if such a subgroup exists, otherwise it returns fail.
##

InstallMethod(OneConjugateSubgroupNotPermutingWithOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(G,H)
    local z,cex;
    if not IsSubgroup(G,H)
       then
        Error("<h> must be a subgroup of <g>");
        #
        # Permutable subgroups are conjugate-permutable.
        #
    elif HasIsPermutableInParent(H) and IsPermutableInParent(H)
      then
        return fail;
    else
        cex:=First(ConjugateSubgroups(G,H), 
                   z->not ArePermutableSubgroups(G,H,z));
        return cex;
    fi;
end);

#############################################################################
##
#M  IsConjugatePermutable( <G>, <H> ) . . . . for groups
##
##  This operation returns true if the subgroup H of G is
##  conjugate-permutable, and false otherwise.
##  H is conjugate-permutable in G when H permutes with H^g for every g of G.
##

InstallMethod(IsConjugatePermutableOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(G,H)
    local z,cex;
    if not IsSubgroup(G,H)
       then
        Error("<H> must be a subgroup of <G>");
        #
        # normal subgroups are conjugate-permutable
        #
    elif HasIsNormalInParent(H) and IsNormalInParent(H)
      then
        return true;
    else
        cex:=OneConjugateSubgroupNotPermutingWith(G,H);
        return cex=fail;
    fi;
end);

#############################################################################
##
#M  OneElementShowingNotWeaklyNormal( <G>, <H> ) . . . . for groups
##
##  This operation finds an element g of G such that H normal <H, H^g>
##  but H not normal in <H,g> if such an element exists, fail otherwise.
##  H is weakly normal in G when H normal in <H,H^g> implies H normal in <H,g>.
##

InstallMethod(OneElementShowingNotWeaklyNormalOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(g,h)
    local x,cex,n;
    n:=Normalizer(g,h);
    if not IsSubgroup(g,h) 
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    cex:=First(RightTransversal(g, n), 
               x->IsSubgroup(n, ConjugateSubgroup(h,x))
               and not x in n);
    return cex;
end);
        
#############################################################################
##
#M  IsWeaklyNormal( <G>, <H> ) . . . . for groups
##
##  This operation returns true if a subgroup H of G is
##  weakly normal, false otherwise.
##  H is weakly normal when H^g\le N_G(H) implies g\in N_G(H)
##

InstallMethod(IsWeaklyNormalOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(g,h)
    local x,cex;
    cex:=OneElementShowingNotWeaklyNormal(g,h);
    return cex=fail;
end);
        
#############################################################################
##
#M  OneElementShowingNotWeaklySPermutable( <G>, <H> ) . . . . for groups
##
##  This operation finds an element g of G such that H Sper <H, H^g>
##  but H not Sper <H,g> if such an element exists, fail otherwise.
##  H is weakly S-permutable in G when H Sper <H,H^g> implies H Sper <H,g>.
##

InstallMethod(OneElementShowingNotWeaklySPermutableOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(g,h)
    local x,cex;
    if not IsSubgroup(g,h) 
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    cex:=First(RightTransversal(g,h),x->
               IsSPermutable(
                       Subgroup(g,
                               Union(
                                     GeneratorsOfGroup(h),
                                     GeneratorsOfGroup(
                                             ConjugateSubgroup(h,x))
                                     )),
                       h
                       )
               and not IsSPermutable(
                       Subgroup(g,Union(GeneratorsOfGroup(h),[x])),
                       h
                       ));
    return cex;
end);

#############################################################################
##
#M  IsWeaklySPermutable( <G>, <H> ) . . . . for groups
##
##  This operation returns true if a subgroup H of G is
##  weakly S-permutable, false otherwise.
##  H is weakly S-permutable in G when H Sper <H,H^g> implies H Sper <H,g>.
##

InstallMethod(IsWeaklySPermutableOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(g,h)
    local x,cex;
    cex:=OneElementShowingNotWeaklySPermutable(g,h);
    return cex=fail;
end);
        
#############################################################################
##
#M  OneElementShowingNotWeaklyPermutable( <G>, <H> ) . . . . for groups
##
##  This operation find an element g such that H per <H, H^g> but
##  H not per <H, g> if such an element exists, fail otherwise.
##  H is permutable in G when H per <H,H^g> implies H per <H,g>.
##

InstallMethod(OneElementShowingNotWeaklyPermutableOp, "for finite groups", [IsGroup and
        IsFinite, IsGroup and IsFinite],
        function(g,h)
    local x;
    if not IsSubgroup(g,h) 
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    return First(RightTransversal(g,h),x->
                 IsPermutable(
                         Subgroup(g,
                                 Union(
                                       GeneratorsOfGroup(h),
                                       GeneratorsOfGroup(
                                               ConjugateSubgroup(h,x)
                                               )
                                       )
                                 ),
                         h
                         )
                 and not IsPermutable(
                         Subgroup(g,Union(GeneratorsOfGroup(h),[x])),
                         h
                         )
                 );
end);
    
#############################################################################
##
#M  IsWeaklyPermutable( <G>, <H> ) . . . . for groups
##
##  This operation returns true if a subgroup H of G is
##  weakly permutable, false otherwise.
##  H is weakly permutable  in G when H per <H, H^g> implies H per <H, g>.
##

InstallMethod(IsWeaklyPermutableOp, "for finite groups", [IsGroup and
        IsFinite, IsGroup and IsFinite],
        function(g,h)
    local x,cex;
    cex:=OneElementShowingNotWeaklyPermutable(g,h);
    return cex=fail;
end);

#############################################################################
##
#M  OneSubnormalNonPermutableSubgroup( <G> ) . . . . for finite groups
##
##  The default method finds a non conjugate-permutable subnormal subgroup
##  of G if there exists one such subgroup, it returns fail otherwise.
##

InstallMethod(OneSubnormalNonPermutableSubgroup,"for finite PT-groups",
        [IsGroup and IsFinite and IsPTGroup],
        function(G)
    local z;
    return fail;
end);

InstallMethod(OneSubnormalNonPermutableSubgroup, "for finite groups with AllSubnormalSubgroups",
        [IsGroup and IsFinite and HasAllSubnormalSubgroups],
        function(G)
    local x;
    return First(AllSubnormalSubgroups(G),x->not IsPermutable(G,x));
end
  );

# If we do not know whether the group is a PT-group,
# we look for a subnormal subgroup which is not permutable.

InstallMethod(OneSubnormalNonPermutableSubgroup,"for finite groups non PT-groups",
        [IsGroup and IsFinite],
        function(G)
    local z,ex,ns,nsz,sns,t,new,sn1,sn0,w,asn,x;
    if HasOneSubnormalNonSPermutableSubgroup(G) and OneSubnormalNonSPermutableSubgroup(G)<>fail
       then
        return OneSubnormalNonSPermutableSubgroup(G);
    fi;
    if HasOneSubnormalNonConjugatePermutableSubgroup(G) and OneSubnormalNonConjugatePermutableSubgroup(G)<>fail
       then
        return OneSubnormalNonConjugatePermutableSubgroup(G);
    fi;
    sn0:=Set(NormalSubgroups(G));
    asn:=ShallowCopy(sn0);
    repeat
        sn1:=[];
        for x in sn0
          do
            new:=Filtered(NormalSubgroups(x),
                         x->not x in asn and not x in sn1);
            w:=First(new,z->not IsPermutable(G,z));
            if w<>fail
               then
                SetIsPTGroup(G,false);
                SetIsTGroup(G,false);
                return w;
            fi;
            UniteSet(sn1,new);
            
        od;
        sn0:=sn1;
        UniteSet(asn,sn1);
    until sn1=[];
    SetAllSubnormalSubgroups(G,asn);
    SetIsPTGroup(G, true);
    SetIsCPTGroup(G, true);
    SetIsPSTGroup(G, true);
    SetIsPSNTGroup(G, true);
    return fail;
end);

#############################################################################
##
#M  IsAbCp( <G>, <p> ) . . . . for finite groups
##
## Returns true if the group has an abelian Sylow p-subgroup P and every
## subgroup of P is normalised by N_G(P), false otherwise.
##

InstallMethod(IsAbCpOp,
        "generic method for group and prime",
        [IsGroup and IsFinite,IsPosInt],
        function(G,p)
    local gN,P,a,n,c,e,nc,b,r,t,compiscps,pos,i,u;
    # if p does not divide |G|, it is true
    if (Size(G) mod p)<>0 
       then 
        return true;
    fi;
    P:=SylowSubgroup(G,p);
    if not IsAbelian(P)
       then
        return false;
    fi;
    # Now P is abelian. We check if being Cp is stored
    compiscps:=ComputedIsCps(G);
    pos:=Position(compiscps{[1,3..Length(compiscps)-1]},p);
    if pos<>fail
       then
        return IsAbCp(G,p);
    fi;
       
    if p=Minimum(PrimesDividingSize(G))
       then 
        return IsPNilpotent(G,p);
    fi;
    n:=Normalizer(G,P);
    # we enforce this test before computing the discrete logarithm
    if ForAny(GeneratorsOfGroup(P),t->not IsNormal(n,Subgroup(G,[t])))
       then
        return false;
    fi;

    c:=Centralizer(G,P);
    if IsSubgroup(c,n)
       then
        return true;
    fi;    
    e:=NaturalHomomorphismByNormalSubgroup(n,c);
    nc:=Image(e);
    if not IsCyclic(nc)
       then
        return false;
    fi;
    a:=First(GeneratorsOfGroup(P),t->Order(t)=Exponent(P));
    b:=PreImagesRepresentative(e,MinimalGeneratingSet(nc)[1]);
    r:=First([1..Exponent(P)-1],t->a^b=a^t);
    return ForAll(GeneratorsOfGroup(P),t->t^b=t^r);
end
  );



#############################################################################
##
#M  IsDedekindSylow( <G>, <p> ) . . . . for finite groups
##
##  Returns true if a Sylow p-subgroup of G is Dedekind, else returns false
##

InstallGlobalFunction(IsDedekindSylow, function(G,p)
    local P,res,epi,a1,a2,mgs;
    P:=SylowSubgroup(G,p);
    if HasIsTGroup(P)
       then 
        return IsTGroup(P);
    elif p>2 then
        res:=IsAbelian(P);
        SetIsTGroup(P,res);
        return res;
    else
        if IsAbelian(P)
           then
            SetIsTGroup(P,true);
            return true;
        else
            #
            # the group should be a direct product of 
            # an elementary abelian group and a quaternion group
            #
            if Size(FrattiniSubgroup(P))<>2
               then
                SetIsTGroup(P,false);
                return false;
            elif Exponent(Centre(P))>2 or Index(P,Centre(P))<>4
              then
                SetIsTGroup(P,false);
                return false;
            else

                epi:=NaturalHomomorphismByNormalSubgroup(P,Centre(P));
                mgs:=MinimalGeneratingSet(Image(epi));
                a1:=PreImagesRepresentative(epi,mgs[1]);
                a2:=PreImagesRepresentative(epi,mgs[2]);
                if Order(a1)<>4 or Order(a2)<>4  then
                    SetIsTGroup(P,false);
                    return false;
                else
                    SetIsTGroup(P,true);
                    return true;
                fi;
            fi;
            
        fi;
    fi;
end
  );


#############################################################################
##
#M  IsIwasawaSylow( <G>, <p> ) . . . . for finite groups
##
##  Returns true if a Sylow p-subgroup of G is modular, else returns false
##

InstallGlobalFunction(IsIwasawaSylow,function(G,p)
    local P,z,ex,x,l,l1,l2,res,u,v,gu,gv,i;
    P:=SylowSubgroup(G,p);
    if (HasIsPTGroup(P))
       then
        return IsPTGroup(P);
    elif IsAbelian(P)
      then
        SetIsTGroup(P,true);
        SetIsPTGroup(P,true);
        return true;
    else
        # first we check permutability of a few subgroup pairs
        for i in [1..PermutMaxTries] do
            u:=Random(P);
            v:=Random(P);
            gu:=Subgroup(P,[u]);
            gv:=Subgroup(P,[v]);
            if not ArePermutableSubgroups(P, gu, gv)
               then
                SetIsTGroup(P,false);
                SetIsPTGroup(P,false);
                SetOneSubnormalNonSPermutableSubgroup(P,gu);
                SetOneSubnormalNonPermutableSubgroup(P,gu);
                return false;
            fi;
        od;
        # Now we apply the general method
        res:=IwasawaTriple(P);
        if res=fail
           then
            SetIsTGroup(P, false);
            SetIsPTGroup(P,false);
            return false;
        elif res=[]
          then
            SetIsPTGroup(P,true);
            SetIsTGroup(P,true);
            return true;
        elif p=2
          then
            SetIsTGroup(P,false);
            SetIsPTGroup(P,res[3]<>1);
            return res[3]<>1;
        else
            SetIsTGroup(P,false);
            SetIsPTGroup(P,true);
            return true;
        fi;
    fi;
end
  );


#############################################################################
##
#M  IsCp( <G>, <p> ) . . . . for finite groups
##
## Returns true if every subgroup of a Sylow p-subgroup P of G
## is normalised by N_G(P), false otherwise.
##

InstallMethod(IsCpOp,
        "generic method for a finite group and prime",
        [IsGroup and IsFinite,IsPosInt],
        function(g,p)
    local a,compisabcp,pos,P;
    
    P:=SylowSubgroup(g,p);
    compisabcp:=ComputedIsAbCps(g);
    pos:=Position(compisabcp{[1,3..Length(compisabcp)-1]},p);
    if p<>fail then
        if IsAbCp(g,p)
           then
            return true;
        elif IsAbelian(P)
          then
            return false;
        fi;
    fi;
    return (IsPNilpotent(g,p) and IsDedekindSylow(g,p)) or IsAbCp(g,p);
end
);


#############################################################################
##
#M  IsXp( <G>, <p> ) . . . . for finite groups
##
## Returns true if every subgroup of a Sylow p-subgroup P of G
## is permutable in N_G(P), false otherwise.
##

InstallMethod(IsXpOp,
        "generic method for a finite group and a prime",
        [IsGroup and IsFinite,IsPosInt],
        function(g,p)
    local a,compisabcp,pos,P;
    
    P:=SylowSubgroup(g,p);
    compisabcp:=ComputedIsAbCps(g);
    pos:=Position(compisabcp{[1,3..Length(compisabcp)-1]},p);
    if p<>fail then
        if IsAbCp(g,p)
           then
            return true;
        fi;
    fi;
    return (IsPNilpotent(g,p) and IsIwasawaSylow(g,p)) or IsAbCp(g,p);
end
);

#############################################################################
##
#M  IsYp( <G>, <p> ) . . . . for finite groups
##
## Returns true if for every p-subgroups H and K such that $H\le K$,
## $H$ is S-permutable in N_G(K), false otherwise.
## 
##

InstallMethod(IsYpOp,
        "generic method for group and prime",
        [IsGroup and IsFinite,IsPosInt],
        function(g,p)
    local a,compisabcp,pos,P;
    
    P:=SylowSubgroup(g,p);
    compisabcp:=ComputedIsAbCps(g);
    pos:=Position(compisabcp{[1,3..Length(compisabcp)-1]},p);
    if p<>fail then
        if IsAbCp(g,p)
           then
            return true;
        fi;
    fi;
    return IsPNilpotent(g,p) or IsAbCp(g,p);
end
);

#############################################################################
##
#F  IwasawaTripleWithSubgroup( <G>, <X>, <p> ) . . . . for finite groups
##
##  Returns an Iwasawa triple of the p-group g such that x belongs to it
##  if it exists one, fail otherwise.
##

InstallGlobalFunction(IwasawaTripleWithSubgroup,function(g,x,p)
    local a,b,c,d,e,h,s,t,res;
    ### We make sure that every generator spans a normal subgroup,
    ### otherwise there cannot be an Iwasawa triple
    if ForAny(GeneratorsOfGroup(x),t->not IsNormal(g,Subgroup(g,[t])))
       then 
        return fail;
    fi;
    e:=NaturalHomomorphismByNormalSubgroup(g,x);
    h:=Image(e);
    b:=PreImagesRepresentative(e,MinimalGeneratingSet(h)[1]);
    a:=First(GeneratorsOfGroup(x),t->Order(t)=Exponent(x));
    #    Print("a");
    for c in AllGeneratorsCyclicPGroup(b,p) do
        s:=First([1..Log(Order(a),p)],t->a^c=a^(1+p^t));
        #        Print("#I c=", c,"\ts=",s,"\n");
        if s<>fail
           then 
            res:=ForAll(GeneratorsOfGroup(x),t->t^c=t^(1+p^s));
            if res
               then 
                return [x,c,s];
            fi;
        fi;
    od;
    return fail;
end
  );


#############################################################################
##
#M  IwasawaTriple( <G> ) . . . . for finite groups
##
##  Computes an Iwasawa triple for the p-group G
##


InstallMethod(IwasawaTriple,"for finite p-groups",
        [IsGroup and IsFinite],
        function(P)
    local p,z,ex,x,l,l1,l2,res;
    if not IsPGroup(P) 
       then 
        Error("<P> must be a p-group for a prime p");
    elif IsTrivial(P)
      then
        #
        # We use this arbitrarily chosen value 
        # to avoid an error in the trivial case
        #
        return [P, Identity(P), 3];
    elif HasIsPTGroup(P) and not IsPTGroup(P)
      then
        # If we know that the group is not Iwasawa, there is no such triple
        return fail;
    else
    p:=PrimePGroup(P);
        if IsAbelian(P) 
           then
            return [P,Identity(P),Log(Exponent(P),p)];
        elif not IsAbelian(DerivedSubgroup(P))      # group should be metabelian
          then
            return fail;
        elif p=2 and Exponent(P)=4 
          then 
            if IsTGroup(P) then return []; else return fail; fi;
        else       
            # We apply Iwasawa's theorem by looking
            # for an abelian subgroup with cyclic quotient
            l:=[P];
            repeat
                x:=l[Length(l)];
                Unbind(l[Length(l)]);
                l1:=Filtered(MaximalSubgroups(x),
                            t->IsNormal(P,t) and IsCyclic(P/t));
                l:=Concatenation(l1,l);
                l2:=Filtered(l1,IsAbelian);
                for x in l2
                  do
                    res:=IwasawaTripleWithSubgroup(P,x,p);
                    if res<>fail
                       then
                        return res; 
                    fi;
                od;
            until l=[];
            return fail;
        fi;        
    fi;
end);
    
    
#############################################################################
##
#M  IsPTGroup( <G> ) . . . . for finite groups
##
##  Returns true if the group is a PT-group, else returns false 
##

InstallMethod(IsPTGroup,"for finite solvable groups",
        [IsGroup and IsFinite and IsSolvableGroup],
        function(G)
    local p;

    if HasIsPSTGroup(G) and not IsPSTGroup(G)
       then
        return false;
    elif HasIsCPTGroup(G) and not IsCPTGroup(G)
      then
        return false;
    elif IsSupersolvableGroup(G)
      #
      # for solvable groups, we use the property Yp + modular Sylow
      # subgroups
      #
      then
        return(ForAll(PrimesDividingSize(G),
                      p->(IsPNilpotent(G,p) and IsIwasawaSylow(G,p)) 
                      or IsAbCp(G,p)));
    else
        return false;
    fi;
end);

InstallMethod(IsPTGroup,"for finite groups",
        [IsGroup and IsFinite],
        function(G)
    local p;

    if HasIsPSTGroup(G) and not IsPSTGroup(G)
       then
        return false;
    fi;
    if HasIsCPTGroup(G) and not IsCPTGroup(G)
       then
        return false;
    fi;
    if IsSolvable(G)
       then
        return IsPTGroup(G);
    elif IsSCGroup(G)
      then
        #
        # we use the definition
        #
        return(OneSubnormalNonPermutableSubgroup(G)=fail);
    else 
        return false;
    fi;
end);

#############################################################################
##
#M  OneSubnormalNonSPermutableSubgroup( <G> ) . . . . for finite groups
##
##  The default method finds a non S-permutable subnormal subgroup of G
##  if such a subgroup exists, fail otherwise.
##

# If the group is a PST-group, return fail
InstallMethod(OneSubnormalNonSPermutableSubgroup,"for finite PST-groups",
        [IsGroup and IsFinite and IsPSTGroup],
        function(G)
    local z;
    return fail;
end);

# If we do not know whether the group is a PST-group,
# we try to find a subnormal subgroup of defect 2
# which is not S-permutable.

InstallMethod(OneSubnormalNonSPermutableSubgroup,"for finite groups non PST-groups",
        [IsGroup and IsFinite],
        function(G)
    local z,ex,ns,nsz,t;
    ns:=NormalSubgroups(G);
    for z in ns
      do
        nsz:=NormalSubgroups(z);
        ex:=First(nsz,t->not IsSPermutable(G,t));
        if ex<>fail
           then 
            SetIsPTGroup(G, false);
            SetIsTGroup(G, false);
            SetIsPSTGroup(G, false);
            return ex;
        fi;
    od;
    SetIsPSTGroup(G, true);
    return fail;
end);


#############################################################################
##
#M  OneSubnormalNonSNPermutableSubgroup( <G> ) . . . . for finite groups
##
##  The default method finds a non SN-permutable subnormal
## (permutable with all system normalisers) subgroup 
##  of the soluble group G if such a subgroup exists, fail otherwise.
##

# If the group is a PSNT-group, return fail.

InstallMethod(OneSubnormalNonSNPermutableSubgroup,"for finite PSNT-groups",
        [IsGroup and IsFinite and IsSolvableGroup and IsPSNTGroup],
        function(G)
    local z;
    return fail;
end);


# If we do not know whether the group is a PSNT-group,
# we try to find a subnormal subgroup
# which is not S-permutable.

InstallMethod(OneSubnormalNonSNPermutableSubgroup,"for finite groups",
        [IsGroup and IsFinite],
        function(G)
    local z,ex,ns,nsz,sns,d,t;
    if not IsSolvableGroup(G)
       then
        Error("<G> must be a solvable group");
    fi;
    sns:=AllSubnormalSubgroups(G);
    d:=SystemNormalizer(G);
    ex:=First(sns,t->not ArePermutableSubgroups(G,d,t));
    if ex<>fail
       then
        SetIsPSNTGroup(G, false);
    else
     SetIsPSNTGroup(G, true);
    fi;
    return ex;

end);




#############################################################################
##
#M  IsPSTGroup( <G> ) . . . . for finite groups
##
##  Returns true if the group is a PST-group, else returns false 
##


InstallMethod(IsPSTGroup,"for finite solvable groups",
        [IsGroup and IsFinite and IsSupersolvableGroup],
        function(G)
    local p;
    #
    # For finite soluble groups, we characterise it via Yp for all primes p:
    # p-nilpotent or abelian with Cp
    #
    return ForAll(PrimesDividingSize(G),
                  p->IsPNilpotent(G,p) or IsAbCp(G,p));
end);

InstallMethod(IsPSTGroup,"for finite groups",
        [IsGroup and IsFinite],
        function(G)
    local p;
    #
    # For finite soluble groups, we characterise it via Yp for all primes p:
    # p-nilpotent or abelian with Cp
    #
    if IsSolvable(G)
       then
        if not IsSupersolvableGroup(G)
           then
            return false;
        else
            return IsPSTGroup(G);
        fi;
    else
        if not IsSCGroup(G)
           then
            return false;
        else
            #
            # For non-solvable groups, we use the definition
            #
            return (OneSubnormalNonSPermutableSubgroup(G)=fail);
        fi;
    fi;
end);

#############################################################################
##
#M  IsPSNTGroup( <G> ) . . . . for finite groups
##
##  Returns true if the soluble group is a PSNT-group, else returns false 
##  A soluble group is a PSNT-group if permutability with system
##  normalisers is transitive.
##



InstallMethod(IsPSNTGroup, "for finite groups",
        [IsGroup and IsFinite],
        function(G)
    if IsSolvableGroup(G)
       then
        return (OneSubnormalNonSNPermutableSubgroup(G)=fail);
    else
        Error("<G> must be a solvable group");
    fi;
end
  );


#############################################################################
##
#M  OneSubnormalNonConjugatePermutableSubgroup( <G> ) . . . . for finite groups
##
##  The default method finds a non conjugate-permutable subnormal subgroup
##  of G if such a subgroup exists, fail otherwise.
##

# If the group is CPT, then return fail
InstallMethod(OneSubnormalNonConjugatePermutableSubgroup,"for finite CPT-groups",
        [IsGroup and IsFinite and IsCPTGroup],
        function(G)
    local z;
    return fail;
end);

# If we do not know whether the group is CPT, the same check would be valid
InstallMethod(OneSubnormalNonConjugatePermutableSubgroup,"for finite groups with AllSubnormalSubgroups",
        [IsGroup and IsFinite and HasAllSubnormalSubgroups],
        function(G)
    local z,ex;
    
    ex:=First(AllSubnormalSubgroups(G),z->not IsConjugatePermutable(G,z));
# Now it is easy to know whether the group is CPT
    if (ex=fail)
       then
        SetIsCPTGroup(G,true);
    else
        SetIsCPTGroup(G,false);
    fi;
    return ex;
end);

# If we do not know whether the group is a CPT-group,
# we look for a subnormal subgroup which is not conjugate-permutable.

InstallMethod(OneSubnormalNonConjugatePermutableSubgroup,"for finite groups non CPT-groups",
        [IsGroup and IsFinite],
        function(G)
    local z,ex,ns,nsz,sns,t,new,sn1,sn0,w,asn,x;
    
    sn0:=Set(NormalSubgroups(G));
    asn:=ShallowCopy(sn0);
    repeat
        sn1:=[];
        for x in sn0
          do
            new:=Filtered(NormalSubgroups(x),
                         x->not x in asn and not x in sn1);
            w:=First(new,z->not IsConjugatePermutable(G,z));
            if w<>fail
               then
                SetIsCPTGroup(G,false);
                SetIsPTGroup(G,false);
                SetIsTGroup(G,false);
                SetOneSubnormalNonPermutableSubgroup(G,w);
                SetOneSubnormalNonNormalSubgroup(G,w);
                return w;
            fi;
            UniteSet(sn1,new);
            
        od;
        sn0:=sn1;
        UniteSet(asn,sn1);
    until sn1=[];
    SetAllSubnormalSubgroups(G,asn);
    SetIsCPTGroup(G, true);
    return fail;
end);


#############################################################################
##
#M  IsCPTGroup( <G> ) . . . . for finite groups
##
##  Returns true if the group is a CPT-group (every subnormal subgroup
##  is conjugate-permutable), else returns false 
##


# For finite groups in general, we use the definition
InstallMethod(IsCPTGroup,"for finite groups",
        [IsGroup and IsFinite],
        function(G)
    local z,ex;
    ex:=OneSubnormalNonConjugatePermutableSubgroup(G);
    return (ex=fail);
end);

#############################################################################
##
#M  OneSubnormalNonNormalSubgroup( <G> ) . . . . for finite groups
##
##  The default method finds a non-normal subnormal subgroup of G 
##  if such a subgroup exists, otherwise returns false.
##

InstallMethod(OneSubnormalNonNormalSubgroup, "for finite groups with AllSubnormalSubgroups",
        [IsGroup and IsFinite and HasAllSubnormalSubgroups],
        function(G)
    local x;
    return Difference(AllSubnormalSubgroups(G),NormalSubgroups(G))=[];
end
  );

InstallMethod(OneSubnormalNonNormalSubgroup,"for finite groups non T-groups",
        [IsGroup and IsFinite],
        function(G)
    local z,ex,ns,nsz,t;
    ns:=NormalSubgroups(G);
    for z in ns
      do
        nsz:=NormalSubgroups(z);
        ex:=First(nsz,t->not IsNormal(G,t));
        if ex<>fail
           then 
            SetIsTGroup(G, false);
            return ex;
        fi;
    od;
    SetIsTGroup(G, true);
    return fail;
end);


#############################################################################
##
#M  IsTGroup( <G> ) . . . . for finite groups
##
##  Returns true if the group is a T-group, else returns false 
##

InstallMethod(IsTGroup,"for finite solvable groups",
        [IsGroup and IsFinite and IsSolvableGroup],
        function(G)
    local p;
    #
    # For finite soluble groups, we characterise it via Cp for all primes p:
    # p-nilpotent or abelian with Cp + Sylow Dedekind
    #
    if IsSupersolvableGroup(G)
       then
        return ForAll(PrimesDividingSize(G),
##                      p->(IsPERMUTPNilpotent(G,p) and IsDedekindSylow(G,p))
                      p->(IsPNilpotent(G,p) and IsDedekindSylow(G,p))
                      or IsAbCp(G,p));
    else
        return false;
    fi;
end);

InstallMethod(IsTGroup,"for finite groups",
        [IsGroup and IsFinite],
        function(G)
    local p;
    #
    # For finite soluble groups, we characterise it via Cp for all primes p:
    # p-nilpotent or abelian with Cp + Sylow Dedekind
    #
    if IsSolvable(G)
       then
        return IsPSTGroup(G);
    elif IsSCGroup(G)
      then
        
        #
        # For non-solvable groups, we use the definition
        #
        return (OneSubnormalNonNormalSubgroup(G)=fail);
    else
        return false;
    fi;
end);


#############################################################################
#############################################################################
##
#M  IsSCGroup( <G> ) . . . . for finite groups
##
##  Returns true if the group is an SC-group, and false otherwise.
##  A group is an SC-group if all its chief factors are simple.
##
##

InstallMethod(IsSCGroup, "for finite solvable groups",
        [IsGroup and IsFinite and IsSolvableGroup],
        function(g)
    return IsSupersolvableGroup(g);
end
  );

InstallMethod(IsSCGroup, "for finite groups with chief series",
        [IsGroup and IsFinite and HasChiefSeries],
        function(g)
    local cs,j,fact;
    cs:=ChiefSeries(g);
    fact:=List([1..Length(cs)-1],j->cs[j]/cs[j+1]);
    return ForAll(fact,IsSimple);
end
  );

InstallMethod(IsSCGroup, "generic method for a finite group",
        [IsGroup and IsFinite],
        function(g)
    local cs;
    if IsSolvable(g)
       then
        return IsSupersolvableGroup(g);
    else
        cs:=ChiefSeries(g);
        return IsSCGroup(g);
    fi;
end
  );

#############################################################################
##
#M  OneSubgroupInWhichSubnormalNotNormal( <G>, <H> ) . . . . for groups
##
##  This operation finds a subgroup K of G such that H is subnormal in K,
##  but H is not normal in K if such a subgroup exists, it returns fail otherwise.
##  H satisfies the subnormalizer condition in G when H subnormal in K
##  implies that H is normal in K.
##
                
InstallMethod(OneSubgroupInWhichSubnormalNotNormalOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite ],
        function(g,h)
    local x,int,t,cex,bool1,bool2;
    if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    
    bool1:=IsSubgroup(Parent(h),g);
    if 
       (bool1 and HasIsWithSubnormalizerConditionInParent(h) and
        IsWithSubnormalizerConditionInParent(h))
       then
        return fail;
    fi;
    if IsNormal(g,h)
    then
        return fail;
    fi;
    
    if IsSubnormal(g,h) then
        #
        # it cannot be normal in g
        #
        return g;
    fi;
                  
    bool2:=IsSubgroup(g,Parent(h));
    if (bool2 and HasOneSubgroupInWhichSubnormalNotNormalInParent(h)
        and OneSubgroupInWhichSubnormalNotNormalInParent(h)<>fail)
       then
        return OneSubgroupInWhichSubnormalNotNormalInParent(h);
    fi;
    int:=IntermediateSubgroups(g,h);
    cex:=First(int.subgroups, t->not IsNormal(t,h) and IsSubnormal(t,h));
    if  bool1 and bool2 then
        if cex=fail
           then
            SetIsWithSubnormalizerConditionInParent(h,true);
            SetIsWithSubpermutizerConditionInParent(h,true);
            SetIsWithSSubpermutizerConditionInParent(h,true);
        fi;
    fi;
    return cex;

end
  );

#############################################################################
##
#M  IsWithSubnormalizerCondition( <G>, <H> ) . . . . for groups
##
##  
##  This operation returns true if H satisfies the subnormaliser
##  condition in G, false otherwise.
##  H satisfies the subnormalizer condition in G when H subnormal in K
##  implies that H is normal in K.
##

InstallMethod(IsWithSubnormalizerConditionOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(g,h)
    local bool1,bool2;
    if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    bool1:=IsSubgroup(Parent(h),g);
    if bool1 and
       (
        (HasOneSubgroupInWhichSubnormalNotNormalInParent(h) and
         OneSubgroupInWhichSubnormalNotNormalInParent(h)=fail)
        or
        (HasIsWithSubnormalizerConditionInParent(h) and
         IsWithSubnormalizerConditionInParent(h))
        )       
       then
        return true;
    fi;
    bool2:=IsSubgroup(g,Parent(h));
    if bool2 and 
       (
        (HasOneSubgroupInWhichSubnormalNotNormalInParent(h) and
         OneSubgroupInWhichSubnormalNotNormalInParent(h)<>fail)
        or
        (HasOneSubgroupInWhichSubnormalNotPermutableInParent(h) and
         OneSubgroupInWhichSubnormalNotPermutableInParent(h)<>fail)
        or
        (HasOneSubgroupInWhichSubnormalNotSPermutableInParent(h) and
         OneSubgroupInWhichSubnormalNotSPermutableInParent(h)<>fail)
        or
        (HasIsWithSubnormalizerConditionInParent(h) and
         not IsWithSubnormalizerConditionInParent(h))
        or
        (HasIsWithSubpermutizerConditionInParent(h) and
         not IsWithSubpermutizerConditionInParent(h))
        or
        (HasIsWithSSubpermutizerConditionInParent(h) and
         not IsWithSSubpermutizerConditionInParent(h))
        )
       then
        return false;
    fi;
    return OneSubgroupInWhichSubnormalNotNormal(g,h)=fail;
end
  );

#############################################################################
##
#M  OneSubgroupInWhichSubnormalNotPermutable( <G>, <H> ) . . . . for groups
##
##  This operation finds a subgroup K of G such that H is subnormal in K,
##  but H is not permutable in K if such a subgroup exists,
##  otherwise it returns fail.
##  H satisfies the subpermutizer condition in G when H subnormal in K
##  implies that H is permutable in K.
##
                
InstallMethod(OneSubgroupInWhichSubnormalNotPermutableOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite ],
        function(g,h)
    local x,int,t,cex,bool1,bool2;
            
            if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");
    fi;    
    bool1:=IsSubgroup(Parent(h),g);
    if bool1 and
       (
        (HasIsWithSubnormalizerConditionInParent(h) and
         IsWithSubnormalizerConditionInParent(h))
        or
        (HasIsWithSubpermutizerConditionInParent(h) and
         IsWithSubpermutizerConditionInParent(h))
        )
       then
        return fail;
    fi;
    if IsNormal(g,h) or
       IsPermutable(g,h)
    then
        return fail;
    fi;
    
    if IsSubnormal(g,h) then
        #
        # h cannot be permutable in g
        #
        return g;
    fi;
    bool2:=IsSubgroup(g,Parent(h));
    if bool2 then
        if       
          (HasOneSubgroupInWhichSubnormalNotPermutableInParent(h)
           and OneSubgroupInWhichSubnormalNotPermutableInParent(h)<>fail)
        then
            
            return OneSubgroupInWhichSubnormalNotPermutableInParent(h);
        elif
          (HasOneSubgroupInWhichSubnormalNotSPermutableInParent(h)
           and OneSubgroupInWhichSubnormalNotSPermutableInParent(h)<>fail)
        then
            
            return OneSubgroupInWhichSubnormalNotSPermutableInParent(h);
        fi;
    fi;
    
    int:=IntermediateSubgroups(g,h);
    
    cex:=First(int.subgroups, t->not IsNormal(t,h) and IsSubnormal(t,h));
    if bool1 and bool2 then
        if cex=fail 
           then
            SetIsWithSubpermutizerConditionInParent(h,true);
            SetIsWithSSubpermutizerConditionInParent(h,true);
        else
            SetIsWithSubpermutizerConditionInParent(h,false);
            SetIsWithSubnormalizerConditionInParent(h,false);
        fi;
    fi;
    return cex;

end
  );

#############################################################################
##
#M  IsWithSubpermutizerCondition( <G>, <H> ) . . . . for groups
##
##  
##  This operation returns true if H satisfies the subpermutiser condition
##  in G, otherwise it returns false.
##  H satisfies the subpermutizer condition in G when H subnormal in K
##  implies that H is permutable in K.
##

InstallMethod(IsWithSubpermutizerConditionOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(g,h)
    local bool1,bool2;
    if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    
    bool1:=IsSubgroup(Parent(h),g);
    if bool1 and
       (
        (HasOneSubgroupInWhichSubnormalNotNormalInParent(h) and
         OneSubgroupInWhichSubnormalNotNormalInParent(h)=fail)
        or
        (HasIsWithSubnormalizerConditionInParent(h) and
         IsWithSubnormalizerConditionInParent(h))
        or
        (HasOneSubgroupInWhichSubnormalNotPermutableInParent(h) and
         OneSubgroupInWhichSubnormalNotPermutableInParent(h)=fail)
        or
        (HasIsWithSubpermutizerConditionInParent(h) and
         IsWithSubpermutizerConditionInParent(h))
        )       
       then
        return true;
    fi;
    bool2:=IsSubgroup(g,Parent(h));
    if bool2 and 
       (
        (HasOneSubgroupInWhichSubnormalNotPermutableInParent(h) and
         OneSubgroupInWhichSubnormalNotPermutableInParent(h)<>fail)
        or
        (HasOneSubgroupInWhichSubnormalNotSPermutableInParent(h) and
         OneSubgroupInWhichSubnormalNotSPermutableInParent(h)<>fail)
        or
        (HasIsWithSubpermutizerConditionInParent(h) and
         not IsWithSubpermutizerConditionInParent(h))
        or
        (HasIsWithSSubpermutizerConditionInParent(h) and
         not IsWithSSubpermutizerConditionInParent(h))
        )
       then
        return false;
    fi;
    return OneSubgroupInWhichSubnormalNotPermutable(g,h)=fail;
end
  );

#############################################################################
##
#M  OneSubgroupInWhichSubnormalNotSPermutable( <G>, <H> ) . . . . for groups
##
##  This operation finds a subgroup K of G such that H is subnormal in K,
##  but H is not S-permutable in K if such a subgroup exists, 
##  otherwise it returns fail.
##  H satisfies the S-subpermutizer condition in G when H subnormal in K
##  implies that H is S-permutable in K.
##
                
InstallMethod(OneSubgroupInWhichSubnormalNotSPermutableOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite ],
        function(g,h)
    local x,int,t,cex,bool1,bool2;
    if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    
    bool1:=IsSubgroup(Parent(h),g);
    if bool1 and
       (
        (HasIsWithSubnormalizerConditionInParent(h) and
         IsWithSubnormalizerConditionInParent(h))
        or
        (HasIsWithSubpermutizerConditionInParent(h) and
         IsWithSubpermutizerConditionInParent(h))
        or
        (HasIsWithSSubpermutizerConditionInParent(h) and
         IsWithSSubpermutizerConditionInParent(h))
        or
        IsSPermutable(g,h)
       )
       then
        return fail;
    fi;
    if IsNormal(g,h) or
       IsSPermutable(g,h)
    then
        return fail;
    fi;
    
    if IsSubnormal(g,h) then
        #
        # h cannot be S-permutable in g
        #
        return g;
    fi;
    bool2:=IsSubgroup(g,Parent(h));
    if bool2 then
        if       
          (HasOneSubgroupInWhichSubnormalNotPermutableInParent(h)
           and OneSubgroupInWhichSubnormalNotPermutableInParent(h)<>fail)
          then 
            return OneSubgroupInWhichSubnormalNotPermutableInParent(h);
        elif
          (HasOneSubgroupInWhichSubnormalNotSPermutableInParent(h)
           and OneSubgroupInWhichSubnormalNotSPermutableInParent(h)<>fail)
          then
            return OneSubgroupInWhichSubnormalNotSPermutableInParent(h);
        fi;
    fi;
    int:=IntermediateSubgroups(g,h);
    cex:=First(int.subgroups, t->not IsNormal(t,h) and IsSubnormal(t,h));
    if bool1 and bool2 then
        if cex=fail 
           then
            SetIsWithSSubpermutizerConditionInParent(h,true);
        else
            SetIsWithSSubpermutizerConditionInParent(h,false);
            SetIsWithSubpermutizerConditionInParent(h,false);
            SetIsWithSubnormalizerConditionInParent(h,false);
            
        fi;
    fi;
    return cex;

end
  );

#############################################################################
##
#M  IsWithSSubpermutizerCondition( <G>, <H> ) . . . . for groups
##
##  
##  This operation returns true if H satisfies the S-subpermutiser
##  condition in G, otherwise it returns false.
##  H satisfies the S-subpermutiser condition in G when H subnormal in K
##  implies that H is S-permutable in K.
##

InstallMethod(IsWithSSubpermutizerConditionOp, "for finite groups",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(g,h)
    local bool1,bool2;
    if not IsSubgroup(g,h)
       then
        Error("<h> must be a subgroup of <g>");
    fi;
    
    bool1:=IsSubgroup(Parent(h),g);
    if bool1 and
       (
        (HasOneSubgroupInWhichSubnormalNotNormalInParent(h) and
         OneSubgroupInWhichSubnormalNotNormalInParent(h)=fail)
        or
        (HasIsWithSubnormalizerConditionInParent(h) and
         IsWithSubnormalizerConditionInParent(h))
        or
        (HasOneSubgroupInWhichSubnormalNotPermutableInParent(h) and
         OneSubgroupInWhichSubnormalNotPermutableInParent(h)=fail)
        or
        (HasIsWithSubpermutizerConditionInParent(h) and
         IsWithSubpermutizerConditionInParent(h))
        or
        (HasOneSubgroupInWhichSubnormalNotSPermutableInParent(h) and
         OneSubgroupInWhichSubnormalNotSPermutableInParent(h)=fail)
        or
        (HasIsWithSSubpermutizerConditionInParent(h) and
         IsWithSSubpermutizerConditionInParent(h))
        )       
       then
        return true;
    fi;
    bool2:=IsSubgroup(g,Parent(h));
    if bool2 and 
       (
        (HasIsWithSSubpermutizerConditionInParent(h) and
         not IsWithSSubpermutizerConditionInParent(h))
        or
        (HasOneSubgroupInWhichSubnormalNotSPermutableInParent(h) and
         not OneSubgroupInWhichSubnormalNotSPermutableInParent(h)<>fail)
        )
         then
        return false;
    fi;
    return OneSubgroupInWhichSubnormalNotSPermutable(g,h)=fail;
end
  );

#############################################################################
##
#M  AreMutuallyPermutableSubgroups( <G>, <U>, <V> ) . . . . for finite groups
#M  AreMutuallyPermutableSubgroups( <U>, <V> )
##
##  This operation returns true if <U> and <V> are mutually permutable,
##  otherwise it returns false.
##  Two subgroups <U> and <V> are mutually permutable
##  if <U> permutes with all subgroups of <V>
##  and <V> permutes with all subgroups of <U>.
##

InstallMethod(AreMutuallyPermutableSubgroups, "with three arguments",
        [IsGroup and IsFinite, IsGroup and IsFinite, IsGroup and IsFinite],
        function(G, A, B)
    local t;
    if not (IsSubgroup(G,A) and IsSubgroup(G,B))
       then
        Error("<A> and <B> must be subgroups of <G>");
    fi;
   
    if not ArePermutableSubgroups(G,A,B)
       then
        return false;
    else
        if IsNormal(G,A) and IsNormal(G,B)
           then 
            return true;
        fi;
        return (IsNormal(G,B) or
                ForAll(Zuppos(A),
                       t->ArePermutableSubgroups(G,Subgroup(G,[t]),B)))
               and
               (IsNormal(G,A) or
                ForAll(Zuppos(B),
                       t->ArePermutableSubgroups(G,A,Subgroup(G,[t]))));
    fi;
end
  );

InstallOtherMethod(AreMutuallyPermutableSubgroups, "with two arguments",
        [IsGroup and IsFinite, IsGroup and IsFinite],
        function(A, B)
    local t,G;
    if not ArePermutableSubgroups(A,B)
       then
        return false;
    else
        if IsIdenticalObj(Parent(A),Parent(B))
           then
            G:=Parent(A);
        else
            G:=ClosureGroup(A,B);
        fi;
        if IsNormal(G,A) and IsNormal(G,B)
           then
            return true;
        fi;
        return (IsNormal(G,B) or
                ForAll(Zuppos(A),
--> --------------------

--> maximum size reached

--> --------------------

[ Dauer der Verarbeitung: 0.49 Sekunden  (vorverarbeitet)  ]