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


Quelle  frelement.gi   Sprache: unbekannt

 
#############################################################################
##
#W frelement.gi                                             Laurent Bartholdi
##
#Y Copyright (C) 2006-2013, Laurent Bartholdi
##
#############################################################################
##
##  This file implements the category of functionally recursive elements.
##
#############################################################################

#############################################################################
##
#O FRMachine
#O InitialState
##
InstallMethod(UnderlyingFRMachine, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep],
        E->E![1]);

InstallMethod(InitialState, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep],
        E->E![2]);

InstallMethod(SetUnderlyingMealyElement, "(FR) for two FR elements",
        [IsFRElement and IsFRElementStdRep,IsFRElement],
        function(E,M)
    E![3] := M;
    SetFilterObj(E,HasUnderlyingMealyElement);
end);    

InstallMethod(UnderlyingMealyElement, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep],
        function(E)
    E![3] := AsMealyElement(E);
    SetFilterObj(E,HasUnderlyingMealyElement);
    return E![3];
end);

InstallMethod(UnderlyingMealyElement, "(FR) for a Mealy-FR element",
        [IsFRElement and IsFRElementStdRep and HasUnderlyingMealyElement],
        function(E)
    return E![3];
end);

InstallMethod(FREFamily, "(FR) for an alphabet",
        [IsListOrCollection],
        d -> FREFamily(FRMFamily(d)));

InstallMethod(FREFamily, "(FR) for an FR machine family",
        [IsFamily],
        function(fam)
    local i, f;
    for i in FR_FAMILIES do
        if fam in i{[2..Length(i)]} then
            if IsBound(i[3]) then return i[3]; fi;
            f := NewFamily(Concatenation("FRElement(",String(i[1]),")"), IsFRElement and IsAssociativeElement);
            f!.alphabet := i[1];
     if IsVectorSpace(i[1]) then # so LieObject works
  SetCharacteristic(f,Characteristic(i[1]));
     fi;
            f!.standard := Size(i[1])<2^28 and i[1]=[1..Size(i[1])];
            if not f!.standard then
                f!.a2n := x->Position(Enumerator(i[1]),x);
                f!.n2a := x->Enumerator(i[1])[x];
            fi;
            Add(i,f);
            return f;
        fi;
    od;
    return fail;
end);

InstallMethod(FRMFamily, "(FR) for an FRE family",
        [IsFamily],
        function(f)
    local i;
    for i in FR_FAMILIES do
        if f in i{[3..Length(i)]} then return i[2]; fi;
    od;
    return fail;
end);

InstallMethod(FRMFamily, "(FR) for an FR machine",
        [IsFRMachine],
        FamilyObj);

InstallMethod(FRMFamily, "(FR) for an FR element",
        [IsFRElement],
        E->FRMFamily(FamilyObj(E)));

InstallMethod(FREFamily, "(FR) for a FR machine",
        [IsFRMachine],
        M->FREFamily(FamilyObj(M)));

InstallMethod(FREFamily, "(FR) for a FR element",
        [IsFRElement],
        FamilyObj);
#############################################################################

#############################################################################
##
#O FRElement(Transitions, Output, Init)
#O FRElement(Names, Transitions, Output, Init)
#O FRElement(Group, Transitions, Output, Init)
#O FRElement(FRMachine, Init)
##
BindGlobal("FRETYPE@", function(f)
    if IsGroup(f) then
        return IsGroupFRElement and IsFRElementStdRep;
    elif HasIsFreeMonoid(f) and IsFreeMonoid(f) then
        return IsMonoidFRElement and IsFRElementStdRep;
    elif HasIsFreeSemigroup(f) and IsFreeSemigroup(f) then
        return IsSemigroupFRElement and IsFRElementStdRep;
    else
        Error("Unknown stateset ",f,"\n");
    fi;
end);

InstallOtherMethod(FRElementNC, "(FR) for a family, a free semigroup, a list of transitions, a list of outputs and an initial state",
        [IsFamily, IsSemigroup, IsList, IsList, IsAssocWord],
        function(fam,free,transitions,output,init)
    return Objectify(NewType(fam, FRETYPE@(free)),
                   [FRMachineNC(FRMFamily(fam),free,transitions,output),Immutable(init)]);
end);

InstallMethod(FRElementNC, "(FR) for a FR machine and an initial word",
        [IsFamily, IsFRMachine and IsFRMachineStdRep, IsAssocWord],
        function(fam,M,init)
    return Objectify(NewType(fam, FRETYPE@(M!.free)),
                   [M,Immutable(init)]);
end);

InstallMethod(FRElement, "(FR) for a list of transitions, a list of outputs and an initial list of states",
        [IsList, IsList, IsList],
        function(transitions,output,init)
    local M;
    M := FRMachine(transitions,output);
    return FRElementNC(FREFamily(M),M,M!.pack(init));
end);

InstallMethod(FRElement, "(FR) for a list of transitions, a list of outputs and an initial state",
        [IsList, IsList, IsInt],
        function(transitions,output,init)
    local M;
    M := FRMachine(transitions,output);
    return FRElementNC(FREFamily(M),M,M!.pack([init]));
end);

InstallMethod(FRElement, "(FR) for a list of names, a list of transitions, a list of outputs and an initial list of states",
        [IsList, IsList, IsList, IsList],
        function(names, transitions,output,init)
    local M;
    M := FRMachine(names, transitions,output);
    return FRElementNC(FREFamily(M),M,M!.pack(init));
end);

