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


Quelle  Autom.gi   Sprache: unbekannt

 
#############################################################################
##
#W  Autom.gi                FGA package                    Christian Sievers
##
##  Methods to create and compute with inverse automata
##
#Y  2003 - 2018
##


DeclareRepresentation( "IsSimpleInvAutomatonRep", 
    IsComponentObjectRep and IsInvAutomatonCategory and
      IsAttributeStoringRep and IsCollection,
#    [ "initial", "terminal", "states", "group" ] );
    [ "states", "group" ] );

InstallMethod( TrivialInvAutomaton,
    [ IsFreeGroup ],
    function(G)
    local state;
    state := FGA_newstate();
    return Objectify( NewType( FamilyObj( G ),
                               IsSimpleInvAutomatonRep and IsMutable),
                      rec(initial:=state, terminal:=state, group:=G) );
    end );

InstallMethod( InvAutomatonInsertGenerator,
    IsCollsElms,
    [ IsSimpleInvAutomatonRep and IsMutable, IsElementOfFreeGroup ],
    function(A,gen)
        FGA_AutomInsertGeneratorLetterRep( A, LetterRepAssocWord( gen ) );
    end );

InstallMethod( \in,
    "for a simple inverse automaton",
    IsElmsColls,
    [ IsElementOfFreeGroup, IsSimpleInvAutomatonRep ],
    function(g,A)
        return IsIdenticalObj(FGA_deltas( A!.initial,
                                          LetterRepAssocWord(g)),
                              A!.terminal);
    end );

InstallMethod( PrintObj,
   [ IsSimpleInvAutomatonRep ],
   function(A)
       Print("<simple inverse automaton representation>");
   end );

InstallMethod( AsGroup,
    "for a simple inverse Automaton",
    [ IsSimpleInvAutomatonRep ],
    function(A)
    local G;

    if IsMutable(A) then
        TryNextMethod();
    fi;

    G := rec ();
    ObjectifyWithAttributes( G,
        NewType( FamilyObj( A ),
                 IsFreeGroup and IsAttributeStoringRep and
                     HasOneImmutable and HasFreeGroupAutomaton ),
        OneImmutable, One( A!.group ),
        FreeGroupAutomaton, A );
    return G;
    end );

InstallGlobalFunction( FGA_newstate,
    function()
    return (rec (delta:=[], deltainv:=[]));
    end );

InstallGlobalFunction( FGA_connectpos,
    function(s1, s2, g)
    s1.delta[g] := s2;
    s2.deltainv[g] := s1;
    end );

InstallGlobalFunction( FGA_connect,
    function(s1, s2, g)
    if g>0 then
        FGA_connectpos(s1, s2, g);
    else
        FGA_connectpos(s2, s1, -g);
    fi;
    end );


InstallGlobalFunction( FGA_define,
    function(state, gen)
    local nstate;
    nstate := FGA_newstate();
    FGA_connect(state, nstate, gen);
    return nstate;  # !!!
    end );

# "active"
InstallGlobalFunction( FGA_find,
    function(s)
    while IsBound(s.isnow) do
        s := s.isnow;
    od;
    return s;
# todo: path compression
    end );

InstallGlobalFunction( FGA_merge,
    function(s1, s2, Q)
    s1 := FGA_find(s1);
    s2 := FGA_find(s2);
    if IsNotIdenticalObj(s1,s2) then
        s2.isnow := s1;
        Add(Q,s2);
    fi;
    end );

InstallGlobalFunction( FGA_coincidence,
    function(s1,s2)
    local Q, s, g, s0, s01, delta, deltainv;
    Q := [];
    FGA_merge(s1, s2, Q);
    for s in Q do
        delta := ShallowCopy(s.delta);
        for g in BoundPositions(delta) do
            Unbind(delta[g].deltainv[g]);
        od;
        deltainv := ShallowCopy(s.deltainv);
        for g in BoundPositions(deltainv) do
            Unbind(deltainv[g].delta[g]);
        od;
        for g in BoundPositions(delta) do
            s0 := FGA_find(s);
            s01 := FGA_find(delta[g]);
            if IsBound(s0.delta[g]) then
                FGA_merge(s01, s0.delta[g], Q);
            elif IsBound(s01.deltainv[g]) then
                FGA_merge(s0, s01.deltainv[g], Q);
            else
                FGA_connectpos(s0, s01, g);
            fi;
        od;
        for g in BoundPositions(deltainv) do
            s0 := FGA_find(s);
            s01 := FGA_find(deltainv[g]);
            if IsBound(s0.deltainv[g]) then
                FGA_merge(s01, s0.deltainv[g], Q);
            elif IsBound(s01.delta[g]) then
                FGA_merge(s0, s01.delta[g], Q);
            else
                FGA_connectpos(s01, s0, g);
            fi;
        od;
    od;
    end );


