Niedeterministyczne automaty skończone

Wstęp

W poprzednim wykładzie poznaliśmy deterministyczne automaty skończone. Czym jednak jest ów determinizm? Determinizm to koncepcja filozoficzna, według której w Świecie nie ma miejsca na przypadek -- gdyby mieć pełną informację o stanie świata, można by przewidzieć jego przyszłość. W determinizmie brak też miejsca na wolną wolę -- nasze decyzje są określone przez stan Świata, którego jesteśmy częścią.

Niedeterminizm stanowi przeciwną koncepcję. Nawet gdybyśmy mieli pełną wiedzę na temat stanu Świata w danej chwili, to i tak nie bylibyśmy w stanie przewidzieć przyszłości. Co najwyżej moglibyśmy określić jakie są możliwe przyszłe dzieje.

W informatyce determinizm oznacza, że jeżeli będziemy wielokrotnie uruchamiać ten sam program czy mechanizm obliczeniowy, podając te same dane, to zawsze uzyskamy te same wyniki. Niedeterminizm zaś przeciwnie -- dla tych samych danych możemy uzyskać różne wyniki. Prostych programy komputerowe (bez randomizacji) zwykle działają w sposób deterministyczny. Niedeterminizm pojawia się np. w algorytmach randomizacyjnych czy programowaniu współbieżnym, czyli tam, gdzie jest jakieś źródło przypadkowości. Wówczas zwykle wymagamy, aby bez względu na przebieg obliczeń była zachowana jakaś wymagana przez nas własność. Niedeterminizm jest też używany przy specyfikowaniu systemów -- specyfikacja nie określa jednoznacznie jak powinien zachowywać się system, każde zachowanie zgodne ze specyfikacją jest dopuszczalne.

Automat niedeterministyczny jest więc automatem, którego działania nie da się w pełni przewidzieć. Będąc w tym samym stanie i wczytując ten sam znak może wykonać różne przejścia. Przestaje więc obowiązywać wymóg, że dla danego znaku, z każdego stanu wychodzi dokładnie jedno przejście odpowiadające wczytaniu tego znaku. Takich przejść może być dowolnie wiele, a nawet może ich nie być wcale (co to znaczy wyjaśni się za chwilę). Automat taki może również mieć wiele stanów początkowych -- każde uruchomienie automatu może rozpocząć się w dowolnym z tych stanów.

Może więc się zdarzyć, że ten sam automat raz zaakceptuje dane słowo, a raz nie. Czy więc takie słowo należy do języka akceptowanego przez automat, czy nie? Otóż, jeśli tylko automat może zaakceptować słowo, to powiemy, że należy ono do języka akceptowanego przez automat. Jest to dosyć nietypowa interpretacja niedeterminizmu. Nie odpowiada ona intuicyjnemu rozumieniu przypadku.

Na taki niedeterministyczny automat możemy spojrzeć jak na mechanizm o dwoistej budowie: jedna jego część to automat skończony określający jakie przejścia są możliwe, druga część, to tzw. wyrocznia, która w przypadku wielu możliwych do wykonania przejść wybiera przejście, które prowadzi do zaakceptowania słowa. (Zapachniało metafizyką? Chwila cierpliwości, zaraz wszystko będzie ściśle zdefiniowane.) Jedno z zagadnień, którymi się zajmiemy, to czy taka wyrocznia zmienia siłę obliczeniową automatów, czyli czy dla tych samych języków potrafimy zbudować automaty deterministyczne i nie, czy też są jakieś różnice? Jak się okaże, w przypadku automatów skończonych nie ma żadnej różnicy, a wyrocznię i niedeterminizm można zastąpić większą liczbą stanów.

Działanie niedeterministycznych automatów skończonych

Jak już powiedzieliśmy, w automacie niedeterministycznym, dla danego znaku, nie musi z każdego stanu wychodzi dokładnie jedno przejście odpowiadające wczytaniu tego znaku. Takich przejść może nie być, może być jedno, lub może być wiele. Podobnie, automat niedeterministyczny może mieć wiele stanów początkowych.