InstallMethod(FRElement, "(FR) for a list of names, a list of transitions, a list of outputs and an initial state",
        [IsList, IsList, IsList, IsInt],
        function(names, transitions,output,init)
    local M;
    M := FRMachine(names, transitions,output);
    return FRElementNC(FREFamily(M),M,M!.pack([init]));
end);

InstallMethod(FRElement, "(FR) for a free group/semigroup/monoid, a list of transitions, a list of outputs and an initial word",
        [IsSemigroup, IsList, IsList, IsAssocWord],
        function(free,transitions,output,init)
    local M;
    if not init in free then
        Error(init, " must be an element of ", free,"\n");
    fi;
    M := FRMachine(free,transitions,output);
    return FRElementNC(FREFamily(M),M,init);
end);

InstallMethod(FRElement, "(FR) for a free group/semigroup/monoid, a list of transitions, a list of outputs and an initial word (as list of states)",
        [IsSemigroup, IsList, IsList, IsList],
        function(free,transitions,output,init)
    local M;
    M := FRMachine(free,transitions,output);
    return FRElementNC(FREFamily(M),M,M!.pack(init));
end);

InstallMethod(FRElement, "(FR) for a free group/semigroup/monoid, a list of transitions, a list of outputs and an initial word (as state)",
        [IsSemigroup, IsList, IsList, IsInt],
        function(free,transitions,output,init)
    local M;
    M := FRMachine(free,transitions,output);
    return FRElement(FREFamily(M),M,M!.pack([init]));
end);

InstallMethod(FRElement, "(FR) for a FR element and an initial word",
        [IsFRElement and IsFRElementStdRep, IsAssocWord],
        function(E,init)
    if not init in E![1]!.free then
        init := E![1]!.pack(LetterRepAssocWord(init));
#       Error("FRElement: ",init, " must be an element of ", E![1]!.free,"\n");
    fi;
    return FRElementNC(FamilyObj(E),E![1],init);
end);

InstallMethod(FRElement, "(FR) for a FR machine and an initial word",
        [IsFRMachine and IsFRMachineStdRep, IsAssocWord],
        function(M,init)
    local t;
    if not init in M!.free then
        Error(init, " must be an element of ", M!.free,"\n");
    fi;
    return FRElementNC(FREFamily(M),M,init);
end);

InstallMethod(FRElement, "(FR) for a FR element and an initial list",
        [IsFRElement and IsFRElementStdRep, IsList],
        function(E,init)
    return FRElementNC(FamilyObj(E),E![1],E![1]!.pack(init));
end);

InstallMethod(FRElement, "(FR) for a FR machine and an initial list",
        [IsFRMachine and IsFRMachineStdRep, IsList],
        function(M,init)
    return FRElementNC(FREFamily(M),M,M!.pack(init));
end);

InstallMethod(FRElement, "(FR) for a FR element and an initial letter",
        [IsFRElement and IsFRElementStdRep, IsPosInt],
        function(E,init)
    return FRElementNC(FamilyObj(E),E![1],E![1]!.pack([init]));
end);

InstallMethod(FRElement, "(FR) for a FR machine and an initial letter",
        [IsFRMachine and IsFRMachineStdRep, IsPosInt],
        function(M,init)
    return FRElementNC(FREFamily(M),M,M!.pack([init]));
end);

InstallMethod(VertexElement, "(FR) for a vertex index and an FR element",
        [IsPosInt, IsFRElement],
        function(v,e)
    local m;
    m := List(AlphabetOfFRObject(e),x->[]);
    m[v] := [e];
    return FRElement([m],[()],[1]);
end);

InstallMethod(VertexElement, "(FR) for a vertex and an FR element",
        [IsList, IsFRElement],
        function(v,e)
    local i;
    for i in [Length(v),Length(v)-1..1] do e := VertexElement(v[i],e); od;
    return e;
end);

InstallMethod(DiagonalElement, "(FR) for a power and an FR element",
        [IsInt, IsFRElement and IsFRElementStdRep],
        function(n,e)
    local f;
    f := VertexElement(1,e);
    f![1]!.transitions := ShallowCopy(f![1]!.transitions);
    f![1]!.transitions[1] := List([0..Size(AlphabetOfFRObject(e))-1],i->f![1]!.transitions[1][1]^((-1)^i*Binomial(n,i)));
    MakeImmutable(f![1]!.transitions);
    return f;
end);

InstallMethod(DiagonalElement, "(FR) for a list and an FR element",
        [IsList, IsFRElement],
        function(v,e)
    local i;
    for i in [Length(v),Length(v)-1..1] do e := DiagonalElement(v[i],e); od;
    return e;
end);

InstallOtherMethod(\[\], "(FR) for an FR machine and an index",
        [IsFRMachine, IsPosInt],
        function(M,s)
    return FRElement(M,s);
end);

InstallOtherMethod(\{\}, "(FR) for an FR machine and a list",
        [IsFRMachine, IsList],
        function(M,x)
    return List(x,s->FRElement(M,s));
end);
#############################################################################

#############################################################################
##
#M  ViewObj(FRElement)
#M  String(FRElement)
#M  Display(FRElement)
##
InstallMethod(ViewString, "(FR) for a FR element",
        [IsFRElement and IsFRElementStdRep],
        function(E)
    local s;
    s := "";
    APPEND@(s,"<", Size(AlphabetOfFRObject(E)), "|");
    if HasOne(UnderlyingFRMachine(E)!.free) and IsOne(InitialState(E)) then
        APPEND@(s,"identity ...");
    else
        APPEND@(s,InitialState(E));
    fi;
    if HasUnderlyingMealyElement(E) then
        APPEND@(s,"|",Length(StateSet(UnderlyingMealyElement(E))));
    fi;
    APPEND@(s,">");
    return s;
end);

