Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/wpe/gap/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 21.9.2024 mit Größe 29 kB image not shown  

Quelle  WreathProductElements.gi   Sprache: unbekannt

 
#############################################################################
##  WreathProductElements.gi
#############################################################################
##
##  This file is part of the WPE package.
##
##  This file's authors include Friedrich Rober.
##
##  Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
#############################################################################


#############################################################################
# Membership test for elements
#############################################################################


BindGlobal( "WPE_IN",
function(g, G)
    local l, grps, K, H;
    l := ListWreathProductElement(G, g);
    if l = fail then
        return false;
    fi;
    grps := ComponentsOfWreathProduct(G);
    K := grps[1];
    H := grps[2];
    return ForAll([1 .. Length(l) - 1], i -> l[i] in K) and l[Length(l)] in H;
end);

# InstallMethod( \in, "perm, and perm wreath product", true,[IsObject, IsPermGroup and HasWreathProductInfo], OVERRIDENICE + 42, WPE_IN);
# InstallMethod( \in, "matrix, and matrix wreath product", true, [IsMatrix, IsMatrixGroup and HasWreathProductInfo], OVERRIDENICE + 42, WPE_IN);


#############################################################################
# Isomorphism to generic wreath product
#############################################################################


# Dirty Hack
BindGlobal( "WPE_GenericWreathProduct_GAP", ApplicableMethod(WreathProduct,
    [DihedralGroup(8), SymmetricGroup(3), IdentityMapping(SymmetricGroup(3))]
));

BindGlobal( "WPE_GenericWreathProduct",
function(args...)
    local K, H, phi;
    if Length(args) < 2 or Length(args) > 3 then
        ErrorNoReturn("Unknown number of arguments");
    fi;
    K := args[1];
    H := args[2];
    if Length(args) = 3 then
        phi := args[3];
    else
        phi := IdentityMapping(H);
    fi;
    return WPE_GenericWreathProduct_GAP(K, H, phi);
end);


InstallMethod( IsomorphismWreathProduct, "wreath products", true, [HasWreathProductInfo], 1,
function(G)
    local grps, W, typ, iso;
    grps := ComponentsOfWreathProduct(G);
    if not IsPermGroup(grps[2]) then
        ErrorNoReturn("Top group of <G> must be a permutation group");
    fi;
    W := WPE_GenericWreathProduct(grps[1], grps[2]);
    iso := GroupHomomorphismByFunction(G, W,
           g-> WreathProductElementList(W, ListWreathProductElement(G, g)),
           x -> WreathProductElementList(G, ListWreathProductElement(W, x)));
    return iso;
end);


#############################################################################
# Printing of elements
#############################################################################


# Default options, immutable entries
BindGlobal( "WPE_DisplayOptionsDefault", Immutable(rec(
    horizontal := true,
    labels := true,
    labelStyle := "none",
    labelColor := "default",
)));

# Current options, mutable entries
BindGlobal( "WPE_DisplayOptions", ShallowCopy(WPE_DisplayOptionsDefault));

InstallGlobalFunction( DisplayOptionsForWreathProductElements,
function()
    Display(WPE_DisplayOptions);
end);

BindGlobal( "WPE_SetDisplayOptions",
function(optionsBase, optionsUpdate)
    local r;
    for r in RecNames(optionsUpdate) do
        if not IsBound(optionsBase.(r)) then
            ErrorNoReturn("Invalid option to Display: ", r);
        fi;
        if r = "labelStyle" and not optionsUpdate.(r) in ["none", "bold", "faint"] then
            ErrorNoReturn("Invalid value to labelStyle: ", optionsUpdate.(r));
        fi;
        if r = "labelColor" and not optionsUpdate.(r) in ["default", "red", "blue"] then
            ErrorNoReturn("Invalid value to labelStyle: ", optionsUpdate.(r));
        fi;
        optionsBase.(r) := optionsUpdate.(r);
    od;
end);

BindGlobal("WPE_SetLabelFont",
function(options)
    # Intensity
    if options.labelStyle = "bold" then
        WriteAll(STDOut, "\033[1m");
    elif options.labelStyle = "faint" then
        WriteAll(STDOut, "\033[2m");
    fi;
    # Color
    if options.labelColor = "red" then
        WriteAll(STDOut, "\033[31m");
    elif options.labelColor = "blue" then
        WriteAll(STDOut, "\033[34m");
    fi;
end);

BindGlobal("WPE_IsLabelFontDefault",
function(options)
    return options.labelStyle = "none" and options.labelColor = "default";
end);

InstallGlobalFunction( SetDisplayOptionsForWreathProductElements,
function(options)
    WPE_SetDisplayOptions(WPE_DisplayOptions, options);
end);

InstallGlobalFunction( ResetDisplayOptionsForWreathProductElements,
function()
    SetDisplayOptionsForWreathProductElements(WPE_DisplayOptionsDefault);
end);

InstallMethod( ViewObj, "wreath elements", true, [IsWreathProductElement], 1,
function(x)
    local degI;
    degI := WPE_TopDegree(x);
    Print("< wreath product element with ", degI, " base components >");
end);

InstallMethod( PrintObj, "wreath elements", true, [IsWreathProductElement], 1,
function(x)
    local i,L,tenToL,degI;
    degI := WPE_TopDegree(x);
    Print("[ ");
    for i in [1..degI] do
        Print(String(WPE_BaseComponent(x, i)));
        if i < degI then
            Print(", ");
        fi;
    od;
    Print(", ",String(WPE_TopComponent(x))," ]");
end);

InstallMethod( Display, "wreath elements", true, [IsWreathProductElement], 1,
function(x)
    Display(x, rec());
end);

InstallOtherMethod( Display, "wreath elements, and a record", [IsWreathProductElement, IsRecord],
function(x, options)
    local displayOptions, r, degI, widthScreen, strElms, bufferLabels, bufferLines, widthLines,
          bufferElm, blanks, prefix, suffix, i, j, k, d, L, tenToL, line, label;

    # setting display options
    displayOptions := ShallowCopy(WPE_DisplayOptions);
    WPE_SetDisplayOptions(displayOptions, options);

    degI := WPE_TopDegree(x);
    widthScreen := SizeScreen()[1] - 2;

    # string representations of each component
    strElms := EmptyPlist(degI + 1);
    for i in [1..degI] do
        strElms[i] := String(WPE_BaseComponent(x, i));
    od;
    strElms[degI + 1] := String(WPE_TopComponent(x));

    # Print horizontally
    if displayOptions.horizontal then
        bufferLines := ["( "];
        widthLines := 2;
        blanks := Concatenation(List([1..widthLines], k -> " "));
        if displayOptions.labels then
            bufferLabels := blanks;
        fi;
        # Print Components
        for i in [1..degI + 1] do
            # Add prefix
            if widthLines = Length(blanks) then
                prefix := "";
            else
                prefix := " ";
            fi;
            # Add element to buffer
            bufferElm := strElms[i];
            # Add suffix
            suffix := "";
            if i < degI then
                suffix := ",";
            elif i = degI then
                suffix := ";";
            fi;
            # Element does not fit into the line, hence print and clear buffer
            if Length(prefix) + Length(bufferElm) + Length(suffix) + widthLines > widthScreen then
                WPE_SetLabelFont(displayOptions);
                if displayOptions.labels then
                    if Length(bufferLabels) > Length(blanks) then
                        Print(bufferLabels, "\n");
                    fi;
                fi;
                WriteAll(STDOut, "\033[0m");
                if widthLines > Length(blanks) then
                    for line in bufferLines do
                        Print(line, "\n");
                    od;
                fi;
                if displayOptions.labels then
                    if Length(bufferLabels) > Length(blanks) then
                        Print("\n");
                    fi;
                fi;
                # The element is long, thus we need inline breaks.
                # Print element directly and start clean buffer for next element.
                if Length(bufferElm) + Length(suffix) > widthScreen then
                    if displayOptions.labels then
                        if i <= degI then
                            label := String(i);
                        else
                            label := "top";
                        fi;
                        Print(Concatenation(List([1 .. Int((widthScreen - Length(label) - Length(blanks)) / 2) + Length(blanks)], k -> " ")), label, "\n");
                    fi;
                    j := 1;
                    d := widthScreen - Length(blanks) - 3;
                    bufferElm := Concatenation(bufferElm, suffix);
                    while j <= Length(bufferElm) do
                        k := Minimum(Length(bufferElm), j + d);
                        if j > 1 then
                            Print("\\\n");
                        fi;
                        # special case, if element does not fit into first line
                        if j = 1 and bufferLines[1] = "( " then
                            Print("( ", bufferElm{[j..k]});
                        else
                            Print(blanks, bufferElm{[j..k]});
                        fi;
                        j := k + 1;
                    od;

                    # extra space between labels and element
                    if displayOptions.labels and i <= degI then
                        Print("\n");
                    fi;

                    Print("\n");
                    bufferLines := [blanks];
                    widthLines := Length(blanks);
                    bufferLabels := blanks;
                # The element is short, hence add it to the clean buffer
                else
                    bufferLines := [Concatenation(blanks, bufferElm, suffix)];
                    widthLines := Length(blanks) + Length(bufferElm) + Length(suffix);
                    if displayOptions.labels then
                        if i <= degI then
                            label := String(i);
                        else
                            label := "top";
                        fi;
                        d := Int((Length(bufferElm) - Length(label)) / 2);
                        bufferLabels := Concatenation(
                            blanks,
                            Concatenation(List([1 .. d], k -> " ")),
                            label,
                            Concatenation(List([1 .. Length(bufferElm) + Length(suffix) - Length(label) - d], k -> " "))
                        );
                    fi;
                fi;
            # The element fits into the line, thus we add it to buffer
            else
                bufferLines[1] := Concatenation(bufferLines[1], prefix, bufferElm, suffix);
                widthLines := widthLines + Length(prefix) + Length(bufferElm) + Length(suffix);
                if displayOptions.labels then
                    if i <= degI then
                        label := String(i);
                    else
                        label := "top";
                    fi;
                    d := Int((Length(bufferElm) - Length(label)) / 2);
                    bufferLabels := Concatenation(
                        bufferLabels,
                        prefix,
                        Concatenation(List([1 .. d], k -> " ")),
                        label,
                        Concatenation(List([1 .. Length(bufferElm) + Length(suffix) - Length(label) - d], k -> " "))
                    );
                fi;
            fi;
        od;
        # Print suffix
        bufferElm := " )";
        if Length(bufferElm) + widthLines < widthScreen then
            bufferLines[1] := Concatenation(bufferLines[1], bufferElm);
        else
            Append(bufferLines, bufferElm);
        fi;
        WPE_SetLabelFont(displayOptions);
        if displayOptions.labels then
            Print(bufferLabels, "\n");
        fi;
        WriteAll(STDOut, "\033[0m");
        for line in bufferLines do
            Print(line, "\n");
        od;
    # Print vertically
    else
        # Length of Largest Number
        L := 1;
        tenToL := 10;
        while tenToL <= degI do
            L := L + 1;
            tenToL := tenToL * 10;
        od;
        L := Maximum(3, L);
        if displayOptions.labels then
            blanks := Concatenation(List([1 .. L + 2], k -> " "));
        else
            blanks := Concatenation(List([1 .. 2], k -> " "));
        fi;
        # Print Components
        for i in [1..degI + 1] do
            WPE_SetLabelFont(displayOptions);
            if displayOptions.labels then
                if i <= degI then
                    label := i;
                else
                    label := "top";
                fi;
                # Hack for test suite
                if WPE_IsLabelFontDefault(displayOptions) then
                    Print(String(label, L) , ": ");
                else
                    WriteAll(STDOut, String(label, L));
                    WriteAll(STDOut, ": ");
                fi;
            fi;
            WriteAll(STDOut, "\033[0m");
            # The element might be too long, thus we need inline breaks.
            bufferElm := strElms[i];
            j := 1;
            d := widthScreen - Length(blanks) - 3;
            while j <= Length(bufferElm) do
                k := Minimum(Length(bufferElm), j + d);
                if j = 1 then
                    Print(bufferElm{[j..k]});
                else
                    Print("\\\n", blanks, bufferElm{[j..k]});
                fi;
                j := k + 1;
            od;
            Print("\n");
        od;
    fi;
end);


#############################################################################
# (Sparse) Wreath Cycles
#############################################################################


InstallTrueMethod( IsWreathCycle, IsSparseWreathCycle );
InstallTrueMethod( IsWreathProductElement, IsWreathCycle );

BindGlobal( "WPE_IsWreathCycle",
function(x)
    local degI, suppTop;

    degI := WPE_TopDegree(x);

    # wreath cycle of base type
    if IsOne(WPE_TopComponent(x)) then
        if Number([1 .. degI], i -> not IsOne(WPE_BaseComponent(x, i))) = 1 then
            SetIsSparseWreathCycle(x, true);
            return true;
        else
            return false;
        fi;
    fi;

    # wreath cycle of top type
    suppTop := MovedPoints(WPE_TopComponent(x));
    if Length(CycleStructurePerm(WPE_TopComponent(x))) + 1 <> Length(suppTop) then
        return false;
    fi;

    return ForAll([1 .. degI], i -> i in suppTop or IsOne(WPE_BaseComponent(x, i)));
end);

InstallMethod( IsWreathCycle, "generic wreath elements", true, [IsWreathProductElement], 0,
function(x)
    return WPE_IsWreathCycle(x);
end);

InstallOtherMethod( IsWreathCycle, "list rep of wreath elements", true, [IsList], 0,
function(x)
    return WPE_IsWreathCycle(x);
end);

BindGlobal( "WPE_IsSparseWreathCycle",
function(x)
    local info, terr, min;
    if IsWreathCycle(x) then
        info := FamilyObj(x)!.info;
        terr := Territory(x);
        return Number(terr, i -> not IsOne(WPE_BaseComponent(x, i))) <= 1;
    else
        return false;
    fi;
end);

InstallMethod( IsSparseWreathCycle, "generic wreath elements", true, [IsWreathProductElement], 0,
function(x)
    return WPE_IsSparseWreathCycle(x);
end);

InstallOtherMethod( IsSparseWreathCycle, "list rep of wreath elements", true, [IsList], 0,
function(x)
    return WPE_IsSparseWreathCycle(x);
end);


#############################################################################
# Wreath Product Element Attributes
#############################################################################


BindGlobal( "WPE_Territory",
function(x)
    local degI, suppTop, suppBase;

    degI := WPE_TopDegree(x);
    suppTop := MovedPoints(WPE_TopComponent(x));
    suppBase := Filtered([1..degI], i -> not IsOne(WPE_BaseComponent(x, i)));
    return Set(Concatenation(suppTop, suppBase));
end);

InstallMethod( Territory, "generic wreath elements", true, [IsWreathProductElement], 0,
function(x)
    return WPE_Territory(x);
end);

InstallOtherMethod( Territory, "list rep of wreath elements", true, [IsList], 0,
function(x)
    return WPE_Territory(x);
end);

BindGlobal( "WPE_ChooseYadePoint",
function(x)
    return Minimum(Territory(x));
end);

BindGlobal( "WPE_Yade",
function(x, i)
    local ord;

    if not i in Territory(x) then
        Error("i not in territory of x");
    fi;

    ord := Order(WPE_TopComponent(x));

    return Product([0 .. ord-1], k -> WPE_BaseComponent(x, i ^ (WPE_TopComponent(x) ^ k)));
end);

InstallMethod( Yade, "wreath cycle wreath elements", true, [IsWreathCycle], 1,
function(x)
    return WPE_Yade(x, WPE_ChooseYadePoint(x));
end);

InstallOtherMethod( Yade, "list rep of wreath cycle", true, [IsList], 1,
function(x)
    return WPE_Yade(x, WPE_ChooseYadePoint(x));
end);

InstallOtherMethod( Yade, "wreath cycle wreath elements", true, [IsWreathCycle, IsInt], 1,
function(x, i)
    return WPE_Yade(x, i);
end);

InstallOtherMethod( Yade, "list rep of wreath cycle wreath elements", true, [IsList, IsInt], 1,
function(x, i)
    return WPE_Yade(x, i);
end);

#############################################################################
# Wreath Cycle Decomposition
#############################################################################

InstallMethod( WreathCycleDecomposition, "generic wreath elements", true, [IsWreathCycle], 1, function(x) return [x]; end);

InstallMethod( WreathCycleDecomposition, "generic wreath elements", true, [IsWreathProductElement], 0,
function(x)
    local
      info,             # wreath product info
      degI,             # degree of top group
      decomposition,    # wreath cycle decomposition of x
      suppTop,          # support of top component, list
      suppBase,         # non-trivial base component indices, list
      id,               # identity vector
      i,                # index point, loop var
      wreathCycle,      # wreath cycle, loop var
      topCycleList,     # cycle decomposition of top component, list
      topCycle;         # cycle of top component, loop var

    # initialization
    info := FamilyObj(x)!.info;
    degI := WPE_TopDegree(x);
    suppTop := MovedPoints(WPE_TopComponent(x));
    suppBase := Filtered([1 .. degI], i -> not IsOne(WPE_BaseComponent(x, i)));
    id := ListWithIdenticalEntries(degI, One(WPE_BaseComponent(x, 1)));
    Add(id, One(WPE_TopComponent(x)));
    decomposition := [];

    # wreath cycles that are of base type
    for i in Filtered(suppBase, x -> not x in suppTop) do
        wreathCycle := ShallowCopy(id);
        wreathCycle[i] := WPE_BaseComponent(x, i);
        wreathCycle := Objectify(info.family!.defaultType,wreathCycle);

        SetIsSparseWreathCycle(wreathCycle,true);
        Add(decomposition, wreathCycle);
    od;

    # wreath cycles that are of top type
    if IsEmpty(suppTop) then
        return decomposition;
    fi;
    topCycleList := Cycles(WPE_TopComponent(x), suppTop);
    for topCycle in topCycleList do
        wreathCycle := ShallowCopy(id);
        wreathCycle[degI + 1] := CycleFromList(topCycle);
        for i in topCycle do
            wreathCycle[i] := WPE_BaseComponent(x, i);
        od;
        wreathCycle := Objectify(info.family!.defaultType,wreathCycle);

        SetIsWreathCycle(wreathCycle,true);
        Add(decomposition, wreathCycle);
    od;

    return decomposition;
end);

InstallOtherMethod( WreathCycleDecomposition, "list rep of wreath elements", true, [IsList], 0,
function(x)
    local
      degI,             # degree of top group
      decomposition,    # wreath cycle decomposition of x
      suppTop,          # support of top component, list
      suppBase,         # non-trivial base component indices, list
      id,               # identity vector
      i,                # index point, loop var
      wreathCycle,      # wreath cycle, loop var
      topCycleList,     # cycle decomposition of top component, list
      topCycle;         # cycle of top component, loop var

    # initialization
    degI := Length(x) - 1;
    suppTop := MovedPoints(WPE_TopComponent(x));
    suppBase := Filtered([1 .. degI], i -> not IsOne(WPE_BaseComponent(x, i)));
    id := ListWithIdenticalEntries(degI, One(WPE_BaseComponent(x, 1)));
    Add(id, One(WPE_BaseComponent(x, degI + 1)));
    decomposition := [];

    # wreath cycles that are of base type
    for i in Filtered(suppBase, x -> not x in suppTop) do
        wreathCycle := ShallowCopy(id);
        wreathCycle[i] := WPE_BaseComponent(x, i);

        Add(decomposition, wreathCycle);
    od;

    # wreath cycles that are of top type
    if IsEmpty(suppTop) then
        return decomposition;
    fi;
    topCycleList := Cycles(WPE_TopComponent(x), suppTop);
    for topCycle in topCycleList do
        wreathCycle := ShallowCopy(id);
        wreathCycle[degI + 1] := CycleFromList(topCycle);
        for i in topCycle do
            wreathCycle[i] := WPE_BaseComponent(x, i);
        od;

        Add(decomposition, wreathCycle);
    od;

    return decomposition;
end);

#############################################################################
# Sparse Wreath Cycle Decomposition
#############################################################################

InstallMethod( SparseWreathCycleConjugate, "sparse wreath cycle wreath elements", true, [IsSparseWreathCycle], 2, function(x) return [x]; end);

InstallMethod( SparseWreathCycleConjugate, "wreath cycle wreath elements", true, [IsWreathCycle], 1,
function(x)
    local info, degI, yade, i, sparseWreathCycle;

    info := FamilyObj(x)!.info;
    degI := WPE_TopDegree(x);
    yade := Yade(x);
    i := Minimum(Territory(x));
    sparseWreathCycle := ListWithIdenticalEntries(degI, One(WPE_BaseComponent(x, 1)));
    Add(sparseWreathCycle, WPE_TopComponent(x));
    sparseWreathCycle[i] := yade;

    SetIsSparseWreathCycle(sparseWreathCycle, true);

    return [Objectify(info.family!.defaultType,sparseWreathCycle)];
end);

InstallMethod( SparseWreathCycleConjugate, "generic wreath elements", true, [IsWreathProductElement], 0,
function(x)
    local decomposition;

    decomposition := WreathCycleDecomposition(x);
    return Concatenation(List(decomposition, SparseWreathCycleConjugate));
end);

InstallOtherMethod( SparseWreathCycleConjugate, "list rep of wreath elements", true, [IsList], 1,
function(w)
    local decomposition, sparseDecomposition, degI, yade, i, l, sparseWreathCycle, x;

    decomposition := WreathCycleDecomposition(w);
    sparseDecomposition := EmptyPlist(Length(decomposition));

    for l in [1 .. Length(decomposition)] do
        x := decomposition[l];
        degI := WPE_TopDegree(x);
        yade := Yade(x);
        i := Minimum(Territory(x));
        sparseWreathCycle := ListWithIdenticalEntries(degI, One(WPE_BaseComponent(x, 1)));
        Add(sparseWreathCycle, WPE_TopComponent(x));
        sparseWreathCycle[i] := yade;

        sparseDecomposition[l] := sparseWreathCycle;
    od;

    return sparseDecomposition;
end);

InstallMethod( ConjugatorWreathCycleToSparse, "sparse wreath cycle wreath elements", true, [IsSparseWreathCycle], 2, function(x) return [One(x)]; end);

InstallMethod( ConjugatorWreathCycleToSparse, "wreath cycle wreath elements", true, [IsWreathCycle], 1,
function(x)
    local info, degI, i, j, min, yade, ord, k, y, conj;

    info := FamilyObj(x)!.info;
    degI := WPE_TopDegree(x);
    ord := Order(WPE_TopComponent(x));
    i := WPE_ChooseYadePoint(x);
    min := Minimum(Territory(x));
    yade := Yade(x);
    conj := ListWithIdenticalEntries(degI, One(WPE_BaseComponent(x, 1)));
    Add(conj, One(WPE_TopComponent(x)));
    y := One(WPE_BaseComponent(x, 1));
    j := i;
    for k in [1..ord] do
        y := WPE_BaseComponent(x, j) ^ -1 * y;
        if j = min then
            y := y * yade;
        fi;
        j := i^(WPE_TopComponent(x) ^ k);
        conj[j] := y;
    od;

    return [Objectify(info.family!.defaultType,conj)];
end);

InstallMethod( ConjugatorWreathCycleToSparse, "generic wreath elements", true, [IsWreathProductElement], 0,
function(x)
    local decomposition;

    decomposition := WreathCycleDecomposition(x);
    return Concatenation(List(decomposition, ConjugatorWreathCycleToSparse));
end);

InstallOtherMethod( ConjugatorWreathCycleToSparse, "list rep of wreath elements", true, [IsList], 1,
function(w)
    local decomposition, conjDecomposition, degI, i, j, l, min, yade, ord, k, y, conj, x;

    decomposition := WreathCycleDecomposition(w);
    conjDecomposition := EmptyPlist(Length(decomposition));

    for l in [1 .. Length(decomposition)] do
        x := decomposition[l];
        degI := WPE_TopDegree(x);
        ord := Order(WPE_TopComponent(x));
        i := WPE_ChooseYadePoint(x);
        min := Minimum(Territory(x));
        yade := Yade(x);
        conj := ListWithIdenticalEntries(degI, One(WPE_BaseComponent(x, 1)));
        Add(conj, One(WPE_TopComponent(x)));
        y := One(WPE_BaseComponent(x, 1));
        j := i;
        for k in [1..ord] do
            y := WPE_BaseComponent(x, j) ^ -1 * y;
            if j = min then
                y := y * yade;
            fi;
            j := i^(WPE_TopComponent(x) ^ k);
            conj[j] := y;
        od;
        conjDecomposition[l] := conj;
    od;
    return conjDecomposition;
end);

#############################################################################
# Components
#############################################################################

InstallGlobalFunction( ComponentsOfWreathProduct,
function(W)
    if not HasWreathProductInfo(W) then
        return Error("W is not a wreath product");
    fi;
    return Immutable(WreathProductInfo(W).groups);
end);

InstallGlobalFunction( TopComponentOfWreathProductElement,
function(x)
    if not IsWreathProductElement(x) then
        return Error("x is not a wreath product element");
    fi;
    return WPE_TopComponent(x);
end);

BindGlobal( "WPE_TopComponent_Elm",
function(x)
    return x![WPE_TopDegree(x) + 1];
end);

InstallMethod( WPE_TopComponent, "generic wreath elements", true, [IsWreathProductElement], 0,
function(x)
    return WPE_TopComponent_Elm(x);
end);

InstallOtherMethod( WPE_TopComponent, "list rep of wreath elements", true, [IsList], 0,
function(x)
    return WPE_TopComponent_Elm(x);
end);

InstallGlobalFunction( TopGroupOfWreathProduct,
function(W)
    if not HasWreathProductInfo(W) then
        return Error("W is not a wreath product");
    fi;
    return WPE_TopGroup(W);
end);

InstallMethod( WPE_TopGroup, "wreath product", true, [HasWreathProductInfo], 0,
function(W)
    return Image(Embedding(W, WPE_TopDegree(W) + 1));
end);

InstallMethod( WPE_TopDegree, "generic wreath elements", true, [IsWreathProductElement], 0,
function(x)
    local info;

    info := FamilyObj(x)!.info;
    return info.degI;
end);

InstallOtherMethod( WPE_TopDegree, "list rep of wreath elements", true, [IsList], 0,
function(x)
    return Length(x) - 1;
end);

InstallOtherMethod( WPE_TopDegree, "wreath product", true, [HasWreathProductInfo], 0,
function(W)
    local info;

    info := WreathProductInfo(W);
    return info.degI;
end);

InstallGlobalFunction( BaseComponentOfWreathProductElement,
function(arg)
    local degI, x, i;

    if Length(arg) > 2 then
        return Error("wrong number of arguments");
    fi;
    x := arg[1];
    if not IsWreathProductElement(x) then
        return Error("x is not a wreath product element");
    fi;
    degI := WPE_TopDegree(x);
    if Length(arg) = 1 then
        return WPE_BaseComponent(x);
    else
        i := arg[2];
        if not IsInt(i) then
            return Error("i must be an integer");
        fi;
        if i < 1 or i > degI then
        return Error("Index out of bounds");
        fi;
        return WPE_BaseComponent(x, i);
    fi;
end);

BindGlobal( "WPE_BaseComponent_Elm",
function(x)
    local degI;

    degI := WPE_TopDegree(x);
    return List([1 .. degI], i -> WPE_BaseComponent(x, i));
end);

InstallMethod( WPE_BaseComponent, "generic wreath elements", true, [IsWreathProductElement], 0,
function(x)
    return WPE_BaseComponent_Elm(x);
end);

InstallOtherMethod( WPE_BaseComponent, "list rep of wreath elements", true, [IsList], 0,
function(x)
    return WPE_BaseComponent_Elm(x);
end);

BindGlobal( "WPE_BaseComponent_ElmAndInt",
function(x, i)
    return x![i];
end);

InstallOtherMethod( WPE_BaseComponent, "generic wreath elements and integer", true, [IsWreathProductElement, IsInt], 0,
function(x, i)
    return WPE_BaseComponent_ElmAndInt(x, i);
end);

InstallOtherMethod( WPE_BaseComponent, "list rep of wreath elements", true, [IsList, IsInt], 0,
function(x, i)
    return WPE_BaseComponent_ElmAndInt(x, i);
end);

InstallGlobalFunction( BaseGroupOfWreathProduct,
function(arg)
    local degI, W, i;

    if Length(arg) > 2 then
        return Error("wrong number of arguments");
    fi;
    W := arg[1];
    if not HasWreathProductInfo(W) then
        return Error("W is not a wreath product");
    fi;
    degI := WPE_TopDegree(W);
    if Length(arg) = 1 then
        return WPE_BaseGroup(W);
    else
        i := arg[2];
        if not IsInt(i) then
            return Error("i must be an integer");
        fi;
        if i < 1 or i > degI then
            return Error("Index out of bounds");
        fi;
        return WPE_BaseGroup(W, i);
    fi;
end);

InstallMethod( WPE_BaseGroup, "wreath product", true, [HasWreathProductInfo], 0,
function(W)
    local info, degI, grps;

    info := WreathProductInfo(W);
    degI := WPE_TopDegree(W);
    grps := ComponentsOfWreathProduct(W);
    if not IsBound(info.base) then
        info.base := Group(Concatenation(List([1 .. degI], i -> List(GeneratorsOfGroup(grps[1]), x -> x ^ Embedding(W, i)))));
    fi;
    return info.base;
end);

InstallOtherMethod( WPE_BaseGroup, "wreath product and integer", true, [HasWreathProductInfo, IsInt], 0,
function(W, i)
    return Image(Embedding(W, i));
end);

[ Dauer der Verarbeitung: 0.30 Sekunden  (vorverarbeitet)  ]