Akademi cki epodr ęcz ni kimul t i medi al ne STUDI AMAGI STERSKI E Wykład 1 Pojęcia podstawowe W niniejszym wykładzie podane są podstawowe definicje dotyczące języków formalnych. Definicja 1.1. Alfabetem nazywany dowolny skończony zbiór. Jego elementy będziemy nazywali symbolami. Przykłady alfabetów: zbiór cyfr binarnych {0, 1} zbiór cyfr ósemkowych (oktalnych) {0, 1, 2, 3, 4, 5, 6, 7} zbiór cyfr dziesiętnych {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} Uwaga: W niektórych publikacjach zamiast terminu „symbol” uŜywany jest termin „litera”. „Symbol” nie musi być pojedynczym znakiem. Teoria języków formalnych stosowana jest do opisu róŜnego rodzaju języków, np. do języków programowania i w tym zastosowaniu napisy begin, for, if, else, do itp. traktowane są jako symbole. Alfabety będziemy zwykle oznaczali duŜymi literami alfabetu łacińskiego, zaś symbole – małymi początkowymi literami alfabetu łacińskiego, np. A = {a1, a2, … , an}. Definicja 1.2. Słowem nad alfabetem A nazywamy dowolny skończony ciąg symboli alfabetu A napisanych jeden po drugim (bez znaków przestankowych, np. przecinków), jak równieŜ napis nie zawierający Ŝadnego symbolu, który będziemy nazywali słowem pustym i będziemy oznaczali małą literą grecką ε. Długość słowa niepustego definiujemy jako liczbę symboli, z których składa się to słowo (jeśli jakiś symbol powtarza się w danym słowie, to liczymy kaŜde jego wystąpienie), zaś dla słowa pustego przyjmujemy wartość zero. Długość słowa w będzie zapisywana jako l(w). Przykład: l(a1a2 … an) = n, l(ε) = 0. Definicja 1.3. Słownikiem nad alfabetem A nazywamy zbiór wszystkich skończonych słów nad alfabetem A. Będziemy oznaczali go przez A*. Przykłady: 1) Słownik nad alfabetem o jednym symbolu zawiera po jednym słowie kaŜdej długości, np. {a}* = {ε, a, aa, aaa, aaaa, …}. 2) Słownik nad alfabetem o dwóch symbolach zawiera 2n słów o długości n, np. w słowniku nad alfabetem {a, b} mamy - jedno słowo o długości 0: ε; - dwa słowa o długości 1: a, b; - cztery słowa o długości 2: aa, ab, ba, bb; - osiem słów o długości 3: aaa, aab, aba, abb, baa, bab, bba, bbb, itd.; 3) Jeśli A = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} i B = {0, 1}, to A* \ {ε} jest zbiorem wszystkich liczb dziesiętnych, zaś B* \ {ε} jest zbiorem wszystkich liczb binarnych (przypomnienie: „\” oznacza operację róŜnicy mnogościowej, tzn. róŜnicy zbiorów). 2 Definicja 1.4. Językiem formalnym nad alfabetem A (lub krócej - językiem nad alfabetem A) nazywamy dowolny podzbiór słownika A* (w szczególności językami nad alfabetem A są zbiór pusty Φ i słownik A*). Przykłady: 1) Zbiór wszystkich liczb binarnych o trzech cyfrach jest następującym językiem nad alfabetem {0, 1}: {000, 001, 010, 011, 100, 101, 110, 111}; 2) Kolejny przykład jest językiem nad alfabetem {a, b, c}. OtóŜ, zbiór wszystkich słów o długości co najwyŜej 3, w których występują co najmniej dwa symbole a jest następującym językiem: {aa, aaa, aab, aac, aba, aca, baa, caa}; Definicja 1.5. ZłoŜeniem dwóch niepustych słów u = a1a2…am i v = b1b2…bn nad tym samym alfabetem A nazywamy słowo otrzymane przez napisanie wszystkich symboli słowa u w takiej kolejności, w jakiej występują w słowie u, następnie napisanie bezpośrednio po ostatnim symbolu słowa u pierwszego symbolu słowa v, a po nim wszystkich pozostałych symboli słowa v w takiej kolejności, w jakiej występują w słowie v, tzn. otrzymamy następujące słowo nad alfabetem A: uv = a1a2…amb1b2…bn, natomiast złoŜenie słowa pustego z dowolnym słowem x daje w wyniku słowo x: εx = xε = x. Uwaga: 1) W języku polskim obecnie zamiast terminu „złoŜenie” uŜywane są równieŜ dwa inne terminy: „konkatenacja” (wzorowany na terminie angielskim „concatenation”) lub „sklejenie”. 2) ZłoŜenie słów nie jest przemienne, tzn. dla wielu par słów u i v mamy uv ≠ vu, na przykład, tak się dzieje, jeśli u = a1 i v = b1 oraz a1 ≠ b1, jak równieŜ dla u = 010 i v = 11, gdyŜ wtedy uv = 01011, zaś vu = 11010. MoŜe się jednak zdarzyć, Ŝe u ≠ v, ale uv = vu, np. tak jest dla u = aa oraz v = aaaaa, gdyŜ wtedy uv = vu = aaaaaaa. 3) Dla kaŜdej trójki dowolnych słów u, v i w zawsze (uv)w = u(vw), a zatem stosowanie nawiasów nie jest w tym przypadku konieczne. 4) Łatwo zauwaŜyć, Ŝe l(uv) = l(u) + l(v). Definicja 1.6. Niech u = xyz, gdzie x, y, z ∈ A* oraz xz ≠ ε (tzn. choć jedno ze słów x i z jest niepuste). Wtedy – słowo y nazywane jest podsłowem słowa u, – słowo x, jeśli jest niepuste, nazywane jest przedrostkiem słowa u, – słowo z, jeśli jest niepuste, nazywane jest przyrostkiem słowa u. Jeśli słowo y jest niepuste, to nazywane jest podsłowem właściwym słowa u. Przykład: Podsłowami słowa aabccc są słowa: ε, a, b, c, aa, ab, bc, cc, aab, abc, bcc, ccc, aabc, abcc, bccc, aabcc, abccc, aabccc, przy czym spośród nich tylko ε nie jest podsłowem właściwym. Przedrostkami są: a, aa, aab, aabc, aabcc i aabccc, zaś przyrostkami są: c, cc, ccc, bccc, abccc i aabccc. 3 Wykład 2 Operacje na słowach i językach Poprzedni wykład zawierał m.in. definicję operacji złoŜenia słów. Niniejszy zawiera definicje kolejnych trzech operacji na słowach (odbicia zwierciadlanego, potęgowania oraz prawostronnego ilorazu) i uogólnienia wyŜej wymienionych czterech operacji dla języków, a takŜe dwie kolejne operacje na językach: domknięcie i iterację. W tekście wykładu zamieszczone są zadania przeznaczone jako ćwiczenia. Ich pełne rozwiązania podane są na końcu tego wykładu. Definicja 2.1. Odbicie zwierciadlane słowa x (oznaczane jako xR) definiowane jest w następujący sposób: ε R = ε, jeśli x = a1a2 … an, to xR = an … a2a1 (tzn. w słowie niepustym zmienia się porządek symboli na odwrotny). Własności operacji odbicia zwierciadlanego: (xR)R = x (xy)R = yRxR (A*)R = A* Definicja 2.2. Odbicie zwierciadlane języka L (oznaczane jako LR) definiowane jest w następujący sposób: LR = {xR | x ∈ L}. Przykład: Jeśli L = {1, 10, 110, 1010}, to LR = {1, 01, 011, 0101}, a jeśli L = {1, 010, 01010}, to LR = {1, 010, 01010} = L. Definicja 2.3. Potęga słowa x definiowana jest w następujący sposób: x0 = ε xn = xxn-1 dla n = 1, 2, 3, … Przykład: Wszystkie słowa naleŜące do A* = {a}* są potęgami słowa a: ε = a0, a = a1, aa = a2, aaa = a3, aaaa = a4 itd. Definicja 2.4. ZłoŜenie języków L1 i L2 (oznaczane jako L1L2) definiowane jest w następujący sposób: L1L2 = {xy | x ∈ L1, y ∈ L2}. Uwaga: Podobnie jak złoŜenie słów, takŜe złoŜenie języków nie jest przemienne, tzn. dla pewnych par L1 i L2 zachodzi L1L2 ≠ L1L2. ZauwaŜmy, iŜ niektóre słowa xy mogą być takie same – wypisując elementy języka L1L2 piszemy je tylko raz (stąd w przykładzie poniŜej liczby elementów w zbiorach L1L2 i L2L1 są róŜne). Natomiast operacja ta jest łączna, tzn. dla kaŜdej trójki języków L1, L2, L3 zachodzi równość (L1L2)L3 = L1(L2L3), a zatem w wyraŜeniu, w którym występuje tylko ta operacja, nie ma konieczności stosowania nawiasów. ZauwaŜmy jeszcze, Ŝe poniewaŜ εx = xε = x dla dowolnego x, to {ε}L = L{ε} = L dla dowolnego L. Przykład: Niech L1 = {ε, 01} i L2 = {0, 010}. Wtedy L1L2 = {(ε)(0), (ε)(010), (01)(0), (01)(010)} = {0, 010, 010, 01010} = {0, 010, 01010}, L2L1 = {(0)(ε), (0)(01), (010)(ε), (010)(01)} = {0, 001, 010, 01001} ≠ L1L2 4 Definicja 2.5. Potęga języka L definiowana jest w następujący sposób: L0 = {ε} Ln = LLn-1 dla n = 1, 2, 3, ... Łatwo zauwaŜyć, Ŝe zgodnie z powyŜszą definicją L1 = LL0 = L{ε} = L. Przykład: Na podstawie Definicji 2.5 mamy: {a}0 = {ε}, {a}1 = {a}{a}0 = {a}{ε} = {a}, {a}2 = {a}{a}1 = {a}{a} = {aa}, {a}3 = {a}{a}2 = {a}{aa} = {aaa}, {a}4 = {a}{a}3 = {a}{aaa} = {aaaa}, itd. ZADANIE 2.1. Obliczyć języki L1L2, L2L1, (L1)2, (L2)2, jeśli L1 = {0, 01, 10} oraz L2 = {00, 100, 110}. Definicja 2.6. Iteracją języka (oznaczaną przez L+) nazywa się sumę mnogościową wszystkich potęg tego języka począwszy od pierwszej potęgi do nieskończoności, zaś domknięciem języka (oznaczanym przez L*) – sumę mnogościową wszystkich potęg tego języka począwszy od zerowej potęgi do nieskończoności: L+ = L1 ∪ L2 ∪ L3 ∪ … L* = L 0 ∪ L 1 ∪ L 2 ∪ L 3 ∪ … Uwaga: Oznaczenie domknięcia przez L* nie jest sprzeczne z oznaczeniem słownika nad alfabetem A przez A* (Wykład 1, Definicja 1.3), bowiem jeśli język L jest równy alfabetowi A, to wtedy domknięcie języka L jest równe słownikowi nad alfabetem A (L* = A*). Z Definicji 2.6 wynika, Ŝe L* = L0 ∪ L+ = {ε} ∪ L+, a więc L* zawsze zawiera słowo puste, zaś L+ zawiera słowo puste wtedy i tylko wtedy, gdy ε ∈ L. Zbiory L+ i L* mają nieskończenie wiele słów wtedy i tylko wtedy, gdy L zawiera co najmniej jedno niepuste słowo. Przykłady: 1) Jeśli L = {00, 11} ⊆ {0, 1}*, to na podstawie Definicji 2.5 i 2.6 mamy: L0 = {ε}, L1 = {00, 11}{00, 11}0 = {00, 11}{ε} = {00, 11}, L 2 = {00, 11}{00, 11}1 = {00, 11}{00, 11} = {0000, 0011, 1100, 1111}, L3 = {00, 11}{00, 11}2 = {00, 11}{0000, 0011, 1100, 1111} = = {000000, 000011, 001100, 001111, 110000, 110011, 111100, 111111}, itd. Zatem L+ = {00, 11, 0000, 0011, 1100, 1111, 000000, 000011, 001100, 001111, 110000, 110011, 111100, 111111, …}, L* = {ε, 00, 11, 0000, 0011, 1100, 1111, 000000, 000011, 001100, 001111, 110000, 110011, 111100, 111111, …} = {ε} ∪ L+. 2) Zbadamy, czy do języka L = ({b}∪{a}{b}{a})* nad alfabetem {a, b} naleŜą słowa bb, bba, abb, abab, baba, abaaba i babababab. Język L moŜna zapisać prościej w postaci L = ({b}∪{aba})* = {b, aba}*. Oznaczmy przez L1 język {b, aba}. Zatem L = (L1)* = (L1)0 ∪ (L1)1 ∪ (L1)2 ∪ (L1)3 ∪ … . Słowa bba, abb nie naleŜą do L, gdyŜ nie naleŜą do Ŝadnej potęgi L1 (inaczej mówiąc, nie moŜna ich otrzymać ze złoŜenia słów b i aba). Cztery z tych słów bb = (b)(b), abab = (aba)(b), baba = (b)(aba) i abaaba = (aba)(aba) naleŜą do (L1)2 , zaś słowo babababab = (b)(aba)(b)(aba)(b) naleŜy do (L1)5, zatem wszystkie naleŜą do L. 5 3) Zbadamy, czy następujące dwa języki nad alfabetem {a, b} są identyczne: L1 = {a, b}*, L2 = {a}*{ba}* = {ε, a, aa, aaa, … }{ε, ba, baba, bababa, … }. Jeśli dwa języki róŜnią się, to wystarczy wskazać słowo, które naleŜy do jednego z nich i równocześnie nie naleŜy do drugiego. Język L1 jest słownikiem nad alfabetem {a, b}, więc wystarczy zbadać, czy do L2 nie naleŜą jakieś słowa nad tym alfabetem. Poszukiwania najlepiej zacząć od najkrótszych słów. Słowa ε oraz a naleŜą do L2, ale słowo b nie naleŜy, gdyŜ słowa w tym języku zaczynające się od symbolu b mają długość co najmniej równą 2. ZADANIE 2.2. Czy do języka L = {c}{a}∪{b}{c}{a}* nad alfabetem {a, b, c} naleŜą słowa c, aa, caa, bca, bcaaa? Uwaga: operacja * dotyczy tylko języka {a}, a nie złoŜenia języków {b}{c}{a}, bo w takim przypadku naleŜałoby uŜyć nawiasu: ({b}{c}{a})*. ZADANIE 2.3. Zbadać, czy następujące dwa języki nad alfabetem {a, b, c} są identyczne: L1 = ({a}*{b})* ∪ {c}, L2 = ({a}{a}*{b})*{c}. Definicja 2.7. Jeśli x, y, z ∈ A* i x = yz, to prawostronny iloraz x // y = z, zaś jeśli x ≠ yz, to wynik operacji x // y nie istnieje. Przykład: 00111 // 001 = 11 001 // 00111 nie istnieje Własności operacji prawostronnego ilorazu słów: x // x = ε x // ε = x jeśli istnieje x // y, to y(x // y) = x Definicja 2.8. Prawostronny iloraz języka L ⊆ A* przez słowo x ∈ A* (oznaczany jako L // x) definiowany jest w następujący sposób: L // x = {y ∈ A* | xy ∈ L}. Uwaga: Operacja prawostronnego ilorazu języka L przez słowo x moŜe być takŜe zdefiniowana w następujący sposób: L // x = {z // x | z ∈ L oraz istnieje z // x}. Zatem, jeśli mamy obliczyć prawostronny iloraz języka L przez słowo x, to moŜemy najpierw wybrać z L te słowa, które mają przedrostek x, a następnie obliczyć ich ilorazy przez x. Przykłady: 1) Niech A = {a, b} i L = {ba} ⊆ A*. Wtedy L // a = Φ, L // b = {a}, L // aa = L // ab = L // bb = Φ, L // ba = {ε}. 2) Jeśli L = {1k01k | k = 0, 1, 2, 3,…} = {0, 101, 11011, 1110111,…}, to L // 0 = L // 101 = L // 11011 = {ε} L // 1 = {1k-101k | k = 1, 2, 3, …} = {01, 1011, 110111, …}, L // 00 = L // 01 = Φ L // 10 = {1} L // 11 = {1k-201k | k = 2, 3, 4, …} = {011, 10111, 1101111, …}. 6 Własności operacji prawostronnego ilorazu języka przez słowo (dla dowolnych a ∈ A, x, y ∈ A*, oraz dla dowolnych języków L, L1, L2 nad alfabetem A): 1) Φ // x = Φ 2) A* // x = A* 3) L // ε = L 4) L // xy = (L // x) // y 5) (L1 ∪ L2) // x = (L1 // x) ∪ (L2 // x) 6) (L1L2) // a = (L1 // a)L2 ∪ (L2 // a), gdy ε ∈ L1 (L1L2) // a = (L1 // a)L2, w przeciwnym przypadku 7) (L*) // x = (L // x) L* Uwaga: Własność czwarta z powyŜszej listy umoŜliwia obliczanie kolejnych ilorazów przez poszczególne symbole słowa zamiast przez całe słowo: (L // a1a2 … an) = (…((L // a1) // a2) … ) // an). ZADANIE 2.4. Dla języków L1 = {a}* i L2 = {a}* \ {aa} nad alfabetem {a} obliczyć: L // a, L // aa, L // aaa. ZADANIE 2.5. Dla języka L = {aibi | i ≥ 0} nad alfabetem {a, b} obliczyć: L // a, L // b, L // aa, L // ab, L // ba, L // bb. ZADANIE 2.6. Dla następujących języków nad alfabetem {a, b} L1 = {a}{b}* L2 = {a}*{b} L3 = {a, b}* \ {ba} obliczyć: L // a, L // b, L // aa, L // ab, L // ba, L // bb. ROZWIĄZANIA ZADAŃ ZADANIE 2.1 Jeśli L1 = {0, 01, 10} i L2 = {00, 100, 110}, to L1L2 = {000, 0100, 0110, 0100, 01100, 01110, 1000, 10100, 10110} = ={000, 0100, 0110, 01100, 01110, 1000, 10100, 10110} (w ostatnim przekształceniu usunęliśmy jedno z powtarzających się słów 0100) L2L1 = {000, 0001, 0010, 1000, 10001, 10010, 1100, 11001, 11010} ≠ L1L2 (L1)2 = L1L1 = {00, 001, 010, 010, 0101, 0110, 100, 1001, 1010} = ={00, 001, 010, 0101, 0110, 100, 1001, 1010} (w ostatnim przekształceniu usunęliśmy jedno z powtarzających się słów 010) 2 (L2) = L2L2 = {0000, 00100, 00110, 10000, 100100, 100110, 11000, 110100, 110110} ZADANIE 2.2 PoniewaŜ {c}{a} = {ca} i {b}{c} = {bc}, więc język L moŜna zapisać prościej w postaci L = {ca}∪{bc}{a}*. Zatem L = {ca}∪{bc}{a}* = {ca}∪{bc}{ε, a, aa, aaa, …} = {ca}∪{bc, bca, bcaa, bcaaa, …} Jak widać, słowa c i caa nie naleŜą do L, gdyŜ spośród wszystkich słów zaczynających się od symbolu c tylko słowo ca naleŜy do L. Wszystkie pozostałe słowa naleŜące do L zaczynają się od symbolu b, zatem słowo aa równieŜ nie naleŜy do L. Natomiast do L naleŜą słowa bca, bcaaa (ogólniej – wszystkie słowa postaci bcak, gdzie k = 0, 1, 2, 3, …). 7 ZADANIE 2.3 W języku L1 = ({a}*{b})* ∪ {c} jedynym słowem, które zawiera symbol c, jest słowo c (występujące w drugim wyrazie sumy mnogościowej), zaś w języku L2 = ({a}{a}*{b})*{c} występuje nieskończenie wiele słów zawierających symbol c (np. abc, aabc, aaabc, ababc, itd.). Zatem , języki L1 i L2 nie są identyczne. ZADANIE 2.4 PoniewaŜ L1 = {a}* = {ε, a, aa, aaa, …} i ε//a nie istnieje, zaś a // a = ε, aa // a = a, aaa // a = aa, itd., więc L1 // a = {ε, a, aa, aaa, …} = {a}*. W podobny sposób otrzymujemy: L1 // aa = L1 // aaa = {ε, a, aa, aaa, …} = {a}*. Natomiast dla L2 = {a}* \ {aa} = {ε, a, aa, aaa, …} \ {aa} = {ε, a, aaa, …}mamy: L2 // a = {a}* \ {a} (poniewaŜ do L2 nie naleŜy tylko słowo aa ze słownika, to do L2 // a nie naleŜy tylko słowo a = aa // a), L2 // aa = {a}* \ {ε} (poniewaŜ do L2 nie naleŜy tylko słowo aa ze słownika, to do L2 // a nie naleŜy tylko słowo ε = aa // aa), L2 // aaa = {a}* (poniewaŜ do L2 nie naleŜy tylko słowo aa ze słownika, zaś wynik ilorazu aa // aaa nie istnieje). ZADANIE 2.5 Jeśli L = {aibi | i = 0, 1, 2, 3, 4, …} = {ε, ab, aabb, aaabbb, aaaabbbb, …}, to L // a = {b, abb, aabbb, aaabbbb, …} = {ai-1bi | i = 1, 2, 3, 4, …} L // b = L // ba = L // bb = Φ (w L brak słów zaczynających się od symbolu b) L // aa = (L // a) // a = {bb, abbb, aabbbb, …} = {ai-2bi | i = 2, 3, 4, …} L // ab = (L // a) // b = {ε} ZADANIE 2.6 Dla języków L1 = {a}{b}* = {a}{ε, b, bb, bbb, bbbb, …} = {a, ab, abb, abbb, abbbb, …} L2 = {a}*{b} = {ε, a, aa, aaa, aaaa, …}{b} = {b, ab, aab, aaab, aaaab, …} L3 = {a, b}* \ {ba} = {ε, a, b, aa, ab, ba, bb, aaa, …} \ {ba} = {ε, a, b, aa, ab, bb, aaa, …} mamy: L1 // a = {ε, b, bb, bbb, …} = {b}* L1 // b = Φ L1 // aa = (L1 // a) // a = Φ L1 // ab = (L1 // a) // b = {ε, b, bb, …} = {b}* L1 // ba = (L1 // b) // a = Φ L1 // bb = (L1 // b) // b = Φ L2 // a = {b, ab, aab, aaab, …} = {a}*{b} L2 // b = {ε} L2 // aa = {b, ab, aab, …} = {a}*{b} L2 // ab = {ε} L2 // ba = Φ L2 // bb = Φ L3 // b = {ε, b, aa, ab, ba, bb, …} = {a, b}* \ {a} (w L3 nie ma ba, więc w L3 // b nie ma a) L3 // ba = {a, b, aa, ab, ba, bb, …} = {a, b}* \ {ε} (w L3 nie ma ba, więc w L3 // ba nie ma ε) L3 // a = L3 // aa = L3 // ab = L3 // bb = {ε, a, b, aa, ab, ba, bb, …} = {a, b}* (brak słowa ba w L3 nie ma wpływu na te ilorazy, bowiem ba // a, ba // aa, ba // ab i ba // bb nie istnieją) 8 Wykład 3 Automat skończony Rabina-Scotta W niniejszym wykładzie najpierw podane są definicje automatów skończonych Moore’a i Mealy’ego, które zostały wprowadzone w teorii automatów jako pierwsze, a następnie – definicja automatu skończonego Rabina-Scotta, który obecnie jest jednym z podstawowych pojęć teorii automatów. Definicja 3.1. Automatem skończonym Moore’a jest szóstka uporządkowana A = <S, X, Y, M, O, s0>, gdzie S – skończony zbiór zwany zbiorem stanów, X – skończony zbiór zwany alfabetem wejściowym, Y – skończony zbiór zwany alfabetem wyjściowym, M: S×X → S – funkcja przejść, s0 ∈ S – stan początkowy, O: S → Y – funkcja wyjściowa. Definicja 3.2. Automatem skończonym Mealy’ego jest szóstka uporządkowana A = <S, X, Y, M, O, s0>, gdzie S – skończony zbiór zwany zbiorem stanów, X – skończony zbiór zwany alfabetem wejściowym, Y – skończony zbiór zwany alfabetem wyjściowym, M: S×X → S – funkcja przejść, s0 ∈ S – stan początkowy, O: S×X → Y – funkcja wyjściowa. Obydwa te modele automatów traktuje się jako „urządzenia” przekształcające słowa wejściowe na słowa wyjściowe. Rys. 3.1 przedstawia wspólny schemat konstrukcji automatów Moore’a i Mealy’ego, przy czym ich definicje róŜnią się tylko funkcją wyjściową. W automacie Moore’a wyjście zaleŜy wyłącznie od aktualnego stanu. Zapisywaną na taśmie wyjściowej odpowiedzią tego automatu na zapisane na taśmie wejściowej niepuste słowo a1a2…an ∈ X* jest słowo wyjściowe O(s0)O(s1)…O(sn), gdzie s1, s2,…, sn jest taką sekwencją stanów, Ŝe M(si-1, ai) = si dla 1 ≤ i ≤ n, zaś odpowiedzią na słowo puste ε jest O(s0). Natomiast w automacie Mealy’ego wyjście zaleŜy takŜe od symbolu czytanego na taśmie wejściowej. Będziemy przyjmowali dla wszystkich modeli automatów, iŜ czas rozbity jest na oddzielne takty i działanie automatów jest synchroniczne, tzn. zmiany stanów i ruchy głowicy odbywają się wyłącznie przy przejściu od dowolnego taktu do następnego taktu. Rys. 3.1. Schemat konstrukcji automatów Moore’a i Mealy’ego 9 W następnych wykładach będziemy zajmowali się wyłącznie automatami skończonymi Rabina-Scotta, nazywając je krócej – po prostu automatami skończonymi. PoniŜej definicja takiego automatu. Definicja 3.3. Automatem skończonym Rabina-Scotta jest piątka uporządkowana A = <S, X, M, s0, F>, gdzie S – skończony zbiór zwany zbiorem stanów, X – skończony zbiór zwany alfabetem wejściowym, M: S×X → 2S – funkcja przejść (2S jest tzw. zbiorem potęgowym, czyli zbiorem wszystkich podzbiorów zbioru S), s0 ∈ S – stan początkowy, F ⊆ S – zbiór stanów końcowych. Schemat konstrukcji automatu Rabina-Scotta róŜni się od wspólnego schematu automatów Moore’a i Mealy’ego tym, Ŝe w automacie Rabina-Scotta nie ma taśmy wyjściowej. Funkcję przejść zwykle rozszerza się w taki sposób, aby jej argumentami zamiast par (stan, symbol alfabetu wejściowego) były pary (stan, słowo nad alfabetem wejściowym): M: S×X* → 2S. Oto definicja indukcyjna tego rozszerzenia przy załoŜeniu, Ŝe s ∈ S oraz x ∈ X*: 1) M(s, ε) = {s} 2) jeśli M(s, x) = {s1, s2, … sk}, to M(s, xa) = M(s1, a) ∪ M(s2, a) ∪ … ∪ M(sk, a). Działanie automatu Rabina-Scotta wygląda następująco: w zaleŜności od aktualnego stanu s i symbolu a czytanego z taśmy wejściowej w danym takcie automat znajdzie się w następnym takcie w stanie M(s, a), a głowica przy przejściu do tego taktu przesuwa się na prawo do następnej klatki na taśmie wejściowej. W początkowym takcie pracy automat jest w stanie początkowym s0, taśma wejściowa zawiera słowo wejściowe i ma dokładnie tyle klatek ile wynosi jego długość, zaś działanie automatu kończy się, gdy głowica czytająca przesunie się na prawo od ostatniego symbolu słowa wejściowego – w zaleŜności od tego, czy automat jest wtedy w stanie końcowym czy nie, sygnalizowane jest odpowiednio akceptowanie lub nie słowa wejściowego. Definicja 3.4. Słowo x ∈ X* jest akceptowane przez automat A, jeśli M(s0, x) ∩ F ≠ Φ. Uwaga: PoniewaŜ M(s, ε) = {s}, to z powyŜszej definicji wynika, iŜ słowo puste ε jest akceptowane przez dowolny automat wtedy i tylko wtedy, gdy s0 ∈ F. Definicja 3.5. Zbiór wszystkich słów akceptowanych przez automat A nazywamy językiem akceptowanym przez automat A i oznaczamy przez L(A). Według definicji 3.3, 3.4 i 3.5 automat Rabina-Scotta jest „urządzeniem” akceptującym określony zbiór słów (czyli język), a nie „urządzeniem” przekształcającym słowa wejściowe na słowa wyjściowe (jak np. automaty Moore’a i Mealy’ego). 10 Definicja 3.6. Automat A nazywamy deterministycznym, jeśli dla kaŜdej pary (s,a) zbiór M(s,a) jest jednoelementowy. W przeciwnym przypadku automat A jest nazywany niedeterministycznym. Definicja 3.7. Automat A1 jest równowaŜny automatowi A2, jeśli L(A1) = L(A2). Przykłady automatów skończonych Rabina-Scotta podane zostaną w następnym wykładzie, gdy wprowadzimy bardziej wygodne sposoby opisu takich automatów. 11 Wykład 4 Graf przejść i tablica przejść automatu skończonego W niniejszym wykładzie podane są dwa sposoby opisu automatów skończonych Rabina-Scotta. Najczęściej stosowanym sposobem opisu automatu skończonego Rabina-Scotta jest graf przejść (zwany takŜe grafem stanów). Wierzchołkom tego grafu, narysowanym w postaci kółek, przyporządkowane są stany automatu (ich nazwy wpisywane są wewnątrz kółek). Stan początkowy oznaczany jest krótką strzałką skierowaną do wierzchołka s0, zaś stan końcowy – podwójnym kółkiem. Jeśli s’ ∈ M(s, a), to w grafie od wierzchołka s do wierzchołka s’ rysujemy krawędź oznaczoną symbolem a (będziemy teŜ wtedy mówili, Ŝe w grafie istnieje przejście z wierzchołka s do wierzchołka s’ pod wpływem symbolu wejściowego a). Jeśli z wierzchołka s istnieje więcej niŜ jedno przejście do wierzchołka s’, to rysujemy tylko jedną krawędź łączącą te wierzchołki i przy czym przy tej krawędzi piszemy wszystkie symbole odpowiadające przejściom z wierzchołka s do wierzchołka s’, oddzielając je przecinkami. Przykład 3.1. Graf przejść przedstawiony na Rys. 3.1 odpowiada automatowi skończonemu, w którym S = {s0, s1}, X = {a, b}, stanem początkowym jest s0, zaś jedynym stanem końcowym jest s1. Z rysunku wynika, Ŝe funkcja przejść M przyjmuje następujące wartości: M(s0, a) = {s0, s1}, M(s0, b) = {s1}, M(s1, a) = {s0}, M(s1, b) = Φ. Jest to automat niedeterministyczny, gdyŜ M(s0, a) i M(s1, b) nie są zbiorami jednoelementowymi. Rys. 3.1. Przykład grafu przejść automatu skończonego Rabina-Scotta Innym sposobem opisu automatu skończonego, stosowanym często w literaturze, jest tablica przejść. Wiersze takiej tablicy odpowiadają stanom, zaś kolumny – symbolom wejściowym. Jeśli M(s, a) = {s1, s2,…, sk}, to na przecięciu wiersza oznaczonego nazwą stanu s i kolumny oznaczonej symbolem a wpisujemy s1, s2,…, sk (bez nawiasu klamrowego, Ŝeby było prościej), zaś jeśli M(s, a) = Φ, to w odpowiedniej kratce wpisywana jest kreska lub zostawia się ją pustą. PoniŜej podana jest tablica przejść dla automatu, którego graf przejść pokazany jest na Rys. 3.1. Tabela 3.1 M s0 s1 a s0 , s1 s0 b s1 – 12 Przykład 3.2. Rys. 3.2 przedstawia graf przejść automatu skończonego, w którym S = {s0, s1, s2, s3, s4}, X = {0, 1}, stanem początkowym jest s0, zaś stanami końcowymi są s2 i s4. Na podstawie grafu przejść moŜna wyznaczyć wartości funkcji M. Rys. 3.2. Graf przejść automatu skończonego. Z Rys. 3.2 wynika, Ŝe funkcja przejść M przyjmuje następujące wartości: M(s0, 0) = {s0, s1} M(s1, 0) = {s2} M(s2, 0) = {s2} M(s3, 0) = Φ M(s4, 0) = {s4} M(s0, 1) = {s0, s3} M(s1, 1) = Φ M(s2, 1) = {s2} M(s3, 1) = {s4} M(s4, 0) = {s4}. Jest to automat niedeterministyczny, gdyŜ niektóre z powyŜszych wartości nie są zbiorami jednoelementowymi. Dla kaŜdego niedeterministycznego automatu skończonego A istnieje równowaŜny mu deterministyczny automat skończony A’, dla którego L(A’) = L(A). Podamy teraz prostą metodę konstrukcji automatu A’ na podstawie automatu A. ZałóŜmy, Ŝe A = <S, X, M, s0, F> jest automatem niedeterministycznym. RównowaŜny mu automat deterministyczny A’ musi mieć ten sam alfabet wejściowy co automat A, natomiast pozostałe cztery elementy piątki uporządkowanej będą zmienione, w szczególności jego zbiór stanów będzie równy 2S (tzn. zbiorowi wszystkich podzbiorów zbioru S), zaś stanem początkowym automatu A’ będzie ten podzbiór S, którego jedynym elementem jest stan początkowy automatu A: A’ = <2S, X, M’, {s0}, F’>. Jeśli T ∈ 2S jest niepustym zbiorem {t1, t2, … , tm} oraz a ∈ X, to M’(T, a) = M’(t1, a) ∪ M’(t2, a) ∪ … ∪ M’(tm, a), zaś M’(Φ, a) = Φ. Zbiór stanów końcowych F’ będzie zawierał te wszystkie stany ze zbioru 2S, które zawierają co najmniej jeden ze stanów końcowych automatu. 13 Przykład 3.3. Dla niedeterministycznego automatu skończonego A z przykładu 3.1, którego graf przejść przedstawiony jest na Rys. 3.1 wyznaczymy równowaŜny mu automat deterministyczny A’. Zbiór stanów tego automatu będzie zawierał następujące stany (wszystkie podzbiory zbioru stanów S): Φ, {s0}, {s1} {s0, s1}. Alfabetem wejściowym jest X = {0, 1}, stanem początkowym jest {s0}, zaś stanami końcowymi są {s1} i {s0, s1}. Z podanej wyŜej definicji funkcji przejść M’ wynika, Ŝe przyjmuje ona następujące wartości: M(Φ, a) = M(Φ, b) = { Φ } M({s0}, a) = { {s0, s1} } M({s0}, b) = { {s1} } M({s1}, a) = { {s0} } M({s1}, b) = { Φ } M({s0, s1}, a) = { {s0, s1} } M({s0, s1}, b) = { {s1} } Tak skonstruowany automat A’ jest automatem deterministycznym, gdyŜ wszystkie wartości funkcji M’ są pojedynczymi stanami automatu A’. Na Rys. 3.2 pokazany jest graf przejść deterministycznego automatu A’ równowaŜnego niedeterministycznemu automatowi A z Rys. 3.1. Rys. 3.3. Graf przejść deterministycznego automatu, który jest równowaŜny niedeterministycznemu automatowi z Przykładu 3.1 14 Wykład 5 WyraŜenia regularne i języki regularne W niniejszym wykładzie podane są podstawowe definicje dotyczące wyraŜeń regularnych, które są wygodnym sposobem opisu języków regularnych, czyli języków akceptowanych przez automaty skończone. Definicja 5.1. WyraŜenia regularne nad dowolnym alfabetem A definiowane są w następujący sposób: 1) Φ i ε są wyraŜeniami regularnymi, 2) jeŜeli a ∈ A, to a jest wyraŜeniem regularnym, 3) jeŜeli P i Q są wyraŜeniami regularnymi, to P + Q, PQ, P*, (P) są teŜ wyraŜeniami regularnymi 4) tylko takie wyraŜenia są regularne, które moŜna otrzymać stosując skończoną liczbę razy powyŜsze reguły 1-3, przy rozmieszczaniu nawiasów kierując się następującą hierarchią operacji: najniŜszy priorytet ma operacja +, zaś najwyŜszy – operacja *. Przykład: Jeśli uwzględnić podaną w Definicji 5.1 hierarchię operacji w wyraŜeniach regularnych, to nawiasy w wyraŜeniu {[0(1*)]+0} moŜna pominąć, dzięki czemu otrzymuje się prostsze wyraŜenie 01*+0. Definicja 5.2. WyraŜenia regularne nad dowolnym alfabetem A opisują języki regularne w następujący sposób: 1) wyraŜenie regularne Φ opisuje język pusty Φ, 2) wyraŜenie regularne ε opisuje język {ε}, 3) jeŜeli a ∈ A, to wyraŜenie regularne a opisuje język {a}, 4) jeŜeli wyraŜenia regularne P i Q opisują języki LP i LQ, to P + Q, PQ i P* opisują odpowiednio języki LP ∪ LQ, LPLQ i LP*. Przykłady. Rozpatrzmy proste wyraŜenia regularne nad alfabetem {0, 1} i opisywane przez nie języki regularne: - wyraŜenie 0 + 1 opisuje język {0, 1} - wyraŜenie 00 opisuje język {00} - wyraŜenie 01 + 11 opisuje język {01, 11} - wyraŜenie (0 + 1)* opisuje język {0, 1}*, tzn. słownik nad alfabetem {0, 1} - wyraŜenie 01 (0 + 1)* opisuje język {01}{0, 1}*, tzn. zbiór wszystkich słów, w których pierwszym symbolem jest 0, zaś drugim symbolem jest 1 - wyraŜenie (0 + 1)*10 opisuje język {0, 1}* {10}, tzn. zbiór wszystkich słów, w których przedostatnim symbolem jest 1, zaś ostatnim symbolem jest 0 - wyraŜenie (0 + 1)* 0 (0 + 1)* opisuje język {0, 1}* {0} {0, 1}*, tzn. zbiór wszystkich słów, w których co najmniej jeden raz występuje symbol 0 - wyraŜenie (0 + 1)* 00 (0 + 1)* opisuje język {0, 1}* {00} {0, 1}*, tzn. zbiór wszystkich słów, w których co najmniej jeden raz występuje para stojących obok siebie symboli 0 - wyraŜenie (0 + 1)* 000 (0 + 1)* opisuje język {0, 1}* {000} {0, 1}*, tzn. zbiór wszystkich słów, w których trójka kolejnych symboli 0 występuje co najmniej jeden raz - wyraŜenie 1* 0 1* opisuje język {1}* {0} {1}*, tzn. zbiór wszystkich słów, w których co symbol 0 występuje dokładnie jeden raz Jak widać w powyŜszych przykładach, wyraŜenia regularne są zwykle prostsze, bo zawierają mniej nawiasów. Wykonywanie operacji na nich jest teŜ prostsze, gdyŜ moŜna je traktować analogicznie jak wyraŜenia algebraiczne, stosując podobne reguły przekształceń. 15 Wykład 6 RównowaŜność wyraŜeń regularnych i ich upraszczanie W niniejszym wykładzie podane są podstawowe wiadomości na temat równowaŜności i upraszczania wyraŜeń regularnych. Definicja 6.1. Dwa wyraŜenia regularne są równowaŜne, jeśli opisują ten sam język. Niech P, Q i R będą wyraŜeniami regularnymi nad dowolnym alfabetem A. Oto lista najczęściej stosowanych toŜsamości dla wyraŜeń regularnych: 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) 17) 18) P+P=P P+Q=Q+P P + (Q + R) = (P + Q) + R P(QR) = (PQ)R P(Q + R) = PQ + PR (P + Q)R = PR + QR PΦ = ΦP = Φ P+Φ=Φ+P=P Pε = εP = P PP* = P*P P*P* = P* (P + ε)* = P* ε* = ε Φ* = ε (P*)* = P* (ε + PP*) = P* P(QP)* = (PQ)*P (P* + Q*)* = (P*Q*)* = (P + Q*)* = (P + Q)* Przykłady upraszczania wyraŜeń regularnych: 1) WyraŜenie ε + 1* (011)* [1*(011)*]* moŜemy stosując toŜsamość nr 16 przekształcić na [1*(011)*]*, a to wyraŜenie z kolei stosując toŜsamość nr 17 przekształcić na (1+011)*. Zatem wyraŜenia ε + 1* (011)* [1*(011)*]* i (1+011)* są równowaŜne. 2) WyraŜenie (1 + 00*1) + (1+00*1) (0 + 10*1)* (0 + 10*1) moŜemy uprościć stosując kolejno toŜsamości nr 5, 10, 16, 6 i 16: (1 + 00*1) + (1+00*1) (0 + 10*1)* (0 + 10*1) = (1 + 00*1) [ε + (0 + 10*1)* (0 + 10*1)] = = (1 + 00*1) [ε + (0 + 10*1) (0 + 10*1)*] = (1 + 00*1) (0 + 10*1)* = (ε + 00*)1(0 + 10*1)* = 0*1(0 + 10*1)* 3) WyraŜenie 0*1 [ε + (0 + 1) 0*1)]* [ε + (0 + 1)0*1] + 0*1 moŜna uprościć stosując kolejno toŜsamości nr 9 i 5, dzięki czemu otrzymuje się wyraŜenie: 0*1 {[ε + (0 + 1) 0*1)]* [ε + (0 + 1)0*1] + ε}, a dalej stosując do wyraŜenia w nawiasach{ i } toŜsamości nr 2 i 16, otrzymuje się: 0*1 [ε + (0 + 1) 0*1)]*, co po zastosowaniu toŜsamości nr 12 daje jeszcze prostszą postać: 0*1 [(0 + 1) 0*1)]*. 16 PoniŜej podane są podstawowe własności wyraŜeń regularnych dla dowolnych a ∈ A, x, y ∈ A*, oraz dla dowolnych języków L, L1, L2 nad alfabetem A (analogiczne do podanych u góry strony 4 w Wykładzie 2). 1) Φ // x = Φ 2) L // ε = L 3) L // xy = (L // x) // y 4) (L1 + L2) // x = (L1 // x) + (L2 // x) 5) (L1 ∪ L2) // x = (L1 // x) ∪ (L2 // x) 6) (L1L2) // a = (L1 // a)L2 ∪ (L2 // a), gdy ε ∈ L1 (L1L2) // a = (L1 // a)L2, w przeciwnym przypadku 7) (L*) // x = (L // x) L* 17 Wykład 7 Synteza automatów skończonych W niniejszym wykładzie opisany jest algorytm syntezy automatów skończonych Rabina-Scotta, tzn. algorytm przejścia od wyraŜenia regularnego opisującego język regularny do grafu stanów deterministycznego automatu skończonego o minimalnej liczbie stanów, akceptującego ten język. Jest to jeden z wielu algorytmów syntezy opublikowanych w literaturze na temat teorii automatów. Oparty jest on na pojęciu prawostronnego ilorazu. Na końcu wykładu podane są przykłady jego stosowania. Opisywany algorytm wynika z następującego twierdzenia: Twierdzenie. Dla dowolnego alfabetu X, dowolnego języka regularnego L nad tym alfabetem i dowolnego słowa x ∈ X* liczba róŜnych wartości ilorazów L//x jest skończona. Podamy teraz opis algorytmu syntezy automatu skończonego Rabina-Scotta (patrz Wykład 3, Definicja 3.3) A = <S, X, M, s0, F>. Weźmy dowolny język regularny L ⊆ X*. Niech liczba wszystkich róŜnych wartości ilorazów L//x , gdzie x ∈ X*, będzie równa n. Oznaczmy je w następujący sposób: L0=L//ε =L, L1, … , Ln-1. Tym wartościom ilorazów przyporządkujemy wzajemnie jednoznacznie stany konstruowanego automatu, których liczba teŜ będzie wynosiła n. Ilorazowi L0 przyporządkujemy stan początkowy s0, ilorazowi L1 przyporządkujemy stan s1, …, ilorazowi Ln-1 przyporządkujemy stan sn-1. Zbiór stanów końcowych F będzie zbiórem tych stanów, które przyporządkowane są wartościom ilorazów zawierającym słowo puste. Funkcja przejść M definiowana jest w następujący sposób: M(si, a) = sj wtedy i tylko wtedy, gdy 1) językowi Li jest przyporządkowany stan si, 2) językowi Lj jest przyporządkowany stan sj, oraz 3) Lj = Li//a. Uwaga: W podanych przykładach języki definiowane będą - dla uproszczenia - nad alfabetem {0,1} o dwóch symbolach, ale prezentowany algorytm moŜe być stosowany dla dowolnych alfabetów X. Obliczanie ilorazów jest proste, gdy pamięta się regułę podaną w Wykładzie 2 (w Uwadze po Definicji 2.8): jeśli mamy obliczyć prawostronny iloraz języka L przez słowo x, to wystarczy wybrać z języka L te słowa, które mają przedrostek x, a następnie obliczyć ich ilorazy przez x (suma mnogościowa tych ilorazów jest równa L//x). W odniesieniu do wyraŜeń regularnych nad alfabetem {0,1} regułę tę moŜna sformułować prościej w następujący sposób: jeśli wyraŜenie regularne ma postać sumy wyrazów, to przy obliczaniu prawostronnego ilorazu przez symbol 0, jeśli wyraz ma postać 0w, to wynik równa się w, jeśli natomiast ma postać 1w, to wynik równa się Φ. Analogicznie postępuje się przy obliczaniu prawostronnego ilorazu przez symbol 1. Przypominamy takŜe, iŜ 0//0 = ε, ε//0 = Φ, Φ //0 = Φ , ε//1 = Φ, Φ //1 = Φ. 1//1 = ε, 18 Obliczanie ilorazów L//x będziemy wykonywać zaczynając od słowa x = ε, następnie dla słów x o długości 1, potem dla słów x o długości 2, itd. Na podstawie własności nr 3 na liście podanej na końcu Wykładu 6: L//xy = (L//x)//y przy obliczaniu ilorazów przez słowa x o długości (k+1) będziemy wykonywali zawsze tylko operację prawostronnego ilorazu przez pojedyncze symbole, tzn. wykorzystując przy tym wyniki obliczeń ilorazów przez słowa x o długości k, np. L//x0 = (L//x)//0 L//x1 = (L//x)//1. Jeśli przy takiej kolejności obliczania ilorazów otrzymamy wyraŜenie regularne definiujące wcześniej otrzymany język, nie bierzemy go do dalszych obliczeń, gdyŜ prowadziłyby one zawsze do otrzymywania tylko takich wyników, które juŜ występowały wcześniej. KaŜdy krok wykonywania algorytmu syntezy polega na: 1) obliczeniu wartości ilorazu wyraŜenia regularnego definiującego język L przez kolejne słowo (oznaczmy język definiowany przez nowo obliczony wynik przez Lk), 2) sprawdzeniu czy język Lk pojawił się wcześniej jako wynik obliczania ilorazów języka L przez kolejne słowa, a) jeśli pojawił się wcześniej, to temu wynikowi przyporządkujemy stan, który juŜ poprzednio był przyporządkowany wynikowi Lk, b) jeśli nie wystąpił wcześniej, to przyporządkowujemy mu nowy stan o kolejnym indeksie i sprawdzamy, czy jest to stan końcowy (czyli sprawdzamy, czy słowo puste naleŜy do języka Lk). Rysowanie grafu stanów zaczynamy od narysowania stanu początkowego s0, przy czym jeśli jest to zarazem stan końcowy, to oznaczenie stanu rysujemy w podwójnym kółku. Ze stanu początkowego prowadzimy dwie gałęzie (oznaczone symbolami 0 i 1) do stanów, które przyporządkowane są odpowiednio wynikom L//0 i L//1. Następnie przechodzimy do stanu o kolejnym indeksie, tzn. s1, (załóŜmy, Ŝe jest on przyporządkowany ilorazowi L//x) i analogicznie jak wyŜej prowadzimy gałęzie oznaczone symbolami 0 i 1 do stanów, które przyporządkowane są odpowiednio ilorazom L//x0 i L//x1. Jeśli któryś ze stanów przyporządkowanych ilorazom L//x0 i L//x1 jest końcowy, to jego oznaczenie umieszczamy w podwójnym kółku. Podobnie postępujemy dla stanów o kolejnych indeksach aŜ do momentu, kiedy oznaczenia wszystkich wyznaczonych stanów (wraz z wychodzącymi z nich gałęziami) znajdą się w grafie. Wyniki obliczania ilorazów przez słowa o tej samej długości będziemy grupowali razem, oddzielając je liniami ciągłymi od wyników obliczeń ilorazów przez słowa o mniejszej lub większej długości. Stany końcowe będziemy w tych obliczeniach oznaczali symbolem √ (w innych publikacjach stosowane są róŜne oznaczenia). Przykład 7.1. Skonstruować graf stanów deterministycznego automatu skończonego Rabina-Scotta o minimalnej liczbie stanów, który akceptuje język opisany następującym wyraŜeniem regularnym: L = 1 + 00 + 0010. Rozwiązanie. WyraŜenie regularne definiujące język L ma postać sumy wyrazów, z których kaŜdy zaczyna się od symbolu alfabetu. W takim przypadku obliczanie ilorazów jest proste na podstawie wyŜej sformułowanych reguł. 19 L//ε = L PoniewaŜ język L zawiera tylko słowa 1, 00, 0010, więc stan s0 nie jest końcowy, gdyŜ słowo puste nie naleŜy do tego języka. s0 L//0 = (1 + 00 + 0010)//0 = 1//0 + 00//0 + 0010//0 = Φ + 0 + 010 = 0 + 010 Wynik 0 + 010 jest nowy, poniewaŜ naleŜy do niego np. słowo 0, które nie naleŜy do L//ε = L. Dlatego wynikowi temu odpowiada nowy stan, który nie jest końcowy: s1 L//1 = (1 + 00 + 0010)//1 = 1//1 + 00//1 + 0010//1 = ε + Φ + Φ = ε (nowy wynik, gdyŜ) słowo puste nie naleŜało do poprzednio obliczonych języków s2 √ L//00 = (L//0)//0 = (0 + 010)//0 = 0//0 + 010//0 = ε + 10 (nowy wynik) L//01 = (L//0)//1 = (0 + 010)//1 = 0//1 + 010//1 = Φ + Φ = Φ (nowy wynik) L//10 = (L//1)//0 = ε//0 = Φ L//11 = (L//1)//1 = ε//1 = Φ s3 √ s4 s4 s4 L//000 = (L//00)//0 = (ε + 10)//0 = ε//0 + 10//0 = Φ + Φ = Φ L//001 = (L//00)//1 = (ε + 10)//1 = ε//1 + 10//1 = Φ + 0 = 0 (nowy wynik) Nie obliczamy ilorazów L//100, L//101, L//110 i L//111, poniewaŜ wyniki ilorazów L//10 i L//11 nie były nowe. s4 s5 s2 √ L//0010 = (L//001)//0 = 0//0 = ε L//0011 = (L//001)//1 = 0//1 = Φ s4 Podobnie jak wyŜej, nie obliczamy innych ilorazów przez słowa o długości 4, bowiem jedyny nowy wynik w poprzedniej grupie (ilorazy przez słowa o długości 3) dał iloraz L//001. PoniewaŜ ilorazy języka L przez słowa o długości 4 nie dały nowych wyników, kończymy obliczenia i rysujemy graf stanów (Rys. 7.1). Rys. 7.1. Graf stanów dla Przykładu 7.1 20 Przykład 7.2. Skonstruować graf stanów deterministycznego automatu skończonego Rabina-Scotta o minimalnej liczbie stanów, który akceptuje język opisany następującym wyraŜeniem regularnym: L = (1 + 00 + 0010)*. Rozwiązanie. Przekształcimy wyraŜenie regularne definiujące język L korzystając z toŜsamości 16 (patrz Wykład 5): P* = ε + PP*. Ta metoda jest skuteczna dla wielu wyraŜeń, w których występują wyrazy zaczynające się od operacji domknięcia. Przekształcamy wyraŜenie regularne definiujące język L na sumę wyrazów, z których kaŜdy będzie zaczynał się od pojedynczego symbolu alfabetu, co umoŜliwi proste obliczenie ilorazów L//0 i L//1: L = (1 + 00 + 0010)* = ε + (1 + 00 + 0010) (1 + 00 + 0010)* = = ε + 1(1 + 00 + 0010)* + 00(1 + 00 + 0010)* +0010(1 + 00 + 0010)* Przed rozpoczęciem obliczeń wygodnie jest zastąpić powtarzający się człon (1 + 00 + 0010)* przez L, zatem L = ε + 1L + 00L +0010 L. L//ε = L (język L zawiera słowo puste, więc stan początkowy jest zarazem końcowym) s0 √ L//0 = (ε + 1L + 00L +0010 L)//0 = Φ + Φ + 0L + 010L = 0L + 010L Jest to nowy wynik, gdyŜ słowo ε naleŜy do L//ε, natomiast nie naleŜy do L//0. s1 L//1 = (ε + 1L + 00L +0010 L)//1 = Φ + L + Φ + Φ = L s0 √ L//00 = (L//0)//0 = (0L + 010L)//0 = L + 10L Nowy wynik, bo np. słowo 10 naleŜy do L//00, natomiast nie naleŜy do L//ε i do L//0. s2 √ L//01 = (L//0)//1 = (0L + 010L)//1 = Φ + Φ = Φ (nowy wynik) s3 L//000 = (L//00)//0 = (L + 10L)//0 = L//0 + 10L//0 = L//0 + Φ = L//0 s1 L//001 = (L//00)//1 = (L + 10L)//1 = L//1 + 10L//1 = L + 0L Nowy wynik, gdyŜ np. słowo 0, które naleŜy do L//001, nie naleŜy do Ŝadnego z wcześniej obliczonych wyników. s4 √ L//0010 = (L + 0L)//0 = L//0 + L = 0L + 010L + L Nowy wynik, gdyŜ trzy słowa ε, 0 i 010, które naleŜą do L//0010, nie naleŜą wszystkie naraz do Ŝadnego z wcześniej obliczonych wyników. s5 √ L//0011 = (L + 0L)//1 = L//1 + Φ = L//1 s0 √ L //00100 = (0L + 010L + L)//0 = L + 10L + L//0 = L + 10L + 0L +010L Nowy wynik, gdyŜ cztery słowa ε, 0, 10 i 010, które naleŜą do L//0010, nie naleŜą wszystkie naraz do Ŝadnego z wcześniej obliczonych wyników. s6 √ L//00101 = (0L + 010L + L)//1 = Φ + Φ + L//1= L//1 s0 √ 21 L//001000 = (L + 10L + 0L +010L)//0 = L//0 + Φ + L + 010L = 0L + 010L+L +10L L//001001 = (0L + 010L + L)//1 = Φ + Φ + L//1 = L//1 s6 √ s4 √ PoniewaŜ ilorazy języka L przez słowa o długości 6 nie dały nowych wyników, kończymy obliczenia i rysujemy graf stanów (Rys. 7.2). Rys. 7.2. Graf stanów dla Przykładu 7.2 Przykład 7.3. Skonstruować graf stanów deterministycznego automatu skończonego o minimalnej liczbie stanów, który akceptuje język opisany następującym wyraŜeniem regularnym: L = (01*01)*1 + 10. Rozwiązanie. Zaczynamy od przekształcenia wyraŜenia regularnego definiującego język L korzystając z toŜsamości 16 (patrz Wykład 5): P* = ε + PP*. Dzięki temu otrzymamy sumę wyrazów, z których kaŜdy będzie zaczynał sie od pojedynczego symbolu alfabetu: L = (01*01)*1 + 10 = [ε + (01*01)(01*01)*]1 + 10 = 1 + 01*01(01*01)*1 + 10. 22 Przechodzimy do obliczania ilorazów : L//ε = L (słowo puste nie naleŜy do L) s0 L//0 = [1 + 01*01(01*01)*1 + 10]//0 = Φ + 1*01(01*01)*1 + Φ = 1*01(01*01)*1 Nowy wynik, gdyŜ wszystkie słowa naleŜące do tego języka mają na końcu 1, zaś język L//ε = L zawiera słowo 10. L//1 = [1 + 01*01(01*01)*1 + 10]//1 = ε + Φ + 0 = ε + 0 s1 s2 √ L//00 = (L//0)//0 = [1*01(01*01)*1]//0 = {(ε + 11*)[01(01*01)*1]}//0 = = [01(01*01)*1 + 11*01(01*01)*1]//0 = 1(01*01)*1 + Φ = 1(01*01)*1 Nowy stan, bo naleŜy do tego języka słowo 11, które nie naleŜy do poprzednich. L//01 = (L//0)//1 = [1*01(01*01)*1]//1 = {(ε + 11*)[01(01*01)*1]}//1 = = [01(01*01)*1 + 11*01(01*01)*1]//1 = Φ + 1*01(01*01)*1 = 1*01(01*01)*1 = L//0 L//10 = (L//1)//0 = (ε + 0)//0 = Φ + ε = ε L//11 = (L//1)//1 = (ε + 0)//1 = Φ + Φ = Φ s3 s1 s4 √ s5 s5 L//000 = (L//00)//0 = [1(01*01)*1]//0 = Φ = L//11 L//001 = (L//00)//1 = [1(01*01)*1]//1 = (01*01)*1 Nowy stan, gdyŜ nie zawiera słowa 10, które naleŜy do L, poza tym zawiera słowo 1, które nie naleŜy do pozostałych. s6 L//100 = (L//10)//0 = (ε)//0 = Φ = L//11 s5 L//101 = (L//10)//1 = (ε)//1 = Φ = L//11 s5 L//0010 = [(01*01)*1]//0 = {[ε + (01*01)(01*01)*]1}//0 = [1 + 01*01(01*01)*1]//0 = s1 = Φ + 1*01(01*01)*1 = 1*01(01*01)*1 = L//0 L//0011 = [(01*01)*1]//1 = {[ε + (01*01)(01*01)*]1}//1 = [1 + 01*01(01*01)*1]//1 = = ε + Φ = ε = L//10 s4 √ PoniewaŜ ilorazy języka L przez słowa o długości 4 nie dały nowych wyników, kończymy obliczenia i rysujemy graf stanów (Rys. 7.3). Rys. 7.3. Graf stanów dla Przykładu 7.3 23 POLI TECHNI KAWARSZAWSKA Ośr odekKszt ał ceni anaOdl egł ość-OKNO PW pl .Pol i t echni ki1,00661War szawa GmachGł ównyPol i t echni kiWar szawski ej ,p.324 Kont akt t el . :( 22)2347770( st udi ai nżyni er ski e) ( 22)2345785( st udni amagi st er ski eipodypl omowe) f ax ( 22)2345004 emai l :i nzyni er ski e@okno. pw. edu. pl magi st er ski e@okno. pw. edu. pl podypl omowe@okno. pw. edu. pl ht t p: / / www. okno. pw. edu. pl