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


Quelle  projector.gi   Sprache: unbekannt

 
Spracherkennung für: .gi vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

#############################################################################
##
##  projector.gi                      CRISP                  Burkhard Höfling
##
##  Copyright © 2000-2003, 2005, 2011 Burkhard Höfling
##


#############################################################################
##
#M  CoveringSubgroupOp(<grp>, <class>)
##
InstallMethod(CoveringSubgroupOp, "for Schunck classes: return projector",
    true, 
    [IsGroup, IsSchunckClass], 0,
    function(G, C)
        return Projector(G, C);
 end);


#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "if ProjectorFunction is known", true, 
    [IsGroup, IsSchunckClass and HasProjectorFunction], 
    SUM_FLAGS, # highly preferable
    function(G, C)
        return ProjectorFunction(C)(G);
 end);


#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "compute from LocalDefinitionFunction", true, 
    [IsGroup and IsFinite and CanEasilyComputePcgs, 
        IsSaturatedFormation and HasLocalDefinitionFunction], 
    RankFilter(HasBoundaryFunction), # prefer to method using boundary func
    function(G, C)
        return ProjectorFromExtendedBoundaryFunction(
            G, 
            rec(
                char := Characteristic(C),
                class := C,
                dfunc := DFUNC_FROM_CHARACTERISTIC,
                cfunc := CFUNC_FROM_CHARACTERISTIC,
                kfunc := KFUNC_FROM_LOCAL_DEFINITION, 
                lfunc := function(G, p, data)
                    return LocalDefinitionFunction(data.class)(G, p);
                end),                
            false); # we want a projector, not a membership test
    end);


#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "compute from boundary", true, 
    [IsGroup and IsFinite and CanEasilyComputePcgs, 
        IsSchunckClass and HasBoundaryFunction], 
    RankFilter(HasMemberFunction),
    function(G, C)
        return ProjectorFromExtendedBoundaryFunction(
            G, 
            rec(
                cfunc := CFUNC_FROM_CHARACTERISTIC_SCHUNCK,
                char := Characteristic(C),
                class := C,
                bfunc := BFUNC_FROM_TEST_FUNC,
                test := function(G, data) 
                    return BoundaryFunction(data.class)(G);
                end),
            false); # we want a projector, not a membership test
    end);


#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "use MemberFunction", true, 
    [IsGroup and IsFinite and CanEasilyComputePcgs, 
        IsSchunckClass and HasMemberFunction], 
    0,
    function(G, C)
        return ProjectorFromExtendedBoundaryFunction(
            G, 
            rec(
                dfunc := DFUNC_FROM_MEMBER_FUNCTION,
                memberf := MemberFunction(C)),
          false); # we want a projector, not a membership test
    end);


#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "use only membership test", true, 
    [IsGroup and IsFinite and CanEasilyComputePcgs, 
        IsSchunckClass], 
    0,
    function(G, C)
        return ProjectorFromExtendedBoundaryFunction(
            G, 
            rec(
                class := C,
                char := Characteristic(C),
                cfunc := CFUNC_FROM_CHARACTERISTIC_SCHUNCK,
                bfunc := BFUNC_FROM_TEST_FUNC,
                test := function(G, data)
                    return not G in data.class;
                end),
          false); # we want a projector, not a membership test
    end);