Działanie automatu niedeterministycznego możemy symulować w następujący sposób. Spójrzmy na diagram automatu jak na planszę, po której będziemy przesuwać pionki -- stany to pola, na których będziemy stawiać pionki, a przesuwać będziemy je zgodnie z przejściami.

  1. Na początku symulacji ustawiamy pionki we wszystkich stanach początkowych.
  2. Wczytując pojedynczy znak przesuwamy zgodnie z przejściami wszystkie pionki na planszy. Przy czym, jeżeli z pola, na którym stoi pionek wychodzi wiele przejść odpowiadających wczytanemu znakowi, to stawiamy pionki na wszystkich polach docelowych. W szczególności, jeżeli z pola, na którym stoi pionek nie wychodzi żadne takie przejście, to taki pionek zdejmujemy z planszy. Jeżeli na jednym polu znajdzie się kilka pionków, to zostawiamy jeden, a resztę zdejmujemy.
  3. Automat akceptuje słowo jeśli po wczytaniu całego słowa w którymkolwiek z pól/stanów akceptujących znajduje się pionek.
Pionki reprezentują wszystkie te stany, w których automat może się znaleźć po wczytaniu odpowiedniego (prefiksu) słowa. Automat akceptuje słowo jeśli choć jeden pionek dotrze do stanu akceptującego, czyli może się zdarzyć takie obliczenie, które prowadzi do jego zaakceptowania.

Przykład

Oto automat niedeterministyczny, który akceptuje te słowa nad alfabetem {a,b}, w których przedostatni znak to a. Obok przedstawiono dla porównania deterministyczny automat skończony akceptujący taki sam język. Automat deterministyczny musi pamiętać ostatnie dwa znaki wczytywanego słowa -- dlatego też ma cztery stany.
automat 0 1 2 3 4 5 6 7 8 9 10
 

Definicja

Automat niedeterministyczny, to dowolna taka piątka $M = \angles{Q, \Sigma, \delta, S, F}$, gdzie:

Definicja

Rozszerzenie funkcji przejścia $\delta^*: 2^Q \times \Sigma^* \to 2^Q$ definiujemy następująco:

\begin{displaymath}
\delta^*(A, \varepsilon) = A
\end{displaymath}


\begin{displaymath}
\delta^*(A, ax) = \delta^*(\bigcup_{q \in A} \delta(q, a), x)
\end{displaymath}

Funkcja $\delta^*$ zamiast na pojedynczych stanach operuje na zbiorach stanów. Dokładnie, opisuje ona jak zmienia się ustawienie pionków pod wpływem wczytywanych słów.

Definicja

Niedeterministyczny automat skończony $M = \angles{Q, \Sigma, \delta, S, F}$ akceptuje słowo x wtw., gdy $\delta^* (S, x) \setint F \neq \emptyset$. Język akceptowany przez automat M, to:

\begin{displaymath}
L(M) =
\{x \in \Sigma^* : \delta^*(S, x) \setint F \neq \emptyset\}
\end{displaymath}

Formalnie automaty niedeterministyczne są czymś innym niż deterministyczne. Jednak my będziemy traktować automaty deterministyczne jak szczególny przypadek automatów niedeterministycznych. Patrząc na diagramy reprezentujące automaty, automaty deterministyczne muszą spełnić więcej wymagań niż automaty niedeterministyczne. Następujący fakt utwierdza nas w takim spojrzeniu:


