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

Quelle  OrbitalStructure.gi   Sprache: unbekannt

 
# Compute an orbital structure which has the
# following properties
#
# Input: G acting on Omega via Act

# Output: Orbital Structure
#         - A set of representatives of orbitals
#         - For any pair (i,j) efficiently
#           determine which orbital it belongs to
#         - For any pair (i,j) efficiently
#           compute an element g in G that takes (i,j)
#           to a representative in the set of
#           representatives
#         - iterate over orbit given a rep
#         - iterate over a transversal for
#           a stabilizer of a pair

InstallGlobalFunction( OrbitalStructure,
# gens  - generators of a group acting on Omega
# Omega - the domain
# Act   - action of Group(gens) on Omega
function(gens, Omega, Act)
    local o, so, i, res;

    # Result will be an orbital structure that allows
    # some stuff to be done with orbitals
    res := rec( gens := gens, group := Group(gens), act := Act );

    # Orbits. Currently we'll just choose the
    # first element in each orbit as orbit rep
    res.orbits := Orbits( res.group, Omega, Act );

    # This is so we're able to determine which orbit the
    # first point of a pair is in, and then get an element
    # of G that maps said point to the orbit rep
    # Really what we want is a schreier trees/vectors here
    res.orbreps := [];
    res.orbnums := HashMap(Size(Omega));
    res.orbstabs := [];
    for o in [1..Length(res.orbits)] do
        Add(res.orbreps, res.orbits[o][1]);
        res.orbstabs[o] := rec( );
        res.orbstabs[o].act := Act;
        res.orbstabs[o].group := Stabilizer(res.group, res.orbits[o][1], Act);
        res.orbstabs[o].orbits := Orbits(res.orbstabs[o].group, Omega, Act);
        res.orbstabs[o].orbnums := HashMap(Size(Omega));
        res.orbstabs[o].orbreps := [];
        for so in [1..Length(res.orbstabs[o].orbits)] do
            Add(res.orbstabs[o].orbreps, res.orbstabs[o].orbits[so][1]);
            for i in res.orbstabs[o].orbits[so] do
                res.orbstabs[o].orbnums[i] := so;
            od;
        od;

        for i in res.orbits[o] do
            res.orbnums[i] := o;
        od;
    od;

    return Objectify(OrbitalStructureType, res);
end);

InstallMethod( ViewObj, "for orbital structures",
               [ IsOrbitalStructure ],
function(os)
    Print("<orbital structure>");
end);

InstallMethod( PrintObj, "for orbital structures",
               [ IsOrbitalStructure ],
function(os)
    Print("<orbital structure>");
end);

# This could be a lot prettier still...
InstallGlobalFunction( OS_OrbitRepresentative,
function(os, pt)
    return os!.orbreps[os!.orbnums[pt]];
end);

InstallGlobalFunction( OS_CanonisingElement,
function(os, pt)
    return RepresentativeAction( os!.group
                              , pt
                              , os!.orbreps[os!.orbnums[pt]]
                              , os!.act);
end);

InstallGlobalFunction( OS_CanonisingElementAndRepresentative,
function(os, pt)
    return [ os!.orbreps[os!.orbnums[pt]]
          , RepresentativeAction( os!.group
                                , pt
                                , os!.orbreps[os!.orbnums[pt]]
                                , os!.act) ];
end);

InstallGlobalFunction( OS_StabilizerOf,
function(os, pt)
    return os!.orbstabs[os!.orbnums[pt]];
end);

InstallGlobalFunction(OrbitalRepresentative,
function(os, pair)
    local fo, so, p;

    # Returns a representative (as a pair of elements of the G set) for the
    # orbital that contains <pair>.

    fo := os!.orbnums[pair[1]];
    p := RepresentativeAction(os!.group, pair[1], os!.orbreps[fo], os!.act );
    so := os!.orbstabs[fo].orbnums[os!.act(pair[2], p)];
    return [ os!.orbreps[fo], os!.orbstabs[fo].orbreps[so] ];
end);