#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "for intersection of group classes", true, 
    [IsGroup and IsFinite and CanEasilyComputePcgs, 
        IsSchunckClass and IsClassByIntersectionRep], 
    0,
    function(G, C)
        local D, data;
        data := rec(locform := [],
            schunck := [],
            others := [],
            char := Characteristic(C),
            cfunc := CFUNC_FROM_CHARACTERISTIC_SCHUNCK);
        
        for D in C!.intersected do
            if HasIsSchunckClass(D) and IsSchunckClass(D) then
                if HasLocalDefinitionFunction(D) then
                    Add(data.locform, D);    
                elif HasBoundaryFunction(D) then
                    Add(data.schunck, D);
                else
                    Add(data.others, D);
                fi;
            else
                Add(data.others, D);
            fi;
        od;
        
        if not IsEmpty(data.locform) then
            data.kfunc := KFUNC_FROM_LOCAL_DEFINITION;
            data.lfunc := function(G, p, data)
                local gens, new;
                    gens := [];
                    # compute generators of residual of intersection
                    #(this is the join of the generators of the
                    # residuals of the individual classes
                    for D in data.locform do
                        new := LocalDefinitionFunction(D)(G, p);
                        if new = fail then
                            return fail; # empty local definition
                        fi;
                        if IsGroup(new) then
                            new := GeneratorsOfGroup(new);
                        fi;
                        new := Union(gens, new);
                    od;
                return gens;
            end;
        fi;
        
        if not IsEmpty(data.others) or not IsEmpty(data.schunck) then
            data.bfunc := BFUNC_FROM_TEST_FUNC;
            data.test := function(G, dat)  
                    return ForAny(data.schunck, H -> BoundaryFunction(H)(G))
                        or ForAny(data.others, H -> not G in H);
                end;
        fi;
        
        return ProjectorFromExtendedBoundaryFunction(
            G, data, false); # we want a projector, not a membership test
    end);


#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, 
    "for intersection of group classes which is a local formation", true, 
    [IsGroup and IsFinite and CanEasilyComputePcgs, 
        IsSaturatedFormation and IsClassByIntersectionRep], 
    0,
    function(G, C)
        local D, data;
        data := rec(locform := [],
            schunck := [],
            others := [],
            char := Characteristic(C),
            dfunc := DFUNC_FROM_CHARACTERISTIC,
            cfunc := CFUNC_FROM_CHARACTERISTIC);
        
        for D in C!.intersected do
            if HasIsSchunckClass(D) and IsSchunckClass(D) then
                if HasLocalDefinitionFunction(D) then
                    Add(data.locform, D);    
                elif HasBoundaryFunction(D) then
                    Add(data.schunck, D);
                else
                    Add(data.others, D);
                fi;
            else
                Add(data.others, D);
            fi;
        od;
        
        if not IsEmpty(data.locform) then
            data.kfunc := KFUNC_FROM_LOCAL_DEFINITION;
            data.lfunc := function(G, p, data)
                local gens, new;
                    gens := [];
                    # compute generators of residual of intersection
                    #(this is the join of the generators of the
                    # residuals of the individual classes
                    for D in data.locform do
                        new := LocalDefinitionFunction(D)(G, p);
                        if new = fail then
                            return fail; # empty local definition
                        fi;
                        if IsGroup(new) then
                            new := GeneratorsOfGroup(new);
                        fi;
                        gens := Union(gens, new);
                    od;
                return gens;
            end;
        fi;
        
        if not IsEmpty(data.others) or not IsEmpty(data.schunck) then
            data.bfunc := BFUNC_FROM_TEST_FUNC;
            data.test := function(G, dat)  
                    return ForAny(data.schunck, H -> BoundaryFunction(H)(G))
                        or ForAny(data.others, H -> not G in H);
                end;
        fi;
        
        return ProjectorFromExtendedBoundaryFunction(
            G, data, false); # we want a projector, not a membership test
    end);


#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
InstallMethodByNiceMonomorphismForGroupAndClass(ProjectorOp, 
    IsFinite and IsSolvableGroup, IsSchunckClass);
    
    
#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
InstallMethodByIsomorphismPcGroupForGroupAndClass(ProjectorOp, 
    IsFinite and IsSolvableGroup, IsSchunckClass);
    
    
#############################################################################
##
#M  ProjectorOp(<grp>, <class>)
##
CRISP_RedispatchOnCondition(ProjectorOp,
    "redispatch if group is finite or soluble",
    true,
    [IsGroup, IsGroupClass], [IsFinite and IsSolvableGroup],
    RankFilter(IsGroup) + RankFilter(IsGroupClass));