InstallMethod(String, "(FR) for a FR element",
        [IsFRElement and IsFRElementStdRep],
        function(E)
    return CONCAT@("FRElement(...,",InitialState(E),")");
end);

InstallMethod(DisplayString, "(FR) for a FR element",
        [IsFRElement and IsFRElementStdRep],
        function(E)
    return CONCAT@(DisplayString(UnderlyingFRMachine(E)),"Initial state: ",InitialState(E),"\n");
end);

INSTALLPRINTERS@(IsFRElement);
#############################################################################

#############################################################################
##
#M One(FRElement)
##
BindGlobal("ONE@", function(E)
    local e;
    e := FRElement(E![1],One(E![2]));
    if HasUnderlyingMealyElement(E) then
        SetUnderlyingMealyElement(e,One(UnderlyingMealyElement(E)));
    fi;
    return e;
end);
    
InstallMethod(OneOp, "(FR) for a FR element",
        [IsGroupFRElement],
        ONE@);

InstallMethod(OneOp, "(FR) for a FR element",
        [IsMonoidFRElement],
        ONE@);

InstallMethod(OneOp, "(FR) for a FR element",
        [IsSemigroupFRElement],
        function(E)
    local s, g, e;
    s := FreeSemigroup(1); g := GeneratorsOfSemigroup(s)[1];
    e := FRElementNC(FamilyObj(E),s,[List(AlphabetOfFRObject(E),x->g)],[AlphabetOfFRObject(E)],g);
    if HasUnderlyingMealyElement(E) then
        SetUnderlyingMealyElement(e,One(UnderlyingMealyElement(E)));
    fi;
    return e;
end);
#############################################################################

#############################################################################
##
#M InverseOp(FRElement)
##
BindGlobal("INVOLVEDGENERATORS@", function(E)
    local s, olds;
    s := Set(List(LetterRepAssocWord(E![2]),AbsInt));
    repeat
        olds := s;
        UniteSet(s,Set(List(Flat(List(E![1]!.transitions{s},r->List(r,LetterRepAssocWord))),AbsInt)));
    until olds=s;
    return s;
end);

BindGlobal("REVERSEDWORD@", function(w)
    return AssocWordByLetterRep(FamilyObj(w),Reversed(LetterRepAssocWord(w)));
end);

InstallMethod(InverseOp, "(FR) for a group FR element",
        [IsFRElement and IsFRElementStdRep],
        function(E)
    local s, trans, out, i, rws, e;
    if HasIsGroupFRMachine(E![1]) and IsGroupFRMachine(E![1]) then
        rws := NewFRMachineRWS(E![1]);
        e := FRElement(E![1], rws.letterunrep(rws.reduce(rws.letterrep(E![2]^-1))));
    else
        s := INVOLVEDGENERATORS@(E);
        trans := [];
        out := [];
        for i in [1..Length(E![1]!.transitions)] do
            if i in s then
                if ISINVERTIBLE@(E![1]!.output[i]) then
                    Add(out,INVERSE@(E![1]!.output[i]));
                else
                    return fail;
                fi;
                Add(trans,List(E![1]!.transitions[i]{out[Length(out)]},REVERSEDWORD@));
            else
                Add(trans,E![1]!.transitions[i]);
                Add(out,E![1]!.output[i]);
            fi;
        od;
        e := FRElementNC(FamilyObj(E),E![1]!.free,trans,out,REVERSEDWORD@(E![2]));
    fi;
    if HasUnderlyingMealyElement(E) then
        SetUnderlyingMealyElement(e,InverseOp(UnderlyingMealyElement(E)));
    fi;
    return e;
end);

InstallMethod(IsInvertible, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep],
        function(E)
    return (HasIsGroupFRMachine(E![1]) and IsGroupFRMachine(E![1])) or
           ForAll(INVOLVEDGENERATORS@(E),s->ISINVERTIBLE@(E![1]!.output[s]));
end);
#############################################################################

#############################################################################
##
#M \*(FRElement, FRElement)
##
InstallMethod(\*, "(FR) for two FR elements",
        IsIdenticalObj,
        [IsFRElement and IsFRElementStdRep, IsFRElement and IsFRElementStdRep],
        function(left, right)
    local M, N, rws, e;
    if IsIdenticalObj(left![1],right![1]) then
        rws := NewFRMachineRWS(left![1]);
        e := FRElement(left![1], rws.letterunrep(rws.reduce(rws.letterrep(left![2]*right![2]))));
    else    
        N := SubFRMachine(left![1],right![1]);
        if N <> fail then
            return FRElement(left![1],left![2]*right![2]^N);
        fi;
        N := SubFRMachine(right![1],left![1]);
        if N <> fail then
            return FRElement(right![1],left![2]^N*right![2]);
        fi;
        M := left![1] * right![1];
        e := FRElement(M,left![2]^Correspondence(M)[1]*right![2]^Correspondence(M)[2]);
    fi;
    if HasUnderlyingMealyElement(left) and HasUnderlyingMealyElement(right) then
        SetUnderlyingMealyElement(e,UnderlyingMealyElement(left)*UnderlyingMealyElement(right));
    fi;
    return e;
end);
#############################################################################

