############################################################################ ## #W aut-basics.gi Manuel Delgado <mdelgado@fc.up.pt> #W Jose Morais <josejoao@fc.up.pt> ## ## #Y Copyright (C) 2004, CMUP, Universidade do Porto, Portugal ## ############################################################################# ## ## This file contains some basic functions or generic methods involving ## automata. ## ############################################################################# ## #F IsDeterministicAutomaton(A) ## ## Tests if A is a deterministic automaton ##
InstallGlobalFunction(IsDeterministicAutomaton, function(A)
return IsAutomatonObj(A) and A!.type = "det"; end); ############################################################################# ## #F IsNonDeterministicAutomaton(A) ## ## Tests if A is a non deterministic automaton ##
InstallGlobalFunction(IsNonDeterministicAutomaton, function(A)
return IsAutomatonObj(A) and A!.type = "nondet"; end); ############################################################################# ## #F IsEpsilonAutomaton(A) ## ## Tests if A is an automaton with epsilon transitions ##
InstallGlobalFunction(IsEpsilonAutomaton, function(A)
return IsAutomatonObj(A) and A!.type = "epsilon"; end); ############################################################################# ## #F AlphabetOfAutomaton(A) ## ## Returns the number of symbols in the alphabet of the automaton ##
InstallGlobalFunction(AlphabetOfAutomaton, function( A ) if not IsAutomaton(A) then
Error("The argument must be an automaton"); fi;
return(ShallowCopy(A!.alphabet)); end); ############################################################################# ## #F AlphabetOfAutomatonAsList(A) ## ## Returns the alphabet of the automaton as a list. ## ## Note that when the alphabet of the automaton is given as an integer ## (meaning the number of symbols) less than 27 it returns the list "abcd....". ## If the alphabet is given by means of an integer greater than 27, the ## function returns [ "a1", "a2", "a3", "a4", ... ]. ##
InstallGlobalFunction(AlphabetOfAutomatonAsList, function( A )
local a; if not IsAutomaton(A) then
Error("The argument must be an automaton"); fi;
return(ShallowCopy(FamilyObj(A)!.alphabet)); end); ############################################################################# ## #F TransitionMatrixOfAutomaton(A) ## ## returns the transition matrix of the automaton ##
InstallGlobalFunction(TransitionMatrixOfAutomaton, function( A ) if not IsAutomaton(A) then
Error("The argument must be an automaton"); fi;
return(A!.transitions); end); ############################################################################# ## #F InitialStatesOfAutomaton(A) ## ## returns the initial states of the automaton ##
InstallGlobalFunction(InitialStatesOfAutomaton, function( A ) if not IsAutomaton(A) then
Error("The argument must be an automaton"); fi;
return(ShallowCopy(A!.initial)); end); ############################################################################# ## #F SetInitialStatesOfAutomaton(A) ## ## Sets the initial states of the automaton ##
InstallGlobalFunction(SetInitialStatesOfAutomaton, function( A, I ) if not IsAutomaton(A) then
Error("The first argument must be an automaton"); fi; if IsInt(I) then if not (I > 0 and I <= A!.states) then
Error("The second argument must be a list of positive integers (or just a positive integer) <= ", A!.states); fi;
A!.initial := [I];
return; fi; if not (IsList(I) and ForAll(I, i->IsPosInt(i)) and ForAll(I, i-> i <= A!.states)) then
Error("The second argument must be a list of positive integers (or just a positive integer) <= ", A!.states); fi;
A!.initial := ShallowCopy(I); end); ############################################################################# ## #F FinalStatesOfAutomaton(A) ## ## returns the final states of the automaton ##
InstallGlobalFunction(FinalStatesOfAutomaton, function( A ) if not IsAutomaton(A) then
Error("The argument must be an automaton"); fi;
return(ShallowCopy(A!.accepting)); end); ############################################################################# ## #F SetFinalStatesOfAutomaton(A, F) ## ## Sets the final states of the automaton ##
InstallGlobalFunction(SetFinalStatesOfAutomaton, function( A, F ) if not IsAutomaton(A) then
Error("The first argument must be an automaton"); fi; if IsInt(F) then if not (F > 0 and F <= A!.states) then
Error("The second argument must be a list of positive integers (or just a positive integer) <= ", A!.states); fi;
A!.accepting := [F];
return; fi; if not (IsList(F) and ForAll(F, i->IsPosInt(i)) and ForAll(F, i-> i <= A!.states)) then
Error("The second argument must be a list of positive integers <= ", A!.states); fi;
A!.accepting := ShallowCopy(F); end); ############################################################################# ## #A NumberStatesOfAutomaton(A) ## ## returns the number of states of the automaton ##
InstallGlobalFunction(NumberStatesOfAutomaton, function( A ) if not IsAutomaton(A) then
Error("The argument must be an automaton"); fi;
return(A!.states); end);
############################################################################# ## #F CopyAutomaton(A) ## ## Returns a copy of the automaton A. ##
InstallGlobalFunction(CopyAutomaton, function ( A ) if not IsAutomatonObj(A) then
Error("The argument must be an automaton"); fi;
return Automaton( ShallowCopy( A!.type ), A!.states,
AlphabetOfAutomatonAsList(A), StructuralCopy( A!.transitions ),
ShallowCopy( A!.initial ),
ShallowCopy( A!.accepting ) ); end);
############################################################################# ## #F NullCompletionAutomaton(aut) ## ## Given an incomplete deterministic automaton returns a deterministic ## automaton completed with a new null state. ##
InstallGlobalFunction(NullCompletionAutomaton, function(aut)
local t, b, i, j;
if not IsAutomatonObj(aut) then
Error("The argument must be an automaton"); fi; if not aut!.type = "det"then
Error("<aut> must be deterministic"); fi;
t := []; if IsDenseAutomaton(aut) then
return aut; fi;
b := aut!.states + 1; for i in [1 .. aut!.alphabet] do
t[i] := Concatenation(aut!.transitions[i], [b]); for j in [1 .. b] do if t[i][j] = 0then
t[i][j] := b; fi;
od;
od;
return Automaton("det", b, AlphabetOfAutomatonAsList(aut), t, aut!.initial, aut!.accepting); end);
############################################################################# ## #F ListPermutedAutomata(A) ## ## Given an automaton, returns a list of automata with permuted states ##
InstallGlobalFunction(ListPermutedAutomata, function(A)
local perms, # List of permutations
perm, # Permutation
T, # Transition function of the permuted automaton
list, # List of the permuted automata
a, q;
if not IsAutomatonObj(A) then
Print("The argument to PermutedAutomata must be an automaton\n");
return; fi; if A!.type = "epsilon"then
list := []; # List of the permuted automata
perms := PermutationsOfN(A!.states); # Compute the list of permutations for perm in perms do# For each permutation compute the permuted automaton
T := []; # New transition function for a in [1 .. A!.alphabet] do
T[a] := []; for q in [1 .. A!.states] do if A!.transitions[a][q] = [] then
T[a][perm[q]] := []; else
T[a][perm[q]] := List(A!.transitions[a][q], s -> perm[s]); fi;
od;
od;
Add(list, Automaton("epsilon", A!.states, AlphabetOfAutomatonAsList(A), T, List(A!.initial, q -> perm[q]), List(A!.accepting, q -> perm[q])));
od; elif A!.type = "nondet"then
list := []; # List of the permuted automata
perms := PermutationsOfN(A!.states); # Compute the list of permutations for perm in perms do# For each permutation compute the permuted automaton
T := []; # New transition function for a in [1 .. A!.alphabet] do
T[a] := []; for q in [1 .. A!.states] do if A!.transitions[a][q] = [] then
T[a][perm[q]] := []; else
T[a][perm[q]] := List(A!.transitions[a][q], s -> perm[s]); fi;
od;
od;
Add(list, Automaton("nondet", A!.states, AlphabetOfAutomatonAsList(A), T, List(A!.initial, q -> perm[q]), List(A!.accepting, q -> perm[q])));
od; else
list := []; # List of the permuted automata
perms := PermutationsOfN(A!.states); # Compute the list of permutations for perm in perms do# For each permutation compute the permuted automaton
T := []; # New transition function for a in [1 .. A!.alphabet] do
T[a] := []; for q in [1 .. A!.states] do if A!.transitions[a][q] = 0then
T[a][perm[q]] := 0; else
T[a][perm[q]] := perm[A!.transitions[a][q]]; fi;
od;
od;
Add(list, Automaton("det", A!.states, AlphabetOfAutomatonAsList(A), T, [perm[A!.initial[1]]], List(A!.accepting, q -> perm[q])));
od; fi;
return(list); end);
############################################################################# ## #F PermutedAutomaton(A, perm) ## ## Given an automaton and a list representing a permutation of the states ## outputs the permuted automaton. ##
InstallGlobalFunction(PermutedAutomaton fi;
len list T,aq
if (A then
Print("The )
return; fi; if not (A!.states = Length(perm) and Set(perm) = [1 .. A!.states]) then
Error("The list must represent a permutation of the states of the automaton fi; fi;
len := 0;
list:=[]
T := []; # New transition function if A!.type="et then for a in [1 .. A!.alphabet fi;
[a]: [; for q in Print(The haslessthan one "; if A!.transitions[a][q] = 0
T[a][perm[q]] := 0; else
T[a][perm[q]] := perm[A!.transitions[a][q]]; fi;
od;
od;
return(Automaton("det", A!.states, AlphabetOfAutomatonAsList(A), T, [perm[A!.initial[1]]], List(A!.accepting, q -> perm[q]))); elif A!.type = "nondet"then for a in [1 .. A!.alphabet] do
T[a] := []; for q in [1 .. A!.states] do if A!.transitions[a][q] = [] then
T[a][perm[q]] := []; else
T[a][perm[q]] := List fi;
od;
;
return(Automaton("nondet", A ifLength(!a[]>1then else for a in [1 .. A!.alphabet fijava.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
T[a] := [];
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 5 if A!.transitions[a]
T[a][perm[q]] := []; else
T[a############################################################################# fi;
od;
od;
return(Automaton("epsilon", A!.states## returns an automaton that recognizes the concatenation of the given fi;
end## <M>u</M> belongs to the first language and <M>v</M>
############################################################################# ## #F IsDenseAutomaton(A) ## ## Tests whether a deterministic automaton is complete ##
InstallGlobalFunction(IsDenseAutomaton, function(A)
local n;
if not IsDeterministicAutomaton(A) then
Error("<A> must be a deterministic automaton"); fi;
return(ForAll(A!.transitions, n -> IsDenseList(n) and
ForAll(n,IsPosInt))); end); ############################################################################# ## #F IsInverseAutomaton ## ## Tests whether a deterministic automaton is inverse, i.e. each letter of ## the alphabet induces a partial injective function on the vertices. ##
InstallGlobalFunction(IsInverseAutomaton,function(aut)
local T, L, i;
if not IsDeterministicAutomaton(aut) then
Error("<A> must be a deterministic automaton"); fi;
T := StructuralCopy(aut!.transitions); for L in T do for i in [1..Length(L)] do if L[] = 0then
Unbind(L[i]); fi;
od; if Length(
return false ifIsAutomaton(1then fi;
od;
return true; end); ############################################################################# ## #F IsPermutationAutomaton ## ## Tests whether a deterministic automaton is a permutation automaton, ## i.e. each letter of the alphabet induces a permutation on the vertices. ##
local T, L, i;
if not IsDeterministicAutomaton(aut) then
Error("<A> must be a deterministic automaton"); fi;
T := StructuralCopy(aut!.transitions); for L in T do for i in [1..Length(L)] do if L[i] = 0then
return false; fi;
od; if aut!.states <> Length(Set(L fi;
returnfalse; fi;
od;
return true; end);
############################################################################# #F ListSinkStatesAut(A) ## ## Returns the list of sink states of the automaton A. ## q is said to be a sink state iff it is not initial nor accepting and ## for all a in A!.alphabet A!.transitions[a][q] = q ## ## <A> must be an automaton. ## ##
InstallGlobalFunctionjava.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 52
local list, j;
if not IsAutomatonObj(A) then
Error("The argument to ListSinkStatesAut must be an automaton"); fijava.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7 fi if A!.type = "det"then fora1: RemovedSinkStatesa1;
a2 = RemovedSinkStatesa2);
Add(list, j); fi;
od; elif A.ype nondet" for j in [1 .. A!java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if ForAll([1 .. A!.alphabet], i -> A!for in[.a2!states java.lang.StringIndexOutOfBoundsException: Range [35, 36) out of bounds for length 35
Add(list, j); fi;
od; else
return(ListSinkStatesAut(EpsilonToNFA(A))); fi;
list := Difference(list, Add(T[a], [a2![]q .tates)java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
list := Difference(list, od
return(list); end);
############################################################################# ## #F RemovedSinkStates(A) ## ## Removes the sink states of the automaton A ##
InstallGlobalFunction(RemovedSinkStates, function(A) for sin !initial
transitions, ([1!alphabet +]q] !. +)java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
if not
Error("The A := Automaton("epsilon .states +a2. fi;
aut := CopyAutomaton(A);
ls !alphabet+1,
initial_states := java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 19
final_states = Intersectionaut. );
new_ini := List(initial_states, s -> Position(ls, s));
new_fin := List(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
transitions := aut!.transitions; # the transition matrix of the original automaton: RemovedSinkStates)java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
Al := aut!.alphabet;
: FamilyObjaut).;
n_states := Length(ls); # the number of states of the subautomaton
=NullMat(,n_states;#thetransitionmatrixof the subautomaton for p in [1 .. n_states] do# for each new state p for a
if q java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 0
matrix[a][p] := Position(ls, q); # the edge belongs to the subautomaton, so add it fi;
od;
od;
return Automaton("det", n_states, alph, matrix, new_ini, new_fin); end);
############################################################################# ## #F IsRecognizedByAutomaton(A, word, alphabet) ## ## Tests if a given word is recognized by the given automaton ##
InstallGlobalFunction(IsRecognizedByAutomaton, function(arg)
local A, w, alph, a, s, c;
if Length(arg) < 2then
Error("Please supply an automaton and a string"); fi; if not IsAutomatonObj(arg[1]) then
Error("The first argument must be an automaton"); fi; if not IsList(arg[2]) then
Error("The second argument must be a list"); fi;
A := MinimalAutomaton(arg[1]);
w := arg[2];
alph := AlphabetOfAutomatonAsList(A); # if IsList(alph) then for a in w do if not a in alph then
Error("....");
return(false);
Error(".."); fi;
od; # else # if alph < 22 then # alph := "abcdefghijklmnopqrstu"; # else # alph := List([1..alph], k -> Concatenation("a", String(k))); # fi; # fi; #
s := A!.initial[1]; for c in w do
a := Position(alph, c); if a = 0 or a > A!.alphabet then
return(false); fi;
s := A!.transitions[a][s];
od; if s in A!.accepting then
return(true); else
return(false); fi; end);
############################################################################# ## #F NormalizedAutomaton(A) ## ## Returns the equivalent automaton but the initial state is numbered 1 ## and the final states have the last numbers ##
InstallGlobalFunction(NormalizedAutomaton, function(A)
local comp_list, q, p, r, X, n, s, j;
if not IsAutomaton(A) then
Error("The argument must be a deterministic automaton"); fi; if not IsDeterministicAutomaton(A) then
Error("The argument must be a deterministic automaton"); fi;
comp_list := function(ls, re)# auxiliary function # ls is a list with holes with length q; # re is a list # with as many elements as the holes in ls # which may occur at the end of the list
local h, k, i;
h := Filtered([1 .. q], n -> not IsBound(ls[n]));
k := 1; for i in h do
ls[i] := re[k];
Unbind(re[k]);
k := k + 1;
od;
ls := Concatenation(ls,Compacted(re));
return ls; end;
q := A!.states;
p := [];
r := A!.initial[1];
X := ShallowCopy(A!.accepting);
X := Difference(X, A!.initial);
n := Length(X);
s := Difference(Difference([1 .. q], A!.initial), A!.accepting);
p[r] := 1; for j in [1 .. n] do
p[X[j]] := q - n +j;
od;
s := [2..q-n];
return(PermutedAutomaton(A, comp_list(p, s))); end);
############################################################################# ## #F UnionAutomata(A, B) ## ## Produces the disjoint union of the automata A and B ##
InstallGlobalFunction(UnionAutomata, function(A, B)
local QA, T, a, i, I, F, mA,mB;
if not (IsAutomatonObj( A ) and IsAutomatonObj( B )) then
Error( "The arguments must be two automata" ); fi;
if A!.type = "epsilon"then
mA := AlphabetOfAutomaton(A)-1; else
mA := AlphabetOfAutomaton(A); fi; if B!.type = "epsilon"then
mB := AlphabetOfAutomaton(B)-1; else
mB := AlphabetOfAutomaton(B); fi; if mA <> mB then
Error( "The arguments must be two automata over the same alphabet" ); fi;
QA := A!.states;
T := List( A!.transitions, ShallowCopy ); if A!.type <> "epsilon" and B!.type = "epsilon"then
Add(T,[]); fi;
for a in [ 1 .. B!.alphabet ] do for i in [ 1 .. B!.states ] do if B!.transitions[a][i] = 0then
T[a][QA + i] := 0; else
T[a][QA + i] := QA + B!.transitions[a][i]; fi;
od;
od; if A!.type = "epsilon" and B!.type <> "epsilon"then for i in [1..B!.states] do
Add(T[mA+1],0);
od; fi;
I := ShallowCopy( A!.initial );
Append( I, QA + B!.initial );
if A!.type = "epsilon" or B!.type = "epsilon"then
return Automaton( "epsilon", QA + B!.states, mA+1, T, I, F ); else
return Automaton( "nondet", QA + B!.states, AlphabetOfAutomatonAsList( A ), T, I, F ); fi; end );
############################################################################# ## #F ReversedAutomaton(A) ## ## Returns the automaton obtained from A by reversing its edges and ## switching the accepting and initial states ##
InstallGlobalFunction(ReversedAutomaton, function(A)
local T, a, q, s, u;
if not IsAutomatonObj(A) then
Error("The argument must be an automaton"); fi;
T := []; for a in [1 .. A!.alphabet] do
T[a] := []; for q in [1 .. A!.states] do
T[a][q] := [];
od;
od; for a in [1 .. A!.alphabet] do for q in [1 .. A!.states] do
s := A!.transitions[a][q]; if IsList(s) then for u in s do if IsPosInt(u) then
Add(T[a][u], q); fi;
od; elif IsPosInt(s) then
Add(T[a][s], q); fi;
od;
od;
return(Automaton("nondet", A!.states, AlphabetOfAutomatonAsList(A), T, ShallowCopy(A!.accepting), ShallowCopy(A!.initial))); end);
############################################################################# ## #F IsReversibleAutomaton(A) ## ## Tests if the given automaton is reversible in the sense ## that the reversed automaton might be regarded as deterministic ## automaton ##
InstallGlobalFunction(IsReversibleAutomaton, function(A)
local B, a, q;
if not IsAutomatonObj(A) then
Error("The argument must be an automaton"); fi; if not A!.type = "det"then
Print("The automaton is not deterministic");
return(false); fi; if Length(A!.accepting) > 1then
Print("The automaton has more than one accepting state");
return(false); fi; if Length(A!.accepting) < 1then
Print("The automaton has less than one accepting state");
return(false); fi;
B := ReversedAutomaton(A); for a in [1 .. B!.alphabet] do for q in [1 .. B!.states] do if Length(B!.transitions[a][q]) > 1then
return(false); fi;
od;
od;
return(true); end);
############################################################################# ## #F ProductOfLanguages(a1, a2) ## ## Given two regular languages (as automata or rational expressions), ## returns an automaton that recognizes the concatenation of the given ## languages, that is, the set of words <M>uv</M> such that ## <M>u</M> belongs to the first language and <M>v</M> ## belongs to the second language. ##
InstallGlobalFunction(ProductOfLanguages, function(a1, a2)
local T, a, q, s, A;
if IsAutomaton(a1) then
a1 := MinimalAutomaton(a1); elif IsRationalExpression(a1) then
a1 := RatExpToAut(a1); else
Error("The first argument must be an automaton or a rational expression"); fi; if IsAutomaton(a2) then
a2 := MinimalAutomaton(a2); elif IsRationalExpression(a2) then
a2 := RatExpToAut(a2); else
Error("The second argument must be an automaton or a rational expression"); fi;
if not AlphabetOfAutomatonAsList(a1) = AlphabetOfAutomatonAsList(a2) then
Error("A1 and A2 must have the same alphabet"); fi;
T := List(a1!.transitions, l -> List(l, q -> [q]));
for a in [1..a2!.alphabet] do for q in [1..a2!.states] do if a2!.transitions[a][q] = 0then
Add(T[a], []); else
Add(T[a], [a2!.transitions[a][q] + a1!.states]); fi;
od;
od;
Add(T, List([1..a1!.states+a2!.states], i -> []));
for q in a1!.accepting do for s in a2!.initial do
Add(T[a1!.alphabet + 1][q], a1!.states + s);
od;
od;
A := MinimalAutomaton(A);
A := RemovedSinkStates(A);
FamilyObj(A)!.alphabet := AlphabetOfAutomatonAsList(a1);
return(A); end);
#E
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.10Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.