InstallGlobalFunction(AllOrbitalRepresentatives,
function(os)
    return Union(List(os!.orbreps, i -> [i,i])
                , ListX( [1..Length(os!.orbreps)]
                       , k -> os!.orbstabs[k].orbreps
                       , {x,y} -> [os!.orbreps[x],y] ) );
end);


# TODO: fix this.
InstallGlobalFunction(OrbitalCanonizingElement,
function(os, pair)

    # Returns a group elements that maps <pair> to its orbital representative
    # (as given by MAJORANA_OrbitalRep).

    local fo, so, p1, p2;

    fo := os!.orbnums[pair[1]];
    p1 := RepresentativeAction(os!.group, pair[1], os!.orbreps[fo], os!.act);
    so := os!.orbstabs[fo].orbnums[os!.act(pair[2], p1)];
    p2 := RepresentativeAction( os!.orbstabs[fo].group, os!.act(pair[2], p1)
                               , os!.orbstabs[fo].orbreps[so], os!.act);

    return p1 * p2;
end);

InstallGlobalFunction(OrbitalCanonizingElementInverse,
function(os, pair)
    return OrbitalCanonizingElement(os, pair)^-1;
    # Returns a group elements that maps the orbital representative of <pair>
    # to <pair> itself. This will be the inverse of the output of
    # MAJORANA_OrbitalCanonizingElement( os, pair )
end);

# Acting on sets of size 2
InstallGlobalFunction(UnorderedOrbitalRepresentative,
function(os, p)
    local a, b, oa, ob, r1, r2, p1, p2, tmp, tmp2;

    a := p[1];
    b := p[2];

    oa := os!.orbnums[a];
    ob := os!.orbnums[b];

    r1 := os!.orbreps[oa];
    r2 := os!.orbreps[ob];

    if r1 = r2 then
        # a and b are in the same orbit
        p1 := RepresentativeAction(os!.group, a, r1, os!.act);
        p2 := RepresentativeAction(os!.group, b, r1, os!.act);

        tmp := [r1, os!.act(b,p1)];
        ob := os!.orbstabs[oa].orbnums[tmp[2]];
        tmp[2] := os!.orbstabs[oa].orbreps[ob];

        tmp2 := [r1, os!.act(a, p2)];
        ob := os!.orbstabs[oa].orbnums[tmp2[2]];
        tmp2[2] := os!.orbstabs[oa].orbreps[ob];

        return Minimum(tmp,tmp2);
    elif r2 < r1 then
        # b has the smaller orbrep, i.e. in the orbitalrep
        # has the smaller representative. We swap roles of a and b
        tmp := b; b := a; a := tmp;
        tmp := r2; r2 := r1; r1 := tmp;
        tmp := ob; ob := oa; oa := tmp;
    fi;

    # Move a to the smaller rep
    p1 := RepresentativeAction(os!.group, a, r1, os!.act);
    # Now look in the point stabiliser of r1 what
    # element we can map b^p1 to
    ob := os!.orbstabs[oa].orbnums[os!.act(b, p1)];
    return [ r1, os!.orbstabs[oa].orbreps[ob]];
end);

InstallGlobalFunction(UnorderedOrbitalCanonizingElement,
function(os, pair)
    local a, b, oa, ob, r1, r2, p1, p2, tmp;

    a := pair[1];
    b := pair[2];

    r1 := OS_OrbitRepresentative(os, a);
    r2 := OS_OrbitRepresentative(os, b);
    if r1 = r2 then
        p1 := OS_CanonisingElement(os, a);
        p2 := OS_CanonisingElementAndRepresentative(OS_StabilizerOf(os, r1), os!.act(b, p1));

        tmp := [ [r1, p2[1]], p1 * p2[2] ];

        p1 := OS_CanonisingElement(os, b);
        p2 := OS_CanonisingElementAndRepresentative(OS_StabilizerOf(os, r1), os!.act(a, p1));

        if p2[1] < tmp[1][2] then
            tmp := [ [r1, p2[1]], p1 * p2[2] ];
        fi;
        return tmp[2];
    elif r2 < r1 then
        p1 := OS_CanonisingElement(os, b);
        return p1 * OS_CanonisingElement(OS_StabilizerOf(os, r2), os!.act(a, p1));
    else
        p1 := OS_CanonisingElement(os, a);
        return p1 * OS_CanonisingElement(OS_StabilizerOf(os, r1), os!.act(b, p1));
    fi;
end);

