Teorie jazyku˚ a automatu - RNDr. Šárka Vavrečková, Ph.D.

Transkript

Teorie jazyku˚ a automatu - RNDr. Šárka Vavrečková, Ph.D.
Šárka Vavrečková
Teorie jazyků
a automatů
II
Sbı́rka úloh pro cvičenı́
Slezská univerzita v Opavě
Filozoficko-přı́rodovědecká fakulta
Ústav informatiky
Opava, poslednı́ aktualizace 1. února 2012
Anotace: Tento dokument obsahuje přı́klady ke cvičenı́m z předmětů Teorie jazyků a automatů II. Studenti zde najdou řešené přı́klady s podrobně popsaným
postupem a neřešené přı́klady, na kterých si mohou sami postupy procvičit.
Teorie jazyků a automatů II – sbı́rka přı́kladů pro cvičenı́
RNDr. Šárka Vavrečková, Ph.D.
Dostupné na: http://fpf.slu.cz/~vav10ui/formal.html
Ústav informatiky
Filozoficko-přı́rodovědecká fakulta
Slezská univerzita v Opavě
Bezručovo nám. 13, 746 01 Opava
Sázeno v systému LATEX
Tato inovace předmětu Teorie jazyků a automatů II je spolufinancována Evropským sociálnı́m fondem a Státnı́m rozpočtem ČR, projekt č. CZ.1.07/2.3.00/09.0197, „Posı́lenı́
konkurenceschopnosti výzkumu a vývoje informačnı́ch technologiı́ v Moravskoslezském kraji“.
Předmluva
Tato skripta jsou určena pro studenty informatických oborů na Ústavu informatiky Slezské
univerzity v Opavě, do cvičenı́ předmětu Teorie jazyků a automatů II, jde vlastně o jakousi
cvičebnici a sbı́rku přı́kladů.
Navazujeme na obdobná skripta pro cvičenı́ z předmětu Teorie jazyků a automatů I, tedy
předpokládajı́ se již základnı́ znalosti v oblasti teoretické informatiky, ale ve skutečnosti
se oboje skripta tematicky poněkud překrývajı́. Je to z toho důvodu, že během několika
let procházejı́ oba předměty rozsáhlými změnami, a snahou je při přeskupovánı́ témat
nepotrhat souvislosti.
Ve skriptech se použı́vajı́ následujı́cı́ barevné ikony:
• Nové pojmy a popisy postupů, nacházejı́ se obvykle na začátku kapitol a sekcı́. Sloužı́
k připomenutı́ pojmů a postupů probı́raných na přednáškách, abychom na cvičenı́ch
při řešenı́ přı́kladů měli vše potřebné po ruce.
• Některé části textu jsou označeny fialovou ikonou, což znamená, že jde o nepovinné
úseky, které nejsou probı́rány. Jejich účelem je dobrovolné rozšı́řenı́ znalostı́ studentů
o pokročilá témata, na která obvykle při výuce nezbývá moc času.
• Červená je ikona pro upozorněnı́ a poznámky.
Přı́klad 0.1
P
L
Takto vypadá prostředı́ s přı́kladem. Čı́slo přı́kladu je 0.1.
Úkol
0.1
Otázky a úkoly, náměty na vyzkoušenı́, které se doporučuje při procvičovánı́ učiva provádět, jsou uzavřeny v tomto prostředı́. Pokud je v prostředı́ vı́ce úkolů, jsou čı́slovány.
iii
C
Obsah
1
2
3
Konečné automaty
1
1.1
Opakovánı́ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1.2
Determinismus a úplnost konečných automatů . . . . . . . . . . . . . . . . .
4
1.3
Odstraněnı́ nepotřebných stavů . . . . . . . . . . . . . . . . . . . . . . . . . .
7
Regulárnı́ jazyky
11
2.1
Pumping lemma pro regulárnı́ jazyky . . . . . . . . . . . . . . . . . . . . . .
11
2.2
Uzávěrové vlastnosti – operace nad regulárnı́mi jazyky . . . . . . . . . . . .
16
2.2.1
Sjednocenı́ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
2.2.2
Zřetězenı́ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
2.2.3
Iterace (Kleeneho uzávěr) . . . . . . . . . . . . . . . . . . . . . . . . .
22
2.2.4
Pozitivnı́ iterace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
2.2.5
Zrcadlový obraz (reverze) . . . . . . . . . . . . . . . . . . . . . . . . .
26
2.2.6
Průnik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
2.2.7
Homomorfismus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
2.3
Sestrojenı́ konečného automatu podle regulárnı́ho výrazu . . . . . . . . . . .
35
2.4
Vytvořenı́ regulárnı́ho výrazu podle konečného automatu . . . . . . . . . .
37
2.5
Minimalizace a normovánı́ konečného automatu . . . . . . . . . . . . . . . .
40
2.5.1
Minimálnı́ konečný automat . . . . . . . . . . . . . . . . . . . . . . .
40
2.5.2
Normovaný konečný automat . . . . . . . . . . . . . . . . . . . . . .
45
K zásobnı́kovým automatům
48
3.1
Využitı́ uzávěrových vlastnostı́ při konstrukci automatu . . . . . . . . . . .
48
3.2
Uzávěrové vlastnosti jako kritérium bezkontextovosti . . . . . . . . . . . . .
51
iv
v
4
5
Regulárnı́ gramatiky
52
4.1
Opakovánı́ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
4.2
Normálnı́ forma regulárnı́ch gramatik . . . . . . . . . . . . . . . . . . . . . .
54
Bezkontextové gramatiky
58
5.1
Derivačnı́ strom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
5.2
Úpravy bezkontextových gramatik . . . . . . . . . . . . . . . . . . . . . . . .
60
5.2.1
Redukce gramatiky . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
5.2.2
Převod na nezkracujı́cı́ bezkontextovou gramatiku . . . . . . . . . .
62
5.2.3
Odstraněnı́ jednoduchých pravidel . . . . . . . . . . . . . . . . . . . .
66
5.2.4
Gramatika bez cyklu a vlastnı́ gramatika . . . . . . . . . . . . . . . .
69
5.2.5
Levá a pravá rekurze . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
Normálnı́ formy bezkontextových gramatik . . . . . . . . . . . . . . . . . . .
76
5.3.1
Chomského normálnı́ forma . . . . . . . . . . . . . . . . . . . . . . .
76
5.3.2
Greibachové normálnı́ forma . . . . . . . . . . . . . . . . . . . . . . .
78
Kritéria bezkontextovosti . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
82
5.4.1
Pumping lemma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
82
5.4.2
Parikhův vektor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
85
5.3
5.4
6
Jazyky typu 0
88
6.1
Turingův stroj . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
88
6.1.1
Co je to Turingův stroj – pojmy a značenı́ . . . . . . . . . . . . . . . .
88
6.1.2
Navrhujeme Turingův stroj pro daný jazyk . . . . . . . . . . . . . . .
89
Gramatiky typu 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
95
6.2.1
Návrh gramatiky typu 0 . . . . . . . . . . . . . . . . . . . . . . . . . .
95
6.2.2
Kurodova normálnı́ forma . . . . . . . . . . . . . . . . . . . . . . . . .
97
6.2
vi
Kapitola
1
Konečné automaty
1.1
Opakovánı́
Nejdřı́v si zopakujeme něco z toho, co jsme se naučili v minulém semestru. Základy musı́me
znát dokonale, protože na nich budeme stavět po celý semestr.
Přı́klad 1.1
Jazyky zadané regulárnı́m výrazem zapı́šeme v množinovém zápisu. Ke každému jazyku
napı́šeme množinu všech jeho slov, která jsou kratšı́ než 5.
L1 = (ab)∗
Množinový zápis:
L1 = {(ab)n : n ≥ 0}
Slova kratšı́ než 5: {w ∈ L1 : |w| < 5} = {ε, ab, abab}
Mnemotechnická pomůcka: za index v množinovém zápisu dosazujeme postupně čı́sla
od nejnižšı́ hodnoty zadaného rozsahu, tj. od 0. Všimněte si symbolického zápisu – nelze
napsat rovnı́tko mezi jazyk L1 a množinu slov tohoto jazyka kratšı́ch než 5, je třeba to
zapsat jinak.
P
L2 = a∗ b∗ a
Množinový zápis: L2 = {am bn a : m, n ≥ 0}
Všimněte si: je třeba použı́t dva navzájem nezávislé indexy!
Slova kratšı́ než 5: {w ∈ L2 : |w| < 5} = a, aa, ba, aaa, aba, bba, a4 , a2 ba, ab2 a, b3 a
Mnemotechnická pomůcka: za indexy m a n v množinovém zápisu dosazujeme čı́sla
navzájem nezávisle (m = n = 0, m = 1 a n = 0, m = 0 a n = 1, atd.). Pozor, prázdné slovo
do jazyka nepatřı́!
1
P
1.1
OPAKOVÁNÍ
2
Přı́klad 1.2
Určı́me typ zadaného jazyka v Chomského hierarchii. Pokud se jedná o regulárnı́ jazyk,
vytvořı́me ekvivalentnı́ regulárnı́ výraz. Vypı́šeme všechna slova jazyka kratšı́ než 5.
L1 = (aa)i (bb)j : i, j ≥ 0
Jde o regulárnı́ jazyk. Ekvivalentnı́ regulárnı́ výraz: L1 = (aa)∗ (bb)∗
Slova kratšı́ než 5: {w ∈ L1 : |w| < 5} = ε, a2 , b2 , a2 b2 , a4 , b4
L2 = (aa)i (bb)i : i ≥ 0
Tento jazyk je sice podobný předchozı́mu, ale nenı́ to regulárnı́ jazyk (je bezkontextový).
Proto nelze vytvořit ekvivalentnı́ regulárnı́ výraz.
Jak poznáme, že nenı́ regulárnı́? Pokud je třeba (při zpracovánı́ slov jazyka automatem)
synchronizovat dvě nebo dokonce vı́ce částı́ slova (totéž pı́smeno indexu se vyskytuje na
vı́ce mı́stech v množinové reprezentaci), nejde o regulárnı́ jazyk. To lze dokázat napřı́klad
pomocı́ Pumping lemma (budeme brát později).
Slova kratšı́ než 5: {w ∈ L2 : |w| < 5} = ε, a2 b2
Srovnejte s obdobnou množinou pro jazyk L1 z tohoto přı́kladu.
L3 = 0i 1i 0i : i ≥ 1
Jde o jazyk typu 1 v Chomského hierarchii, nenı́ to regulárnı́ ani bezkontextový jazyk.
Slova kratšı́ než 5: {w ∈ L3 : |w| < 5} = {010}
Přı́klad 1.3
Vypı́šeme všechna slova jazyka kratšı́ než 5.
n
L1 = ai bj : 1 ≤ i ≤ j ∪ ck : k ≤ 3
o
Slova kratšı́ než 5: {w ∈ L1 : |w| < 5} = ab, ab2 , a2 b2 , ε, c, c2 , c3
Poměrně častou chybou bývá „otočenı́“ relačnı́ho znaménka. V předpisu druhé množiny
sjednocenı́ máme symbol „menšı́ nebo rovno“, ne naopak, musı́me tedy vypsat slova o délce
0 až 3.
L2 = ai bj : 1 ≤ i ≤ j ∩ ai bj : 1 ≤ j ≤ i
Když se pozorně podı́váme na množiny, jejichž průnikem je jazyk L2 , zjistı́me, že tento
jazyk můžeme zapsat jednodušeji, protože prvnı́ množina nám dává podmı́nku „symbolů
b má být stejně nebo vı́ce než symbolů a“, druhá množina předepisuje „symbolů b má být
stejně nebo méně než symbolů a“:
L2 = ai bi : i ≥ 1
Slova kratšı́ než 5: {w ∈ L2 : |w| < 5} = ab, a2 b2
Pozor na rozdı́l mezi sjednocenı́m a průnikem, záměna těchto dvou množinových operacı́
je poměrně častou chybou.
P
1.2
DETERMINISMUS A ÚPLNOST KONEČNÝCH AUTOMATŮ
3
Přı́klad 1.4
Pro zadané jazyky sestrojı́me konečný automat ve všech třech reprezentacı́ch.
L1 = ab∗
Stavový diagram:
Tabulka přechodů:
δ-funkce:
A1 = ({q0 , q1 }, {a, b}, δ, q0 , {q1 })
δ(q0 , a) = q1
δ(q1 , b) = q1
a
→
←
q0
q1
b
a
q1
q0
b
q1
q1
Všimněte si, že u δ-funkce je nutné uvádět plnou specifikaci, aby bylo zřejmé, který
stav je počátečnı́ a které stavy jsou koncové, u jiných reprezentacı́ jsou tyto informace
zaznamenány jinak.
L2 = ab∗ + ε
Tabulka přechodů:
δ-funkce:
A2 = ({q0 , q1 }, {a, b}, δ, q0 , {q0 , q1 })
δ(q0 , a) = q1
δ(q1 , b) = q1
Úkol
a
↔
←
q0
q1
Stavový diagram:
b
a
q1
q0
b
q1
q1
1.1
Srovnejte automaty pro jazyky L1 a L2 z tohoto přı́kladu a zjistěte, jaké důsledky mělo
přidánı́ prázdného slova k jazyku u jednotlivých reprezentacı́ automatu.
C
Přı́klad 1.5
Pro zadaný jazyk sestrojı́me konečný automat ve všech třech reprezentacı́ch.
L = a∗ b + b∗ a
δ-funkce:
Tabulka přechodů:
A = ({q0 , q1 , q2 }, {a, b}, δ, q0 , {q1 , q2 })
δ(q0 , a) = q1
δ(q0 , b) = q2
δ(q1 , b) = q1
δ(q2 , a) = q2
→
←
←
q0
q1
q2
a
b
q1
q2
q1
q2
Stavový diagram:
b
q1
a
q0
a
b
q2
Všimněte si, jakým způsobem se v reprezentacı́ch automatu projevila operace sčı́tánı́
regulárnı́ch (pod)výrazů. Jazyk lze zapsat také následovně – v množinovém zápisu s využitı́m operace sjednocenı́ množin:
L = abi : i ≥ 0 ∪ bai : i ≥ 0
P
1.2
DETERMINISMUS A ÚPLNOST KONEČNÝCH AUTOMATŮ
1.2
4
Determinismus a úplnost konečných automatů
Nedeterministický konečný automat je takový automat, kde v alespoň jednom stavu lze na
některý signál reagovat vı́ce různými způsoby. Platı́ (viz přednášky), že třı́da jazyků rozpoznávaných deterministickými konečnými automaty a třı́da jazyků rozpoznávaných těmi
nedeterministickými jsou ekvivalentnı́, a tedy existuje postup, jak k nedeterministickému
automatu sestrojit ekvivalentnı́ deterministický a naopak.
Vytvořenı́ nedeterministického podle deterministického je triviálnı́, stačı́ v přechodové
funkci přidat množinové závorky. Opačný postup již nenı́ triviálnı́, postupujeme takto:
• v ekvivalentnı́m deterministickém automatu budou stavy určeny množinami stavů
původnı́ho nedeterministického automatu,
• pro každou dvojici stav–signál v původnı́m automatu vytvořı́me množinu stavů, které
jsou cı́lem přechodů vedoucı́ch z daného stavu na daný signál,
• pro každý stav nového automatu (tj. množinu stavů původnı́ho automatu) určı́me
přechody pomocı́ operace sjednocenı́ množin.
Postup si připomeneme na přı́kladu.
Přı́klad 1.6
Je dán nedeterministický konečný automat. Sestrojı́me ekvivalentnı́ deterministický.
δ-funkce:
Tabulka přechodů:
AN = ({0, 1, 2}, {a, b}, δN , 0, {2})
δN (0, a) = {1, 2}
δN (0, b) = {1}
δN (1, a) = {0}
δN (2, a) = {2}
δN (2, b) = {0, 1}
→
←
←
0
1
2
a
b
1,2
0
2
1
Stavový diagram:
0,1
b
q1
a
q0
a
b
q2
Nejdřı́v určı́me stavy nového automatu. To budou množiny obsahujı́cı́ stavy původnı́ho
automatu:
n
{0}, {1}, {2}, {0, 1}, {0, 2}, {1, 2}, {0, 1, 2}
o
Počátečnı́ stav bude {0}, množina koncových stavů bude obsahovat právě ty množiny původnı́ch stavů, kde alespoň jeden původnı́ stav je koncový, tj.
n
o
{1}, {2}, {0, 1}, {0, 2}, {1, 2}, {0, 1, 2} .
Zbývá určit přechodovou funkci – postupujeme podle předpisu:
δD {q1 , . . . , qk }, a =
[
δN (qi , a)
i=1,...,k
kde δD a δN jsou přechodové funkce nového deterministického a původnı́ho nedeterministického automatu, qi jsou stavy původnı́ho automatu a symbol a je některým prvkem
abecedy (a ∈ Σ).
P
1.2
DETERMINISMUS A ÚPLNOST KONEČNÝCH AUTOMATŮ
5
Předpis nám řı́ká, že budeme jednoduše sjednocovat množiny, tedy:
AD =
n
o
{0}, {1}, {2}, {0, 1}, {0, 2}, {1, 2}, {0, 1, 2} , {a, b}, δD , {0},
n
o
{1}, {2}, {0, 1}, {0, 2}, {1, 2}, {0, 1, 2}
δD ({0}, a) = {1, 2}
δD ({0}, b) = {1}
δD ({1}, a) = {0}
δD ({2}, a) = {2}
δD ({2}, b) = {0, 1}
δD ({0, 1}, a) = {1, 2} ∪ {0} = {0, 1, 2}
δD ({0, 1}, b) = {1} ∪ ∅ = {1}
δD ({0, 2}, a) = {1, 2} ∪ {2} = {1, 2}
δD ({0, 2}, b) = {1} ∪ {0, 1} = {0, 1}
δD ({1, 2}, a) = {0} ∪ {2} = {0, 2}
δD ({1, 2}, b) = ∅ ∪ {0, 1} = {0, 1}
δD ({0, 1, 2}, a) = {1, 2} ∪ {0} ∪ {2} = {0, 1, 2}
δD ({0, 1, 2}, b) = {1} ∪ ∅ ∪ {0, 1} = {0, 1}
V tabulce přechodů:
→
←
←
←
←
←
←
{0}
{1}
{2}
{0, 1}
{0, 2}
{1, 2}
{0, 1, 2}
Stavový diagram:
b
0
a
a
b
1, 2
a
a
a
b
{1, 2}
{0}
{2}
{1}
{1, 2} ∪ {0} = {0, 1, 2}
{1, 2} ∪ {2} = {1, 2}
{0} ∪ {2} = {0, 2}
{0, 1}
{1, 2} ∪ {0} ∪ {2} = {0, 1, 2}
b
1
b
a
0, 1
b
b
0, 2
a
2
0,1,2 a
{1} ∪ ∅ = {1}
{1} ∪ {0, 1} = {0, 1}
∅ ∪ {0, 1} = {0, 1}
{1} ∪ ∅ ∪ {0, 1} = {0, 1}
Je zřejmé, že stav {2} je ve výsledném
deterministickém automatu nedosažitelný (nevede do něj žádná cesta z počátečnı́ho stavu), proto lze tento stav
odebrat při zachovánı́ rozpoznávaného
jazyka.
Postup můžeme zkrátit – nové stavy (množiny původnı́ch stavů) lze vytvářet „dynamicky
podle potřeby“, tedy pokud se v některé buňce uvnitř tabulky (resp. za rovnı́tkem v předpisu δ-funkce) nacházı́ množina původnı́ch stavů, kterou ještě nemáme v ohodnocenı́ žádného řádku (resp. v parametru δ-funkce), přidáme nový řádek s tı́mto ohodnocenı́m a sestrojı́me operacı́ sjednocenı́ množin obsah buněk na řádku (resp. výsledek δ-funkce), to
provádı́me rekurzı́vně tak dlouho, dokud nebudou vytvořeny všechny přechody.
P
1.2
DETERMINISMUS A ÚPLNOST KONEČNÝCH AUTOMATŮ
6
Totálnı́ (úplný) konečný automat je takový deterministický konečný automat, kde v každém stavu lze reagovat na jakýkoliv signál z abecedy. Zúplněnı́ konečného automatu (tj.
vytvořenı́ ekvivalentnı́ho totálnı́ho automatu) se provádı́ takto:
1. vytvořı́me deterministický automat ekvivalentnı́ původnı́mu nedeterministickému,
2. přidáme nový stav (obvykle se označuje ∅), tento stav bude fungovat jako „odpadkový
koš“, nesmı́ patřit do množiny koncových stavů,
3. pokud v některém stavu nelze reagovat na některý signál, vytvořı́me pro tento signál
nový přechod vedoucı́ do stavu ∅,
4. totéž provedeme i pro stav ∅, i v tomto stavu je třeba reagovat na jakýkoliv signál.
Přı́klad 1.7
V přı́kladu 1.6 jsme vytvořili deterministický konečný automat ekvivalentnı́ původnı́mu
nedeterministickému. Ukážeme si jeho zúplněnı́, tj. vytvořı́me ekvivalentnı́ totálnı́ (úplný)
automat.
ADT =
n
o
{0}, {1}, {2}, {0, 1}, {0, 2}, {1, 2}, {0, 1, 2}, ∅ , {a, b}, δD , {0},
n
{1}, {2}, {0, 1}, {0, 2}, {1, 2}, {0, 1, 2}
δD ({0, 1}, a) = {1, 2} ∪ {0} = {0, 1, 2}
δD ({0, 1}, b) = {1} ∪ ∅ = {1}
δD ({0, 2}, a) = {1, 2} ∪ {2} = {1, 2}
δD ({0, 2}, b) = {1} ∪ {0, 1} = {0, 1}
δD ({1, 2}, a) = {0} ∪ {2} = {0, 2}
δD ({1, 2}, b) = ∅ ∪ {0, 1} = {0, 1}
δD ({0}, a) = {1, 2}
δD ({0}, b) = {1}
δD ({1}, a) = {0}
δD ({2}, a) = {2}
δD ({2}, b) = {0, 1}
δD ({1}, b) = ∅
δD (∅, a) = ∅
δD (∅, b) = ∅
δD ({0, 1, 2}, a) = {1, 2} ∪ {0} ∪ {2} = {0, 1, 2}
δD ({0, 1, 2}, b) = {1} ∪ ∅ ∪ {0, 1} = {0, 1}
Tabulka přechodů:
→
←
←
←
←
←
←
{0}
{1}
{2}
{0, 1}
{0, 2}
{1, 2}
{0, 1, 2}
∅
o
Stavový diagram:
a
b
{1, 2}
{0}
{2}
{0, 1, 2}
{1, 2}
{0, 2}
{0, 1, 2}
∅
{1}
∅
{0, 1}
{1}
{0, 1}
{0, 1}
{0, 1}
∅
b
0
a
a
b
1, 2
a
a
b
1
b
a
0, 1
b
b
0, 2
a, b
∅
0,1,2 a
P
1.3
ODSTRANĚNÍ NEPOTŘEBNÝCH STAVŮ
7
Proč jsou vlastnosti determinismu a úplnosti důležité? Protože pouze pro to, co lze popsat
deterministickým postupem, existuje algoritmus a lze to naprogramovat, a úplnost je důležitá při programovánı́ postupů s předvı́datelným chovánı́m – program by měl reagovat
předvı́datelně v každé situaci, i kdyby to mělo být třeba jen vypsánı́ chybového hlášenı́.
Nový stav přidávaný během zúplňovánı́ si můžeme představit jako „chybový stav“ sloužı́cı́
k ošetřenı́ chyb.
Úkol
1.2
1. Uvedené nedeterministické konečné automaty reprezentované tabulkami převed’te
na ekvivalentnı́ deterministické. Ke každému vytvořte stavový diagram původnı́ho nedeterministického automatu i vytvořeného deterministického a porovnejte.
Všechny vytvořené automaty zúplňte.
a
↔
←
A
B
C
b
B
A
B
c
B, C
C
→
←
←
q0
q1
q2
0
1
q0 , q1
q1
q0 , q1
q2
→
←
q0
q1
q2
a
b
q1 , q2
q2
q0
q1
q2
L
C
c
q1
q2
2. K zadaným konečným automatům sestrojte ekvivalentnı́ deterministické totálnı́ automaty. Před zúplněnı́m můžete odstranit nepotřebné stavy. Výsledný automat napište
ve všech třech formách (δ-funkce, tabulka přechodů, stavový diagram).
A1 = ({0, 1, 2}, {a, b}, δ, 0, {2})
δ(0, b) = {1, 2}
δ(1, a) = {0, 1}
δ(1, b) = {0}
δ(2, a) = {1}
1.3
A2 = ({0, 1, 2}, {a, b}, δ, 0, {2})
δ(0, a) = {1, 2}
δ(1, a) = {1}
δ(1, b) = {0, 2}
δ(2, b) = {1}
Odstraněnı́ nepotřebných stavů
Nepotřebné stavy jsou stavy, které nejsou použity při žádném úspěšném výpočtu (tj. končı́cı́m v koncovém stavu). Jedná se o stavy
• nedosažitelné – neexistuje k nim cesta z počátečnı́ho stavu,
• nadbytečné – neexistuje cesta z tohoto stavu do jakéhokoliv koncového stavu.
S odstraňovánı́m (lépe řečeno ignorovánı́m, neuvedenı́m či vypuštěnı́m) prvnı́ho typu
nepotřebných stavů – nedosažitelných – jsme se setkali už u zkráceného postupu pro převod
nedeterministického automatu na deterministický. Pokud nové řádky tabulky přechodů
P
1.3
ODSTRANĚNÍ NEPOTŘEBNÝCH STAVŮ
8
tvořı́me jen pro takové množiny původnı́ch stavů, které se již vyskytly v některé buňce,
většinu nedosažitelných stavů (ale ne vždy všechny) automaticky odstraňujeme.
Když chceme odstranit nepotřebné stavy, vždy začı́náme nedosažitelnými stavy a až
potom odstranı́me nadbytečné. V obou přı́padech postupujeme rekurzı́vně, a to bud’ podle
stavového diagramu nebo podle tabulky přechodů.
• nedosažitelné stavy: jako bázi (základnı́ množinu) zvolı́me S0 = {q0 } (obsahuje pouze
počátečnı́ stav), dalšı́ prvky přidáváme „ve směru šipek“ v stavovém diagramu, resp.
v tabulce přechodů ve směru označenı́ řádku → obsah buněk na řádku, postupně
vytvářı́me množinu všech stavů, do kterých vede cesta z počátečnı́ho stavu o délce
max. 0, 1, . . . , n kroků (toto čı́slo je dolnı́ index u označenı́ vytvářené množiny Si );
• nadbytečné stavy: jako bázi naopak zvolı́me množinu koncových stavů – E0 = F , dalšı́
prvky přidáváme „proti směru šipek“ v stavovém diagramu, resp. ve směru obsah
některé buňky tabulky přechodů → označenı́ řádku, vytvářı́me množinu všech stavů,
ze kterých vede cesta do některého koncového stavu o délce max. 0, 1, . . . , n kroků.
Formálnı́ zápis pro automat A = (Q, Σ, δ, q0 , F ):
• S0 = {q0 }
Si = Si−1 ∪ {q : δ(p, a) = q, kde p ∈ Si−1 , a ∈ Σ} , pro i ≥ 1
• E0 = F
Ei = Ei−1 ∪ {p : δ(p, a) = q, kde q ∈ Si−1 , a ∈ Σ} , pro i ≥ 1
Index i samozřejmě nejde do nekonečna, iteraci lze omezit hornı́ hranicı́ |Q|, tedy mohutnostı́ (počtem prvků) množiny stavů automatu (tj. 1 ≤ i ≤ |Q|).
Přı́klad 1.8
V zadaném konečném automatu odstranı́me nedosažitelné a nadbytečné stavy.
→ q0
← q1
q2
q3
← q4
← q5
a
b
q1
q1
q3
q3
q5
q5
q3
q2
q2
c
q5
q0
q3
a
q0
c
b
a q3
a
a
c
q1
b
b
q2
c
a
a
q5
q4
Odstranı́me nedosažitelné stavy (do kterých neexistuje cesta z počátečnı́ho stavu):
S0
S1
S2
S3
= {q0 }
= {q0 } ∪ {q1 , q3 } = {q0 , q1 , q3 } (ze stavu q0 vede přechod do q1 a q3 )
= {q0 , q1 , q3 } ∪ {q5 , q2 } = {q0 , q1 , q3 , q5 , q2 }
= {q0 , q1 , q3 , q5 , q2 } = S2 (konec, v poslednı́m kroku žádný stav do množiny nepřibyl)
1.3
ODSTRANĚNÍ NEPOTŘEBNÝCH STAVŮ
9
V množině S3 nenı́ stav q4 , je tedy nedosažitelný z počátečnı́ho stavu a můžeme ho
z automatu odstranit. V každé z množin Si , které jsme postupně vytvořili, najdeme všechny
stavy, které jsou z počátečnı́ho stavu dosažitelné po nejvýše i krocı́ch.
Dále zjistı́me, ze kterých stavů nevede cesta do koncových stavů. Budeme pracovat již
s automatem po odstraněnı́ stavu q4 .
E0
E1
E2
E3
= F = {q1 , q5 }
= {q1 , q5 } ∪ {q0 } = {q1 , q5 , q0 } (do stavů z E0 vede přechod pouze ze stavu q0 )
= {q1 , q5 , q0 , q2 }
= {q1 , q5 , q0 , q2 } = E2
V množině E3 nenı́ stav q3 , to znamená, že z tohoto stavu neexistuje žádná cesta do
koncového a tedy když tento stav odstranı́me, neovlivnı́me výpočet žádného slova, které
automat rozpoznává. Odstranı́me tento stav a také všechny přechody s nı́m přı́mo souvisejı́cı́.
Po odstraněnı́ stavů, které jsme vyřadili s použitı́m množin Si a Ei , dostáváme následujı́cı́ konečný automat:
a
→ q0
← q1
q2
← q5
Úkol
q1
q1
b
q2
c
q5
q0
q5
a
q0
c
a
c
q1
b
q2
a
q5
1.3
1. Podle zadánı́ následujı́cı́ho automatu vytvořte tabulku přechodů a stavový diagram.
Potom odstraňte nepotřebné stavy. Takto upravený automat pak zúplňte (převed’te
na totálnı́ automat).
A = ({A, B, C, D, E, F }, {0, 1, 2}, δ, A, {A, C}) s funkcı́ δ:
δ(A, 0) = E
δ(A, 1) = B
δ(A, 2) = E
δ(B, 0) = C
δ(B, 1) = D
δ(B, 2) = E
δ(C, 0) = C
δ(C, 1) = C
δ(D, 2) = C
δ(E, 1) = E
δ(E, 2) = E
δ(F, 0) = C
δ(F, 1) = E
δ(F, 2) = F
C
1.3
ODSTRANĚNÍ NEPOTŘEBNÝCH STAVŮ
10
2. Ke konečnému automatu vpravo vytvořte zbývajı́cı́ dvě reprezentace – δ-funkci a tabulku
přechodů. Potom odstraňte všechny nepotřebné stavy.
a
b
A
a
c
b
D
3. Podle následujı́cı́ch konečných automatů určených tabulkami přechodů sestrojte stavové
diagramy a pak odstraňte všechny nepotřebné
stavy.
↔A
B
C
D
←E
a
b
c
A
C
A
B
D
C
A
B
C
B
C
→A
B
←C
←D
E
a
b
c
C
A
B
B
E
B
A
A
E
D
A
E
↔A
B
C
D
←E
a
b
A
C
B
A
B
B
E
C
→ q0
← q1
← q2
q3
q4
B
a
a
C
b
a
a
F
a
b
q4
q4
q3
q1
q1
q4
q3
b
E
a
G
c
q0
q2
q3
4. Zamyslete se nad těmito přı́pady: jak by vypadal jazyk upraveného automatu (bez nepotřebných stavů), kdyby do množin Si nebyly zařazeny žádné koncové stavy? Jak by
vypadal tento jazyk, kdyby do množin Ei nebyl zařazen počátečnı́ stav?
Kapitola
2
Regulárnı́ jazyky
2.1
Pumping lemma pro regulárnı́ jazyky
Pro každý regulárnı́ jazyk L platı́ tato vlastnost: vždy existuje přirozené čı́slo p > 0 takové,
že pro každé slovo w ∈ L delšı́ než p (tj. |w| > p) existuje (alespoň jedno, přı́padně vı́ce)
rozdělenı́ w = x · y · z (tj. na tři části) takové, že
• |y| > 0 (v prostřednı́ části musı́ být alespoň jeden znak – signál),
P
• |y| ≤ p (délka prostřednı́ části slova je shora omezena, tedy konečná, v jejı́ specifikaci
nesmı́me použı́t „index“),
• x · (y)k · z ∈ L pro jakékoliv k ≥ 0 (když prostřednı́ část „pumpujeme“, výsledné slovo
opět patřı́ do jazyka – y bud’ vyřadı́me pro k = 0 a nebo opakujeme 1×, 2×, 3×, atd.)
Pumpovacı́ věta je implikace. Řı́ká nám, že když je jazyk regulárnı́, tak má danou vlastnost.
Nenı́ nikde řečeno, že jazyk, který nenı́ regulárnı́, danou vlastnost nemá.
Přı́klad 2.1
Nejdřı́v si ukážeme, jak ověřit, že regulárnı́ jazyk tuto vlastnost má. Postup si ukážeme na
jazyku L = {ai bj : i, j ≥ 0}
Pro tento jazyk dokážeme sestrojit konečný automat, tedy
b
a
vı́me, že se jedná o regulárnı́ jazyk. Vlastnost popsanou v Pumb
q1
q0
ping lemma si můžeme představit takto:
• použijeme p rovno počtu stavů konečného automatu, tedy p = 2
• vezmeme jakékoliv slovo jazyka delšı́ než 2, napřı́klad w = a3 b (má délku 4)
• w je delšı́ než počet stavů automatu, je tedy zřejmé, že některá část slova bude vyhodnocována v cyklu
• při pohledu na stavový diagram automatu vidı́me, že tento cyklus jde přes jediný
stav, a to q0
11
L
2.1
PUMPING LEMMA PRO REGULÁRNÍ JAZYKY
12
• vhodné rozdělenı́ může být napřı́klad w = (a) · (a2 ) · (b), po pumpovánı́ dostáváme
slova (a) · (a2 )k · (b) = a1+2k b, pro jakékoliv k ≥ 0 tato slova patřı́ do jazyka L,
• jiné vhodné rozdělenı́ je třeba w = (a2 ) · (a) · (b).
Vidı́me, že prostřednı́ část slova vlastně odpovı́dá části slova, která procházı́ cyklem
(nejméně jednou). Pumpovánı́ s indexem k pak odpovı́dá knásobnému průchodu cyklem
v automatu.
Platı́ pumping lemma pro všechny regulárnı́ jazyky včetně konečných? Samozřejmě ano.
Pro každý konečný jazyk existuje konečný automat, který ho rozpoznává. Jako p si u konečného jazyka zvolı́me opět bud’ počet stavů tohoto automatu a nebo čı́slo ještě většı́.
V Pumping lemma se pı́še „pro každé slovo w daného jazyka delšı́ než p . . . “, ale nepı́še se
tam, že takové slovo opravdu musı́ existovat. Opravdu žádné takové neexistuje, protože kdyby
existovalo slovo delšı́ než počet stavů automatu, musel by být v grafu stavového diagramu
cyklus, a cyklus znamená nekonečný jazyk. Takže Pumping lemma platı́ i pro konečné
jazyky.
Úkol
2.1
U následujı́cı́ch regulárnı́ch jazyků vytvořte stavový diagram, vyberte „dostatečně dlouhé
slovo“ – delšı́ než počet stavů automatu, určete některé vhodné rozdělenı́ slova na tři části
podle podmı́nek Pumping lemma a ukažte, že pro jakékoliv čı́slo (mocninu) k jde opět
o slovo z daného jazyka.
P
C
Pracujte s těmito jazyky:
(a) La = {abi a : i ≥ 0}
(b) Lb = {(ab)i : i ≥ 0}
(c) Lc = {a(bb)i : i ≥ 1}
(d) Ld = {000(111)i : i ≥ 0}
(e) Lc = {disk, data, plat}
(f) Ld = N
(množina přirozených čı́sel, zde včetně 0)
Obvyklejšı́m způsobem použitı́ Pumping lemma je jejı́ obrázená forma: mı́sto tvrzenı́
Regular(L) ⇒ Vlastnost(L, p)
dokazujeme
¬Vlastnost(L, p) ⇒ ¬Regular(L),
tedy „Pokud neexistuje žádné p takové, že pro každé slovo delšı́ než p dokážeme najı́t dané
rozdělenı́, pak jazyk nenı́ regulárnı́.“.
P
2.1
PUMPING LEMMA PRO REGULÁRNÍ JAZYKY
13
Abychom mohli dokázat, že pracujeme s opravdu jakkoliv dlouhým slovem, použijeme
v určenı́ slova „proměnnou“ v exponentu, kterou v přı́padě potřeby můžeme jakkoliv
zvyšovat (do nekonečna), napřı́klad proměnnou i ve slově (ab)i .
Dále u zvoleného slova zkoušı́me různé možnosti jeho rozdělenı́ na tři části tak, aby
prostřednı́ část nebyla prázdné slovo. Nemusı́me hledat absolutně všechny možnosti (to
bychom hledali do nekonečna), ale je třeba vystihnout různé možné způsoby umı́stěnı́
hranic mezi potenciálnı́mi částmi. Pro každé možné rozdělenı́ pak najdeme alespoň jednu
hodnotu k, pro kterou x · y k · z nepatřı́ do jazyka.
Končı́me tehdy, když se podařı́ najı́t slovo takové, že pro jakékoliv jeho rozdělenı́ vždy
najdeme alespoň jednu hodnotu k takovou, že x · y k · z nepatřı́ do daného jazyka.
Přı́klad 2.2
Ukážeme, že jazyk L = {an b2n : n ≥ 0} nenı́ regulárnı́.
Vybereme „dostatečně dlouhé“ slovo jazyka. Protože nemáme zkonstruován konečný
automat pro tento jazyk (samozřejmě, vždyt’ ve skutečnosti neexistuje), musı́me vybrat
takové slovo, o kterém si můžeme být jisti, že je opravdu dlouhé. Napřı́klad w = ai b2i pro
„nějaké“ i, dostatečně velké. Použili jsme proměnnou i, o které vı́me jen jedinou konkrétnı́
věc – je většı́ než 0 (protože musı́ být většı́ než nějaké čı́slo p, které je většı́ než 0).
Slovo máme, a to dostatečně reprezentativnı́, vlastně nám určuje všechna dlouhá slova
daného jazyka. Zbývá projı́t všechna možná rozdělenı́ x · y · z tohoto slova a dokázat, že
pro jakékoliv k ≥ 0 slovo x · y k · z nepatřı́ do jazyka L. U jednotlivých možnostı́ budeme
volit k = 0 nebo k = 2.
Jsou tyto možnosti:1
1. hranice mezi x a y je před začátkem slova (tj. x = ε):
(a) hranice mezi y a z je někde mezi znaky a, v prvnı́ části slova: x · y · z = ε · am ·
ai−m b2i , m > 0, x · y k · z = akm+i−m b2i , napřı́klad pro k = 0 vycházı́ ai−m b2i ;
protože m > 0, toto slovo nepatřı́ do jazyka L
(b) hranice mezi y a z je na hranici mezi znaky a a b: x·y ·z = ε·ai ·b2i , x·y k ·z = aki b2i ;
opět stačı́ dosadit k = 0, dostáváme b2i , protože i je velké čı́slo, určitě většı́ než
0, toto slovo nenı́ z jazyka L
(c) hranice mezi y a z je někde mezi znaky b, v druhé části slova: x · y · z = ε · ai bm ·
b2i−m , 0 < m < 2i, x · y k · z = (ai bm )k b2i−m , pro k = 0 je taktéž narušen vztah
v exponentech – slovo b2i−m ∈
/L
(d) hranice mezi y a z je na konci slova, tj. celé slovo je v prostřednı́ části rozdělenı́:
x · y · z = ε · ai b2i · ε, x · y 2 · z = ai b2i ai b2i , i > 0 ∈
/L
2. hranice mezi x a y je v prvnı́ části slova, někde mezi znaky a:
1
Poznámka: v rozdělenı́ch se sice v prostřednı́ části vyskytuje index m, přestože jsme si na začátku sekce
řekli, že tam žádný do nekonečna rostoucı́ index být nesmı́, zde nám však m zastupuje konečné čı́slo (napřı́klad
čı́slo 1, 2, 3, atd.) a jeho účelem je zjednodušit zápis.
2.1
PUMPING LEMMA PRO REGULÁRNÍ JAZYKY
14
(a) hranice mezi y a z je ve stejné části slova: x · y · z = am · an · ai−m−n b2i , m, n > 0,
x · y 0 · z = ai−n b2i ∈
/L
(b) hranice mezi y a z je na hranici znaků a a b: x · y · y = am · ai−m · b2i , 0 < m < i,
x · y 0 · z = am b2i ∈
/L
(c) hranice mezi y a z je někde mezi znaky b: x · y · z = am · ai−m bn · b2i−n , m, n >
0, m < i, x · y 2 · z = ai bn ai−m b2i ∈
/L
(d) hranice mezi y a z je na konci slova: x · y · z = am · ai−m b2i · ε, 0 < m < i,
x · y 0 · z = am ∈
/L
3. hranice mezi x a y je na hranici mezi znaky a a b:
(a) hranice mezi y a z je někde mezi znaky b: x · y · z = ai · bm · b2i−m , 0 < m < 2i,
x · y 0 · z = ai b2i−m ∈
/L
(b) hranice mezi y a z je na konci slova: x · y · z = ai · b2i · ε, x · y 0 · z = ai ∈
/L
4. hranice mezi x a y je v druhé části slova, někde mezi znaky b:
(a) hranice mezi y a z je někde mezi znaky b: x·y·z = ai bm ·bn ·b2i−m−n , 0 < m, n < 2i,
x · y 0 · z = ai b2i−n ∈
/L
(b) hranice mezi y a z je na konci slova: x · y · z = ai bm · b2i−m · ε, 0 < m < 2i,
x · y 0 · z = ai bm ∈
/L
Jednotlivé varianty rozdělenı́ jsou přehlednějšı́ v tabulce:
x·y·z
ε · am · ai−m b2i
ε · ai · b2i
ε · ai bm · b2i−m
ε · ai b2i · ε
Podmı́nky
0<m<i
0 < m < 2i
x · yk · z
k=0
akm+i−m b2i
aki b2i
(ai bm )k b2i−m
(ai b2i )k
ai−m b2i ∈
/L
b2i ∈
/L
b2i−m ∈
/L
am · an · ai−m−n b2i
am · ai−m · b2i
am · ai−m bn · b2i−n
am · ai−m b2i · ε
m, n > 0
0<m<i
m, n > 0, m < i
0<m<i
akn+i−n b2i
am+k(i−m) b2i
am (ai−m bn )k b2i−n
am (ai−m b2i )k
ai−n b2i ∈
/L
m
2i
a b ∈
/L
0 < m < 2i
ai bkm+2i−m
ai b2ki
ai bm · bn · b2i−m−n
ai bm · b2i−m · ε
0 < m, n < 2i
0 < m < 2i
ai bkn+2i−n
ai bm+k(2i−m)
ai b2i−m ∈
/L
i
a ∈
/L
ai · bm · b2i−m
ai · b2i · ε
am ∈
/L
k=2
ai b2i ai b2i ∈
/L
ai bn ai−m b2i ∈
/L
ai b2i−n ∈
/L
i
m
ab ∈
/L
Pro každé možné rozdělenı́ jsme našli k takové, že xy k z nepatřı́ do jazyka, proto L nenı́
regulárnı́ jazyk.
2.1
PUMPING LEMMA PRO REGULÁRNÍ JAZYKY
15
Na testu stačı́ trochu jednoduššı́ postup, jak si ukážeme na následujı́cı́m přı́kladu.
Přı́klad 2.3
Použijeme tentýž jazyk jako v předchozı́m přı́kladu, L = {an b2n : n ≥ 0}, a důkaz, že nenı́
regulárnı́, trochu zjednodušı́me.
Vı́me, že pokud chceme dokázat, že tento jazyk nenı́ regulárnı́, stačı́, když najdeme
dostatečně dlouhé slovo a ukážeme, že toto slovo nelze rozdělit na tři části při splněnı́
podmı́nek stanovených v Pumping lemma.
Takže stačı́ určit pozici prostřednı́ části ve slově w = ai b2i , při dělenı́ w = x · y · z:
1. y = ar, r > 0: pak wk = x · y k · z = ai−r+k·r b2i , napřı́klad pro k = 2 by platilo
w2 = ai+r b2i pro r > 0, w2 ∈
/ L (podobně pro k = 0 a všechny dalšı́ indexy kromě 1,
sle stačı́ to ukázat pro jediný index).
2. y = br, r > 0: pak wk = x · y k · z = ai b2i−r+k·r , napřı́klad pro k = 0 by platilo
w0 = ai b2i−r , w0 ∈
/ L.
3. y = ar bs, r, s > 0: pak wk = x·y k ·z = ai−r (ar bs )k b2i−s , ale pro k > 1 by se v prostřednı́
části střı́daly symboly a a b, což neodpovı́dá předpisu jazyka, proto wk ∈
/ L.
Jiné rozdělenı́ nenı́ možné, proto jazyk L nenı́ regulárnı́.
Přı́klad 2.4
Dokážeme, že jazyk L = {an : n je prvočı́slo} nenı́ regulárnı́.
Kdyby tento jazyk byl regulárnı́, pak by pro každé dostatečně dlouhé slovo jazyka
existovalo rozdělenı́ s výše uvedenými vlastnostmi. Zvolme slovo w = ai , kde i je některé
dostatečně velké prvočı́slo.
Nynı́ určı́me rozdělenı́ pro w = x · y · z (v tomto přı́padě nenı́ moc možnostı́, jak volit).
Zvolme y = ar pro nějaké r > 1. Pro pumpovánı́ určı́me index k = i + 1 . To můžeme,
protože u regulárnı́ho jazyka by věta platila pro jakoukoliv hodnotu indexu k, a čı́slo i je
z našeho pohledu konstantnı́ (a dostatečně velké).
Určı́me tedy wk = ai−r+k·r , konkrétně wi+1 = ai−r+r(i+1) = ai−r+r·i+r = ai·(1+r) . Exponent lze rozložit na součin dvou čı́sel, která jsou obě většı́ než 2, proto se nejedná o prvočı́slo
a toto slovo nepatřı́ do jazyka L. Z toho vyplývá, že L nenı́ regulárnı́.
Pumping lemma nenı́ ekvivalence, ale pouze implikace. Proto mohou existovat jazyky,
které sice nejsou regulárnı́, ale přesto danou vlastnost splňujı́. Může se jednat napřı́klad
o jazyk vzniklý zřetěnenı́m regulárnı́ho a neregulárnı́ho jazyka.
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
16
Přı́klad 2.5
Jazyk L = {ai bj c2j : i, j ≥ 0} nenı́ regulárnı́, přesto splňuje Pumping lemma. Můžeme
zvolit napřı́klad slovo am . Toto slovo patřı́ do jazyka L a existuje dokonce vı́ce různých
rozdělenı́ x · y · z takových, že x · y k · z ∈ L, napřı́klad ε · (am )k · ε = akm ∈ L pro jakékoliv
k ≥ 0.
Co z toho plyne? Když jazyk splňuje Pumping lemma, nemůžeme tvrdit, že je regulárnı́.
A naopak – když se nepodařı́ pomocı́ Pumping lemma dokázat, že jazyk nenı́ regulárnı́, tak
to ještě neznamená, že je regulárnı́. Pumping lemma je jedno z kritériı́ regularity (tj. způsobů,
jak lze dokázat, že daný jazyk nenı́ regulárnı́).
Úkol 2.2
1. Ukažte, že jazyk L = {ba(ab)n : n ≥ 0} splňuje Pumping lemma.
2. Pomocı́ Pumping lemma dokažte, že jazyk L =
{an bcn
: n ≥ 1} nenı́ regulárnı́.
L
C
3. Pomocı́ Pumping lemma dokažte, že jazyk L = {wwR : w ∈ {a, b}∗ } nenı́ regulárnı́.
Můžete zvolit napřı́klad slovo v = ai b2i ai , které také patřı́ do jazyka L, stačı́ dokázat,
že pro toto slovo neexistuje vhodné rozdělenı́ pro pumpovánı́.
2.2
Uzávěrové vlastnosti – operace nad regulárnı́mi jazyky
Třı́da jazyků je množina všech jazyků s danou společnou vlastnostı́. Také regulárnı́ jazyky
tvořı́ třı́du – třı́da regulárnı́ch jazyků je množina všech jazyků, pro které lze sestrojit konečný
automat.
P
Vı́me, že na řetězce lze použı́t operaci zřetězenı́. Jazyk je množina řetězců, a tedy na
jazyk můžeme použı́t různé množinové operace (sjednocenı́, průnik, doplněk – zrcadlenı́,
substituci), a také operace odvozené z práce s řetězci a znaky (signály) – zřetězenı́, dále
iteraci (operace „hvězdička“) a dalšı́.
Třı́da jazyků je uzavřena vzhledem k nějaké operaci, pokud po uplatněnı́ operace na
jazyky z této třı́dy vždy vznikne jazyk patřı́cı́ do stejné třı́dy.
Postupně si ukážeme všechny základnı́ operace, a to na konečných automatech. Pokud
jde o binárnı́ operaci (uplatňuje se na dva jazyky), je obvykou podmı́nkou disjunktnost
průniku množin stavů automatů (žádný stav existuje v obou automatech zároveň).
2.2.1
Sjednocenı́
V přı́padě sjednocenı́ využijeme celou definici původnı́ch automatů. Přidáme nový stav
a z tohoto stavu povedeme přechody do všech stavů, do kterých vede přechod z počátečnı́ho
stavu. Nový stav nám tedy simuluje použitı́ počátečnı́ch stavů v původnı́ch automatech.
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
17
Postup si můžeme představit třeba tak, že vezmeme všechny přechody, které vedou
z původnı́ch počátečnı́ch stavů, a zkopı́rujeme (ne přeneseme, ty původnı́ musejı́ zůstat)
jejich začátky (tj. u stavů, ze kterých vycházejı́) k novému stavu.
Pokud některý z původnı́ch počátečnı́ch stavů patřı́ i do množiny koncových stavů, pak
také tuto vlastnost přidáme novému počátečnı́mu stavu.
Označme
• A1 = (Q1 , Σ1 , δ1 , q1 , F1 ) je prvnı́ automat,
• A2 = (Q2 , Σ2 , δ2 , q2 , F2 ) je druhý automat,
pak automat rozpoznávajı́cı́ jazyk, který je sjednocenı́m jazyků obou automatů, je
A = (Q1 ∪ Q2 ∪ {s0 }, Σ1 ∪ Σ2 , δ, s0 , F1 ∪ F2 ), platı́, že s0 ∈
/ Q1 ∪ Q2 , přechodová funkce:
δ(s0 , x) =(δ1 (q1 , x) ∪ δ2 (q2 , x), x ∈ Σ1 ∪ Σ2
δ1 (r, x) : r ∈ Q1 , x ∈ Σ1 ,
δ(r, x) =
δ2 (r, x) : r ∈ Q2 , x ∈ Σ2
To znamená, že přechodovou funkci prakticky přejmeme z původnı́ch automatů, změna
bude jen na začátku.
Přı́klad 2.6
Ukážeme si operaci sjednocenı́ na následujı́cı́ch jazycı́ch a automatech:
L1 = {(ba)i (a ∪ bb) : i ≥ 0}
L2 = {ai baaj : i, j ≥ 0}
Konečné automaty pro tyto jazyky jsou následujı́cı́:
a
q1
q0
↔ q0
b
b
← q1
a
q2
q2
a
b
q1
q2
q0
q1
A1 = ({q0 , q1 , q2 }, {a, b}, δ1 , q0 , {q0 , q1 })
δ1 (q0 , a) = q1
δ1 (q0 , b) = q2
δ1 (q2 , a) = q0
δ1 (q2 , b) = q1
b
A
a
B
→A
a
B
←C
C
a a
b
A
C
C
B
A2 = ({A, B, C}, {a, b}, δ2 , A, {C})
δ2 (A, a) = A
δ2 (A, b) = B
δ2 (B, a) = C
δ2 (C, a) = C
Přidáme nový stav s0 a všechny přechody z tohoto stavu nasměrujeme a označı́me
stejně jako přechody z počátečnı́ch stavů původnı́ch automatů.
Postup je nejnázornějšı́ na stavovém diagramu, ale je jednoduchý také v tabulce přechodů – stačı́ obě tabulky shrnout do jedné a přidat nový řádek, jehož buňky budou
sjednocenı́m buněk na řádcı́ch původnı́ch počátečnı́ch stavů a na přı́slušných sloupcı́ch.
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
18
Protože jeden z původnı́ch počátečnı́ch stavů (q0 ) patřı́ do množiny koncových stavů, také
nový počátečnı́ stav s0 bude zároveň koncovým.
a
q1
q0
b
b
a
a
b
q2
s0
a
a
a
b
b
a
C
A
B
a
q1 , A
q1
↔ s0
← q0
← q1
q2
A
B
←C
b
q2 , B
q2
q0
A
q1
B
C
C
A = ({s0 , q0 , q1 , q2 , A, B, C}, {a, b}, δ, s0 , {q0 , q1 , C})
δ(s0 , a) = δ1 (q0 , a) ∪ δ2 (A, a) = {q1 , A}
δ(s0 , b) = δ1 (q0 , b) ∪ δ2 (A, b) = {q2 , B}
δ(q0 , a) = {q1 }
δ(q0 , b) = {q2 }
δ(q2 , a) = {q0 }
δ(q2 , b) = {q1 }
δ(A, a) = {A}
δ(A, b) = {B}
δ(B, a) = {C}
δ(C, a) = {C}
Je zřejmé, že L(A) = L(A1 ) ∪ L(A2 ).
Pokud by žádný z původnı́ch počátečnı́ch stavů nepatřil do množiny koncových stavů,
pak ani stav s0 nesmı́me zařadit do množiny koncových stavů! Znamenalo by to, že do
výsledného jazyka nemá patřit prázdné slovo.
Úkol
2.3
C
1. Použijte operaci sjednocenı́ na následujı́cı́ konečné automaty:
0
A
1
0
1
C
B
0
1
1
E
D
2. Použijte operaci sjednocenı́ na následujı́cı́ konečné automaty (q3 zároveň koncový!):
→ q0
← q1
← q2
a
b
q0 , q2
q1
q2
q2
↔ q3
q4
q5
← q6
L
a
b
q4
q6
q5
c
q3
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
19
3. Pro oba konečné automaty ze zadánı́ předchozı́ho přı́kladu a také pro výsledný
automat vytvořte zbylé dva typy reprezentacı́ – stavový diagram a δ-funkci včetně
plné specifikace automatu.
4. Zamyslete se nad tı́m, jak by vypadalo sjednocenı́ vı́ce než dvou konečných automatů.
2.2.2
Zřetězenı́
Zřetězenı́ dvou jazyků vytvořı́me tak, že ve výsledném jazyce jsou všechny možné řetězce, jejichž prvnı́ část je kterékoliv slovo z prvnı́ho jazyka a druhá část zase kterékoliv
slovo z druhého jazyka. Záležı́ na pořadı́, části slova nemůžeme přehodit, řı́dı́ se pořadı́m
zřetězovaných jazyků.
P
Přı́klad 2.7
Princip zřetězenı́ jazyků si ukážeme na těchto konečných jazycı́ch:
L1 = {ε, abc, ba}
L2 = {ddb, dc}
Zřetězenı́m těchto dvou jazyků zı́skáme jazyk L = L1 · L2 :
L = {ε · ddb, ε · dc, abc · ddb, abc · dc, ba · ddb, ba · dc} = {ddb, dc, abcccb, abcdc, baddb, badc}
Při zřetězenı́ nenı́ třeba ve výsledném automatu vytvářet nový stav. Opět využijeme
všechny stavy a přechody z původnı́ch automatů a budeme přidávat nové přechody, které
je propojı́.
Při ukončenı́ výpočtu prvnı́ části slova (tj. v prvnı́m původnı́m automatu) je třeba „plynule“ navázat na výpočet druhého původnı́ho automatu. Proto nově přidávané přechody
budou vést z koncových stavů prvnı́ho automatu, jejich cı́lový stav (stav, do kterého bude
směřovat šipka přechodu) a označenı́ přejmeme (zkopı́rujeme) od přechodů z počátečnı́ho
stavu druhého původnı́ho automatu.
Počátečnı́m stavem výsledného automatu bude samozřejmě počátečnı́ stav prvnı́ho
původnı́ho automatu.
Do množiny koncových stavů zařadı́me
• koncové stavy druhého původnı́ho automatu,
• pokud počátečnı́ stav druhého automatu byl zároveň koncovým (to znamená, že
do druhého jazyka patřilo slovo ε), pak do množiny koncových stavů výsledného
automatu zařadı́me také koncové stavy prvnı́ho původnı́ho automatu.
Označme
• A1 = (Q1 , Σ1 , δ1 , q1 , F1 ) je prvnı́ automat,
• A2 = (Q2 , Σ2 , δ2 , q2 , F2 ) je druhý automat, zde je již důležité jejich pořadı́,
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
20
pak automat rozpoznávajı́cı́ jazyk, který je zřetězenı́m jazyků obou automatů, je
A = (Q1 ∪ Q2 , Σ1 ∪ Σ2 , δ, q1 , F ), koncové stavy:
• F = F2 , pokud ε ∈
/ L(A2 )
• F = F1 ∪ F2 , pokud ε ∈ L(A2 )
(tj. jestliže v jazyce druhého automatu bylo prázdné slovo, tedy počátečnı́ stav patřil do
množiny koncových stavů, znamená to, že do výsledného jazyka budou patřit i všechna
slova rozpoznávaná prvnı́m automatem – zřetězená s ε, lze skončit také ve stavech z F1 )
Přechodová funkce:


 δ1 (r, x) : r ∈ Q1 − F1 , x ∈ Σ1 ,
δ(r, x) =
δ1 (r, x) ∪ δ2 (q2 , x) : r ∈ F1 , x ∈ Σ1 ∪ Σ2 ,


δ2 (r, x) : r ∈ Q2 , x ∈ Σ2
Znamená to, že v koncových stavech prvnı́ho původnı́ho automatu budeme (kromě existujı́cı́ch původnı́ch reakcı́) reagovat stejně, jako v počátečnı́m stavu druhého původnı́ho
automatu (což je podle našeho značenı́ q2 ).
Přı́klad 2.8
Zřetězı́me jazyky těchto konečných automatů:
a
A1
q1
q0
↔ q0
b
b
← q1
a
q2
q2
a
b
q1
q2
q0
q1
A1 = ({q0 , q1 , q2 }, {a, b}, δ1 , q0 , {q0 , q1 })
δ1 (q0 , a) = q1
δ1 (q0 , b) = q2
δ1 (q2 , a) = q0
δ1 (q2 , b) = q1
b
A
a
B
A2
→A
a
B
←C
C
a a
b
A
C
C
B
A2 = ({A, B, C}, {a, b}, δ2 , A, {C})
δ2 (A, a) = A
δ2 (A, b) = B
δ2 (B, a) = C
δ2 (C, a) = C
V automatu A1 (prvnı́m) jsou dva koncové stavy. Z nich budou vést nové přechody ke
stavům automatu A2 – ke všem stavům, do kterých vede přechod z počátečnı́ho stavu A.
b a
a
q0
b
a
q1
b
b
a
q2
b
A
a
B
a
C
a → q0
q1
q2
A
B
←C
a
b
q1 , A
A
q0
A
C
C
q2 , B
B
q1
B
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
21
A = ({q0 , q1 , q2 , A, B, C}, {a, b}, δ, {C})
δ(q0 , a) = {q1 , A}
δ(q0 , b) = {q2 , B}
δ(q1 , a) = {A}
δ(q1 , b) = {B}
δ(q2 , a) = {q0 }
δ(q2 , b) = {q1 }
δ(A, a) = {A}
δ(A, b) = {B}
δ(B, a) = {C}
δ(C, a) = {C}
Platı́ L(A) = L(A1 ) · L(A2 ).
Přı́klad 2.9
Nynı́ použijeme stejné zadánı́ jako v předchozı́m přı́kladu, jen obrátı́me pořadı́ zřetězovaných automatů. Musı́me brát v úvahu to, že počátečnı́ stav automatu, který je ted’ druhý
v pořadı́, je zároveň koncovým stavem, což bude mı́t vliv také na množinu koncových
stavů:
b
A
a
B
a
a
C
a b
a
q1
q0
b
b
a
q2
→A
B
←C
q0
q1
q2
a
b
A
C
C, q1
q1
B
q0
q2
q2
q1
A0 = ({q0 , q1 , q2 , A, B, C}, {a, b}, δ, {C, q0 , q1 })
δ(A, a) = {A}
δ(A, b) = {B}
δ(B, a) = {C}
δ(C, a) = {C, q1 }
δ(C, b) = {q2 }
δ(q0 , a) = {q1 }
δ(q0 , b) = {q2 }
δ(q2 , a) = {q0 }
δ(q2 , b) = {q1 }
Platı́ L(A0 ) = L(A2 ) · L(A1 ).
Úkol
2.4
1. Proved’te operaci zřetězenı́ jazyků následujı́cı́ch konečných automatů:
0
A
1
0
1
C
B
0
1
1
E
D
C
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
22
2. Proved’te operaci zřetězenı́ jazyků následujı́cı́ch konečných automatů – nejdřı́v v pořadı́ podle zadánı́ (L(A1 ) · L(A2 )) a potom v opačném pořadı́ (L(A2 ) · L(A1 )). Sestrojte
také stavové diagramy.
A1
→ q0
← q1
← q2
2.2.3
a
b
q0 , q2
q1
q2
A2
↔ q3
q4
q5
← q6
q2
a
b
q4
q6
q5
c
q3
Iterace (Kleeneho uzávěr)
Při iteraci zřetězujeme jazyk sám se sebou, a to 0×, 1×, 2×, . . . , a pak všechny výsledné
jazyky po zřetězenı́ sjednotı́me. Formálně to můžeme zapsat následovně:
L∗ =
∞
[
P
Li
i=0
kde Li je i-násobné zřetězenı́ jazyka L sama se sebou (napřı́klad pro i = 3 bylo L3 = L·L·L).
Zřetězenı́ jsme již probı́rali.
Přı́klad 2.10
Princip iterace jazyka si ukážeme na tomto konečném jazyce:
L1 = {abc, ba, cd}
Iteracı́ zı́skáme jazyk L = L∗1 :
L = { ε,
.................................................................
abc, ba, cd, . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
abcabc, abcba, abccd, baabc, baba, bacd,
..............................
abcabcabc, abcabcba, abcabccd, abcbaabc, abcbaba, abcbacd, . . .}
.......
0×
1×
2×
3×, . . .
Výsledkem iterace je vždy nekonečný jazyk obsahujı́cı́ prázdné slovo ε, i kdyby původnı́
jazyk L1 byl konečný a i kdyby prázdné slovo neobsahoval.
Úprava konečného automatu při iteraci spočı́vá v těchto dvou krocı́ch:
1. vytvořı́me nový počátečnı́ stav, přechody z něj vedoucı́ určı́me stejné jako ty, které
vedou z původnı́ho počátečnı́ho stavu,
2. vytvořı́me nové přechody umožňujı́cı́ „návrat“ z koncových stavů na počátek výpočtu
(dalšı́ slovo z jazyka),
L
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
23
3. nový počátečnı́ stav zařadı́me do množiny koncových stavů (tı́m zařadı́me do jazyka
slovo ε).
Prvnı́ bod je nevyhnutelný předevšı́m tehdy, pokud v původnı́m automatu vede některý
přechod do počátečnı́ho stavu a zároveň tento stav nebyl v množině koncových stavů; je
třeba zabránit tomu, aby zařazenı́ počátečnı́ho stavu do množiny koncových stavů mělo za
následek rozpoznávánı́ takových slov, která do jazyka správně patřit nemajı́.
Označme A1 = (Q1 , Σ, δ1 , q0 , F1 ) původnı́ automat, pak automat rozpoznávajı́cı́ jazyk,
který je iteracı́ původnı́ho jazyka, je
A = (Q1 ∪ {s0 }, Σ, δ, s0 , F1 ∪ {s0 }), přechodová funkce:
δ(r, x) =


 δ1 (r, x) : r ∈ Q1 − F1 , x ∈ Σ,
δ1 (r, x) ∪ δ1 (q0 , x) : r ∈ F1 , x ∈ Σ,


δ1 (q0 , x) : r = s0 , x ∈ Σ
Nové přechody povedou z původnı́ch koncových stavů, a to do všech stavů, do kterých
vede přechod z počátečnı́ho stavu. Princip je prakticky stejný jako u dřı́ve probı́raných
operacı́, kopı́rujeme počátky přechodů od počátečnı́ho stavu se zachovánı́m jejich cı́le
i označenı́ (signálu).
Přı́klad 2.11
Vytvořı́me iteraci jazyka následujı́cı́ho automatu:
A1 = ({A, B, C, D}, {0, 1, 2}, δ1 , A, {B, D})
0
1
A
2
0
C
2
→A
←B
C
←D
1
B
D
0
1
2
A
B
D
C
B
δ1 (A, 0) = A
δ1 (A, 1) = B
δ1 (A, 2) = C
δ1 (B, 1) = D
δ1 (B, 2) = B
δ1 (C, 0) = D
D
Koncové stavy jsou dva. Z každého přidáme přechody do všech stavů, do kterých
směřujı́ přechody z počátečnı́ho stavu, a potom počátečnı́ stav označı́me jako koncový (aby
automat přijı́mal také prázdné slovo ε).
1
0
s0
2
0
0
1
A
2
2
0
C
2
1, 2
1
1
B
D
0
0
↔ s0
A
←B
C
←D
A
A
A
D
A
1
2
B
B
D, B
C
C
B, C
B
C
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
24
A = ({s0 , A, B, C, D}, {0, 1, 2}, δ, s0 , {s0 , B, D})
δ(s0 , 0) = A
δ(s0 , 1) = B
δ(s0 , 2) = C
δ(A, 0) = A
δ(A, 1) = B
δ(A, 2) = C
δ(B, 1) = D
δ(B, 2) = B
δ(C, 0) = D
δ(B, 0) = A
δ(B, 1) = B
δ(B, 2) = C
δ(D, 0) = A
δ(D, 1) = B
δ(D, 2) = C
Kdyby stav A už v původnı́m automatu patřil do množiny koncových stavů, tak by
samozřejmě koncovým stavem zůstal.
Úkol
2.5
1. Zkonstruujte konečný automat jazyka, který je iteracı́ jazyka následujı́cı́ho automatu:
a
q1
q0
b
b
a
q2
A1
↔ q0
← q1
q2
a
b
q1
q2
q0
q1
C
2. Zkonstruujte konečný automat jazyka, který je iteracı́ jazyka následujı́cı́ho automatu:
0
1
1
E
D
→D
←E
0
1
D
E
E
Pro výsledný automat také vytvořte třetı́ typ reprezentace – δ-funkci s plnou specifikacı́.
2.2.4
Pozitivnı́ iterace
Pozitivnı́ iterace je podobná operace jako předchozı́, ale zatı́mco iterace znamená řetězenı́
0×, 1×, 2×, . . ., při pozitivnı́ iteraci začı́náme při řetězenı́ až 1×, 2×, . . .. Matematicky
můžeme zapsat iteraci a pozitivnı́ iteraci následovně:
L∗ =
∞
[
i=0
Li
L+ =
∞
[
i=1
Li
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
25
Postup je stejný jako u iterace, ale pokud počátečnı́ stav původnı́ho automatu nepatřil
do množiny koncových stavů (tj. slovo ε nepatřilo do jazyka), nebude koncovým stavem
ani po úpravě automatu.
Označme A1 = (Q1 , Σ, δ1 , q0 , F1 ) původnı́ automat, pak automat rozpoznávajı́cı́ jazyk,
který je pozitivnı́ iteracı́ původnı́ho jazyka, je
A = (Q1 ∪ {s0 }, Σ, δ, s0 , F ), kde F = F1 ∪ {s0 }, pokud q0 ∈ F1 , jinak F = F1 .
Přechodová funkce:


 δ1 (r, x) : r ∈ Q1 − F1 , x ∈ Σ,
δ(r, x) =
δ1 (r, x) ∪ δ1 (q0 , x) : r ∈ F1 , x ∈ Σ,


δ1 (q0 , x) : r = s0 , x ∈ Σ
Přı́klad 2.12
Vytvořı́me pozitivnı́ iteraci jazyka následujı́cı́ho automatu:
A1 = ({A, B, C, D}, {0, 1, 2}, δ1 , A, {B, D})
0
1
A
2
0
C
2
→A
←B
C
←D
1
B
D
0
1
2
A
B
D
C
B
δ1 (A, 0) = A
δ1 (A, 1) = B
δ1 (A, 2) = C
δ1 (B, 1) = D
δ1 (B, 2) = B
δ1 (C, 0) = D
D
Přidáváme pouze nové přechody, počátečnı́ stav nebudeme zařazovat do množiny
koncových stavů, protože v původnı́m automatu také nebylo rozpoznáváno slovo ε:
1
0
s0
2
0
0
1
A
2
2
0
C
2
1, 2
1
1
B
D
0
→ s0
A
←B
C
←D
A
A
A
D
A
1
2
B
B
D, B
C
C
B, C
B
C
0
A = ({s0 , A, B, C, D}, {0, 1, 2}, δ, s0 , {B, D})
δ(s0 , 0) = A
δ(s0 , 1) = B
δ(s0 , 2) = C
δ(A, 0) = A
δ(A, 1) = B
δ(A, 2) = C
δ(B, 1) = D
δ(B, 2) = B
δ(C, 0) = D
δ(B, 0) = A
δ(B, 1) = B
δ(B, 2) = C
δ(D, 0) = A
δ(D, 1) = B
δ(D, 2) = C
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
26
Pokud původnı́ jazyk L obsahuje slovo ε, pak platı́ L∗ = L+ , v opačném přı́padě se tyto
jazyky nerovnajı́ a platı́ L∗ = L+ ∪ {ε}.
Úkol
2.6
1. Zkonstruujte konečný automat jazyka, který je pozitivnı́ iteracı́ jazyka následujı́cı́ho
automatu:
a
q1
q0
b
b
a
q2
A1
↔ q0
← q1
q2
a
b
q1
q2
q0
q1
L
C
2. Zkonstruujte konečný automat jazyka, který je pozitivnı́ iteracı́ jazyka následujı́cı́ho
automatu:
0
1
1
E
D
2.2.5
→D
←E
0
1
D
E
E
Zrcadlový obraz (reverze)
Reverze je převrácenı́. Zrcadlový obraz slova sestrojı́me tak, že je zrcadlově „převrátı́me“,
tj. napřı́klad ze slova abcd zı́skáme slovo (abcd)R = dcba.
Zrcadlový obraz jazyka je jazyk obsahujı́cı́ všechna slova původnı́ho jazyka, ale převrácená. Operace zrcadlenı́ je sama k sobě inverznı́ – když slovo (nebo jazyk) revertujeme
dvakrát, dostáváme původnı́ slovo (jazyk). Zrcadlenı́ můžeme zapsat takto:
LR = {w : wR ∈ L}
Pokud budeme při reverzi pracovat s konečným automatem, předevšı́m převrátı́me
všechny cesty, které v automatu existujı́ (tj. převrátı́me všechny přechody) a zaměnı́me
počátečnı́ a koncové stavy.
Dále musı́me vyřešit jeden problém – počátečnı́ stav musı́ být vždy jen jeden, ale koncových stavů může být obecně jakýkoliv počet. Proto rozlišı́me dva přı́pady – pokud původnı́
automat má jen jediný koncový stav, stačı́ postup naznačený v předchozı́m odstavci. Jestliže
však má vı́ce koncových stavů, musı́me zajistit, aby po reverzi existoval jen jediný počátečnı́ stav. Proto vytvořı́me nový stav, který v sobě bude shrnovat vlastnosti původnı́ch
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
27
koncových stavů (resp. nových „počátečnı́ch“ stavů) týkajı́cı́ se přechodů, které z nich po
reverzi vycházejı́.
Pokud počátečnı́ stav původnı́ho automatu patřil do množiny koncových stavů, bude
koncovým stavem také počátečnı́ stav po reverzi.
Označme A1 = (Q1 , Σ, δ1 , q0 , F1 ) původnı́ automat, pak automat rozpoznávajı́cı́ jazyk,
který je reverzı́ původnı́ho jazyka, je
A = (Q1 ∪ {s0 }, Σ, δ, s0 , F ), množina koncových stavů je F = {q0 , s0 }, pokud q0 ∈ F1 ,
jinak F = {q0 } (záležı́ na tom, zda do původnı́ho jazyka patřilo ε). Přechodová funkce:
(
δ(r, x) =
p : δ1 (p, x) = r, x ∈ Σ,
t : r = s0 , δ1 (t, x) ∈ F1 , x ∈ Σ
Na přechodové funkci vidı́me, že podle prvnı́ho řádku předpisu se všechny přechody
obrátı́ (tj. zaměnı́ se zdroj a cı́l přechodu), podle druhého řádku vytvořı́me přechody vedoucı́ z nového (počátečnı́ho) stavu s0 .
Přı́klad 2.13
Provedeme operaci zrcadlenı́ jazyka tohoto konečného automatu:
A1 = ({q0 , q1 , q2 , q3 }, {a, b, c}, δ1 , q0 , {q1 })
a
q0
b
q1 c
c
b
q2
a
→ q0
← q1
q2
q3
a
b
q1
q2
c
δ1 (q0 , a) = q1
δ1 (q0 , b) = q2
δ1 (q1 , c) = q1
δ1 (q2 , a) = q3
δ1 (q2 , c) = q1
δ1 (q3 , b) = q2
q1
q1
q3
q2
q3
Obrátı́me všechny přechody. Protože máme jen jediný koncový stav, stačı́ pak jen zaměnit počátečnı́ a koncový stav (nebudeme vytvářet nový stav s0 ). U tabulky se zaměňujı́
označenı́ řádků s obsahem buněk na tomto řádku.
AR = ({q0 , q1 , q2 , q3 }, {a, b, c}, δ, q1 , {q0 })
q1 c
a
q0
c
b
b
q2
a
a
← q0
→ q1
q2
q3
q3
b
q0
q1 , q2
q0 , q3
q2
c
δ1 (q1 , a) = q0
δ1 (q2 , b) = q0
δ1 (q1 , c) = q1
δ1 (q3 , a) = q2
δ1 (q1 , c) = q2
δ1 (q2 , b) = q3
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
28
Přı́klad 2.14
Podı́váme se na složitějšı́ přı́pad – konečný automat s vı́ce koncovými stavy. Postup bude
podobný, ale navı́c řešı́me nutnost existence jediného počátečnı́ho stavu. Je dán tento konečný automat:
b
A
b
a C
b
B
→A
←B
C
←D
c
a
D
a
b
C
B
c
D
A, D
D
Jsou zde dva koncové stavy. Nejdřı́v přesměrujeme všechny přechody a označı́me nový
koncový stav, a až v druhém kroku (automat vpravo) vytvořı́me nový počátečnı́ stav
podobným postupem, jaký jsme použili napřı́klad u sjednocenı́ (tam šlo také o „simulaci“
– nahrazenı́ dvou počátečnı́ch stavů jediným).
b
A
b
a C
b
B
⇒
c
D a
b
A
b
a C
b
b c
s0
B
c
a
D a
b
→ s0
←A
B
C
D
a
b
c
D
A, C
C
A
B
C
B
A
D
Poslednı́ přı́pad, na který se podı́váme, je konečný automat s vı́ce koncovými stavy, kde
také počátečnı́ stav patřı́ do množiny koncových stavů.
Přı́klad 2.15
Pro operaci zrcadlenı́ je dán tento konečný automat:
A1 = ({q0 , q1 , q2 }, {a, b}, δ1 , q0 , {q0 , q1 })
a
q1
q0
b
b
a
q2
↔ q0
← q1
q2
a
b
q1
q2
q0
q1
δ1 (q0 , a) = q1
δ1 (q0 , b) = q2
δ1 (q2 , a) = q0
δ1 (q2 , b) = q1
Narozdı́l od předchozı́ch přı́kladů budou ve výsledném automatu dva koncové stavy.
Stav q0 bude koncový, protože v původnı́m automatu je počátečnı́m stavem, a stav s0 bude
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
29
koncový, protože do jazyka původnı́ho automatu patřı́ slovo ε, jehož převrácenı́m je opět
slovo ε pro jeho rozpoznánı́ musı́ být počátečnı́ stav (tj. s0 ) v množině koncových stavů.
AR = ({s0 , q0 , q1 , q2 }, {a, b}, δ, s0 , {q0 , s0 })
a
Úkol
a
q0
b
q1
b
a
q2
s0
a, b
↔ s0
← q0
q1
q2
a
b
q0 , q2
q2
q0
q2
δ(s0 , a) = {q0 , q2 }
δ(s0 , b) = {q2 }
δ(q1 , a) = {q0 }
δ(q2 , b) = {q0 }
δ(q0 , a) = {q2 }
δ(q1 , b) = {q2 }
q2
q0
2.7
1. Zkonstruujte konečný automat jazyka, který je reverzı́ (zrcadlovým obrazem) jazyka
následujı́cı́ho automatu:
0
1
1
E
D
→D
←E
0
1
D
E
E
2. Vytvořte konečný automat jazyka, který je reverzı́ jazyka následujı́cı́ho automatu. Pro
oba automaty (uvedený i ten, který vytvořı́te) sestrojte tabulku přechodů.
b
a
b
q1
q0
3. Vytvořte konečný automat rozpoznávajı́cı́ jazyk L = {ε, tisk, tis, sı́to} tak, aby
jednotlivá slova jazyka byla rozpoznávaná koncovým stavem (tj. pro každé slovo
vlastnı́ koncový stav). Potom proved’te reverzi tohoto automatu.
4. Vytvořte zrcadlový obraz jazyka tohoto konečného automatu (má jediný koncový
stav, který je zároveň počátečnı́m stavem):
↔ q0
q1
q2
a
b
q1
q2
q2
q0
q2
C
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
2.2.6
30
Průnik
Když vytvářı́me konečný automat pro průnik dvou jazyků pomocı́ automatů, které je
rozpoznávajı́, tak vlastně simulujeme (paralelně) činnost obou těchto automatů. Po přečtenı́ každého signálu ze vstupu provedeme jeden krok v obou automatech zároveň. Ve
výsledném automatu jsou proto stavy uspořádanými dvojicemi stavů z prvnı́ho a druhého
původnı́ho automatu (pozor, záležı́ na pořadı́).
Označme
• A1 = (Q1 , Σ1 , δ1 , q1 , F1 ) je prvnı́ automat,
• A2 = (Q2 , Σ2 , δ2 , q2 , F2 ) je druhý automat,
pak automat rozpoznávajı́cı́ jazyk, který je průnikem jazyků obou automatů, je
AP = (Q1 × Q2 , Σ1 ∩ Σ2 , δ, [q1 , q2 ], F1 × F2 ), kde operace × je kartézským součinem
uvedených množin. Přechodová funkce:
δ([p, r], x) = [δ1 (p, x), δ2 (r, x)], kde p ∈ Q1 , r ∈ Q2 , x ∈ Σ2 , x ∈ Σ1 ∩ Σ2
Přı́klad 2.16
Sestrojı́me konečný automat rozpoznávajı́cı́ průnik jazyků následujı́cı́ch dvou automatů:
a
b
q0
b
b
q1
a
b
q2
q3
a
p0
a
p2
b
a
p1
b
b
p3
p4
A1 = ({q0 , . . . , q3 }, {a, b}, δ1 , q0 , {q2 })
A2 = ({p0 , . . . , p4 }, {a, b}, δ2 , p0 , {p4 })
δ1 (q0 , a) = {q0 }
δ1 (q0 , b) = {q1 }
δ1 (q1 , b) = {q1 , q2 }
δ2 (p0 , a) = {p1 , p3 }
δ2 (p1 , a) = {p2 }
δ2 (p1 , b) = {p1 }
δ1 (q2 , a) = {q3 }
δ1 (q3 , b) = {q2 }
Nejdřı́v si vyznačı́me průběh „simulace“. Nenı́
to nutné (a u složitějšı́ho automatu je to prakticky
neproveditelné), ale na diagramu lépe pochopı́me
paralelnost obou zpracovánı́ téhož slova (červeně
jsou spojeny stavy, ve kterých jsou automaty ve stejném kroku zpracovánı́ slova) – obrázek vpravo.
Napřı́klad pro slovo abbabab paralelně procházı́me dvojicemi stavů [q0 , p0 ], pak [q0 , p1 ], [q1 , p1 ],
[q2 , p1 ], [q3 , p2 ], [q2 , p0 ], dále [q3 , p3 ] a [q2 , p4 ].
δ2 (p2 , b) = {p0 }
δ2 (p3 , b) = {p4 }
a
b
q0
b
b
q1
a
a
p0
b
a
p1
b
p2
a
b
p3
b
q2
p4
q3
P
P
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
31
Protože by bylo hodně náročné (a také nedeterministické a těžko naprogramovatelné)
takto vyhledávat všechny dvojice stavů, ve kterých se nacházı́ výpočet v obou automatech
ve stejném kroku, použijeme jinou (trochu „otrockou“) metodu:
• jako množinu stavů použijeme množinu všech uspořádaných dvojic, kde prvnı́ prvek
je stav prvnı́ho automatu a druhý prvek je stav druhého automatu,
• vytvořı́me δ-funkci nebo tabulku přechodů, ve které zachytı́me společné přechody
na stejný signál v obou automatech,
• odstranı́me nepotřebné stavy.
Počátečnı́m stavem bude uspořádaná dvojice obsahujı́cı́ počátečnı́ stavy obou původnı́ch
automatů, koncové stavy budou všechny uspořádané dvojice, ve kterých jsou oba původnı́
stavy koncovými.
Jednoduššı́ je využitı́ tabulky přechodů. Podle tabulek původnı́ch automatů vytvořı́me
tabulku pro výsledný automat (kombinace řádků ve stejném sloupci).
→ q0
q1
← q2
q3
a
b
a
q0
q1
q1 , q2
→ p0
p1
p2
p3
← p4
q3
q2
b
p1 , p3
p2
p1
p0
p4
Tabulka přechodů výsledného konečného automatu má 4 · 5 = 20 řádků:
a
→ [q0 , p0 ]
[q0 , p1 ]
[q0 , p2 ]
[q0 , p3 ]
[q0 , p4 ]
[q0 , p1 ], [q0 , p3 ]
[q0 , p2 ]
[q1 , p0 ]
[q1 , p1 ]
[q1 , p2 ]
[q1 , p3 ]
[q1 , p4 ]
b
[q1 , p1 ]
[q1 , p0 ]
[q1 , p4 ]
[q1 , p1 ], [q2 , p1 ]
[q1 , p0 ], [q2 , p0 ]
[q1 , p4 ], [q2 , p4 ]
(pokračovánı́)
[q2 , p0 ]
[q2 , p1 ]
[q2 , p2 ]
[q2 , p3 ]
← [q2 , p4 ]
[q3 , p0 ]
[q3 , p1 ]
[q3 , p2 ]
[q3 , p3 ]
[q3 , p4 ]
a
b
[q3 , p1 ], [q3 , p3 ]
[q3 , p2 ]
[q2 , p1 ]
[q2 , p0 ]
[q2 , p4 ]
Nynı́ odstranı́me nepotřebné (tj. nedosažitelné a nadbytečné) stavy tak, jak jsme se učili
v předchozı́ch kapitolách, obsah množin je průběžně třı́děn pro usnadněnı́ porovnávánı́.
S0 = {[q0 , p0 ]}
S1 = {[q0 , p0 ], [q0 , p1 ], [q0 , p3 ]}
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
32
= {[q0 , p0 ], [q0 , p1 ], [q0 , p3 ], [q0 , p2 ], [q1 , p1 ], [q1 , p4 ]}
= {[q0 , p0 ], [q0 , p1 ], [q0 , p2 ], [q0 , p3 ], [q1 , p1 ], [q1 , p4 ], [q1 , p0 ], [q2 , p1 ]}
= {[q0 , p0 ], [q0 , p1 ], [q0 , p2 ], [q0 , p3 ], [q1 , p0 ], [q1 , p1 ], [q1 , p4 ], [q2 , p1 ], [q3 , p2 ]}
= {[q0 , p0 ], [q0 , p1 ], [q0 , p2 ], [q0 , p3 ], [q1 , p0 ], [q1 , p1 ], [q1 , p4 ], [q2 , p1 ], [q3 , p2 ], [q2 , p0 ]}
= {[q0 , p0 ], [q0 , p1 ], [q0 , p2 ], [q0 , p3 ], [q1 , p0 ], [q1 , p1 ], [q1 , p4 ], [q2 , p0 ], [q2 , p1 ], [q3 , p2 ], [q3 , p1 ],
[q3 , p3 ]}
S7 = {[q0 , p0 ], [q0 , p1 ], [q0 , p2 ], [q0 , p3 ], [q1 , p0 ], [q1 , p1 ], [q1 , p4 ], [q2 , p0 ], [q2 , p1 ], [q3 , p1 ], [q3 , p2 ],
[q3 , p3 ], [q2 , p4 ]}
S8 = {[q0 , p0 ], [q0 , p1 ], [q0 , p2 ], [q0 , p3 ], [q1 , p0 ], [q1 , p1 ], [q1 , p4 ], [q2 , p0 ], [q2 , p1 ], [q2 , p4 ], [q3 , p1 ],
[q3 , p2 ], [q3 , p3 ]} = S7
S2
S3
S4
S5
S6
Odstranili jsme stavy [q0 , p4 ], [q1 , p2 ], [q1 , p3 ], [q2 , p2 ], [q2 , p3 ], [q3 , p0 ], [q3 , p4 ], které jsou nedosažitelné z počátečnı́ho stavu. Dále pracujeme s touto tabulkou přechodů:
a
→ [q0 , p0 ]
[q0 , p1 ]
[q0 , p2 ]
[q0 , p3 ]
[q1 , p0 ]
[q1 , p1 ]
[q1 , p4 ]
[q2 , p0 ]
[q2 , p1 ]
← [q2 , p4 ]
[q3 , p1 ]
[q3 , p2 ]
[q3 , p3 ]
[q0 , p1 ], [q0 , p3 ]
[q0 , p2 ]
b
[q1 , p1 ]
[q1 , p0 ]
[q1 , p4 ]
[q1 , p1 ], [q2 , p1 ]
[q3 , p1 ], [q3 , p3 ]
[q3 , p2 ]
[q2 , p1 ]
[q2 , p0 ]
[q2 , p4 ]
Odstranı́me nadbytečné symboly (ze kterých neexistuje cesta do koncového stavu):
E0
E1
E2
E3
E4
E5
E6
E7
E8
= {[q2 , p4 ]}
= {[q2 , p4 ], [q3 , p3 ]}
= {[q2 , p4 ], [q3 , p3 ], [q2 , p0 ]}
= {[q2 , p0 ], [q2 , p4 ], [q3 , p3 ], [q3 , p2 ]}
= {[q2 , p0 ], [q2 , p1 ], [q2 , p4 ], [q3 , p2 ], [q3 , p3 ]}
= {[q2 , p0 ], [q2 , p1 ], [q2 , p4 ], [q3 , p2 ], [q3 , p3 ], [q1 , p1 ], [q3 , p1 ]}
= {[q1 , p1 ], [q2 , p0 ], [q2 , p1 ], [q2 , p4 ], [q3 , p1 ], [q3 , p2 ], [q3 , p3 ], [q0 , p1 ]}
= {[q0 , p1 ], [q1 , p1 ], [q2 , p0 ], [q2 , p1 ], [q2 , p4 ], [q3 , p1 ], [q3 , p2 ], [q3 , p3 ], [q0 , p0 ]}
= {[q0 , p0 ], [q0 , p1 ], [q1 , p1 ], [q2 , p0 ], [q2 , p1 ], [q2 , p4 ], [q3 , p1 ], [q3 , p2 ], [q3 , p3 ]} = E7
Po odstraněnı́ stavů [q0 , p2 ], [q0 , p3 ], [q1 , p0 ], [q1 , p4 ] dostáváme tuto tabulku přechodů
(s původnı́m označenı́m stavů a po přeznačenı́ na pı́smena):
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
a
→ [q0 , p0 ]
[q0 , p1 ]
[q1 , p1 ]
[q2 , p0 ]
[q2 , p1 ]
← [q2 , p4 ]
[q3 , p1 ]
[q3 , p2 ]
[q3 , p3 ]
b
a
→A
B
C
D
E
←F
G
H
K
[q0 , p1 ]
[q1 , p1 ]
[q1 , p1 ], [q2 , p1 ]
[q3 , p1 ], [q3 , p3 ]
[q3 , p2 ]
[q2 , p1 ]
[q2 , p0 ]
[q2 , p4 ]
Stavový diagram (stavy jsou přeznačené):
a
A
Úkol
b
B
b
C
b
33
a
E
b
a
G
b
B
C
C, E
G, K
H
E
D
F
H
b
a
D
b
K
F
2.8
1. Vytvořte deterministické konečné automaty pro jazyky L1 = {if, then, else} a L2 = {if,
iff, elif}, v každém z automatů stačı́ jediný koncový stav pro všechna slova daného
jazyka. Potom pomocı́ automatů vytvořte průnik těchto jazyků.
2. Sestrojte konečný automat, který je průnikem jazyků následujı́cı́ch automatů (pracujte s tabulkami přechodů). Odstraňte všechny nedosažitelné a nadbytečné stavy
a sestrojte stavový diagram.
→A
←B
C
D
0
1
B
C
A
D
B
→E
F
←H
0
1
F
H
F
H
H
Pro kontrolu: po odstraněnı́ nepotřebných stavů by měl automat mı́t osm stavů, z toho
jeden koncový, jeden cyklus přes jeden stav a jeden cyklus přes tři stavy.
C
2.2
UZÁVĚROVÉ VLASTNOSTI – OPERACE NAD REGULÁRNÍMI JAZYKY
2.2.7
34
Homomorfismus
Homomorfismus je takové zobrazenı́, které
• zachovává neutrálnı́ prvek (tj. u řetězců prázdný řetězec ε zobrazı́ opět na ε)
• zachovává zobrazenı́ operace, pro kterou je definován (u řetězců jde o zřetězenı́, tj.
h(a · b) = h(a) · h(b))
• výsledkem zobrazenı́ prvku (signálu, znaku) je vždy řetězec (u substituce, což je
zobecněnı́ homomorfismu, je výsledkem zobrazenı́ množina řetězců).
Když konstruujeme konečný automat homomorfismu pro některý jazyk, využı́váme plně
způsobu definice daného homomorfismu – pokud je v předpisu tohoto zobrazenı́ napřı́klad
h(a) = xyz, tj. znak a má být zobrazen na řetězec xyz, vezmeme postupně všechny přechody
označené znakem a a nahradı́me je cestami rozpoznávajı́cı́mi slovo xyz. Každá z těch cest
musı́ být samozřejmě samostatná, vždy jeden konkrétnı́ přechod označený signálem a
nahradı́me jednou samostatnou cestou pro xyz.
Přı́klad 2.17
Podle následujı́cı́ho automatu sestrojı́me konečný automat rozpoznávajı́cı́ jazyk podle zadaného homomorfismu.
↔ q0
q1
← q2
a
b
q1
q2
q1
c
q2
Homomorfismus:
h(a) = df,
h(b) = f f d,
h(c) = d
a
q0
b
a
q1
c
q2
Po úpravě vypadá konečný automat následovně:
↔ q0
q1
← q2
q3
q4
q5
q6
d
f
q5
q6
q2
q3
q4
q1
q1
q2
Původnı́ abeceda:
Σ1 = {a, b, c}
Nová abeceda:
Σ2 = {d, f }
f
q4
q3
f
d
d
q0
q2
q1
d f
d f
q5
q6
Jazyk rozpoznávaný původnı́m automatem je L = {ε} ∪ {abi acj : i, j ≥ 0}, po úpravě
dostáváme automat rozpoznávajı́cı́ jazyk h(L) = {ε} ∪ {df (ff d)i df dj : i, j ≥ 0}.
2.3
SESTROJENÍ KONEČNÉHO AUTOMATU PODLE REGULÁRNÍHO VÝRAZU
Úkol
35
2.9
C
Je dán konečný automat A s jazykem L = L(A) a homomorfismy h1 a h2 .
h1 (a) = 01
h1 (b) = 110
h1 (c) = 1
→ q0
← q1
q2
q3
h2 (a) = dd
h2 (b) = g
h3 (c) = dg
a
b
q1
q2
c
q1
q1
q3
q2
a
q0
b
q1 c
c
b
q2
a
q3
Zjistěte jazyky h1 (L) a h2 (L) a vytvořte také konečné automaty pro tyto jazyky (úpravou
automatu A). Jazyk automatu A je L(A) = {aci : i ≥ 0} ∪ {b(ab)i ccj : i, j ≥ 0}.
Dále pro výsledné automaty sestrojte jejich δ-funkci včetně plné specifikace, nezapomeňte na změnu abecedy.
2.3
Sestrojenı́ konečného automatu podle regulárnı́ho výrazu
Při sestrojenı́ konečného automatu podle zadaného regulárnı́ho výrazu využı́váme vztahu
mezi prvky regulárnı́ho výrazu (+, ·, ∗ ) a operacemi nad množinami řetězců ∪, ·, ∗ ). V předchozı́ch cvičenı́ch jsme se naučili pracovat s regulárnı́mi operacemi (sjednocenı́, zřetězenı́
a iteraci) a tyto postupy použijeme také zde.
Přı́klad 2.18
Sestrojı́me konečný automat pro regulárnı́ výraz a∗ b + (b∗ a + bbc)∗ . Postupně vytvořı́me
konečné automaty pro jednotlivé podvýrazy a zároveň je zjednodušı́me.
a
0
REG1 = a
1
REG3 = (REG1 )∗ = a∗
a
a
1
0
REG5 = ((REG2 )∗ · REG1 ) = b∗ a
b
a
3
5
b
2
REG2 = b
3
REG4 = (REG3 · REG2 ) = a∗ b
a
b
1
b
6
REG6 = bbc
4
b
7
c
9
8
P
2.4
VYTVOŘENÍ REGULÁRNÍHO VÝRAZU PODLE KONEČNÉHO AUTOMATU
REG7 = (REG5 + REG6 ) = b∗ a + bbc
b
a
5
3
b
a
10
b
b
@
@6
@
36
REG8 = (REG7 )∗ = (b∗ a + bbc)∗
b
b
a
a
5
3
b
b
a
b
c
b
9
8
7
10
b
7
b a
c
9
8
b
Výsledný automat: REG9 = (REG4 + REG8 ) = a∗ b + (b∗ a + bbc)∗
a
b
4
1
a
b
11
b
b
a
b
b
a
a
5
3
b
b
a
@
@
10
@
b
b
b
c
7
8
b
a
→ 11
1
3
←4
←5
7
8
←9
a
b
1, 5
1
5
3, 4, 7
4
3
5
3, 7
8
c
9
5
3, 7
9
Stav 10 je nedosažitelný z počátečnı́ho stavu, proto může být odstraněn (v tabulce
vpravo se již nenacházı́).
Úkol
2.10
Sestrojte konečné automaty podle těchto regulárnı́ch výrazů:
• (a + b∗ ) · b∗
• a · (b + (ab)∗ ) + b
• (01 + 10)∗ 10∗
• (abc)∗ · a · (ba + c)
• a∗ ba · (bb∗ + ca)∗ · a
C
2.4
VYTVOŘENÍ REGULÁRNÍHO VÝRAZU PODLE KONEČNÉHO AUTOMATU
2.4
37
Vytvořenı́ regulárnı́ho výrazu podle konečného automatu
Pokud máme zjistit jazyk rozpoznávaný zadaným konečným automatem, obvykle vytvářı́me regulárnı́ výraz (který pak můžeme převést do množinové reprezentace). Postupujeme
takto:
1. Pokud je to nutné, přeznačı́me stavy (tak, aby byly označeny čı́sly od 1).
2. Jako bázi rekurze (indukce) použijeme přı́mé cesty mezi dvěma stavy, na kterých se
0 a dokážeme je jednoduše
nenacházı́ žádný dalšı́ stav (tj. přechody); značı́me je Rij
zjistit přı́mo z automatu (v jakékoliv reprezentaci), napřı́klad:
...
i
j
p
...
a
b
i, j
p
j
p
j, p
a
a
i
b
a, b
j
a
b
p
0 =a+ε
Rii
0 =a
Rij
0 =b
Rip
0 =∅
Rji
0 =ε
Rjj
0 =a
Rjp
0 =∅
Rpi
0 =a+b
Rpj
0 =b+ε
Rpp
k – je
3. Indukcı́ budeme postupně cesty prodlužovat (spojovat). Vytvářı́me množiny Rij
to regulárnı́ výraz odpovı́dajı́cı́ cestě ze stavu i do stavu j vedoucı́ pouze přes stavy
označené maximálně čı́slem k. Postupujeme podle vzorce:
k−1
k−1 ∗
k−1
k−1
k
+ Rik
· (Rkk
) · Rkj
Rij
= Rij
Použı́váme výhradně množiny zjištěné v předchozı́m kroku (k − 1).
4. Postupujeme až k množinám s hornı́m indexem rovným počtu stavů (tj. v poslednı́m
kroku vytvořı́me množiny pro cesty mezi stavy, které vedou přes jakékoliv stavy bez
omezenı́). V poslednı́m kroku nenı́ třeba vypracovat množiny pro všechny kombinace
stavů (dolnı́ index), ale pouze pro cesty z počátečnı́ho stavu do koncových stavů.
5. Výsledný regulárnı́ výraz je součet (tedy sjednocenı́) regulárnı́ch výrazů odpovı́dajı́cı́ch cestám z počátečnı́ho stavu do jednotlivých koncových stavů.
Přı́klad 2.19
Zjistı́me regulárnı́ výraz odpovı́dajı́cı́ jazyku rozpoznávanému následujı́cı́m automatem:
a
b
1
a
b
2
b
3
→1
←2
←3
a
b
1
1
2
3
3
0 – regulárnı́ výrazy pro nejkratšı́ cesty bez mezistavů.
Nejdřı́v vytvořı́me množiny Rij
2.4
VYTVOŘENÍ REGULÁRNÍHO VÝRAZU PODLE KONEČNÉHO AUTOMATU
0 =a+ε
R11
0 =b
R12
0 =∅
R13
0 =a
R21
0 =ε
R22
0 =b
R23
38
0 =∅
R31
0 =∅
R32
0 =b+ε
R33
Hornı́ index znamená maximálnı́ čı́slo stavu, přes který může vést cesta mezi stavy
uvedenými v dolnı́m indexu (omezenı́ z hornı́ho indexu se netýká okrajových stavů cesty).
2 je regulárnı́ výraz odpovı́dajı́cı́ cestě ze stavu 1 do stavu 3 takové, že vede
Napřı́klad R13
přes stavy s čı́slem maximálně 2, tedy přes stavy 1 a 2. Hornı́ index budeme postupně
zvyšovat.
V prvnı́m kroku se setkáme se vztahem (a + ε)∗ = a∗ a dále (a + ε) · a∗ = a∗ .
1 = (a + ε) + (a + ε) · (a + ε)∗ · (a + ε) =
R11
= a + ε + a∗ = a∗
1
R12 = b + (a + ε) · (a + ε)∗ · b = b + a∗ b = a∗ b
1 = ∅ + (a + ε) · (a + ε)∗ · ∅ = ∅
R13
1 = a + a · (a + ε)∗ · (a + ε) = a + aa∗ = aa∗
R21
1
R22
1
R23
1
R31
1
R32
1
R33
= ε + a · (a + ε)∗ · b = ε + aa∗ b
= b + a · (a + ε)∗ · ∅ = b
= ∅ + ∅ · (a + ε)∗ · (a + ε) = ∅
= ∅ + ∅ · (a + ε)∗ · b = ∅
= (b + ε) + ∅ · (a + ε)∗ · ∅ = b + ε
V druhém kroku budeme hodně použı́vat vztah (ε + aa∗ b)∗ = (aa∗ b)∗ .
2
R11
2
R12
2
R13
2
R21
2
R22
2
R23
2
R31
2
R32
2
R33
= a∗ + a∗ b · (ε + aa∗ b)∗ · aa∗ = a∗ + a∗ b(aa∗ b)∗ aa∗
= a∗ b + a∗ b · (ε + aa∗ b)∗ · (ε + aa∗ b) = a∗ b + a∗ b(aa∗ b)∗ = a∗ b(aa∗ b)∗
= ∅ + a∗ b · (ε + aa∗ b)∗ · b = a∗ b(aa∗ b)∗ b
= aa∗ + (ε + aa∗ b) · (ε + aa∗ b)∗ · aa∗ = (aa∗ b)∗ aa∗
= ε + aa∗ b + (ε + aa∗ b) · (ε + aa∗ b)∗ · (ε + aa∗ b) = (aa∗ b)∗
= b + (ε + aa∗ b) · (ε + aa∗ b)∗ · b = (aa∗ b)∗ b
= ∅ + ∅ · (ε + aa∗ b)∗ · aa∗ = ∅
= ∅ + ∅ · (ε + aa∗ b)∗ · (ε + aa∗ b) = ∅
= b + ε + ∅ · (ε + aa∗ b)∗ · b = b + ε
Protože máme pouze tři stavy, třetı́ krok je poslednı́. Zde nenı́ třeba vypočı́távat výrazy
přes všechny dvojice stavů. Potřebujeme pouze ty cesty, které vedou z počátečnı́ho stavu do
některého koncového. V automatu jsou dva koncové stavy, dostaneme tedy dva regulárnı́
výrazy.
3 = a∗ b(aa∗ b)∗ + a∗ b(aa∗ b)∗ b · (b + ε)∗ · ∅ = a∗ b(aa∗ b)∗
R12
3 = a∗ b(aa∗ b)∗ b + a∗ b(aa∗ b)∗ b · (b + ε)∗ · (b + ε) = a∗ b(aa∗ b)∗ b + a∗ b(aa∗ b)∗ b · b∗ =
R13
= a∗ b(aa∗ b)∗ b · (ε + b∗ ) = a∗ b(aa∗ b)∗ bb∗
Výsledkem je regulárnı́ výraz odpovı́dajı́cı́ jazyku rozpoznávanému daným automatem:
3
3
R = R12
+ R13
=
= a∗ b(aa∗ b)∗ + a∗ b(aa∗ b)∗ bb∗ = a∗ b(aa∗ b)∗ · (ε + bb∗ ) = a∗ b(aa∗ b)∗ b∗
2.4
VYTVOŘENÍ REGULÁRNÍHO VÝRAZU PODLE KONEČNÉHO AUTOMATU
39
Přı́klad 2.20
Zjistı́me regulárnı́ výraz odpovı́dajı́cı́ jazyku rozpoznávanému následujı́cı́m automatem:
b
1
a
a
a
b
3
2
→1
2
←3
←4
a
4
a
b
4
2
3
3
3
0:
Nejdřı́v vytvořı́me množiny Rij
0
R11
0
R12
0
R13
0
R14
=ε
=b
=∅
=a
0
R21
0
R22
0
R23
0
R24
=a
=ε
=b
=∅
0
R31
0
R32
0
R33
0
R34
=∅
=∅
=a+ε
=∅
0
R41
0
R42
0
R43
0
R44
=∅
=∅
=a
=ε
Ve čtyřech krocı́ch (čı́slo kroku je v hornı́m indexu) zjistı́me dalšı́ množiny:
1
R11
1
R12
1
R13
1
R14
= ε + ε · ε∗ · ε = ε
= b + ε · ε∗ · b = b
= ∅ + ε · ε∗ · ∅ = ∅
=a+ε·a=a
2
R11
2
R12
2
R13
2
R14
1
R31
1
R32
1
R33
1
R34
=∅
=∅
= a+ε+∅ = a+ε
=∅
= ε + b(ab)∗ a = (ba)∗
= b + b(ab)∗ (ε + ab) = b(ab)∗
= ∅ + b(ab)∗ b = b(ab)∗ b
= a + b(ab)∗ aa = a + ba(ba)∗ a = (ba)∗ a
2
R31
2
R32
2
R33
2
R34
2
R21
2
R22
2
R23
2
R24
= a + (ε + ab)(ab)∗ a = (ab)∗ a
= (ab)∗
= b + (ε + ab)(ab)∗ b = (ab)∗ b
= aa + (ε + ab)(ab)∗ aa = (ab)∗ aa
2
R41
2
R42
2
R43
2
R44
=∅+∅=∅
=∅
=a+ε+∅=a+ε
=∅
3
R11
3
R12
3
R13
3
R14
= (ba)∗ + ∅ = (ba)∗
= b(ab)∗ + ∅ = b(ab)∗
= b(ab)∗ b + b(ab)∗ ba∗ (a + ε) = b(ab)∗ ba∗
= (ba)∗ a + ∅ = (ba)∗ a
3
R31
3
R32
3
R33
3
R34
3
R21
3
R22
3
R23
3
R24
1
R21
1
R22
1
R23
1
R24
=a+a·ε=a
= ε+aεb = ε+ab
=b+∅=b
= ∅ + aεa = aa
= (ab)∗ a + ∅ = (ab)∗ a
= (ab)∗ + ∅ = (ab)∗
= (ab)∗ b + (ab)∗ ba∗ (a + ε) = (ab)∗ ba∗
= (ab)∗ aa + ∅ = (ab)∗ aa
3
R41
3
R42
3
R43
3
R44
1
R41
1
R42
1
R43
1
R44
=∅
=∅
=a+∅=a
=ε+∅=ε
=∅
=∅
=a+∅=a
=ε+∅=ε
=∅
=∅
= a + ε + (a + ε)a∗ (a + ε) = a∗
=∅
=∅
=∅
= a + aa∗ (a + ε) = aa∗
=ε
2.5
MINIMALIZACE A NORMOVÁNÍ KONEČNÉHO AUTOMATU
40
Ve čtvrtém kroku nás zajı́majı́ pouze cesty vedoucı́ z počátečnı́ho stavu do koncových
stavů:
4 = b(ab)∗ ba∗ + (ba)∗ a · ε∗ · aa∗ = b(ab)∗ ba∗ + (ba)∗ aaa∗ = (ba)∗ bba∗ + (ba)∗ aaa∗
R13
4 = (ba)∗ a + (ba)∗ a · ε∗ · ε = (ba)∗ a
R14
Regulárnı́ výraz odpovı́dajı́cı́ jazyku zadaného automatu je
4
4
R = R13
+ R14
=
= (ba)∗ bba∗ + (ba)∗ aaa∗ + (ba)∗ a = (ba)∗ (bba∗ + aaa∗ + a)
Úkol
2.11
Zjistěte regulárnı́ výraz odpovı́dajı́cı́ jazyku následujı́cı́ch konečných automatů:
a
b
1
2
a
a
a
3
2.5
2.5.1
b
a
2
1
b
a
a
C
3
Minimalizace a normovánı́ konečného automatu
Minimálnı́ konečný automat
Minimalizace konečného automatu je snı́ženı́ počtu stavů při rozpoznávánı́ téhož jazyka,
a to na úroveň absolutně nezbytnou vzhledem k rozpoznávanému jazyku. Účelem může být
samotné snı́ženı́ počtu stavů (napřı́klad z důvodu snadnějšı́ho naprogramovánı́ či snı́ženı́
složitosti automatu) a nebo zajištěnı́ porovnatelnosti dvou automatů.
Při minimalizaci automatu A s množinou stavů 1, 2, . . . , n postupujeme takto:
• automat A by měl být deterministický; pokud nenı́, převedeme ho do deterministického tvaru,
• podle automatu A s n stavy vytvořı́me n konečných automatů A1 , A2 , . . . , An , které
jsou určeny téměř stejně (včetně přechodové funkce a koncových stavů) jako automat
A, lišı́ se pouze koncovým stavem – automat Ai má počátečnı́ stav i (1 ≤ i ≤ n),
• postupem popsaným v předchozı́ kapitole zjistı́me regulárnı́ výrazy odpovı́dajı́cı́
všem automatům Ai vytvořeným v předchozı́m bodu, zde vlastně zjišt’ujeme nejdůležitějšı́ charakteristiku cesty v grafu automatu z uzlu (stavu) i do koncových stavů,
• regulárnı́ výrazy vhodně upravı́me, aby byly snadno porovnatelné,
2.5
MINIMALIZACE A NORMOVÁNÍ KONEČNÉHO AUTOMATU
41
• pokud pro některé dva automaty Ai a Aj (i 6= j) vycházı́ stejný regulárnı́ výraz,
znamená to, že stavy i a j jsou rovnocenné (ekvivalentnı́) v základnı́ charakteristice
– na cestě z těchto dvou stavů jsou rozpoznávána tatáž slova (a žádná jiná, jde
o ekvivalenci), proto jeden z nich vlastně můžeme vyřadit, a to následovně (chceme
odstranit stav j a jeho funkci nahradit stavem i):
– nejdřı́v všechny přechody směřujı́cı́ do stavu j přesměrujeme do stavu i,
– pak můžeme stav j odstranit včetně všech přechodů, které z něho vycházejı́.
Přı́klad 2.21
Minimalizujeme následujı́cı́ konečný automat:
a
1
b
a
2
a
b
4
3
→1
2
←3
4
a
b
2
3
4
3
4
Automat je deterministický, proto můžeme začı́t se zjišt’ovánı́m regulárnı́ch výrazů.
0
R11
0
R12
0
R13
0
R14
0
R21
0
R22
0
R23
0
R24
0
R31
0
R32
0
R33
0
R34
0
R41
0
R42
0
R43
0
R44
=ε
=a
=∅
=∅
=∅
=ε
=a
=b
=∅
=∅
=ε
=∅
=∅
=∅
=a
=b+ε
1
R11
1
R12
1
R13
1
R14
1
R21
1
R22
1
R23
1
R24
1
R31
1
R32
1
R33
1
R34
1
R41
1
R42
1
R43
1
R44
=ε
=a
=∅
=∅
=∅
=ε
=a
=b
=∅
=∅
=ε
=∅
=∅
=∅
=a
=b+ε
2
R11
2
R12
2
R13
2
R14
2
R21
2
R22
2
R23
2
R24
2
R31
2
R32
2
R33
2
R34
2
R41
2
R42
2
R43
2
R44
=ε
=a
= aa
= ab
=∅
=ε
=a
=b
=∅
=∅
=ε
=∅
=∅
=∅
=a
=b+ε
3
R11
3
R12
3
R13
3
R14
3
R21
3
R22
3
R23
3
R24
3
R31
3
R32
3
R33
3
R34
3
R41
3
R42
3
R43
3
R44
=ε
=a
= aa
= ab
=∅
=ε
=a
=b
=∅
=∅
=ε
=∅
=∅
=∅
=a
=b+ε
Zajı́majı́ nás pouze cesty vedoucı́ z jednotlivých stavů do koncových stavů (což je jen
stav 3), proto zjistı́me pouze tyto regulárnı́ výrazy:
4
R13
4
R23
4
R33
4
R43
= aa + abb∗ a = ab∗ a
= a + bb∗ a = b∗ a
=ε
= a + (b + ε)b∗ a = a + b∗ a = b∗ a
2.5
MINIMALIZACE A NORMOVÁNÍ KONEČNÉHO AUTOMATU
42
4 a R4 se rovnajı́, proto jeden z nich můžeme
Při porovnánı́ zjistı́me, že výrazy R23
43
odstranit. Je jedno, který zvolı́me, jen nesmı́me zapomenout všechny přechody vedoucı́ do
rušeného stavu přesměrovat do ekvivalentnı́ho stavu.
a
1
b
a
2
a
b
4
3
⇒
a
1
a
2
b
→1
2
3
a
b
2
3
2
←3
Přı́klad 2.22
Minimalizujeme následujı́cı́ konečný automat (počátečnı́ stav je prvkem množiny koncových stavů):
a
b
a
1
2
b
b
a
b
4
b
5
a
a
↔1
2
←3
4
←5
3
a
b
2
2
3
1
3
4
3
2
5
2
Protože v automatu je vı́ce stavů než u předchozı́ho a výpis všech pomocných množin
by byl nepřehledný, vypı́šeme pouze ty množiny, které nejsou prázdné (nemajı́ hodnotu ∅).
0 =ε
R11
0 =a
R12
0 =b
R14
0 =a+ε
R22
0 =b
R23
0 =b
R32
0 =a+ε
R33
0 =a
R41
0 =ε
R44
0 =b
R45
0 =b
R52
0 =a
R53
0 =ε
R55
1 =ε
R11
1 =a
R12
1 =b
R14
1 =a+ε
R22
1 =b
R23
1 =b
R32
1 =a+ε
R33
1 =a
R41
1 = aa
R42
1 = ε + ab
R44
1 =b
R45
1 =b
R52
1 =a
R53
1 =ε
R55
2
R11
2
R12
2
R13
2
R14
=ε
= aa∗
= aa∗ b
=b
2
R22
2
R23
2
R32
2
R33
= a∗
= a∗ b
= ba∗
= a + ε + ba∗ b
3 =ε
R11
3 = aa∗ + aa∗ (a + ba∗ b)∗ ba∗
R12
3 = aa∗ b(a + ba∗ b)∗
R13
2
R41
2
R42
2
R43
2
R44
=a
= aaa∗
= aaa∗ b
= ε + ab
2
R45
2
R52
2
R53
2
R55
=b
= ba∗
= a + ba∗ b
=ε
3 =b
R14
3 = a∗ + a∗ b(a + ba∗ b)∗ ba∗
R22
3 = a∗ b(a + ba∗ b)∗
R23
2.5
3
R32
3
R33
3
R41
3
R42
3
R43
MINIMALIZACE A NORMOVÁNÍ KONEČNÉHO AUTOMATU
= (a + ba∗ b)∗ ba∗
= (a + ba∗ b)∗
=a
= aaa∗ + aaa∗ b(a + ba∗ b)∗ ba∗
= aaa∗ b(a + ba∗ b)∗
3
R44
3
R45
3
R52
3
R53
3
R55
43
= ε + ab
=b
= ba∗
= (a + ba∗ b)(a + ba∗ b)∗
=ε
4 = ε + b(ab)∗ a = (ba)∗
R11
4 = aa∗ + aa∗ (a + ba∗ b)∗ ba∗ + b(ab)∗ (aaa∗ + aaa∗ b(a + ba∗ b)∗ ba∗ )
R12
4 = aa∗ b(a + ba∗ b)∗ + b(ab)∗ aaa∗ b(a + ba∗ b)∗ = (ε + b(ab)∗ a)(aa∗ b(a + ba∗ b)∗ ) =
R13
= (ba)∗ aa∗ b(a + ba∗ b)∗
4
R14 = b
4 = b(ab)∗ b = (ba)∗ bb
R15
4 = a∗ + a∗ b(a + ba∗ b)∗ ba∗
R22
4 = a∗ b(a + ba∗ b)∗
R23
4
R32 = (a + ba∗ b)∗ ba∗
4 = (a + ba∗ b)∗
R33
4 = (ab)∗ a
R41
4 = (ab)∗ (aaa∗ + aaa∗ b(a + ba∗ b)∗ ba∗ )
R42
4 = (ab)∗ aaa∗ b(a + ba∗ b)∗
R43
4 = (ab)∗
R44
4 = (ab)∗ b
R45
4 = ba∗
R52
4 = (a + ba∗ b)(a + ba∗ b)∗
R53
4 =ε
R55
V poslednı́m kroku se zaměřı́me pouze na cesty končı́cı́ v některém koncovém stavu (to
jsou stavy 1, 3 a 5), vypı́šeme i prázdné množiny.
5 = (ba)∗
R11
5 = (ba)∗ aa∗ b(a + ba∗ b)∗ +
R13
+(ba)∗ bb(a + ba∗ b)(a + ba∗ b)∗
5
R15 = (ba)∗ bb
5 =∅
R21
5
R23 = a∗ b(a + ba∗ b)∗
5 =∅
R25
5 =∅
R31
5 = (a + ba∗ b)∗
R33
5 =∅
R35
5 = (ab)∗ a
R41
5 = (ab)∗ aaa∗ b(a + ba∗ b)∗ +
R43
+(ab)∗ b(a + ba∗ b)(a + ba∗ b)∗
5
R45 = (ab)∗ b
5 =∅
R51
5 = (a + ba∗ b)(a + ba∗ b)∗
R53
5 =ε
R55
2.5
MINIMALIZACE A NORMOVÁNÍ KONEČNÉHO AUTOMATU
44
Zbývá zjistit jazyky jednotlivých automatů A1 , A2 , . . . , A5 (odlišujı́cı́ch se pouze svým
počátečnı́m stavem – 1, 2, . . . , 5):
5 + R5 + R5 =
L(A1 ) = L(A) = R11
15
13
= (ba)∗ + (ba)∗ aa∗ b(a + ba∗ b)∗ + bb(a + ba∗ b)(a + ba∗ b)∗ + bb =
= (ba)∗ + (ba)∗ aa∗ b(a + ba∗ b)∗ + bb(a + ba∗ b)∗ =
= (ba)∗ + (ba)∗ (aa∗ b + bb)(a + ba∗ b)∗
5 + R5 + R5 = a∗ b(a + ba∗ b)∗
L(A2 ) = R21
23
25
5 + R5 + R5 = (a + ba∗ b)∗
L(A3 ) = R31
33
35
5 + R5 + R5 = (ab)∗ a + (ab)∗ aaa∗ b(a + ba∗ b)∗ + (ab)∗ b(a + ba∗ b)∗ =
L(A4 ) = R41
43
45
= (ab)∗ a + (ab)∗ (aaa∗ b + b)(a + ba∗ b)∗
5 + R5 + R5 = (a + ba∗ b)∗
L(A5 ) = R51
53
55
Jazyky L(A3 ) a L(A5 ) jsou stejné, proto jeden z těchto stavů můžeme odstranit.
a
b
a
1
2
b
b
a
b
4
Úkol
a
3
b
5
a
⇒
a
b
a
1
2
b
b
a
b
4
a
3
↔1
2
←3
4
a
b
2
2
3
1
4
3
2
3
2.12
C
1. Minimalizujte následujı́cı́ konečný automat:
a
1
b
b
a
2
a
b
4
3
a
5
b
→1
2
←3
4
5
a
b
2
3
4
2
2
3
2
5
2. Následujı́cı́ (nedeterministický) konečný automat
• převed’te na deterministický (po převodu a odstraněnı́ nepotřebných stavů by
měl mı́t čtyři stavy),
• vhodně přeznačte stavy (čı́sla od 1) a určete jazyk tohoto konečného automatu,
• minimalizujte ho.
2.5
MINIMALIZACE A NORMOVÁNÍ KONEČNÉHO AUTOMATU
b
a
a
b
1
a
3
→1
←2
3
2
45
a
b
1, 2
3
1
1
Při úpravách regulárnı́ch výrazů lze využı́t napřı́klad těchto vztahů:
• b(ab)∗ = (ba)∗ b
• (ab)∗ a = a(ba)∗
• b(ab)∗ a = (ba)∗ ba
• ε + b(ab)∗ a = ε + (ba)∗ ba = (ba)∗
• ε + (ba)∗ aa∗ b ((ba)∗ aa∗ b)∗ =
= ((ba)∗ aa∗ b)∗
Pozor, sice platı́ rovnost ε + b∗ a = b∗ , ale napřı́klad regulárnı́ výrazy ε + b∗ ac∗ a b∗ c∗
nejsou ekvivalentnı́!
2.5.2
Normovaný konečný automat
Účelem normovánı́ (čehokoliv) je uvést daný objekt (prvek, automat, atd.) do stavu s určitými žádanými vlastnostmi, a to za účelem snadnějšı́ho prováděnı́ dalšı́ch operacı́ s tı́mto
objektem (napřı́klad porovnávánı́ nebo programovánı́).
Když normujeme konečný automat, chceme, aby měl vhodně označené stavy (tedy
normujeme označenı́ stavů) – stavy by měly být pojmenovány čı́sly od 1 a navı́c by jejich
označenı́ mělo být seřazeno.
Kromě vlastnı́ho označenı́ majı́ stavy jen jedinou dalšı́ charakteristiku – regulárnı́ výraz
odpovı́dajı́cı́ cestě z daného stavu do koncových stavů. Tuto charakteristiku použijeme pro
vytvořenı́ metriky při řazenı́ označenı́ stavů. Postupujeme takto:
• minimalizujeme konečný automat,
• pro každý stav určı́me regulárnı́ výraz cesty z tohoto stavu do koncových stavů,
• v regulárnı́ch výrazech najdeme nejmenšı́ slova,
• stavy porovnáváme takto:
1. stav, jehož regulárnı́ výraz má kratšı́ nejmenšı́ slovo, dostane vyššı́ index než
stav s delšı́m nejmenšı́m slovem, napřı́klad stav s nejmenšı́m slovem ab bude
mı́t vyššı́ čı́slo v označenı́ než stav s nejmenšı́m slovem bba,
2. pokud dva stavy majı́ nejmenšı́ slova stejně dlouhá, pak zvolı́me navı́c dalšı́
metriku – abecedu, napřı́klad stav s nejmenšı́m slovem ab bude mı́t vyššı́ čı́slo
v označenı́ než stav s nejmenšı́m slovem bb,
2.5
MINIMALIZACE A NORMOVÁNÍ KONEČNÉHO AUTOMATU
46
3. pokud se nejmenšı́ slova dvou stavů shodujı́ (tj. předchozı́ metriky selhávajı́),
pak v regulárnı́ch výrazech těchto stavů hledáme druhé nejkratšı́ slovo a to
porovnáváme, pokud se opět shodujı́, hledáme třetı́, atd., dokud nenajdeme
rozdı́l.
Přestože poslednı́ uvedený způsob porovnánı́ může trvat hodně dlouho, u minimalizovaného automat je vždy konečný, protože regulárnı́ výrazy pro žádné dva stavy nejsou
ekvivalentnı́ (kdyby byly ekvivalentnı́, jeden z nich bychom vyřadili při minimalizaci).
Přı́klad 2.23
Seřadı́me následujı́cı́ regulárnı́ výrazy podle výše uvedených kritériı́.
Reg. výraz
Nejkratšı́ slova
ba(ba)∗
ba, baba, bababa, . . .
aab, aabb, aabbb, . . .
ab, abab, ababab, . . .
aab, aaba, aabaa, . . .
ab, abba, abbaba, . . .
ab, aab, bab, aaab, baab, bbab, . . .
b, bb, aab, bbb, baab, aaaab, . . .
b, a, ab, ba, aab, aab, bba, . . .
ab, ba
ε, ab, ba, abab, abba, baab, baba, . . .
aabb∗
ab(ab)∗
aaba∗
ab(ba)∗
b∗ aa∗ b
b∗ (aa)∗ b
a∗ b + b∗ a
ab + ba
(ab + ba)∗
Zjištěné pořadı́
Přidělený index
8
10
6
9
7
5
3
2
4
1
3
1
5
2
4
6
8
9
7
10
Přı́klad 2.24
Znormujeme automat, který jsme zı́skali minimalizacı́ v přı́kladu 2.22 na straně 42.
a
b
a
1
2
b
b
a
b
4
a
3
↔1
2
←3
4
a
b
2
2
3
1
4
3
2
3
Využijeme také regulárnı́ výrazy pro jednotlivé stavy:
5 + R5 + R5 = (ba)∗ + (ba)∗ (aa∗ b + bb)(a + ba∗ b)∗
L(A1 ) = L(A) = R11
13
15
5 + R5 + R5 = a∗ b(a + ba∗ b)∗
L(A2 ) = R21
23
25
5 + R5 + R5 = (a + ba∗ b)∗
L(A3 ) = R31
33
35
5 + R5 + R5 = (ab)∗ a + (ab)∗ (aaa∗ b + b)(a + ba∗ b)∗
L(A4 ) = R41
43
45
2.5
MINIMALIZACE A NORMOVÁNÍ KONEČNÉHO AUTOMATU
47
Z těchto regulárnı́ch výrazů vybereme nejkratšı́ slova:
Stav
1
2
3
4
Nejkratšı́ slova
Nové označenı́ stavu
ab, bb, ba, aba, . . .
b, ba, ab, . . .
ε, a, bb, . . .
a, b, . . .
1
2
4
3
Stavy přeznačı́me a vše ostatnı́ zachováme. Po přeznačenı́ dostaneme tento konečný
automat:
a
b
a
1
2
b
b
Úkol
a
b
3
a
4
↔1
2
←4
3
a
b
2
2
4
1
3
4
2
4
2.13
1. Setřid’te podle výše zadaných kritériı́ následujı́cı́ch 16 regulárnı́ch výrazů:
• a(a + b)a
• a∗ (a + b)a∗
• (a∗ b + a)∗
• a(a + b)∗ a
• a∗ b + a
• (a∗ b + b)∗
• a(a + b)∗ b
• a∗ b
• (b∗ a + b)∗
• a∗ (a + b)a
• b∗ a
• (b∗ a + b)∗
Pozor, může se stát, že některé dva regulárnı́ výrazy jsou ekvivalentnı́.
2. Podle konečného automatu v zadánı́ přı́kladu 2.20 na straně 39 dopočtěte zbývajı́cı́
4 , minimalizujte tento automat a normujte ho.
množiny Rij
3. Podle konečného automatu v zadánı́ přı́kladu 2.14 na straně 28 vytvořte všechny
k , minimalizujte (pokud nenı́ minimálnı́) a normujte ho.
potřebné množiny Rij
C
Kapitola
3
K zásobnı́kovým automatům
Zde se krátce vrátı́me k zásobnı́kovým automatům, které bychom již měli znát. Soustředı́me
se pouze na jejich vlastnosti souvisejı́cı́ s množinovými operacemi.
3.1
Využitı́ uzávěrových vlastnostı́ při konstrukci automatu
Synchronizace dvou částı́ slova (tj. u automatu zjištěnı́, zda mezi jejich délkami je přı́má
úměrnost) se provádı́ pomocı́ zásobnı́ku. V prvnı́ synchronizované části do zásobnı́ku
ukládáme symboly, při čtenı́ druhé části naopak symboly ze zásobnı́ku vyjı́máme. Postup
při navrhovánı́ automatu:
1. Promyslı́me si, co by automat měl provádět v různých částech rozpoznávaného slova.
2. Určı́me stavy, které budou pro jednotlivé části slova použı́vány, platı́, že odlišné
chovánı́ pro různé části slova znamená odlišné stavy.
3. Určı́me, jak se bude v různých stavech při konkrétnı́m symbolu na vrcholu zásobnı́ku
chovat automat.
4. Zajistı́me správné ukončenı́ rozpoznánı́ slova, dále měli bychom otestovat, zda automat správně přijı́má nebo naopak nepřijı́má prázdné slovo, také provedeme otestovánı́ několika typických slov patřı́cı́ch do jazyka a naopak do jazyka nepatřı́cı́ch (pro
kontrolu).
Přı́klad 3.1
Sestrojı́me zásobnı́kový automat pro následujı́cı́ jazyk, využijeme uzávěrové vlastnosti
(konkrétně operaci sjednocenı́ jazyků).
L = {ai bj ck : i, j, k ≥ 1, i = j nebo j = k}
Nejdřı́v sestrojı́me zásobnı́kové automaty pro jazyky
L1 = {ai bi ck : i, k ≥ 1}
L2 = {ai bk ck : i, k ≥ 1}
48
P
3.1
VYUŽITÍ UZÁVĚROVÝCH VLASTNOSTÍ PŘI KONSTRUKCI AUTOMATU
49
Vidı́me, že prvnı́ jazyk splňuje podmı́nku i = j kladenou v původnı́m jazyce, druhý
jazyk zase podmı́nku j = k. Pro oba jazyky lze velmi jednoduše sestrojit zásobnı́kový
automat, to již umı́me. Když pak sestrojı́me sjednocenı́, zı́skáme automat rozpoznávajı́cı́
jazyk L1 ∪ L2 = L.
Nejdřı́v sestrojı́me automat A1 rozpoznávajı́cı́ jazyk L1 . Použijeme tyto stavy:
• q0 . . . začátek výpočtu, načı́táme symboly a ze vstupu, ukládáme je do zásobnı́ku
(zásobnı́k se v každém kroku prodlužuje o 1)
• q1 . . . načı́táme symboly b ze vstupu, pro každý symbol b vyndáme ze zásobnı́ku
jeden symbol a, v každém kroku se zásobnı́k krátı́ o 1
• q2 . . . načı́táme symboly c ze vstupu, v zásobnı́ku by měl být pouze symbol Z0
(v každém kroku je ze zásobnı́ku vyndán a hned vrácen)
• qf . . . koncový stav, v tomto stavu končı́ výpočet (pokud je vstup přečtený a přı́padně
zásobnı́k prázdný, pak výpočet končı́ přijetı́m slova, jinak jeho odmı́tnutı́m).
A1 = (Q1 , Σ, Γ1 , δ1 , q0 , Z1 , F1 ) = ({q0 , q1 , q2 , qf }, {a, b, c}, {Z1 , a}, δ1 , q0 , Z1 , {qf })
δ1 (q0 , a, Z1 ) = (q0 , aZ1 ) . . .
δ1 (q0 , a, a) = (q0 , aa) . . . . .
δ1 (q0 , b, a) = (q1 , ε) . . . . . . .
δ1 (q1 , b, a) = (q1 , ε) . . . . . . .
δ1 (q1 , c, Z1 ) = (q2 , Z1 ) . . . .
δ1 (q2 , c, Z1 ) = (q2 , Z1 ) . . . .
δ1 (q2 , ε, Z1 ) = (qf , ε) . . . . .
prvnı́ rozpoznané pı́smeno musı́ být a, vložı́me je do zásobnı́ku
načı́táme symboly a, ukládáme do zásobnı́ku
prvnı́ b, smažeme jedno a ze zásobnı́ku, přesun do stavu q1
pro každé b ze vstupu odstranı́me jedno a ze zásobnı́ku
třetı́ část slova, v zásobnı́ku už musı́ být jen Z1
načı́táme symboly c, zásobnı́k se neměnı́ (co vyndáme, vrátı́me)
zakončenı́, přechod do koncového stavu
Všimněte si poslednı́ho řádku předpisu – ε neznamená, že vstup byl přečten, znamená
pouze to, že si vstupu „nevšı́máme“; tento řádek může být použit i v přı́padě, že na vstupu
zůstaly nepřečtené symboly, ale v tom přı́padě přecházı́me do koncového stavu, pro který
nemáme žádný předpis, tudı́ž by výpočet nemohl skončit úspěchem. Z toho vyplývá, že
tento řádek lze úspěšně (v posloupnosti konfiguracı́ vedoucı́ ke koncové konfiguraci) použı́t
pouze tehdy, když je celý vstup přečtený.
Poslednı́ řádek by také mohl vypadat takto:
δ1 (q2 , ε, Z1 ) = (qf , Z1 )
a to v přı́padě, že bychom sestrojovali automat, který neodstraňuje symbol konce zásobnı́ku.
Dále sestrojı́me automat A2 rozpoznávajı́cı́ jazyk L2 . Význam stavů bude podobný.
A2 = (Q2 , Σ, Γ2 , δ2 , r0 , Z2 , F2 ) = ({r0 , r1 , r2 , rf }, {a, b, c}, {Z2 , b}, δ2 , r0 , Z2 , {rf })
δ1 (r0 , a, Z2 ) = (r0 , Z2 ) . . . .
δ1 (r0 , b, Z2 ) = (r1 , bZ2 ) . . .
δ1 (r1 , b, b) = (r1 , bb) . . . . . .
δ1 (r1 , c, b) = (r2 , ε) . . . . . . .
δ1 (r2 , c, b) = (r2 , ε) . . . . . . .
δ1 (r2 , ε, Z2 ) = (rf , ε) . . . . .
prvnı́ rozpoznané pı́smeno musı́ být a, zásobnı́k neměnı́me
prvnı́ symbol b, uložı́me do zásobnı́ku
načı́táme symboly b, ukládáme do zásobnı́ku
pro c ze vstupu odstranı́me jedno b ze zásobnı́ku
dto., opakovaně
zakončenı́, přechod do koncového stavu
L
3.1
VYUŽITÍ UZÁVĚROVÝCH VLASTNOSTÍ PŘI KONSTRUKCI AUTOMATU
50
Zbývá sestrojit výsledný automat, který bude rozpoznávat jazyk, jež je sjednocenı́m
předchozı́ch dvou (tj. slova patřı́cı́ bud’ do L1 nebo do L2 ). Postup je principiálně podobný
tomu, co jsme prováděli pro konečné automaty (včetně přidánı́ nového stavu s0 ), ale máme
to jednoduššı́ v tom směru, že lze provádět „prázdné“ přechody – bez čtenı́ ze vstupu,
a naopak postup mı́rně komplikuje zásobnı́k.
Prvnı́m krokem v novém automatu bude nasměrovánı́ výpočtu bud’ do prvnı́ho, a nebo
do druhého původnı́ho automatu (správně bychom měli hovořit o převzetı́ přechodové
funkce). Tedy z počátečnı́ho stavu s0 přecházı́me bud’ do stavu q0 a nebo do stavu r0 , podle
toho, zda je na vstupu slovo z jazyka L1 nebo L2 . Protože v tomto kroku nebude čten vstup
(a ostatně podle prvnı́ho symbolu stejně nelze rozlišit, do kterého z těchto jazyků slovo
patřı́), bude se jednat o nedeterministický krok.
Zároveň s přechodem do jednoho z původnı́ch počátečnı́ch stavů se změnı́ i symbol
na zásobnı́ku. Zásobnı́kový symbol výsledného automatu bude nahrazen zásobnı́kovým
symbolem Z1 nebo Z2 .
A = ({s0 } ∪ Q1 ∪ Q2 , Σ, {Z} ∪ Γ1 ∪ Γ2 , δ, s0 , Z, F1 ∪ F2 ) =
= ({s0 , q0 , q1 , q2 , qf , r0 , r1 , r2 , rf }, {a, b, c}, {Z, Z1 , Z2 , a, b}, δ, s0 , Z, {qf , rf })
Přechodová funkce – nejdřı́v pro nový stav:
δ(s0 , ε, Z) = {(q0 , Z1 ), (r0 , Z2 )}
Zbylou část předpisu δ-funkce přejmeme z automatů A1 a A2 :
(
δ(p, x, Y ) =
δ1 (p, x, Y ) : p ∈ Q1 , x ∈ Σ, Y ∈ Γ1
δ2 (p, x, Y ) : p ∈ Q2 , x ∈ Σ, Y ∈ Γ2
Ukážeme si rozpoznánı́ jednoho ze slov jazyka L(A), slova a3 b3 c2 :
(s0 , aaabbbcc, Z) ` (q0 , aaabbbcc, Z1 ) ` (q0 , aabbbcc, aZ1 ) ` (q0 , abbbcc, aaZ1 ) `
` (q0 , bbbcc, aaaZ1 ) ` (q1 , bbcc, aaZ1 ) ` (q1 , bcc, aZ1 ) ` (q1 , cc, Z1 ) ` (q2 , c, Z1 ) `
` (q2 , ε, Z1 ) ` (qf , ε, ε)
Slovo ε nepatřı́ do jazyka rozpoznávaného automatem, tedy bychom se při výpočtu
neměli dostat do koncové konfigurace, je lepšı́ to ověřit:
(s0 , ε, Z) ` (q0 , ε, Z1 ) `
nelze pokračovat, slovo nepatřı́ do jazyka
Nejkratšı́ slovo jazyka je abc:
(s0 , abc, Z) ` (r0 , abc, Z2 ) ` (r0 , bc, Z2 ) ` (r1 , c, bZ2 ) ` (r2 , ε, Z2 ) ` (rf , ε, ε)
Úkol
3.1
1. Sestrojte zásobnı́kové automaty rozpoznávajı́cı́ tyto jazyky:
(a) L1 = nai bj aj bi : i, j ≥ 1 o
(b) L2 = wwR : w ∈ {a, b}∗
(c) L3 = ai bj : 0 < i < j
C
3.2
UZÁVĚROVÉ VLASTNOSTI JAKO KRITÉRIUM BEZKONTEXTOVOSTI
n
(d) L4 = ai cbj cak : i, j, k ≥ 0, i + j = k
51
o
2. Využijte uzávěrové vlastnosti (konkrétně sjednocenı́) při konstrukci zásobnı́kových
automatů rozpoznávajı́cı́ch tyto jazyky:
n n
n an : n ≥ 1}
(a) L1 = {a
n b : n ≥ 1} ∪ {b o
(b) L2 = wcwR : w ∈ {a, b}∗ ∪ {cn bn : n ≥ 0}
n
(c) L3 = ai cbj cak : i, j, j ≥ 0, i = j + k nebo i + j = k
3.2
o
Uzávěrové vlastnosti jako kritérium bezkontextovosti
Při důkazu, že daný jazyk nenı́ bezkontextový, se ve většině přı́padů využı́vajı́ spı́še gramatiky. Výjimkou je napřı́klad důkaz s využitı́m operace průniku s regulárnı́m jazykem. Vı́me,
že třı́da bezkontextových jazyků je uzavřena vzhledem k průniku s regulárnı́m jazykem,
nynı́ toho využijeme.
Přı́klad 3.2
Dokážeme, že následujı́cı́ jazyk nenı́ bezkontextový:
L = {w ∈ {a, b, c}∗ : |w|a = |w|b = |w|c }
Do tohoto jazyka patřı́ napřı́klad tato slova (v každém slově je stejný počet symbolů a,
b a c, ale o jejich pořadı́ ve slově předpis nic neřı́ká):
L = {ε, abc, acb, bac, bca, cab, cba, aabbcc, aaccbb, aabcbc, . . .}
Provedeme důkaz sporem. Předpokládejme, že L je bezkontextový jazyk. Potom by
jeho průnik s kterýmkoliv regulárnı́m jazykem byl opět bezkontextovým jazykem. Stačı́
tedy najı́t jediný regulárnı́ jazyk takový, že jeho průnik s jazykem L nebude bezkontextový
jazyk.
Vybereme napřı́klad R = a∗ b∗ c∗ , což je regulárnı́ výraz popisujı́cı́ regulárnı́ jazyk, kde
je určeno pořadı́ symbolů ve slově (nejdřı́v symboly a, pak b, potom teprve c), ale naopak
nepředepisuje vzájemný poměr počtu různých symbolů ve slově. Opět pro ilustraci vypı́šeme několik slov jazyka R:
R = {ε, a, b, c, aa, ab, ac, bb, bc, cc, a3 , aab, aac, abb, abc, acc, b3 , bbc, bcc, c3 , . . .}
Průnikem jazyků L a R bude jazyk, který splňuje jak vlastnost rovnosti počtu symbolů
a, b a c ve slově, tak i vlastnost uspořádánı́ symbolů:
n
o
L ∩ R = w ∈ {a, b, c}∗ : |w|a = |w|b = |w|c , w = ai bj ck , i, j, k ≥ 0 = {an bn cn : n ≥ 0}
O tomto jazyce však vı́me, že nenı́ bezkontextový. Dospěli jsme ke sporu, dokázali jsme,
že L nenı́ bezkontextový.
P
Kapitola
4
Regulárnı́ gramatiky
4.1
Opakovánı́
S regulárnı́mi gramatikami jsme se seznámili v předchozı́m semestru. Nejdřı́v si zopakujeme některé základnı́ pojmy a postupy, které by se pro nás měly stát již zcela triviálnı́mi,
abychom mohli navázat v pokročilejšı́ch tématech.
Připomeňme si, že regulárnı́ gramatika s předpisem G = (N, T, P, S) má pravidla v této
formě:
• A → aB, A, B ∈ N, a ∈ T
• A → a,
A ∈ N, a ∈ T
• S → ε je jediné přı́pustné ε-pravidlo, pokud existuje, tak se S nesmı́ nacházet na
pravé straně žádného pravidla.
Pokud máme sestrojit automat, který rozpoznává jazyk generovaný regulárnı́ gramatikou
G = (N, T, P, S), půjde samozřejmě o konečný automat a budeme postupovat takto:
1. Označme A = (Q, Σ, δ, q0 , F ).
2. Abeceda je zřejmá – slova generovaná gramatikou jsou nad abecedou T , proto nad
touto abecedou budou také slova rozpoznávaná automatem:
Σ=T
3. Jako množinu stavů použijeme množinu neterminálů, navı́c přidáme stav X, který
bude sloužit jako koncový stav:
Q = N ∪ {X}
4. Počátečnı́m stavem automatu bude stav vzniklý ze startovacı́ho symbolu S, tedy
q0 = S
5. Množina
( koncových stavů:
{X} : ε ∈
/ L(G)
F =
{S, X} : ε ∈ L(G)
52
P
4.1
OPAKOVÁNÍ
6. Zbývá δ-funkce:
δ(A, a) = B ⇔
δ(A, a) = X ⇔
53
(A → aB) ∈ P, A, B ∈ N, a ∈ T
(A → a) ∈ P, A, B ∈ N, a ∈ T
Přechodovou funkci tedy tvořı́me podle pravidel. Mnemotechnická pomůcka: všimněte si,
že v předpisu δ-funkce jsou jednotlivé prvky ve stejném pořadı́, ve kterém jsou i v pravidle.
Přı́klad 4.1
Podle zadané regulárnı́ gramatiky sestrojı́me konečný automat.
G = ({S, A, B}, {a, b}, P, S)
S → aA | bB
A → aA | aB | a
B → bA | b
Gramatika neobsahuje ε-pravidlo, proto množina koncových stavů bude obsahovat
pouze nový stav X. Automat vypadá takto:
A = ({S, A, B, X}, {a, b}, δ, S, {X})
δ(S, a) = {A}
δ(S, b) = {B}
δ(A, a) = {A, B}
δ(A, b) = {X}
δ(B, b) = {A, X}
a
S
b
a
A
b
b
b
b
B
X
→ S
A
B
← X
a
b
A
A, B
B
X
A, X
Přı́klad 4.2
Podle zadané regulárnı́ gramatiky sestrojı́me konečný automat.
G = ({S, A, B}, {a, b}, P, S), v množině P jsou pravidla
S → bA | ε
A → aB | a
B → bA | b
V jazyce generovaném gramatikou je také prázdné slovo ε a toto slovo musı́ přijı́mat i konečný automat, který vytvořı́me. Počátečnı́ stav automatu přidáme do množiny koncových
stavů.
A = ({S, A, B, X}, {a, b}, δ, S, {S, X})
δ(S, b) = {A}
δ(A, a) = {B, X}
δ(B, b) = {A, X}
a b
S
A
B
b a
b
X
a
↔ S
A
B
← X
b
A
B, X
A, X
L
4.2
NORMÁLNÍ FORMA REGULÁRNÍCH GRAMATIK
54
Jazyk generovaný gramatikou a rozpoznávaný automatem je
L(G) = L(A) = ε + b(ab)∗ a + b(ab)∗ ab = ε + b(ab)∗ a(ε + b)
To by pro připomenutı́ stačilo. Podobné postupy pro různé základnı́ operace s regulárnı́mi
gramatikami (včetně vytvořenı́ gramatiky podle konečného automatu) najdeme ve sbı́rce
přı́kladů pro předmět Teorie jazyků a automatů I.
4.2
Normálnı́ forma regulárnı́ch gramatik
Normálnı́ forma gramatiky obecně je předpis určujı́cı́ formu řetězce na levé a pravé straně
pravidla gramatiky. V přı́padě regulárnı́ch gramatik máme pouze jednu normálnı́ formu,
a to právě tu, kterou jsme dosud běžně použı́vali. Ve skutečnosti se totiž můžeme setkat
s regulárnı́mi gramatikami v obecnějšı́m formátu a pak je třeba takovou gramatiku převést
do normálnı́ formy.
Obecná regulárnı́ gramatika G = (N, T, P, S) může vypadat takto:
• A → a1 a2 . . . an B, A, B ∈ N, ai ∈ T, 1 ≤ i ≤ n
• A → a1 a2 . . . an , A ∈ N, ai ∈ T, 1 ≤ i ≤ n
• může existovat pravidlo S → ε pokud se symbol S nacházı́ na pravé straně žádného
pravidla.
Také se můžeme setkat s gramatikami, kde se vyskytujı́ ε-pravidla i u jiných neterminálů než
jen u startovacı́ho symbolu, přı́padně mohou existovat tzv. jednoduchá pravidla. Jednoduché
pravidlo je pravidlo ve tvaru A → B, tj. neterminál je přepisován jiným neterminálem
(pozor, pravidlo přepisujı́cı́ neterminál na terminál nenı́ jednoduché!).
Regulárnı́ gramatika G = (N, T, P, S) je v normálnı́ formě, pokud všechna jejı́ pravidla
splňujı́ tyto podmı́nky:
• A → aB,
A, B ∈ N, a ∈ T
• A → a, A ∈ N, a ∈ T
• může existovat pravidlo S → ε pokud se symbol S nacházı́ na pravé straně žádného
pravidla.
Pokud máme regulárnı́ gramatiku převést do normálnı́ formy, je třeba postupovat takto:
1. Odstranı́me ε-pravidla, která neodpovı́dajı́ předpisu (pozor, nelze je pouze smazat,
vytvářı́me přece ekvivalentnı́ gramatiku).
2. Odstranı́me jednoduchá pravidla, tj. pravidla typu A → B, tedy na pravé i levé straně
je jeden neterminál.
4.2
NORMÁLNÍ FORMA REGULÁRNÍCH GRAMATIK
55
3. Zkrátı́me přı́liš dlouhá pravidla.
Přı́klad 4.3
Následujı́cı́ gramatiku převedeme do normálnı́ formy pro regulárnı́ gramatiky.
G = ({S, A, B}, {a, b}, P, S)
S → abA | b
A → aaB | a
B → S | bba | ε
Normálnı́ formě neodpovı́dá většina pravidel. Předevšı́m tu máme ε-pravidlo, které by
u symbolu B nemělo být, dále jedno jednoduché pravidlo a potom je třeba několik pravidel
zkrátit. Postupně provedeme tyto úpravy:
1. Odstranı́me ε-pravidlo:
Pravidlo B → ε odstranı́me, ale abychom zajistili ekvivalenci nové a původnı́ gramatiky,
musı́me „simulovat“ použitı́ tohoto pravidla. Symbol B se nacházı́ na pravé straně pravidla
A → aaB, pokud by toto pravidlo bylo použito v derivaci a v následujı́cı́m kroku bychom
použili ε-pravidlo, derivace by vypadala takto:
. . . ⇒ γA ⇒ γaaB ⇒ γaa ⇒ . . .
Proto přidáme nové pravidlo:
A → aa
Obrazem uvedené derivace z původnı́ gramatiky by pro novou gramatiku bylo:
. . . ⇒ γA ⇒ γaa ⇒ . . .
Kdyby se symbol B vyskytoval na pravé straně vı́ce pravidel, provedli bychom totéž pro
všechna tato pravidla. Po změně jsou pravidla následujı́cı́:
S → abA | b
A → aaB | aa | a
B → S | bba
2. Odstranı́me jednoduché pravidlo:
Je zde pouze jedno jednoduché pravidlo, B → S. Opět z důvodu zajištěnı́ ekvivalence nové
gramatiky s původnı́ budeme vycházet z možných derivacı́:
. . . ⇒ γB ⇒ γS ⇒ γabA ⇒ . . .
. . . ⇒ γB ⇒ γS ⇒ γb ⇒ . . .
Pravou stranu jednoduchého pravidla proto nahradı́me pravými stranami pravidel přepisujı́cı́ch symbol S. Mı́sto pravidla B → S zı́skáme pravidla
B → abA | b
Všechna pravidla:
S → abA | b
A → aaB | aa | a
4.2
NORMÁLNÍ FORMA REGULÁRNÍCH GRAMATIK
56
B → abA | b | bba
3. Zkrátı́me dlouhá pravidla:
Z důvodu zachovánı́ ekvivalence gramatik použijeme nové neterminály. U předchozı́ch
úprav jsme vlastně derivaci krátili, ted’ ji budeme prodlužovat. Napřı́klad mı́sto následujı́cı́
derivace
. . . ⇒ γB ⇒ γabA
bude derivace
. . . ⇒ γB ⇒ γaZ1 ⇒ γabA
Což mı́sto B → abA předpokládá pravidla
B → aZ1
Z1 → bA
Ted’ už můžeme zkompletovat celou gramatiku:
G0 = ({S, A, B, Z1 , Z2 , Z3 , Z4 }, {a, b}, P 0 , S)
S → aZ1 | b
Z1 → bA
A → aZ2 | aZ3 | a
Z2 → aB
Z3 → a
B → aZ1 | b | bZ4
Z4 → bZ3
Jak vidı́me, gramatika je v normálnı́ formě pro regulárnı́ gramatiky a navı́c L(G0 ) = L(G),
tedy gramatiky jsou ekvivalentnı́.
Přı́klad 4.4
Následujı́cı́ gramatiku opět převedeme do normálnı́ formy pro regulárnı́ gramatiky.
G = ({S, A}, {0, 1, 2}, P, S)
S → 0A | 1S | ε
A → 2A | 1S | 2
Pravidlo S → ε by samo o sobě nemuselo vadit, ale vidı́me, že symbol S je na pravé
straně dokonce dvou pravidel. Řešenı́m je vytvořit nový startovacı́ symbol, který se na
začátku derivace bude chovat stejně jako S (tj. pro tento symbol budou stejná pravidla jako
pro S), ale samozřejmě nebude na pravé straně žádného pravidla.
S 0 → 0A | 1S | ε
Pak ε-pravidlo vyřešı́me stejně jako v předchozı́m přı́kladu.
Po úpravě:
G0
= ({S 0 , S, A}, {0, 1, 2}, P, S 0 )
S 0 → 0A | 1S | 1 | ε
S → 0A | 1S | 1
A → 2A | 1S | 1 | 2
(pravidlo S 0 → 1 jsme přidali při eliminaci pravidla S → ε)
4.2
NORMÁLNÍ FORMA REGULÁRNÍCH GRAMATIK
57
Mohlo by se zdát, že normálnı́ forma pro regulárnı́ gramatiky je zbytečná, vždyt’ zvyšuje
množstvı́ pravidel (všimněte si, jakým způsobem se krátila pravidla). Normálnı́ forma má
význam předevšı́m v úlohách, kde provádı́me srovnánı́, využı́váme gramatiku v některém algoritmu či důkazu (když se nad tı́m zamyslı́te, algoritmus a důkaz majı́ mnoho
společného), a také pokud podle gramatiky vytvářı́me ekvivalentnı́ konečný automat.
Úkol
4.1
Následujı́cı́ gramatiky převed’te do normálnı́ formy pro regulárnı́ gramatiky:
G1 = ({S, A, B}, {a, b}, P, S)
S → aB | bA
A → bbB | ε
B → aA | b
G2 = ({S, A, B}, {a, b, c}, P, S)
S → bbA | aS | ε
A → abaA | bB | a
B → cabS | bc
L
C
Kapitola
5
Bezkontextové gramatiky
5.1
Derivačnı́ strom
Derivačnı́ strom je vlastně graf, který je stromem (má jediný kořen, každý uzel kromě kořene
má právě jednoho předka a hrany jsou orientované, i když orientaci neznačı́me), tvořený
podle pravidel gramatiky použitých v derivaci, podle které je derivačnı́ strom vytvořen.
Přı́klad 5.1
Sestrojı́me bezkontextovou gramatiku pro jazyk L = {0n 102n 1i | i, n ≥ 1} a vytvořı́me
derivaci slova 0010000111 a derivačnı́ strom k této derivaci.
G = ({S, A, B}, {0, 1}, P, S)
S → AB
A → 0A00 | 0100
B → 1B | 1
Derivace slova 0010000111 je následujı́cı́:
S ⇒ AB ⇒ 0A00B ⇒ 0010000B ⇒ 00100001B ⇒ 001000011B ⇒ 0010000111
Modře je vyznačena pravá část pravidla, které bylo v daném kroku odvozenı́ použito
(napřı́klad v druhém kroku jsme použili pravidlo A → 0A00).
Derivačnı́ strom se vždy vztahuje ke konkrétnı́ derivaci. Podle výše uvedené derivace
postupně sestrojı́me derivačnı́ strom takto (jsou uvedeny i mezikroky):
S ⇒ AB
S ⇒ AB ⇒ 0A00B
S → AB
A → 0A00
S
A
B
S
A
0
58
A
0
B
0
P
5.1
DERIVAČNÍ STROM
59
S ⇒ AB ⇒ 0A00B ⇒ 0010000B
A → 0100
S ⇒ . . . ⇒ 0010000B ⇒ 00100001B
B → 1B
S
A
S
A
B
B
0
A
0
0
0
A
0
0
0
1
0
0
0
1
0
0
S ⇒ . . . ⇒ 00100001B ⇒ 001000011B
B → 1B
S ⇒ . . . ⇒ 001000011B ⇒ 0010000111
B→1
S
A
S
A
B
0
A
0
0
0
1
0
0
B
1
1
B
1
B
B
0
A
0
0
0
1
0
0
1
B
1
B
1
V jednotlivých krocı́ch je kromě samotného stromu uvedeno použité pravidlo a také momentálnı́ stav derivace. Modře je vyznačena větná forma, kterou jsme v daném kroku
vytvořili. Můžeme si všimnout, že v derivačnı́m stromě vždy jde o obsah listů stromu
v daném kroku. Derivačnı́ strom dané derivace je poslednı́ v pořadı́.
Úkol
5.1
1. Podle zadané gramatiky vytvořte derivaci slova ababa a k nı́ derivačnı́ strom.
G = ({S, A, B}, {a, b}, P, S)
S → bAB | aBA | ε
A → abAab | ε
B → baBba | ε
2. Podle gramatiky z předchozı́ho přı́kladu vytvořte derivaci jakéhokoliv slova o délce
alespoň 6 začı́najı́cı́ho symbolem b a k této derivaci sestrojte derivačnı́ strom.
3. Sestrojte gramatiky generujı́cı́ následujı́cı́ jazyky. V každém jazyce vyberte jakékoliv
slovo o délce alespoň 3 symboly, vytvořte jeho derivaci a sestrojte k nı́ derivačnı́ strom.
(a) L1 = (ab)i cj (ba)i : i, j ≥ 0
(b) L2 = {0n 11n : n ≥ 3} ∪ {ε}
(c) L3 = 0i 10i : i ≥ 1 ∪ 1i 01i : i ≥ 1
L
C
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
60
(d) L4 = {abc, bad, f aa, diff } (nezapomeňte, že na pravé straně pravidla může být
jakýkoliv řetězec)
5.2
5.2.1
Úpravy bezkontextových gramatik
Redukce gramatiky
Účelem redukce gramatiky je snı́ženı́ počtu neterminálů při zachovánı́ generovaného jazyka. Odstraňujeme
• nadbytečné neterminály (tj. neterminály, ze kterých nelze vygenerovat žádné terminálnı́
slovo),
P
• nedostupné symboly (terminálnı́ i neterminálnı́ – nelze je vygenerovat ze startovacı́ho
symbolu).
Zachováváme toto pořadı́ – nejdřı́v nadbytečné a pak teprve nedostupné. Použı́váme podobný postup jako při redukci množiny stavů konečného automatu.
V obou přı́padech rekurzı́vně (použijeme indukci) tvořı́me množinu obsahujı́cı́ všechny
symboly, které v gramatice majı́ zůstat. Formálnı́ zápis pro gramatiku G = (N, T, P, S):
• Odstraňujeme nadbytečné neterminály:
N0 = T
(báze indukce – použijeme množinu terminálů)
∗ }
Ni = Ni−1 ∪ {A ∈ N : (A → α) ∈ P, α ∈ Ni−1
(do následujı́cı́ množiny vložı́me obsah předchozı́ množiny a přidáme všechny symboly, pro které existuje pravidlo, kde na pravé straně jsou pouze symboly z množiny
z předchozı́ho kroku, pozor, α může být i ε – prázdné slovo!)
Končı́me tehdy, když v daném kroku nepřidáme žádný symbol, Nk+1 = Nk , kde k
je nejmenšı́ takový index, pro který daná rovnost platı́. Pak zjistı́me novou množinu
neterminálů:
N 0 = N ∩ Nk
(protože v množině Nk jsou také terminály).
• Odstraňujeme nedostupné symboly (terminálnı́ i neterminálnı́):
V0 = {S}
(báze indukce, začı́náme startovacı́m symbolem)
Vi = Vi−1 ∪ {X ∈ (N ∪ T ) : (A → αXβ) ∈ P, A ∈ Vi−1 }
(přidáme všechny symboly, které se nacházejı́ na pravé straně pravidel přepisujı́cı́ch
již zařazené neterminály)
Končı́me opět tehdy, když nedocházı́ ke změnám, Vr+1 = Vr , kde r je nejmenšı́
takový index, pro který daná rovnost platı́. Pak zjistı́me nové množiny terminálů
a neterminálů:
N 00 = N 0 ∩ Vr
T 0 = T ∩ Vr
P
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
61
Když se nad tı́m zamyslı́me, tak při odstraňovánı́ nadbytečných neterminálů vlastně zjišt’ujeme, které symboly jsou použı́vány, proti směru derivace (mnemotechnická pomůcka:
v pravidlech se dı́váme „proti směru šipky“), kdežto při odstraňovánı́ nedostupných symbolů naopak jdeme ve směru derivace a zjišt’ujeme, které symboly mohou být vygenerovány
(po různém počtu kroků) ze startovacı́ho symbolu (v pravidlech postupujeme „ve směru
šipky“).
Přı́klad 5.2
Redukujeme následujı́cı́ gramatiku:
G = ({S, A, B, C, D}, {a, b, c, d}, P, S)
S → bS | bD | ε
A → aCB | bAD
B → dB | d
C → bCC | aAbB
D → bA | cDb | aS | ε
Nejdřı́v odstranı́me nadbytečné neterminály. Rekurzı́vně vytvořı́me množinu všech
symbolů, které jsou bud’ terminálnı́ a nebo z nich lze vygenerovat terminálnı́ řetězec (v přı́padě, že jde o neterminál). Bázı́ rekurze je množina všech terminálů. V dalšı́ch krocı́ch
přidáváme neterminály z levých stran pravidel, na jejichž pravé straně jsou pouze symboly, které jsme do našı́ množiny přidali v předchozı́ch krocı́ch (a nebo pro ně existuje
ε-pravidlo).
N0 = {a, b, c, d}
N1 = {a, b, c, d, S, B, D}
N2 = {a, b, c, d, S, B, D}
(podle pravidel S → ε, B → d, D → ε)
(podle pravidel S → bS | bD, B → dB, D → cDb | aS)
Protože jsme do množiny N2 oproti množině N1 nic dalšı́ho nepřidali, rekurze končı́.
Množina neterminálů bude N ∩ N2 = {S, B, D}, vyřadı́me neterminály A a C včetně všech
pravidel, která je obsahujı́ na levé nebo pravé straně. Gramatika po odstraněnı́ nadbytečných symbolů je následujı́cı́:
G0 = ({S, B, D}, {a, b, c, d}, P 0 , S)
S → bS | bD | ε
B → dB | d
D → cDb | aS | ε
Zbývá odstranit nedostupné symboly. Postupujeme opět rekurzı́vně. Vytvořı́me množinu symbolů, které se nacházejı́ v nějaké větné formě v derivaci ze startovacı́ho symbolu. Začneme množinou obsahujı́cı́ pouze startovacı́ symbol, v každém kroku přidáváme
symboly, které se nacházejı́ na pravých stranách pravidel přepisujı́cı́ch symboly zařazené
v předchozı́ch krocı́ch.
V0 = {S}
V1 = {S, b, D}
(podle pravidel S → bS | bD)
L
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
V2 = {S, b, D, c, a}
V3 = V2
62
(podle pravidel D → cDb | aS)
Z postupu vyplývá, že pokud v některém kroku přidáme pouze terminálnı́ symboly,
v následujı́cı́m kroku již nelze nic přidat (protože terminály se nepřepisujı́ žádným pravidlem) a rekurze končı́. Je zřejmé, že nedostupný neterminál je jeden (B) a terminál taktéž
jeden (d). Redukovaná gramatika (tj. již bez nadbytečných i nedostupných symbolů) je
následujı́cı́:
G00 = ({S, D}, {a, b, c}, P 00 , S)
S → bS | bD | ε
D → cDb | aS | ε
Úkol
5.2
C
Redukujte tyto gramatiky:
G1 = ({S, A, B, C, D}, {a, b, c, d}, P, S)
G2 = ({S, A, B, C, D, E}, {0, 1, 2, 3}, P, S)
S → aBa | bA | c | ABc
A → aA | dD | bDa
B → aB | bA | bS
C → aSc | cC | c
D → dD | aAb
S → AB0 | 2E | A1 | ε
A → 0A0 | 1B | 1S
B → 01B | 1D | EB
C → 2A | 1S | 0
D → D1 | 3B
E → 0E1 | 1B
G3 = ({S, A, B, C, D}, {a, b, c}, P, S)
G4 = ({S, A, B, C, D}, {a, b, c}, P, S)
S → aD | bBD | c
A → bbB | aA
B → bB | aAb
C → aD | b
D → cS | aDD | ε
5.2.2
S → BaD | a
A → aS | cc
B → bSB | DC | ε
C → aSDC | bSC
D → aC | Da | BS
Převod na nezkracujı́cı́ bezkontextovou gramatiku
Nezkracujı́cı́ bezkontextová gramatika bud’ vůbec neobsahuje ε-pravidla (pokud v jazyce
generovaném gramatikou nenı́ prázdné slovo), a nebo existuje jediné takové pravidlo, a to
pro startovacı́ symbol gramatiky, pak ale se startovacı́ symbol nesmı́ vyskytovat na pravé
straně žádného pravidla (to znamená, že v každé derivaci se vyskytuje pouze na jejı́m
začátku, pak už ne).
P
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
63
Při převodu na nezkracujı́cı́ gramatiku odstraňujeme ε-pravidla tak, že „simulujeme“
jejich použitı́. Stejný postup jsme použili i v algoritmu převodu regulárnı́ gramatiky do
normálnı́ formy.
Přı́klad 5.3
K následujı́cı́ gramatice vytvořı́me ekvivalentnı́ gramatiku s nezkracujı́cı́mi pravidly.
G = ({S, A, B}, {a, b}, P, S)
S → aaB | bAb
A → aBa | ε
B → AbAa | a
Téměř všechna pravidla jsou nezkracujı́cı́, je zde pouze jediné ε-pravidlo – A → ε.
Přepisovaný symbol A se nacházı́ na pravé straně dvou pravidel – druhého a pátého. Obě
tato pravidla necháme a přidáme jejich varianty se „simulovaným“ použitı́m ε-pravidla:
G0 = ({S, A, B}, {a, b}, P 0 , S)
S → aaB | bAb | bb
A → aBa
B → AbAa | bAa | Aba | ba | a
U prvnı́ho ze zpracovávaných pravidel máme jen jeden výskyt neterminálu A, tedy
existuje pouze jediná dalšı́ varianta (toto jediné A odstranı́me – přepı́šeme na ε). U druhého
zpracovávaného pravidla jsou dva výskyty neterminálu A, proto musı́me vytvořit variant
vı́ce – odstranı́me jen prvnı́ A, odstranı́me jen druhé, a nebo odstranı́me obě.
Derivace v gramatice G0 bude téměř stejná jako v gramatice G, ale kroky s použitı́m
ε-pravidel jsou „přeskočeny“, napřı́klad
v gramatice G:
v gramatice G0 :
S ⇒ aaB ⇒ aaAbAa ⇒ aabAa ⇒ aabaBaa ⇒ aabaaaa
S ⇒ aaB ⇒ aabAa ⇒ aabaBaa ⇒ aabaaaa
Přı́klad 5.4
K zadané gramatice vytvořı́me ekvivalentnı́ nezkracujı́cı́ gramatiku (tj. generujı́cı́ tentýž
jazyk).
G = ({S, A}, {a, b, c}, P, S)
S → aaS | bbA | ε
A → cSbSc | ε
Gramatika generuje také prázdné slovo. Proto nejdřı́v použijeme stejný postup jako
v předchozı́m přı́kladu, ale pak ještě musı́me zajistit, aby výsledná gramatika také generovala prázdné slovo a přitom zůstala nezkracujı́cı́.
Nejdřı́v vytvořı́me pomocnou gramatiku G0 , která nemá žádná ε-pravidla, jejı́ jazyk je
L(G0 ) = L(G) − {ε}.
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
64
G0 = ({S, A}, {a, b, c}, P 0 , S)
S → aaS | aa | bbA | bb
A → cSbSc | cbSc | cSbc | cbc
Přidáme nový neterminál (startovacı́ symbol) a vytvořı́me gramatiku, která již bude
ekvivalentnı́ původnı́ gramatice.
G00 = ({S 0 , S, A}, {a, b, c}, P 00 , S 0 )
S0 → S | ε
S → aaS| aa | bbA| bb
A → cSbSc | cbSc | cSbc | cbc
Derivace v gramatice G:
Derivace v gramatice G00 :
S ⇒ aaS ⇒ aaaaS ⇒ aaaa
S 0 ⇒ S ⇒ aaS ⇒ aaaa
Přı́klad 5.5
Někdy se může stát, že „simulacı́“ ε-pravidla vytvořı́me dalšı́ ε-pravidlo. Pak je třeba
postup provádět rekurzı́vně tak dlouho, dokud nejsou všechna ε-pravidla odstraněna.
G = ({S, A, B}, {a, b}, P, S)
S → bA | aS | bB | a
A → baB | ε
B → AA | b
Po odstraněnı́ pravidla A → ε dostaneme tuto gramatiku:
G0 = ({S, A, B}, {a, b}, P 0 , S)
S → bA | b | aS | bB | a
A → baB
B → AA | A | ε | b
Odstraněnı́m obou symbolů A v pravidle B → AA vzniklo dalšı́ ε-pravidlo, které je
také třeba odstranit:
G00 = ({S, A, B}, {a, b}, P 00 , S)
S → bA | b | aS | bB | b | a
A → baB | ba
B → AA | A | b
Rekurze při řešenı́ pravidel se zbavı́me tak, že ji přeneseme jinam. Můžeme použı́t řešenı́
podobné tomu z redukce gramatiky – vytvořı́me (rekurzı́vně) množinu Nε všech neterminálů, které lze (třeba i po vı́ce než jednom kroku) přepsat na prázdné slovo ε.
V množině Nε,0 bude pouze prázdný řetězec, tj. Nε,0 = {ε}. V dalšı́ch krocı́ch do
této množiny přidáváme neterminály, které lze přepsat na řetězec skládajı́cı́ se pouze ze
P
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
65
symbolů, které byly do této množiny přidány v předchozı́ch krocı́ch, tj.
Nε,i = Nε,i−1 ∪ {X ∈ N : X → α, α ∈ Nε,i−1 }.
Přı́klad 5.6
Podle pravidel gramatiky
G = ({S, A, B, C, D}, {a, b, c, d}, P, S)
S → aAa | aa
A → BC | b
B → aC | cD | ε
C → AAa | ε
D → AAB | d
vytvořı́me tyto množiny:
Nε,0
Nε,1
Nε,2
Nε,3
= {ε}
= {B, C} podle B → ε, C → ε, prázdné slovo už nezařazujeme
= {B, C, A} podle A → BC
= {B, C, A, D} podle D → AAB
V dalšı́m kroku již nelze dalšı́ neterminál přidat (ostatně všechny už v množině jsou),
proto Nε = Nε,3 = {B, C, A, D}.
Množiny použijeme takto: pokud je na pravé straně pravidla některý z neterminálů
obsažených v množině Nε , pak vytvořı́me dalšı́ pravidla se „simulovaným“ použitı́m εpravidel na tento neterminál, ε-pravidla odstranı́me.
Postup je prakticky stejný jako předchozı́, ale zpracovánı́ gramatiky již nenı́ třeba provádět rekurzı́vně (rekurze byla použita při generovánı́ množiny Nε ). Fialovou barvou jsou
zvýrazněny neterminály obsažené v množině Nε (a tedy vytvořı́me pravidlo, ve kterém je
odstranı́me), modrou barvou pak nová pravidla.
S → aAa | aa | aa (vlastně máme dvě stejná pravidla, jedno může být odstraněno)
A → BC | C | B | b
B → aC | a | cD | c
C → AAa | Aa | a
D → AAB | AB | B | d
Přı́klad 5.7
Postup předvedený v předchozı́m přı́kladu použijeme na gramatiku z přı́kladu 5.5.
G = ({S, A, B}, {a, b}, P, S)
S → bA | aS | bB | a
A → baB | ε
B → AA | b
Opět rekurzı́vně vytvořı́me množinu Nε :
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
66
Nε,0 = {ε}
Nε,1 = {A}
Nε,2 = {A, B} = Nε,3 = Nε
Vycházı́ nám tato gramatika:
G0
= ({S, A, B}, {a, b}, P 0 , S)
S → bA | b | aS | bB | b | a
A → baB | ba
B → AA | A | b
Oproti původnı́mu řešenı́ nenı́ třeba několikrát přepisovat pravidla gramatiky.
Úkol
5.3
K následujı́cı́m gramatikám vytvořte ekvivalentnı́ nezkracujı́cı́ gramatiky.
G1 = ({S, A, B}, {a, b}, P, S)
G2 = ({S, A}, {0, 1}, P, S)
G3 = ({S, A, B}, {a, b}, P, S)
G4 = {S, A, B}, {a, b}, P, S)
G5 = ({S, A, B}, {a, b}, P, S)
G6 = ({S, A, B}, {a, b}, P, S)
S → aSbA | ab
A → aAbA | ε
B → bAbB | b
S → BAa | aS | ε
A → aA | ε
B → bBA | ε
S → aABa | bS | b
A → aAA | bB | ε
B → bB | aS | b
5.2.3
C
S → S1S1 | A | ε
A → 0A0 | 1
S → AB | BA | b
A → aaA | ε
B → AA | bS | a
S → aAA | bB | ε
A → AaB | a | ε
B → BbAA | a
Odstraněnı́ jednoduchých pravidel
Jednoduchá pravidla jsou taková pravidla, na jejichž pravé straně máme jen jediný symbol,
a to neterminál, napřı́klad A → B (opět jsme se s nimi setkali při převodu regulárnı́ gramatiky na normálnı́ formu). Jednoduchá pravidla zbytečně prodlužujı́ výpočet a v některých
algoritmech mohou být překážkou při programovánı́.
Pokud tento typ pravidel chceme odstranit, můžeme jednoduše nahradit symbol na
pravé straně jednoduchého pravidla celou množinou pravidel, na která se tento symbol
P
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
67
přepisuje. Napřı́klad pokud existujı́ pravidla B → α | β | γ, pak jednoduché pravidlo
A → B nahradı́me pravidly A → α | β | γ (v derivaci to bude znamenat zkrácenı́ odvozenı́
o jeden krok – zpracovánı́ jednoduchého pravidla).
Protože touto náhradou můžeme opět pro daný neterminál dostat jednoduché pravidlo,
postup je rekurzivnı́ a lze ho zjednodušit přenesenı́m rekurze na množiny neterminálů
podobně jako v předchozı́ch postupech. Vytvářı́me množiny NA postupně pro všechny
neterminály A ∈ N , které inicializujeme jednoprvkovou množinou obsahujı́cı́ neterminál
v označenı́ množiny (tj. v tomto přı́padě A). Jde o množiny neterminálů, jejichž pravidla
se pomocı́ jednoduchých pravidel majı́ postupně připsat do množiny pravidel pro daný
neterminál A.
Přı́klad 5.8
Odstranı́me jednoduchá pravidla v následujı́cı́ gramatice:
G = ({S, A, B, C}, {a, b}, P, S)
S → aBa | A
A → aA | B
B → bB | AB | C | ε
C → bA | b
Rekurzı́vně vytvořı́me množiny NS , NA , NB , NC . Na začátku rekurze, v bázi, bude
v dané množině pouze ten symbol, pro který množinu tvořı́me, tj. napřı́klad NS,0 = {S}.
NS,0
NS,1
NS,2
NS,3
= {S}
= {S, A} (podle S → A)
= {S, A, B} (podle A → B)
= {S, A, B, C} = NS,4 = NS (podle B → C)
NA,0 = {A}
NA,1 = {A, B} (podle A → B
NA,2 = {A, B, C} = NA,3 = NA
NB,0 = {B}
NB,1 = {B, C} = NB,2 = NA
(podle B → C)
(podle B → C)
NC,0 = {C} = NC,1 = NC
Z gramatiky odstranı́me všechna jednoduchá pravidla. Po jejich odstraněnı́ pak použijeme vytvořené množiny – pokud napřı́klad pro neterminál A je NA = {A, B, C}, pak
v gramatice pro neterminál A použijeme všechna pravidla, která v původnı́ gramatice byla
pro neterminály A, B, C.
G0 = ({S, A, B, C}, {a, b}, P 0 , S)
S → aBa | aA | bB | AB | ε | bA | b
A → aA | bB | AB | ε | bA | b
B → bB | AB | ε | bA | b
C → bA | b
P
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
68
Pokud nám vadı́ pouze jednoduchá pravidla samotná, předchozı́ postup je dostačujı́cı́.
Jestliže však je překážkou samotné chovánı́ jednoduchých pravidel (napřı́klad prodlužovánı́ derivace), je třeba předem odstranit ε-pravidla. Napřı́klad v gramatice z přı́kladu 5.9
po odstraněnı́ jednoduchých pravidel existuje derivace S ⇒ AB ⇒ A ⇒ . . ., kde nacházı́me
ekvivalent použitı́ jednoduchého pravidla S → A z původnı́ gramatiky.
L
Přı́klad 5.9
Gramatiku z přı́kladu 5.9 převedeme na nezkracujı́cı́, pak odstranı́me jednoduchá pravidla.
G = ({S, A, B, C}, {a, b}, P, S)
S → aBa | A
A → aA | B
B → bB | AB | C | ε
C → bA | b
Po převodu na nezkracujı́cı́ gramatiku:
Odstranı́me jednoduchá pravidla:
Nε = {B, A, S}
NS = {S, A, B, C}
NA = {A, B, C}
NB = {B, A, C}
(všimněte si rozdı́lu oproti přı́kladu 5.9)
NC = {C}
G0 = ({S, A, B, C}, {a, b}, P 0 , S)
S → aBa | aa | A | ε
A → aA | a | B
B → bB | b | AB | A | B | C
C → bA | b
G00 = ({S, A, B, C}, {a, b}, P 00 , S)
S → aBa | aa | aA | a | ε | aA | a | bB | b | AB | bA | b
A → aA | a | bB | b | AB | bA | b
B → bB | b | AB | aA | a | bA | b
C → bA | b
Úkol
5.4
Odstraňte jednoduchá pravidla z následujı́cı́ch gramatik:
G1 = ({S, A, B}, {0, 1}, P, S)
S → 0A1 | B | ε
A → 1S | S | B
B → 1A | S | 0
G2 = ({S, A, B}, {a, b}, P, S)
S → aA | bB | A
A → bAb | S | ε
B → aBa | A | a
C
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
5.2.4
69
Gramatika bez cyklu a vlastnı́ gramatika
Gramatika bez cyklu je taková gramatika, kde neexistuje žádná derivace A ⇒+ A pro jakýkoliv neterminál A. Už z definice je zřejmé, jak gramatiku upravit, aby splňovala tuto
vlastnost – stačı́ ji převést na nezkracujı́cı́ gramatiku (bez ε-pravidel) a odstranit jednoduchá
pravidla.
Vlastnı́ gramatika je gramatika bez cyklu, nezkracujı́cı́ a bez nadbytečných symbolů.
Postup je tedy následujı́cı́:
• převedeme gramatiku na nezkracujı́cı́,
P
P
• odstranı́me jednoduchá pravidla,
• odstranı́me nadbytečné symboly postupem, který již známe z redukce gramatiky.
5.2.5
Levá a pravá rekurze
Gramatika je rekurzivnı́ zleva, pokud v nı́ existuje derivace A ⇒+ Aα, gramatika je rekurzı́vnı́ zprava, pokud v nı́ existuje derivace A ⇒+ αA, kde A je některý neterminál
gramatiky, α je jakýkoliv řetězec z terminálů a neterminálů.
Levá nebo pravá rekurze nám může bránit v některých dalšı́ch úpravách a nebo v naprogramovánı́ postupu popsaného gramatikou (ano, čtete dobře, pı́še se tady o programovánı́
podle gramatiky, bližšı́ informace v předmětu Překladače). Obvykle nám vadı́ jen levá
a nebo jen pravá rekurze, proto jejich odstraněnı́ řešı́me jednoduše převodem na tu, která
nám nevadı́. Při odstraňovánı́ rekurze vycházı́me z toho, že k témuž řetězci lze dojı́t vı́ce
různými způsoby.
Postup je následujı́cı́:
1. Předběžné úpravy: převedeme gramatiku do tvaru vlastnı́ gramatiky, tj.
• převedeme do tvaru nezkracujı́cı́ gramatiky,
• odstranı́me jednoduchá pravidla,
• odstranı́me nadbytečné a nedostupné symboly.
2. Levou rekurzi převedeme na pravou rekurzi.
V druhém bodu vycházı́me z této myšlenky: předpokládejme, že máme sadu pravidel pro
tentýž neterminál, označme
A → Aα1 | Aα2 | . . . Aαn | β1 | β2 | . . . | βk
kde řetězce βi , 1 ≤ i ≤ k začı́najı́ jiným symbolem než A
Je zřejmé, že tato pravidla v rekurzi vygenerujı́ řetězec, na jehož začátku bude některý
z podřetězců βi a bude následovat libovolný počet podřetězců αj , napřı́klad:
A ⇒ Aα3 ⇒ Aα5 α3 ⇒ Aα2 α5 α3 ⇒ β8 α2 α5 α3
Je třeba tedy sestavit pravidla taková, aby byly generovány tytéž řetězce, ale bez levé
rekurze. Původnı́ sadu pravidel nahradı́me jinou sadou:
P
P
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
70
A → β1 B | β2 B | . . . | βk B | β1 | β2 | . . . | βk
B → α1 B | α2 B | . . . | αn B | α1 | α2 | . . . | αn
Předchozı́ derivaci podle původnı́ch pravidel by odpovı́dala následujı́cı́ derivace:
A ⇒ β8 B ⇒ β8 α2 B ⇒ β8 α2 α5 B ⇒ β8 α2 α5 α3
Vidı́me, že je generován tentýž řetězec, jen v opačném pořadı́ – zleva mı́sto zprava, tedy
levou rekurzi jsme nahradili pravou rekurzı́. Pozor – provedenı́m výše naznačených úprav
můžeme opět zı́skat levě rekurzivnı́ pravidla, tedy postup je třeba provádět tak dlouho,
dokud se nezbavı́me levě rekurzivnı́ch pravidel.
Přı́klad 5.10
Následujı́cı́ gramatiku zbavı́me levé rekurze. Gramatika je nezkracujı́cı́, neobsahuje jednoduchá pravidla, neobsahuje ani nadbytečné a nedostupné symboly, můžeme tedy přı́mo
přikročit k odstraňovánı́ levě rekurzivnı́ch pravidel.
G = ({S, A, B}, {a, b, c}, P, S)
S → aAb | b
A → Aa | bB | ab
B → Ba | Bb | ca
Levá rekurze je v pravidlech A → Aa a dále B → Ba | Bb. Nejdřı́v vyřešı́me prvnı́
z těchto pravidel – pro neterminál A. Množinu pravidel A → Aa | bB | ab nahradı́me jinou
množinou, která generuje tentýž řetězec. Jak může vypadat derivace z neterminálu A?
A ⇒ Aa ⇒ Aaa ⇒ Aaaa ⇒∗ Aai ⇒ bBai (generujeme zprava doleva, a to nejdřı́v rekurzı́vnı́m pravidlem, rekurze je pak ukončena vlevo některým nerekurzı́vnı́m pravidlem).
Stejný řetězec lze generovat pravou rekurzı́, a to přidánı́m nového neterminálu a úpravou pravidel (původnı́ pravidla jsou A → Aa | bB | ab):
A → bBA0 | abA0 | bB | ab
A0 → aA0 | a
Derivace ze symbolu A pak vypadá následovně:
A ⇒ bBA0 ⇒ bBaA0 ⇒ bBaaA0 ⇒∗ bBai−1 A0 ⇒ bBai
Pravidla B → Ba | Bb | ca nahradı́me pravidly
B → caB 0 | ca
B 0 → aB 0 | bB 0 | a | b
Vytvořili jsme tedy ekvivalentnı́ gramatiku bez přı́mé levé rekurze:
G0 = ({S, A, A0 , B, B 0 }, {a, b, c}, P 0 , S)
S → aAb | b
A → bBA0 | abA0 | bB | ab
A0 → aA0 | a
B → caB 0 | ca
B 0 → aB 0 | bB 0 | a | b
L
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
71
Uvedený postup je použitelný pouze na vlastnı́ gramatiku (tj. gramatiku bez cyklu, nezkracujı́cı́, bez nadbytečných symbolů). Gramatika z předchozı́ho přı́kladu je vlastnı́, proto
nebylo třeba ji předem upravovat.
Přı́klad 5.11
Odstranı́me levou rekurzi v následujı́cı́ gramatice:
G = ({S, A, B}, {a, b, c}, P, S)
S → bAa | c | A
A → Ba | b | Abb
B → aBb | Bbc | ca | ε
Tato gramatika nenı́ vlastnı́. Je třeba nejdřı́v převést ji na nezkracujı́cı́, odstranit jednoduchá pravidla a teprve potom můžeme odstranit levou rekurzi.
1. Odstranı́me ε-pravidla (resp. jediné, B → ε):
G0 = ({S, A, B}, {a, b, c}, P 0 , S)
S → bAa | c | A
A → Ba | a | b | Abb
B → aBb | ab | Bbc | bc | ca
2. Odstranı́me jednoduché pravidlo S → A:
G00 = ({S, A, B}, {a, b, c}, P 00 , S)
S → bAa | c | Ba | a | b | Abb
A → Ba | a | b | Abb
B → aBb | ab | Bbc | bc | ca
3. Odstranı́me přı́mou levou rekurzi. Pravidla A → Ba | a | b | Abb nahradı́me pravidly
A → BaA0 | aA0 | bA0 | Ba | a | b
A0 → bbA0 | bb
Dále pravidla B → aBb | ab | Bbc | bc | ca nahradı́me pravidly
B → aBbB 0 | abB 0 | aB 0 | |bcB 0 | caB 0 | aBb | ab | bc | ca
B 0 → bcB 0 | bc
Vytvořili jsme tuto gramatiku:
G000
= ({S, A, A0 , B, B 0 }, {a, b, c}, P 000 , S)
S → bAa | c | Ba | a | b | Abb
A → BaA0 | aA0 | bA0 | Ba | a | b
A0 → bbA0 | bb
B → aBbB 0 | abB 0 | aB 0 | |bcB 0 | caB 0 | aBb | ab | bc | ca
B 0 → bcB 0 | bc
L
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
72
Přı́klad 5.12
Odstranı́me pravou rekurzi v této gramatice:
G = ({S, A, B}, {a, b, c}, P, S)
S → aAb | AB
A → abA | c | Sc
B → bbB | cB | a
Jde o vlastnı́ gramatiku, nemusı́me ji předem do tohoto tvaru upravovat. Postupujeme
stejně jako u odstraněnı́ levé rekurze, jen zaměnı́me levou a pravou stranu. Přidáme nové
neterminály a upravı́me pravidla.
Z neterminálu A může být napřı́klad tato derivace:
A ⇒ abA ⇒ ababA ⇒∗ (ab)i A ⇒ (ab)i c
Pravidla A → abA | c | Sc nahradı́me pravidly
A → A0 c | A0 Sc | c | Sc
A0 → A0 ab | ab
Derivace z neterminálu A se změnı́:
A ⇒ A0 c ⇒ A0 abc ⇒ A0 ababc ⇒∗ A0 (ab)i−1 c ⇒ (ab)i c
Vygenerovaný řetězec je tentýž, ale zatı́mco u pravé rekurze byl generován zleva doprava, u levé rekurze je generován opačně – zprava doleva.
Podobně upravı́me pravidla B → bbB | cB | a:
B → B0a | a
B 0 → B 0 bb | B 0 c | bb | c
Vycházı́ nám tato gramatika:
G0 = ({S, A, A0 , B, B 0 }, {a, b, c}, P 0 , S)
S → aAb | AB
A → A0 c | A0 Sc | c | Sc
A0 → A0 ab | ab
B → B0a | a
B 0 → B 0 bb | B 0 c | bb | c
Rekurze může být také nepřı́má, napřı́klad v pravidlech
A → Bba | a
B → Aab | b
Levou rekurzi, včetně nepřı́mé, odstranı́me tak, že pravidla převedeme do tvaru, kdy
pravá strana pravidla začı́ná neterminálem pouze za přesně určených okolnostı́. Postup:
1. Stanovı́me pořadı́ neterminálů. Můžeme si je napřı́klad označit indexy, přejmenovat
nebo jednoduše určit jejich pořadı́. Necht’ pořadı́ neterminálů je (A1 , A2 , . . . , An ).
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
73
Účelem algoritmu je upravit pravidla tak, aby mohla začı́nat pouze neterminály
s vyššı́m indexem než je index přepisovaného neterminálu. Tı́m zcela odstranı́me
levou rekurzi.
2. Pro neterminály Ai , Aj , 1 ≤ i, j ≤ n postupně transformujeme pravidla. Pro prvnı́
krok stanovı́me i = 1, j = 1.
• Pokud j < i a existuje pravidlo Ai → Aj α, kde α je jakýkoliv řetězec (tj. pravidlo
pro Ai začı́ná neterminálem Aj ), pak symbol Aj v pravidle nahradı́me postupně
všemi pravými stranami pravidel pro Aj , napřı́klad
Ai → Aj abB
Aj → bDAi a | CAj a
Prvnı́ z uvedenených pravidel nahradı́me pravidly Ai → bdAi aabB | CAj aabB.
Provedeme j = j + 1.
• Pokud j = i, pak odstranı́me přı́mou levou rekurzi podle postupu, který už
známe. Provedeme j = j + 1.
• Pokud j > i, provedeme i = i + 1, j = 1.
3. Bod 2 postupu provedeme pro všechna i, 1 ≤ i ≤ n.
Aby byl postup použitelný, musı́ být uplatněn pouze na vlastnı́ gramatiku. Postup pro
pravou rekurzi je obdobný, jen zaměnı́me levou za pravou stranu.
Přı́klad 5.13
Odstranı́me levou rekurzi včetně nepřı́mé v následujı́cı́ gramatice:
G = ({S, A, B}, {a, b, c}, P, S)
S → aA | AB | b
A → SBa | a
B → Bb | Aa | c
Přı́má levá rekurze je zde jen v jednom pravidle, ale nepřı́má rekurze se týká vı́ce
pravidel. Gramatika je vlastnı́, nenı́ třeba ji do tohoto tvaru upravovat. Stanovı́me pořadı́
neterminálů: (A1 , A2 , A3 ) = (S, A, B).
• i = 1, j = 1 :
nenı́ třeba upravovat, pravidla pro S neobsahujı́ přı́mou rekurzi.
• i = 2, j = 1 :
jedno z pravidel pro A začı́ná neterminálem s „nižšı́m indexem“, S; upravı́me:
A → aABa | ABBa | bBa | a
• i = 2, j = 2 :
řešı́me přı́mou rekurzi (protože i = j):
A → aABaA0 | bBaA0 | aA0 | aABa | bBa | a
A0 → BBaA0 | BBa
5.2
ÚPRAVY BEZKONTEXTOVÝCH GRAMATIK
74
• i = 3, j = 1 :
žádné z pravidel pro B nezačı́ná symbolem S
• i = 3, j = 2 :
změna se týká druhého pravidla pro symbol B (začı́ná symbolem A, jehož index je 2).
Při nahrazenı́ symbolu A v tomto pravidle použijeme již upravená pravidla pro A:
B → Bb | aABaA0 a | bBaA0 a | aA0 a | aABaa | bBaa | aa | c
• i = 3, j = 3 :
odstranı́me přı́mou rekurzi:
B → aABaA0 aB 0 | bBaA0 aB 0 | aA0 aB 0 | aABaaB 0 | bBaaB 0 | aaB 0 | cB 0 |
aABaA0 a | bBaA0 a | aA0 a | aABaa | bBaa | aa | c
B 0 → bB 0 | b
Celá gramatika bez levé rekurze:
G0 = ({S, A, A0 , B, B 0 }, {a, b, c}, P 0 , S)
S → aA | AB | b
A → aABaA0 | bBaA0 | aA0 | aABa | bBa | a
A0 → BBaA0 | BBa
B → aABaA0 aB 0 | bBaA0 aB 0 | aA0 aB 0 | aABaaB 0 | bBaaB 0 | aaB 0 | cB 0 |
aABaA0 a | bBaA0 a | aA0 a | aABaa | bBaa | aa | c
B 0 → bB 0 | b
Odstraněnı́m přı́mé rekurze rozšiřujeme množinu neterminálů, proto je nutné dynamicky
upravovat také nadefinovanou posloupnost neterminálů určujı́cı́ pořadı́. Neterminály s pravidly, které takto vytvořı́me, je třeba zahrnout do algoritmu.
Přı́klad 5.14
Odstranı́me levou rekurzi v následujı́cı́ gramatice:
G = ({S, A, B}, {a, b}, P, S)
S → aA | bB
A → BaA | ab
B → BaA | b
• i = 1, j = 1 : nenı́ třeba upravovat, pravidla pro S neobsahujı́ přı́mou rekurzi.
• i = 2, j = 1, 2 : nenı́ třeba upravovat, pravidla pro A nezačı́najı́ symboly S a A.
• i = 3, j = 1, 2 : nenı́ třeba upravovat, pravidla pro B nezačı́najı́ symboly S a A.
• i = 3, j = 3 : odstranı́me přı́mou rekurzi.
B → bB 0 | b
B 0 → AaB 0 | Aa
Měnı́me posloupnost: (A1 , A2 , A3 , A4 ) = (S, A, B, B 0 )
5.3
NORMÁLNÍ FORMY BEZKONTEXTOVÝCH GRAMATIK
75
• i = 4, j = 1 : nenı́ třeba upravovat, pravidla pro B 0 nezačı́najı́ symbolem S.
• i = 4, j = 2 :
B 0 → BaAaB 0 | abaB 0 | BaAa | aba
• i = 4, j = 3 :
B 0 → bB 0 aAaB 0 | baAaB 0 | abaB 0 | bB 0 aAa | baAa | aba
• i = 4, j = 4 : nenı́ třeba upravovat.
Výsledná gramatika:
G0 = ({S, A, B, B 0 }, {a, b}, P 0 , S)
S → aA | bB
A → BaA | ab
B → bB 0 | b
B 0 → AaB 0 | Aa
B 0 → bB 0 aAaB 0 | baAaB 0 | abaB 0 | bB 0 aAa | baAa | aba
Úkol
5.5
1. Odstraňte levou rekurzi v těchto gramatikách (zvažte, zda nenı́ třeba gramatiku
předem upravit):
G1 = ({S, A, B}, {a, b, c}, P, S)
G2 = ({S, A, B}, {a, b}, P, S)
S → aAB | b | SB | ε
A → bA | Aac | AB | a
B → BbA | c
S → AB | BA
A → ABbA | bA | ε
B → SA | a | BbA
G3 = ({S, A, B}, {a, b}, P, S)
G4 = ({E, T, F }, {i, +, ∗, (, )}, P, S)
S → AB | a
A → AaB | Sb | ba
B → BB | b | Ab | ε
E →E+T |T
T →T ∗F |F
F → (E ) | i
2. Odstraňte pravou rekurzi v těchto gramatikách (přı́p. gramatiku předem upravte):
G1 = ({S, A, B}, {0, 1}, P, S)
G2 = ({S, A, B}, {a, b}, P, S)
S → 11A | 01B | ε
A → 11A | B01 | 10
B → 01B | 00AB | 1A1 | 01
S → aAb | abB | ASA
A → bA | B | ε
B → bbB | abAB | abb
C
5.3
NORMÁLNÍ FORMY BEZKONTEXTOVÝCH GRAMATIK
5.3
76
Normálnı́ formy bezkontextových gramatik
Normálnı́ formy (čehokoliv) sloužı́ k usnadněnı́ porovnávánı́ a přı́padných dalšı́ch úprav,
normované gramatiky se také využı́vajı́ pro zjednodušenı́ některých důkazů. V přı́padě
bezkontextových gramatik lze využı́t Chomského normálnı́ formu (CNF) a Greibachové
normálnı́ formu (GNF).
5.3.1
Chomského normálnı́ forma
Gramatika G = (N, T, P, S) v Chomského normálnı́ formě (značı́me CNF) má všechna
pravidla v jednom z následujı́cı́ch tvarů:
• A → BC, tedy na pravé straně dva neterminály,
P
• A → a, tedy na pravé straně jeden terminál, a nebo
• S → ε – pouze v přı́padě, že S se nevyskytuje na pravé straně žádného pravidla (tj.
toto pravidlo lze využı́t pouze na začátku derivace).
Postupujeme takto:
1. Převedeme gramatiku do tvaru vlastnı́ gramatiky (tj. převod na nezkracujı́cı́ gramatiku,
odstranı́me jednoduchá pravidla, odstranı́me nadbytečné neterminály).
2. Pravidla, která majı́ na pravé straně jen jeden symbol (půjde vždy o terminál, protože
jednoduchá pravidla jsme již odstranili) necháme – odpovı́dajı́ požadavkům na normálnı́ formu; dále zpracováváme jen pravidla, jejichž pravá strana má délku alespoň 2.
3. Pro každé pravidlo A → α, kde |α| > 1, provedeme tyto úpravy:
• každý terminál a v řetězci α nahradı́me novým (nově vytvořeným) neterminálem Na (podle dolnı́ho indexu poznáme, který terminál byl nahrazen), takže
napřı́klad pravidlo A → BaAbca zaměnı́me za pravidlo A → BNa ANb Nc Na ,
• vytvořı́me nová pravidla Na → a pro každý terminál a.
4. Délku pravých stran všech pravidel omezı́me na nejvýše 2 takto: pro každé pravidlo
A → B1 B2 B3 . . . Bn , n > 2, vytvořı́me množinu pravidel
A → B1 X1
X1 → B2 X2
...
Xn−3 → Xn−2 Bn−2
Xn−2 → Bn−1 Bn
Napřı́klad pravidlo A → BCDEF nahradı́me množinou pravidel
A → BX1
X1 → CX2
X2 → DX3
X3 → EF
P
5.3
NORMÁLNÍ FORMY BEZKONTEXTOVÝCH GRAMATIK
77
Neterminály X1 , . . . , Xn−2 , které použı́váme při propojenı́ generovánı́ pravé strany původnı́ho pravidla, musı́ být nové, tedy různé pro různá pravidla, která takto upravujeme.
Přı́klad 5.15
Následujı́cı́ gramatiku převedeme do Chomského normálnı́ formy:
G = ({S, A, B}, {a, b, c}, P, S)
S → aBAc | c
A → Ab | ε
B → bB | AS | a
Tato gramatika nenı́ vlastnı́. Nejdřı́v odstranı́me ε-pravidlo A → ε.
S → aBAc | aBc | c
A → Ab | b
B → bB | AS | S | a
Jedno z pravidel je jednoduché (B → S), to je třeba odstranit:
S → aBAc | aBc | c
A → Ab | b
B → bB | AS | aBAc | aBc | c | a
Všechna pravidla, jejichž pravá strana je dlouhá alespoň 2 symboly, upravı́me – terminály nahradı́me přı́slušnými neterminály:
S → Na BANc | Na BNc | c
A → ANb | b
B → Nb B | AS | Na BANc | Na BNc | c | a
Na → a
Nb → b
Nc → c
Všechna pravidla s pravou stranou delšı́ než 2 zkrátı́me a zı́skáme tuto gramatiku:
GCN F = ({S, A, B, Na , Nb , Nc , X1 , X2 , X3 , X4 , X5 , X6 }, {a, b, c}, P 0 , S)
S → Na X1 | Na X3 | c
X1 → BX2
X2 → ANc
X3 → BNc
A → ANb | b
B → Nb B | AS | Na X4 | Na X6 | c | a
X4 → BX5
X5 → ANc
X6 → BNc
Jedna z derivacı́ v původnı́ gramatice G:
S ⇒ aBAc ⇒ aaAc ⇒ aaAbc ⇒ aabc
Derivace stejného slova v gramatice G00 (po předběžné úpravě):
S ⇒ aBAc ⇒ aaAc ⇒ aabc
Obdobně ve výsledné gramatice GCN F :
S ⇒ Na X1 ⇒ aX1 ⇒ aBX2 ⇒ aBANc ⇒ aBAc ⇒ aaAc ⇒ aabc
Na → a
Nb → b
Nc → c
5.3
NORMÁLNÍ FORMY BEZKONTEXTOVÝCH GRAMATIK
Úkol
78
5.6
Následujı́cı́ gramatiky převed’te do Chomského normálnı́ formy:
G1 = ({S, A, B}, {a, b}, P, S)
G2 = ({S, A, B}, {0, 1}, P, S)
S → AaB | ba | aA
A → aAB | aAb | ab
B → bBASb | b
S → 0B | 1A | ε
A → 10A1 | AB | ε
B → A1B01 | 1S1 | 0
G3 = ({E, F, G}, {a, b}, P, E)
G4 = ({S, A, B}, {0, 1}, P, S)
E → aaF | GF | b
F → aF aa | ε
G → aF GbG | ε
S → 01AB0 | 10BA1 | ε
A → 1AB1AB1 | 111
B → 0B | 0
G5 = ({S, A, B}, {a, b}, P, S)
G6 = ({S, A, B}, {0, 1}, P, S)
S → aAbB | ε
A → aA | a | Bba
B → b | aSb | A
5.3.2
C
S → 0A1 | 1B0 | ε
A → 00AB | 1
B → 1S | 0
Greibachové normálnı́ forma
Gramatika je v Greibachové normálnı́ formě (značı́me GNF), pokud všechna pravidla této
gramatiky jsou v jednom z těchto tvarů:
• A → aB1 B2 . . . Bn , n ≥ 0, tedy na pravé straně je vždy jeden terminál a následujı́
pouze neterminály (nemusı́ být žádný neterminál),
P
• S → ε (S je startovacı́ symbol gramatiky), a to pouze v přı́padě, že S se nevyskytuje na
pravé straně žádného pravidla (tj. toto pravidlo lze využı́t pouze na začátku derivace).
Podobně jako u převodu na Chomského normálnı́ tvar, i zde budeme gramatiku předem
upravovat. Možnost existence ε-pravidla pouze pro startovacı́ symbol znamená nutnost
převést gramatiku na nezkracujı́cı́. Dále odstranı́me jednoduchá pravidla a přı́padně také
nadbytečné symboly.
Kromě toho je zde požadavek na terminálnı́ symbol na začátku pravidla. Pokud pravidlo začı́ná neterminálem, logickým postupem by bylo dosazovat za tento neterminál
postupně všechna pravidla, na který lze neterminál přepsat, a to rekurzı́vně tak dlouho,
dokud nezı́skáme pravidlo začı́najı́cı́ terminálem. Pokud je však v gramatice levá rekurze,
dosazovali bychom do nekonečna, proto je třeba předem odstranit levou rekurzi. Celý
postup je následujı́cı́:
1. Převedeme gramatiku do tvaru vlastnı́ gramatiky (převod na nezkracujı́cı́, odstraněnı́
jednoduchých pravidel, odstraněnı́ nadbytečných symbolů).
P
5.3
NORMÁLNÍ FORMY BEZKONTEXTOVÝCH GRAMATIK
79
2. Odstranı́me levou rekurzi. Pokud jsme jejı́m odstraněnı́m vytvořili ε-pravidla nebo
jednoduchá pravidla, opakujeme bod 1.
3. Pravidla, jejichž pravá strana má délku 1, již vyhovujı́ požadavkům na normálnı́
formu (a také přı́padné ε-pravidlo pro startovacı́ symbol).
4. Pravidla, jejichž pravá strana má délku ≥ 2, dále zpracováváme:
• pokud pravidlo začı́ná neterminálem, dosadı́me za tento neterminál všechna
pravidla, která ho přepisujı́, tj. napřı́klad pravidlo A → BbAa při existenci pravidel B → α | β | γ nahradı́me pravidly A → αbAa | βbAa | γbAa,
• to provádı́me rekurzı́vně tak dlouho, dokud všechna pravidla nezačı́najı́ terminálnı́m symbolem,
• Všechny terminálnı́ symboly a na pravých stranách pravidel, kromě prvnı́ho terminálu v řetězci, nahradı́me přı́slušnými symboly Na (podobně jako při převodu
na Chomského normálnı́ tvar).
5. Vytvořı́me nová pravidla Na → a pro všechny terminály a.
Přı́klad 5.16
Následujı́cı́ gramatiku převedeme do Greibachové normálnı́ formy.
G = ({S, A, B, C}, {a, b, c}, P, S)
S → aBba | baA | ε
A → BaAB | bb | ε
B → CBab | abc
C → bCb | a
Sestrojı́me ekvivalentnı́ vlastnı́ gramatiku – odstranı́me ε-pravidla.
Podle množiny Nε = {S, A} je zřejmé, že existujı́ pouze dvě ε-pravidla. Jedno z nich je
pro startovacı́ symbol, který se však nevyskytuje na pravé straně žádného pravidla. Proto
nenı́ nutné přidávat nový neterminál a měnit startovacı́ symbol gramatiky.
G0 = ({S, A, B, C}, {a, b, c}, P 0 , S)
S → aBba | baA | ba | ε
A → BaAB | BaB | bb
B → CBab | abc
C → bCb | a
Levá rekurze se v této gramatice nevyskytuje. Při převodu do Greibachové normálnı́
formy nejdřı́v zajistı́me, aby nejlevějšı́m symbolem v pravých stranách pravidel byl vždy
terminál. To provedeme přepsánı́m toho neterminálu, který je na začátku upravovaného
řetězce.
Pravidlo A → BaAB nahradı́me těmito pravidly:
A → CBabaAB | abcaAB
Jedno z pravidel opět začı́ná neterminálem, tedy úpravu provedeme znovu:
A → bCbBabaAB | aBabaAB | abcaAB
5.3
NORMÁLNÍ FORMY BEZKONTEXTOVÝCH GRAMATIK
80
Pravidlo A → BaB nahradı́me pravidly
A → CBabaB | abcaB
Po druhé úpravě:
A → bCbBabaB | aBabaB | abcaB
Pravidlo B → CBab nahradı́me pravidly
B → bCbBab | aBab
V této fázi jsme zı́skali následujı́cı́ pravidla:
S → aBba | baA | ba | ε
A → bCbBabaAB | aBabaAB | abcaAB | bCbBabaB | aBabaB | abcaB | bb
B → bCbBab | aBab | abc
C → bCb | a
Zbývá splnit podmı́nku, podle které v pravých stranách pravidel jsou všechny symboly
kromě nejlevějšı́ho neterminálnı́.
GGN F = ({S, A, B, C, Na , Nb , Nc }, {a, b, c}, P 00 , S)
S → aBNb Na | bNa A | bNa | ε
A → bCNb BNa Nb Na AB | aBNa Nb Na AB | aNb Nc Na AB | bCNb BNa Nb Na B |
| aBNa Nb Na B | aNb Nc Na B | bNb
B → bCNb BNa Nb | aBNa Nb | aNb Nc
C → bCNb | a
Na → a
Nb → b
Nc → c
Přı́klad 5.17
Následujı́cı́ gramatiku převedeme do Greibachové normálnı́ formy.
G = ({S, A, B}, {a, b}, P, S)
S → aA | AB | b
A → SBa | a
B → Bb | a
V gramatice nejsou žádná ε-pravidla ani jednoduchá pravidla, ale je tu levá rekurze, kterou musı́me předem odstranit. Přı́má rekurze je v jednom z pravidel pro B, nepřı́má rekurze
je v pravidlech pro neterminály S a A. Budeme postupovat podle algoritmu popsaného na
straně 72. Stanovı́me pořadı́ neterminálů (A1 , A2 , A3 ) = (S, A, B).
• i = 1, j = 1 : nenı́ třeba upravovat, pravidla pro S neobsahujı́ přı́mou rekurzi.
• i = 2, j = 1 : dosadı́me pravé strany pravidel pro S do prvnı́ho z pravidel pro
neterminál A:
A → aABa | ABBa | bBa | a
5.3
NORMÁLNÍ FORMY BEZKONTEXTOVÝCH GRAMATIK
81
• i = 2, j = 2 : odstranı́me přı́mou rekurzi:
A → aABaA0 | bBaA0 | aA0 | aABa | bBa | a
A0 → BBaA0 | BBa
• i = 3, j = 1, j = 2 : beze změny.
• i = 3, j = 3 : odstranı́me přı́mou rekurzi:
B → aB 0 | a
B 0 → bB 0 | b
Upravená gramatika bez levé rekurze (také nepřı́mé) je následujı́cı́:
G0
= ({S, A, A0 , B, B 0 }, {a, b}, P 0 , S)
S → aA | AB | b
A → aABaA0 | bBaA0 | aA0 | aABa | bBa | a
A0 → BBaA0 | BBa
B → aB 0 | a
B 0 → bB 0 | b
Zajistı́me, aby pravé strany pravidel začı́naly vždy terminálnı́m symbolem.
S → aA | aABaA0 B | bBaA0 B | aA0 B | aABaB | bBaB | aB | b
A → aABaA0 | bBaA0 | aA0 | aABa | bBa | a
A0 → aB 0 BaA0 | aBaA0 | aB 0 Ba | aBa
B → aB 0 | a
B 0 → bB 0 | b
V dalšı́m kroku všechny terminály na pravých stranách pravidel, kromě nejlevějšı́ho,
zaměnı́me za přı́slušné neterminálnı́ symboly.
GGN F = ({S, A, A0 , B, B 0 , Na }, {a, b}, P 00 , S)
S → aA | aABNa A0 B | bBNa A0 B | aA0 B | aABNa B | bBNa B | aB | b
A → aABNa A0 | bBNa A0 | aA0 | aABNa | bBNa | a
A0 → aB 0 BNa A0 | aBNa A0 | aB 0 BNa | aBNa
B → aB 0 | a
B 0 → bB 0 | b
Na → a
Úkol
5.7
Převed’te následujı́cı́ gramatiky do Greibachové normálnı́ formy.
G1 = ({S, A, B}, {a, b}, P, S)
S → aAB | AB | ε
A → BbA | ab
B → Ba | b
G2 = ({S, A, B}, {a, b}, P, S)
S → BAaB | aBA | ε
A → aaA | SB | a
B → AbA | b
C
5.4
KRITÉRIA BEZKONTEXTOVOSTI
G3 = ({S, A, B, C}, {a, b, c}, P, S)
S → CAa | ε
A → aCb | c
B → cB | cS | b
C → caC | A | b
5.4
5.4.1
82
G4 = ({E, F }, {i, +, (, )}, P, S)
E →E+F |F
F → (E ) | i
Kritéria bezkontextovosti
Pumping lemma
S Pumping lemma jsme se seznámili už u regulárnı́ch jazyků. U bezkontextových jazyků
narůstá složitost pravidel gramatiky a proto je složitějšı́ i tato věta.
Když pomocı́ Pumping lemma dokazujeme, že jazyk L nenı́ bezkontextový, postupujeme takto:
1. vybereme vhodné slovo w ∈ L, a to tak, aby bylo „dostatečně dlouhé“ – mělo by
tedy být určeno výrazem, ve kterém je index („proměnná“) potenciálně jdoucı́ do
nekonečna,
2. vybereme vhodné rozdělenı́ w = x · y · z · u · v tak, aby
• |y · z · u| ≤ q, kde q je některé konečné čı́slo, to znamená, že v celé prostřednı́
části slova můžeme jako indexy použı́t pouze konečná čı́sla (žádné „pı́smenné
proměnné“),
• |y · u| > 0 (v těchto dvou částech dohromady musı́ být alespoň jeden symbol),
3. zvolı́me čı́slo k ≥ 0 (většinou stačı́ vybrat k = 0 nebo k = 2) a vytvořı́me slovo
wk = x · y k · z · uk · v
4. pokud wk ∈
/ L, vracı́me se k bodu 2 a vyzkoušı́me dalšı́ rozdělenı́, pokud wk ∈ L,
vracı́me se k bodu 1 a hledáme jiné vhodné slovo,
5. končı́me tehdy, když se v bodu 2 nedařı́ najı́t dalšı́ rozdělenı́.
Účelem je pro vybrané slovo otestovat všechna možná rozdělenı́ a pro každé dojı́t k závěru,
že wk ∈
/ L, pak dokážeme, že jazyk L nenı́ bezkontextový.
Přı́klad 5.18
Dokážeme, že jazyk L = an b2n an : n ≥ 0 nenı́ bezkontextový.
Vybereme si slovo w = ai b2i ai a předpokládáme, že i je dostatečně vysoké (může růst
do nekonečna). Dále si určı́me možná rozdělenı́ tohoto slova – w = x · y · z · u · v:
1) y · z · u obsahuje pouze symboly 0 a0 z prvnı́ části slova,
P
5.4
KRITÉRIA BEZKONTEXTOVOSTI
83
2) y · z · u v sobě zahrnuje hranici mezi symboly 0 a0 z prvnı́ části slova a symboly 0 b0
z druhé části slova,
3) y · z · u obsahuje pouze symboly 0 b0 z prvnı́ části slova,
4) y · z · u v sobě zahrnuje hranici mezi symboly 0 b0 z druhé části slova a symboly 0 a0
z třetı́ části slova,
5) y · z · u obsahuje pouze symboly 0 a0 z prvnı́ části slova.
Dalšı́ rozdělenı́ již nejsou možná, protože musı́ být splněny podmı́nky omezenı́ |y · z · u|
shora a nenulové délky řetězce y · u (proto napřı́klad do y · z · u nemohou patřit symboly ze
všech třı́ částı́ slova – tento řetězec by obsahoval celý podřetězec b2i , který ale nelze shora
omezit).
Prověřı́me všechny možnosti:
ad. 1) x · y · z · u · v = (am1 ) · (am2 ) · (am3 ) · (am4 ) · ai−(m1 +m2 +m3 +m4 ) b2i ai
kde m2 + m3 + m4 ≤ q, m2 + m4 > 0
x · y k · z · uk · v = am1 · akm2 · am3 · akm4 ai−(m1 +m2 +m3 +m4 ) b2i ai =
= a(k−1)(m2 +m4 )+i b2i ai
pro k = 0: w0 = ai−m2 −m4 b2i ai ∈
/ L (protože m2 + m4 > 0)
ad. 2) (x) · (y · z · u) · (v) = (am1 ) · (am2 bm3 ) · bm4 ai
sestrojı́me x · y k · z · uk · v; protože vždy platı́ |y · u| > 0, pro každé k > 1 se zvyšuje:
(a) počet 0 a0 indexovaných m2 , pak x · y k · z · uk · v = aj b2i ai , kde j 6= i, slovo wk ∈
/ L,
0
0
k
k
i
j
i
(b) počet b indexovaných m3 , pak x · y · z · u · v = a b a , kde j 6= 2i, slovo wk ∈
/ L,
j
p
k
m
i
0
0
0
0
k
k
m
4
1
(c) počet a i b indexovaných m2 a m3 , pak x · y · z · u · v = a (a b ) b a , kde
k > 1, j, p ≥ 1, slovo wk ∈
/ L.
ad. 3) x · y · z · u · v = ai bm1 · (bm2 ) · (bm3 ) · (bm4 ) · b2i−(m1 +m2 +m3 +m4 ) ai
kde m2 + m3 + m4 ≤ q, m2 + m4 > 0
x · y k · z · uk · v = ai bm1 bkm2 bm3 bkm4 b2i−(m1 +m2 +m3 +m4 ) ai =
= ai b(k−1)(m2 +m4 )+2i ai
pro k = 0: w0 = ai b2i−(m2 +m4 ) ai ∈
/L
ad. 4) dokazujeme podobně jako bod 2)
ad. 5) dokazujeme podobně jako bod 1)
Pro všechna možná rozdělenı́ nám vyšlo, že pro alespoň jednu hodnotu k slovo wk nepatřı́
do jazyka L, proto jazyk L nenı́ bezkontextový.
Přı́klad 5.19
n 2
o
Dokážeme, že jazyk L = an : n ≥ 0 nenı́ bezkontextový.
2
Opět zvolı́me nějaké slovo w = ap ∈ L s „dostatečně velkým“ indexem p. Toto slovo
rozdělı́me následovně:
2
ap = ax1 ax2 ax3 ax4 ax5
5.4
KRITÉRIA BEZKONTEXTOVOSTI
84
Pokud z těchto dvou reprezentacı́ téhož slova (na dvou stranách rovnice) vezmeme pouze
délky, zı́skáme již „čı́selnou“ rovnici
p2 = x1 + x2 + x3 + x4 + x5 .
Podle podmı́nek Pumping lemma musı́ zároveň platit nerovnice
• x2 + x4 > 0
podle podmı́nky |y · u| > 0
• x2 + x3 + x4 ≤ q podle podmı́nky |y · z · u| ≤ q
Po „pumpovánı́“ s indexem k, což musı́ být nezáporné celé čı́slo, zı́skáme jinou rovnici
(hodnotu m použijeme pouze pro vyjádřenı́ faktu, že slovo patřı́cı́ do jazyka L má délku
rovnu druhé mocnině některého přirozeného čı́sla):
m2 = x1 + k · x2 + x3 + k · x4 + x5 = k · (x2 + x4 ) + (x1 + x3 + x5 )
Zı́skali jsme rovnici, v jejı́ž obou částech oddělených rovnı́tkem jsou funkce. Zatı́mco levá
část rovnice roste s mocninnou řadou, pravá lineárně (je to lineárnı́ funkce) a tedy mnohem
pomaleji. Uvědomme si, že na obou stranách rovnice musı́ být výsledkem přirozené čı́slo
(oborem hodnot obou funkcı́ jsou přirozená čı́sla), a dále že x1 , . . . , x5 jsou z našeho pohledu
vlastně konstantnı́ čı́sla (navı́c přirozená), zatı́mco m a k jsou proměnné.
At’stanovı́me čı́sla x2 a x4 jakkoliv, vždy se najde čı́slo k, pro které součet čı́sel x2 + x4
nenı́ roven druhé mocnině žádného čı́sla. Proto jazyk L nenı́ bezkontextový.
Přı́klad 5.20
n
Pomocı́ Pumping lemma dokážeme, že jazyk L = a2 : n ≥ 0 nenı́ bezkontextový. Důkaz
bude podobný předchozı́mu.
r
Zvolı́me nějaké slovo w = a2 ∈ L s „dostatečně velkým“ indexem r. Toto slovo rozděr
lı́me na a2 = ax1 ax2 ax3 ax4 ax5 a musı́ platit x2 + x4 > 0, x2 + x3 + x4 ≤ q
Před pumpovánı́m:
2r = x1 + x2 + x3 + x4 + x5
Po pumpovánı́:
2m = x1 + k · x2 + x3 + k · x4 + x5 = k · (x2 + x4 ) + (x1 + x3 + x5 )
Zı́skali jsme rovnici, v jejichž obou částech oddělených rovnı́tkem jsou funkce. Zatı́mco
levá část rovnice roste exponenciálně, pravá lineárně (je to lineárnı́ funkce) a tedy mnohem
pomaleji. Ze stejných důvodů jako v předchozı́m přı́kladu lze vyvodit, že jazyk L nenı́
bezkontextový.
Přı́klad 5.21
Dokážeme, že jazyk L = {ww : w ∈ {a, b}∗ } nenı́ bezkontextový. Tento jazyk se skládá ze
slov, jejichž obě poloviny jsou stejné.
5.4
KRITÉRIA BEZKONTEXTOVOSTI
85
Pro důkaz si vybereme slovo w = ap bp ap bp , p > 4, q = 4 a dokážeme, že pro toto
slovo neexistuje žádné rozdělenı́, které by umožňovalo „pumpovánı́“ dle Pumping lemma.
Podmı́nky s čı́slem 4 se mohou zdát podivné, ale i tak je zřejmé, že slovo splňuje podmı́nky
z Pumping lemma – index p může být dostatečně velký a prostřednı́ část je shora omezena.
x
y
z
u
v
xy i zui v
ap bp−1
ap bp−1
ap bp−1
...
b
ε
ε
ε
b
ε
a
a
ba
ap−1 bp
ap−1 bp
ap−1 bp
ap bp−1+i ap−1+i bp
ap bp ap−1+i bp
ap bp−1 (ba)i ap−1 bp
pro i = 0
ap bp−1 ap−1 bp
ap bp ap−1 bp
ap bp−1 ap−1 bp
∈
/L
∈
/L
∈
/L
Jak vidı́me, většinou nám úplně stačı́ pro každé rozdělenı́ otestovat slovo pro i = 0.
Můžeme pokračovat dalšı́mi řádky tabulky, ale vždy dojdeme ke stejnému závěru.
Je to proto, že když je část yzu omezena konstantou, může zabrat nejvýše dvě různé
části ze čtyř částı́ vybraného slova w (a přitom do yu musı́ padnout alespoň jeden symbol
slova), tedy po iteraci pro žádné i kromě i = 1 nedostaneme slovo, jehož obě poloviny jsou
stejné. Proto L nenı́ bezkontextový.
Úkol 5.8
1. Dokažte, že jazyk L1 = {an bm an : 0 ≤ m ≤ n} nenı́ bezkontextový. Použijte podobný
postup jako je v přı́kladu 5.18, a také nerovnosti v zadánı́ jazyka.
C
2. Ukažte, že pro jazyk L2 = an b2n an bm : m, n ≥ 0 podmı́nka z Pumping lemma
platı́, třebaže nejde o bezkontextový jazyk. Proč?
5.4.2
Parikhův vektor
Parikhův vektor slova obsahuje informaci o počtu jednotlivých symbolů v daném slově,
Parikhův vektor jazyka obsahuje informaci o počtu jednotlivých symbolů ve slovech daného
jazyka (je to množina Parikhových vektorů všech slov jazyka). Jde tedy o redukci informace
na pouhý počet, bez ohledu na konkrétnı́ umı́stěnı́ symbolů ve slovech.
Přı́klad 5.22
Je dán jazyk L = ai cb2i+2 a5 | i ≥ 0 ∪ ai cb3i+2 a5 | i ≥ 0 . Vytvořı́me Parikhův vektor
slova a3 cb8 a5 .
Pracujeme nad abecedou Σ = {a, b, c}. Stanovı́me pořadı́ symbolů v této abecedě, můžeme použı́t pořadı́, ve kterém jsou zde prvky množiny vyjmenovány. Parikhův vektor
bude třı́prvkový, jeho prvky odpovı́dajı́ počtu symbolů ve slově podle stanoveného pořadı́.
Spočı́táme symboly ve slově a vytvořı́me vektor: ψ(a3 cb8 a5 ) = (3 + 5, 8, 1) = (8, 8, 1)
5.4
KRITÉRIA BEZKONTEXTOVOSTI
86
Přı́klad 5.23
Vytvořı́me Parikhův vektor jazyka z předchozı́ho přı́kladu. Definice jazyka se skládá ze
dvou částı́. Z prvnı́ části zı́skáme tento vektor:
ψ1 (L) = {(i + 5, 2i + 2, 1) | i ≥ 0} = {i(1, 2, 0) + (5, 2, 1) | i ≥ 0} (rozdělı́me na část závislou na i a část konstantnı́). Podle druhé části zjistı́me tento vektor:
ψ2 (L) = {(i + 5, 3i + 2, 1) | i ≥ 0} = {i(1, 3, 0) + (5, 2, 1) | i ≥ 0}
Nynı́ můžeme sestrojit Parikhův vektor jazyka L:
ψ(L) = ψ1 (L) ∪ ψ2 (L) = {i(1, 2, 0) + (5, 2, 1) | i ≥ 0} ∪ {i(1, 3, 0) + (5, 2, 1) | i ≥ 0}
Vidı́me, že se jedná o množinu Parikhových vektorů, do této množiny patřı́ také vektor
(8, 8, 1) slova a3 cb8 a5 z předchozı́ho přı́kladu.
Semilineárnı́ množina je sjednocenı́ konečně mnoha lineárnı́ch množin (třeba lineárnı́ch
množin Parikhových vektorů). Parikhův vektor každého bezkontextového jazyka je vždy
semilineárnı́ množina.
V přı́kladu 5.23 jsme vytvořili Parikhův vektor bezkontextového jazyka. Jde o sjednocenı́
lineárnı́ch množin (konstantnı́ vektory jsou násobeny proměnnou i bez mocniny, tedy
lineárnı́ funkce).
Přı́klad 5.24
Vytvořı́me Parikhův vektor bezkontextového jazyka L = ai+3 bj a2i b | i, j ≥ 1 .
ψ(L) = {i(3, 0) + j(0, 1) + (3, 1) | i, j ≥ 1}, opět jde o semilineárnı́ množinu.
Jde o implikaci (jestliže je jazyk bezkontextový, pak jeho Parikhův vektor je semilineárnı́
množina), proto Parikhův vektor lze použı́t jako kritérium bezkontextovosti pouze důkazem, že Parikhův vektor daného jazyka nenı́ semilineárnı́ množina.
Přı́klad 5.25
n
Dokážeme, že jazyk L = an b2 +5n+2 a3 | n ≥ 0 nenı́ bezkontextový. Sestrojı́me jeho Parikhův vektor:
ψ(L) = {2n (0, 1) + n(1, 5) + (3, 2) | n ≥ 0}
Tato množina nenı́ semilineárnı́ (resp. lineárnı́, nic dalšı́ho nesjednocujeme), protože
jeden z vektorů násobı́me exponenciálnı́ hodnotou 2n . Proto jazyk L nenı́ bezkontextový.
Ke každému bezkontextovému jazyku lze sestrojit regulárnı́ jazyk se stejným Parikhovým
vektorem. Postup si ukážeme na přı́kladu.
5.4
KRITÉRIA BEZKONTEXTOVOSTI
87
Přı́klad 5.26
Podle jazyka L = a2n cbn ca3m b | n ≥ 1, m ≥ 0 sestrojı́me regulárnı́ jazyk R se stejným
Parikhovým vektorem.
Sestrojı́me Parikhův vektor jazyka L:
ψ(L) = {n(2, 1, 0) + m(3, 0, 0) + (0, 1, 2) | n ≥ 1, m ≥ 0}
Regulárnı́ výraz popisujı́cı́ jazyk R pak sestavı́me podle Parikhova vektoru:
R = (aab)∗ aab (aaa)∗ ccb
Všimněte si rozdı́lu mezi prvnı́ a druhou částı́ regulárnı́ho výrazu – protože n ≥ 1, musı́
být obsah iterované závorky uveden ještě jednou (počet nejméně 1).
Existuje vı́ce řešenı́. Napřı́klad regulárnı́ jazyk (aaa)∗ aab(aab)∗ ccb má také stejný Parikhův vektor.
Úkol
5.9
C
1. Sestrojte Parikhův vektor těchto slov nad abecedou Σ = {a, b, c}:
• aabacbb
• bcabcabca
• caacbbbc
• aaab
• baaccbbb
• ε
2. Sestrojte Parikhův vektor těchto jazyků:
• L1 = a2i bi | i ≥ 1
• L2 = a2i bi+3 | i ≥ 1
• L3 = a2i bi+j+1 cj | i, j ≥ 0
• L4 = nbn a2n bn | n ≥ 0 o
n
• L5 = bn a2 bk | n, k ≥ 0
n
• L6 = bn a2 b | 1 ≤ n ≤ 4
3. Jazyky L4 a L5 z předchozı́ úlohy zjevně nejsou bezkontextové. U kterého z nich je to
možné dokázat pomocı́ Parikhova vektoru a u kterého ne? Proč?
n
4. Dokažte pomocı́ Parikhova vektoru, že jazyk L = an bn
textový.
2 +1
o
a2 | n ≥ 1 nenı́ bezkon-
5. Pro všechny jazyky z úlohy 2, které jsou bezkontextové, sestrojte regulárnı́ jazyky se
stejným Parikhovým vektorem.
Kapitola
6
Jazyky typu 0
Jazyky typu 0 v Chomského hierarchii nám popisujı́ vše, co je vypočitatelné, algoritmizovatelné. Problém je vypočitatelný (algoritmizovatelný), právě když existuje jazyk typu 0,
který jej popisuje. Protože jazyky typu 0 jsou rozpoznávány Turingovými stroji, můžeme
řı́ct, že problém je vypočitatelný právě tehdy a jen tehdy, pokud lze sestrojit Turingův stroj,
který jej počı́tá.
6.1
6.1.1
Turingův stroj
Co je to Turingův stroj – pojmy a značenı́
Z přednášek vı́me, že Turingův stroj je abstraktnı́ výpočetnı́ model. Je určen takto:
M = (Q, Σ, Γ, δ, q0 , F, {−1, 0, 1}), kde
• Q je neprázdná konečná množina stavů,
• Σ je neprázdná konečná vstupnı́ abeceda,
• Γ je neprázdná konečná pásková (pracovnı́) abeceda a platı́ Σ ⊂ Γ,
• δ je přechodová funkce, která musı́ být vypočitatelná,
• F je neprázdná množina koncových stavů, platı́ F ⊆ Q,
• {−1, 0, 1} je určenı́ možných pohybů čtecı́ a zápisové hlavy na pásce (vlevo, stát, vpravo),
také může být napřı́klad {L, S, R}.
Vstupnı́ abeceda obsahuje ty symboly, ze kterých se může skládat vstupnı́ slovo, jazyk
rozpoznávaný Turingovým strojem je právě nad touto abecedou. Je zřejmé, že pásková
abeceda obsahuje i takové symboly, které nejsou ve vstupnı́ abecedě. Je to předevšı́m
speciálnı́ páskový symbol označujı́cı́ buňku, ve které nenı́ nic zapsáno, obvykle se značı́ B
(ze slova Blank – „prázdný“) nebo t. Dále tam mohou být symboly určujı́cı́ začátek a konec
obsazené části pásky (pokud jsou použı́vány), obvykle symboly $ nebo #.
88
P
6.1
TURINGŮV STROJ
89
Přechodová funkce má formu δ(p, a) = (q, b, M ), kde
• p, q ∈ Q je výchozı́ a cı́lový stav přechodu,
• a, b ∈ Γ jsou symboly páskové abecedy, předpis určuje, že přečtený symbol a má být
přepsán symbolem b,
• M ∈ {−1, 0, 1} určuje pohyb hlavy – určujeme, zda se má pokračovat vlevo, zůstat
na mı́stě nebo se posunout o pole doprava.
Přı́klad 6.1
Napřı́klad konfigurace (abbca, q, daab) znamená, že se stroj nacházı́ ve stavu q, na pásce je
slovo abbcadaab a čtecı́ a zápisová hlava ukazuje na šestý symbol slova – d.
Konfigurace je (α, q, β), kde α · β je slovo na pásce, α, β ∈ Γ∗ , výpočet je ve stavu q ∈ Q
a čtecı́/zápisová hlava ukazuje na prvnı́ symbol řetězce β. Také lze zapsat jako αqβ.
Počátečnı́ konfigurace je (ε, q0 , w0 ), kde q0 je počátečnı́ stav a w0 ∈ Σ∗ je slovo na vstupu.
Koncová konfigurace je (w1 , qf , w2 ), kde qf ∈ F, w1 , w2 ∈ Γ∗ . Slovo w1 · w2 lze brát jako
výstupnı́ řetězec, pokud je nějaký výstup požadován. Turingův stroj totiž nejen určuje,
zda dané slovo patřı́ do jazyka jı́m rozpoznávaného, ale může provádět také nejrůznějšı́
výpočty včetně složitých matematických operacı́ – vždyt’ pro cokoliv vypočitatelného lze
vytvořit Turingův stroj.
Přechod mezi konfiguracemi (přesněji – jde o relaci, vzpomeňte si, co to znamená v řeči
matematiky) je definován pomocı́ přechodové funkce, podobně jako u jiných typů automatů, jen je trochu komplikovanějšı́, protože existuje vı́ce možnostı́ posunu čtecı́/zápisové
hlavy. Relace přechodu mezi konfiguracemi je určena takto:
(α, qi , aβ) ` (αb, qj , β) ⇔ δ(qi , a) = (qj , b, 1)
(6.1)
(αc, qi , aβ) ` (α, qj , cbβ) ⇔ δ(qi , a) = (qj , b, −1)
(6.3)
(α, qi , aβ) ` (α, qj , bβ) ⇔ δ(qi , a) = (qj , b, 0)
(6.2)
V prvnı́m přı́padě se čtecı́ a zápisová hlava posunuje doprava, v druhém zůstává na mı́stě
(tj. v dalšı́m kroku bude čı́st totéž polı́čko jako v tomto) a v třetı́m se posunuje doleva.
6.1.2
Navrhujeme Turingův stroj pro daný jazyk
Při návrhu Turingova stroje postupujeme následovně:
• zjistı́me si, které části slova majı́ být „synchronizovány“ – pokud je jejich délka nebo
typ symbolu v nějakém vztahu, a také jakým způsobem,
• určı́me stavy a odpovı́dajı́cı́ reakce, promyslı́me si „strategii“ zpracovánı́ slova včetně
přechodu do koncových stavů,
• sestavı́me δ-funkci,
P
6.1
TURINGŮV STROJ
90
• otestujeme pro několik typických slov rozpoznávaného jazyka, předevšı́m pro nejkratšı́ slova.
Přı́klad 6.2
Sestrojı́me Turingův stroj rozpoznávajı́cı́ jazyk L = {an bn cn : n ≥ 0}
M = ({q0 , qP , qA , qB , qC , qf , qaccept }, {a, b, c}, {a, ā, b, b̄, c, c̄, t, $}, δ, {qaccept }, {−1, 0, 1})
Budeme postupovat takto:
1. označı́me prvnı́ symbol a na pásce (tj. přepı́šeme symbolem ā),
2. najdeme prvnı́ b, označı́me ho,
3. pak najdeme prvnı́ c, taktéž označı́me,
4. přejdeme na začátek (postupujeme doleva, dokud nenajdeme nejbližšı́ označené ā),
5. posuneme se o polı́čko dále na prvnı́ neoznačené a,
6. návrat k bodu 1,
7. po označenı́ všech symbolů a a k nim přı́slušejı́cı́ch b a c ještě zkontrolujeme, zda
neexistujı́ některé neoznačené symboly b a c a ukončı́me výpočet.
Cyklus naznačený v bodech 1 až 6 bude probı́hat postupně přes všechny symboly a ze
vstupu, tedy nkrát.
Jednotlivé stavy znamenajı́:
• qA – označili jsme a, přeskakujeme symboly a, b̄, hledáme prvnı́ neoznačené b,
• qB – označili jsme b, přeskakujeme symboly b, c̄, hledáme prvnı́ neoznačené c,
• qC – označili jsme c, vracı́me se na začátek k poslednı́mu označenému ā, při pohybu
doleva přeskakujeme všechny symboly c̄, b, b̄, a.
Definujeme δ funkci:
δ(q0 , $) = (qaccept , 0) (přijali jsme prázdné slovo)
δ(q0 , a) = (qA , ā, 1)
δ(qB , b) = (qB , b, 1)
δ(qP , a) = (qA , ā, 1)
δ(qB , c̄) = (qB , c̄, 1)
δ(qA , a) = (qA , a, 1)
δ(qB , c) = (qC , c̄, −1)
δ(qA , b̄) = (qA , b̄, 1)
δ(qC , X) = (qC , X, −1),
δ(qA , b) = (qB , b̄, 1)
X ∈ {a, b, b̄, c̄}
δ(qC , ā) = (qP , ā, 1)
δ(q0 , b̄) = (qf , b̄, 1)
δ(qf , b̄) = (qf , b̄, 1)
δ(qf , c̄) = (qf , c̄, 1)
δ(qf , $) = (qaccept , $, 0)
Ukázka zpracovánı́ slova abc:
(ε, q0 , abc) ` (ā, qA , bc) ` (āb̄, qB , c) ` (ā, qC , b̄c̄) ` (ε, qC , āb̄c̄) ` (ā, q0 , b̄c̄) `
` (āb̄, qf , c̄) ` (āb̄c̄, qf , ε) ` (āb̄c̄, qaccept , ε)
Jestliže zaznamenáme i hraničnı́ symboly, zpracovánı́ bude vypadat takto:
($, q0 , abc$) ` ($ā, qA , bc$) ` ($āb̄, qB , c$) ` ($ā, qC , b̄c̄$) ` ($, qC , āb̄c̄$) `
` ($ā, q0 , b̄c̄$) ` ($āb̄, qf , c̄$) ` ($āb̄c̄, qf , $) ` ($āb̄c̄, qaccept , $)
6.1
TURINGŮV STROJ
91
Ukázka zpracovánı́ slova aabbcc:
(ε, q0 , aabbcc) `
` (āab̄, qC , bc̄c)
` (āā, qA , b̄bc̄c)
` (āāb̄, qC , b̄c̄c̄)
` (āāb̄b̄, qf , c̄c̄)
(ā, qA , abbcc) ` (āa, qA , bbcc) `
` (āa, qC , b̄bc̄c) ` (ā, qC , ab̄bc̄c)
` (āāb̄, qA , bc̄c) ` (āāb̄b̄, qB , c̄c)
` (āā, qC , b̄b̄c̄c̄) ` (ā, qC , āb̄b̄c̄c̄)
` (āāb̄b̄c̄, qf , c̄) ` (āāb̄b̄c̄c̄, qf , ε)
(āab̄, qB , bcc) ` (āab̄b, qB , cc) `
` (ε, qC , āab̄bc̄c) ` (ā, q0 , ab̄bc̄c) `
` (āāb̄b̄c̄, qB , c) ` (āāb̄b̄, qC , c̄c̄) `
` (āā, q0 , b̄b̄c̄c̄) ` (āāb̄, qf , b̄c̄c̄) `
` (āāb̄b̄c̄c̄, qaccept , ε)
Ukázka zpracovánı́ slova ac:
(ε, q0 , ac) ` (ā, qA , c) chyba ⇒ slovo ac nenı́ přijato.
Ukázka zpracovánı́ slova ε:
(ε, q0 , ε) ` (ε, qaccept , ε)
Přı́klad 6.3
Vytvořı́me Turingův stroj rozpoznávajı́cı́ jazyk L = {wcw : w ∈ {a, b}∗ }
Opět si nejdřı́v promyslı́me, jak by měl stroj postupovat. Předpokládejme, že na vstupu
je slovo abbcabb. Nejdřı́v označı́me symbol v prvnı́ polovině slova, pak se přesuneme do
druhé části slova a najdeme párový symbol. Potom je třeba se přesunout zpět do prvnı́ části
slova, označit dalšı́ symbol, atd. Může to vypadat napřı́klad takto:
začátek zpracovánı́:
abb c abb
označı́me prvnı́ symbol:
xbb c abb
označı́me k němu párový symbol:
xbb c xbb
podobně po druhém kroku:
xxb c xxb
po třetı́m kroku:
xxx c xxx
V předchozı́m přı́kladu jsme počı́tali s tı́m, že slovo na vstupu je ohraničeno symboly $.
Nynı́ si ukážeme postup, ve kterém slovo nenı́ těmito symboly ohraničeno, ale za poslednı́m
symbolem slova jsou symboly t. Když se nad tı́m zamyslı́me, obě řešenı́ jsou ekvivalentnı́,
protože t můžeme také chápat jako hraničnı́ symboly a stejně s nimi zacházet.
Použijeme tyto stavy:
• q0 – označı́me symbol v prvnı́ části slova, na který ukazuje čtecı́/zápisová hlava,
přejdeme do stavu qA nebo qB podle toho, zda jsme označili symbol a nebo b, posun
vpravo,
• qA – byl označen symbol a, posunujeme se v cyklu doprava a hledáme polovinu slova
(symbol c, tedy přeskakujeme všechny symboly a a b, které jsou před c),
• qB – totéž pro b,
• qAC – pokračovatel stavu qA , přecházı́me do něj, pokud ve stavu qA najdeme symbol
c, hledáme párový symbol (symbol a v druhé části slova, tedy přeskakujeme vše, co
bylo označeno – symboly x),
6.1
TURINGŮV STROJ
92
• qBC – podobně ze stavu qB ,
• qZC – v druhé části slova jsme ve stavech qAC nebo qBC našli párový symbol, označili, ted’ se v cyklu posunujeme zpět doleva a hledáme polovinu slova (symbol c,
přeskakujeme vše označené – symboly x),
• qZ – ve stavu qZC jsme našli polovinu slova, nynı́ budeme pokračovat doleva a hledat
poslednı́ označený symbol, přeskakujeme symboly a a b, až najdeme nejpravějšı́ x,
změnı́me stav na q0 , posuneme se o krok doprava (tj. čtecı́/zápisová hlava bude ukazovat na prvnı́ neoznačený symbol nebo v přı́padě všech označených na c) a v cyklu
se vracı́me na začátek tohoto postupu,
• qf – do tohoto stavu přecházı́me, pokud jsme ve stavu q0 mı́sto neoznačeného symbolu
a nebo b našli přı́mo symbol c, tj. prvnı́ část slova je celá označená; nynı́ musı́me v cyklu
směrem doprava projı́t zbytek slova, zda tam nezůstaly neoznačené symboly,
• qaccept – do tohoto stavu přejdeme, pokud ve stavu qf najdeme konec slova (symbol
t), což znamená, že je označena i celá druhá část.
Turingův stroj bude definován následovně:
M = ( {q0 , qA , qAC , qB , qBC , qZ , qZC , qf , qaccept }, {a, b, c}, {a, b, c, x, t}, δ,
{qaccept }, {−1, 0, 1})
Nalezeno a:
δ(q0 , a) = (qA , x, 1)
δ(qA , Y ) = (qA , Y, 1), Y ∈ {a, b}
δ(qA , c) = (qAC , c, 1)
δ(qAC , x) = (qAC , x, 1)
δ(qAC , a) = (qZC , x, −1)
Nalezeno b:
δ(q0 , b) = (qB , x, 1)
δ(qB , Y ) = (qB , Y, 1), Y ∈ {a, b}
δ(qB , c) = (qBC , c, 1)
δ(qBC , x) = (qBC , x, 1)
δ(qBC , b) = (qZC , x, −1)
Návrat doleva:
δ(qZC , x) = (qZC , x, −1)
δ(qZC , c) = (qZ , c, −1)
δ(qZ , Y ) = (qZ , Y, −1), Y ∈ {a, b}
δ(qZ , x) = (q0 , x, 1)
Ukončenı́ s kontrolou:
δ(q0 , c) = (qf , c, 1)
δ(qf , x) = (qf , x, 1)
δ(qf , t) = (qaccept , t, 0)
Ukázka zpracovánı́ slova aca:
(ε, q0 , aca) ` (x, qA , ca) ` (xc, qAC , a) ` (x, qZC , cx) ` (ε, qZ , xcx) ` (x, q0 , cx) `
` (xc, qf , x) ` (xcx, qf , t) ` (xcx, qaccept , t)
Ukázka zpracovánı́ slova c (to je nejkratšı́ slovo jazyka):
(ε, q0 , c) ` (c, qf , t) ` (c, qaccept , t)
6.1
TURINGŮV STROJ
93
Přı́klad 6.4
Sestrojı́me Turingův stroj, který pro zadaný vstup vytvořı́ jeho reverzi (tj. pro slovo w na
vstupu bude na výstupu wR ). Na vstupu mohou být jakákoliv slova nad abecedou {a, b}.
Předpokládejme, že na vstupu je slovo aabab. Nejdřı́v na konec slova přidáme symbol
#, kterým označı́me rozhranı́ mezi původnı́m a novým slovem, a pak začneme kopı́rovat
původnı́ slovo na pásku za #. Původnı́ načı́táme zprava (od konce, přitom přepisujeme
symboly, abychom poznali, co už je zkopı́rováno), nové slovo naopak tvořı́me zleva, aby
bylo revertováno (převráceno). Může to vypadat napřı́klad takto:
začátek zpracovánı́:
označı́me hranici:
označı́me prvnı́ symbol:
zapı́šeme k němu párový symbol:
podobně po druhém kroku:
po třetı́m kroku:
po čtvrtém kroku:
po pátém kroku:
po ukončenı́:
Stavy:
aabab
aabab #
aabax #
aabax # b
aabxx # ba
aaxxx # bab
axxxx # baba
xxxxx # babaa
babaa
• q0 – projdeme celé slovo, na konec přidáme #, pak „couvnutı́“ před # a přechod do
stavu qZ ,
• qZ – v cyklu postupujeme doleva a přeskakujeme označené symboly, zastavı́me se na
nejbližšı́m neoznačeném symbolu, pak přechod do qA nebo qB ,
• qA – právě jsme označili a, v cyklu postupujeme doprava a přeskakujeme označené
symboly, zastavı́me se až na symbolu #, přechod do qAH ,
• qB – podobně jako qA , ale pro symbol b,
• qAH – v cyklu postupujeme doprava a přeskakujeme všechny zapsané symboly
z pravé části slova, hledáme konec, pak zapı́šeme a a přecházı́me do stavu qZH ,
• qBH – podobně jako qAH , ale pro symbol b,
• qZH – v cyklu postupujeme doleva až k symbolu #, přeskakujeme všechny zapsané
symboly a a b, pak přejdeme do stavu qZ ,
• qf – úklid po kopı́rovánı́, smažeme původnı́ slovo a dodaný hraničnı́ symbol #,
• qaccept – koncový stav.
M = ( {q0 , qA , qAH , qB , qBH , qZ , qZH , qf , qaccept }, {a, b, c}, {a, b, x, t, #}, δ,
{qaccept }, {−1, 0, 1})
6.1
TURINGŮV STROJ
94
Začátek – přı́prava:
δ(q0 , Y ) = (q0 , Y, 1), Y ∈ {a, b}
δ(q0 , t) = (qZ , #, −1)
Ukončenı́ s úklidem:
δ(qZ , t) = (qf , t, 1)
δ(qf , x) = (qf , t, 1)
δ(qf , #) = (qaccept , t, 0)
Posun zpět – doleva:
δ(qZ , x) = (qZ , x, −1)
δ(qZ , a) = (qA , x, 1)
δ(qZ , b) = (qB , x, 1)
δ(qZH , Y ) = (qZH , Y, −1)
δ(qZH , #) = (qZ , #, −1)
Našli jsme a:
δ(qA , x) = (qA , x, 1)
δ(qA , #) = (qAH , #, 1)
δ(qAH , Y ) = (qAH , Y, 1)
δ(qAH , t) = (qZ H, a, −1)
Našli jsme b:
δ(qB , x) = (qB , x, 1)
δ(qB , #) = (qBH , #, 1)
δ(qBH , Y ) = (qBH , Y, 1)
δ(qBH , t) = (qZ H, b, −1)
Všimněme si rozdı́lu mezi činnostı́ Turingova stroje a dřı́ve definovaných automatů:
• Turingův stroj nejen čte vstupnı́ pásku, může ji i zapisovat,
• čtecı́ a zápisová hlava se může (nemusı́) pohybovat různými směry, nejen doprava,
L
• nepotřebujeme zásobnı́k, ale přesto můžeme uchovávat i jinou informaci než označenı́
stavu, ve kterém právě jsme – kamkoliv na pásku si můžeme cokoliv poznamenat
a později tuto informaci využı́t,
• na Turingově stroji lze provádět i výpočty.
Turingovými stroji se budeme podrobněji zabývat v navazujı́cı́m kurzu Teorie vyčı́slitelnosti a složitosti.
Úkol 6.1
1. Sestrojte Turingovy stroje rozpoznávajı́cı́ jazyky
• L1 = {an b2n an : n ≥ 1}
• L2 = {wcwcw : w ∈ {a, b}∗ }
• L3 = {wcwR cw : w ∈ {a, b}∗ }
2. Podle Turingova stroje z přı́kladu 6.4 zpracujte slova bba a ε. Dále upravte definici
tohoto stroje tak, aby zpracovával slova nad abecedou {a, b, c} (tj. přidejte do předpisu
δ-funkce zpracovánı́ symbolů c).
3. Navrhněte (alespoň rámcově, popisem činnosti) Turingův stroj, který zdvojı́ svůj
vstup (tj. napřı́klad pokud je na vstupu slovo abb, na výstupu bude slovo abbabb).
4. Navrhněte Turingův stroj, který bude mı́t na vstupu čı́slo v desı́tkové soustavě a jeho
výstupem bude toto čı́slo vynásobené dvěma.
C
6.2
GRAMATIKY TYPU 0
6.2
6.2.1
95
Gramatiky typu 0
Návrh gramatiky typu 0
Gramatika typu 0 je taková gramatika, jejı́ž pravidla jsou ve tvaru
α → β,
α ∈ (N ∪ T )∗ N (N ∪ T )∗ , β ∈ (N ∪ T )∗
Jde tedy o obecné gramatiky, kde v předpisu máme jediný požadavek – na levé straně
pravidla musı́ být řetězec terminálnı́ch a neterminálnı́ch symbolů obsahujı́cı́ alespoň jeden
neterminál.
Přı́klad 6.5
n
Následujı́cı́ gramatika generuje jazyk L = a2 : n ≥ 1 .
G = ({S, A, B, C, D, E}, {a}, P, S)
S → ACaB
Ca → aaC
CB → DB
CB → E
aD → Da
AD → AC
aE → Ea
AE → ε
Odvodı́me nejkratšı́ slovo generované gramatikou:
S ⇒ ACaB ⇒ AaaCB ⇒ AaaE ⇒ AaEa ⇒ AEaa ⇒ aa
Všimněte si „stěhovánı́“ symbolu E doleva pomocı́ pravidla AE → EA. Takový postup
nenı́ v bezkontextových gramatikách možný.
Přı́klad 6.6
Sestrojı́me gramatiku generujı́cı́ jazyk L = {an bn cn : n ≥ 1}.
Na začátku vytvořı́me neterminálovou „kostru“. Použijeme neterminály H1 a H2 jako
hranice částı́ slova obsahujı́cı́ch různé symboly, dále neterminály A a B jako „běžce“ určujı́cı́
právě zpracovávanou část slova (přidáváme bud’ zároveň symboly a a b, a nebo symbol
c), dále neterminál Z pro návrat, kdy se připravujeme na generovánı́ dalšı́ trojice symbolů
a, b, c, a konečně neterminál E zajišt’ujı́cı́ správné ukončenı́ generovánı́ slova a odstraněnı́
hraničnı́ch symbolů.
Postup si můžeme nastı́nit na sekvenci větných forem, které by podle pravidel gramatiky
byly generovány – viz tabulku 6.1.
P
6.2
GRAMATIKY TYPU 0
začátek generovánı́ dalšı́ trojice a, b, c
vygenerujeme a, b, posun zpracovánı́ doprava
posun zpracovánı́ doprava
postupně „přeskočı́me“ všechna b . . .
vygenerujeme c za symbolem H2 , posun doleva
posun doleva, přeskočı́me b
pořád doleva . . .
navážeme na začátek
96
aaaA H1 bbb H2 ccc
aaaa H1 bBbbb H2 ccc
aaaa H1 bbBbb H2 ccc
aaaa H1 bbbbB H2 ccc
aaaa H1 bbbbZ H2 cccc
aaaa H1 bbbZb H2 cccc
aaaa H1 Zbbbb H2 cccc
aaaaA H1 bbbb H2 cccc
Tabulka 6.1: Postup generovánı́ slova v gramatice typu 0
Budeme postupovat takto:
• Nejdřı́v vygenerujeme hraničnı́ symboly a neterminál A.
S → AH1 H2
• Vygenerujeme a a b, přesun doprava.
AH1 → aH1 bB
• Posouvánı́ symbolu B doprava:
Bb → bB
• Konec rekurze z předchozı́ho bodu, vygenerujeme c, posun zpět doleva.
BH2 → ZH2 c
• Posun symbolu Z doleva:
bZ → Zb
• Konec rekurze z předchozı́ho bodu, navážeme na prvnı́ bod.
H1 Z → AH1
• Zajistı́me správné ukončenı́ generovánı́ terminálnı́ho slova.
AH1 → abE
Eb → bE
EH2 → c
Celá gramatika:
G = ({S, A, B, H1 , H2 , Z, E}, {a, b, c}, P, S)
S → AH1 H2 | abE
AH1 → aH1 bB
Bb → bB
BH2 → ZH2 c
bZ → Zb
H1 Z → AH1
Eb → bE
EH2 → c
6.2
GRAMATIKY TYPU 0
97
Vygenerujeme slovo a2 b2 c2 , modře je vyznačena část slova přepisovaná v dalšı́m kroku
některým pravidlem:
S ⇒ AH1 H2 ⇒ aH1 bBH2 ⇒ aH1 bZH2 c ⇒ aH1 ZbH2 c ⇒ aAH1 bH2 c ⇒ aabEbH2 c ⇒
⇒ aabbEH2 c ⇒ aabbcc
Úkol
6.2
2
1. V gramatice z přı́kladu 6.5 vygenerujte slovo a2 = a4 .
C
2. Ke gramatice z přı́kladu 6.5 přidejte ještě jedno pravidlo tak, aby generovala jazyk
n
L = a2
: n≥0 .
3. V gramatice z přı́kladu 6.6 vygenerujte slovo a3 b3 c3 .
4. Gramatiku z přı́kladu 6.6 upravte tak, aby generovala jazyk
• L1 = {an bn cn : n ≥ 0}
• L2 = a2n bn c2n : n ≥ 1
6.2.2
Kurodova normálnı́ forma
Obecný tvar pravidla může být trochu problém předevšı́m v důkazech. Proto v přı́padě,
že gramatiku 0 chceme využı́t pro některý účel, ji převedeme do normálnı́ formy. Pro
gramatiky typu 0 existuje Kurodova normálnı́ forma (anglicky Kuroda Normal Form).
Gramatika typu 0 je v Kurodově normálnı́ formě (KNF) pro jazyky typu 0, jestliže pro
všechna jejı́ pravidla α → β platı́
|α| ≤ 2, |β| ≤ 2
(a samozřejmě musı́ splňovat předpis pro pravidla gramatiky typu 0, tedy alespoň jeden neterminál na levé straně pravidla). Obvykle se předpokládá, že všechna pravidla gramatiky
G = (N, T, P, S) v KNF splňujı́ jeden z těchto tvarů:
• AB → CD, A, B, C, D ∈ N
• A → CD, A, C, D ∈ N
• A → a, A ∈ N, a ∈ T
• A → ε, A ∈ N
Všimněte si, že se připouštı́ i jeden typ zkracujı́cı́ho pravidla (poslednı́ typ), protože gramatiky typu 0 obecně nejsou nezkracujı́cı́ (to jsou až gramatiky typu 1).
Vidı́me, že předpis druhého a třetı́ho typu pravidla je podobný předpisu pro Chomského normálnı́ formu. Pokud se jedná o pravidlo bezkontextového typu (i taková mohou
být v gramatice typu 0), pak pro takové pravidlo můžeme použı́t algoritmus pro převod
do Chomského normálnı́ formy.
6.2
GRAMATIKY TYPU 0
98
Postup převodu gramatiky typu 0 do KNF:
1. Odstranı́me jednoduchá pravidla.
2. Všechny terminály a ∈ T (na levé i pravé straně pravidla) nahradı́me „pomocnými“
neterminály Na .
3. Pro všechny neterminály vytvořené v předchozı́m bodu přidáme pravidlo Na → a.
4. Pravidla A → B1 B2 . . . Bn , n > 2 nahradı́me pravidly
A
→ B1 X1
X1 → B2 X2
..
.
Xn−2 → Bn−1 Bn
Tedy pravidla bezkontextového typu zpracováváme stejně jako pro Chomského NF.
5. Pravidla A1 A2 . . . Am → B1 B2 . . . Bm , m > 2 (obě strany pravidla stejně dlouhé)
nahradı́me pravidly
A1 A2 → B1 X1
X1 A3 → B2 X2
..
.
Xm−2 Am → Bm−1 Bm
6. Nezkracujı́cı́ pravidla A1 A2 . . . Am → B1 B2 . . . Bn , 2 < m ≤ n nahradı́me pravidly
A1 A2 → B1 X1
X1 A3 → B2 X2
..
.
Xm−2 Am → Bm−1 Xm−1
Xm−1 → Bm Xm
Xm → Bm+1 Xm+1
..
.
Xn−2 → Bn−1 Bn
7. Zkracujı́cı́ pravidla A1 A2 . . . Am → B1 B2 . . . Bn , n < m nahradı́me pravidly
A1 A2 → B1 X1
X1 A3 → B2 X2
..
.
Xn−1 An+1 → Bn Xn
Přı́klad 6.7
Postup si ukážeme na gramatice
S → AaBC
C → cBAa | bS
AaBc → d
BA → abcd
1
2 3
,
4
5
Xn An+2 → Xn+1
..
.
Xm−3 Am−1 → Xm−2
Xm−2 Am → ε
6.2
GRAMATIKY TYPU 0
99
4 a 5 provedeme náhradu terminálů a ∈ T novými neterminály Na .
V pravidlech 3
Pravidlo , nynı́ C → Nb S, nemusı́me dále zpracovávat, už odpovı́dá KNF.
1 a .
2
Nejdřı́v zpracujeme pravidla bezkontextového typu S → AX1
X1 → Na X2
X2 → BC
C → Nc X3
X3 → BX4
X4 → ANa
3 a
4 – jedno je zkracujı́cı́ a druhé nezkracujı́cı́:
Zbývajı́ pravidla BA → Na X5
Na X5 → Nb X6
X6 → Nc Nd
ANa → Nd X7
X7 B → X8
X8 Nc → ε
Celá gramatika po převodu do KNF:
S → AX1
X1 → Na X2
X2 → BC
C → Nc X3
Úkol
X3 → BX4
X4 → ANa
BA → Na X5
Na X5 → Nb X6
X6 → Nc Nd
ANa → Nd X7
X7 B → X8
X8 Nc → ε
6.3
1. Převed’te do KNF gramatiky z přı́kladů 6.5 a 6.6 (str. 95).
2. Převed’te do tvaru KNF následujı́cı́ gramatiku:
G = ({S, A, B, C}, {a, b, c, d}, P, S)
S → aAB | BA | C
aAa → bCba | B
AC → d
B → aB | CC | b
C → cS | d
Na → a
Nb → b
Nc → c
Nd → d
C

Podobné dokumenty

Teorie jazyku˚ a automatu˚ I - RNDr. Šárka Vavrečková, Ph.D.

Teorie jazyku˚ a automatu˚ I - RNDr. Šárka Vavrečková, Ph.D. RNDr. Šárka Vavrečková, Ph.D. Dostupné na: http://vavreckova.zam.slu.cz/formal1.html Ústav informatiky Filozoficko-přı́rodovědecká fakulta v Opavě Slezská univerzita v Opavě Bezručovo ...

Více

Bakalarske statnice

Bakalarske statnice Předmět lze splnit jeho úspěšným absolvovánı́m nebo uznánı́m z předchozı́ho studia. Ústnı́ část státnı́ závěrečné zkoušky se skládá ze dvou předmětů, jimiž jsou Základy mat...

Více

Září - Časopis Život v Kristu

Září - Časopis Život v Kristu modlí. Jeho modlitby však nejsou „točením mlýnku“, nýbrž zápasem. Čteme zde, že vynakládá mnoho námahy. Modlitba je tedy zápas, námaha. A kde je zápas, tam je i práce. Zdá se mi obtížné podrobně po...

Více

Detekce tautologie Bc. Jan Schindler

Detekce tautologie Bc. Jan Schindler konstrukčnı́ prvky, které majı́ jen dva možné stavy (0, 1). Těm bude odpovı́dat taková Booleova algebra, která má právě jen tyto dva prvky. Velmi rozsáhlé integrované obvody - VLSI1 hr...

Více

Minimalizace ne´uplne urcen´ych logick´ych funkcı pomocı

Minimalizace ne´uplne urcen´ych logick´ych funkcı pomocı Minimalizace logických funkcı́ je obor, který se rozvinul s prvnı́m praktickým uplatněnı́m Booleovy algebry v praxi. Z algebraicky zadaných logických funkcı́ se přı́mo vycházı́ nejen při n...

Více