###################################################################################
##
#F  BFUNC_FROM_TEST_FUNC_FAC(<upcgs>, <cpcgs>, <kpcgs>, <npcgs>, <p>, 
##      <centind>, <data>)
##
InstallGlobalFunction(BFUNC_FROM_TEST_FUNC_FAC, 
    function(upcgs, cpcgs, kpcgs, npcgs, p, centind, data)
        local H, N, cent, x, nat, F, hom;
    
        H := GroupOfPcgs(upcgs);
        hom := NaturalHomomorphismByNormalSubgroupNC(H,
            GroupOfPcgs(DenominatorOfModuloPcgs(npcgs)));
            
        # compute centralizer of npcgs in the group generated by cpcgs
        # in factor group
        N := ImagesSet(hom, GroupOfPcgs(NumeratorOfModuloPcgs(npcgs)));
        cent := Centralizer(ImagesSet(hom, GroupOfPcgs(cpcgs)), N);
            
        # now compute primitive image
        nat := NaturalHomomorphismByNormalSubgroupNC(ImagesSource(hom), cent);
        F := ImagesSource(nat);
        SetIsPrimitiveSolubleGroup(F, true);
        SetSocle(F, ImagesSet(nat, N));
        SetSocleComplement(F, 
            ImagesSet(nat, ImagesSet(hom, GroupOfPcgs(cpcgs))));
        return data.test(F, data);
    end);


###################################################################################
##
#F  BFUNC_FROM_TEST_FUNC_MOD(<upcgs>, <cpcgs>, <kpcgs>, <npcgs>, <p>, 
##      <centind>, <data>)
##
InstallGlobalFunction(BFUNC_FROM_TEST_FUNC_MOD, 
    function(upcgs, cpcgs, kpcgs, npcgs, p, centind, data)
        local H, cent, x, nat, F;
    
        H := GroupOfPcgs(upcgs);
         cent := GroupOfPcgs(cpcgs);
        for x in npcgs do
            cent := CentralizerModulo(cent, 
                GroupOfPcgs(DenominatorOfModuloPcgs(npcgs)), 
                x);
        od;
        
        # compute H/C_<cpcgs>(npcgs), which will be the primitive factor group
        # which either lies in the Schunck class or its boundary
        
        nat := NaturalHomomorphismByNormalSubgroupNC(H, cent);
        F := ImagesSource(nat);
        SetIsPrimitiveSolubleGroup(F, true);
        SetSocle(F, ImagesSet(nat, GroupOfPcgs(npcgs)));
        SetSocleComplement(F, ImagesSet(nat, GroupOfPcgs(cpcgs)));
        return data.test(F, data);
    end);


###################################################################################
##
#F  KFUNC_FROM_LOCAL_DEFINITION(<upcgs>, <kpcgs>, <npcgs>, <p>, <centind>, <data>)
##
InstallGlobalFunction(KFUNC_FROM_LOCAL_DEFINITION,
    function(upcgs, kpcgs, npcgs, p, cent, data)
        local ldef;
        ldef := data.lfunc(GroupOfPcgs(upcgs), p, data);
        if ldef = fail then 
            return true; # empty local def - in boundary
        elif IsGroup(ldef) then
            ldef := GeneratorsOfGroup(ldef);
        fi;
        return not CentralizesLayer(ldef, npcgs);
    end);
    

###################################################################################
##
#F  DFUNC_FROM_CHARACTERISTIC(<upcgs>, <npcgs>, <p>, <data>)
##
##  this only works if groups in C only have prime divisors in the characteristic
##
InstallGlobalFunction(DFUNC_FROM_CHARACTERISTIC, 
    function(upcgs, npcgs, p, data) 
        if p in data.char then
            return fail;
        else 
            return true; 
        fi;
    end);


###################################################################################
##
#F  DFUNC_FROM_MEMBER_FUNCTION(<upcgs>, <npcgs>, <p>, <data>)
##
##  use a membership function to test if the factor group is in the class
##
InstallGlobalFunction(DFUNC_FROM_MEMBER_FUNCTION, 
    function(upcgs, npcgs, p, data) 
        return not data.memberf(
         GroupOfPcgs(upcgs)/GroupOfPcgs(DenominatorOfModuloPcgs(npcgs)));
    end);