InstallGlobalFunction(UnorderedOrbitalCanonizingElementInverse,
     {os, pair} -> UnorderedOrbitalCanonizingElement(os, pair) ^ -1);

InstallGlobalFunction(AllUnorderedOrbitalRepresentatives,
function(os)
    local reps, reps2, p, q;

    reps := Set(Union( List( [1..Length(os!.orbreps)]
                       , k -> ListX(os!.orbreps, os!.orbstabs[k].orbreps
                                    , {x,y} -> UnorderedOrbitalRepresentative(os, [x,y]) ) ) ) );
    return reps;
end);

InstallGlobalFunction(OrbitalTransversalIterator,
function( os, rep )
    local r, fo, so;

    # Make sure we have *the* rep, not *a* rep
    rep := OrbitalRepresentative(os, rep);

    r := rec( orb := HashMap()
            , new := [ [ rep, [] ] ]
            , NextIterator := function(iter)
                local i, pntp, pnt, npntp, npnt;

                pntp := Remove(iter!.new, 1);
                pnt := pntp[1];

                for i in [1..Length(os!.gens)] do
                    npnt := OnTuples(pnt, os!.gens[i]);
                    if not npnt in iter!.orb then
                        npntp := [ npnt, Concatenation(pntp[2], [i]) ];
                        iter!.orb[npnt] := npntp[2];
                        Add(iter!.new, npntp);
                    fi;
                od;
                if Length(pntp[2]) = 0 then
                    return One(os!.group);
                else
                    return Product(List(pntp[2], i -> os!.gens[i]));
                fi;
            end
            , IsDoneIterator := iter -> iter!.new = []
            , ShallowCopy := iter -> rec( orb := StructuralCopy(iter!.orb)
                                        , new := ShallowCopy(iter!.new) )
            );
    r.orb[rep] := [];
    return IteratorByFunctions(r);
end);

# For now, a disguised orbit algorithm which is probably better
# than computing RepresentativeAction all the time!
InstallGlobalFunction(UnorderedOrbitalTransversalIterator,
function( os, rep )
    local r, fo, so;

    # Make sure we have *the* rep, not *a* rep
    rep := UnorderedOrbitalRepresentative(os, rep);

    r := rec( orb := HashMap()
            , new := [ [ rep, [] ] ]
            , NextIterator := function(iter)
                local i, pntp, pnt, npntp, npnt;

                pntp := Remove(iter!.new, 1);
                pnt := pntp[1];

                for i in [1..Length(os!.gens)] do
                    npnt := Set(pnt, x -> os!.act(x, os!.gens[i]));
                    if not npnt in iter!.orb then
                        npntp := [ npnt, Concatenation(pntp[2], [i]) ];
                        iter!.orb[npnt] := npntp[2];
                        Add(iter!.new, npntp);
                    fi;
                od;
                if Length(pntp[2]) = 0 then
                    return One(os!.group);
                else
                    return Product(List(pntp[2], i -> os!.gens[i]));
                fi;
            end
            , IsDoneIterator := iter -> iter!.new = []
            , ShallowCopy := iter -> rec( orb := StructuralCopy(iter!.orb)
                                        , new := ShallowCopy(iter!.new) )
            );
    r.orb[rep] := [];
    return IteratorByFunctions(r);
end);