############################################################################
##
#O \^(Integer, FRElement)
#O \^(Sequence, FRElement)
#O FRElement[Integer]
#O FRElement{Sequence}
##
InstallOtherMethod(\^, "(FR) for an integer and an FR element",
        [IsPosInt, IsFRElement and IsFRElementStdRep],
        function(x,E)
    return Output(E![1],E![2],x);
end);

InstallOtherMethod(\^, "(FR) for a vertex and an FR element",
        [IsList, IsFRElement],
        function(l,E)
    local t, i, s, M;
    t := [];
    M := UnderlyingFRMachine(E);
    s := InitialState(E);
    for i in l do
        Add(t,Output(M,s,i));
        s := Transition(M,s,i);
    od;
    return t;
end);

InstallOtherMethod(\^, "(FR) for a periodic vertex and an FR element",
        [IsPeriodicList, IsFRElement],
        function(l,E)
    local t, i, s, states, M;
    t := [];
    M := UnderlyingFRMachine(E);
    s := InitialState(E);
    for i in l![1] do
        Add(t,Output(M,s,i));
        s := Transition(M,s,i);
    od;
    if l![2]<>[] then
        states := NewDictionary(s,true);
        while not KnowsDictionary(states,s) do
            AddDictionary(states,s,Length(t));
            for i in l![2] do
                Add(t,Output(M,s,i));
                s := Transition(M,s,i);
            od;
        od;
        t := CompressedPeriodicList(t,LookupDictionary(states,s)+1);
    fi;
    return t;
end);

InstallOtherMethod(State, "(FR) for an FR element and an integer",
        [IsFRElement and IsFRElementStdRep, IsInt],
        function(E,x)
    local e;
    e := FRElement(E![1], Transition(E![1],E![2],x));
    if HasUnderlyingMealyElement(E) then
        SetUnderlyingMealyElement(e,State(UnderlyingMealyElement(E),x));
    fi;
    return e;
end);

InstallOtherMethod(State, "(FR) for an FR element and a list",
        [IsFRElement and IsFRElementStdRep, IsList],
        function(E,x)
    local pi, i, v, e;
    pi := WreathRecursion(E![1]);
    v := E![2];
    for i in [1..Length(x)] do
        v := pi(v)[1][x[i]];
    od;
    e := FRElement(E![1], v);
    if HasUnderlyingMealyElement(E) then
        SetUnderlyingMealyElement(e,State(UnderlyingMealyElement(E),x));
    fi;
    return e;    
end);
#############################################################################

############################################################################
##
#O Output(FRElement)
#O Activity(FRElement, Level)
#O Portrait
##
InstallMethod(Output, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep],
        E->Output(E![1],E![2]));

InstallMethod(Output, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep, IsObject, IsObject],
        function(E,s,a)
    return Output(E![1],s,a);
end);

InstallMethod(Transition, "(FR) for an FR element and a [list of] letters",
        [IsFRElement and IsFRElementStdRep, IsObject],
        function(E,i)
    return Transition(E![1],E![2],i);
end);

InstallMethod(Transition, "(FR) for an FR element and a list",
        [IsFRElement, IsList],
        function(E,l)
    local i, s, M;
    s := InitialState(E);
    M := UnderlyingFRMachine(E);
    for i in l do
        s := Transition(M,s,i);
    od;
    return s;
end);

InstallMethod(Transitions, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep],
        E->Transitions(E![1],E![2]));

InstallMethod(Transitions, "(FR) for an FR element and a state",
        [IsFRElement and IsFRElementStdRep, IsAssocWord],
        function(E,w)
    return Transitions(E![1],w);
end);

InstallMethod(Transitions, "(FR) for an FR element and a state",
        [IsFRElement and IsFRElementStdRep, IsList],
        function(E,s)
    return Transitions(E![1],s);
end);

BindGlobal("MAKEPERMS@", function(M,l)
    local d, i, j, k, s, p, q, perms, oldperms, S, SR;
    d := Size(AlphabetOfFRObject(M));
    S := GeneratorsOfFRMachine(M);
    SR := List(S,WreathRecursion(M));
    perms := List(S,s->[1]);
    for i in [1..l] do
        oldperms := perms;
        perms := [];
        for s in SR do
            p := [];
            for j in [1..d] do
                q := [1..d^(i-1)];
                for k in LetterRepAssocWord(s[1][j]) do
                    if k>0 then
                        q := oldperms[k]{q};
                    else
                        q := INVERSE@(oldperms[-k]){q};
                    fi;
                od;
                Append(p,q+d^(i-1)*(s[2][j]-1));
            od;
            Add(perms,p);
        od;
    od;
    return perms;
end);

BindGlobal("PERMORTRANSFORMATION@", function(t)
    if RankOfTransformation(t)=DegreeOfTransformation(t) then
        return AsPermutation(t);
    fi;
    return t;
end);

InstallMethod(Activity, "(FR) for an FR element",
        [IsFRElement],
        E->PERMORTRANSFORMATION@(TransformationList(Output(E))));

InstallMethod(ActivityTransformation, "(FR) for an FR element",
        [IsFRElement],
        E->TransformationList(Output(E)));

InstallMethod(ActivityPerm, "(FR) for an FR element",
        [IsFRElement],
        E->PermList(Output(E)));

InstallMethod(ActivityInt, "(FR) for an FR element",
        [IsFRElement],
        function(E)
    local p, delta;
    p := Output(E);
    delta := p[1]-1;
    if p=Concatenation([1+delta..Size(AlphabetOfFRObject(E))],[1..delta]) then
        return delta;
    else
        return fail;
    fi;
end);

InstallMethod(Activity, "(FR) for a group FR element and a level",
        [IsGroupFRElement and IsFRElementStdRep, IsInt],
        function(E,l)
    return MAPPEDWORD@(E![2],List(MAKEPERMS@(E![1],l),PermList),());
end);

InstallMethod(Activity, "(FR) for an FR element and a level",
        [IsFRElement and IsFRElementStdRep, IsInt],
        function(E,l)
    return PERMORTRANSFORMATION@(ActivityTransformation(E,l));
end);

InstallMethod(ActivityTransformation, "(FR) for an FR element and a level",
        [IsFRElement and IsFRElementStdRep, IsInt],
        function(E,l)
    return MAPPEDWORD@(E![2],List(MAKEPERMS@(E![1],l),Transformation),IdentityTransformation);
end);

InstallMethod(ActivityPerm, "(FR) for an FR element and a level",
        [IsFRElement and IsFRElementStdRep, IsInt],
        function(E,l)
    return MAPPEDWORD@(E![2],List(MAKEPERMS@(E![1],l),PermList),());
end);

BindGlobal("INT2SEQ@", function(x,l,n)
    local s, i;
    s := [];
    x := x-1;
    for i in [1..l] do
        Add(s,1+RemInt(x,n));
        x := QuoInt(x,n);
    od;
    return s;
end);

BindGlobal("SEQ2INT@", function(s,l,n)
    return 1+Sum([1..l],i->(s[i]-1)*n^(i-1));
end);

InstallMethod(ActivityInt, "(FR) for an FR machine and a state",
        [IsFRElement, IsInt],
        function(E,l)
    local p, n, i, delta, x;
    n := Size(AlphabetOfFRObject(E));
    p := ANY2OUT@(Activity(E,l),n^l);
    if p=fail then return fail; fi;
    x := List([1..n^l],i->SEQ2INT@(Reversed(INT2SEQ@(i,l,n)),l,n));
    delta := Position(x,p[1])-1;
    if p{x}=Concatenation(x{[1+delta..n^l]},x{[1..delta]}) then
        return delta;
    else
        return fail;
    fi;
end);

PORTRAIT@ := fail; # shut up warning
PORTRAIT@ := function(g,n,act)
    if n=0 then
        return act(g,1);
    else
        return List(AlphabetOfFRObject(g),a->PORTRAIT@(State(g,a),n-1,act));
    fi;
end;
MakeReadOnlyGlobal("PORTRAIT@");

InstallMethod(Portrait, "(FR) for an FR element an a maximal level",
        [IsFRElement, IsInt],
        function(E,l)
    return List([0..l],i->PORTRAIT@(E,i,Activity));
end);

InstallMethod(PortraitPerm, "(FR) for an FR element an a maximal level",
        [IsFRElement, IsInt],
        function(E,l)
    return List([0..l],i->PORTRAIT@(E,i,ActivityPerm));
end);

InstallMethod(PortraitTransformation, "(FR) for an FR element an a maximal level",
        [IsFRElement, IsInt],
        function(E,l)
    return List([0..l],i->PORTRAIT@(E,i,ActivityTransformation));
end);

InstallMethod(PortraitInt, "(FR) for an FR element an a maximal level",
        [IsFRElement, IsInt],
        function(E,l)
    return List([0..l],i->PORTRAIT@(E,i,ActivityInt));
end);

InstallMethod(DecompositionOfFRElement, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep],
        function(E)
    local d, e, i;
    d := WreathRecursion(E![1])(E![2]);
    e := List(d[1],x->FRElement(E![1],x));
    if HasUnderlyingMealyElement(E) then
        for i in [1..Length(e)] do
            SetUnderlyingMealyElement(e[i],State(UnderlyingMealyElement(E),i));
        od;
    fi;
    return [e,d[2]];
end);

InstallMethod(DecompositionOfFRElement, "(FR) for an FR element and a level",
        [IsFRElement, IsPosInt],
        function(E,n)
    local d, s, t, i, l, m;
    E := DecompositionOfFRElement(E);
    if n=1 then return E; fi;
    d := Length(E[1]);
    l := [];
    for s in [1..d] do
        Append(l,ListWithIdenticalEntries(d^(n-1),d^(n-1)*(E[2][s]-1)));
    od;
    s := []; m := [];
    for E in E[1] do
        t := DecompositionOfFRElement(E,n-1);
        Append(s,t[1]);
        Append(m,t[2]);
    od;
    return [s,l+m];
end);
#############################################################################

#############################################################################
##
#M \=(FRElement, FRElement)
##
BindGlobal("GROUPISONE@", function(m,w)
    local rws, todo, d, t, u;

    rws := NewFRMachineRWS(m);
    todo := NewFIFO([rws.letterrep(w)]);
    for t in todo do
        u := rws.reduce(rws.cyclicallyreduce(t));
        if u<>[] then
            d := rws.pi(u);
            if not ISONE@(d[2]) then return false; fi;
            rws.addgprule(u,true);
            Append(todo,d[1]);
        fi;
    od;
    rws.commit();
    return true;
end);