###################################################################################
##
#F  CFUNC_FROM_CHARACTERISTIC(<upcgs>, <npcgs>, <p>, <centind>, <data>)
##
InstallGlobalFunction(CFUNC_FROM_CHARACTERISTIC, 
    function(upcgs, npcgs, p, centind, data) 
        if centind = 1 then # p in Characteristic has been tested by DFUNC...
            return false; # the primitive group is cyclic of order p
        else
            return fail;
        fi;
    end);


###################################################################################
##
#F  CFUNC_FROM_CHARACTERISTIC_SCHUNCK(<upcgs>, <npcgs>, <p>, <centind>, <data>)
##
InstallGlobalFunction(CFUNC_FROM_CHARACTERISTIC_SCHUNCK, 
    function(upcgs, npcgs, p, centind, data) 
        if centind = 1 and p in data.char then
            return false; # the primitive group is cyclic of order p
        else
            return fail;
        fi;
    end);


###################################################################################
##
#M  ProjectorFromExtendedBoundaryFunction(<grp>, <rec>, <inonly>) 
##
InstallMethod(ProjectorFromExtendedBoundaryFunction, "for pc group",
    [IsPcGroup and IsFinite, IsRecord, IsBool], 0,
    function(grp, r, inonly)
        local pcgs, re;

        if not IsBound(r.dfunc) then
            r.dfunc := ReturnFail;
        fi;
        if not IsBound(r.cfunc) then
            r.cfunc := ReturnFail;
        fi;
        if not IsBound(r.kfunc) then
            r.kfunc := ReturnFail;
        fi;
        if not IsBound(r.bfunc) then
            r.bfunc := ReturnFail;
        fi;

        pcgs := PcgsElementaryAbelianSeries(grp);
        re := PROJECTOR_FROM_BOUNDARY(
            pcgs, r, inonly, true, true);
        if inonly then
            return re;
        else
            return GroupOfPcgs(re);
        fi;
    end);
    
    
###################################################################################
##
#M  ProjectorFromExtendedBoundaryFunction(<grp>, <rec>, <inonly>) 
##
InstallMethod(ProjectorFromExtendedBoundaryFunction, "for soluble groups",
    [IsGroup and IsFinite and IsSolvableGroup, IsRecord, IsBool], 0,
    function(grp, r, inonly)
        local pcgs, re;
        if not IsBound(r.dfunc) then
            r.dfunc := ReturnFail;
        fi;
        if not IsBound(r.cfunc) then
            r.cfunc := ReturnFail;
        fi;
        if not IsBound(r.kfunc) then
            r.kfunc := ReturnFail;
        fi;
        if not IsBound(r.bfunc) then
            r.bfunc := ReturnFail;
        fi;

        pcgs := PcgsElementaryAbelianSeries(grp);
        re := PROJECTOR_FROM_BOUNDARY(
            pcgs, r, inonly, false, false);
        if inonly then
            return re;
        else
            return GroupOfPcgs(re);
        fi;
    end);
    
    
###################################################################################
##
#M  ProjectorFromExtendedBoundaryFunction(<grp>, <rec>, <inonly>) 
##
CRISP_RedispatchOnCondition(ProjectorFromExtendedBoundaryFunction, 
    "redispatch if group is finite or soluble",
    true,
    [IsGroup, IsRecord, IsBool], 
    [IsGroup and IsSolvableGroup],
    RankFilter(IsGroup) + RankFilter(IsRecord) + RankFilter(IsBool));
    

