% Created by: Radovan Klembara
\chapter{Úvod}
Počítačový program je možné popísať ako postup jednoduchých operácií, ktoré má vykonať. Problém je, že tieto jednoduché operácie musí počítač najskôr poznať. Preto je nutné počítač nejako informovať o~týchto operáciách. Tieto operácie je možné popísať pomocou programovacích jazykov, ich sémantiky a~syntaxi.

Pokiaľ by programovací jazyk bol konečný, tak by pre jeho popis stačilo jednoduché vymenovanie operácií a~ich možného poradia vykonávania. Bohužiaľ ale pre väčšinu programovacích jazykov toto nie je možné, pretože počet spôsobov zoradenia ich operácií je nekonečný. Z~tohoto dôvodu je pre ich popis nutné použiť nejaké konečné prostriedky. Vhodnými prostriedkami sú gramatiky a~automaty. Popis štruktúry jazyka veľmi galantne modelujú gramatiky, avšak automaty túto štruktúru ľahko identifikujú a~spracujú. V~súčastnosti väčšina programovacích jazykov patrí medzi takzvané bezkontextové jazyky. To znamená, že pre ich modelovanie sú postačujúce bezkontextové gramatiky a~zásobníkové automaty. Táto skutočnosť sa ale môže zmeniť, a~to znamená, že bude potrebné používať modely, ktoré sú schopné popisovať náročnejšie jazyky, ako napríklad takzvané kontextové jazyky. Jedným z~takýchto modelov sú práve hlboké zásobníkové automaty.

Hlboké zásobníkové automaty boli prvýkrát zavedené Alexandrom Medunom v~roku 2006, v~časopise Acta Informatica. Tieto automaty presahujú silu bezkontextových jazykov, ale zároveň ich vyjadrovacia sila nie je väčšia ako sú kontextové jazyky. Ich vyjadrovaciu silu je možné popísať pomocou regulovaných bezkontextových gramatík bez pravidiel vymazávania. Ide v~podstate o~zásobníkové automaty, ktoré povoľujú pristupovanie k~nevstupným symbolom uloženým na zásobníku aj na inom mieste ako je jeho vrchol. Povoľujú ale iba prístup k~nevstupným symbolom do~nejakej predom určenej nemennej hĺbky. Pri počítaní hĺbky nevstupného symbolu sa ale ignorujú všetky vstupné symboly.

Práca sa zaoberá jednou z~oblastí teoretickej informatiky, preto je nutné rozumieť použitým matematickým zápisom. Pre pochopenie práce je taktiež dôležité rozumieť teórií formálnych jazykov. Cieľom tejto práce je zaviesť, skúmať a~aplikovať alternatívne verzie hlbokých zásobníkových automatov. Zavedenie alternatívnych verzií týchto automatov vedie k~vytvoreniu rýchlejších a~efektívnejších modelov, ktoré môže byť jednoduchšie navrhnúť a~prípadne aj použiť. Zároveň je v~texte práce aj dokázané, že tieto modely majú rovnakú vyjadrovaciu silu ako základné hlboké zásobníkové automaty.

Modifikácie popísané v~tejto práci spočívajú v~pridaní paralelizmu. Modifikácie povoľujú súbežný prepis viacerých nevstupných symbolov na viaceré reťazce skladajúce sa z~vstupných aj nevstupných symbolov alebo na prázdne reťazce. Rozdiel medzi alternatívnymi verziami spočíva v~rozdielnom vyžadovanom počte prepísaných nevstupných symbolov v~jednom paralelnom kroku.  

Pre každú alternatívnu verziu hlbokého zásobníkového automatu, bol navrhnutý jeden algoritmus pre prevod danej verzie automatu na základný hlboký zásobníkový automat. Aby prevod nebol iba jednostranný v~práci navrhujem pre každú verziu aj jeden algoritmus pre prevod hlbokého zásobníkového automatu na automat každej z~navrhnutých verzií. 

Text v~kapitole \ref{theory} predstavuje čitateľovi akýsi matematický a~informatický základ k~pochopeniu práce.  V~kapitole sa nachádza aj úvod do gramatík a~automatov ako takých. Ďalší text tejto práce je určený pre čitateľa znalého odboru teoretickej informatiky. Zmysel tejto kapitoly preto nie je naučiť čitateľa dané definície, ale úlohou tejto kapitoly je skôr ozrejmenie významu použitých symbolov a~konštrukcií.  

V~nadchádzajúcej kapitole \ref{deepPushdownAutomata} sa nachádza popis hlbokého zásobníkového automatu. Text tejto kapitoly je v~podstate voľným prekladom a~interpretáciou článku Alexandra Medunu z~časopisu Acta Informatica \cite{meduna_acta_informatica}. Kapitola teda popisuje a~definuje hlboký zásobníkový automat tak, ako ho sformoval profesor Meduna. Ďalej vysvetľuje a~dokazuje silu hlbokých zásobníkových automatov. Ďalšou časťou tejto kapitoly je popis niektorých vybraných modifikácii obyčajných hlbokých zásobníkových automatov. 

Kapitola \ref{PPD} navrhuje, popisuje a~definuje prvú alternatívnu verziu hlbokého zásobníkového automatu. Ide o~automat s~paralelným spracovávaním expanzných prechodov. Idea spočíva v~tom, že automat môže v~jednom kroku prepísať jeden alebo viacero nevstupných symbolov. Maximálne ale môže v~jednom kroku prepísať toľko nevstupných symbolov, aká je maximálna hĺbka prístupu do zásobníka automatom. Kapitola navyše obsahuje aj spôsob simulácie takéhoto automatu obyčajným hlbokým zásobníkovým automatom a~spôsob simulácie obyčajného hlbokého zásobníkového automatu jeho paralelnou verziou.

V kapitole \ref{TPPD} je predstavená druhá alternatívna verzia hlbokého zásobníkového automatu. Ide o~automat, ktorý podobne ako prvá alternatíva taktiež paralelne spracováva expanzné prechody automatu. Idea spočíva ale v~tom, že v~jednom kroku musí automat prepísať práve toľko nevstupných symbolov, aká je maximálna hĺbka prístupu daného automatu. Spôsob simulácie takéhoto automatu obyčajným hlbokým zásobníkovým automatom a~spôsob simulácie obyčajného hlbokého zásobníkového automatu jeho druhou paralelnou verziou je taktiež súčasťou tejto kapitoly.

Dôležitou súčasťou práce je aj prezentovanie možných aplikácií vytvorených automatov. Kapitola \ref{aplications} sa venuje práve tomuto. Ukazuje dve možné aplikácie v~rámci bioinformatiky a~genetiky. Obsahuje aj príklady automatov pre dané aplikácie a~demonštruje ich funkčnosť na jednoduchých reťazcoch.

Pre jednoduchšiu prácu s~alternatívnymi verziami a~hlavne pre ich prevod som vytvoril konzolovú aplikáciu, ktorá implementuje algoritmy pre prevod medzi obyčajným hlbokým zásobníkovým automatom na jednu z~alternatívnych verzií. Aplikácia taktiež implementuje aj opačný smer a~to teda prevod paralelných verzií na obyčajný hlboký zásobníkový automat. Kapitola \ref{implement} obsahuje popis naprogramovanej aplikácie, jej vstupy, výstupy a~iné parametre.

Posledná kapitola s~číslom \ref{zaver}, sa zaoberá zhrnutím výsledkov dosiahnutých v~tejto práci a~potenciálnymi možnosťami budúceho rozšírenia tejto práce.






%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         Matematicky zaklad
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Úvod do teórie formálnych jazykov}
\label{theory}
Táto kapitola obsahuje základné definície, ktoré sú potrebné pre pochopenie práce. Skladá sa zo štyroch sekcií, kde sekcia \ref{mat_zaklad} pojednáva o~základných matematických štruktúrach a~operáciach nad nimi. Ďalšia \ref{formal_languages}. sekcia sa zameriava na formálne jazyky. Sekcia \ref{grammars} vysvetľuje formálne gramatiky ich rozdelenie, vyjadrovaciu silu a~bližšie špecifikuje stavové gramatiky. Posledná \ref{automata}. sekcia definuje základné stavové automaty a~popisuje ich vlastnosti.