\begin{fact}
Niech $M = \angles{Q, \Sigma, \delta, s, F}$\ będzie
automatem de...
...\{\delta(q,a)\}$
akceptuje dokładnie ten sam język, $L(M) = L(M')$.
\end{fact}

Kilka własności funkcji $\delta^*$, które przydadzą nam się w dalszej części wykładu:


\begin{fact}
Dla dowolnych $x, y \in \Sigma^*$\ mamy
$\delta^*(A, xy) = \delta^*(\delta^*(A, x), y)$.
\end{fact}
Dowód przebiega przez indukcję ze względu na |y|.


\begin{fact}
Funkcja $\delta^*$\ jest rozłączna ze względu na sumowanie
zbioró...
...a^*(\bigcup_i A_i, x) = \bigcup_i \delta^*(A_i, x)
\end{displaymath} \end{fact}
Dowód przebiega przez indukcję ze względu na |x|.

Determinizacja automatów skończonych

Pokażemy teraz, że siła wyrazu automatów niedeterministycznych jest dokładnie taka sama, jak deterministycznych. W tym celu musimy pokazać, że dla każdego niedeterministycznego automatu skończonego istnieje równoważny mu automat deterministyczny. To, że automaty deterministyczne możemy traktować jak szczególny przypadek automatów niedeterministycznych powiedzieliśmy już wcześniej.

W trakcie symulacji działania automatu niedeterministycznego istotny jest zbiór pól, na których w danym momencie znajdują się pionki. Nasza konstrukcja będzie polegała na zbudowaniu automatu deterministycznego, którego stanami będą zbiory stanów automatu niedeterministycznego (mogące się pojawić w czasie symulacji), jego stanem początkowym będzie zbiór stanów początkowych automatu niedeterministycznego, a akceptujące będą te stany, które zawierają choć jeden stan akceptujący automatu niedeterministycznego.

Konstruując automat deterministyczny liczba stanów może wzrosnąć nawet wykładniczo. Jednak nie zawsze tak musi być, gdyż nie zawsze wszystkie możliwe zbiory stanów automatu niedeterministycznego mogą się pojawić w czasie symulacji. Zobaczmy kilka przykładów.

Przykład

Przypomnijmy sobie automat niedeterministyczny akceptujący słowa nad alfabetem {a,b}, w których przedostatni znak to a. W trakcie dowolnego obliczenia, na polu początkowym nr 1 będzie cały czas stał pionek. Tak więc mogą się pojawić cztery różne konfiguracje pionków (czy też cztery różne zbiory pól zajmowanych przez pionki). Ponieważ konfiguracje nieosiągalne nie mają znaczenia dla działania automatu, możemy się ograniczyć się do tych czterech konfiguracji. Odpowiada to automatowi zapamiętującemu dwa ostatnie znaki w słowie.
automat 0 1 2 3 4 5 6 7 8 9 10
 

Przykład

Automat przedstawiony na poniższym rysunku akceptuje słowa (nad alfabetem {a}) o długości podzielnej przez 2 lub 3. Jedyny niedeterminizm polega tu na wybraniu stanu początkowego. Automat deterministyczny ma 6 stanów.
automat 0 1 2 3 4 5 6 7 8 9 10
 

Konstruowany automat deterministyczny, równoważny automatowi niedeterministycznemu, jest nazywany automatem potęgowym -- gdyż jego zbiór stanów to zbiór potęgowy zbioru stanów automatu niedeterministycznego. Formalnie, jego konstrukcja przebiega następująco.


Konstrukcja automatu potęgowego

Niech $M = \angles{Q, \Sigma, \delta, S, F}$ będzie niedeterministycznym automatem skończonym. Jego determinizacją będziemy nazywać automat deterministyczny $M' = \angles{2^Q, \Sigma, \delta', S, F'}$, gdzie:

\begin{displaymath}
\delta'(A, a) =\delta^*(A, a)
\end{displaymath}


\begin{displaymath}
F' = \{ A \subseteq Q : A \setint F \neq \emptyset \}
\end{displaymath}

Pokażemy, że oba automaty akceptują te same języki.


\begin{lemma}
Dla dowolnych $A \subseteq Q$\ i $x \in \Sigma^*$\ zachodzi
\begin{displaymath}
\delta^* (A, x) = \delta'^*(A, x)
\end{displaymath} \end{lemma}

Dowód:

Dowód przebiega przez indukcja ze względu na |x|.
  1. $\delta^* (A, \varepsilon) = A = \delta'^*(A, \varepsilon)$,
  2. Załóżmy, że lemat zachodzi dla słowa x. Pokażemy, że zachodzi również dla słowa postaci ax:

    \begin{displaymath}
\delta^* (A, ax) =
\delta^*(\delta^*(A, a), x) =
\delta^*(\delta'(A, a), x) =
\delta^*(\delta'^*(A, a), x)
\end{displaymath}

    Z założenia indukcyjnego:

    \begin{displaymath}
\delta^*(\delta'^*(A, a), x) =
\delta'^*(\delta'^*(A, a), x) =
\delta'^*(A, ax)
\end{displaymath}

\qed

Korzystając z lematu, dowód, że jest natychmiastowy:

\begin{eqnarray*}
L(M) &=&
\{x \in \Sigma^* : \delta^*(S, x) \setint F \neq \...
...\\
&=& \{x \in \Sigma^* : \delta'^*(S, x) \in F' \} =
L(M')
\end{eqnarray*}


W tak skonstruowanym automacie potęgowym możemy, bez zmiany akceptowanego przez niego języka, usunąć wszystkie stany nieosiągalne.

Automaty z $\varepsilon$-przejściami

Automaty z $\varepsilon$-przejściami stanowią rozszerzenie automatów niedeterministycznych. Mogą one dodatkowo zawierać tzw. $\varepsilon$-przejścia. Są to przejścia, które automat może w każdej chwili wykonywać, nie wczytując nic z wejścia. Tak więc automat z $\varepsilon$-przejściami nie musi w każdym kroku wczytywać jednego znaku.

Podobnie, jak automaty deterministyczne stanowią szczególny przypadek automatów niedeterministycznych, tak automaty niedeterministyczne stanowią szczególny przypadek automatów z $\varepsilon$-przejściami -- są to automaty z $\varepsilon$-przejściami, w których nie ma $\varepsilon$-przejść.

Okazuje się, że automaty z $\varepsilon$-przejściami mają taką samą siłę wyrazu co automaty niedeterministyczne. Czasami jednak $\varepsilon$-przejścia pozwalają uprościć budowę automatu.

Przykład

Poniższy rysunek przedstawia automat z $\varepsilon$-przejściami akceptujący język a*b*c*. Poniżej przedstawiono dwa równoważne mu automaty niedeterministyczne. Jak widać, $\varepsilon$-przejścia można usunąć zachowując ten sam zbiór stanów, ale kosztem zwiększenia liczby przejść oraz większej liczby stanów początkowych lub akceptujących.
automat 0 1 2 3 4 5 6 7 8 9 10
 

Definicja

Automat z $\varepsilon$-przejściami, to dowolna taka piątka $M = \angles{Q, \Sigma, \delta, S, F}$, w której:
Jak widać, jedyna różnica między definicją automatu niedeterministycznego i $\varepsilon$-przejściami polega na dodatkowej etykiecie jaka może towarzyszyć przejściom: $\varepsilon$. Zobaczmy jak definiujemy wpływ $\varepsilon$-przejść na działanie automatów:

Definicja

Niech A będzie zbiorem stanów, $A \subseteq Q$. Przez D(A) oznaczamy zbiór stanów, które można osiągnąć z A poprzez $\varepsilon$-przejścia.

Rozszerzenie funkcji przejścia $\delta^*: 2^Q \times \Sigma^* \to 2^Q$ definiujemy następująco:

\begin{displaymath}
\delta^*(A, \varepsilon) = D(A)
\end{displaymath}


\begin{displaymath}
\delta^*(A, ax) = \delta^*(\bigcup_{q \in D(A)} \delta(q, a), x)
\end{displaymath}

Każde obliczenie automatu z $\varepsilon$-przejściami to przeplot $\varepsilon$-przejść i zwykłych przejść. Odpowiada temu w definicji $\delta^*$ przeplatanie funkcji D i $\delta$.

Definicja

Język akceptowany przez automat z $\varepsilon$-przejściami to:

\begin{displaymath}
L(M) =
\{x \in \Sigma^* : \delta^*(S, x) \setint F \neq \emptyset\}
\end{displaymath}

Powyższa definicja jest identyczna jak w przypadku automatów niedeterministycznych. Pamiętajmy jednak, że funkcja $\delta^*$, opisująca działanie automatu, jest zdefiniowana inaczej.

Pokażemy teraz, że automaty z $\varepsilon$-przejściami i automaty niedeterministyczne mają taką samą siłę wyrazu. (Tym samym, automaty z $\varepsilon$-przejściami mają taką samą siłę wyrazu co automaty deterministyczne.) Powiedzieliśmy już wcześniej, że automaty niedeterministyczne są szczególnym przypadkiem automatów z $\varepsilon$-przejściami. Musimy pokazać, że $\varepsilon$-przejścia nie zwiększają siły wyrazu i że zawsze można je wyeliminować, zamieniając automat z $\varepsilon$-przejściami w automat niedeterministyczny.


Eliminacja $\varepsilon$-przejść

Eliminacja $\varepsilon$-przejść opiera się na dodaniu dodatkowych przejść i stanów początkowych, tak aby definicje funkcji $\delta^*$ dla automatów niedeterministycznych i z $\varepsilon$-przejściami były sobie równoważne. W tym celu dodamy dodatkowe stany początkowe oraz dodatkowe przejścia.

Niech $M = \angles{Q, \Sigma, \delta, S, F}$ będzie automatem skończonym z $\varepsilon$-przejściami. Równoważny mu niedeterministyczny automat skończony M' ma postać $M' = \angles{Q, \Sigma, \delta', S', F}$, gdzie S'=D(S), $\delta'(q,a) = D(\delta(q,a))$ (dla $a \neq \varepsilon$).

Dowód poprawności

Zbiory stanów i stanów akceptujących są w obu automatach takie same. Pokażemy przez indukcję (ze względu na |x|), że dla dowolnego $A \subseteq Q$ zachodzi $\delta^*(A,x) = \delta'^*(D(A),x)$.
  1. Dla $x=\varepsilon$ mamy:

    \begin{displaymath}
\delta^*(A,\varepsilon) =
D(A) =
\delta'^*(D(A),\varepsilon)
\end{displaymath}

  2. Załóżmy, że teza jest prawdziwa dla x. Pokażemy jej prawdziwość dla ax (dla dowolnego $a \in \Sigma$).

    \begin{eqnarray*}
\delta^*(A,ax) &=&
\delta^*(\bigcup_{q \in D(A)} \delta(q, ...
...^*(\bigcup_{q \in D(A)} \delta'(q, a), x) =
\delta'^*(D(A),ax)
\end{eqnarray*}


Stąd mamy:

\begin{displaymath}
L(M') =
\{x \in \Sigma^* :
\delta'^*(S', x) \setint F \...
...Sigma^* :
\delta^*(S, x) \setint F \neq \emptyset\} =
L(M)
\end{displaymath}

Czyli oba automaty, M i M', akceptują ten sam język. \qed

Podsumowanie

W tym wykładzie przedstawiliśmy automaty niedeterministyczne i automaty z $\varepsilon$-przejściami. Pokazaliśmy, że mają one taką samą siłę wyrazu Siła wyrazu automatów deterministycznych, niedeterministycznych i z $\varepsilon$-przejściami jest dokładnie taka sama.

Skorowidz

Praca domowa

  1. Podaj automat niedeterministyczny akceptujący słowa nad alfabetem {a,b} zawierające podsłowo ababb.
  2. Zdeterminizuj następujący automat niedeterministyczny:
    \includegraphics{rys-3-7}
  3. Wyeliminuj $\varepsilon$-przejścia w poniższym automacie. Jaki język on akceptuje?
    \includegraphics{rys-3-e}

Ćwiczenia

  1. Podaj automat niedeterministyczny akceptujący słowa nad alfabetem {a,b} zawierające podsłowo bababba. Porównaj go z automatem deterministycznym stworzonym ręcznie i w wyniku determinizacji automatu niedeterministycznego.
  2. Zdeterminizuj następujące automaty niedeterministyczne. Pomiń stany nieosiągalne.
    \includegraphics{rys-3-2.eps}
    \includegraphics{rys-3-6}
    \includegraphics{rys-3-8.eps}
    \includegraphics{rys-3-9.eps}
    \includegraphics{rys-det-1.1}
    \includegraphics{rys-det-2.1}

    \begin{picture}(50,50)(-5,-5)
\thicklines
\put(10,10){\circle*{2}}
\put(10,...
...\put(16,20){\makebox(0,0)[l]{0}}
\put(16,35){\makebox(0,0)[l]{0}}
\end{picture}

    \begin{picture}(70,40)(-5,-5)
\thicklines
\put(10,10){\circle*{2}}
\put(30,...
...\put(30,21){\makebox(0,0)[b]{0}}
\put(50,21){\makebox(0,0)[b]{1}}
\end{picture}
  3. Wyeliminuj $\varepsilon$-przejścia, a następnie zdeterminizuj poniższy automat. Możesz pominąć stany nieosiągalne.
    \includegraphics{rys-3-1.eps}