###################################################################################
##
#F  PROJECTOR_FROM_BOUNDARY(<gpcgs>, <data>, <inonly>, <hom>, <conv>)
##  
InstallGlobalFunction("PROJECTOR_FROM_BOUNDARY", 
    function(pcgs, data, inonly, hom, conv)

    local 
        ppcgs,        # pcgs wrt to which all computations are carried out
        grp,          # group in which all computations are carried out
        opcgs,        # image of ppcgs
        elabpcgs,    # elementary abelian series derived from pcgs
        fac,          # images mod el. ab. series
        inds,         # indices of pcgs exhibiting an elementary abelian series
        upcgs,        # pcgs of a projector
        userinds,    # indices of an el. ab. series of upcgs,
                        # as obtained by intersecting with elabpcgs
        diff,         # difference between composition length of projector
                        # of upcgs mod elabpcgs[i+1] and upcgs mod elabpcgs[i]
        userp,        # prime exponents of el ab series of upcgs
        i, j,         # loop variables
        mpcgs,        # modulo pcgs representing a factor of the series in elabpcgs
        ser,          # upcgs-composition series of mpcgs
        npcgs,        # modulo pcgs representing a composition factor of ser
        centind,     # all elements of upcgs {[centind..Length(upcgs)]} centralise npcgs
        centpcgs,    # upcgs {[centind..Length(upcgs)]}
        p,             # exponent of mpcgs and npcgs
         cpcgs,        # pcgs of a complement of npcgs in upcgs
         kpcgs,        # pcgs of a normal complement of npcgs in a suitable normal subgroup
                         # of upcgs
         id,            # a suitable identity matrix
         bool;         # result returned by the boundary function, or false if no complement
              
    if Length(pcgs) = 0 then
        if inonly then
            return true;
        else
            return pcgs;
        fi;
    fi;
    
    if not IsPcgsElementaryAbelianSeries(pcgs) then
        Error("pcgs must refine an elementary abelian series");
    fi;
    
    inds := IndicesEANormalSteps(pcgs);
    
    if conv or hom then
        grp := PcGroupWithPcgs(pcgs);
    else
        grp := GroupOfPcgs(pcgs);
    fi;
    
    if hom then 
        # compute factor groups modulo subgroups in el. ab. series of pcgs
        fac := [];
        fac[Length(inds)] := grp;
        for j in [Length(inds)-1, Length(inds)-2..2] do
            ppcgs := FamilyPcgs(fac[j+1]);
            fac[j] := PcGroupWithPcgs(
                ppcgs mod InducedPcgsByPcSequenceNC(ppcgs, ppcgs{[inds[j]..Length(ppcgs)]}));
        od;
    else
        if conv then
            ppcgs := FamilyPcgs(grp);
        else
            ppcgs := pcgs;
        fi;
        elabpcgs := List(inds, 
            i -> InducedPcgsByPcSequenceNC(pcgs, pcgs{[i, i+1..Length(pcgs)]}));
        upcgs := pcgs; # set up the projector
        ppcgs := pcgs;
    fi;
    userinds := [1];
    userp := [];
    
    # treat the layers of the elementary abelian series obtained from pcgs
    for j in [1,2..Length(inds) - 1] do
        Info(InfoProjector, 1, "starting step ",j, " of ",Length(inds) - 1);
        
        if hom then
            # translate results from factor group
            grp := fac[j+1];
            ppcgs := FamilyPcgs(grp);
            mpcgs := InducedPcgsByPcSequenceNC(ppcgs, ppcgs{[inds[j]..Length(ppcgs)]});
            if j = 1 then
                upcgs := ppcgs; # projector is whole group
            else
                opcgs := FamilyPcgs(fac[j]);
                upcgs := InducedPcgsByPcSequenceNC(ppcgs,
                    Concatenation( List(upcgs, x -> 
                        PcElementByExponentsNC(ppcgs, [1..inds[j]-1], ExponentsOfPcElement(opcgs, x))),
                        mpcgs));
            fi;
        else
            mpcgs := elabpcgs[j] mod elabpcgs[j+1]; 
        fi;
        
        # we assume that upcgs mod elabpcgs[j] represents a projector
        # of pcgs mod elabpcgs[j]
                
        p := RelativeOrderOfPcElement(ppcgs, mpcgs[1]); # exp. of mpcgs
        
        ser := PcgsCompositionSeriesElAbModuloPcgsUnderAction(
            upcgs{[1,2..userinds[Length(userinds)]-1]}, mpcgs);
            
        Info(InfoProjector, 2, Length(ser)-1, " composition factors");
        
        diff := 0; # assume that the composition length remains the same
        
        # now find a projector of upcgs mod elabpcgs[j+1] - this
        # will be a projector of pcgs mod elabpcgs[j+1] as well
        
        for i in [1..Length(ser) - 1] do
        
            # We want to replace upcgs mod ser[i+1] by one of its
            # projectors. There are two possibilities
            # between which dfunc, cfunc, kfunc, bfunc try to decide:
            # if upcgs mod ser[i+1] is in the Schunck class,
            # it is itself a projector. In this case, we have bool=false
            # eventually. Otherwise the projectors are the maximal subgroups 
            # complementing ser[i] mod ser[i+1](bool = true).
            # If we want to decide membership 
            # only, we can return false as soon as we know that
            # the projector is a proper subgroup, i.e., as soon as bool
            # becomes true.
            

            npcgs := ser[i] mod ser[i+1];
            
            # try if we can decide with only minimal information
            # for instance by testing if p is in the characteristic of a
            # saturated formation
            
            bool := data.dfunc(upcgs, npcgs, p, data);
            Info(InfoProjector, 3, "dfunc returns ", bool);

            if inonly and bool = true then
                return false; # factor group in boundary 
            fi;
            
            if bool <> false then 
                # if dfunc returns false, we know that upcgs mod ser[i+1] is the projector
                # Otherwise we look for a complement of npcgs = ser[i] mod ser[i+1]
                
                Info(InfoProjector, 2, "complementing factor of size ",p,"^",Length(npcgs));
                centind := Length(userinds);
                
                # find the largest term centpcgs in the el. ab. series 
                # of upcgs centralising npcgs
                
                while centind > 1 and 
                    (p = userp[centind-1] or 
                        CentralizesLayer(upcgs{[userinds[centind-1]..userinds[centind]-1]}, npcgs)) do
                            centind := centind - 1;
                od;
                                
                Info(InfoProjector, 3, "centralizing level: ",userinds[centind]);
                
                centpcgs := InducedPcgsByPcSequenceNC(ppcgs, 
                            upcgs{[userinds[centind]..Length(upcgs)]});
                
                # if we haven't reached a decision yet, try with additional information
                # for instance if npcgs is central, we can use the characteristic of the
                # Schunck class
                
                if bool = fail then
                    bool := data.cfunc(upcgs, npcgs, p, userinds[centind], data);
                    Info(InfoProjector, 3, "cfunc returns ", bool);
                    if inonly and bool = true then
                        return false;
                    fi;
                fi;
                
                if bool <> false then
                    # now find upcgs-invariant complement of npcgs in centpcgs 
                    # note that any complement of npcgs in upcgs intersects
                    # centpcgs in such a complement, and any upcgs-invariant
                    # complement arises in that way(see crisp.dvi)
                
                    if centind = Length(userinds) and i = 1 and diff = 0 then 
                        # centind = Length(userinds) means that ser[1] = centpcgs, so that
                        # the complement is trivial
                        kpcgs := ser[i+1];
                        Info(InfoProjector, 3, "trivial normal complement");
                    else
                        kpcgs := PcgsComplementsOfCentralModuloPcgsUnderActionNC(
                            List(upcgs{[1,2..userinds[centind]-1]}, 
                                x -> InnerAutomorphismNC(grp, x)), 
                            ppcgs, centpcgs mod ser[i], npcgs, ser[i+1], false);
                        if Length(kpcgs) = 0 then # no complement exists
                            kpcgs := fail;
                            bool := false;
                            Assert(1, p in userp, 
                                "coprime situation but no complement");
                            Info(InfoProjector, 3, "no normal complement found");
                        else
                            Info(InfoProjector, 3, Length(kpcgs)," normal complement(s) found");
                            kpcgs := kpcgs[1]; # we only want one normal complement
                            Assert(1, IsSubgroup(GroupOfPcgs(kpcgs), GroupOfPcgs(ser[i+1])),
                                " complement is not a subgroup");
                            Assert(1, GroupOfPcgs(SumPcgs(ppcgs, kpcgs, ser[i]))
                                = GroupOfPcgs(InducedPcgsByPcSequenceNC(ppcgs, 
                                    upcgs{[userinds[centind]..Length(upcgs)]})),
                                "wrong join for normal complement");
                            Assert(1, GroupOfPcgs(NormalIntersectionPcgs(ppcgs, kpcgs, ser[i]))
                                = GroupOfPcgs(ser[i+1]),
                                "wrong intersection for normal complement");
                        fi;
                    fi;
                    if bool = fail then
                        # we have more information(kpcgs) at hand, so 
                        # try to decide again
                        bool := data.kfunc(upcgs, kpcgs, npcgs, p, 
                            userinds[centind], data);
                        Info(InfoProjector, 3, "kfunc returns ", bool);
                        
                        if inonly and bool = true then
                            return false; # not in Schunck class
                        fi;
                    fi;
                fi;
                
                if bool <> false then
                    # at this point, we either know whether upcgs mod ser[i+1]
                    # is in the Schunck class(bool = false/true), or we have
                    # an upcgs-invariant subgroup of centpcgs complementing
                    # npcgs
                    
                    # now find a complement of npcgs in upcgs
                    if centind = 1 then 
                        # npcgs is central, so kpcgs is a complement
                        cpcgs := kpcgs;
                        Info(InfoProjector, 3, "central socle");
                    else
                        Assert(1, userp[centind-1] <> p, Error("wrong prime ", p));
                        Info(InfoProjector, 3, "noncentral socle - computing complement");
                        # compute a complement of npcgs from the normal complement
                        # obtained before
                        cpcgs := PcgsComplementOfChiefFactor(ppcgs,
                            upcgs{[1..userinds[centind]-1]}, 
                                userinds[centind-1], centpcgs mod kpcgs, kpcgs);
                        Assert(1, Length(npcgs) + Length(cpcgs) = Length(upcgs),
                            Error("cpcgs does not complement"));
                    fi;
        
                    if bool = fail then
                        # now we have all information at hand - do the final test
                        Info(InfoProjector, 3, "testing group of size ", 
                            Product(RelativeOrders(upcgs)) / 
                            Product(RelativeOrders(ser[i+1])),
                            " size of socle: ",
                            Product(RelativeOrders(npcgs)),
                            " size of complement: ",
                            Product(RelativeOrders(cpcgs)) / 
                            Product(RelativeOrders(ser[i+1])));
                            
                        bool := data.bfunc(upcgs, cpcgs, kpcgs, npcgs, p, 
                            userinds[centind], data);
                        Info(InfoProjector, 3, "bfunc returns ", bool);
                            
                        if bool = fail then
                            Error("bfunc must not return fail");
                        fi;
                        
                        if inonly and bool = true then
                            return false;
                        fi;
                        
                    fi;
                fi;
            fi;
            
            if bool then # cpcgs mod ser[i+1] is a projector
                upcgs := cpcgs; 
                # note that npcgs centralises ser and that cpcgs together with npcgs
                # generate the same group as upcgs, so that ser is also a
                # cpcgs-composition series of mpcgs
            else
                diff := diff + Length(npcgs); # adjust composition length
            fi;
        od;
        if diff > 0 then # update the elementary abelian series of upcgs
            Add(userp, p);
            Add(userinds, userinds[Length(userinds)]+diff);
        fi;
    od;
    if inonly then # group equals projector, so it belongs to the Schunck class
        return true;
    fi;
    
    if hom or conv then # translate result back to previous pcgs
        upcgs := InducedPcgsByPcSequenceNC(pcgs,
            List(upcgs, x -> 
                PcElementByExponentsNC(pcgs, ExponentsOfPcElement(ppcgs, x))));
    fi;
    return upcgs;
end);


############################################################################
##
#E
##

[ Dauer der Verarbeitung: 0.45 Sekunden  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge