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


Quellcode-Bibliothek pcgsspec.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Bettina Eick.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##


#############################################################################
##
#F  PrimePowerPcSequence( <pcgs> )
##
BindGlobal( "PrimePowerPcSequence", function( pcgs )
    local   new,  i,  p;

    new := List( [1..Length(pcgs)], x -> false );
    p   := RelativeOrders( pcgs );
    for i in [1..Length(pcgs)] do
        new[i] := PrimePowerComponent( pcgs[i], p[i] );
    od;
    return new;
end );


#############################################################################
##
#F  ModifyPcgs( ... )
##
DeclareGlobalName("ModifyPcgs");
BindGlobal( "ModifyPcgs", function( pcgs, wf, list, weights, work, g, wt )
    local d, h, S, s, min, tmp, i;

    # the trivial case
    d := DepthOfPcElement( pcgs, g );
    if d > Length( pcgs ) then return d; fi;

    h := ReducedPcElement( pcgs, list[d], g );
    S := PrimePowerComponents( h );

    # insert h in base
    if weights[ d ] < wt  then

        Info(InfoSpecPcgs, 3, " insert ", g );
        Info(InfoSpecPcgs, 3, " at position ",d," with weight ", wt);
        tmp := weights[ d ];
        weights[ d ] := wt;
        list[ d ] := g;

        # correct work-flag
        work[ d ] := List( work[ d ], x -> true );
        for i in [d..Length( pcgs )]  do
            work[ i ][ d ] := true;
        od;

        # ModifyPcgs with components of h
        for s  in S  do
            ModifyPcgs( pcgs, wf, list, weights, work, s,
                        wf.adj( pcgs, s, tmp ));
        od;
        return d;

    # base is not changed
    else

        # modify with components of gg
        min := Length( pcgs ) + 1;
        for s  in S  do
            tmp := wf.adj( pcgs, s, wt );
            min := Minimum( min,
                   ModifyPcgs(pcgs, wf, list, weights, work , s, tmp) );
        od;
        return min;
    fi;
end );


#############################################################################
##
#F  PcgsSystemWithWf( <pcgs> <wf> )
##
BindGlobal( "PcgsSystemWithWf", function( pcgs, wf )
    local   ppcgs,  m,  list,  weights,  work,  nilp,  h,  i,  j,  g,  S,
            pos,  s,  wt,  newpcgs,  wset,  layers,  first;

    ppcgs := PrimePowerPcSequence( pcgs );

    # initialise
    m    := Length( pcgs );
    list := ShallowCopy( ppcgs );
    weights := List( list, x -> wf.one( pcgs, x ) );
    work    := List( [1..m], x -> List( [1..x], y -> true ) );

    # run down series
    nilp := 1;
    h := 1;
    while h <= nilp+1 do

        # run through powers and commutators
        Info(InfoSpecPcgs, 2, " start layer ",h);
        i := 1;
        while i <= m  do
            j := 1;
            while j <= i  do
                if wf.relevant( pcgs, weights, i, j, h ) and work[i][j]  then
                    Info(InfoSpecPcgs, 3, " try ",i," ",j);

                    # set work flag new
                    if wf.useful( weights, i, j, h ) then
                        work[ i ][ j ] := false;
                    fi;

                    # modify with components of power or commutator
                    if i = j  then
                        g := list[ i ] ^ weights[i][3];
                    else
                        g := Comm( list[ i ], list[ j ] );
                    fi;
                    S := PrimePowerComponents( g );
                    pos := m + 1;
                    for s  in S  do
                        wt := wf.weight( pcgs, weights, i, j, h, s );
                        pos := Minimum( pos,
                        ModifyPcgs( pcgs, wf, list, weights, work, s, wt ) );
                    od;

                    # if necessary, set indices new
                    if pos <= i  then
                        i := pos;
                        j := 0;
                    fi;
                fi;
                j := j+1;
            od;
            i := i+1;
        od;
        h := h+1;

        # set nilp
        for i in [1..m] do
            nilp := Maximum( nilp, weights[i][1] );
        od;
    od;

    # sort
    SortParallel( weights, list );

    # compute pcgs - be careful!
    if ppcgs = AsList( pcgs ) and
       ForAll( [1..m], x -> DepthOfPcElement(pcgs, list[x]) = x )
    then
        newpcgs := pcgs;
    else
        newpcgs := PcgsByPcSequenceNC( FamilyObj(OneOfPcgs(pcgs)), list );
        SetRelativeOrders(newpcgs, List(weights, x -> x[3]));
        SetOneOfPcgs( newpcgs, OneOfPcgs(pcgs) );
    fi;

    # set up layers
    wset := Set( weights );
    layers := List( [1..m], x -> Position( wset, weights[x] ) );

    # set up first
    first := [1];
    for i in [2..m] do
        if weights[i] <> weights[i-1] then
            Add( first, i );
        fi;
    od;
    Add( first, m+1 );

    return rec( pcgs    := newpcgs,
                weights := weights,
                layers  := layers,
                first   := first );
end );


#############################################################################
##
#F  PcgsSystemLGSeries( <pcgs> )
##
BindGlobal( "PcgsSystemLGSeries", function( pcgs )
    local wf;

    # set up weight function
    wf := rec(

        adj := function( pcgs, g, wt )
            wt := ShallowCopy( wt );
            wt[ 3 ] := RelativeOrderOfPcElement( pcgs, g );
            return wt;
        end,

        one := function( pcgs, g )
            return [ 1, 1, RelativeOrderOfPcElement( pcgs, g ) ];
        end,

        relevant := function( pcgs, w, i, j, h )
            if i = j  and (w[i][1] = h-1 or w[i][1] = h+1)  then
                return true;
            else
                if w[i][1] = w[j][1]  then
                    if w[i][1] = h-1 and w[i][3] = w[j][3] and
                      (w[i][2] = 1 or w[j][2] = 1)  then
                        return true;
                    elif w[i][1] = h  and w[i][3] <> w[j][3]  then
                        return true;
                    elif w[i][1] >= h+1  then
                        return true;
                    else
                        return false;
                    fi;
                elif w[i][1] >= h+1 and w[j][1] >= h+1 then
                     return true;
                elif w[i][1] = h+1  and w[j][1] <= h  and w[j][2] = 1  then
                     return true;
                elif w[i][1] <= h  and w[j][1] = h+1  and w[i][2] = 1  then
                     return true;
                else
                     return false;
                fi;
            fi;
        end,

        weight := function( pcgs, w, i, j, h, g )
            local p;

            p := RelativeOrderOfPcElement(pcgs, g);
            if i = j  then
                if w[i][1] = h-1  then
                    return [ w[i][1], w[i][2]+1, w[i][3] ];
                else
                    return w[i];
                fi;
            else
                if w[i][1] = w[j][1]  and w[i][1] = h-1  then
                    return [ w[i][1], w[i][2]+w[j][2], w[i][3] ];
                elif w[i][1] = w[j][1]  and w[i][1] = h  then
                    return [ w[i][1]+1, 1, p ];
                elif w[i][1] = w[j][1]  and w[j][1] >= h+1  then
                    if w[i][3] <> w[j][3] or w[i][3] <> p then
                        return [w[i][1]+1, 1, p];
                    else
                        return [w[i][1], 1, p];
                    fi;
                else
                    return [ Maximum( w[i][1],w[j][1] ), 1, p ];
                fi;
            fi;
        end,

        useful := function( w, i, j, h )

            if i = j and w[i][1] >= h+1 then
                return false;
            elif i<>j and w[i][1] = w[j][1] and w[i][1] >= h+1 and
                w[i][3] = w[j][3] then
                return false;
            else
                return true;
            fi;
        end
    );

    return PcgsSystemWithWf( pcgs, wf );
end );