BindGlobal("UnorderedOrbitalTest",
function(os, domain)
    local o, orbs, reps, muoreps;
    orbs := Orbits(os!.group, Combinations(domain, 2), OnSets);
    reps := List(orbs, Minimum);

    muoreps := AllUnorderedOrbitalRepresentatives(os);
    for o in domain do
        if o in os!.orbreps then
            if not ([o,o] in muoreps) then
                Error("The element ", o, " is an orbit representative, but its diagonal is not a representative");
            fi;
            Remove(muoreps, Position(muoreps, [o,o]));
        else
            if [o,o] in muoreps then
                Error("The element ", o, " is not an orbit representative, but its diagonal is a representative");
            fi;
        fi;
    od;
    if not IsSet(muoreps) then
        Error("Representatives do not form a set");
    fi;
    if not Set(muoreps) = Set(reps) then
        Print("Elements in muoreps that are not in reps: ", Difference(muoreps, reps), "\n");
        Print("Elements in reps that are not in muoreps: ", Difference(reps, muoreps), "\n");
        Error("differences between orbital reps and reps");
    fi;
    return true;
end);

BindGlobal("UnorderedOrbitalTransversalTest",
function(os, domain)
    local o, orbs, r, reps, i, iter, e, p;

    orbs := Orbits(os!.group, Combinations(domain, 2), OnSets);
    reps := List(orbs, Minimum);

    for r in reps do
        o := ShallowCopy(Filtered(orbs, x -> r in x)[1]);
        iter := UnorderedOrbitalTransversalIterator(os, r);
        for i in iter do
            e := OnSets(r, i);
            p := Position(o, e);
            if p = fail then
                Print("element ", e, " = ", r, "^", i, " not found\n");
            else
                Remove(o, p);
            fi;
        od;
        if not IsEmpty(o) then
            Error("leftover elements in orbit: ", o, " with rep ", r, "\n");
        fi;
    od;
    return true;
end);

BindGlobal("UnorderedOrbitalCanonizingTest",
function(os, domain)
    local o, orbs, r, rep, i, iter, e, p, can;

    orbs := Orbits(os!.group, Combinations(domain, 2), OnSets);
    for o in orbs do
        for i in o do
            rep := UnorderedOrbitalRepresentative(os, i);
            can := UnorderedOrbitalCanonizingElement(os, i);
            if rep <> OnSets(i, can) then;
                Error("element ", i, " is not canonized by ", can, "\n");
            fi;
        od;
    od;
    return true;
end);

BindGlobal("OrbitalTest",
function(os, domain)
    local o, orbs, reps, muoreps;
    orbs := Orbits(os!.group, Tuples(domain, 2), OnTuples);
    reps := List(orbs, Minimum);

    muoreps := AllOrbitalRepresentatives(os);
    if not IsSet(muoreps) then
        Error("Representatives do not form a set");
    fi;
    if not Set(muoreps) = Set(reps) then
        Print("Elements in muoreps that are not in reps: ", Difference(muoreps, reps), "\n");
        Print("Elements in reps that are not in muoreps: ", Difference(reps, muoreps), "\n");
        Error("differences between orbital reps and reps");
    fi;
    return true;
end);

BindGlobal("OrbitalTransversalTest",
function(os, domain)
    local o, orbs, r, reps, i, iter, e, p;

    orbs := Orbits(os!.group, Arrangements(domain, 2), OnTuples);
    reps := List(orbs, Minimum);

    for r in reps do
        o := ShallowCopy(Filtered(orbs, x -> r in x)[1]);
        iter := OrbitalTransversalIterator(os, r);
        for i in iter do
            e := OnTuples(r, i);
            p := Position(o, e);
            if p = fail then
                Print("element ", e, " = ", r, "^", i, " not found\n");
                Error("");
            else
                Remove(o, p);
            fi;
        od;
        if not IsEmpty(o) then
            Error("leftover elements in orbit: ", o, " with rep ", r, "\n");
        fi;
    od;
    return true;
end);

BindGlobal("OrbitalCanonizingTest",
function(os, domain)
    local o, orbs, r, rep, i, iter, e, p, can;

    orbs := Orbits(os!.group, Combinations(domain, 2), OnTuples);
    for o in orbs do
        for i in o do
            rep := OrbitalRepresentative(os, i);
            can := OrbitalCanonizingElement(os, i);
            if rep <> OnTuples(i, can) then;
                Print("element ", i, " is not canonized by ", can, "\n");
            fi;
        od;
    od;
    return true;
end);


[ Dauer der Verarbeitung: 0.35 Sekunden  (vorverarbeitet)  ]