InstallGlobalFunction( FGA_delta,
    function(state, gen)
    if gen>0 then
        return ATf(state.delta, gen);
    else
        return ATf(state.deltainv, -gen);
    fi;
    end );

InstallGlobalFunction( FGA_deltas,
    function(state, genlist)
    return IteratedF(genlist, FGA_delta, state);
    end );

InstallGlobalFunction( FGA_TmpState,
    function(state, genlist)
    local undo, oldstate, i;
    i := 1;
    while state <> fail and i <= Size(genlist) do
       oldstate := state;
       state := FGA_delta( oldstate, genlist[i] );
       i := i+1;
    od;
    if state = fail then
       i := i-1;
       if genlist[i] > 0 then
           undo := function() Unbind(oldstate.delta[genlist[i]]); end;
       else
           undo := function() Unbind(oldstate.deltainv[-genlist[i]]); end;
       fi;
       state := Iterated( genlist{[i..Size(genlist)]}, FGA_define, oldstate );
    else
       undo := ReturnTrue;
    fi;
    return rec( state:=state, undo:=undo);
    end );

InstallGlobalFunction( FGA_trace,
    function(s,w)
    local i, s1;
    s1 := s;
    i := 1;
    while i <= Length(w) and s1 <> fail do
        s := s1;
        s1 := FGA_delta(s, w[i]);
        i := i+1;
    od;
    if s1 = fail then
        return rec(state:=s, index:=i-1);
    else
        return rec(state:=s1, index:=i);
    fi;
    end );

InstallGlobalFunction( FGA_backtrace,
    function(s,w,j)
    local i, s1;
    s1 := s;
    i := Length(w);
    while i >= j and s1 <> fail do
        s := s1;
        s1 := FGA_delta(s, -w[i]);
        i := i-1;
    od;
    if s1 = fail then
        return rec(state:=s, index:=i+1);
    else
        return rec(state:=s1, index:=i);
    fi;
    end );

InstallGlobalFunction( FGA_InsertGenerator,
    function(s, gen)
    return FGA_InsertGeneratorLetterRep(s, LetterRepAssocWord(gen));
    end );

InstallGlobalFunction( FGA_AutomInsertGeneratorLetterRep,
    function(A, w)
    A!.initial := FGA_InsertGeneratorLetterRep( A!.initial, w);
    A!.terminal := A!.initial;
    end );

InstallGlobalFunction( FGA_InsertGeneratorLetterRep,
    function(s, w)
    local i, t, bt, s1, s2;
    t := FGA_trace(s, w);
    bt := FGA_backtrace(s, w, t.index);
    s1 := t.state;
    s2 := bt.state;
    if t.index > bt.index then  # trace complete
        FGA_coincidence(s1, s2);
    else
        if IsIdenticalObj(s1, s2) then
            while w[t.index] = -w[bt.index] do
                s1 := FGA_define(s1, w[t.index]);
                t.index  := t.index  + 1;
                bt.index := bt.index - 1;
            od;
            s2 := s1;
        fi;
        for i in [t.index .. bt.index-1] do
            s1 := FGA_define(s1, w[i]);
        od;
        FGA_connect(s1, s2, w[bt.index]);
    fi;
    return FGA_find(s);
    end );

InstallGlobalFunction( FGA_FromGroupWithGenerators,
#    gens -> Iterated(gens, FGA_InsertGenerator, FGA_newstate()) );
    function(G)
    local s;
    s := Iterated(GeneratorsOfGroup(G), FGA_InsertGenerator, FGA_newstate());
    return Objectify( NewType( FamilyObj( G ),IsSimpleInvAutomatonRep),
                      rec(initial:=s, terminal:=s, group:=G) );
    end );

InstallGlobalFunction( FGA_FromGeneratorsLetterRep,
    function(gens,G)
    local s;
    s := Iterated(gens, FGA_InsertGeneratorLetterRep, FGA_newstate());
    return Objectify( NewType( FamilyObj( G ),
                      IsSimpleInvAutomatonRep and IsMutable),
                      rec(initial:=s, terminal:=s, group:=G) );
    end );

   
InstallGlobalFunction( FGA_Check,
    function(s, w)
    return IsIdenticalObj(FGA_deltas(s, w), s);
   end );

InstallGlobalFunction( FGA_FindGeneratorsAndStates,
    function(A)
    local Q, Gens, nq, q, i, nr, freegens;
    q := A!.initial;
    nr := 0;
    Gens := [];
    q.repr := [];
    Q := [q];
    for nq in Q do
        freegens := [];
        nr := nr + 1;
        nq.nr := nr;
        for i in BoundPositions(nq.delta) do
            q := nq.delta[i];
            if IsBound(q.repr) then
                if nq.repr = [] or nq.repr[Length(nq.repr)] <> -i then
                    Add(Gens, Concatenation(nq.repr, [i], -Reversed(q.repr)));
                    freegens[i] := Length(Gens);
                fi;
            else
                q.repr := ShallowCopy(nq.repr);
                Add(q.repr, i);
                Add(Q, q);
            fi;
        od;
        for i in BoundPositions(nq.deltainv) do
            q := nq.deltainv[i];
            if not(IsBound(q.repr)) then
                q.repr := ShallowCopy(nq.repr);
                Add(q.repr, -i);
                Add(Q, q);
            fi;
        od;
        if freegens <> [] then
            nq.freegens := freegens;
        fi;
    od;
    ###
    A!.states := Q;
    A!.genslr := Gens;
    end );

InstallGlobalFunction( FGA_initial,
    A -> A!.initial );

InstallGlobalFunction( FGA_repr,
    state -> state.repr );

InstallGlobalFunction( FGA_GeneratorsLetterRep,
    function(A)
    if not IsBound( A!.genslr ) then
        FGA_FindGeneratorsAndStates(A);
    fi;
    return A!.genslr;
    end );

InstallGlobalFunction( FGA_States,
    function(A)
    if not IsBound( A!.states ) then
        FGA_FindGeneratorsAndStates(A);
    fi;
    return A!.states;
    end );
 
InstallGlobalFunction( FGA_reducedPos,
    function(A)
    local i, states, n;
    i := 0;
    states := FGA_States(A);
    repeat
        i := i+1;
        n := Size(BoundPositions(states[i].delta)) +
             Size(BoundPositions(states[i].deltainv));
    until n > 2 or ( n=2 and i=1);
    return i;
    end );

InstallGlobalFunction( FGA_Index,
    function(A)
    local states, r;
    states := FGA_States(A);
    r := Size(FreeGeneratorsOfWholeGroup(A!.group));
    if ForAny( List( states, s -> s.delta),
               delta -> not IsDenseList(delta) or Size(delta) <> r ) then
        return infinity;
    fi;
    return Size(states);
    end );

InstallGlobalFunction( FGA_AsWordLetterRepInFreeGenerators,
    function(g,A)
    local s,x,f,w;
    FGA_States(A); # do work in the automaton if needed
    w := [];
    s := A!.initial;
    for x in g do
        if x > 0 then
            if IsBound(s.freegens) and IsBound(s.freegens[x]) then
                Add(w, s.freegens[x]);
            fi;
            s := ATf(s.delta, x);
            if s = fail then
                return fail;
            fi;
        else
            s := ATf(s.deltainv, -x);
            if s=fail then
                return fail;
            fi;
            if IsBound(s.freegens) and IsBound(s.freegens[-x]) then
                Add(w, -s.freegens[-x]);
            fi;
        fi;
    od;

    if IsNotIdenticalObj( s, A!.terminal ) then
        return fail;
    fi;

    return w;
    end );


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

[ Dauer der Verarbeitung: 0.25 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