BindGlobal("MONOIDCOMPARE@", function(m,v,w)
    # returns 0 if v=w in machine m,
    # returns -1 if v<w, and returns 1 if v>w
    local rws, todo, d, t;

    rws := NewFRMachineRWS(m);
    todo := NewFIFO([[rws.letterrep(v),rws.letterrep(w)]]);
    
    for t in todo do
        t := List(t,rws.reduce);
        if t[1]<>t[2] then
            d := List(t,rws.pi);
            if d[1][2]<>d[2][2] then
                if d[1][2]<d[2][2] then return -1; else return 1; fi;
            fi;
            rws.addsgrule(t[1],t[2],false);
            Append(todo,TransposedMat(List(d,x->x[1])));
        fi;
    od;
    rws.commit(); # add these rules, since we now know we have equality
    return 0;
end);

InstallMethod(\=, "(FR) for two group FR-Mealy elements",
        IsIdenticalObj,
        [IsFRMealyElement and IsFRElementStdRep, IsFRMealyElement and IsFRElementStdRep], 2, # better than other methods
        function(left, right)
    return UnderlyingMealyElement(left)=UnderlyingMealyElement(right);
end);

InstallMethod(\=, "(FR) for two group FR elements",
        IsIdenticalObj,
        [IsGroupFRElement and IsFRElementStdRep, IsGroupFRElement and IsFRElementStdRep],
        function(left, right)
    local m;
    
    if IsIdenticalObj(left![1], right![1]) then
        if left![2]=right![2] then
            return true;
        else
            return GROUPISONE@(left![1],left![2]/right![2]);
        fi;
    fi;
    m := FRMMINSUM@(left![1],right![1]);
    left := left![2]^Correspondence(m)[1]/right![2]^Correspondence(m)[2];
    return GROUPISONE@(m,left);
end);

InstallMethod(\=, "(FR) for two FR elements",
        IsIdenticalObj,
        [IsFRElement and IsFRElementStdRep, IsFRElement and IsFRElementStdRep],
        function(left, right)
    local m;
    
    if IsIdenticalObj(left![1], right![1]) then
        if left![2]=right![2] then
            return true;
        else
            return MONOIDCOMPARE@(left![1],left![2],right![2])=0;
        fi;
    fi;
    m := FRMMINSUM@(left![1],right![1]);
    return MONOIDCOMPARE@(m,left![2]^Correspondence(m)[1],right![2]^Correspondence(m)[2])=0;
end);

InstallMethod(IsOne, "(FR) for a group FR element",
        [IsFRMealyElement and IsFRElementStdRep], 1, # better than next
        function(E)
    return IsOne(UnderlyingMealyElement(E));
end);

InstallMethod(IsOne, "(FR) for a group FR element",
        [IsGroupFRElement and IsFRElementStdRep],
        function(E)
    if IsOne(E![2]) then
        return true;
    fi;
    return GROUPISONE@(E![1],E![2]);
end);

InstallMethod(IsOne, "(FR) for a FR element",
        [IsFRElement and IsFRElementStdRep],
        function(E)
    if HasOne(E![1]!.free) and IsOne(E![2]) then
        return true;
    else
        return MONOIDCOMPARE@(E![1],E![2],
                       AssocWordByLetterRep(FamilyObj(E![2]),[]))=0;
    fi;
end);

InstallMethod(Minimized, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep],
        function(E)
    local M;
    M := Minimized(E![1]);
    return FRElement(M,E![2]^Correspondence(M));
end);
#############################################################################

#############################################################################
##
#M \<(FRElement, FRElement)
##
InstallMethod(\<, "(FR) for two FR elements",
        IsIdenticalObj,
        [IsFRMealyElement and IsFRElementStdRep, IsFRMealyElement and IsFRElementStdRep],
        function(left, right)
    return UnderlyingMealyElement(left)<UnderlyingMealyElement(right);
end);

InstallMethod(\<, "(FR) for two FR elements",
        IsIdenticalObj,
        [IsFRElement and IsFRElementStdRep, IsFRElement and IsFRElementStdRep],
        function(left, right)
    local m;
    if IsIdenticalObj(left![1],right![1]) then
        return MONOIDCOMPARE@(left![1],left![2],right![2])<0;
    else
        m := FRMMINSUM@(left![1],right![1]);
        return MONOIDCOMPARE@(m,left![2]^Correspondence(m)[1],right![2]^Correspondence(m)[2])<0;
    fi;
end);
#############################################################################

#############################################################################
##
#M AsGroupFRElement
#M AsMonoidFRElement
#M AsSemigroupFRElement
##
InstallMethod(AsGroupFRElement, "(FR) for a group FR element",
        [IsGroupFRElement],
        E->FRElement(E![1],E![2]));

InstallMethod(AsGroupFRElement, "(FR) for a monoid FR element",
        [IsMonoidFRElement],
        function(E)
    local M;
    M := AsGroupFRMachine(E![1]);
    if M=fail then
        return fail;
    else
        return FRElement(M,E![2]^Correspondence(M));
    fi;
end);

InstallMethod(AsGroupFRElement, "(FR) for a semigroup FR element",
        [IsSemigroupFRElement],
        function(E)
    local M;
    M := AsGroupFRMachine(E![1]);
    if M=fail then
        return fail;
    else
        return FRElement(M,E![2]^Correspondence(M));
    fi;
end);

InstallMethod(AsMonoidFRElement, "(FR) for a group FR element",
        [IsGroupFRElement],
        function(E)
    local M;
    M := AsMonoidFRMachine(E![1]);
    return FRElement(M,E![2]^Correspondence(M));
end);

InstallMethod(AsMonoidFRElement, "(FR) for a monoid FR element",
        [IsMonoidFRElement],
        E->FRElement(E![1],E![2]));

InstallMethod(AsMonoidFRElement, "(FR) for a semigroup FR element",
        [IsSemigroupFRElement],
        function(E)
    local M;
    M := AsMonoidFRMachine(E![1]);
    return FRElement(M,E![2]^Correspondence(M));
end);

InstallMethod(AsSemigroupFRElement, "(FR) for a group FR element",
        [IsGroupFRElement],
        function(E)
    local M;
    M := AsSemigroupFRMachine(E![1]);
    return FRElement(M,E![2]^Correspondence(M));
end);

InstallMethod(AsSemigroupFRElement, "(FR) for a monoid FR element",
        [IsMonoidFRElement],
        function(E)
    local M;
    M := AsSemigroupFRMachine(E![1]);
    return FRElement(M,E![2]^Correspondence(M));
end);

InstallMethod(AsSemigroupFRElement, "(FR) for a semigroup FR element",
        [IsSemigroupFRElement],
        E->FRElement(E![1],E![2]));
############################################################################

############################################################################
##
#O States(FRElement)
##
InstallMethod(StateSet, "(FR) for an FR element",
        [IsFRElement and IsFRElementStdRep],
        E->StateSet(E![1]));

InstallMethod(States, "(FR) for an FR element",
        [IsFRElement],
        E->States([E]));

InstallOtherMethod(States, "(FR) for an empty list",
        [IsListOrCollection and IsEmpty],
        E->E);

InstallMethod(States, "(FR) for a list of FR elements",
        [IsFRElementCollection],
        function(L)
    local states, i, x, stateset;
    states := ShallowCopy(L);
    stateset := Set(states);
    i := 1;
    while i <= Length(states) do
        for x in DecompositionOfFRElement(states[i])[1] do
            if not x in stateset then
                Add(states,x);
                AddSet(stateset,x);
            fi;
        od;
        i := i+1;
        if RemInt(i,100)=0 then
            Info(InfoFR, 2, "The states contain at least ", states);
        fi;
    od;
    return states;
end);

BindGlobal("FRFIXEDSTATES@", function(L)
    local states, i, x, addstates, stateset;
    states := [];
    stateset := [];
    addstates := function(d)
        local i;
        for i in AlphabetOfFRObject(L[1]) do
            if d[2][i]=i and not d[1][i] in stateset then
                Add(states,d[1][i]);
                AddSet(stateset,d[1][i]);
            fi;
        od;
    end;
    for x in L do addstates(DecompositionOfFRElement(x)); od;
    i := 1;
    while i <= Length(states) do
        addstates(DecompositionOfFRElement(states[i]));
        i := i+1;
        if RemInt(i,100)=0 then
            Info(InfoFR, 2, "The fixed states contain at least ", states);
        fi;
    od;
    return states;
end);

InstallMethod(FixedStatesOfFRElement, "(FR) for an FR element",
        [IsFRElement],
        E->FRFIXEDSTATES@([E]));
InstallMethod(FixedStates, "(FR) for an FR element",
        [IsFRElement],
        FixedStatesOfFRElement);

InstallMethod(FixedStates, "(FR) for a list of FR elements",
        [IsFRElementCollection],
        FRFIXEDSTATES@);

InstallMethod(IsFiniteStateFRMachine, "(FR) for an FR machine",
        [IsFRMachine],
        M->ForAll(GeneratorsOfFRMachine(M),x->IsFiniteStateFRElement(FRElement(M,x))));

InstallMethod(IsFiniteStateFRElement, "(FR) for an FR element",
        [IsFRElement],
        e->CategoryCollections(IsFRElement)(States(e)));

BindGlobal("FRLIMITSTATES@", function(L)
    local s, d, S, oldS;
    s := Set(States(L));
    d := List(s,w->BlistList([1..Length(s)],List(DecompositionOfFRElement(w)[1],x->Position(s,x))));
    S := BlistList([1..Length(s)],[1..Length(s)]);
    repeat
        oldS := S;
        S := UnionBlist(ListBlist(d,S));
    until oldS=S;
    return ListBlist(s,S);
end);

InstallMethod(LimitStatesOfFRElement, "(FR) for an FR element",
        [IsFRElement],
        E->FRLIMITSTATES@([E]));
InstallMethod(LimitStates, "(FR) for an FR element",
        [IsFRElement],
        LimitStatesOfFRElement);

InstallMethod(LimitStates, "(FR) for a list of FR elements",
        [IsFRElementCollection],
        FRLIMITSTATES@);

BindGlobal("MAYBE_ORDER@", function(e,limit)
    # does the element e have provable infinite order, within raising to power
    # 'limit'?
    local testing, found, recur;
    testing := NewDictionary(e,true); # current order during recursion
    found := NewDictionary(e,true); # elements for which we found the order
    AddDictionary(testing,One(e),infinity);
    AddDictionary(found,One(e),1);
    recur := function(g,mult)
        local d, o, p, h, ho, i, j, c, m;
        if KnowsDictionary(testing,g) then
            if KnowsDictionary(found,g) then
                return LookupDictionary(found,g);
            elif mult>LookupDictionary(testing,g) then
                return infinity;
            else
                return 1;
            fi;
        fi;
        d := DecompositionOfFRElement(g);
        p := PermList(d[2]); # returns fail if d[2] not invertible
        if p=fail or mult*Order(p)>limit then return fail; fi;
        AddDictionary(testing,g,mult);
        o := 1;
        for i in AlphabetOfFRObject(g) do
            c := Cycle(p,i);
            h := d[1][c[1]];
            for j in c{[2..Length(c)]} do h := h*d[1][j]; od;
            if i in c then m := Size(c)*mult; else m := Size(c)*mult+1; fi;
            ho := recur(h,m);
            if ho=infinity or ho=fail then
                return ho;
            else
                o := LcmInt(o,Size(c)*ho);
            fi;
        od;
        AddDictionary(found,g,o);
        return o;
    end;
    return recur(e,1);
end);