\section{Matematický základ}
    \label{mat_zaklad}
    Teoretická informatika využíva pre definície a~ich popisy matematické zápisy. Pre automaty a~formálne jazyky z~matematického hľadiska je potrebná hlavne znalosť výrokovej logiky a~teórie množín. Nasledujúci text týkajúci sa výrokovej logiky je zhrnutím a~voľnou interpretáciou teórie výrokovej logiky prebranej zo~študijných textov pre predmet Diskrétna matematika od pána Kovára \cite{kovar_study}.

    Prvky jazyka výrokovej logiky (bez kvantifikátorov) sú tvorené \textit{symbolmi pravdivostných hodnôt}, \textit{spojkami}, \textit{výrokovými konštantami} a~\textit{pomocnými symbolmi}. Symboly pravdivostných hodnôt sú dva prvky \textit{true} a~\textit{false} označujúce pravdu a~nepravdu, pre jednoduchosť sa môžu označovať ako \textit{1}~a~\textit{0}. Spojkami sú logický súčet~($\lor$), súčin ($\land$~alebo~$,$) implikácia ($\Rightarrow$) a~ekvivalencia ($\Leftrightarrow$). Výrokové konštanty sú atomické výroky, ktoré majú nejakú pravdivostnú hodnotu. Pomocné symboly sú zátvorky \textit{(}~a~\textit{)}. Pre spojenie výrokov je možné použiť spojky, ktoré sú binárne, čiže spájajú práve dve výroky do jedného nového. Pomocou zátvoriek je možné ohraničiť výroky, a~tak označiť poradie vykonávania spojovania výrokov. Vďaka spojkám a~zátvorkám je možné vytvárať zložitejšie výroky. Pravdivostné hodnoty spojených výrazov spojkami sú znázornené v~Tabuľke \ref{tab:logic_table}.

    \begin{table}[H]
        \centering
        \begin{tabular}{@{}cccccc@{}}
            \toprule
            $s_1$ & $s_2$ & $s_1 \land s_2$ & $s_1 \lor s_2$ & $s_1 \Rightarrow s_2$ & $s_1 \Leftrightarrow s_2$ \\ \midrule
            \textbf{0} & \textbf{0} & \textbf{0} & \textbf{0} & \textbf{1} & \textbf{1}  \\
            \textbf{0} & \textbf{1} & \textbf{0} & \textbf{1} & \textbf{1} & \textbf{0}  \\
            \textbf{1} & \textbf{0} & \textbf{0} & \textbf{1} & \textbf{0} & \textbf{0}  \\
            \textbf{1} & \textbf{1} & \textbf{1} & \textbf{1} & \textbf{1} & \textbf{1}  \\
            \bottomrule
        \end{tabular}
        
        \caption{Pravdepodobnostné hodnoty spojok.}
        \label{tab:logic_table}
    \end{table}

    Do výrokovej logiky patria aj kvantifikátory, a~to \textit{obecný} alebo \textit{univerzálny kvantifikátor} a~\textit{existenčný kvantifikátor}. Obecný kvantifikátor sa označuje $\forall$ a~jeho význam je \myuv{pre všetky prvky}. Naopak existenčný sa označuje $\exists$ s~významom \myuv{existuje aspoň jeden prvok}.

    
    Zvyšok tejto kapitoly, ak nie je určené inak, je spojením definícií prebratých z~knihy Alexandra Medunu \cite{meduna_automata_languages} a~z~učebných textov od Milana Češky \cite{ceska_study}.
    
    \textit{Množina} $\Sigma$ je kolekcia prvkov patriacich do nejakého špecifikovaného priestoru. Množiny v~tejto práci sú výhradne značené veľkými písmenami z~anglickej alebo gréckej abecedy. Pokiaľ množina obsahuje nejaký prvok \textit{a}, tak sa táto skutočnosť zapisuje ako $a \in \Sigma$. Naopak prvok \textit{a}, ktorý nie je členom množiny sa zapíše $a \notin \Sigma$. \textit{Kardinalita množiny} $\Sigma$, $card(\Sigma)$, je číslo označujúce počet prvkov množiny $\Sigma$. Množina, ktorá neobsahuje žiadny prvok sa nazýva \textit{prázdnou množinou} a~označuje sa ako $\emptyset$. Kardinalita takejto množiny, $card(\emptyset)$, je preto rovná nule. Pokiaľ množina obsahuje konečný počet prvkov, nazýva sa \textit{konečnou množinou,} inak sa označuje ako \textit{nekonečná množina}. Konečná množina sa obecne špecifikuje vymenovaním jej prvkov. Napríklad $\Sigma = \{a_1, a_2, \dots , a_n\}$, kde $a_1$ až po $a_n$ sú všetky prvky množiny $\Sigma$. Nekonečná množina $\Omega$ je zvyčajne špecifikovaná vlastnosťou $\pi$ tak, že $\Omega$ obsahuje všetky prvky, ktoré spĺňajú vlastnosť $\pi$. Obecne sa to zapisuje $\Omega = \{a; \pi(a)\}$. Príkladom nekonečnej množiny je množina všetkých nezáporných celých čísel $\mathbb{N}_0$, ktorá je definovaná ako $\mathbb{N}_0 = \{i; i$ sa rovná $0 \lor i$ je prirodzené číslo$\}$ alebo skrátene $\mathbb{N}_0 = \{i; i \geq 0\}$. \textit{Konkatenácia} dvoch prvkov \textit{a}~a~\textit{b}, $a \cdot b$, je ich zreťazenie $a \cdot b = ab$. Konkatenácia dvoch množín je definovaná ako $\Sigma \cdot \Omega = \{a \cdot b; a \in \Sigma \land b \in \Omega\}$. 
    
    Nech $\Sigma$ a~$\Omega$ sú dve množiny, potom $\Sigma$ je \textit{podmnožinou} množiny $\Omega$ pokiaľ každý prvok patriaci do $\Sigma$ patrí aj do $\Omega$. Množina $\Omega$ sa potom nazýva \textit{nadmnožinou}. Tento vzťah sa zapíše ako $\Sigma \subseteq \Omega$. $\Sigma$ je \textit{vlastná podmnožina} množiny $\Omega$, označené ako $\Sigma \subset \Omega$, ak platí, že $\Sigma \subseteq \Omega$ a~$\Omega$ obsahuje aspoň jeden prvok \textit{a}, pre ktorý platí $a \notin \Sigma$. Pokiaľ $\Sigma \subseteq \Omega$ a~$\Omega \subseteq \Sigma$, tak označujeme tieto dve množiny ako \textit{rovnajúce sa}, čo sa zapíše pomocou výrazu $\Sigma = \Omega$. \textit{Zjednotenie} dvoch množín $\Sigma$ a~$\Omega$ sa znázorní $\Sigma \cup \Omega$ a~je definované ako $\Sigma \cup \Omega = \{a; a \in \Sigma \lor a \in \Omega\}$. Ich \textit{prienik} je množina $\Sigma \cap \Omega = \{a; a \in \Sigma \land a \in \Omega\}$. \textit{Rozdiel} dvoch množín sa zapíše $\Sigma \setminus \Omega$ a~je definovaný ako $\Sigma \setminus \Omega = \{a; a \in \Sigma \land a \notin \Omega\}$. Mocnina množiny $\Sigma$, zapísaná $2^\Sigma$, je množina všetkých podmnožín množiny $\Sigma$. Definovaná ako $2^\Sigma = \{\Sigma'; \Sigma' \subseteq \Sigma\}$. 

    Nech \textit{a}~a~\textit{b}~sú dva elementy, potom \textit{(a, b)} označuje \textit{usporiadanú dvojicu} obsahujúcu prvok \textit{a}~a~\textit{b}~v~tomto poradí. Nech $\Sigma$ a~$\Omega$ sú dve množiny.  \textit{Kartézsky súčin} týchto množín, $\Sigma \times \Omega$, je definovaný ako $\Sigma \times \Omega = \{(a, b); a \in \Sigma \land b \in \Omega\}$. \textit{Relácia} $\rho$ z~$\Sigma$ do $\Omega$ je podmnožina kartézskeho súčinu týchto dvoch množín, $\rho \subset \Sigma \times \Omega$. Pokiaľ $\rho$ reprezentuje konečnú podmnožinu $\Sigma \times \Omega$, tak sa $\rho$ nazýva \textit{konečnou reláciou}. Relácia $\rho \subset \Sigma \times \Omega$ je označovaná ako relácia nad $\Sigma$ ak $\Sigma = \Omega$. Pokiaľ platí, že $\rho \subset \Sigma \times \Sigma$ a pre všetky $a \in \Sigma$ platí $(a, a) \in \rho$, tak relácia sa nazýva \textit{reflexívnou}. \textit{Reflexívny uzáver} relácie $\rho$ je najmenšia reflexívna nadmnožina $\rho'$. \textit{Tranzitívnou} reláciou sa označuje relácia, pre ktorej všetky prvky platí tvrdenie $\forall a, b, c \in \Sigma; (a, b) \in \rho \land (b, c) \in \rho \Rightarrow (a, c) \in \rho$. \textit{Tranzitívny uzáver} relácie $\rho$ je najmenšia tranzitívna nadmnožina $\rho^+$. \textit{Reflexívny a~tranzitívny uzáver} relácie $\rho$ je najmenšia reflexívna a~tranzitívna nadmnožina označovaná ako $\rho^*$. Pre označenie toho, že dva prvky \textit{a}~a~\textit{b} patria do relácie $\rho$ je v~práci zavedená konvencia, ktorá nahrádza zápis $(a, b) \in \rho$ za zápis $a \rho b$. 

    Nech $\Sigma$~a~$\Omega$ sú dve množiny a~nech $\phi$ je relácia z~$\Sigma$ do $\Omega$ taká, že pre každé $a \in \Sigma$ platí $card(\{b; b \in \Omega \land a\phi b\}) \leq 1$. Potom $\phi$ je \textit{funkcia} z~$\Sigma$ do $\Omega$. Pokiaľ pre funkciu $\phi$ platí $card(\{b; b \in \Omega \land a\phi b\}) = 1$, pre každé $a \in \Sigma$, tak $\phi$ sa nazýva \textit{totálnou funkciou} z~$\Sigma$ do $\Omega$. V~rámci tejto práce je zavedená konvencia, ktorá zavádza označenie $\phi(a) = b$, ktoré má rovnaký význam ako $a \phi b$. Pokiaľ platí $\phi(a) = b$, tak je možné povedať, že funkcia $\phi$ vracia pre prvok $a$ prvok $b$. Funkcie je možné definovať napríklad vymenovaním podmienok a~ku nim patriacich prvkov. Príkladom takejto funkcie môže byť funkcia $abs$, ktorá pre každé nezáporné číslo \textit{n}~vracia to isté číslo \textit{n},~ale pre každé záporné číslo vracia jeho obrátenú hodnotu. Funkcia $abs$ je definovaná:

    \begin{center}
        $abs(x): \mathbb{R} \times \mathbb{R} = \left\{ 
        \begin{array}{ll}
            x & \textit{pre x} \geq 0 \\
            -x & \textit{pre x} < 0 \\
        \end{array}
        \right.$
    \end{center}

\section{Formálne jazyky}
\label{formal_languages}
    Pochopenie formálnych jazykov a~operácií nad týmito jazykmi vyžaduje najprv definovanie \textit{abecedy} a~\textit{slov} (niekedy nazývaných reťazcami). Abeceda v~kontexte formálnych jazykov je konečná neprázdna množina prvkov, ktoré sa nazývajú \textit{symbolmi}. Sekvencia alebo zreťazenie symbolov tvorí slová. Formálne jazyky predstavujú koncept prázdneho slova, ktoré je označené symbolom $\epsilon$. Konkatenácia prázdneho slova $\epsilon$ s~neprázdnym slovom \textit{x} sa rovná neprázdnemu slovu \textit{x}, zapísané ako $x\epsilon = \epsilon x = x$. \textit{Slovom nad} $\Sigma$ sa rozumie slovo \textit{x}, ktoré vzniklo poskladaním symbolov vybratých práve z~množiny $\Sigma$. Slovo je formálne definované pomocou rekurzie. Nech $\Sigma$ je abeceda, potom $\epsilon$ je slovo nad $\Sigma$. Ak \textit{x} je slovo nad $\Sigma$ a~$a \in \Sigma$, potom \textit{xa} je tiež slovo nad $\Sigma$. 

    \textit{Dĺžka} slova \textit{x} je číslo vyjadrujúce počet symbolov v~\textit{x} a označuje sa pomocou výrazu $|x|$. Formálne je dĺžka definovaná tak, že pokiaľ $x = \epsilon$, potom dĺžka $|x| = 0$. Pokiaľ $x = a_1 \dots a_n$ pre nejaké $n \geq 1$, kde $a_i \in \Sigma$ pre všetky $i = 1, \dots, n$, potom $|x| = n$. Nech $a \in \Sigma$, potom $\#_a(x)$ značí počet prvkov \textit{a} v~slove \textit{x}. \textit{Mocninou} slova \textit{x} nad abecedou $\Sigma$ sa rozumie opakovaná konkatenácia tohoto slova so~slovom \textit{x}. Mocnina je rekurzívne definovaná. Pre všetky $i \geq 0$, i-ta mocnina slova \textit{x}, $x^i$, je $\epsilon$ ak $i = 0$ inak $x^i = xx^{i - 1}$. \textit{Prevrátenie reťazca x}, $reversal(x)$, je definované ako $reversal(x) = \epsilon$ ak $x = \epsilon$ alebo ak $x = a_1a_2\dots a_{n}$ pre nejaké $n \in \mathbb{N}^+; n \geq 1$ a~$a_i \in \Sigma$, pre všetky $i = 1, 2, \dots, n$ potom $reversal(x) = a_n\dots a_2a_1$. 

    Nech \textit{x} a~\textit{y} sú dve slová nad abecedou $\Sigma$. Potom \textit{x}~je \textit{prefix} slova \textit{y},~ak existuje slovo \textit{z}~nad $\Sigma$ také, že $xz = y$. Slovo \textit{x}~je \textit{sufix} slova \textit{y},~pokiaľ existuje slovo \textit{z}~nad $\Sigma$ také, že $zx = y$. 

    Nech $\Sigma$ je abeceda a~nech $\Sigma^*$ označuje množinu všetkých slov nad $\Sigma$. Reťazec \textit{x} je \textit{podreťazcom} reťazca \textit{y}, pokiaľ existuje také $z \in \Sigma^*$, pre ktoré platí $y = xz \lor y = zx$. Každá podmnožina $L \subseteq \Sigma^*$ je \textit{jazyk} nad $\Sigma$. 

\section{Gramatiky}
\label{grammars}
    Jeden zo spôsobov reprezentácie formálnych jazykov je vymenovanie ich všetkých slov. Avšak tento triviálny spôsob je častokrát pre rozsiahle konečné jazyky nepraktický. Navyše pre nekonečné jazyky je takýto spôsob absolútne nepoužiteľný. Narozdiel od triviálnej reprezentácie ako je vymenovanie všetkých slov jazyka, sú gramatiky schopné popísať konečné aj nekonečné jazyky. Gramatika je najznámejším modelom používaným pre reprezentáciu formálnych jazykov.
    
    Gramatika je generatívny systém, v ktorom je možné pomocou takzvaných prepisovacích pravidiel generovať z~počiatočného nevstupného symbolu výsledné reťazce. Tieto reťazce sú práve prvkami gramatikou definovaného jazyka. Gramatika používa dve konečné disjunktné množiny abecied. Prvá je množina nevstupných symbolov (označovaná \textit{N}) a~druhá je množina vstupných symbolov (označovaná $\Sigma$). Nevstupné symboly, majú rolu pomocných premenných označujúcich určité syntaktické celky (kategórie). Takéto symboly sú ďalej v~práci zapisované veľkými symbolmi (A, B, S). Abeceda vstupných symbolov je identická s~abecedou, nad ktorou je definovaný jazyk. Vstupné symboly sú v~práci reprezentované malými symbolmi (a, b, c, d) a~symbolom $\epsilon$. Reťazce obsahujúce len vstupné symboly sú v~práci reprezentované napríklad $u, v, w$. Pre zápis reťazcov obsahujúcich vstupné aj nevstupné symboly sa v~práci používajú symboly $\alpha$~a~$\beta$.

    \begin{definition}
    \label{def:grammar}
        Gramatika je štvorica $G = (N, \Sigma, P, S)$, kde 
        \begin{itemize}
            \item $N$ je konečná množina nevstupných symbolov,
            \item $\Sigma$ je konečná množina vstupných symbolov $N \cap \Sigma = \emptyset$,
            \item $P$ je konečná množina pravidiel, $P \subseteq (N \cup \Sigma)^*N(N \cup \Sigma)^* \times (N \cup \Sigma)^*$,
            \item $S \in N$ je počiatočný symbol gramatiky.
        \end{itemize}
    \end{definition}

    \noindent
    Najväčšiu časť gramatiky tvorí množina prepisovacích pravidiel \textit{P}. Každý prvok množiny \textit{P} sa nazýva pravidlom a~je to usporiadaná dvojica $(\alpha, \beta)$. Ide o~reláciu možného prepisu reťazca $\beta$ namiesto reťazca $\alpha$, ktorý sa vyskytuje ako podreťazec generovaného reťazca. Pre ľahšie rozpoznanie pravidiel sú pravidlá v~práci zapisované ako $\alpha \xrightarrow{} \beta$. Reťazec $\alpha$ ale musí obsahovať aspoň jeden nevstupný symbol a~$\beta$~musí byť prvok patriaci do $(N \cup \Sigma)^*$. Formálne vyjadrené, množina \textit{P} je podmnožina kartézskeho súčinu $(N \cup \Sigma)^*N(N \cup \Sigma)^* \times (N \cup \Sigma)^*$. 
    
    Pokiaľ množina pravidiel \textit{P} obsahuje pravidlá tvaru $\alpha \xrightarrow{} \beta_1, \alpha \xrightarrow{} \beta_2, \dots, \alpha \xrightarrow{} \beta_n$ potom je možné skrátiť zápis pravidiel na $\alpha \xrightarrow{} \beta_1| \beta_2| \dots| \beta_n$. Nech $\lambda$ a~$\mu$ sú reťazce z $(N \cup \Sigma)^*$. Medzi týmito reťazcami platí relácia $\Rightarrow_G$, nazývaná \textit{priama derivácia}, pokiaľ je možné $\lambda$~a~$\mu$ vyjadriť v~tvaroch $\lambda = \gamma \alpha \delta$ a~$\mu = \gamma \beta \delta$, kde $\gamma$ a~$\delta$ sú ľubovolné reťazce z~$(N \cup \Sigma)^*$ a~$\alpha \xrightarrow{} \beta$ je nejaké prepisovacie pravidlo z~\textit{P}. Pokiaľ relácia priamej derivácie medzi $\lambda$~a~$\mu$ exituje, tak je možné povedať, že z~reťazca $\lambda$ sa dá v~gramatike \textit{G} priamo generovať reťazec $\mu$. Pokiaľ je zrejmé, že ide o~deriváciu v~gramatike \textit{G}, tak nie je potrebné špecifikáciu gramatiky pod symbolom $\Rightarrow$ zapisovať. Medzi $\lambda$ a~$\mu$ existuje relácia \textit{derivácie} $\Rightarrow^+$, pokiaľ existuje postupnosť priamych derivácií $v_{i - 1} \Rightarrow v_i$, kde $i = 1, \dots, n \land n \geq 1$, také, že platí $\lambda = v_0 \Rightarrow v_1 \Rightarrow \dots \Rightarrow v_{n - 1} \Rightarrow v_n = \mu$. Táto postupnosť sa nazýva \textit{deriváciou dĺžky~n}. Pokiaľ platí $\lambda \Rightarrow^+ \mu$, potom sa reťazec $\mu$ dá generovať z~reťazca $\lambda$. Je zjavné, že relácia $\Rightarrow^+$ je tranzitívnym uzáverom priamej derivácie $\Rightarrow$. Symbolom $\Rightarrow^n$ sa značí derivácia s~dĺžkou práve \textit{n}. Relácia $\Rightarrow^*$ je tranzitívnym a~reflexívnym uzáverom priamej derivácie $\Rightarrow$.

    Na reťazec vzniknutý postupnosťou priamych derivácií, ktorý obsahuje len vstupné symboly nie je možné aplikovať žiadne ďalšie prepisovacie pravidlá a~proces generovania tým pádom končí. Nech $G = (N, \Sigma, P, S)$ je gramatika. Reťazec $\alpha \in (N \cup \Sigma)^*$ sa nazýva \textit{vetnou formou}, pokiaľ platí $S \Rightarrow^* \alpha$, inak povedané slovo $\alpha$ je generované z~počiatočného symbolu \textit{S}. Vetná forma obsahujúca iba vstupné symboly je považovaná za \textit{vetu} a~jazyk $L(G)$, generovaný gramatikou \textit{G} je definovaný množinou všetkých takýchto viet. Formálne zapísané ako $L(G) = \{w; S \Rightarrow^* w \land w \in \Sigma^*\}$

    \subsection*{Klasifikácia formálnych jazykov}
    Jednotlivé jazyky je možné klasifikovať rôznymi spôsobmi. Najpoužívanejší spôsob je však \textit{Chomského hierarchia jazykov}. Hierarchia popisuje štyri základné typy (triedy) jazykov. Klasifikácia jazykov je založená na klasifikácií gramatík, ktoré dané jazyky generujú, preto v~nasledujúcom texte sa klasifikácia jazykov tiež označuje ako klasifikácia gramatík.
    
    Typy gramatík sú klasifikované na základe \myuv{náročnosti} formy pravidiel \textit{P} v~gramatike. Tieto typy sú však položené hierarchicky, čo znamená, že vyššie klasifikované gramatiky (s~väčšími nárokmi na formu pravidiel) je možné zaradiť k~akémukoľvek nižšie klasifikovanému (s~menšími nárokmi na formu pravidiel) typu gramatiky. Inými slovami nižšia klasifikácia znamená väčšiu vyjadrovaciu \myuv{silu} gramatiky patriacej do danej triedy. Chomského hierarchia jazykov je znázornená na Obr. \ref{img:chomHierarchy}.
    
    Typy tried Chomského hierarchie jazykov sú označené číslicami (0, 1, 2, 3). Jazyk generovaný gramatikou \textit{i}, kde \textit{i} je anonymný názov typu gramatiky v~Chomského hierarchii jazykov, $i = 0, 1, 2, 3$, je označovaný ako $\mathcal{L}_i$. Zároveň $\mathcal{L}_i$ označuje aj množiny jazykov generovaných gramatikami typu \textit{i}. Preto je možné vzťah medzi typmi jazykov popísať matematicky takto $\mathcal{L}_0 \supset \mathcal{L}_1 \supset \mathcal{L}_2 \supset \mathcal{L}_3$.

    \img[chomHierarchy][Chomského hierarchia jazykov.][img:chomHierarchy][][0.6]

    \subsection*{Typ 0}
    Najnižšie postavený typ v~Chomského hierarchii jazykov je \textit{typ 0}. Jazyky tohoto typu sú označované za \textit{rekurzívne vyčísliteľné jazyky}, gramatiky popisujúce tieto jazyky sú označované ako \textit{neobmedzené} alebo \textit{frázové} gramatiky. Ukážkovým modelom pre tieto jazyky sú Turingove stroje. Požiadavka na náročnosť formy pravidiel je zhodná s~definíciou pravidiel použitou v~Definícií \ref{def:grammar}. Forma pravidiel je teda $u \xrightarrow{} v$, kde $u \in (N \cup \Sigma)^*N(N \cup \Sigma)^* \land v \in (N \cup \Sigma)^*$. 
    
    \subsection*{Typ 1}
    Ďalším typom je \textit{typ 1}, ktorý zastrešuje takzvané \textit{kontextové jazyky}. Pre ich popis sa používajú \textit{kontextové gramatiky} a~pre ich modelovanie sa používajú lineárne ohraničené konečné automaty. Typ 1 vyžaduje formu pravidiel v~tvare $\alpha A \beta \xrightarrow{} \alpha \gamma \beta$, kde $A \in N \land \alpha, \beta \in (N \cup \Sigma)^* \land \gamma \in (N \cup \Sigma)^+$ alebo $S \xrightarrow{} \epsilon$. Z~tohoto tvaru vyplýva, že kontextové gramatiky neobsahujú pravidlá, ktoré nahradzujú nevstupné symboly za prázdny reťazec. Jedinou výnimkou je pravidlo $S \xrightarrow{} \epsilon$, kde je ale vyžadované, že \textit{S} je počiatočný symbol danej gramatiky. Vďaka forme pravidiel typu 1, je možné tvrdiť, že tieto gramatiky nie sú schopné skracovania generovaných reťazcov. Inými slovami ak platí $\lambda \Rightarrow \mu$, tak $|\lambda| \leq |\mu|$. Jedinou prijateľnou výnimkou je avšak prípad $S \Rightarrow \epsilon$.
    
    \subsection*{Typ 2}
    \textit{Bezkontextové jazyky} spadajú práve pod \textit{typ 2} a sú popisované rovnomennými \textit{bezkontextovými gramatikami}. Pravidlá sú vyžadované v~tvare $A \xrightarrow{} \gamma$, kde $A \in N \land \gamma \in (N \cup \Sigma)^*$. Gramatiky substituujú ľavú stranu pravidla bez ohľadu na kontext, v~ktorom sa nevstupný symbol nachádza. Ekvivalentným spôsobom reprezentácie bezkontextových jazykov sú konečné zásobníkové automaty.
    
    \subsection*{Typ 3}
    Posledným typom Chomského hierarchie gramatík je \textit{typ 3} a jazyky ním obsiahnuté sa nazývajú \textit{regulárne jazyky}. Gramatiky tohoto typu sa nazývajú \textit{pravými lineárnymi gramatikami}, majú tvar $A \xrightarrow{} xB$ alebo $A \xrightarrow{} x$, kde $A, B \in N \land x \in \Sigma$. K~tejto gramatike je možné vytvoriť ekvivalentnú špeciálnu pravú lineárnu gramatiku nazývanú \textit{pravou regulárnou gramatikou}, z~ktorej vyplýva aj častejšie používaný názov gramatiky tretieho typu, a~teda gramatika je nazývaná \textit{regulárnou gramatikou}. Tvar pravidiel regulárnej gramatiky je $A \xrightarrow{} xB$ alebo $A \xrightarrow{} x$, kde $A, B \in N \land x \in \Sigma$, alebo $S \xrightarrow{} \epsilon$, kde $S \in N$. Tieto gramatiky je možno reprezentovať obyčajnými základnými konečnými stavovými automatmi.

    \subsection*{Stavové gramatiky}
    Neobmedzené a~kontextové gramatiky je nepohodlné použiť v~praxi z~dôvodu ich sily a~nutnosti čistej kontextovej verifikácie. Na druhú stranu bezkontextové gramatiky je síce jednoduchšie použiť, avšak ich sila nemusí byť dostačujúca. Preto je nutné zaviesť gramatiku, ktorá bude patriť medzi bezkontextové a~kontextové gramatiky. Takouto gramatikou je \textit{stavová gramatika}, ktorej nasledujúci popis je prevzatý od pána Medunu a~Zemku \cite{meduna_regulated_grammars}.

    Stavová gramatika je bezkontextová gramatika rozšírená o~stavový mechanizmus, ktorý je veľmi podobný konečnému stavovému mechanizmu stavového automatu. Pri vykonávaní každého prepisovacieho pravidla stavová gramatika prepisuje najľavejší nevstupný symbol, ktorý môže byť prepísaný v~aktuálnom stave. Navyše pri tomto prepise gramatika prechádza do ďalšieho stavu. Nový stav má potom vplyv na to, ktoré ďalšie pravidlo sa použije v~ďalšom kroku. Pokiaľ aplikácia pravidla vždy prepisuje jeden z~prvých \textit{n} nevstupných symbolov, kde $n \in \mathbb{N}$, tak sa gramatika nazýva \textit{n-limitovanou}.

    \begin{definition}
        Stavová gramatika je pätica $G = (V, W, T, P, S)$, kde 
        \begin{itemize}
            \item \textit{V} je celková abeceda,
            \item \textit{W} je konečná množina stavov,
            \item $T \subset V$ je abeceda vstupných symbolov,
            \item $S \in V \setminus T$ je počiatočný symbol,
            \item $P \subseteq (W \times (V \setminus T)) \times (W \times V^+)$ je konečná relácia.
        \end{itemize}
    \end{definition}

    Namiesto výrazu $(q, A, p, v) \in P$ sa používa $(q, A) \xrightarrow{} (p, v) \in P$. Pre každé $z \in V^*$, množina ${}_G{states}(z) = \{q; (q, B) \xrightarrow{} (p, v) \in P\}$, kde $B \in (V \setminus T) \cup alph(z), v \in V^+ \land q, p \in W$, kde $alph(z)$ značí množinu symbolov nachádzajúcich sa v~reťazci \textit{w}. Pokiaľ platí $(q, A) \xrightarrow{} (p, v) \in P \land x, y \in V^*, {}_G{states}(x) \cup \{q\} = \emptyset$, potom \textit{G} vykoná derivačný krok z konfigurácie $(q, xAy)$ do konfigurácie $(p, xvy)$, symbolicky zapísané $(q, xAy) \Rightarrow (p, xvy)$. Navyše ak \textit{n} je kladné celé číslo, pre ktoré platí, že  $xA$ sa nachádza medzi prvými \textit{n} symbolmi (vstupné symboly sa nepočítajú), potom je možné povedať, že krok $(q, xAy) \Rightarrow (q, xvy)$ je n-limitovaný, symbolicky znázornené $(q, xAy) {}_n\Rightarrow (q, xvy)$. Index \textit{n} je možné vynechať iba pokiaľ nie je možná zámena významu výrazu za iný význam. Štandardne sú definované symboly $\Rightarrow^+$~a~$\Rightarrow^*$, ktoré popisujú tranzitívny uzáver relácie $\Rightarrow$ a~tranzitívny a~reflexívny uzáver nad $\Rightarrow$. Jazyk gramatiky \textit{G}, označený \textit{L(G)} je definovaný takto $L(G) =\{w \in T^*; (q, S) \Rightarrow^* (p, w) \land q,p \in W\}$.

    Symbolom \textbf{ST} sa označuje rodina jazykov generovaných stavovými gramatikami. Pre každé $n \geq 1$, $\textbf{ST}_n$ označuje rodinu jazykov generovaných \textit{n}-limitovanými stavovými gramatikami. Množina $\textbf{ST}_\infty = \bigcup\limits _{n \geq 1} \textbf{ST}_n$. 

    Vyjadrovacia sila stavových gramatík ako takých je rovná kontextovým gramatikám. Avšak sila \textit{n}-limitovanej stavovej gramatiky je priamo závislá na veľkosti \textit{n}. Pokiaľ \textit{n} je rovné \textit{1}, tak sila tejto gramatiky je rovná sile bezkontextových gramatík. To znamená, že medzi rodinami jazykov generovanými gramatikami platí $\mathcal{L}_2 = \textbf{ST}_1 \subset \textbf{ST}_2 \subset \dots \textbf{ST}_n \subset \textbf{ST}_\infty \subset \textbf{ST} = \mathcal{L}_1$.

    \hfill

    \noindent
    \exe{} Demonštrácia stavovej gramatiky generujúcej jazyk $L(G) = \{ww; w \in \{ab\}^+\}$ a~generovanie slova \textit{abab}. 

    \hfill
    
    \noindent $G = (\{S, X, Y, a, b\}, \{p_0, p_1, p_2, p_3, p_4, p_5\}, \{a, b\}, P, S)$, kde $P$ sú pravidlá:
    \begin{enumerate}
        \item $(p_0, S) \xrightarrow{} (p_0, XY)$
        \item $(p_0, X) \xrightarrow{} (p_1, aX)$
        \item $(p_1, Y) \xrightarrow{} (p_0, aY)$
        \item $(p_0, X) \xrightarrow{} (p_2, bX)$ 
        \item $(p_2, Y) \xrightarrow{} (p_0, bY)$ 
        \item $(p_0, X) \xrightarrow{} (p_3, a)$
        \item $(p_3, Y) \xrightarrow{} (p_0, a)$ 
        \item $(p_0, X) \xrightarrow{} (p_4, b)$
        \item $(p_4, Y) \xrightarrow{} (p_0, b)$
    \end{enumerate}

    \hfill
    
    Stavová gramatika \textit{G} pre jazyk \textit{L(G)} najskôr prepíše počiatočný symbol \textit{S} na \textit{XY}, potom použitím stavov \textit{G} zaistí, že kedykoľvek je \textit{X} prepísané na \textit{aX}, tak sa aktuálny stav zmení na taký, ktorý vyžaduje prepis \textit{Y} na \textit{aY}. Podobne kedykoľvek \textit{X} je prepísané na \textit{bX,} tak aktuálny stav sa zmení tak, aby vyžadoval prepis \textit{Y} na \textit{bY}. Každé úspešné generovanie slova je ukončené prepísaním \textit{X} na~\textit{a} alebo~\textit{b} nasledované prepisom \textit{Y} na~\textit{a} alebo~\textit{b} v~uvedenom poradí. 

    \hfill

    \noindent
    Generovanie slova $abab$ vyzerá takto:
    \begin{alignat*}{2}
        (p_0, S) &\quad \derM{}{} \quad (p_0, XY) \;  && [1] \nonumber \\
        &\quad \derM{}{} \quad (p_1, aXY) \; && [2] \nonumber \\
        &\quad \derM{}{} \quad (p_0, aXaY) \; && [3] \nonumber \\
        &\quad \derM{}{} \quad (p_4, abaY) \; && [8] \nonumber \\
        &\quad \derM{}{} \quad (p_0, abab) \; && [9] \nonumber 
    \end{alignat*}
    
    \noindent Číslo použitého pravidla gramatiky je znázornené v~hranatých zátvorkách.

\section{Stavové automaty}
\label{automata}
    Táto sekcia sa zaoberá automatmi, ktoré sú rovnako často používanými matematickými aparátmi pre štúdium formálnych jazykov ako gramatiky. Je možné ich jednoducho realizovať pomocou matematických vzorcov alebo vo spočetnom prostredí. Využívajú sa hlavne pre rozhodovanie toho, či nejaké slovo patrí alebo nepatrí do jazyka modelovaného daným automatom. Nech \textit{M} je akýkoľvek automat, potom jazyk prijímaný automatom \textit{M} je zaznačený ako $L(M)$.
    
    Pre pochopenie základného hlbokého zásobníkového automatu a~jeho modifikácií je nutné rozumieť aj jednoduchším automatom, ktorých modifikáciou vznikli hlboké zásobníkové automaty. Pre každú gramatiku označujúcu nejakú triedu Chomského hierarchie jazykov existuje verzia konečného stavového automatu, ktorá je ekvivalentná s~danou gramatikou. Ďalej v~texte sú predstavené konečné automaty ekvivalentné regulárnym a~bezkontextovým gramatikám. 
    
    \subsection*{Nedeterministický konečný automat}
    Najstarší a~najjednoduchší  automat je \textit{nedeterministický konečný automat}. Ide o~automat schopný modelovať regulárne jazyky. Skladá sa z~konečného počtu stavov, vstupnej čítacej pásky, čítacej hlavy a~pravidiel pre prechod medzi stavmi. Pravidlá sú pritom dané ako funkcia, ktorej vstupom je aktuálny stav a~aktuálny prečítaný symbol. Výstupom funkcie je množina stavov. Tento automat sa vždy nachádza v~nejakom stave a~pomocou čítacej hlavy číta postupne symboly na vstupnej páske. Symboly na vstupnej páske patria do vstupnej abecedy, čo je abeceda jazyka $L(M)$. Pri prečítaní každého symbolu na páske automat zmení svoj stav na nedeterministicky zvolený stav z~množiny stavov daných funkciou prechodu. Po prečítaní symbolu na vstupnej páske je čítacia hlava vždy posunutá na prvý ďalší neprečítaný symbol. Pokiaľ automat prečítal všetky symboly na vstupnej páske, tak ukončuje svoju činnosť, pretože automat nedokáže posunúť čítaciu hlavu proti smeru čítania. Na základe stavu, v~ktorom automat ukončil svoje vykonávanie, je možné zistiť, či prečítané slovo na vstupnej páske patrí do jazyka (bolo prijaté automatom) popísaného automatom alebo nie (automat neprijal slovo). Automat má špecifikované takzvané koncové stavy. Pokiaľ automat skončí v~koncovom stave, tak slovo bolo prijaté. Ak automat skončil prácu v~inom stave ako koncovom, tak automat neprijal slovo uložené na vstupnej páske. Automat vždy začína svoju prácu vo vopred špecifikovanom stave, ktorý sa nazýva počiatočný stav. Čítacia hlava automatu je vždy na začiatku práce automatu nastavená na prvý symbol na vstupnej páske. 

    \begin{definition}
        Nedeterministický konečný automat je pätica $M = (Q, \Sigma, R, q_0, F)$, kde 
        \begin{itemize}
            \item \textit{Q} je neprázdna konečná množina stavov,
            \item $\Sigma$ je vstupná abeceda,
            \item \textit{R} je prechodová funkcia, $R \subseteq Q \times \Sigma \xrightarrow{} 2^Q$,
            \item $q_0 \in Q$ je počiatočný stav,
            \item $F \subseteq Q$ je množina koncových stavov.
        \end{itemize}
    \end{definition}

    \noindent
    Nedeterministický konečný automat, ktorého prechodová funkcia splňuje $R: Q \times \Sigma \xrightarrow{} Q$, je označovaný za \textit{deterministický konečný automat}.

    \begin{lemma}
    \label{lemma:NKA_to_DKA}
        Každý nedeterministický konečný automat M môže byť zmenený na \myuv{ekvivalentný} deterministický konečný automat $M'$.
    \end{lemma}

    \noindent
    Ekvivalencia automatov použitá vo Vete \ref{lemma:NKA_to_DKA} hovorí o~ekvivalencii jazykov popísaných automatmi \textit{M}~a~\textit{M'}. To formálne znamená, že platí výraz $L(M) = L(M')$. 

    Ak $M = (Q, \Sigma, R, q_0, F)$ je konečný automat, potom dvojicu $C = (q, w)$ z~$Q \times \Sigma^*$ nazývame \textit{konfiguráciou} automatu \textit{M}. Stav \textit{q} v~konfigurácii \textit{C} sa nazýva aktuálny stav a~\textit{w} je doposiaľ neprečítaný podreťazec na vstupnej páske. Pokiaľ $w = \epsilon$, tak automat prečítal všetky symboly zo~vstupnej pásky.
    
    \textit{Prechod} automatu \textit{M} je reprezentovaný reláciou $\Rightarrow_M$ nad množinou konfigurácií \textit{C}. Pokiaľ $R(q, a) = Q_j$ obsahuje nejaké \textit{q'}, pre ktoré platí $Q_j \in 2^Q \land q' \in Q_j$ a~$Q_j$ označuje množinu budúcich stavov, daných funkciou \textit{R}, tak $(q, aw) \Rightarrow_M (q', w)$ pre všetky $w \in \Sigma^*$. Tranzitívny a~reflexívny uzáver relácie $\Rightarrow_M$ je relácia $\Rightarrow_M^*$. Pokiaľ je zrejmé, že sa jedná o~prechody automatu \textit{M}, tak relácie je možné značiť bez špecifikácie \textit{M} v~tvare $\Rightarrow$~a~$\Rightarrow^*$. 
    
    Vstupný reťazec \textit{w} je prijímaný konečným automatom \textit{M}, ak $(q_0, w) \Rightarrow^* (q, \epsilon) \land q \in F$. Jazyk prijímaný konečným automatom \textit{M} je definovaný ako $L(M) = \{w; (q_0, w) \Rightarrow^* (q, \epsilon) \land q \in F\}$.
    
    \subsection*{Zásobníkový konečný automat}
    Modifikáciou nedeterministického konečného automatu je možné vytvoriť \textit{zásobníkový konečný automat}, ktorý je schopný prijímať bezkontextové jazyky. Modifikácia spočíva v~tom, že sa nedeterministickému konečnému automatu pridá nekonečná pamäť, označovaná ako zásobník. Zásobníkový automat potom môže použiť zásobník pri získavaní množiny budúcich stavov. Tak ako názov pamäte napovedá, automat je schopný vždy pristúpiť iba na naposledy uložený symbol na zásobníku (symbol na vrchu zásobníka). Zásobníkový automat navyše môže pri prechode prečítať symbol $\epsilon$ zo~vstupnej pásky, a~to aj potom, ako prečítal posledný symbol na vstupnej páske. Pri každom prečítaní symbolu zo zásobníka je tento symbol zo zásobníka vybratý. Avšak automat musí pri každom kroku vložiť akékoľvek slovo na vrchol zásobníka (ako postupnosť jednotlivých symbolov slova). 

    \begin{definition}
        Zásobníkový automat $M$ je sedmica $M = (Q, \Sigma, \Gamma, R, q_0, Z_0, F)$, kde 
        \begin{itemize}
            \item $Q$ je neprázdna konečná množina stavov,
            \item $\Sigma$ je vstupná abeceda,
            \item $\Gamma$ je konečná množina zásobníkových symbolov, nazývaná zásobníková abeceda, kde $\Sigma \subseteq \Gamma$, a~znak $\# \in \Gamma \setminus \Sigma$, znak $\#$ označuje špeciálny pomocný symbol označujúci dno zásobníka,
            \item $R$ je prechodová funkcia $Q \times (\Sigma \cup \{\epsilon\}) \times (\Gamma \setminus \{\#\}) \xrightarrow{} 2^{Q \times (\Gamma \setminus \{\#\})^*}$,
            \item $q_0 \in Q$ je počiatočný stav,
            \item $Z_0 \in \Gamma$ je počiatočný symbol uložený na zásobníku, nazývaný štartovací symbol,
            \item $F \subseteq Q$ je množina koncových stavov.
        \end{itemize}
    \end{definition}

    \noindent
    \textit{Konfigurácia} zásobníkového automatu \textit{M} je trojica $C = (q, w, \alpha) \in Q \times \Sigma^* \times (\Gamma \setminus \{\#\})^*\{\#\}$, kde \textit{q} je aktuálny stav, \textit{w} je doposiaľ neprečítaná časť vstupného reťazca a~$\alpha$~je aktuálny obsah zásobníka. Obsah zásobníka je v~práci reprezentovaný reťazcom, ktorého najľavejší symbol korešponduje s~najvrchnejším symbolom uloženým na zásobníku. Pokiaľ $\alpha = \#$ tak zásobník je prázdny. 

    \textit{Prechod} automatu \textit{M} je reprezentovaný reláciou $\Rightarrow_M$ nad množinou konfigurácií \textit{C}. Pokiaľ je zrejmé, že sa jedná o~prechod automatu \textit{M}, je možné použiť označenie relácie $\Rightarrow$.  Relácia $(q, aw, x\alpha) \Rightarrow (q', w, \gamma \alpha)$ platí, pokiaľ $R(q, a, x)$ obsahuje prvok $(q', \gamma)$, pre nejaké $q \in Q, a \in (\Sigma \cup \{\epsilon\}), w \in \Sigma^*, x \in \Gamma \land \alpha, \gamma \in \Gamma^*$. Tranzitívny a~reflexívny uzáver relácie $\Rightarrow$ je označovaný reláciou $\Rightarrow^*$. 

    Počiatočná konfigurácia automatu je $(q_0, w, Z_0)$, pre $w \in \Sigma^*$. Koncová konfigurácia má tvar $(q, \epsilon, \alpha)$, kde $q \in F$ je koncový stav a~$\alpha \in \Gamma^*$.

    Vstupný reťazec $w \in \Sigma^*$ je prijatý zásobníkovým automatom, ak platí relácia \\ $(q_0, w, Z_0) \Rightarrow^* (q, \epsilon, \alpha)$, pre nejaké $q \in F$ a~$\alpha \in \Gamma^*$. Jazyk prijímaný zásobníkovým automatom \textit{M} je definovaný ako $L(M) = \{w; (q_0, w, Z_0) \Rightarrow^* (q, \epsilon, \alpha), q \in F, \alpha \in \Gamma^* \}$.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         PD_n
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Hlboký zásobníkový automat} 
\label{deepPushdownAutomata}

Táto kapitola sa zameriava na zhrnutie teórie týkajúcej sa hlbokých zásobníkových automatov. Kapitola je prekladom a~interpretáciou článku prezentovanom v~časopise Acta Informatica od profesora Alexandra Medunu \cite{meduna_acta_informatica}. 

Hlboký zásobníkový automat \textit{M} rovnako ako obyčajný zásobníkový automat pracuje s~pomocnou pamäťou (zásobníkom). Je možné povedať, že má dve operácie (typy pravidiel). Prvou je operácia vybratia. Tá je zhodná s~obyčajným prechodom zásobníkového automatu, pri ktorom je prečítaný akýkoľvek symbol (okrem symbolu $\epsilon$) zo~vstupnej pásky. Druhá operácia je operácia expanzie, ktorá je v~podstate prechod zásobníkového automatu, v~ktorom je prečítaný symbol $\epsilon$ a~v~ktorom sa zo~zásobníka prečíta iný symbol ako vstupný (nevstupný symbol). To znamená, že ak sa symbol \textit{a} nachádza na vrchole zásobníka, \textit{M} porovná tento vrchol s~aktuálnym vstupným symbolom. Ak sa symboly rovnajú, tak \textit{M} vyberie najvrchnejší symbol zo~zásobníka a~pokračuje s~ďalším vstupným symbolom. Pokiaľ sa na vrchole zásobníka nachádza nevstupný symbol, tak \textit{M} vykoná expanziu zásobníka. Navyše \textit{M} môže vykonať expanziu v~hĺbke \textit{m}, pre ktorú platí $m \geq 1$. Automat teda môže expandovať \textit{m}-tý najvrchnejší nevstupný symbol na zásobníku, a~tak ho nahradiť za nejaký reťazec. Okrem tejto zmeny expanznej operácie automat \textit{M} pracuje ako obyčajný zásobníkový automat.

\img[PDAMove][Demonštrácia zmeny zásobníka pre expanzné pravidlo $2sB \xrightarrow{} sbBA$.][img:pdaMove][H][0.8]

Na Obr. \ref{img:pdaMove} je zobrazený zásobník pred a~po vykonaní expanznej operácie. Zmena stavu pre tento príklad nie je podstatná. Veľké písmená označujú nevstupné symboly, malé písmená vstupné symboly a~symbol $\#$~označuje dno zásobníka. Použitá operácia je operácia, ktorá číta zo zásobníka druhý nevstupný symbol, porovná ho so symbolom \textit{B} a~ak sa rovnajú (v~tomto prípade sa rovnajú), tak nahradí tento symbol slovom \textit{bBA}. Pretože reťazec \textit{bBA} obsahuje dva nevstupné symboly \textit{A}~a~\textit{B}, tak symboly uložené na pôvodnom zásobníku za druhým symbolom sú po vykonaní operácie \myuv{posunuté} o~jedna hlbšie. Na obrázku to je demonštrované pomocou indexov pod každým prvkom uloženým na zásobníku. Napríklad symbol \textit{C}~mal index v~pôvodnom zložení zásobníka rovný \textit{3} ale po vykonaní pravidla je index symbolu \textit{C}~rovný \textit{4}. 

\begin{definition}
    Hlboký zásobníkový automat je sedmica, $M = (Q, \Sigma, \Gamma, R, s, S, F)$, kde 

    \begin{itemize}
        \item Q je konečná množina stavov,
        \item $\Sigma$ je vstupná abeceda, 
        \item $\Gamma$ je zásobníková abeceda, kde $\Sigma \subseteq \Gamma$ a~znak \# je špeciálny pomocný symbol označujúci dno zásobníku,
        \item R je konečná relácia, $R \subseteq (\mathbb{N^+} \times Q \times (\Gamma \setminus (\Sigma \cup \{\#\})) \times Q \times (\Gamma \setminus \{\#\})^+) \cup (\mathbb{N^+} \times Q \times \{\#\} \times Q \times (\Gamma \setminus \{\#\})^*\{\#\})$
        \item s je počiatočný stav, $s \in Q$,
        \item S je počiatočný zásobníkový symbol, $S \in \Gamma$,
        \item F je množina koncových stavov, F $\subseteq Q$. 
    \end{itemize}
\end{definition}

Nech $r = (m, q, A, p, v)$ je prvkom relácie \textit{R}. Potom tento prvok je možno zapísať ako $r = mqA \xrightarrow{} pv$. Každý prvok relácie \textit{R} sa nazýva pravidlom. Množina \textit{R} sa potom označuje ako množina pravidiel automatu \textit{M}. Pravidlo $mqA \xrightarrow{} pv$ je označované ako pravidlo majúce hĺbku \textit{m}.

Pokiaľ číslo $m \in \mathbb{N}^+$ a~je minimálne kladné celé číslo, také, že každé pravidlo automatu \textit{M} má hĺbku rovnú alebo menšiu ako \textit{m}, tak \textit{M} má hĺbku \textit{m}. Symbolicky zapísané ${}_mM$.

\hfill

\conf{} $ \chi \in Q \times \Sigma^* \times (\Gamma \setminus \{\#\})^*\#) $

\move{} Nech $\Xi$ je množina všetkých konfigurácií $M$ a~nech $x, y \in \Xi$ sú dve konfigurácie. Potom krok automatu \textit{M} je definovaný takto:
\begin{itemize}
    \item Automat vykoná vybratie a~prejde z~$x$ do $y$, pokiaľ $x = (q, au, az)$ a~$y = (q, u, z)$ a~zároveň pravidlo $aqa \xrightarrow{} q \in R$, kde $q \in Q, a\in\Sigma, u \in\Sigma^*, z \in \Gamma^*$. Zapíše sa ako \pop{x}{y}.
    \item Automat vykoná expanziu a~prejde z~$x$ do $y$, pokiaľ $x = (q, w, uAz)$ a~$y = (p, w, uvz)$ a~zároveň $mqA \xrightarrow{} pv \in R$, kde $p,q \in Q, m \in \mathbb{N}; m \geq 1 \land w, u \in \Sigma^*, A \in \Gamma \land v,z \in \Gamma^* $. Zapíše sa ako \expand{x}{y}.
\end{itemize}

Relácia kroku $\Rightarrow$ značí, že automat je schopný vykonať krok z~konfigurácie \textit{x} do \textit{y} práve vtedy, keď je schopný vykonať vybratie alebo expanziu z~\textit{x}~do~\textit{y}. Formálne definované takto:
\begin{align}
    (x \Rightarrow y) &\quad \Leftrightarrow \quad (\popM{x}{y} \lor \; \expandM{x}{y}), \nonumber
\end{align}
\noindent
kde  $x,y \in \Xi$.
 
Nech \moveClosure \: je tranzitívny a reflexívny uzáver relácie $\Rightarrow$ definovanej nad $\Xi$.

Konvencia udáva, že pri definovaní hlbokého zásobníkového automatu (ďalej označovaný ako $PD_n$), sú pravidlá vybratia dané implicitne pre každý stav automatu.

\hfill

\acceptedL{} Nech ${}_nM$ je hlboký zásobníkový automat, potom jazyk prijímaný týmto automatom $L({}_nM)$ je definovaný takto:
\begin{align}
    L({}_nM) = \{w; w \in \Sigma^*, \moveClosureM{(s, w, S\#)}{(f, \epsilon, \#)}\}, \nonumber
\end{align}

\noindent
kde $f \in F$.

Vyjadrovacia sila hlbokého zásobníkového automatu presahuje silu zásobníkových automatov, avšak nepresahuje silu takzvaných lineárne ohraničených konečných automatov. Rodina jazykov definovaná obecným hlbokým zásobníkovým automatom ${}_{deep}\textbf{PD}_k$, s~hĺbkou maximálne \textit{k}, označuje množinu jazykov definovanú hlbokými zásobníkovými automatmi s~hĺbkou \textit{i}, kde platí $1 \leq i \leq k$. Zväčšením hĺbky prístupu automatu je možno získať väčšiu vyjadrovaciu silu. Z~tohoto je možné povedať, že hlboké zásobníkové automaty na základe svojej hĺbky tvoria nekonečnú hierarchiu jazykov. Hierarchia sa ale pohybuje v~rozmedzí bezkontextových a~kontextových gramatík. Sila nepresahuje kontextové gramatiky, pretože pre každú hĺbku hlbokého zásobníkového automatu \textit{n} existuje kontextová gramatika, ktorú nie je možné prijať automatom s~hĺbkou \textit{n} alebo s~hĺbkou menšou ako \textit{n}. 

Modelom s~rovnakou vyjadrovacou silou ako hlboký zásobníkový automat s~hĺbkou \textit{n} sú práve \textit{n}-limitované stavové gramatiky. Platí, že rodiny jazykov hlbokých zásobníkových automatov sú ekvivalentné rodinám limitovaných stavových gramatík, ${}_{deep}\textbf{PD}_k = \textbf{ST}_k$, pre $k \in \mathbb{N}^+$. Hierarchiu rodín jazykov definovaných hlbokými zásobníkovými automatmi je možné zapísať ako $\textbf{CF} = {}_{deep}\textbf{PD}_1 \subset {}_{deep}\textbf{PD}_2 \subset \dots {}_{deep}\textbf{PD}_k \subset {}_{deep}\textbf{PD}_\infty \subset {}_{deep}\textbf{PD} = \textbf{CS}$.

\hfill

\exe{} Demonštrácia prijatia slova $w = aabbcc$, ktoré patrí do jazyka $L = \{a^nb^nc^n; n \geq 1\}$, automatom typu $PD_n$.

\hfill

\noindent
${}_2M = (\{s, q, p, f\}, \{a,b,c\}, \{a, b, c, A, S, \#\}, R, s, S, \{f\})$, kde $R$ sú pravidlá:
\begin{enumerate}
    \item $1sS \xrightarrow{} qAA$
    \item $1qA \xrightarrow{} paAb$ 
    \item $1qA \xrightarrow{} fab$
    \item $2pA \xrightarrow{} qAc$ 
    \item $1fA \xrightarrow{} fc$
\end{enumerate}

Hlboký zásobníkový automat ${}_2M$, najskôr vygeneruje z~počiatočného zásobníkového symbolu dva nevstupné symboly, kde prepísaním prvého zo symbolov sa vygeneruje slovo \textit{aAb}. Pri tomto prepise sa navyše zmení stav tak, aby sa ako ďalšie slovo vygenerovalo slovo \textit{Ac} z~druhého nevstupného symbolu. Prepis druhého symbolu vracia stav na počiatočný. Týmto cyklom je zabezpečený rovnaký počet všetkých symbolov a~ich správne usporiadanie. Úspešné prijatie slova musí byť sprevádzané prepisom prvého nevstupného symbolu na slovo \textit{ab} a~zmenou stavu na~\textit{f}. Pričom ďalší krok je zabezpečenie posledného symbolu \textit{c} a~nemožnosť ďalšieho generovania nevstupných symbolov. Pomedzi tieto všetky kroky je možno vykonávať operáciu vybratia, čím môže automat postupne prečítať slovo na vstupnej páske.

\hfill

\noindent
Prijatie slova $w$ vyzerá napríklad takto (čísla v~hranatých zátvorkách označujú použité expanzné pravidlo):
\begin{alignat*}{2}
    (s, aabbcc, S\#) &\quad \expandM{}{} \quad (q, aabbcc, AA\#) \; && [1] \nonumber \\
    &\quad \expandM{}{} \quad (p, aabbcc, aAbA\#) \; && [2] \nonumber \\
    &\quad \popM{}{} \quad (p, abbcc, AbA\#) \nonumber \\
    &\quad \expandM{}{} \quad (q, abbcc, AbAc\#) \; && [4] \nonumber \\
    &\quad \expandM{}{} \quad (f, abbcc, abbAc\#) \; && [3] \nonumber \\
    &\quad \popM{}{} \quad (f, bbcc, bbAc\#) \nonumber \\
    &\quad \popM{}{} \quad (f, bcc, bAc\#) \nonumber \\
    &\quad \popM{}{} \quad (f, cc, Ac\#) \nonumber \\
    &\quad \expandM{}{} \quad (f, cc, cc\#) \; && [5] \nonumber \\
    &\quad \popM{}{} \quad (f, c, c\#) \nonumber \\
    &\quad \popM{}{} \quad (f, \epsilon, \#) \nonumber \\
\end{alignat*}

\section{Modifikácie hlbokého zásobníkového automatu}
Tak ako píše Leupold vo svojom článku \cite{leupold}, definícia hlbokých zásobníkových automatov obsahuje niekoľko aspektov, ktoré nie sú na prvý pohľad zrejmé. Napríklad operácia vybratia nemôže zmeniť stav automatu. Takéto aspekty je potom možné študovať a~ich zmenou je možné získať automaty s~inými vlastnosťami. Na základe tejto skutočnosti boli hlboké zásobníkové automaty rôzne modifikované. Niektoré vybrané modifikácie sú popísané ďalej v~tejto sekcii.

\section*{Zmena stavu v pravidle vybratia}
 Nasledujúci text je prevzatý z článku od pána Leupolda \cite{leupold}, ktorý popisuje rôzne modifikácie hlbokých zásobníkových automatov. Jednou z~nich sú hlboké zásobníkové automaty s pravidlami vybratia, ktoré môžu meniť stav automatu. Autor článku vysvetľuje, že idea zmeny stavu automatu je konzistentná s~ideou za hlbokými zásobníkovými automatmi, pretože nijak neovplyvňuje prácu so zásobníkom. 

 Hlavným rozdielom oproti originálnej definícii je, že operácie vybratia nie sú definované implicitne a~keď je vstupný symbol vybratý zo zásobníka, je možné zmeniť stav. Rodina jazykov, ktoré je možné prijať hlbokými zásobníkovými automatmi s~hĺbkou \textit{1} je rovná bezkontextovým jazykom, avšak toto neplatí pre hlboké zásobníkové automaty s~vyberacími pravidlami, schopnými zmeny stavu. Takéto automaty sú silnejšie ako ich originálna verzia.

\section*{Vymazanie nevstupných symbolov a neohraničený prístup do zásobníka}
 Rovnako ako predošlý text, aj tento text je prevzatý od Leupolda \cite{leupold}. Už v~článku od Meduny \cite{meduna_acta_informatica} je napísaný efekt prijímania \myuv{vymazávacích} pravidiel. Bez tejto možnosti každý nevstupný symbol musí byť eventuálne prepísaný na vstupný symbol. To spôsobuje, že na zásobníku nikdy nemôže byť viacej nevstupných symbolov ako je počet doposiaľ neprečítaných vstupných symbolov. S~touto úpravou ale je možné rozširovať zásobník bez limitu. 

 Hlboké zásobníkové automaty majú ohraničený prístup do zásobníka (hĺbku), pokiaľ sa táto špecifikácia zmení tak, že automaty môžu obsahovať pravidlá s~neohraničeným prístupom, tak sila automatov narastie. Príkladom neohraničeného prístupu je napríklad nájdenie a~prepísanie najľavejšieho nevstupného symbolu (s najmenšou hĺbkou) na zásobníku. Takýto automat má vyjadrovaciu silu rovnú Turingovému stroju. 

\section*{Riadené hlboké zásobníkové automaty} 
Riadené hlboké zásobníkové automaty sú popísané v~diplomovej práci od pána Šoustara\cite{controlled_pda}, ktorý ich využil k syntaktickej analýze, sú založené na systémoch hlbokých zásobníkových automatov. Nasledujúci text je prevzatý práve z~jeho práce. 

Zatiaľ čo bežný hlboký zásobníkový automat reťazec na svojom vstupe len porovnáva s~obsahom svojho zásobníka, bežný zásobníkový automat je navyše schopný voliť pravidlo, ktoré použije, na základe aktuálneho vstupného symbolu. Pridaním tejto schopnosti vznikajú riadené hlboké zásobníkové automaty. Sila riadených hlbokých zásobníkových automatov je aspoň tak veľká ako sila obyčajných hlbokých zásobníkových automatov. Úplný dôkaz sily riadených hlbokých zásobníkových automatov je otvoreným problémom.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         PPD_n
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Paralelný hlboký zásobníkový automat}
\label{PPD}
Prvou modifikáciou je prevedenie hlbokého zásobníkového automatu na paralelnú verziu. Idea za touto modifikáciou je urýchlenie vykonávania $PD_n$. Táto modifikácia umožňuje v~jednom kroku pristúpiť na jeden až $n$ nevstupných symbolov uložených na zásobníku, kde $n$ je \textit{hĺbka} daného automatu a~$n \in \mathbb{N}^+$. Automat podľa pravidiel v~rámci tohoto kroku paralelne prepisuje nevstupné symboly na slová patriace do $\Gamma^*$. Ďalej v~práci bude táto modifikovaná verzia $PD_n$ označovaná skratkou $PPD_n$, kde \textit{n} označuje maximálnu hĺbku prístupu automatu.

Paralelizmus je teda zabezpečený len v~rámci expanzných pravidiel, a~to vďaka ich tvaru. To znamená, že $PPD_n$ má dva druhy pravidiel rovnako ako $PD_n$. Prvý tvar (typ) pravidiel sú vyberacie pravidlá, ktorých tvar je rovnaký ako je tvar vyberacích pravidiel $PD_n$. Tvar expanzných pravidiel má ľavú stranu a~pravú stranu. Strany sú spojené symbolom $\xrightarrow{}$. Ľavá strana je tvorená aktuálnym stavom a~usporiadanou \textit{k}-ticou zloženou z~\textit{k}~nevstupných symbolov. Pozícia nevstupného symbolu udáva hĺbku, v~ktorej sa musí daný nevstupný symbol nachádzať, aby bolo možné pravidlo vykonať. Pravá strana sa skladá z~cieľového stavu a~usporiadanej \textit{k}~tice výsledných reťazcov. Pričom pozícia reťazca označuje v~pôvodnom stave zásobníka nevstupný symbol, ktorý bude nahradený za daný reťazec. Reťazec sa môže skladať z~akéhokoľvek počtu vstupných aj nevstupných symbolov v~akomkoľvek zoradení.

\img[PPDAMove][Demonštrácia zmeny zásobníku pre expanzné pravidlo $s(A, B) \xrightarrow{} s(A, bB)$.][img:ppdaMove][][0.8]

Prepis viacerých symbolov na zásobníku je možné pozorovať na Obr. \ref{img:ppdaMove}, kde je zobrazený zásobník pred a~po vykonaní paralelného pravidla. Na obrázku je možné pozorovať, že pravidlo je paralelné a~že prepisuje dva nevstupné symboly. Prvý je nevstupný symbol \textit{A}, ktorý je prepísaný sám na seba. Druhým symbolom je symbol \textit{B}, ktorý je nahradený za reťazec \textit{bB}. Pretože ani prvý ani druhý výsledný reťazec neobsahuje viac ako jeden nevstupný symbol, indexy hlbšie uložených symbolov sa nemenia. Zmena stavu nie je pre tento príklad podstatná.

\hfill

\noindent
Formálne pravidlá $PPD_n$ sú v jednom z týchto dvoch tvarov:
\begin{enumerate}
    \item $aqa \xrightarrow{} q$\textit{, kde q} $\in Q, a \in \Sigma$
    \item $p(A_1, A_2, \dots , A_k) \xrightarrow{} q(\alpha_1, \alpha_2, \dots, \alpha_k)$\textit{, kde p,q}  $\in Q, \forall k \in \mathbb{N}; k \leq n, A_k \in \Gamma \setminus (\Sigma \cup  \{ \# \}), \alpha_k \in (\Gamma \setminus \{\#\})^*$
\end{enumerate}

\begin{definition}
    Paralelný hlboký zásobníkový automat $(PPD_n)$ je usporiadaná sedmica \\ ${}_{n}M = (Q, \Sigma, \Gamma, R, s, S, F)$, kde

    \begin{itemize}
        \item Q je neprázdna konečná množina stavov,
        \item $\Sigma$ je vstupná abeceda, 
        \item $\Gamma$ je konečná množina zásobníkových symbolov, nazývaná zásobníková abeceda, kde $\Sigma \subseteq \Gamma$ a~znak $\# \in (\Gamma \setminus \Sigma) $, znak \# je špeciálny pomocný symbol označujúci dno zásobníka,
        \item R je konečná množina pravidiel,
        \item s je počiatočný stav, $s \in Q$,
        \item S je počiatočný zásobníkový symbol, $S \in ((\Gamma \setminus \Sigma) \setminus \{\#\})$,
        \item F je konečná množina koncových stavov, F $\subseteq Q$.
    \end{itemize}
\end{definition}


\noindent
\conf{} $ \chi \in Q \times \Sigma^* \times \{(\Gamma \setminus \{\#\})^*\#)\} $

\move{} Nech $n$ označuje hĺbku $PPD_n$ a~$x, y$ sú dve konfigurácie daného $PPD_n$, potom prechod je definovaný takto:
\begin{itemize}
    \item Automat vykoná vybratie a~prejde z~$x$ do $y$, pokiaľ $x = (q, au, az)$ a~$y = (q, u, z)$ a~zároveň pravidlo $aqa \xrightarrow{} q \in R$ , kde $q \in Q, a\in\Sigma, u \in\Sigma^*, z \in \Gamma^*$. Zapíše sa ako \pop{x}{y}.
    \item Automat vykoná expanziu a~prejde z~$x$ do $y$, pokiaľ $x = (p, w, a_1A_1a_2A_2\dots a_kA_kz)$ a~$y = (q, w, a_1\alpha_1a_2\alpha_2\dots a_k\alpha_kz)$ a~zároveň $p(A_1, A_2, \dots, A_k) \xrightarrow{} q(\alpha_1, \alpha_2, \dots, \alpha_k) \in R$, kde $p,q \in Q, \forall j \in \mathbb{N}; 1 \leq j \leq k, 1 \leq k \leq n \land w, a_j \in \Sigma^*, A_j \in \Gamma, \alpha_j, z \in \Gamma^* $. Zapíše sa ako \expand{x}{y}.
\end{itemize}

\noindent
Nech ${}_nM$ je $PPD_n$ a nech $\Xi$ je množina všetkých konfigurácií ${}_nM$. Relácia prechodu $\Rightarrow$ je potom definovaná takto:

\begin{align}
    (x \Rightarrow y) &\quad \Leftrightarrow \quad (\popM{x}{y} \lor \; \expandM{x}{y}), \nonumber
\end{align}
\noindent
kde  $x,y \in \Xi$.

Nech \moveClosure \: je tranzitívny a reflexívny uzáver relácie $\Rightarrow$ definovanej nad $\Xi$. Tak ako u~$PD_n$ tak aj u~$PPD_n$ sú pravidlá vybratia implicitne dané pre každý stav.

\hfill

\acceptedL{} Nech ${}_nM$ je $PPD_n$, potom jazyk prijímaný týmto automatom $L({}_nM)$ je definovaný takto:

\begin{align}
    L({}_nM) = \{w; w \in \Sigma^*, \moveClosureM{(s, w, S\#)}{(f, \epsilon, \#)}\}, \nonumber
\end{align}

\noindent
kde $f \in F$.

\hfill

\exe{} Demonštrácia prijatia slova $w = aaabbcc$, ktoré patrí do jazyka $L = \{a^ib^jc^k; \\ \forall i,j,k \in \mathbb{N}_0^+; i \geq j \geq k \}$, automatom typu $PPD_n$.

\hfill

\noindent
${}_2M = (\{s\}, \{a, b, c\}, \{a, b, c, S, A, B, \#\}, R, s, S, \{s\})$, kde $R$ sú pravidlá:
\begin{enumerate}
    \item $s(S) \xrightarrow{} s(\epsilon)$
    \item $s(S) \xrightarrow{} s(ABc)$ 
    \item $s(A, B) \xrightarrow{} s(a, b)$
    \item $s(A, B) \xrightarrow{} s(aA, bB)$ 
    \item $s(A, B) \xrightarrow{} s(aA, bBc)$
    \item $s(A) \xrightarrow{} s(aA)$
\end{enumerate}

Paralelný hlboký zásobníkový automat ${}_2M$ najskôr vždy pri vygenerovaní symbolu \textit{c}~vygeneruje nevstupné symboly \textit{A}~a~\textit{B}, ktoré zaručujú, že niekedy v budúcnosti budú vygenerované symboly \textit{a}~a~\textit{b}. Ďalej generuje reťazce \textit{aA}, \textit{bBc} tak, aby bol počet symbolov \textit{c} rovnaký ako počet symbolov \textit{c}~vo~vstupnom reťazci. Po vygenerovaní symbolov pokračuje podobným princípom symbolom \textit{b}, avšak iba po počet symbolov rovný počtu vo~vstupnom reťazci mínus jedna. Nasleduje generovanie všetkých ďalších symbolov \textit{a} okrem posledného. Nakoniec sú symboly \textit{A}~a~\textit{B} zmenené na \textit{a}~a~\textit{b}. Paralelizmus dovoľuje automatu generovanie rovnakého počtu symbolov \textit{a},~\textit{b}~a~\textit{c}~alebo iba symbolov \textit{a}~a~\textit{b} v~jednom prechode pričom nie je nutná zmena stavu. Toto urýchľuje prijatie slova a~zabezpečuje správny formát slova. 

\hfill

\noindent
Prijatie slova $w$ vyzerá takto:
\begin{alignat*}{2}
    (s, aaabbcc, S\#) &\quad \expandM{}{} \quad (s, aaabbcc, ABc\#) \; && [2] \nonumber \\
    &\quad \expandM{}{} \quad (s, aaabbcc, aAbBcc\#) \; && [5] \nonumber \\
    &\quad \popM{}{} \quad (s, aabbcc, AbBcc\#) \; &&  \nonumber \\
    &\quad \expandM{}{} \quad (s, aaabbcc, aAbBcc\#) \; && [6] \nonumber \\
    &\quad \popM{}{} \quad (s, abbcc, AbBcc\#) \; &&   \nonumber \\
    &\quad \expandM{}{} \quad (s, abbcc, abbcc\#) \; && [3] \nonumber \\
    &\quad \popM{}{} \quad (s, bbcc, bbcc\#) \; &&   \nonumber \\
    &\quad \popM{}{} \quad (s, bcc, bcc\#) \; &&    \nonumber \\ 
    &\quad \popM{}{} \quad (s, cc, cc\#) \; &&   \nonumber \\
    &\quad \popM{}{} \quad (s, c, c\#) \; &&   \nonumber \\ 
    &\quad \popM{}{} \quad (s, \epsilon, \#) \; &&   \nonumber 
\end{alignat*}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         Simulácia PPD_n pomocou PD_n
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{Simulácia paralelného hlbokého zásobníkového automatu hlbokým zásobníkovým automatom}

Paralelný hlboký zásobníkový automat prepisuje v~jednom kroku viacero nevstupných symbolov. Toto sekvenčný automat môže simulovať tak, že namiesto paralelne, bude symboly prepisovať sekvenčne. To znamená, že jedno paralelné pravidlo automatu $PPD_n$, bude $PD_n$ vykonávať $k$ novými pravidlami, kde \textit{k} je počet prepisovaných nevstupných symbolov v~danom paralelnom pravidle. Sekvenčné pravidlá budú vždy pristupovať do hĺbky určenej indexom pozície prepisovaného nevstupného symbolu paralelného pravidla, z~ktorého dané sekvenčné pravidlo vzniklo. 

Problém tejto simulácie ale nastáva, keď výsledok prepisu nejakého nevstupného symbolu je slovo, ktoré neobsahuje žiadny nevstupný symbol alebo slovo obsahujúce viac ako jeden nevstupný symbol. V prípade, kedy slovo neobsahuje žiadny nevstupný symbol, by bolo teoreticky možné zmenšiť ostatným ďalším pravidlám v~rámci paralelného kroku hĺbku o~jedna. Avšak pre druhý prípad by takýto trik vyžadoval zmenu maximálnej hĺbky prístupu automatu. Napríklad za predpokladu, že počet \uv{pod-pravidiel} pre vykonanie jedného paralelného pravidla je rovný maximálnej hĺbke prístupu a~ak by napríklad prvé \uv{pod-pravidlo} prepísalo symbol na aspoň dva nevstupné symboly a~ostatné pod-pravidlá by sa prepísali na aspoň jeden nevstupný symbol, tak pri sekvenčnom vykonávaní pravidiel by nebolo možné vykonať posledné pod-pravidlo. Pozícia nevstupného symbolu posledného pod-pravidla by bola väčšia ako je maximálna hĺbka prístupu daného automatu. To je dané práve tým, že prvé pod-pravidlo by zväčšilo hĺbku ostatných doposiaľ neprepísaných nevstupných symbolov o~jedna. 

Oveľa jednoduchším riešením, ktoré navyše nemení maximálnu hĺbku prístupu je upresnenie poradia vykonávania pravidiel v~rámci paralelného kroku.

\hfill

\begin{algorithm}[H]\label{alg:PPD_to_PD}
    \caption{\textsc{Prevod $PPD_n$ na $PD_n$.}}
    \SetNlSty{}{}{:}
    \KwIn{$PPD_n \; {}_nM = (Q, \Sigma, \Gamma, R_1, s, S, F)$} 
    \KwOut{$ PD_n \; {}_nN = (Q, \Sigma, \Gamma, R_2, s, S, F)$}
    \Indp \Indpp
    \BlankLine 
    $R_2 = \{r = apa \xrightarrow{} p; r \in R_1\}$ \label{step:PPD_to_PD_1} \\
    $R_{tmp} = R_1 \setminus R_2$  \label{step:PPD_to_PD_2} \\
    \While {$R_{tmp} \neq \emptyset$} { \label{step:PPD_to_PD_3}
        extract a~rule $p(A_1, A_2, \dots, A_k) \xrightarrow{} q(\alpha_1, \alpha_2, \dots, \alpha_k)$ from $R_{tmp}$ to $r$ \label{step:PPD_to_PD_4} \\
        $R_2 = R_2 \cup \{iqA_i \xrightarrow{} q\alpha_i; \forall i \in \mathbb{N}; 1 \leq i < k \land p, q, A_i, \alpha_i \in r\}$ \label{step:PPD_to_PD_5} \\
        $R_2 = R_2 \cup \{kpA_k \xrightarrow{} q\alpha_k; p, q, A_k, \alpha_k \in r\}$ \label{step:PPD_to_PD_6} \\
    }
    \KwRet{${}_nN = (Q, \Sigma, \Gamma, R_2, s, S, F)$} \label{step:PPD_to_PD_8}
\end{algorithm}

\hfill

\simul{} Nech ${}_nM = (Q, \Sigma, \Gamma, R_1, s, S, F)$ je $PPD_n$ a nech ${}_nN = (Q, \Sigma, \Gamma, R_2, s, S, F)$ označuje $PD_n$, ktorý má simulovať ${}_nM$. Pomocou Algoritmu \ref{alg:PPD_to_PD} je možné vytvoriť ${}_nN$. Automat ${}_nN$ bude potom simulovať ${}_nM$ takto:

\begin{enumerate}
    \item Ak by ${}_nM$ vykonal vybratie, tak ${}_nN$ taktiež vykoná vybratie.
    \item Ak by ${}_nM$ skončil úspešne, tak ${}_nN$ taktiež skončí úspešne.
    \item Ak by ${}_nM$ skončil neúspešne, tak ${}_nN$ taktiež skončí neúspešne.
    \item Ak by ${}_nM$ vykonal expanziu pomocou nejakého pravidla $r \in R_1$, tak ${}_nN$ vykoná postupne všetky pravidlá $r' = ipA_i \xrightarrow{} q\alpha_i \in R_2$, ktoré boli vytvorené v krokoch \ref{step:PPD_to_PD_5} a~\ref{step:PPD_to_PD_6} Algoritmu \ref{alg:PPD_to_PD} pre pravidlo \textit{r} v zostupnom poradí vzhľadom na \textit{i}.
\end{enumerate}

\begin{lemma} 
    \label{lemma:PPD_to_PD}
    Algoritmus \ref{alg:PPD_to_PD} pre prevod $PPD_n$ na $PD_n$ je správny. 
\end{lemma}

\subproof{Vety \ref{lemma:PPD_to_PD}}{
    Algoritmus vytvára pre každé expanzné pravidlo toľko pod-pravidiel, koľko je paralelne prepisovaných nevstupných symbolov v~danom pravidle. To znamená, že pokiaľ $PD_n$ úspešne vykoná všetky pod-pravidlá daného pravidla, tak vzniknuté slovo na zásobníku bude rovnaké ako slovo vytvorené $PPD_n$. Pokiaľ $PD_n$ postupuje tak, že najskôr prepíše nevstupný symbol, ktorý sa nachádza v~najväčšej hĺbke do ktorej by paralelný krok zasiahol, tak hĺbka nevstupných symbolov v~menšej hĺbke sa nezmení. Vďaka tomuto $PD_n$ je schopný pristúpiť na nevstupný symbol potrebný pre akékoľvek ďalšie pod-pravidlo. To znamená, že pre simuláciu paralelného prístupu stačí, keď bude automat vykonávať pod-pravidlá v~poradí od najhlbšie zasahujúceho až po to, ktoré pracuje s~prvým nevstupným symbolom. Zmena stavu automatu môže byť vykonaná kedykoľvek v~rámci vykonávania pod-pravidiel, ale je nutné dbať na to, aby pod-pravidlá so zmenou stavu \uv{počítali}. Algoritmus zmenu stavu rieši tak, že stav zmení už pri prepisovaní najhlbšieho nevstupného symbolu. Zmena stavu už na začiatku sa potom v~algoritme prejaví v~kroku \ref{step:PPD_to_PD_5}, kde každé pod-pravidlo má počiatočný stav rovný cieľovému.
}

\hfill

\exe{} Demonštrácia prevodu automatu ${}_2M$ typu $PPD_n$ na automat ${}_2N$ typu $PD_n$ pomocou Algoritmu \ref{alg:PPD_to_PD}. Jazyk prijímaný automatom ${}_2M$ je jazyk $L({}_2M)$, ktorý je definovaný ako $L({}_2M) = \{a^ib^jc^k; \forall i, j, k \in \mathbb{N}_0^+; i \geq j \geq k\}$. Číslo vykonaného kroku algoritmu je znázornené v~hranatých zátvorkách.

\hfill

\noindent ${}_2M =  (\{s\}, \{a, b, c\}, \{a, b, c, S, A, B, \#\}, R_1, s, S, \{s\})$, kde $R_1$ sú pravidlá: 
\begin{itemize}
    \item $s(S) \xrightarrow{} s(\epsilon)$ 
    \item $s(S) \xrightarrow{} s(ABc)$ 
    \item $s(A, B) \xrightarrow{} s(a, b)$ 
    \item $s(A, B) \xrightarrow{} s(aA, bB)$ 
    \item $s(A, B) \xrightarrow{} s(aA, bBc)$
    \item $s(A) \xrightarrow{} s(aA)$
\end{itemize}

\construct{$PD_n$}
\begin{enumerate}
    \item $R_2 = \{asa \xrightarrow{} s, bsb \xrightarrow{} s, csc \xrightarrow{} s\}$ \hfill [\ref{step:PPD_to_PD_1}]
    \item $R = \{s(S) \xrightarrow{} s(\epsilon), s(S) \xrightarrow{} s(ABc), s(A, B) \xrightarrow{} s(a, b), s(A, B) \xrightarrow{} s(aA, bB), \\ s(A, B) \xrightarrow{} s(aA, bBc), s(A) \xrightarrow{} s(aA)\}$  \hfill [\ref{step:PPD_to_PD_2}]
    
    \item $R \neq \emptyset $ \hfill [\ref{step:PPD_to_PD_4}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(S) \xrightarrow{} s(\epsilon) \land R = \{s(S) \xrightarrow{} s(ABc), s(A, B) \xrightarrow{} s(a, b), s(A, B) \xrightarrow{} s(aA, bB), \\ s(A, B) \xrightarrow{} s(aA, bBc), s(A) \xrightarrow{} s(aA)\}$  \hfill [\ref{step:PPD_to_PD_4}]
        \item $R_2 = R_2 \cup \emptyset$  \hfill [\ref{step:PPD_to_PD_5}]
        \item $R_2 = R_2 \cup \{1sS \xrightarrow{} s\epsilon \}$  \hfill [\ref{step:PPD_to_PD_6}]
    \end{enumerate}

    \item $R \neq \emptyset $  \hfill [\ref{step:PPD_to_PD_4}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(S) \xrightarrow{} s(ABc) \land R = \{s(A, B) \xrightarrow{} s(a, b), s(A, B) \xrightarrow{} s(aA, bB), \\  s(A, B) \xrightarrow{} s(aA, bBc), s(A) \xrightarrow{} s(aA)\}$  \hfill [\ref{step:PPD_to_PD_4}]
        \item $R_2 = R_2 \cup \emptyset$  \hfill [\ref{step:PPD_to_PD_5}]
        \item $R_2 = R_2 \cup \{1sS \xrightarrow{} sABc\}$  \hfill [\ref{step:PPD_to_PD_6}]
    \end{enumerate}

    \item $R \neq \emptyset $  \hfill [\ref{step:PPD_to_PD_4}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(A, B) \xrightarrow{} s(a, b) \land R = \{s(A, B) \xrightarrow{} s(aA, bB), s(A, B) \xrightarrow{} s(aA, bBc), \\ s(A) \xrightarrow{} s(aA)\}$  \hfill [\ref{step:PPD_to_PD_4}]
        \item $R_2 = R_2 \cup \{1sA \xrightarrow{} sa\}$  \hfill [\ref{step:PPD_to_PD_5}]
        \item $R_2 = R_2 \cup \{2sB \xrightarrow{} sb\}$  \hfill [\ref{step:PPD_to_PD_6}]
    \end{enumerate}

    \item $R \neq \emptyset $ \hfill  [\ref{step:PPD_to_PD_4}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(A, B) \xrightarrow{} s(aA, bB) \land R = \{s(A, B) \xrightarrow{} s(aA, bBc), s(A) \xrightarrow{} s(aA)\}$  \hfill [\ref{step:PPD_to_PD_4}]
        \item $R_2 = R_2 \cup \{1sA \xrightarrow{} saA\}$ \hfill  [\ref{step:PPD_to_PD_5}]
        \item $R_2 = R_2 \cup \{2sB \xrightarrow{} sbB\}$ \hfill  [\ref{step:PPD_to_PD_6}]
    \end{enumerate}

    \item $R \neq \emptyset $  \hfill [\ref{step:PPD_to_PD_4}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(A, B) \xrightarrow{} s(aA, bBc) \land R = \{s(A) \xrightarrow{} s(aA)\}$  \hfill [\ref{step:PPD_to_PD_4}]
        \item $R_2 = R_2 \cup \{1sA \xrightarrow{} saA\}$  \hfill [\ref{step:PPD_to_PD_5}]
        \item $R_2 = R_2 \cup \{2sB \xrightarrow{} sbBc\}$  \hfill [\ref{step:PPD_to_PD_6}]
    \end{enumerate}

    \item $R \neq \emptyset $  \hfill [\ref{step:PPD_to_PD_4}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(A) \xrightarrow{} s(aA) \land R = \emptyset$  \hfill [\ref{step:PPD_to_PD_4}]
        \item $R_2 = R_2 \cup \emptyset$  \hfill [\ref{step:PPD_to_PD_5}]
        \item $R_2 = R_2 \cup \{1sA \xrightarrow{} sa\}$  \hfill [\ref{step:PPD_to_PD_6}]
    \end{enumerate}

    \item $R == \emptyset $  \hfill [\ref{step:PPD_to_PD_4}]
    \item vráť ${}_2N = (\{s\}, \{a, b, c\}, \{a, b, c, S, A, B, \#\}, R_2, s, S, \{s\})$, kde $R_2 = \{asa  \xrightarrow{} s, bsb \xrightarrow{} s, csc \xrightarrow{} s, 1sS \xrightarrow{} s\epsilon, 1sS \xrightarrow{} sABc, 1sA \xrightarrow{} sa, 2sB \xrightarrow{} sb, 1sA \xrightarrow{} saA, 2sB \xrightarrow{} sbB, 2sB \xrightarrow{} sbBc\}$ \hfill  [\ref{step:PPD_to_PD_8}]
\end{enumerate}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         Simulácia PD_n pomocou PPD_n
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{Simulácia hlbokého zásobníkového automatu paralelným hlbokým zásobníkovým automatom}

Simulovanie spočíva v~tom, že jeden prepis nevstupného symbolu automatom $PD_n$ v~hĺbke \textit{k} bude vykonaný tak, že automat $PPD_n$ v~jednom kroku prepíše všetky nevstupné symboly nachádzajúce sa v~menšej hĺbke ako \textit{k} na seba. Symbol v~hĺbke \textit{k} zároveň nahradí za slovo podľa daného pravidla $PD_n$ automatu. Automat $PPD_n$ je možné zostrojiť Algoritmom \ref{alg:PD_to_PPD}.

\begin{algorithm}\label{alg:PD_to_PPD}
    \caption{\textsc{Prevod $PD_n$ na $PPD_n$}}
    \SetNlSty{}{}{:}
    \KwIn{ $PD_n \; {}_nM = (Q, \Sigma, \Gamma, R_1, s, S, F)$} 
    \KwOut{$PPD_n \; {}_nN = (Q, \Sigma, \Gamma, R_2, s, S, F)$}
    \Indp \Indpp
    \BlankLine 
    $R_2 = \{r = apa \xrightarrow{} p; r \in R_1\}$ \label{step:PD_to_PPD_1} \\
    $R_2 = R_2 \cup \{p(A_1, A_2, \dots, A_k) \xrightarrow{} q(\alpha_1, \alpha_2, \dots, \alpha_{k}); r = kpA_k \xrightarrow{} q\alpha_k \in R_1, \forall i \in \mathbb{N}; \forall A_i \in \Gamma; i < k, \alpha_i = A_i \} $  \label{step:PD_to_PPD_2} \\
    \KwRet{${}_nN = (Q, \Sigma, \Gamma, R_2, s, S, F)$} \label{step:PD_to_PPD_3}
\end{algorithm}

\simul{} Nech ${}_nM = (Q, \Sigma, \Gamma, R_1, s, S, F)$ je $PD_n$ a nech ${}_nN = (Q, \Sigma, \Gamma, R_2, s, S, F)$ označuje $PPD_n$, ktorý má simulovať ${}_nM$. Potom Algoritmom \ref{alg:PD_to_PPD} je možné vytvoriť ${}_nN$. Automat ${}_nN$ potom simuluje automat ${}_nM$ takto:

\begin{enumerate}
    \item Ak by ${}_nM$ vykonal vybratie, tak ${}_nN$ taktiež vykoná vybratie.
    \item Ak by ${}_nM$ skončil úspešne, tak ${}_nN$ taktiež skončí úspešne.
    \item Ak by ${}_nM$ skončil neúspešne, tak ${}_nN$ taktiež skončí neúspešne.
    \item Ak by ${}_nM$ vykonal expanziu pomocou nejakého pravidla $r \in R_1$, tak ${}_nN$ vykoná pravidlo $r' = p(A_1, A_2, \dots, A_k) \xrightarrow{} q(\alpha_1, \alpha_2, \dots, \alpha_k) \in R_2$, ktoré bolo vytvorené v~kroku \ref{step:PD_to_PPD_2} Algoritmu \ref{alg:PD_to_PPD} pre pravidlo~\textit{r}.
\end{enumerate}

\begin{lemma} 
    \label{lemma:PD_to_PPD}
    Algoritmus \ref{alg:PD_to_PPD} pre prevod $PD_n$ na $PPD_n$ je správny. 
\end{lemma}

\subproof{Vety \ref{lemma:PD_to_PPD}}{
    Pre každé expanzné pravidlo $PD_n$ algoritmus vytvára nové pravidlo. Toto pravidlo vždy prepisuje \textit{k} nevstupných symbolov, kde \textit{k} je hĺbka prístupu pôvodného pravidla $PD_n$. Všetky symboly, ktorých hĺbka je menšia ako \textit{k}, sú prepísané na seba. Vďaka tejto skutočnosti platí, že podreťazec pred symbolom v~hĺbke \textit{k} zostáva nemenný. Symbol v~hĺbke \textit{k} je prepísaný na slovo dané pôvodným pravidlom. To zaručuje, že výsledné slovo na zásobníku je po paralelnom kroku rovnaké ako slovo, ktoré by vzniklo za pomoci pôvodného sekvenčného pravidla.
}

\hfill

\exe{} Demonštrácia prevodu automatu ${}_2M$ typu $PD_n$ na automat ${}_2N$ typu $PPD_n$ pomocou Algoritmu \ref{alg:PD_to_PPD}. Jazyk $L({}_2M)$ je definovaný ako $L({}_2M) = \{a^nb^nc^n; \forall n \in \mathbb{N}^+\}$. Číslo vykonaného kroku algoritmu je znázornené v~hranatých zátvorkách.

\hfill

\noindent 
${}_2M =  (\{s, q, p, f\}, \{a, b, c\}, \{a, b, c, S, A, \#\}, R_1, s, S, \{f\})$, kde $R_1$ sú pravidlá: 
\begin{itemize}
    \item $1sS \xrightarrow{} qAA$ 
    \item $1qA \xrightarrow{} paAb$ 
    \item $1qA \xrightarrow{} fab$ 
    \item $2pA \xrightarrow{} qAc$ 
    \item $1fA \xrightarrow{} fc$
\end{itemize}

\construct{$PPD_n$}
\begin{enumerate}
    \item $R_2 = \{asa \xrightarrow{} s, bsb \xrightarrow{} s, csc \xrightarrow{} s\}$  \hfill [\ref{step:PD_to_PPD_1}]
    \item $R = R_2 \cup \{s(S) \xrightarrow{} s(qAA), q(A) \xrightarrow{} p(aAb), q(A) \xrightarrow{} f(ab), p(A, A) \xrightarrow{} q(A, Ac), \\ p(S, A) \xrightarrow{} q(S, Ac), f(A) \xrightarrow{} f(c)\}$   \hfill [\ref{step:PD_to_PPD_2}]
    \item vráť ${}_2N = (\{s, q, p, f\}, \{a, b, c\}, \{a, b, c, S, A, \#\}, R_2, s, S, \{f\})$  \hfill [\ref{step:PD_to_PPD_3}]
\end{enumerate}

\section{Vyjadrovacia sila}
\begin{lemma} 
    \label{lemma:str_PPD_to_PD}
    Pre každý paralelný hlboký zásobníkový automat ${}_nM$ existuje hlboký zásobníkový automat ${}_nM'$, ktorý prijíma rovnaký jazyk. Platí teda $L({}_nM) = L({{}_nM'})$.
\end{lemma}

\proof{Vety \ref{lemma:str_PPD_to_PD}}{
    Nech ${}_nM$ je akýkoľvek paralelný hlboký zásobníkový automat, potom na základe Vety \ref{lemma:PPD_to_PD} je možné vytvoriť automat ${}_nM'$ Algoritmom \ref{alg:PPD_to_PD}. Pretože Veta \ref{lemma:PPD_to_PD} je správna, tak automat je korektným hlbokým zásobníkovým automatom, ktorý prijíma jazyk $L({}_nM)$. Potom platí $L({}_nM) = L({{}_nM'})$.
}

\begin{lemma} 
    \label{lemma:str_PD_to_PPD}
    Pre každý hlboký zásobníkový automat ${}_nM$ existuje paralelný hlboký zásobníkový automat ${}_nM'$, ktorý prijíma rovnaký jazyk. Platí teda $L({}_nM) = L({{}_nM'})$.
\end{lemma}

\proof{Vety \ref{lemma:str_PD_to_PPD}}{
    Nech ${}_nM$ je akýkoľvek hlboký zásobníkový automat, potom na základe Vety~\ref{lemma:PD_to_PPD} je možné vytvoriť automat ${}_nM'$ Algoritmom \ref{alg:PD_to_PPD}. Pretože Veta \ref{lemma:PD_to_PPD} je správna, tak automat je korektným paralelným hlbokým zásobníkovým automatom, ktorý prijíma jazyk $L({}_nM)$. Potom platí $L({}_nM) = L({{}_nM'})$.
}

\begin{lemma} 
    \label{lemma:str_PPD_eq_PD}
    Rodina jazykov generovaných paralelným hlbokým zásobníkovým automatom s~hĺbkou \textit{n} je ekvivalentná rodine jazykov generovaných hlbokým zásobníkovým automatom s~rovnakou hĺbkou. Platí $\textbf{PPD}_\textbf{n} = \textbf{PD}_\textbf{n}$.
\end{lemma}

\proof{Vety \ref{lemma:str_PPD_eq_PD}}{
    Dôsledok Vety \ref{lemma:str_PPD_to_PD} a \ref{lemma:str_PD_to_PPD}.
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
%                                              TPPD_n
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Násobný paralelný hlboký zásobníkový automat}
\label{TPPD}
Táto modifikácia sa veľmi podobá na modifikáciu, ktorou vznikol $PPD_n$. Idea za touto modifikáciou ale je, že vyžaduje v~jednom kroku prístup na práve $n$ nevstupných symbolov uložených na zásobníku, kde $n$ je \textit{hĺbka} daného automatu. V~rámci jedného kroku automat paralelne prepisuje práve $n$ nevstupných symbolov na slová patriace do $\Gamma^*$, podľa daného pravidla automatu. Takto modifikovaný automat bude v~tejto práci ďalej označovaný skratkou $TPPD_n$. Automat $TPPD_n$ je v~skutočnosti špeciálnou verziou $PPD_n$, kde počet nevstupných symbolov prepísaných v~každom kroku je rovný \textit{n}.

Pravidlá $TPPD_n$ môžu byť formované v~jednom z~dvoch tvarov rovnako ako pravidlá v~$PPD_n$. Pravidlá pre vybratie symbolu sú rovnaké ako pravidlá pre vybratie v~$PPD_n$. Expanzné pravidlá sú taktiež rovnako tvarované ako v~$PPD_n$, avšak veľkosť \textit{k}-tic v~pravidlách musí byť práve \textit{n}. Inými slovami, počet prepísaných nevstupných symbolov musí byť rovný hĺbke automatu.

\img[TPPDAMove][Demonštrácia zmeny zásobníku pre pravidlo $s(A, B, B, G) \xrightarrow{} s(A, AC, B, \epsilon)$.][img:tppdaMove][][0.8]

Obr. \ref{img:tppdaMove} prezentuje, ako vplýva expanzné pravidlo na zásobník. Z~obrázku je možné vyčítať, že prvý nevstupný symbol \textit{A} je prepísaný sám na seba, tak isto ako aj tretí nevstupný symbol \textit{B}. Druhý nevstupný symbol je prepísaný na \textit{AC}, vďaka čomu mení hĺbku tretieho nevstupného symbolu z~\textit{3} na \textit{4}. Posledný nevstupný symbol s~indexom \textit{4} je prepísaný na prázdny reťazec, čo spôsobí, že ostatné hlbšie symboly nie sú posunuté hlbšie. Zároveň na základe indexu posledného nevstupného symbolu je možné určiť, že sa jedná o~pravidlo automatu s~hĺbkou \textit{4}.

\hfill

\noindent
Formálne sú pravidlá $TPPD_n$ v jednom z týchto dvoch tvarov:
\begin{enumerate}
    \item $aqa \xrightarrow{} q$\textit{, kde q} $\in Q, a \in \Sigma$
    \item $p(A_1, A_2, \dots , A_n) \xrightarrow{} q(\alpha_1, \alpha_2, \dots, \alpha_n)$\textit{, kde p,q}  $\in Q, \forall k \in \mathbb{N}; k \leq n, A_k \in \Gamma \setminus (\Sigma \cup  \{ \# \}), \alpha_k \in (\Gamma \setminus \{\#\})^*$
\end{enumerate}

\begin{definition}
    Násobný paralelný hlboký zásobníkový automat $(TPPD_n)$ je usporiadaná sedmica ${}_{n}M = (Q, \Sigma, \Gamma, R, s, \Omega, F)$, kde

    \begin{itemize}
        \item Q je neprázdna konečná množina stavov,
        \item $\Sigma$ je vstupná abeceda,
        \item $\Gamma$ je konečná množina zásobníkových symbolov nazývaná zásobníková abeceda, kde $\Sigma \subseteq \Gamma$ a~znak $\# \in (\Gamma \setminus \Sigma) $, znak \# je špeciálny pomocný symbol označujúci dno zásobníka,
        \item R je konečná množina pravidiel,
        \item s je počiatočný stav, $s \in Q$,
        \item $\Omega$ je počiatočné zásobníkové slovo, $\Omega \in ((\Gamma \setminus \Sigma) \setminus \{\#\})^i$, kde $i \in \mathbb{N}^+; i \geq n$,
        \item F je konečná množina koncových stavov, F $\subseteq Q$.
    \end{itemize}
\end{definition}

\conf{} $ \chi \in Q \times \Sigma^* \times (\Gamma \setminus \{\#\})^*\{\#\})$

\move{} Nech $n$ označuje hĺbku $TPPD_n$ a~$x, y \in \chi$ sú dve konfigurácie daného $TPPD_n$, potom prechod je definovaný takto:
\begin{itemize}
    \item Automat vykoná vybratie a~prejde z~$x$ do $y$, pokiaľ $x = (q, au, az), y = (q, u, z)$ a~zároveň pravidlo $aqa \xrightarrow{} q \in R$ , kde $q \in Q, a \in \Sigma, u \in \Sigma^*, z \in \Gamma^*$. Zapíše sa ako \pop{x}{y}.
    \item Automat vykoná expanziu a~prejde z~$x$ do $y$, pokiaľ $x = (p, w, a_1A_1a_2A_2\dots a_nA_nz), \\ y = (q, w, a_1\alpha_1a_2\alpha_2\dots a_n\alpha_nz)$ a~zároveň $p(A_1, A_2, \dots,A_n) \xrightarrow{} q(\alpha_1, \alpha_2, \dots, \alpha_n) \in R$, kde $p,q \in Q, \forall j \in \mathbb{N}; 1 \leq j \leq n \land\, w, a_j \in \Sigma^*, A_j \in \Gamma \land\, \alpha_j, z \in \Gamma^*$. Zapíše sa ako \expand{x}{y}.
\end{itemize}

\noindent
Nech ${}_nM$ je $TPPD_n$ a nech $\Xi$ je množina všetkých konfigurácií ${}_nM$. Relácia prechodu $\Rightarrow$ je potom definovaná takto:
\begin{align}
    (x \Rightarrow y) &\quad \Leftrightarrow \quad (\popM{x}{y} \lor \; \expandM{x}{y}), \nonumber
\end{align}
\noindent
kde  $x,y \in \Xi$.

Nech \moveClosure \, je tranzitívny a reflexívny uzáver relácie $\Rightarrow$ definovanej nad $\Xi$.

\hfill

\acceptedL{} Nech ${}_nM$ je $TPPD_n$, potom jazyk prijímaný týmto automatom $L({}_nM)$ je definovaný takto:
\begin{align}
    L({}_nM) = \{w; w \in \Sigma^*, \moveClosureM{(s, w, \Omega\#)}{(f, \epsilon, \#)}\}, \nonumber
\end{align}

\noindent
kde $f \in F$.

\hfill

\exe{} Demonštrácia prijatia slova $w = aaabbbccc$, ktoré patrí do jazyka $L = \{ a^nb^nc^n; \\ \forall n \in \mathbb{N}^+\}$, automatom typu $TPPD_n$.

\hfill

\noindent
${}_3M = (\{s\}, \{a, b, c\}, \{a, b, c, S, \#\}, R, s, \Omega, \{s\})$, kde $\Omega = SSS$ a~$R$ sú pravidlá:
\begin{enumerate}
    \item $s(S, S, S) \xrightarrow{} s(a, b, c)$
    \item $s(S, S, S) \xrightarrow{} s(aS, Sb, Sc)$  
\end{enumerate}

Automat ${}_3M$ pomocou svojho 2. pravidla začne paralelne generovať po jednom slová \textit{aS}, \textit{Sb}~a~\textit{Sc}, vďaka čomu po každom kroku je počet symbolov \textit{a}, \textit{b}~a~\textit{c} rovnaký. Generovanie slov pokračuje, dokým nie sú počty výskytov každého symbolu rovné počtom výskytov vo vstupnom reťazci mínus jedna. Nakoniec sú nevstupné symboly prepísané naraz na posledné symboly \textit{a}, \textit{b}~a~\textit{c}.

\noindent
Prijatie slova $w$ vyzerá takto:

\begin{alignat*}{2}
    (s, aaabbbccc, SSS\#) &\quad \expandM{}{} \quad (s, aaabbcc, aSSbSc\#) \; && [2] \nonumber \\
    &\quad \popM{}{} \quad (s, aabbbccc, SSbSc\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (s, aabbbccc, aSSbbScc\#) \; && [2] \nonumber \\
    &\quad \popM{}{} \quad (s, abbbccc, SSbbScc\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (s, abbbccc, abbbccc\#) \; && [1] \nonumber \\
    &\quad \popM{}{} \quad (s, bbbccc, bbbccc\#) \nonumber \; && \\
    &\quad \popM{}{} \quad (s, bbccc, bbccc\#)  \nonumber \; && \\
    &\quad \popM{}{} \quad (s, bccc, bccc\#)  \nonumber \; && \\ 
    &\quad \popM{}{} \quad (s, ccc, ccc\#) \nonumber \; && \\
    &\quad \popM{}{} \quad (s, cc, cc\#) \nonumber \; && \\ 
    &\quad \popM{}{} \quad (s, c, c\#) \nonumber \; && \\ 
    &\quad \popM{}{} \quad (s, \epsilon, \#) \; &&  \nonumber 
\end{alignat*}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         Simulácia TPPD_n pomocou PD_n
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{Simulácia násobného paralelného hlbokého zásobníkového automatu hlbokým zásobníkovým automatom}

Idea za simuláciou je, že nevstupné symboly, ktoré by sa mali paralelne nahradiť, sú zamieňané postupne. Rovnako ako pri prevode $PPD_n$ na $PD_n$. Pretože pri nahradzovaní nevstupných symbolov je možné ich nahradiť ďalšími viacerými nevstupnými symbolmi, je nutné ich nahrádzať od toho najhlbšie uloženého v~zásobníku. 

Vzhľadom na to, že $TPPD_n$ vyžaduje nahradenie práve \textit{n} nevstupných symbolov, je nutné, aby $PD_n$, ktorý ho má simulovať na začiatku svojho pôsobenia najskôr vytvoril \textit{n} počiatočných symbolov automatu $TPPD_n$. Definícia $PD_n$ hovorí, že automat začína s~práve jedným počiatočným symbolom. Z~toho vyplýva, že nový $PD_n$ musí v~rámci zásobníkovej abecedy mať počiatočný symbol, z~ktorého bude počiatočné zásobníkové slovo vygenerované. Pre vygenerovanie slova je ale nutné pridať aj špecifické \myuv{počiatočné} pravidlo, ktoré práve počiatočný symbol nahradí za počiatočné slovo. Toto pravidlo sa ale musí použiť práve jeden krát počas chodu automatu, a~to práve na začiatku jeho chodu.

Algoritmus \ref{alg:TPPD_to_PD} vyžaduje, aby tento počiatočný symbol nepatril do pôvodnej zásobníkovej abecedy. Táto požiadavka zabezpečí, že počiatočné pravidlo bude určite použité práve raz práve na začiatku práce automatu.

\begin{algorithm}\label{alg:TPPD_to_PD}
    \caption{\textsc{Prevod $TPPD_n$ na $PD_n$}}
    \SetNlSty{}{}{:}
    \KwIn{$TPPD_n \; {}_nM = (Q, \Sigma, \Gamma_1, R_1, s, \Omega, F)$} 
    \KwOut{$ PD_n \; {}_nN = (Q, \Sigma, \Gamma_2, R_2, s, S, F)$}
    \Indp \Indpp
    \BlankLine 
    $\Gamma_2 = \Gamma_1 \cup \{S; S \notin \Gamma_1\}$ \label{step:TPPD_to_PD_1} \\
    $R_2 = \{1sS \xrightarrow{} s\Omega \}$ \label{step:TPPD_to_PD_2} \\
    $R_2 = R_2 \cup \{r = apa \xrightarrow{} p; r \in R_1\}$ \label{step:TPPD_to_PD_3} \\
    $R_{tmp} = R_1 \setminus R_2 $ \label{step:TPPD_to_PD_4} \\ 
    \While {$R_{tmp} \ne \emptyset$} { \label{step:TPPD_to_PD_5}
        extract a~rule $p(A_1, A_2, \dots, A_n) \xrightarrow{} q(\alpha_1, \alpha_2, \dots, \alpha_n)$ from $R_{tmp}$ to $r$ \label{step:TPPD_to_PD_6} \\
        $R_2 = R_2 \cup \{kqA_k \xrightarrow{} q\alpha_k; \forall k \in \mathbb{N}; 1 \leq k < n \land q, A_k, \alpha_k \in r\}$ \label{step:TPPD_to_PD_7} \\
        $R_2 = R_2 \cup \{npA_n \xrightarrow{} q\alpha_n; p, q, A_n, \alpha_n \in r\}$ \label{step:TPPD_to_PD_8} \\
    }
    \KwRet{${}_nN = (Q, \Sigma, \Gamma_2, R_2, s, S, F)$} \label{step:TPPD_to_PD_10}
\end{algorithm}

\hfill

\simul{} Nech ${}_nM = (Q, \Sigma, \Gamma_1, R_1, s, \Omega, F)$ je $TPPD_n$ a~${}_nN = (Q, \Sigma, \Gamma_2, R_2, s, S, F)$ označuje $PD_n$, ktorý má simulovať ${}_nM$. Potom ${}_nN$ je možné vytvoriť Algoritmom \ref{alg:TPPD_to_PD}. Automat ${}_nN$ bude simulovať ${}_nM$ takto:

\begin{enumerate}
    \item Prvý vykonaný krok ${}_nN$ bude použitie pravidla vytvoreného v kroku \ref{step:TPPD_to_PD_2} Algoritmu \ref{alg:TPPD_to_PD}.
    \item Ak by ${}_nM$ vykonal vybratie, tak ${}_nN$ taktiež vykoná vybratie.
    \item Ak by ${}_nM$ skončil úspešne, tak ${}_nN$ taktiež skončí úspešne.
    \item Ak by ${}_nM$ skončil neúspešne, tak ${}_nN$ taktiež skončí neúspešne.
    \item Ak by ${}_nM$ vykonal expanziu pomocou nejakého pravidla $r \in R_1$, tak ${}_nN$ vykoná postupne všetky pravidlá $r' = kpA_k \xrightarrow{} q\alpha_k \in R_2$, ktoré boli vytvorené v krokoch \ref{step:TPPD_to_PD_7} a~\ref{step:TPPD_to_PD_8} Algoritmu \ref{alg:TPPD_to_PD} pre pravidlo \textit{r} v zostupnom poradí vzhľadom na \textit{k}.
\end{enumerate}


\begin{lemma} 
    \label{lemma:TPPD_to_PD}
    Algoritmus \ref{alg:TPPD_to_PD} pre prevod $TPPD_n$ na $PD_n$ je správny. 
\end{lemma}

\subproof{Vety \ref{lemma:TPPD_to_PD}}{
    V~krokoch \ref{step:TPPD_to_PD_1} a \ref{step:TPPD_to_PD_2} algoritmu je zabezpečený spôsob, ktorým sa automat dokáže dostať do počiatočného stavu vyhovujúcemu automatu $TPPD_n$. Vďaka tomu môže podľa správnosti vykonávať sadu pod-pravidiel pre každé paralelné pravidlo. Algoritmus vytvára pre každé expanzné pravidlo práve $n$~pod-pravidiel, kde \textit{n}~je maximálna hĺbka prístupu do zásobníku. To znamená, že pokiaľ $PD_n$ úspešne vykoná všetky pod-pravidlá, ktoré boli vytvorené pre nejaké n-ticové paralelné pravidlo, tak vzniknuté slovo na zásobníku bude rovnaké ako slovo vytvorené $TPPD_n$. Pokiaľ $PD_n$ postupuje tak, že najskôr prepíše nevstupný symbol, ktorý sa nachádza v~hĺbke \textit{n}, tak hĺbka nevstupných symbolov v~menšej hĺbke sa nezmení. Vďaka tomuto $PD_n$ je schopný pristúpiť na nevstupný symbol potrebný pre akékoľvek ďalšie pod-pravidlo. Preto pre simuláciu paralelného prístupu stačí, keď bude automat vykonávať pod-pravidlá v~poradí od najhlbšie zasahujúceho až po to, ktoré pracuje s~prvým nevstupným symbolom. Stav automatu môže byť zmenený kedykoľvek pri vykonávaní pod-pravidiel, ale ostatné pod-pravidlá musia byť na toto \uv{pripravené}. Algoritmus stav mení pri nahradzovaní najhlbšieho nevstupného symbolu a~zároveň zabezpečuje, že ďalšie pod-pravidlá pre dané pravidlo pracujú s~cieľovým stavom a~nemenia ho.
}

\hfill

\noindent
\exe{} Demonštrácia prevodu automatu ${}_2M$ typu $TPPD_n$ na automat ${}_2N$ typu $PD_n$ pomocou Algoritmu \ref{alg:TPPD_to_PD}. Jazyk prijímaný automatom ${}_2M$ je jazyk $L({}_2M)$, ktorý je definovaný ako $L({}_2M) = \{a^ib^jc^k; \forall i, j, k \in \mathbb{N}_0^+; i \geq j \geq k\}$. Číslo vykonaného kroku algoritmu je znázornené v~hranatých zátvorkách.

\hfill

\noindent ${}_2M =  (\{s\}, \{a, b, c\}, \{a, b, c, S, \#\}, R_1, s, SS, \{s\})$, kde $R_1$ sú pravidlá: 
\begin{itemize}
    \item $s(S, S) \xrightarrow{} s(\epsilon, \epsilon)$ 
    \item $s(S, S) \xrightarrow{} s(aS, bS)$ 
    \item $s(S, S) \xrightarrow{} s(aS, bSc)$ 
    \item $s(S, S) \xrightarrow{} s(aS, S)$ 
\end{itemize}

\construct{$PD_n$}
\begin{enumerate}
    \item $\Gamma_2 = \{a, b, c, S, \#\} \cup \{ S_2 \}$ \hfill [\ref{step:TPPD_to_PD_1}]
    \item $R_2 = \{1sS_2 \xrightarrow{} sSS\}$ \hfill [\ref{step:TPPD_to_PD_2}]
    \item $R_2 = R_2 \cup \{asa \xrightarrow{} s, bsb \xrightarrow{} s, csc \xrightarrow{} s\}$ \hfill [\ref{step:TPPD_to_PD_3}]
    \item $R = \{s(S, S) \xrightarrow{} s(\epsilon, \epsilon), s(S, S) \xrightarrow{} s(aS, bS), s(S, S) \xrightarrow{} s(aS, bSc), \\ s(S, S) \xrightarrow{} s(aS, S)\}$  \hfill [\ref{step:TPPD_to_PD_4}]
    
    \item $R \neq \emptyset $ \hfill [\ref{step:TPPD_to_PD_5}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(S, S) \xrightarrow{} s(\epsilon, \epsilon) \land R = \{s(S, S) \xrightarrow{} s(aS, bS), s(S, S) \xrightarrow{} s(aS, bSc), \\ s(S, S) \xrightarrow{} s(aS, S)\}$ \hfill [\ref{step:TPPD_to_PD_6}]
        \item $R_2 = R_2 \cup \{1sS \xrightarrow{} s\epsilon\}$ \hfill [\ref{step:TPPD_to_PD_7}]
        \item $R_2 = R_2 \cup \{2sS \xrightarrow{} s\epsilon \}$ \hfill [\ref{step:TPPD_to_PD_8}]
    \end{enumerate}

    \item $R \neq \emptyset $ \hfill [\ref{step:TPPD_to_PD_5}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(S, S) \xrightarrow{} s(aS, bS) \land R = \{s(S, S) \xrightarrow{} s(aS, bSc), s(S, S) \xrightarrow{} s(aS, S)\}$ \hfill [\ref{step:TPPD_to_PD_6}]
        \item $R_2 = R_2 \cup \{1sS \xrightarrow{} saS\}$ \hfill [\ref{step:TPPD_to_PD_7}]
        \item $R_2 = R_2 \cup \{2sS \xrightarrow{} sbS \}$ \hfill [\ref{step:TPPD_to_PD_8}]
    \end{enumerate}

    \item $R \neq \emptyset $ \hfill [\ref{step:TPPD_to_PD_5}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(S, S) \xrightarrow{} s(aS, bSc) \land R = \{s(S, S) \xrightarrow{} s(aS, S)\}$ \hfill [\ref{step:TPPD_to_PD_6}]
        \item $R_2 = R_2 \cup \{1sS \xrightarrow{} saS\}$ \hfill [\ref{step:TPPD_to_PD_7}]
        \item $R_2 = R_2 \cup \{2sS \xrightarrow{} sbSc\}$ \hfill [\ref{step:TPPD_to_PD_8}]
    \end{enumerate}

    \item $R \neq \emptyset $ \hfill [\ref{step:TPPD_to_PD_5}]
    \begin{enumerate}[label*=\arabic*.]
        \item $r = s(S, S) \xrightarrow{} s(aS, S) \land R = \emptyset$ \hfill [\ref{step:TPPD_to_PD_6}]
        \item $R_2 = R_2 \cup \{1sS \xrightarrow{} saS\}$ \hfill [\ref{step:TPPD_to_PD_7}]
        \item $R_2 = R_2 \cup \{2sS \xrightarrow{} sS\}$ \hfill [\ref{step:TPPD_to_PD_8}]
    \end{enumerate}

    \item $R == \emptyset $ \hfill [\ref{step:TPPD_to_PD_5}]
    \item vráť ${}_2N = (\{s\}, \{a, b, c\}, \{a, b, c, S, S_2, \#\}, R_2, s, S_2, \{s\})$, kde $R_2 = \{asa  \xrightarrow{} s, \\ bsb \xrightarrow{} s, csc \xrightarrow{} s, 1sS_2 \xrightarrow{} sSS, 1sS \xrightarrow{} s\epsilon, 2sS \xrightarrow{} s\epsilon, 1sS \xrightarrow{} saS, 2sS \xrightarrow{} sbS, \\ 2sS \xrightarrow{} sbSc, 2sS \xrightarrow{} sS\}$ \hfill [\ref{step:TPPD_to_PD_10}]
\end{enumerate}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         Simulácia PD_n pomocou TPPD_n
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{Simulácia hlbokého zásobníkového automatu násobným paralelným hlbokým zásobníkovým automatom}

Simulovanie spočíva v~tom, že jeden prepis nevstupného symbolu $PD_n$ v~hĺbke \textit{k} bude vykonaný tak, že $TPPD_n$ prepíše všetky nevstupné symboly na seba sama, okrem symbolu v~hĺbke \textit{k}. Symbol v~hĺbke \textit{k} bude expandovaný podľa daného kroku $PD_n$. 

\begin{algorithm}\label{alg:PD_to_TPPD}
    \caption{\textsc{Prevod $PD_n$ na $TPPD_n$}}
    \SetNlSty{}{}{:}
    \KwIn{ $PD_n \; {}_nM = (Q, \Sigma, \Gamma_1, R_1, s, S_1, F)$} 
    \KwOut{$TPPD_n \; {}_nN = (Q, \Sigma, \Gamma_2, R_2, s, \Omega, F)$}
    \Indp \Indpp
    \BlankLine 
    $\Gamma_2 = \Gamma_1 \cup \{X; X \notin \Gamma_1\}$  \label{step:PD_to_TPPD_1} \\
    $\Omega = S_1\{X\}^n$  \label{step:PD_to_TPPD_2} \\
    $R_2 = \{r = apa \xrightarrow{} p; r \in R_1\}$  \label{step:PD_to_TPPD_3} \\
    $R_2~=~R_2~\cup~\{p(A_1, A_2, \dots, A_k, \dots, A_n)~\xrightarrow{}~q(\alpha_1, \alpha_2, \dots, \alpha_k \dots, \alpha_n);  \newline r~=~kpA_k~\xrightarrow{}~q\alpha_k \in R_1, \forall i \in \mathbb{N}, \forall A_i \in \Gamma_2; i \leq n, i \neq k, \alpha_i = A_i\}$ \label{step:PD_to_TPPD_4} \\
    $R_2 = R_2 \cup \{p(X_1, X_2, \dots, X_n) \xrightarrow{} p (\epsilon_1, \epsilon_2, \dots, \epsilon_n); p \in Q, X_i$ \textit{je nevstupný symbol} $X $ na i-tej pozícii a~$\epsilon_i $ \textit{je prázdny reťazec na i-tej pozícii, kde} $0 < i \leq n \}$  \label{step:PD_to_TPPD_5} \\
    \KwRet{${}_nN = (Q, \Sigma, \Gamma_2, R_2, s, \Omega, F)$}  \label{step:PD_to_TPPD_6}
\end{algorithm}

\hfill

\simul{} Nech ${}_nM = (Q, \Sigma, \Gamma_1, R_1, s, S_1, F)$ je $PD_n$ a nech ${}_nN = (Q, \Sigma, \Gamma_2, R_2, s, \Omega, F)$ označuje $TPPD_n$, ktorý má simulovať ${}_nM$. Potom ${}_nN$ je možné vytvoriť pomocou Algoritmu \ref{alg:PD_to_TPPD}. Vytvorený automat ${}_nN$ potom simuluje automat ${}_nM$ takto:

\begin{enumerate}
    \item Ak by ${}_nM$ vykonal vybratie, tak ${}_nN$ taktiež vykoná vybratie.
    \item Ak by ${}_nM$ skončil úspešne, tak ${}_nN$ taktiež skončí úspešne.
    \item Ak by ${}_nM$ skončil neúspešne, tak ${}_nN$ taktiež skončí neúspešne.
    \item Ak by ${}_nM$ vykonal expanziu pomocou nejakého pravidla $r \in R_1$, tak ${}_nN$ vykoná pravidlo $r' \in R_2$, ktoré bolo vytvorené v kroku \ref{step:PD_to_TPPD_4} Algoritmu \ref{alg:PD_to_TPPD} pre pravidlo \textit{r}.
    \item Ak všetky dostupné nevstupné symboly na zásobníku ${}_nN$ sú pomocné symboly \textit{X}, tak ${}_nN$ vykoná pravidlo vytvorené v~kroku \ref{step:PD_to_TPPD_5} Algoritmu \ref{alg:PD_to_TPPD}.
\end{enumerate}

\begin{lemma} 
    \label{lemma:PD_to_TPPD}
    Algoritmus \ref{alg:PD_to_TPPD} pre prevod $PD_n$ na $TPPD_n$ je správny. 
\end{lemma}

\subproof{Vety \ref{lemma:PD_to_TPPD}}{
    Algoritmus v~\ref{step:PD_to_TPPD_2}. kroku vytvorí počiatočné zásobníkové slovo, ktorého dĺžka je rovná maximálnej hĺbke prístupu $n$ plus jedna. Vďaka tomuto je zabezpečené, že automat má v~zásobníku uložených aspoň \textit{n} nevstupných symbolov. Tieto symboly môžu byť prepísané iba na samé seba. Pre každé pôvodné pravidlo sa v~kroku \ref{step:PD_to_TPPD_4} vytvorí sada nových pravidiel. Pravidlá sú vytvorené tak, aby pre každú možnú správnu kombináciu usporiadania nevstupných symbolov na zásobníku existovalo aspoň jedno pravidlo. Tento krok vytvára teda pravidlá, ktoré prepisujú všetky nevstupné symboly na seba sama okrem symbolu, ktorý by mal byť prepísaný podľa pôvodného pravidla $PD_n$. Vďaka prepisovaniu symbolov na seba sama je zabezpečená správna hĺbka ostatných symbolov, ako aj správny počet nevstupných symbolov na zásobníku. Automat je schopný pridávať aj odoberať nevstupné symboly podľa potreby. Akonáhle odoberie posledný nevstupný symbol nerovný pomocnému symbolu \textit{X} je zrejmé, že na zásobníku sa nachádza iba \textit{n} výplnkových nevstupných symbolov, ktoré je možno potom v~jednom kroku vymazať.
}

\hfill

\exe{} Demonštrácia prevodu automatu ${}_2M$ typu $PD_n$ na automat ${}_2N$ typu $TPPD_n$ pomocou Algoritmu \ref{alg:PD_to_TPPD}. Jazyk $L({}_2M)$ je definovaný ako $L({}_2M) = \{a^nb^nc^n; \forall n \in \mathbb{N}^+\}$. Číslo vykonaného kroku algoritmu je znázornené v~hranatých zátvorkách.


\hfill

\noindent ${}_2M =  (\{s, q, p, f\}, \{a, b, c\}, \{a, b, c, S, A, \#\}, R_1, s, S, \{f\})$, kde $R_1$ sú pravidlá: 
\begin{itemize}
    \item $1sS \xrightarrow{} qAA$ 
    \item $1qA \xrightarrow{} paAb$ 
    \item $1qA \xrightarrow{} fab$ 
    \item $2pA \xrightarrow{} qAc$ 
    \item $1fA \xrightarrow{} fc$
\end{itemize}

\construct{$TPPD_n$}
\begin{enumerate}
    \item $\Gamma_2 = \{a, b, c, S, A, \#\} \cup \{ X \}$ \hfill [\ref{step:PD_to_TPPD_1}]
    \item $\Omega = SXX$ \hfill [\ref{step:PD_to_TPPD_2}]
    \item $R_2 = \{asa \xrightarrow{} s, bsb \xrightarrow{} s, csc \xrightarrow{} s\}$ \hfill [\ref{step:PD_to_TPPD_3}]
    \item $R_2 = R_2 \cup \{s(S, X) \xrightarrow{} q(AA, X), s(S, S) \xrightarrow{} q(AA, S), s(S, A) \xrightarrow{} q(AA, A)\}$  \hfill [\ref{step:PD_to_TPPD_4}~pre~pravidlo~$1sS \xrightarrow{} qAA$]
    \item $R = R_2 \cup \{q(A, X) \xrightarrow{} p(aAb, X), q(A, S) \xrightarrow{} p(aAb, S), q(A, A) \xrightarrow{} p(aAb, A)\}$  \hfill [\ref{step:PD_to_TPPD_4} pre pravidlo $1qA \xrightarrow{} paAb$ ]
    \item $R = R_2 \cup \{q(A, X) \xrightarrow{} f(ab, X), q(A, S) \xrightarrow{} f(ab, S), q(A, A) \xrightarrow{} f(ab, A)\}$  \hfill [\ref{step:PD_to_TPPD_4} pre pravidlo $1qA \xrightarrow{} fab$ ]
    \item $R = R_2 \cup \{p(X, A) \xrightarrow{} q(X, Ac), p(S, A) \xrightarrow{} q(S, Ac), p(A, A) \xrightarrow{} q(A, Ac)\}$  \hfill [\ref{step:PD_to_TPPD_4} pre pravidlo $2pA \xrightarrow{} qAc$ ]
    \item $R = R_2 \cup \{f(A, X) \xrightarrow{} f(c, X), f(A, S) \xrightarrow{} f(c, S), f(A, A) \xrightarrow{} f(c, A)\}$  \hfill [\ref{step:PD_to_TPPD_4} pre pravidlo $1fA \xrightarrow{} fc$ ]

    \item $ R_2 = R_2 \cup \{s(X, X) \xrightarrow{} s(\epsilon, \epsilon), p(X, X) \xrightarrow{} p(\epsilon, \epsilon), q(X, X) \xrightarrow{} q(\epsilon, \epsilon), \\ f(X, X) \xrightarrow{} f(\epsilon, \epsilon)\}$ \hfill [\ref{step:PD_to_TPPD_5}]
    \item vráť ${}_2N = (\{s, q, p, f\}, \{a, b, c\}, \{a, b, c, S, A, X, \#\}, R_2, s, SXX, \{f\})$, $\\$  kde $R_2 = \{asa  \xrightarrow{} s, bsb \xrightarrow{} s, csc \xrightarrow{} s, s(S, X) \xrightarrow{} q(AA, X), s(S, S) \xrightarrow{} q(AA, S), \\ s(S, A) \xrightarrow{} q(AA, A), q(A, X) \xrightarrow{} p(aAb, X), q(A, S) \xrightarrow{} p(aAb, S), \\ q(A, A) \xrightarrow{} p(aAb, A), q(A, X) \xrightarrow{}  f(ab, X), q(A, S) \xrightarrow{} f(ab, S), q(A, A) \xrightarrow{} f(ab, A), \\ p(X, A) \xrightarrow{} q(X, Ac), p(S, A) \xrightarrow{} q(S, Ac), p(A, A) \xrightarrow{} q(A, Ac), f(A, X) \xrightarrow{} f(c, X), \\ f(A, S) \xrightarrow{} f(c, S), f(A, A) \xrightarrow{} f(c, A), s(X, X) \xrightarrow{} s(\epsilon, \epsilon), p(X, X) \xrightarrow{} p(\epsilon, \epsilon), \\ q(X, X) \xrightarrow{} q(\epsilon, \epsilon), f(X, X) \xrightarrow{} f(\epsilon, \epsilon) \}$ \hfill [\ref{step:PD_to_TPPD_6}]
\end{enumerate}

\section{Vyjadrovacia sila}
\begin{lemma} 
    \label{lemma:str_TPPD_to_PD}
    Pre každý násobný paralelný hlboký zásobníkový automat ${}_nM$ existuje hlboký zásobníkový automat ${}_nM'$, ktorý prijíma rovnaký jazyk. Platí teda $L({}_nM) = L({{}_nM'})$.
\end{lemma}

\proof{Vety \ref{lemma:str_TPPD_to_PD}}{
    Nech ${}_nM$ je akýkoľvek násobný paralelný hlboký zásobníkový automat, potom na základe Vety \ref{lemma:TPPD_to_PD} je možné vytvoriť automat ${}_nM'$ Algoritmom \ref{alg:TPPD_to_PD}. Pretože Veta \ref{lemma:TPPD_to_PD} je správna, tak automat je korektným hlbokým zásobníkovým automatom, ktorý prijíma jazyk $L({}_nM)$. Potom platí $L({}_nM) = L({{}_nM'})$.
}

\begin{lemma} 
    \label{lemma:str_PD_to_TPPD}
    Pre každý hlboký zásobníkový automat ${}_nM$ existuje násobný paralelný hlboký zásobníkový automat ${}_nM'$, ktorý prijíma rovnaký jazyk. Platí teda $L({}_nM) = L({{}_nM'})$.
\end{lemma}

\proof{Vety \ref{lemma:str_PD_to_TPPD}}{
    Nech ${}_nM$ je akýkoľvek hlboký zásobníkový automat, potom na základe Vety \ref{lemma:PD_to_TPPD} je možné vytvoriť automat ${}_nM'$ Algoritmom \ref{alg:PD_to_TPPD}. Pretože Veta \ref{lemma:PD_to_TPPD} je správna, tak automat je korektným násobným paralelným hlbokým zásobníkovým automatom, ktorý prijíma jazyk $L({}_nM)$. Potom platí $L({}_nM) = L({{}_nM'})$.
}

\begin{lemma} 
    \label{lemma:str_TPPD_eq_PD}
    Rodina jazykov generovaných násobným paralelným hlbokým zásobníkovým automatom s~hĺbkou \textit{n} je ekvivalentná rodine jazykov generovaných hlbokým zásobníkovým automatom s~rovnakou hĺbkou. Platí $\textbf{TPPD}_\textbf{n} = \textbf{PD}_\textbf{n}$.
\end{lemma}

\proof{Vety \ref{lemma:str_TPPD_eq_PD}}{
    Dôsledok Vety \ref{lemma:str_TPPD_to_PD} a \ref{lemma:str_PD_to_TPPD}.
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         Využitie alternatívnych automatov
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Využitie alternatívnych automatov} 
\label{aplications}

Aby tvorba modelu dávala zmysel, musí byť možné výsledný model niekde aplikovať. Toto je veľmi dôležité, pretože model bez využitia nemá význam vytvárať a~ani dokazovať jeho vlastnosti. V~tejto práci sú predstavené dve alternatívne verzie hlbokých zásobníkových automatov, tieto verzie majú rovnakú vyjadrovaciu silu ako obyčajné hlboké zásobníkové automaty. Vďaka tejto skutočnosti je možné povedať, že ich aplikácie sú rovnaké ako hlbokých zásobníkových automatov. To znamená že majú veľké využitie napríklad v~odvetví spracovania prirodzeného jazyka, pri oprave pravopisu alebo syntéze textu na reč.

Automaty je možné využiť aj v~bioinformatike. Výhodou predstavených paralelných verzií je možné jednoduché generovanie viacerých reťazcov na viacerých miestach bez zbytočnej zmeny stavu. Paralelné generovanie privádza jednoduchú myšlienku akého si \myuv{kopírovania} reťazca na viacero miest, vďaka čomu je možné nachádzať rôzne opakovania. Rovnosť reťazcov na viacerých rôznych miestach je možné označiť ako nejakú \myuv{reláciu}, ktorá napríklad môže hovoriť, že dva pod-reťazce sú v~relácii práve vtedy, keď jeden pod-reťazec sa rovná druhému. Takúto reláciu je potom možné nahradiť ďalšími podobnými reláciami, čím vzniká veľké množstvo \uv{nových} aplikácií predstavených alternatívnych hlbokých zásobníkových automatov. Jednou z~takýchto relácií môže byť nejaká funkcia, ktorá jednotlivé symboly prvého pod-reťazca  transformuje na symboly druhého pod-reťazca. Takto je potom možné zistiť, či reťazec obsahuje symboly, ktoré je možné dať do funkcie a~symboly, ktoré sa nachádzajú za prvotnými symbolmi a~ktoré sú výsledkom transformácie prvotných symbolov funkciou. Prezentované skutočnosti je možné využiť napríklad v~bioinformatike pri rozpoznávaní \textit{DNA opakovaní} alebo pri hľadaní \textit{RNA pseudouzlov}.

\section{Základy genetiky a bioinformatiky}
Nasledujúci odstavec bol prevzatý zo študijných textov biológie pre žiakov prvého ročníka SZŠ Nymburg od Dagmary Sitnej a~Renaty Kůstovej \cite{genetika}.

Genetika je náuka o dedičnosti a premenlivosti organizmov. Dedičnosťou sa rozumie schopnosť organizmu predávať vlohy (genetické informácie, gény) z~generácie na generáciu a~zachovať tak stálosť, respektíve nemennosť rodov. Premenlivosť je tendencia organizmov sa meniť v~jednotlivostiach, čiže nebyť úplne rovnaký. Pre predávanie génov organizmy používajú, okrem iného, dve kyseliny. Prvou je \textit{kyselina deoxyribonukleová}, ktorá je hlavným prenášačom genetickej informácie. Označuje sa ako \textit{DNA} a~je v~nej zakódovaná genetická informácia. Druhou je \textit{ribonukleová kyselina}. Označuje sa \textit{RNA} a~je dôležitá pre kódovanie a~dekódovanie genetickej informácie. Základnou jednotkou oboch kyselín, ako aj všetkých ostatných nukleových kyselín, sú takzvané \textit{nukleotidy}. Nukleotidy sú tvorené bázami a~na základe danej bázy sú aj rozlišované. V~DNA a~RNA sú nukleotidy uložené v~tvare reťazca.  Poradie a~druhy nukleotidov v~reťazci tvorí genetickú informáciu, ktorá určuje celkové chovanie organizmu. Celý reťazec je možné rozdeliť na menšie reťazce, ktoré potom kódujú iba nejakú konkrétnu časť chovania. 

Nasledujúce dva odstavce sú zhrnutím a~interpretáciou textu knihy \textit{An Introduction to Genetic Analysis} \cite{dna_rna}.

DNA je biologická makromolekula v~podobe reťazca nukleotidov. Nukleotidy DNA sú vždy zložené z~cukru deoxyribózy, fosfátovej skupiny a~jednej zo štyroch nukleových báz. Informačnú funkciu majú práve bázy, ktoré sú pripojené na kostru. Týmito bázami sú adenín (\textit{A}), guanín (\textit{G}), cytozín (\textit{C}) a~tymín (\textit{T}). Takýto reťazec DNA sa väčšinou spája s~druhým reťazcom DNA tak, že vzniká známa dvojzávitnica. Na Obr. \ref{img:dnaRna} je prezentovaná DNA dvojzávitnica aj spolu s~jej nukleotidmy (vpravo).  Dvojzávitnica je spojená takzvanými vodíkovými mostíkmi. Tieto mostíky môžu byť práve 3 medzi guanínom a~cytozínom alebo dva medzi adenínom a~tymínom. To znamená, že guanín a~cytozín sú komplementárne a~adenín a~tymín sú taktiež komplementárne vzhľadom na spojenie medzi dvoma DNA reťazcami.


\begin{figure}[H]
    \centering
    \tmpframe{
        \includesvg[width=1\columnwidth]{Images/dnaRna}
    }
    \caption{Ukážka RNA a~DNA molekuly spolu s nukleotídovými bázami \cite{img_dna_rna}.}
    \label{img:dnaRna}
\end{figure}

RNA je rovnako ako DNA biologická makromolekula v~podobe reťazca nukleotidov. Nukleotidy RNA však nemôžu mať bázu tymínu, ale namiesto nej majú nukleovú bázu uracil (\textit{U}). Molekula RNA je vyobrazená na Obr. \ref{img:dnaRna} (vľavo). Reťazec RNA sa ale nezvykne spájať s~druhým reťazcom RNA do dvojzávitnice. Namiesto toho sa stáva, že sa RNA reťazec pospája do úplne iného útvaru s~inými RNA reťazcami alebo aj sám so sebou. Spájanie funguje na podobnom princípe ako u~DNA, pričom ale pri RNA sa spája guanín s~cytozínom a~adenín s~uracilom.

Bioinformatika je vedecká disciplína, ktorá se zaoberá metódami pre zhromažďovanie, analýzu a vizualizáciu rozsiahlych súborov biologických dát. Typické dáta spájané s~bioinformatikou sú napríklad sekvencie proteínov alebo nukleových kyselín. To je spôsobené tým, že reťazec DNA (ale aj RNA) je možné označiť za slovo z~jazyka tvoreného štyrmi symbolmi. Tieto symboly môžu byť pre jednoduchosť \textit{a}, \textit{g}, \textit{c}~a~\textit{t}~alebo v~prípade RNA  \textit{a}, \textit{g}, \textit{c}~a~\textit{u}. Tak isto je možné zakódovať aj dvojzávitnicu DNA, pričom ale počet symbolov sa zmení podľa toho, čo všetko je predmetom záujmu v~danej dvojzávitnici. Napríklad pokiaľ je zaujímavé iba poradie mostíkov v~reťazci, tak stačia dva symboly \textit{3}~a~\textit{2}, podľa počtu mostíkov v~spojení. 

Nejaký takýto jazyk je možné popísať formálne, a~to znamená, že je možné s~ním pracovať ako s~akýmkoľvek iným formálnym jazykom. Z~pohľadu automatov je potom možné vytvoriť automat, ktorý nejaký takýto jazyk prijíma. Vďaka tomu je potom možné pre akékoľvek slovo zložené z~abecedy patriacej do jazyka určiť, či patrí alebo naopak nepatrí do jazyka. Takéto rozhodnutie je dôležité pokiaľ daný jazyk modeluje nejakú vlastnosť DNA alebo RNA molekuly. V~takomto prípade prijatie slova automatom znamená, že slovo má danú vlastnosť, čím je možné určiť, že pozorovaná molekula má taktiež túto vlastnosť.

\section{DNA opakovanie}
Jednou zo zaujímavých vlastností DNA reťazca môže byť opakovanie nejakého pod-reťazca v~molekule. Príkladom, prečo je táto vlastnosť zaujímavá, je nestabilita DNA reťazca, ako píšu Hastings, Lupski, Rosenberg a~Ira \cite{dna_repetition_duplication}. Autori popisujú, že opakovanie v~DNA reťazci môže napríklad sťažiť zostavenie genetickej informácie, pretože tá sa tvorí tak, že sa DNA reťazec rozdelí na menšie reťazce. Z~menších reťazcov sa potom postupne skladá genetická informácia. Ak DNA obsahuje opakovania, môže to viesť ku duplikáciám, medzerám alebo k celkovému zlému zostaveniu informácie. Ďalším možným využitím je, ako píše pán Guy-Franck a~pán Pâques \cite{dna_repetition_mutation}, že pri štúdiu evolúcie druhov existujú zaujímavé opakujúce sa DNA sekvencie. Tieto sekvencie sa môžu pohybovať v~genetickej informácii a~môžu spôsobovať mutácie, čo vedie ku novým génom. Porovnávanie týchto sekvencií medzi rôznymi druhmi pomáha vedcom pochopiť evolučné vzťahy medzi druhmi.

Pre rozhodnutie, či molekula DNA obsahuje opakovanie, je nutné využiť model, ktorý je schopný generovania dvoch (alebo viacerých) rovnakých reťazcov na dvoch (alebo viacerých) rôznych miestach. Hlboké zásobníkové automaty toto narozdiel od jednoduchších obyčajných zásobníkových automatov dokážu. Nevýhodou môžu byť \myuv{zbytočné} prechody medzi stavmi v~automate. Tu preto môžu nastúpiť paralelné alebo násobné paralelné hlboké zásobníkové automaty, ktoré veľmi jednoducho a~elegantne riešia generovanie dvoch ale aj viacerých reťazcov v~jednom kroku.

\section{Hľadanie DNA opakovaní pomocou paralelného hlbokého zásobníkového automatu}
Využitie paralelného hlbokého automatu v~tejto problematike môže byť prezentované na príklade, kde sa predpokladá, že zaujímavý počet opakovaní je jedna. Ide teda o~problém, kedy je nutné určiť, či nejaká molekula DNA zakódovaná do reťazca patrí, či naopak nepatrí medzi DNA reťazce s~aspoň jedným opakovaním o~dĺžke väčšej ako 1. V~nasledujúcom príklade je prezentovaný $PPD_n$, ktorého úspešné skončenie a~prečítanie vstupného reťazca značí existenciu opakovania v~DNA reťazci. Príklad obsahuje daný automat $PPD_n$ a~demonštráciu prijatia slova, obsahujúceho opakovanie. Automat opakovanie reťazca o~dĺžke jedna, čiže opakovanie jedného nukleotidu nepovažuje za DNA opakovanie, a~teda reťazec obsahujúci iba takéto opakovanie nepatrí do jazyka automatu. 

Reťazec DNA je v príklade kódovaný abecedou $\Sigma = \{a, u, g, t\}$, kde jednotlivé prvky sú prvé písmená báz nukleotidov DNA.

\hfill

\exe{} Demonštrácia $PPD_n$ automatu hľadajúceho DNA opakovanie a~prijatie slova $w = agtccttgtcca$, ktoré patrí do jazyka $L$ nad množinou $\Sigma = \{a, g, c, t\}$, ktorý je definovaný ako $L = \{fvmvl; f, m, l, v \in \Sigma^*, |v| > 1\}$

\hfill

\noindent
${}_5M = (\{s, o, f\}, \{a, g, c, t\}, \{a, g, c, t, S, B, \#\}, R, s, S, \{f\})$, kde $R$~sú pravidlá:
\begin{enumerate}
    \item $s(S) \xrightarrow{} s(SSSSS)$
    \item $s(S) \xrightarrow{} s(aS) | s(gS) | s(cS) | s(tS)$  
    \item $s(S, S, S) \xrightarrow{} s(S, S, aS) | s(S, S, gS) | s(S, S, cS) | s(S, S, tS)$
    \item $s(S, S, S, S) \xrightarrow{} o(S, aS, S, aS) | o(S, gS, S, gS) | o(S, cS, S, cS) | o(S, tS, S, tS)$
    \item $o(S, S, S, S) \xrightarrow{} f(S, aS, S, aS) | f(S, gS, S, gS) | f(S, cS, S, cS) | f(S, tS, S, tS)$
    \item $f(S, S, S, S) \xrightarrow{} f(S, aS, S, aS) | f(S, gS, S, gS) | f(S, cS, S, cS) | f(S, tS, S, tS)$
    \item $f(S, S, S, S, S) \xrightarrow{} f(S, S, S, S, aS) | f(S, S, S, S, gS) | f(S, S, S, S, cS) | f(S, S, S, S, tS) | \\ f(\epsilon, \epsilon, \epsilon, \epsilon, \epsilon)$ 
\end{enumerate}

Automat ${}_5M$ pracuje tak, že je schopný pravidlom 6 vytvoriť prvú časť slova \textit{w}, označenú písmenom \textit{f}. Túto časť môže rovno čítať zo vstupnej pásky, pričom bude vyprázdňovať zásobník. Potom pravidlom 3 vygeneruje stred slova, označený ako \textit{m}. Použitím pravidla 4 automat vygeneruje v~jednom kroku prvý symbol pod-reťazca \textit{v}~a~aj jeho kópiu. Zmení svoj stav aby zabezpečil, že dĺžka pod-reťazca \textit{v}~je aspoň 1. Ďalej pokračuje pravidlom 5, ktoré generuje druhý symbol pod-reťazca a~jeho kópiu, čím sa docieli minimálna dĺžka pod-reťazca \textit{v}. Úlohou predposledného pravidla je generovanie ostatných symbolov pod-reťazca. Posledné pravidlo potom generuje buď poslednú časť slova \textit{l}~alebo, ak už sú na zásobníku správne pod-reťazce, tak zmaže nevstupné symboly zo zásobníku. Nakoniec automat postupne číta zbytok vstupu, a~vyprázdňuje zásobník. Celé prijatie slova \textit{w}~automatom je znázornené nižšie spolu so znázornením rodiny vykonaného pravidla pri každom kroku.

\hfill

\noindent
Prijatie slova $w$ vyzerá nasledovne:
\begin{alignat*}{2}
    (s, agtcccttgtccca, S\#) &\quad \expandM{}{} \quad (s, agtccttgtcca, SSSSS\#) \; && [5] \nonumber \\
    &\quad \expandM{}{} \quad (s, agtccttgtcca, aSSSSS\#) \; && [2] \nonumber \\
    &\quad \popM{}{} \quad (s, gtccttgtcca, SSSSS\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (s, gtccttgtcca, SStSSS\#) \; && [3] \nonumber \\
    &\quad \expandM{}{} \quad (s, gtccttgtcca, SSttSSS\#) \; && [3] \nonumber \\
    &\quad \expandM{}{} \quad (o, gtccttgtcca, SgSttSgSS\#) \; && [4] \nonumber \\
    &\quad \expandM{}{} \quad (f, gtccttgtcca, SgtSttSgtSS\#) \; && [5] \nonumber \\
    &\quad \expandM{}{} \quad (f, gtccttgtcca, SgtcSttSgtcSS\#) \; && [6] \nonumber \\
    &\quad \expandM{}{} \quad (f, gtccttgtcca, SgtccSttSgtccSS\#) \; && [6] \nonumber \\
    &\quad \expandM{}{} \quad (f, gtccttgtcca, SgtccSttSgtccSaS\#) \; && [7] \nonumber \\
    &\quad \expandM{}{} \quad (f, gtccttgtcca, gtccttgtcca\#) \; && [7] \nonumber \\
    &\quad \popM{}{} \quad (f, tccttgtcca, tccttgtcca\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, ccttgtcca, ccttgtcca\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, cttgtcca, cttgtcca\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, ttgtcca, ttgtcca\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, tgtcca, tgtcca\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, gtcca, gtcca\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, tcca, tcca\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, cca, cca\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, ca, ca\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, a, a\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, \epsilon, \#) \nonumber \; &&  
\end{alignat*}


\section{RNA pseudouzol}
Páni Staple a~Buther vo~svojom článku \cite{rna_pseudoknots_usage} píšu, že RNA pseudouzol je dôležitou vlastnosťou RNA, pretože pseudouzly vykonávajú mnoho rolí v~biológii. Jednou z~rolí je napríklad formovanie katalytických jadier rôznych ribozómov, formovanie samorezačných intrónov a~telomeráz. Tak ako aj u~DNA opakovaní, tak aj u~RNA pseudouzlov platí, že majú veľký význam pri študovaní evolúcie. V~článku pre ViennaRNA Package 2.0 \cite{rna_evolution}, sa píše, že dôvod významu pseudouzlov v~evolúcii je stabilizácia. Stabilizované RNA tak dokáže pracovať v~rôznorodom prostredí.

RNA pseudouzol vzniká vtedy, keď sa molekula RNA spojí sama zo sebou v~trojrozmernom priestore. Pre vznik RNA pseudouzlu musí reťazec obsahovať postupne štyri časti, ktoré sú spojené striedavo  (prvá je spojená s~treťou a~druhá so štvrtou). Jednoduchý pseudouzol je prezentovaný na Obr. \ref{img:pseudoknot}.

\img[pseudoknot][Jednoduchý RNA pseudouzol \cite{pseudoknot_img}.][img:pseudoknot][H][0.8]

Existenciu RNA pseudouzlu v~molekule je možné rozhodnúť iba silnejšími nástrojmi, ako sú základné zásobníkové automaty. Je to spôsobené tým, že je nutné generovať znaky prvej časti na jednom mieste, jej komplement na druhom mieste, pričom ale medzi týmito slovami je nutné generovať ďalšiu inú časť. Problém nastáva v~tom, že pre túto strednú časť je nutné generovať komplement tak, aby sa nachádzal až za komplementárnymi symbolmi prvej časti. Toto je ale možné modelovať pomocou $PPD_n$ alebo $TPPD_n$. 

\section{Hľadanie RNA pseudouzlu pomocou paralelného hlbokého zásobníkového automatu}
Pre demonštráciu využitia $PPD_n$ sa bude uvažovať, že je nutné vedieť zistiť, či molekula obsahuje iba jeden RNA pseudouzol. Pre zjednodušenie príkladu sa bude uvažovať iba pseudouzol, ktorý v~rámci jednotlivých spájaných častí neobsahuje nespojené nukleotidy. To znamená, že napríklad pseudouzol ukázaný na Obr. \ref{img:pseudoknot} by nebol prijatý týmto automatom. Avšak medzi jednotlivými časťami budú nespojené nukleotidy povolené, zároveň sú povolené aj pred pseudouzlom aj za pseudouzlom. Ďalej sa bude predpokladať, že každá časť sa skladá z~aspoň dvoch symbolov. Nasledujúci príklad demonštruje práve automat $PPD_n$ prijímajúci reťazce so~pseudozlom. Súčasťou príkladu je aj demonštrácia prijatia nejakého slova vyhovujúceho daným podmienkam. Príklad pracuje s~abecedou, ktorá kóduje RNA reťazce $\Sigma = \{a, u, g, c\}$, kde prvky abecedy sú nukleotidy označené ich prvými písmenami. Ďalej pracuje s~funkciou $f$, ktorá prevádza vstupný reťazec na reťazec, ktorý je komplementárny vzhľadom na možné spojenia medzi nukleotidmi a~je prevrátený. Funkcia $f$ je definovaná takto:

\hfill

$f(x): \Sigma^+ \times \Sigma^+  \left\{ 
\begin{array}{ll}
    a & \text{pre u} \\
    u & \text{pre a} \\
    c & \text{pre g} \\
    g & \text{pre c} \\
	f(w)f(v) & \text{pre } x = vw; v \in \Sigma, w \in \Sigma^+
\end{array}
\right.$

\hfill

\exe{} Demonštrácia $PPD_n$ automatu hľadajúceho RNA pseudouzol a~prijatie slova $w = gagcguccga$, ktoré patrí do jazyka, $L$ ktorý je definovaný: 

\hfill

$L = \{tdvxreyhz; t, d, v, x, r, d, z \in \Sigma^*, |d| = |e| > 1, |x| = |h| > 1, e = f(d), h = f(x)\}$

\hfill

\noindent

Automat $PPD_n$ potom je definovaný nasledovne:

\hfill

${}_5M = (\{s, b, d, e, h, i\}, \{a, g, c, u\}, \{a, g, c, t, S, T, U, V, X, Y, Z, P, H \#\}, R, s, S, \{f\})$, kde $R$~sú pravidlá:

\begin{enumerate}
    \item $s(S) \xrightarrow{} s(TUVXHYZSP)$
    \item $s(T) \xrightarrow{} s(aT) | s(gT) | s(cT) | s(uT) | s(\epsilon)$  % 6
    \item $s(U, V, X, H, Y) \xrightarrow{} b(aU, V, X, H, Yu) | b(uU, V, X, H, Ya) | b(cU, V, X, H, Yg) | \\ b(gU, V, X, H, Yc)$ % 7
    \item $b(U, V, X, H, Y) \xrightarrow{} d(aU, V, X, H, Yu) | d(uU, V, X, H, Ya) | d(cU, V, X, H, Yg) | \\ d(gU, V, X, H, Yc)$ % 8
    \item $d(U, V, X, H, Y) \xrightarrow{} d(aU, V, X, H, Yu) | d(uU, V, X, H, Ya) | d(cU, V, X, H, Yg) | \\ d(gU, V, X, H, Yc) |  d(\epsilon, V, X, H, \epsilon)$ % 9
    \item $d(V) \xrightarrow{} d(aV) | d(gV) | d(cV) | d(uV) | d(\epsilon)$ % 11
    \item $d(X, H, Z, S) \xrightarrow{} e(aX, H, Z, Su) | e(uX, H, Z, Sa) | e(cX, H, Z, Sg) | e(gX, H, Z, Sc)$
    \item $e(X, H, Z, S) \xrightarrow{} h(aX, H, Z, Su) | h(uX, H, Z, Sa) | h(cX, H, Z, Sg) | h(gX, H, Z, Sc)$
    \item $h(X, H, Z, S) \xrightarrow{} h(aX, H, Z, Su) | h(uX, H, Z, Sa) | h(cX, H, Z, Sg) | h(gX, H, Z, Sc) | \\ i(\epsilon, H, Z, \epsilon)$
    \item $i(H) \xrightarrow{} i(aH) | i(gH) | i(cH) | i(uH) | j(\epsilon)$ 
    \item $j(Z) \xrightarrow{} j(aZ) | j(gZ) | j(cZ) | j(uZ) | f(\epsilon)$ 
    \item $f(P) \xrightarrow{} f(aP) | f(gP) | f(cP) | f(uP) | f(\epsilon)$ 
\end{enumerate}

\hfill

Paralelný hlboký zásobníkový automat ${}_5M$ pracuje tak, že v~stave \textit{s}~je schopný generovať akýkoľvek reťazec, ktorý by sa mal vo výslednom reťazci nachádzať pred pseudouzlom (prefix). Po vygenerovaní prefixu začne generovať prvú dvojicu pseudouzlu (prvú a~tretiu časť), pričom ale zmení stav na \textit{b}, aby bolo zdôraznené, že prvá dvojica má jeden znak. Z~tohto stavu sa prejde do stavu \textit{d} vygenerovaním druhých symbolov prvej dvojice. V~stave \textit{d}~je už potom možné generovať ďalšie symboly prvej dvojice, pretože je zabezpečená minimálna dĺžka dvojice. Ďalej v~stave \textit{d} je možné generovať reťazec medzi prvou a~druhou časťou uzlu. Zmena stavu z~\textit{d}~do \textit{e}~je spojená s~vygenerovaním prvých symbolov druhej dvojice psudouzlu. Pre zabezpečenie správnej dĺžky reťazcov druhej dvojice automat prejde do stavu \textit{h}, v~ktorom je potom možné generovať ľubovolný počet ďalších znakov druhej dvojice. Prejdenie do stavov \textit{i}, \textit{j} a~\textit{f} a~práca v~nich umožňuje vygenerovanie ostatných pod-reťazcov nachádzajúcich sa medzi ostatnými časťami pseudouzlu ako aj jeho sufixu. Automat je možné vytvoriť s~menej stavmi a~menej nevstupnými symbolmi, avšak stal by sa zbytočne komplikovaným pre pochopenie. 

\hfill

\noindent 
Prijatie slova $w$ vyzerá nasledovne: 

\begin{alignat*}{2}
    (s, gagcguccga, S\#) &\quad \expandM{}{} \quad (s, gagcguccga, TUVXHYZSP\#) \; && [1] \nonumber \\
    &\quad \expandM{}{} \quad (s, gagcguccga, UVXHYZSP\#) \; && [2] \nonumber \\
    &\quad \expandM{}{} \quad (b, gagcguccga, gUVXHYcZSP\#) \; && [3] \nonumber \\
    &\quad \popM{}{} \quad (b, agcguccga, UVXHYcZSP\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (d, agcguccga, aUVXHYucZSP\#) \nonumber \; &&  [4] \\
    &\quad \popM{}{} \quad (d, gcguccga, UVXHYucZSP\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (d, gcguccga, VXHucZSP\#) \nonumber \; &&  [5] \\
    &\quad \expandM{}{} \quad (d, gcguccga, gVXHucZSP\#) \nonumber \; &&  [6] \\
    &\quad \popM{}{} \quad (d, cguccga, VXHucZSP\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (d, cguccga, XHucZSP\#) \nonumber \; &&  [6] \\
    &\quad \expandM{}{} \quad (e, cguccga, cXHucZSgP\#) \nonumber \; &&  [7] \\
    &\quad \popM{}{} \quad (e, guccga, XHucZSgP\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (h, guccga, gXHucZScgP\#) \nonumber \; && [8] \\ 
    &\quad \popM{}{} \quad (h, uccga, XHucZScgP\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (i, uccga, HucZcgP\#) \nonumber \; && [9] \\ 
    &\quad \expandM{}{} \quad (j, uccga, ucZcgP\#) \nonumber \; && [10] \\ 
    &\quad \popM{}{} \quad (j, ccga, cZcgP\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (j, cga, ZcgP\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (f, cga, cgP\#) \nonumber \; && [11] \\
    &\quad \popM{}{} \quad (f, ga, gP\#) \nonumber \; &&  \\
    &\quad \popM{}{} \quad (f, a, P\#) \nonumber \; &&  \\
    &\quad \expandM{}{} \quad (f, a, aP\#) \nonumber \; && [12] \\
    &\quad \popM{}{} \quad (f, \epsilon, P\#) \nonumber \; && \\
    &\quad \expandM{}{} \quad (f, \epsilon, \epsilon\#) \nonumber \; && [12] \\
\end{alignat*}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         Implementácia algoritmov
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Implementácia algoritmov} 
\label{implement}

Programovacia časť tejto práce je zameraná na algoritmy prezentované v~kapitole \ref{PPD}~a~\ref{TPPD}. Jedná sa konkrétne o~algoritmy prevodu medzi $PD_n$ a~$PPD_n$, a~prevodu $PD_n$ a~$TPPD_n$. Prvou dvojicou teda je  Algoritmus \ref{alg:PPD_to_PD} pre prevod hlbokého zásobníkového automatu na paralelný hlboký zásobníkový automat a~Algoritmus \ref{alg:PPD_to_PD} prevodu paralelného hlbokého zásobníkového automatu na hlboký zásobníkový automat. Druhá dvojica implementovaných algoritmov je Algoritmus \ref{alg:TPPD_to_PD} pre prevod násobného paralelného hlbokého zásobníkového automatu na základný hlboký zásobníkový automat a~pre opačný prevod Algoritmus \ref{alg:PD_to_TPPD}. Implementácia je zameraná na túto problematiku, pretože algoritmy prevodov môžu viesť k~zdĺhavému vytváraniu pravidiel, ktoré je možné generovať jednoducho automaticky a~je možné tento prevod nahradiť programom. V~rámci práce som preto vytvoril aplikáciu, ktorá je schopná prevodu $PD_n$ na $PPD_n$, $PD_n$ na $TPPD_n$ a~naopak. V~tejto kapitole je popísaná jej implementácia.

\section{Návrh aplikácie}
Zámerom aplikácie je zautomatizovanie prevodu automatov, z~tohoto dôvodu sa jedná o~jednoduchú konzolovú aplikáciu. Aplikácia zastrešuje všetky štyri navrhnuté prevody. Z~dôvodu jednoduchosti je aplikácia implementovaná v~jazyku Python verzie 3.9. Aplikácia je schopná čítať automat zo štandardného vstupu, ktorý následne prevedie a~vypíše na štandardný výstup. Pre automatizáciu je aplikácia schopná čítať automat aj zo vstupného súboru a~je schopná výsledok zapísať do výstupného súboru. 

Aplikácia používa objektovo orientované programovanie. Základom každého automatu je trieda \textit{Automaton}, ktorá zastrešuje všetky spoločné prvky všetkých verzií automatov a~stará sa aj o~správnosť týchto prvkov vzhľadom na spoločné prvky definícií automatov. Táto trieda má teda za úlohu kontrolu a~tvorbu základnej štruktúry automatov. Trieda je schopná kontrolovať a~vytvárať množinu stavov, vstupnú abecedu, zásobníkovú abecedu, počiatočný stav a~množinu koncových stavov.

Každá verzia hlbokého zásobníkového automatu je reprezentovaná samostatnou triedou. Jedná sa konkrétne o~triedy \textit{PD}, \textit{PPD} a~\textit{TPPD}, ktoré implementujú kontrolu a~tvorbu ich pravidiel a~kontrolu počiatočného zásobníkového symbolu alebo slova. Pre každú triedu špecifického automatu je vytvorená aj trieda schopná reprezentácie pravidla daného automatu. Jednotlivé triedy automatov potom pracujú s~pravidlami ako s~polom objektov triedy pravidiel. 

Ďalej aplikácia obsahuje triedu, ktorá je zodpovedná za získanie vstupného automatu zo štandardného vstupu alebo vstupného súboru. Z~dôvodu prehľadnosti sú prevody implementované ako samostatné funkcie v~jednom súbore s~názvom \textit{Converter.py}. 

Správnosť výsledku závisí na správnosti samostatného vstupu. Aplikácia kontroluje vstup oproti samotným definíciám automatov, pričom ale z~dôvodu zbytočnosti aplikácia neprijíma vyberacie pravidlá ani špeciálne symboly (okrem symbolu \textit{:}, ktorý sa používa pre rozdelenie ľavej a~pravej strany paralelného pravidla). 


\section{Spustenie aplikácie}
Aplikáciu je možné spustiť pomocou príkazu \textit{python3 Src/automatonConverter.py [options]} alebo pomocou príkazu \textit{make run ARGS="[options]"}. Prevod medzi automatmi sa vykonáva na základe jej parametrov. Aplikácia pozná tieto parametre:

\begin{itemize}
    \item \textit{-h | --help} - Vypíše nápovedu k aplikácii.
    \item \textit{-i \{vstupny\_subor\} | --input \{vstupny\_subor\}} - Určuje vstupný súbor.
    \item \textit{-o \{vystupny\_subor\} | --output \{vystupny\_subor\}} - Určuje výstupný súbor.
    \item \textit{-1 | --pda2ppda} - Nastaví prevod z~$PD_n$ na $PPD_n$.
    \item \textit{-2 | --ppda2pda} - Nastaví prevod z~$PPD_n$ na $PD_n$.
    \item \textit{-3 | --pda2tppda} - Nastaví prevod z~$PD_n$ na $TPPD_n$.
    \item \textit{-4 | --tppda2pda} - Nastaví prevod z~$TPPD_n$ na $PD_n$.
\end{itemize}

\section*{Vstup}
Predpokladaným vstupom aplikácie je automat $PD_n$, $PPD_n$ alebo $TPPD_n$, podľa zadaného parametra. Pokiaľ nie je zadaný parameter vstupného súboru, tak program postupne vyzýva používateľa k postupnej špecifikácii automatu. Obsah vstupného súboru musí mať formát vyhovujúci danému typu automatu. Aplikácia pre prevod $PD_n$ na $PPD_n$ očakáva následujúci formát: 

\begin{itemize}
    \item \textbf{Prvý riadok:} hĺbka automatu
    \item \textbf{Druhý riadok:} stavy automatu oddelené medzerou
    \item \textbf{Tretí riadok:} symboly vstupnej abecedy oddelené medzerou
    \item \textbf{Štvrtý riadok:} symboly zásobníkovej abecedy oddelené medzerou
    \item \textbf{Piaty riadok:} počiatočný stav
    \item \textbf{Šiesty riadok:} počiatočný zásobníkový symbol
    \item \textbf{Siedmy riadok:} koncové stavy oddelené medzerou
    \item \textbf{Ostatné riadky:} pravidlá automatu
\end{itemize}

Aplikácia predpokladá, že riadky obsahujúce pravidlá automatu (všetky riadky okrem prvých siedmych) sú postupným vymenovaním parametrov pravidiel. Formát pravidiel je teda hĺbka prepisu, východiskový stav, východiskový symbol na zásobníku, cieľový stav a~cieľové slovo na zásobníku. Jednotlivé parametre sú pritom rozdelené medzerami. Pre posledné riadky platí, že jeden riadok je jedným pravidlom. 

Predpokladaný formát pre opačný prevod je rovnaký ako pre prevod $PD_n$ na $PPD_n$ až na formát pravidiel. Pravidlá sú vo formáte východiskový stav, prvý, druhý, až \textit{k}-ty východiskový symbol na zásobníku, dvojbodka, cieľový stav, prvý, druhý, až \textit{k}-ty cieľový reťazec, kde $1 \leq k \leq n$. Dvojbodka oddeľuje \myuv{ľavú} a~\myuv{pravú} stranu pravidla.

Formát pre prevod $TPPD_n$ na $PD_n$ sa líši od formátu pre prevod $PPD_n$ na $PD_n$ tým, že namiesto počiatočného zásobníkového symbolu na šiestom riadku očakáva počiatočné zásobníkové slovo. Ďalej sa líši tým, že počet východiskových zásobníkových symbolov v~pravidlách musí byť vždy rovnaký a~musí sa rovnať maximálnej hĺbke prístupu automatu. 

Príkladom vstupného súboru môže byť napríklad textový súbor, ktorý obsahuje obyčajný hlboký zásobníkový automat ${}_2M$, prijímajúci jazyk $L({}_2M) = \{a^nb^nc^n; \forall n \in \mathbb{N}^+\}$. Obsah súboru môže byť napríklad takýto:


\begin{center}
  \begin{tabular}{l}
    2 \\
    s q p f \\
    a b c \\
    a b c S A \\
    s \\
    S \\
    f \\
    1 s S q AA \\
    1 q A p aAb \\
    1 q A f ab \\
    2 p A q Ac \\
    1 f A f c \\
  \end{tabular}
 \end{center}


\section*{Výstup}
Výstupom úspešne ukončenej aplikácie je vždy nový prevedený automat. Automat je prezentovaný buď na štandardnom výstupe alebo je uložený do zadaného výstupného súboru. Formát výstupného automatu je rovný vstupnému formátu pre typ daného automatu.

Príkladom výstupného súboru je súbor, do ktorého bude vypísaný paralelný hlboký zásobníkový automat. Obsah výstupného súboru napríklad pre vstupný súbor, ktorý bol prezentovaný ako príklad vstupného súboru, bude takýto:

\begin{center}
  \begin{tabular}{l}
    2 \\
    s q p f \\
    a b c \\
    a b c S A \\
    s \\
    S \\
    f \\
    q A : f ab \\
    q A : p aAb \\
    f A : f c \\
    s S : q AA \\
    p A A : q A Ac \\
    p S A : q S Ac \\
  \end{tabular}
 \end{center}

\section{Testovanie}
Správnosť aplikácie bola overená testovaním. Aplikácia bola testovaná pomocou simulovaného používania, kedy boli potencionálni používatelia vyzvaní k~sledovanému použitiu aplikácie. Vzhľadom na jednoduchosť aplikácie ale tieto testy nepriniesli žiadny zaujímavý záver. Vzhľadom na výsledky predošlého testovania bolo vyhodnotené, že najvhodnejším spôsobom testovania sú automatické testy. 

Pre automatické testovanie bol vytvorený testovací skript, ktorý spúšťa aplikáciu nad rôznymi vstupmi a~kontroluje jej výstupy, prípadne chybové kódy. Skript bol vytvorený v~jazyku Python verzie 3.9 rovnako ako aplikácia. Je možné ho spustiť s~parametrom, ktorý odkazuje na meno priečinku obsahujúceho testovacie vstupy, výstupy, prípadne chybové kódy. Testovanie sa vykonáva nad \textit{74} rôznymi vstupmi. Automatické testovanie bolo vykonávané pravidelne a~pomohlo k~nájdeniu niekoľko menších chýb v~aplikácii, ktoré boli vzápätí opravené. Pre spustenie automatických testov je možné použiť príkaz \textit{make test} pre testovanie na vopred pripravených testoch alebo príkaz \textit{python3 Src/tester.py \{directory\_path\}} pre testovanie na testoch nachádzajúcich sa v~priečinku \textit{\{directory\_path\}}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                         Záver
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Záver}
\label{zaver}

Zmyslom práce bolo vytvoriť nové verzie hlbokých zásobníkových automatov, ktoré budú mať lepšie vlastnosti. Tento cieľ sa mi podarilo dosiahnuť vytvorením dvoch modifikácií. Jedná sa o~paralelný hlboký zásobníkový automat a~násobný paralelný hlboký zásobníkový automat. Tieto automaty som formálne definoval a~potom som pre každý automat vytvoril príklad prijatia nejakého slova. Ďalej som popísal vlastnosti oboch vytvorených modifikácií. Práca obsahuje formálny popis matematických konštrukcii, základného hlbokého zásobníkového automatu a~popis niektorých ďalších už vytvorených vybraných modifikácii hlbokého zásobníkového automatu. 

V~práci dokazujem, že paralelný hlboký zásobníkový automat má rovnakú vyjadrovaciu silu ako hlboký zásobníkový automat. Táto rovnosť je dokázaná pre celú nekonečnú hierarchiu jazykov generovaných hlbokými zásobníkovými automatmi. To znamená, že pre akúkoľvek hĺbku automatu sú rodiny jazykov paralelného a~obyčajného hlbokého zásobníkového automatu ekvivalentné. Modifikácia pridania paralelizmu navyše zmenšuje počet vykonaných prechodov automatu. Na druhú stranu paralelný hlboký zásobníkový automat má obecne viacej pravidiel, ktoré sú rozsiahlejšie ako sú pravidlá obyčajného hlbokého zásobníkového automatu. Pre jednoduchý prevod medzi novou verziou a~základným hlbokým zásobníkovým automatom som vytvoril algoritmus prevodu. Ďalej som vytvoril algoritmus pre opačný prevod, zo základného hlbokého zásobníkového automatu na paralelný. Oba algoritmy som popísal a~demonštroval na príkladoch. 

Druhá modifikácia taktiež pridáva paralelizmus do hlbokých zásobníkových automatov a~je možno povedať, že je v~skutočnosti špeciálnym prípadom paralelného hlbokého zásobníkového automatu. Násobný paralelný hlboký zásobníkový automat má vyjadrovaciu silu rovnú hlbokému zásobníkovému automatu a~taktiež vytvára ekvivalentnú nekonečnú hierarchiu jazykov. Nevýhodou tejto modifikácie môžu byť až príliš rozsiahle pravidlá, ktoré sú ale vždy rovnakej veľkosti, čo by mohlo byť výhodné pre vektorové spracovávanie prechodov. Táto modifikácia obecne zmenšuje počet vykonaných prechodov automatu. Rovnako ako pre obyčajnú paralelnú verziu aj pre túto násobnú som vytvoril algoritmus prevodu na základný hlboký zásobníkový automat a~algoritmus prevodu zo základného na násobný hlboký zásobníkový automat. Algoritmy som v~práci vysvetlil a~pre oba algoritmy som demonštroval na príkladoch. 

V~práci konštatujem, že je možné využiť v~rovnakých oblastiach ako základné hlboké zásobníkové automaty. Vzhľadom na paralelný prístup modifikácií môže byť ale efektívnejšie ich vytvárať pre jazyky obsahujúce pod-reťazce, ktoré sú v~nejakom vzťahu. Vzhľadom na túto skutočnosť bola pre alternatívy nájdená ich aplikácia v~rámci bioinformatiky. Jedná sa o~problém rozhodnutia toho, či molekula DNA obsahuje podreťazec, ktorý sa opakuje alebo nie. Ďalšie možné použitie bolo prezentované pri rozhodovaní, či molekula RNA môže obsahovať pseudouzol. Pre dané využitia boli prezentované triviálne príklady, ktoré ujasnili, akým spôsobom je možné použiť alternatívne verzie hlbokých zásobníkových automatov.

Súčasťou práce je aj implementácia nástroja pre prevod medzi modifikovanými verziami a~základnou verziou. Nástroj bol implementovaný ako konzolová aplikácia napísaná v~jazyku Python verzie 3.9. Aplikácia predpokladá na vstupe hlboký zásobníkový automat alebo jednu z~jeho modifikovaných verzií, ktoré boli predstavené v~tejto práci. Aplikácia na základe parametrov jej volania prevedie daný vstupný automat na zvolenú verziu.

Medzi otázky, ktorým sa táto práca nevenovala, patrí determinizmus nových modifikácií a teda prípadne rozšírenie tejto práce by sa mohlo venovať tejto téme. Ďalší rozvoj by sa mohol zamerať na odstránenie vymazávacích pravidiel, čiže pravidiel, ktoré expandujú aspoň jeden nevstupný symbol na prázdny reťazec. Zároveň by bolo možné študovať aj prípad, kedy automaty nebudú môcť používať iba vymazávacie pravidlá, ktoré prepisujú všetky nevstupné symboly na prázdne reťazce. Medzi zaujímavé vlastnosti jazykov definovaných hlbokými zásobníkovými automatmi by mohli byť študované ich uzáverové vlastnosti. Analogicky by bolo možné študovať uzáverové vlastnosti jazykov definovaných násobnými a~obyčajnými paralelnými hlbokými zásobníkovými automatmi. Otvorenou otázkou je aj otázka vlastnosti systémov hlbokých zásobníkových automatov. Tieto systémy by mohli byť zavedené tak, aby pracovali analogicky ku gramatickým systémom, to znamená, že sú súbežne používané rôzne verzie hlbokých zásobníkových automatov. Posledným námetom na pokračovanie práce by mohlo byť študovanie systémov tvorených násobnými alebo obyčajnými paralelnými hlbokými zásobníkovými automatmi.

%===============================================================================