4.2. Automat skończony

Transkrypt

4.2. Automat skończony
4.2. Automat skończony
Przykład:
Rozważamy język nad alfabetem binarnym T = {0, 1} składający się z łańcuchów zero-jedynkowych
o tej własności, że liczba zer w każdym łańcuchu jest parzysta i liczba jedynek w każdym łańcuchu też
jest parzysta. Wszystkie łańcuchy binarne możemy podzielić na cztery grupy:
S – łańcuchy z parzystą liczbą jedynek i parzystą liczbą zer,
A – łańcuchy z parzystą liczbą jedynek i nieparzystą liczbą zer,
B – łańcuchy z nieparzystą liczbą jedynek i parzystą liczbą zer,
C – łańcuchy z nieparzystą liczbą jedynek i nieparzystą liczbą zer.
Analizujemy łańcuch zero-jedynkowy symbol po symbolu od lewej strony. Przed rozpoczęciem
analizy jesteśmy w grupie S (łańcuch pusty zawiera zero jedynek i tyleż zer, więc liczba jedynek i
liczba zer w tym łańcuchu są parzyste). Jeśli pierwszym symbolem jest jedynka – przechodzimy do
grupy A (wtedy liczba jedynek jest nieparzysta, a liczba zer jest dalej parzysta), zaś jeśli pierwszym
symbolem jest zero – przechodzimy do grupy B (wtedy liczba zer jest nieparzysta, a liczba jedynek
jest dalej parzysta). Zapisujemy to w postaci produkcji:
S → 1A | 0B
Dalej analizujemy podobnie kolejne symbole łańcucha. Np. jeśli jesteśmy w grupie A i przeczytamy
zero – przechodzimy do grupy C, w której zarówno liczba jedynek, jak i zer są nieparzyste
(odpowiedni zapis: A → 0C). Proces analizy łańcucha można zilustrować w postaci poniższego grafu:
1
S
A
1 parz.
0 parz.
1 nieparz.
0 parz.
0
1
0
0
0
1
B
C
1 parz.
0 nieparz.
1 nieparz.
0 nieparz.
1
Wreszcie, gdy przeczytaliśmy cały łańcuch, sprawdzamy, czy zatrzymaliśmy się w grupie S. Jeśli tak
– badany łańcuch spełnia nałożony nań warunek parzystej liczby jedynek i parzystej liczby zer.
Wówczas należy wyeliminować z wyprowadzenia symbol S (odpowiedni zapis: S → ε). Ostatecznie
gramatyka naszego języka ma postać:
S → 1A | 0B | ε
A → 1S | 0C
B → 1C | 0S
C → 1B | 0A
Opisana procedura i zamieszczony powyżej rysunek ilustrują właściwie nie tyle proces
konstruowania gramatyki dla pewnego języka, co proces odpowiadania na pytanie: czy dany
łańcuch jest słowem należącym do danego języka. Jest to pewien (w naszym przypadku
deterministyczny) algorytm postępowania, polegający na czytaniu badanego łańcucha symbol
po symbolu i przechodzenia od jednego stanu do drugiego. Stany reprezentowane są przez
kółka (węzły grafu), zaś przejścia pomiędzy stanami, to skierowane krawędzie, opisane
(etykietowane) odpowiednimi symbolami alfabetu, z którego pochodzą symbole łańcucha.
Jeden ze stanów jest wyróżniony jako stan początkowy (na rysunku – jest to stan oznaczony
krótką strzałką dochodząc do niego z zewnątrz). Od tego stanu zawsze rozpoczynamy
„wędrówkę” po grafie. Niektóre stany są traktowane jako stany końcowe – akceptujące (są
one zaznaczone kółkami rysowanymi podwójną linią). Jeśli w trakcie naszej „wędrówki” po
grafie zatrzymamy się w takim stanie, to akceptujemy badany łańcuch, jeśli zatrzymamy się w
stanie nie będącym stanem końcowym – nie akceptujemy analizowanego łańcucha.
Zatrzymanie się w naszym przypadku może być tylko spowodowane przeczytaniem badanego
słowa do końca i stwierdzeniem, że już nic nie pozostało do przeczytania.
Opisany powyżej algorytm nosi nazwę automatu skończonego (a dokładnie
deterministycznego i zupełnego automatu skończonego). Okazuje się, że językami, które
mogą być akceptowane przez tego typu automaty są języki regularne (zbiory regularne) i
tylko one. Pewnym potwierdzeniem tej reguły jest fakt, że otrzymana w naszym przykładzie
gramatyka jest gramatyką prawostronnie liniową.
Skąd pochodzi nazwa automat? Możemy sobie wyobrazić, że nasz algorytm to
„pseudourządzenie” dysponujące taśmą wejściową, na której zapisany jest badany łańcuch i
nad którą może poruszać się głowica odczytująca pojedyncze symbole. Głowica ma tylko
możliwość ruchu w prawo, tzn. od początku łańcucha ku jego końcowi. Każdorazowo
głowica przesuwa się tylko o jeden symbol. W każdym kroku głowica „widzi” tylko jeden
symbol na taśmie. W każdym momencie automat charakteryzowany jest przez aktualny stan
(liczba możliwych stanów jest skończona). Automat posiada swoje sterowanie (jest ono
zdefiniowane przez tzw. funkcję przejść automatu), które na podstawie aktualnego stanu i
symbolu czytanego przez głowicę, określa następny stan w następnym kroku. Początkowo
głowica ustawiona jest na pierwszym symbolu badanego łańcucha, zaś automat znajduje się w
stanie początkowym. Każdy krok pracy automatu to: odczytanie przez głowicę symbolu z
taśmy wejściowej, określenie nowego stanu i przesunięcie głowicy o jedną pozycję w prawo
na taśmie wejściowej. Kroki są powtarzane tak długo, jak długo można. Automat zatrzyma
się, gdy np. przeczytał wejście do końca lub z innych powodów nie jest w stanie wykonać
żadnego kroku. Zatrzymanie się automatu w stanie należącym do grupy stanów końcowych
oznacza akceptację czytanego łańcucha i stwierdzenie, że łańcuch zapisany na taśmie
wejściowej jest słowem należącym do języka akceptowanego przez automat. Zatrzymanie się
naszego automatu (w jego wersji deterministycznej i zupełnej) w stanie nie będącym stanem
końcowym oznacza brak akceptacji badanego łańcucha.
Formalna definicja automatu skończonego
Automatem skończonym nazywamy piątkę A = < T, Q, F, qo, δ >, gdzie:
T – zbiór symboli terminalnych (alfabet wejściowy)
Q – zbiór stanów, #Q < ∞
F ⊆ Q – zbiór stanów końcowych
qo ∈ Q – stan początkowy
δ – funkcja przejścia
δ: Q × ( T ∪ {ε}) ! 2Q
a
b
b
a
b
a
b
a
b
b
konfiguracja (q i,bbabababb)
qi
a
b
b
przed wykonaniem kroku
a
b
a
b
a
b
b
konfiguracja (q j,bbabababb)
qi
po wykonaniu kroku
Konfiguracja automatu to dwójka: (q, w), gdzie q jest aktualnym stanem, zaś w jest
nieprzeczytaną przez automat częścią słowa zapisanego na taśmie wejściowej
W T*
q Q
Konfiguracja początkowa :
q0
Konfiguracja końcowa ( akceptująca ):
q F
stan końcowy
Wyprowadzenie bezpośrednie:
( q, ax ) "A ( q’, x )
gdzie: q,q’∈Q, a∈( T ∪ {ε}), x∈T* , q’∈ δ(q,a)
Wyprowadzenia pośrednie "A+ i "A* są odpowiednio przechodnim oraz przechodnim i
zwrotnym domknięciem relacji wyprowadzenia bezpośredniego "A:
(q,w) "A+ (q’ ,w’) ⇔ ∃ po, ... ,pn (pi – konfiguracje), takie że:
qo=(q,w),
qn= (q’ , w’),
pi "A pi+1
dla i=0,1,...,n-1
*
(q,w) "A (q’ , w’) ⇔ (q,w) "A+ (q’ ,w’) ∪ (q,w) = (q’ , w’)
Konfiguracja blokująca :
(q,w) jest blokująca ⇔! ¬ (∃(q’ ,w’)) ((q,w) "A (q’ ,w’))
x∈T* jest słowem akceptowanym przez automat A (skończony) ⇔ (∃q∈F) ((qo ,x) "A* (q,ε))
Język L jest akceptowany przez automat A ( co oznaczamy L(A) ) ⇔
L = L(A) = { x∈ T* | x jest akceptowane przez A }
Przykład : Język regularny opisany wyrażeniem regularnym (a|b)*abb
T={a,b}
Q={q0, q1 ,q2 ,q3 )
F={q3}
Q0 – stan początkowy
δ - funkcja przejścia:
Stan
q0
q1
q2
a
{ q0 , q1 }
∅
∅
b
{q0}
{q2}
{q3}
a
start
q0
a
q1
b
q2
b
Analizowane słowo : aabb ∈ L( (a|b)*abb )
Możliwe wyprowadzenia:
b
q3
( q0 , aabb ) " ( q0,abb) " ( q1,bb ) " ( q2,b ) " ( q3, ε) – konfiguracja końcowa akceptująca)
( q0 , aabb ) " ( q0,abb) " ( q0,bb ) " ( q0,b ) " ( q0, ε) – konfiguracja blokująca bo q0 ∉F
( q0 , aabb ) " ( q1,abb) – konfiguracja blokująca, słowo nie zostało przeczytane do końca
Automat nie jest deterministyczny. Jednak istnieje wyprowadzenie (ciąg kroków), które
doprowadza do konfiguracji akceptującej, więc zgodnie z definicją automat akceptuje to
słowo.
Własności automatu skończonego
Automat skończony A jest zupełny ⇔ (∀a∈T) (∀q∈Q) (#δ(q,a) ≥ 1
Automat skończony A jest deterministyczny ⇔
(i) (∀q∈Q) (#δ(q,ε) = 0) oraz
(ii) (∀a∈T) (∀q∈Q) (#δ(q,a) ≤ 1)
Automat skończony A jest deterministyczny i zupełny ⇔
(i) (∀q∈Q) (#δ(q,ε) = 0) oraz
(ii) (∀a∈T) (∀q∈Q) (#δ(q,a) = 1)
Automat skończony zupełny nazywamy automatem Rabina-Scotta.
Automat skończony, deterministyczny i zupełny nazywamy deterministycznym automatem
Rabina-Scotta
Przykład: Deterministyczny zupełny automat akceptujący język opisany wyrażeniem
regularnym (a|b)*abb
T={a,b}
Q = { 0, 1 , 2 , 3, }
a
F={3}
Przypomnienie poprzedniego przykładu :
q0 = 0
automat niederministyczny i niezupełny
δ - funkcja przejścia:
Stan
a
b
a
b
b
0
1
2
3
start
0
1
0
1
1
2
2
1
3
b
3
1
0
b
b
0
a
1
a
b
2
a
a
b
3

Podobne dokumenty