BindGlobal("NUCLEUS@", function(L)
    local s, news, olds, gens, i, j, maybeinf;

    gens := Set(L);
    news := gens;
    s := [];
    maybeinf := []; # the part of s that may be of
                    # infinite order and self-recurrent
    while true do
        olds := ShallowCopy(s);
        UniteSet(s,LimitStates(news));
        if Length(s)=Length(olds) then
            return s;
        fi;

        i := 1; while i <= Size(maybeinf) do
            j := MAYBE_ORDER@(maybeinf[i],Size(s));
            if j=infinity then
                return fail;
            elif j=fail then
                i := i+1;
            else
                Remove(maybeinf,i);
            fi;
        od;

        news := [];
        for i in Difference(s,olds) do
            if i in FixedStates(i) then
                Add(maybeinf,i);
            fi;
            for j in gens do AddSet(news,i*j); od;
        od;
        Info(InfoFR, 2, "Nucleus: The nucleus contains at least ",s);
    od;
end);

InstallMethod(NucleusOfFRMachine, "(FR) for an FR machine",
        [IsFRMachine],
        M->NUCLEUS@(List(GeneratorsOfFRMachine(M),x->FRElement(M,x))));
#############################################################################

#############################################################################
##
#M Order(FRElement)
##
## is proved to terminate for bounded elements, by Said Sidki (personal
## communication); otherwise could run forever
##
BindGlobal("ORDER@", function(e)
    local testing, found, recur;
    
    if HasUnderlyingMealyElement(e) then
        e := UnderlyingMealyElement(e);
    fi;

    if not IsInvertible(e) then
 return fail;
    fi;
    
    if IsAbelian(VertexTransformationsFRElement(e)) then
        found := NewDictionary(e,false);
        recur := function(e)
            local d, i;
            if KnowsDictionary(found,e) then
                return false;
            elif IsLevelTransitiveFRElement(e) then
                return true;
            else
                AddDictionary(found,e);
                d := DecompositionOfFRElement(e);
                for i in AlphabetOfFRObject(e) do
                    if d[2][i]=i and recur(d[1][i]) then return true; fi;
                od;
            fi;
            return false;
        end;
        if recur(e) then
            return infinity;
        fi;
    fi;
    
    testing := NewDictionary(e,true); # current order during recursion
    found := NewDictionary(e,true); # elements for which we found the order
    AddDictionary(testing,One(e),infinity);
    AddDictionary(found,One(e),1);
    recur := function(g,mult)
        local d, o, h, ho, i, j;
        if IsGroupFRElement(g) then
            g := FRElement(g,CyclicallyReducedWord(InitialState(g)));
        fi;
        if KnowsDictionary(testing,g) then
            if KnowsDictionary(found,g) then
                return LookupDictionary(found,g);
            elif mult>LookupDictionary(testing,g) then
                return infinity;
            else
                return 1;
            fi;
        else
            AddDictionary(testing,g,mult);
            d := DecompositionOfFRElement(g);
            o := 1;
            for i in Cycles(PermList(d[2]),AlphabetOfFRObject(g)) do
                h := One(g);
                for j in i do h := h*d[1][j]; od;
                ho := recur(h,Length(i)*mult);
                if ho=infinity then
                    return infinity;
                else
                    o := LcmInt(o,Length(i)*ho);
                fi;
            od;
            AddDictionary(found,g,o);
            return o;
        fi;
    end;
    return recur(e,1);
end);

InstallMethod(Order, "(FR) for an FR element; not guaranteed to terminate",
        [IsFRElement and IsFRElementStdRep], ORDER@);
        
InstallMethod(Order, "(FR) for a Mealy element; not guaranteed to terminate",
        [IsMealyElement], ORDER@);
        
InstallMethod(IsLevelTransitiveFRElement, "(FR) for a group FR element",
        [IsGroupFRMealyElement],
        E->IsLevelTransitiveFRElement(UnderlyingMealyElement(E)));

InstallMethod(IsLevelTransitiveFRElement, "(FR) for a group FR element",
        [IsGroupFRElement],
        function(E)
    local seen, d, c, w, x;

    x := CyclicallyReducedWord(E![2]);
    seen := NewDictionary(x,false);
    w := WreathRecursion(E![1]);

    while not KnowsDictionary(seen,x) do
        AddDictionary(seen,x);
        d := w(x);
        c := Cycle(d[2],AlphabetOfFRObject(E),Representative(AlphabetOfFRObject(E)));
        if Set(c)<>AlphabetOfFRObject(E) then
            return false;
        fi;
        x := CyclicallyReducedWord(Product(d[1]{c}));
    od;
    return true;
end);
#############################################################################


[ Dauer der Verarbeitung: 0.51 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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