#############################################################################
##
#F  LeastBadHallLayer( <pcgssys>, <i> )
##
BindGlobal( "LeastBadHallLayer", function( pcgssys, i )
    local m, pi, bad, j, w, pj, k, exponents;

    m  := Length( pcgssys.pcgs );
    pi := pcgssys.weights[ i ][ 3 ];

    # run through powers/commutators and search for bad one
    bad := m + 1;
    for j  in [ i .. m ]  do
        if j = i  then
            w := pcgssys.pcgs[ i ] ^ pi;
            pj := pi;
        else
            w := Comm( pcgssys.pcgs[ j ], pcgssys.pcgs[ i ] );
            pj := pcgssys.weights[ j ][ 3 ];
        fi;
        if DepthOfPcElement( pcgssys.pcgs, w ) <= m then
            exponents := ExponentsOfPcElement( pcgssys.pcgs, w, [i+1..m] );
            k := 1;

            # run through exponent list until bad entry is found
            while k <= Length( exponents )  do

                # test primes
                if exponents[k] <> 0 and
                   pi <> pcgssys.weights[k+i][3] and
                   pj <> pcgssys.weights[k+i][3]
                then
                    bad := Minimum( bad, k+i );
                    k := Length( exponents ) + 1;
                else
                    k := k + 1;
                fi;
            od;
        fi;

        # if bad is minimal return; otherwise go on
        if i = bad -1  then
            return bad;
        fi;
    od;
    return bad;
end );


#############################################################################
##
#F  PcgsSystemWithHallSystem( <pcgssys> )
##
BindGlobal( "PcgsSystemWithHallSystem", function( pcgssys )
    local m, i, k, n, F,
          layer, start, next, size, base,
          V, M,
          pi, pk, field, id,
          g, v, A, I, B, l, test, aij,
          new, solution, j, subs;

    # set up
    m   := Length( pcgssys.pcgs );
    F   := FamilyObj(OneOfPcgs(pcgssys.pcgs));

    # find starting index
    n := m;
    while 1 <= n and pcgssys.weights[n][1] = pcgssys.weights[m][1] do
         n := n - 1;
    od;
    if n = 1 and pcgssys.weights[n][1] = pcgssys.weights[m][1] then
        return pcgssys;
    fi;

    # run up the composition series
    for i in Reversed( [1..n] ) do
        Info(InfoSpecPcgs, 2, " start ",i,"th pcgs element");
        k := LeastBadHallLayer( pcgssys, i );
        while k <= m do
            Info(InfoSpecPcgs, 2, "  bad layer ",k);
            layer := pcgssys.layers[k];
            start := pcgssys.first[ layer ];
            next  := pcgssys.first[ layer+1 ];
            size  := next - start;
            base  := pcgssys.pcgs{[start..next-1]};

            # InitializeSystem inhomogeneous system
            V := [];
            M := List([1..size], x -> []);

            # get primes and field
            pi := pcgssys.weights[ i ][ 3 ];
            pk := pcgssys.weights[ k ][ 3 ];
            field := GF(pk);
            id := One( field );

            # add the power
            g := pcgssys.pcgs[ i ] ^ pi;
            v := ExponentsOfPcElement( pcgssys.pcgs, g, [start..next-1] );
            v := v * id;

            # set up matrix
            A := List( base, x -> ExponentsOfPcElement(
                       pcgssys.pcgs, x^pcgssys.pcgs[i], [start..next-1] ) );
            A := A * id;
            I := A ^ 0;
            B := I;
            for l  in [ 1..pi-1 ]  do
                B := B * A + I;
            od;
            B := (- 1) * B;

            # append to system
            for l  in [ 1..size ]  do
                Append( M[ l ], B[ l ] );
            od;
            Append( V, v );

            # add the commutators
            test := Filtered([i+1..start-1], x -> pcgssys.weights[x][3] <> pk);
            for j in test do
                g := Comm( pcgssys.pcgs[j], pcgssys.pcgs[i] );
                v := ExponentsOfPcElement( pcgssys.pcgs, g, [start..next-1] );
                v := v * id;

                # corresponding matrix
                aij := pcgssys.pcgs[j] ^ pcgssys.pcgs[i];
                A := List( base, x -> ExponentsOfPcElement(
                                 pcgssys.pcgs, x^aij, [start..next-1] ) );
                A := A * id;
                I := A ^ 0;
                I := (-1) * I;
                B := A + I;

                # append to system
                for l  in [ 1..size ]  do
                    Append( M[ l ], B[ l ] );
                od;
                Append( V, v );
            od;

            # solve system simultaneously
            solution := SolutionMat( M, V );

            # calculate new i-th base element
            new := ShallowCopy( pcgssys.pcgs!.pcSequence );
            subs := PcElementByExponentsNC(pcgssys.pcgs, base, solution);
            new[i] := new[i] * subs;
            pcgssys.pcgs := PcgsByPcSequenceNC( F, new );

            # change k
            k := LeastBadHallLayer( pcgssys, i );
        od;
    od;
    return pcgssys;
end );


#############################################################################
##
#F  LeastBadComplementLayer( <pcgssys>, <i> )
##
BindGlobal( "LeastBadComplementLayer", function( pcgssys, i )
    local m, p, bad, j, w, exponents, k;

    m := Length( pcgssys.pcgs );
    p := pcgssys.weights[i][3];
    bad := m + 1;

    # look through commutators
    for j in [ 1 .. m ] do
        if pcgssys.weights[j][1] >= pcgssys.weights[i][1] and
           pcgssys.weights[j][3] <> p then
            w := Comm( pcgssys.pcgs[j], pcgssys.pcgs[i] );
            if DepthOfPcElement( pcgssys.pcgs, w ) <= m then
                exponents := ExponentsOfPcElement( pcgssys.pcgs, w, [i+1..m] );
                k := 1;

                # run through exponent list until bad entry is found
                while k <= Length( exponents )  do
                    if exponents[k] <> 0 and
                       pcgssys.weights[i+k][1] = pcgssys.weights[j][1] + 1 and
                       pcgssys.weights[i+k][2] = 1  and
                       pcgssys.weights[i+k][3] = p  then
                        if i+k < bad  then
                            bad := i+k;
                        fi;
                        k := Length( exponents ) + 1;
                    else
                        k := k + 1;
                    fi;
                od;
            fi;
        fi;

        ## if bad is minimal return; otherwise go on
        if i = bad - 1  then
            return bad;
        fi;
    od;
    return bad;
end );


#############################################################################
##
#F  PcgsSystemWithComplementSystem( <pcgssys> )
##
BindGlobal( "PcgsSystemWithComplementSystem", function( pcgssys )
    local m, F, n, i, k,
          layer, start, next, size, base,
          V, M, l,
          pi, pk, field,
          nil, test, j, g, v, aij, A, B,
          solution, new, subs;

    m  := Length( pcgssys.pcgs );
    F  := FamilyObj( OneOfPcgs(pcgssys.pcgs) );

    # find starting index
    n := m;
    while 1 <= n and pcgssys.weights[n][1] = pcgssys.weights[m][1] do
         n := n - 1;
    od;
    if n = 1 and pcgssys.weights[n][1] = pcgssys.weights[m][1] then
        return pcgssys;
    fi;

    # run up the composition series
    for i in Reversed( [1..n] ) do
        Info(InfoSpecPcgs, 2, " start ",i,"th pcgs element");
        k := LeastBadComplementLayer( pcgssys, i );
        while k <= m do
            Info(InfoSpecPcgs, 2, "  bad index ",k);
            layer := pcgssys.layers[ k ];
            start := pcgssys.first[ layer ];
            next  := pcgssys.first[ layer+1 ];
            size  := next - start;
            base  := pcgssys.pcgs{[start..next-1]};

            # InitializeSystem inhomogeneous system
            V := [];
            M := List([1..size], x -> []);

            # get primes
            pi := pcgssys.weights[ i ][ 3 ];
            pk := pcgssys.weights[ k ][ 3 ];
            field := GF( pk );

            # pic the p'-generators in the head above
            nil  := pcgssys.weights[k][1]-1;
            test := Filtered( [1..m], x -> pcgssys.weights[x][3] <> pi
                                      and  pcgssys.weights[x][1] = nil );
            for j in test do
                g := Comm( pcgssys.pcgs[j], pcgssys.pcgs[i] );
                v := ExponentsOfPcElement( pcgssys.pcgs, g, [start..next-1] );
                v := v * One(field);

                # corresponding matrix
                aij := pcgssys.pcgs[j] ^ pcgssys.pcgs[i];
                A := List( base, x -> ExponentsOfPcElement(
                           pcgssys.pcgs, x^aij, [start..next-1] ) );
                A := A * One(field);
                B := A - A ^ 0;

                # append to system
                for l  in [ 1..size ]  do
                    Append( M[ l ], B[ l ] );
                od;
                Append( V, v );
            od;

            # solve system simultaneously
            solution := SolutionMat( M, V );

            # calculate new i-th base element
            new := ShallowCopy( pcgssys.pcgs!.pcSequence );
            subs:= PcElementByExponentsNC(pcgssys.pcgs, base, solution);
            new[i] := new[i] * subs;
            pcgssys.pcgs := PcgsByPcSequenceNC( F, new );

            # change k
            k := LeastBadComplementLayer( pcgssys, i );
        od;
    od;
    return pcgssys;
end );


#############################################################################
##
#M  SpecialPcgs( <pcgs> )
##
InstallMethod( SpecialPcgs, "method for special pcgs", true,
    [ IsSpecialPcgs ],
    # we need to rank this method higher -- otherwise the extra filters in
    # the following method give it the same rank...
    10,IdFunc);


InstallMethod( SpecialPcgs,
    "generic method for pcgs",
    true,
    [ IsPcgs and IsFiniteOrdersPcgs and IsPrimeOrdersPcgs ],
    0,

function( pcgs )
    local   newpcgs,  pcgssys,w;

    # catch the trivial case
    if Length( pcgs ) = 0 then
        newpcgs := pcgs;
        SetIsSpecialPcgs( pcgs, true );
        SetLGWeights( pcgs, [ ] );
        SetLGLayers( pcgs, [ ] );
        SetLGFirst( pcgs, [1] );

    else
        # compute Leedham-Green series
        Info(InfoSpecPcgs, 1, "compute LG series");
        pcgssys := PcgsSystemLGSeries( pcgs );

        # change to hall base
        Info(InfoSpecPcgs, 1, "exhibit hall system");
        pcgssys := PcgsSystemWithHallSystem( pcgssys );

        # change to complement base
        Info(InfoSpecPcgs, 1, "exhibit complement system");
        pcgssys := PcgsSystemWithComplementSystem( pcgssys );
        if IsBound(pcgssys.pcgs!.LGWeights) then
          # pcgs is reused -- force new one
          pcgssys.pcgs:=PcgsByPcSequence(FamilyObj(OneOfPcgs(pcgs)),
            pcgssys.pcgs!.pcSequence);
        fi;

        # create the special pcgs
        newpcgs := pcgssys.pcgs;
        SetIsSpecialPcgs( newpcgs, true );

        w:=pcgssys.weights;
        if Last(w)[1]=1 then
          SetIndicesCentralNormalSteps( newpcgs, pcgssys.first );
          if Length(Set(RelativeOrders(newpcgs)))=1 then
            SetIndicesPCentralNormalStepsPGroup( newpcgs, pcgssys.first );
          fi;
        fi;

        SetLGWeights( newpcgs, pcgssys.weights );
        SetLGLayers( newpcgs, pcgssys.layers );
        SetLGFirst( newpcgs, pcgssys.first );
        SetIndicesEANormalSteps( newpcgs, pcgssys.first );
        SetIndicesChiefNormalSteps( newpcgs, pcgssys.first );
        SetIsFiniteOrdersPcgs( newpcgs, true );
        SetIsPrimeOrdersPcgs( newpcgs, true );
    fi;
    if HasGroupOfPcgs (pcgs) then
        SetGroupOfPcgs (newpcgs, GroupOfPcgs (pcgs));
    fi;
    return newpcgs;
end );

#############################################################################
##
#M  LGHeads( <pcgs> )
##
InstallMethod( LGHeads, "for special pcgs", true,
               [ IsSpecialPcgs ], 0,
function( pcgs )
    local h, i, w, j;
    h := [];
    i := 1;
    w := LGWeights( pcgs );
    for j in [1..Length(w)] do
        if w[j][1] = i then
            Add( h, j );
            i := i + 1;
        fi;
    od;
    Add( h, Length( w ) + 1 );
    return h;
end);

#############################################################################
##
#M  LGTails( <pcgs> )
##
InstallMethod( LGTails, "for special pcgs", true,
               [ IsSpecialPcgs ], 0,
function( pcgs )
    local h, w, i, j, t;
    h := LGHeads( pcgs );
    w := LGWeights( pcgs );
    t := [];
    for i in [1..Length(h)-1] do
        j := h[i];
        while j <= Length( w ) and w[h[i]][1] = w[j][1] and w[j][2] = 1 do
            j := j + 1;
        od;
        Add( t, j );
    od;
    return t;
end);

#############################################################################
##
#M  SpecialPcgs( <group> )
##
InstallOtherMethod( SpecialPcgs,
    "generic method for groups",
    true,
    [ IsGroup ],
    0,

function( group )
    local   spec;

    spec := SpecialPcgs( Pcgs( group ) );
    SetGroupOfPcgs (spec, group);
    return spec;
end );

InstallOtherMethod( SpecialPcgs,"last resort method which tests solvability",
    true,[IsGroup],0,
function(G)
  # this test should always fail (because otherwise the other method
  # that uses 'CanEasilyComputePcgs' will have been called). It is there
  # just to avoid infinite recursion if methods get sorted in a strange way.
  if HasIsSolvableGroup(G) then
    TryNextMethod();
  fi;
  if not IsSolvableGroup(G) then
    Error("<G> must be solvable to permit computation of a special pcgs");
  else
    return SpecialPcgs(G);
  fi;
end);

#############################################################################
##
#M  IsomorphismSpecialPcGroup( <group> )
##
InstallMethod( IsomorphismSpecialPcGroup, "method for pc groups",
    true, [ IsPcGroup ], 0,
function(G)
local s,H,iso,pc,w;
  s:=SpecialPcgs(G);
  H:=PcGroupWithPcgs(s);
  pc:=FamilyPcgs(H);
  SetLGWeights(pc,LGWeights(s));
  SetLGLayers(pc,LGLayers(s));
  SetLGFirst(pc,LGFirst(s));
  SetIsSpecialPcgs(pc,true);
  if Length(LGWeights(pc)) = 0 or Last(LGWeights(pc))[1]=1 then
        SetIsPcgsCentralSeries(pc,true);
  fi;
  SetIndicesEANormalSteps( pc, LGFirst(pc) );
  SetIndicesChiefNormalSteps( pc, LGFirst(pc) );
  w:=LGWeights(pc);
  if Length(w) > 0 and Last(w)[1]=1 then
    SetIndicesCentralNormalSteps( pc, LGFirst(pc));
    if Length(Set(RelativeOrders(pc)))=1 then
      SetIndicesPCentralNormalStepsPGroup( pc, LGFirst(pc) );
    fi;
  fi;


  iso:=GroupHomomorphismByImagesNC(G,H,s,pc);
  SetIsBijective( iso, true );
  SetSpecialPcgs(H,pc);
  SetPcgs(H,pc);
  # note: `ImagesSource' might be
  # physically a different group than the `Range' H.
  SetSpecialPcgs(ImagesSource(iso),pc);
  SetPcgs(ImagesSource(iso),pc);
  return iso;
end);

InstallMethod( IsomorphismSpecialPcGroup, "generic method for groups",
    true, [ IsGroup ], 0,
function(G)
local iso;
  iso:=IsomorphismPcGroup(G);
  return iso*IsomorphismSpecialPcGroup(Range(iso));
end);

#############################################################################
##
#M  InducedPcgsWrtSpecialPcgs( <group> )
##
InstallOtherMethod( InducedPcgsWrtSpecialPcgs, "method for pc groups",
    true, [ IsPcGroup ], 0,
function( U )
local spec, ind;
    spec := SpecialPcgs( FamilyPcgs( U ) );
    if HasPcgs(U) and spec=HomePcgs(U) then
      return InducedPcgsWrtHomePcgs(U);
    fi;
    ind := InducedPcgsByGeneratorsNC( spec, GeneratorsOfGroup(U) );
    SetGroupOfPcgs (ind, U);
    return ind;
end );

InstallOtherMethod( InducedPcgsWrtSpecialPcgs, "generic method for groups",
    true, [ IsGroup ], 0,
function( U )
local spec, ind;
  spec := SpecialPcgs( Parent( U ) );
  ind := InducedPcgsByGeneratorsNC( spec, GeneratorsOfGroup(U) );
  SetGroupOfPcgs (ind, U);
  return ind;
end );

BindGlobal( "IndPcgsWrtSpecFromFamOrHome", function( U )
local spec, ind;
  spec := SpecialPcgs( FamilyPcgs( U ) );
  if spec=HomePcgs(U) then
    return InducedPcgsWrtHomePcgs(U);
  elif IsSortedPcgsRep(spec) and spec!.sortingPcgs=HomePcgs(U) then
    ind := InducedPcgsByPcSequenceNC(spec,AsList(InducedPcgsWrtHomePcgs(U)));
  else
     ind := InducedPcgsByGeneratorsNC( spec, InducedPcgsWrtHomePcgs(U) );
  fi;
  SetGroupOfPcgs (ind, U);
  return ind;
end );

InstallOtherMethod( InducedPcgsWrtSpecialPcgs,
  "for groups that have already an induced pcgs wrt home pcgs", true,
  [ IsGroup and HasInducedPcgsWrtHomePcgs], 0,
IndPcgsWrtSpecFromFamOrHome);

InstallOtherMethod( InducedPcgsWrtSpecialPcgs,
  "for groups that have already an induced pcgs wrt family pcgs", true,
  [ IsGroup and HasInducedPcgsWrtFamilyPcgs], 0,
IndPcgsWrtSpecFromFamOrHome);

#############################################################################
##
#M LGWeights( pcgs )
##
InstallMethod( LGWeights,
               "for induced wrt special",
               true,
               [IsInducedPcgsWrtSpecialPcgs],
               0,
function( pcgs )
    local spec, sweights, weights, i, g, d;

    # catch special pcgs
    spec := ParentPcgs( pcgs );
    sweights := LGWeights( spec );

    # rewrite weights
    weights := List( pcgs, x -> true );
    for i in [1..Length(pcgs)] do
        g := pcgs[i];
        d := DepthOfPcElement( spec, g );
        weights[i] := sweights[d];
    od;
    return weights;
end );

#############################################################################
##
#M LGLayers( pcgs )
##
InstallMethod( LGLayers,
               "for induced wrt special",
               true,
               [IsInducedPcgsWrtSpecialPcgs],
               0,
function( pcgs )
    local weights, layers, layer, o, i, w;

    weights := LGWeights( pcgs );
    layers  := List( pcgs, x -> true );
    layer   := 1;
    o       := weights[1];
    for i in [1..Length( pcgs )] do
        w := weights[i];
        if w <> o then
            o := w;
            layer := layer + 1;
        fi;
        layers[i] := layer;
    od;
    return layers;
end );

#############################################################################
##
#M LGFirst( pcgs )
##
InstallMethod( LGFirst,
               "for induced wrt special",
               true,
               [IsInducedPcgsWrtSpecialPcgs],
               0,
function( pcgs )
    local weights, first, o, i, w;

    weights := LGWeights( pcgs );
    first   := [1];
    o       := weights[1];
    for i in [1..Length( pcgs )] do
        w := weights[i];
        if w <> o then
            o := w;
            Add( first, i );
        fi;
    od;
    Add( first, Length(pcgs) + 1 );
    return first;
end );

#############################################################################
##
#M LGLength( G )
##
InstallMethod( LGLength,
               "for groups",
               true,
               [ IsGroup ],
               0,
function( G )

    if not IsSolvableGroup( G ) then
        return fail;
    fi;
    return Length( Set( LGWeights( SpecialPcgs( G ) ) ) );
end );

#############################################################################
##
#M  PClassPGroup( <G> )   . . . . . . . . . .  . . . . . . <p>-central series
##
InstallMethod( PClassPGroup,
    "for groups with special pcgs",
    true, [ IsPGroup and HasSpecialPcgs ], 1,
    function( G )

    return LGLength( G );
    end );

#############################################################################
##
#M  RankPGroup( <G> ) . . . . . . . . . . . .  . . . . . . <p>-central series
##
InstallMethod( RankPGroup,
    "for groups with special pcgs",
    true, [ IsPGroup and HasSpecialPcgs ], 1,
    function( G )

    return LGFirst( SpecialPcgs( G ) )[ 2 ] - 1;
    end );

#############################################################################
##
#F SpecialPcgsSubgroup( G, i )
##
BindGlobal( "SpecialPcgsSubgroup", function( G, i )
    local spec, firs, sub;
    spec := SpecialPcgs( G );
    firs := LGFirst( spec );
    sub  := InducedPcgsByPcSequenceNC( spec, spec{[firs[i]..Length(spec)]} );
    return SubgroupByPcgs( G, sub );
end );

#############################################################################
##
#F SpecialPcgsFactor( G, i )
##
BindGlobal( "SpecialPcgsFactor", function( G, i )
    return G / SpecialPcgsSubgroup( G, i );
end );

#############################################################################
##
#M  IndicesEANormalSteps( <pcgs> )
##
InstallMethod( IndicesEANormalSteps, "special pcgs: LGFirst", true,
        [ IsSpecialPcgs ], 0, LGFirst );

BindGlobal( "DoCentralSeriesPcgsIfNilpot", function(G)
local w;
  w:=LGWeights(SpecialPcgs(G));
  if Last(w)[1]<>1 then
    Error("The group is not nilpotent");
  fi;
  return SpecialPcgs(G);
end );

InstallOtherMethod( PcgsCentralSeries, "if special pcgs is known",
  true,[HasSpecialPcgs],0,DoCentralSeriesPcgsIfNilpot);

InstallOtherMethod( PcgsCentralSeries, "for pc groups use SpecialPcgs",
  true,[IsPcGroup],0,DoCentralSeriesPcgsIfNilpot);

InstallOtherMethod( PcgsPCentralSeriesPGroup, "for pc groups use SpecialPcgs",
  true,[IsPcGroup],0,DoCentralSeriesPcgsIfNilpot);

InstallOtherMethod( PcgsCentralSeries, "for pcgs computable use SpecialPcgs",
  true,[CanEasilyComputePcgs],0,DoCentralSeriesPcgsIfNilpot);

InstallOtherMethod( PcgsPCentralSeriesPGroup,
  "for pcgs computable use SpecialPcgs",
  true,[CanEasilyComputePcgs],0,DoCentralSeriesPcgsIfNilpot);

BindGlobal( "PcgsElAbSerFromSpecPcgs", function(G)
local s;
  if HasHomePcgs(G)
     and IsPcgsElementaryAbelianSeries(InducedPcgsWrtHomePcgs(G)) then
    return InducedPcgsWrtHomePcgs(G);
    # prefer the `HomePcgs' because wrt. it we store inducedness and for pc
    # groups its the family pcgs wrt. calculations are quicker
  fi;
  s:=SpecialPcgs(G);
  return s;
end );

InstallOtherMethod(PcgsElementaryAbelianSeries, "if special pcgs is known",
  true,[HasSpecialPcgs],0,PcgsElAbSerFromSpecPcgs);

InstallMethod(PcgsElementaryAbelianSeries,"for PCgroups via SpecialPcgs",
  true,[IsPcGroup],0,PcgsElAbSerFromSpecPcgs);

[ 0.41Quellennavigators  Projekt   ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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