Commit 6516cc10 authored by Niklas Rieken's avatar Niklas Rieken
Browse files

nicified some files for fosap.de launch

parent 33e4ac73
No preview for this file type
......@@ -473,9 +473,9 @@ Wir bezeichnen die Inversen zu Einheiten \( a \) in der Regel mit \( a^{-1} \) o
\begin{lemma}
Ist \( (A, \bullet, e) \) Monoid, so ist \( (A^\times, \bullet, e) \) Gruppe (Einheitengruppe).
\begin{proof}
Per Definition ist jedes Element in \( A^\times \) eine Einheit. Außerdem ist \( e \) stets eine Einheit, da es invers zu sich selbst ist. Es bleibt zu zeigen, dass \( A^\times \) auch abgeschlossen ist unter der Operation \( \bullet \). Sei dazu \( a, b \in A^\times \) und \( a^\prime, b^\prime \) die jeweiligen Inversen. Wir zeigen das \( a \bullet b \) Einheit ist mit Inversem \( b^\prime \bullet a^\prime \):
Per Definition ist jedes Element in \( A^\times \) eine Einheit. Außerdem ist \( e \) stets eine Einheit, da es invers zu sich selbst ist. Es bleibt zu zeigen, dass \( A^\times \) auch abgeschlossen ist unter der Operation \( \bullet \). Sei dazu \( a, b \in A^\times \) und \( a^{-1}, b^{-1} \) die jeweiligen Inversen \( (\ast) \). Wir zeigen das \( a \bullet b \) Einheit ist mit Inversem \( b^{-1} \bullet a^{-1} \):
\[
(a \bullet b) \bullet (b^{-1} \bullet a^{-1}) = a \bullet (b \bullet b^{-1}) \bullet a^{-1} = a \bullet e \bullet a^{-1} = a \bullet a^{-1} = e. \qedhere
(a \bullet b) \bullet (b^{-1} \bullet a^{-1}) \overset{\text{(i)}}{=} a \bullet (b \bullet b^{-1}) \bullet a^{-1} \overset{(\ast)}{=} a \bullet e \bullet a^{-1} \overset{\text{(ii)}}{=} a \bullet a^{-1} \overset{(\ast)}{=} e. \qedhere
\]
\end{proof}
\end{lemma}
......@@ -1317,7 +1317,7 @@ Bisher haben wir Sprachen betrachtet, die sich von endlichen Automaten erkennen
\item Für jedes \( a \in \Sigma \) ist \( \bm{a} \) ein regulärer Ausdruck.
\item Falls \( r, r^\prime \) reguläre Ausdrücke sind, dann ist auch \( (r \bm{+} r^\prime) \) ein regulärer Ausdruck.
\item Falls \( r, r^\prime \) reguläre Ausdrücke sind, dann ist auch \( (r \bm{\cdot} r^\prime) \) ein regulärer Ausdruck.
\item Falls \( r \) reguläre Ausdrücke sind, dann ist auch \( (r) \overset{\bm{\ast}}{} \) ein regulärer Ausdruck.
\item Falls \( r \) reguläre Ausdrücke sind, dann ist auch \( r \overset{\bm{\ast}}{} \) ein regulärer Ausdruck.
\end{itemize}
Die \textit{Menge aller regulären Ausdrücke} über \( \Sigma \) bezeichnen mit \( \mathsf{RE}_\Sigma \).
\end{definition}
......@@ -1333,11 +1333,11 @@ Das ist bisher lediglich die Syntax der regulären Ausdrücke gewesen. Nun defin
\item \( \llbracket \bm{a} \rrbracket = \{ a \} \) für jedes \( \bm{a} \in \mathsf{RE}_\Sigma \),
\item \( \llbracket (r \bm{+} r^\prime) \rrbracket = \llbracket r \rrbracket \cup \llbracket r^\prime \rrbracket \),
\item \( \llbracket (r \bm{\cdot} r^\prime) \rrbracket = \llbracket r \rrbracket \cdot \llbracket r^\prime \rrbracket \),
\item \( \llbracket (r) \overset{\bm{\ast}}{} \rrbracket = \llbracket r \rrbracket^\ast \).
\item \( \llbracket r \overset{\bm{\ast}}{} \rrbracket = \llbracket r \rrbracket^\ast \).
\end{itemize}
Eine Sprache \( L \subseteq \Sigma^\ast \) heißt \textit{regulär}, wenn ein regulärer Ausdruck \( r \in \mathsf{RE}_\Sigma \) existiert mit \( \llbracket r \rrbracket = L \).
\end{definition}
Wir erlauben in der Regel auch als Abkürzung die Ausdrücke \( \bm{\varepsilon} \) für \( (\bm{\emptyset}) \overset{\bm{\ast}}{} \) und \( (r) \overset{\bm{+}}{} \) für \( r \bm{\cdot} (r) \overset{\bm{\ast}}{} \). Außerdem lassen wir den Punkt (\( \bm{\cdot} \)) weg, es sei denn er dient der Lesbarkeit. Die Klammern können wir auch weglassen unter der Konvention, dass \( \overset{\bm{\ast}}{} \) stärker bindet als \( \bm{\cdot} \), was wiederum stärker bindet als \( \bm{+} \). Statt \( \llbracket r \rrbracket \) ist auch die Schreibweise \( L(r) \) gebräuchlich.\par
Wir erlauben in der Regel auch als Abkürzung die Ausdrücke \( \bm{\varepsilon} \) für \( \bm{\emptyset}\overset{\bm{\ast}}{} \) und \( r \overset{\bm{+}}{} \) für \( r \bm{\cdot} r \overset{\bm{\ast}}{} \). Außerdem lassen wir den Punkt (\( \bm{\cdot} \)) weg, es sei denn er dient der Lesbarkeit. Die Klammern können wir auch weglassen unter der Konvention, dass \( \overset{\bm{\ast}}{} \) stärker bindet als \( \bm{\cdot} \), was wiederum stärker bindet als \( \bm{+} \). Statt \( \llbracket r \rrbracket \) ist auch die Schreibweise \( L(r) \) gebräuchlich.\par
Reguläre Ausdrücke kennt man auch für Computerprogramme wie \texttt{grep}, \texttt{awk} oder \texttt{sed}. Diese sind syntaktisch etwas anders aufgebaut, jedoch lässt sich jeder POSIX-Ausdruck (das sind die regulären Ausdrücke für oben genannte Programme) auch als regulärer Ausdruck wie in Definition~\ref{def:regexsyntax} umschreiben.
\begin{example}
Die POSIX-Syntax für reguläre Ausdrücke geht wie folgt.
......@@ -1579,7 +1579,6 @@ Wir werden nun anstelle von FA-erkennbaren Sprachen auch nur noch von regulären
\subsection{Weitere Abschlusseigenschaften}\label{sec:regular_closure2}
Wir haben bis hier hin reguläre Sprachen eine umfangreiche Charakterisierung gegeben, nämlich als Sprachen, die sich durch reguläre Ausdrücke oder Sprachen von endliche Automaten beschreiben lassen -- auf die Äquivalenz dieser Charakterisierungen haben wir lange hingearbeitet und mit dem Ä\-qui\-va\-lenz\-satz von Kleene einen schweren Brocken der theoretischen Informatik bewiesen. Dieser Abschnitt wird nun wieder deutlich einfacher. Wir haben bereits einige Abschlusseigenschaften regulärer Sprachen bewiesen: Schnitt, Vereinigung, Komplement, Konkatenation, Iteration usw., aber auch unter ''erfundenen`` Operatoren wie \textit{Perfect Shuffle}. Diese Abschlüsse allein zusammen mit dem Äquivalenzsatz von Kleene ergeben bereits genug Gründe um reguläre Sprachen als eine in wissenschaftlicher Hinsicht \textit{sinnvolle} Sprachklasse zu sehen. Wir werden in diesem Abschnitt nun ein paar weitere sinnvolle Abschlusseigenschaften beweisen.\par
%TODO Freies Monoid
\begin{definition}\label{def:stringhomomorphism}
Seien \( \Sigma, \Gamma \) Alphabete. Die Abbildung \( h\colon \Sigma^\ast \to \Gamma^\ast \) heißt \textit{(Wort-)Homomorphismus}, wenn für alle \( a_0 \ldots a_{n-1} \in \Sigma^\ast \) gilt, dass
\[
......@@ -1627,7 +1626,7 @@ Beachte, dass \( w^\mathcal{R} \) wohldefiniert ist für jedes \( w \in \Sigma
\begin{theorem}
Sei \( L \subseteq \Sigma^\ast \) regulär. Dann ist auch \( L^\mathcal{R} \) regulär.
\begin{proof}
folgt. %TODO
Übung.
\end{proof}
\end{theorem}
......@@ -1637,9 +1636,9 @@ Bisher haben wir nur sehr einfache Sprachen betrachtet, die alle regulär waren.
\[
L_\mathbb{P} \coloneqq \{ a^p : p \in \mathbb{P} \}.
\]
\( L_\mathbb{P} \) ist die Sprache aller (mit \( a \)) unär codierten Primzahlen, d.h. \( L_\mathbb{P} = \{ aa, aaa, a^5, a^7, a^{11}, \ldots \} \). Dass \( L_\mathbb{P} \) nicht regulär ist, ist auch nicht so schwer einzusehen: Intuitiv, wie würde ein regulärer Ausdruck aussehen? Natürlich könnten wir eine unendliche Vereinigung bilden (dies wäre jedoch nicht regulär, da reguläre Ausdrücke endlich sind):
\( L_\mathbb{P} \) ist die Sprache aller (mit \( a \)) unär codierten Primzahlen, d.h. \( L_\mathbb{P} = \{ a^2, a^3, a^5, a^7, a^{11}, \ldots \} \). Dass \( L_\mathbb{P} \) nicht regulär ist, ist auch nicht so schwer einzusehen: Intuitiv, wie würde ein regulärer Ausdruck aussehen? Natürlich könnten wir eine unendliche Vereinigung bilden (dies wäre jedoch nicht regulär, da reguläre Ausdrücke endlich sind):
\[
r_\mathbb{P} = \sum_{p \in \mathbb{P}} a^p = aa + aaa + a^5 + a^7 + a^{11} + \ldots
r_\mathbb{P} = \sum_{p \in \mathbb{P}} a^p = a^2 + a^3 + a^5 + a^7 + a^{11} + \ldots
\]
Es erscheint klar, dass es jedoch keine Möglichkeit gibt diesen Ausdruck zu vereinfachen. In einem Automaten wird es noch deutlicher. Wenn wir mit endlich vielen Zuständen auskämen um genau alle unendlich vielen Primzahlcodierungen zu erkennen würden wir Kreise im Transitionsgraphen und somit eine gewisse Regelmäßigkeit in der Wiederholung von Primzahlen bekommen. Dies würde bedeuten, dass die Generierung neuer Primzahlen viel einfacher wäre als bisher angenommen, da wir ab einer bestimmten Primzahl einfach immer eine Konstante addieren könnten um die nächste zu bekommen. Das ist natürlich nicht der Fall. Eine schematische Erklärung dieses Arguments ist in Abbildung~\ref{fig:dfa_primes}. Egal an welcher und an wie vielen Stellen wir eine Zustandwiederholung zulassen (durch gestrichtelte Kante angedeutet), wir würden stets Codierungen akzeptieren, die nicht zu Primzahlen gehören können. In diesem Abschnitt werden wir uns ansehen, wie wir dieses Argument formalisieren und auf weitere nicht-reguläre Sprachen anwenden können.
\begin{figure}
......@@ -1709,6 +1708,8 @@ Dieses Beispiel ist sehr ausführlich jetzt besprochen worden. Sobald man diese
Angenommen \( L \) wäre regulär. Dann gilt das Pumping-Lemma. Sei also \( n \in \mathbb{N}_+ \) beliebig und wir betrachten das Wort \( w = a^n bb a^n \in L \). Es hat die Länge \( \left| w \right| = 2n+2 \geq n \). Wir betrachten nun Zerlegungen, die die Eigenschaften (i) und (ii) erfüllen und zeigen, dass (iii) dann nicht gelten kann. Wegen (i) ist \( y = a^k \) für ein \( k \leq n \) (\( k = \left| y \right| \leq \left| xy \right| \leq n \), da die ersten \( n \) Zeichen alle \( a \) sind, kommt also auch kein \( b \) in \( y \) vor). Wegen (ii) gilt außerdem, dass \( k > 0 \). Betrachte nun das Wort \( w^\prime \coloneqq xyyz = a^{n+k}bba^n \). Es liegt nicht in \( L \), da \( w^\prime \) kein Palindrom ist. Damit gilt die Eigenschaft (iii) für \( i = 2 \) nicht (gilt sogar für gar kein \( i \neq 1 \)). Dies ist ein Widerspruch zum Pumping-Lemma, also kann \( L \) nicht regulär sein.
\end{proof}
\end{example}
%TODO Pumping-Lemma-Spiel
%TODO Nicht-Regularität durch Abschlusseigenschaften zeigen.
\subsection{Minimierung von DFAs}\label{sec:regular_minimization}
......
No preview for this file type
\documentclass[11pt, a4paper]{article}
\usepackage[left=3cm, right=3cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage[ngerman]{babel}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{amsfonts}
......@@ -13,6 +14,8 @@
\usepackage{listings}
\usepackage[justification=centering]{caption}
\usetikzlibrary{arrows, automata, graphs, shapes, petri, decorations.pathmorphing}
\let\emptyset\varnothing
\parindent = 0pt
% define environments
\theoremstyle{definition}
......@@ -37,7 +40,7 @@ In diesem Dokument verwenden wir die Variablen \( h, i, j, k, \ell \) stets als
\subsection*{Problemstellung: Extended Matching Problem}
Das \textit{erweiterte (extended) Matching-Problem} kommt direkt aus der Anwendung des Compilerbaus. Gegeben ist ein Wort \( w \in \Sigma^\ast \) und eine Reihe von regulären Ausdrücken \( r_1, \ldots, r_n \in \mathsf{RE}_\Sigma \). (\textit{Bemerkung:} In der Praxis ist die Annahme \( \varepsilon \notin L(r_i) \neq \emptyset \) für alle \( i \) sinnvoll). Gesucht ist nun eine Zerlegung des Wortes \( w = u_1 \ldots u_k \), wobei für jedes \( u_j \) ein \( r_{i_j} \) existieren muss, sodass \( u_j \in L(r_{i_j}) \). Man nennt die Zerlegung in \( (u_1, \ldots, u_k) \) auch \textit{Dekomposition} und die zugehörigen Indizes der regulären Ausdrücke \( (i_1, \ldots, i_k) \) \textit{Analyse} von \( w \) bezüglich \( r_1, \ldots, r_n \).
Das \textit{erweiterte (extended) Matching-Problem} kommt direkt aus der Anwendung des Compilerbaus. Gegeben ist ein Wort \( w \in \Sigma^\ast \) und eine Reihe von regulären Ausdrücken über $\Sigma$ \( r_1, \ldots, r_n \in \mathsf{RE}_\Sigma \). (\textit{Bemerkung:} In der Praxis ist die Annahme \( \varepsilon \notin L(r_i) \neq \emptyset \) für alle \( i \) sinnvoll). Gesucht ist nun eine Zerlegung des Wortes \( w = u_1 \ldots u_k \), wobei für jedes \( u_j \) ein \( r_{i_j} \) existieren muss, sodass \( u_j \in L(r_{i_j}) \). Man nennt die Zerlegung in \( (u_1, \ldots, u_k) \) auch \textit{Dekomposition} und die zugehörigen Indizes der regulären Ausdrücke \( (i_1, \ldots, i_k) \) \textit{Analyse} von \( w \) bezüglich \( r_1, \ldots, r_n \).
Wir sehen schnell, dass weder Dekomposition, noch Analyse eindeutig sein müssen (insbesondere dann, wenn wir \( \varepsilon \in L(r_i) \) zulassen).
\begin{example}
......
\documentclass[11pt, a4paper]{article}
\usepackage[left=3cm, right=3cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{mathtools}
\usepackage{array}
\usepackage{graphicx}
\usepackage{tikz}
\usepackage{listings}
\usepackage[justification=centering]{caption}
\usetikzlibrary{arrows, automata, graphs, shapes, petri, decorations.pathmorphing}
\parindent = 0pt
\let\emptyset\varnothing
\renewcommand{\labelenumi}{(\roman{enumi})}
\author{Niklas Rieken}
\title{Äquivalenzsatz von Kleene}
\begin{document}
\maketitle
In diesem Dokument geht es um die Äquivalenz von regulären Ausdrücken und endlichen Automaten. Stephen C. Kleene zeigte, dass es zu jedem regulären Ausdruck einen DFA(!) gibt und umgekehrt. Der Beweis damals war aufgrund des fehlenden Konzept des \textit{Nichtdeterminismus} ziemlich abgedreht (denkt mal drüber nach, wie man es anstellt aus einem Regex sofort einen DFA zu bauen).
\subsection*{Reguläre Ausdrücke}
Reguläre Ausdrücke sind induktiv aufgebaut und beschreiben immer eine reguläre Sprache, welche mit den FA-erkennbaren Sprachen zusammenfallen (Satz von Kleene).\par
Reguläre Ausdrücke sind wie folgt definiert:\\
Basisfälle: $\emptyset, \varepsilon$ und $a$ sind reguläre Ausdrücke für jedes $a \in \Sigma$.\\
Rekursionsschritt: Sind $r$ und $e$ reguläre Ausdrücke, so sind auch $(r \cdot e), (r + e)$ und $r^\ast$ reguläre Ausdrücke.\\
Semantisch stehen die Ausdrücke $\emptyset, \varepsilon, a$ für die Sprachen $L(\emptyset) \coloneqq \emptyset, L(\varepsilon) \coloneqq \{ \varepsilon \}, L(a) \coloneqq \{ a \}$ und im rekursiven Fall $L(r \cdot e) \coloneqq L(r) \cdot L(e), L(r + e) \coloneqq L(r) \cup L(e), L(r^\ast) \coloneqq L(r)^\ast$. Klammern und $\cdot$ werden gerne auch weggelassen, wenn der Ausdruck auch so klar ist.\par
Gelegentlich kennen Studenten reguläre Ausdrücke bereits durch Programme wie \texttt{grep}, \texttt{sed}, womit sich Textdateien u.a. durchsuchen lassen mithilfe von POSIX-Ausdrücken. Diese sind gleichmächtig mit denen aus der Vorlesung, sollten aber nicht verwendet werden. Man möchte die Anzahl der Rekursionen auf das Minimum reduzieren, da dadurch auch die Beweise über reguläre Ausdrücke kürzer werden. Auf POSIX-Shortcuts wie $(r?)$ für $(r + \varepsilon)$, Umbenennungen wie $(r|e)$ für $(r + e)$ oder Schreibweisen wie $[a-c]$ für $(a + b + c)$ solltet ihr also verzichten. Die einzige Ausnahme ist hier vielleicht $r^+$ für $rr^\ast$.\par
Aus den Tutoraufgaben hier zwei Beispiele nun:
\begin{description}
\item[a)] $L_1 = \{ w \in \{ a, b, c \}^\ast \,\vert\, w \text{ hat gerade Länge } \}$.\\
$r_1 = ((a+b+c)(a+b+c))^\ast$. Das dieser Ausdruck die Sprache beschreibt lässt sich wie gewohnt über Induktion beweisen (zwei Richtungen für Gleichheit). Das ist aber hier nicht gefordert.
\item[c)] $L_3 = \{ w \in \{ a, b, c \}^\ast \,\vert\, \left| w \right| > 0 \text{ und } w \text{ beginnt und endet mit dem selben Symbol} \}$.\\
$r_3 = a(a+b+c)^\ast a + b(a+b+c)^\ast b + c(a+b+c)^\ast c + a + b + c$. Hier werden die Spezialfälle für $\left| w \right| = 1$ gerne übersehen.
\end{description}
Statt $(a+b+c)$ schreibt man gerne auch einfach $\Sigma$. Das ist aber eigentlich nicht ganz korrekt, da wir zwischen regulären Ausdrücken und den Sprachen die sie beschreiben unterscheiden. ($r$ vs. $L(r)$). Streng genommen sind demnach auch die Zeichen $\emptyset, \varepsilon, a$, wie oben in der Definition der regulären Ausdrücke, verschieden von den der Sprache $\emptyset$, dem leeren Wort $\varepsilon$ und dem Symbol $a \in \Sigma$. Wenn man also wie in Aufgabe a) z.B. $(\Sigma\Sigma)^\ast$ schreiben möchte, sollte man sich zumindest vorher $\Sigma$ als regulären Ausdruck $\Sigma \coloneqq (a+b+c)$ definieren.
\subsection*{Von Automaten zu regulären Ausdrücken (Floyd-Warshall-Algorithmus)}
Das Verfahren was hier beschrieben wird ist leider etwas umständlich aufgeschrieben, es gibt durchaus übersichtlichere Wege oder auch "graphische" Verfahren. Andererseits ist dieser Weg aber auch sehr genau und Fehler sind schneller nachzuvollziehen. Die Idee ist eigentlich sogar recht einfach: Wir wollen vom Startzustand $q_0$ alle möglichen Pfade (d.h. über alle möglichen Zustände) zu akzeptierenden Zuständen finden (hier nur $q_0$). Allgemein suchen wir den regulären Ausdruck
$$
r = \sum_{q \in F} r_Q(q_0, q) = r_Q(q_0, p_1) + \ldots + r_Q(q_0, p_k),
$$
wobei $p_1, \ldots, p_k \in F$. Die Notation funktioniert folgendermaßen: Ein regulärer Ausdruck $r_P(p, q)$ mit $P \subseteq Q$ und $p, q \in Q$ beschreibt die Wörter mit denen man von $p$ nach $q$ kommt und dabei nur Zustände benutzt, die in $P$ sind. Dies lässt sich rekursiv nun runterbrechen wie folgt:
Rekursionsanfang:
$$
r_\emptyset(p, q) = \left\lbrace
\begin{array}{*3{>{\displaystyle}l}p{5cm}}
\ &\sum_{(p, a, q) \in \Delta} a, & p \neq q\\
\varepsilon + &\sum_{(p, a, q) \in \Delta} a, & p = q.
\end{array}
\right.
$$
Der Rekursionsschritt funktioniert nun folgendermaßen: Für ein \( P \neq \emptyset \) wählen wir einen Zustand \( s \in P \) und entfernen diesen mit folgender Umformung
$$
r_P(p, q) = r_{P^\prime}(p, q) + r_{P^\prime}(p, s) r_{P^\prime}(s, s)^\ast r_{P^\prime}(s, q),
$$
wobei $P^\prime \coloneqq P \setminus \{ s \}$. Auch dies einmal in einfache Worte gefasst: Um von $p$ nach $q$ zu kommen über Zustände ausschließlich aus $P$ können wir entweder (links vom +) von $p$ nach $q$ gehen ohne einen Zustand $s$ zu besuchen oder (rechts vom +) von $p$ nach $s$ gehen, Pfade von $s$ nach $s$ benutzen und schließlich von $s$ nach $q$ gehen, wobei auch hier nur Zustände in $P \setminus \{ s \}$ benutzt werden.\\
Diesen rekursiven Schritt habe ich nochmal in Abbildung~\ref{fig:fwa} veranschaulicht.
\begin{figure}
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick]
\draw[black, fill=black!20] (2, .3) circle[x radius=3, y radius= 1.3];
\draw[black] (2, 2) circle[x radius=4, y radius=3.5];
\node[state] (p) at (0, 0) {$p$};
\node[state] (q) at (4, 0) {$q$};
\node[state] (s) at (2, 3) {$s$};
\path (p) edge node {$r_{P^\prime}(p, q)$} (q)
(p) edge node {$r_{P^\prime}(p, s)$} (s)
(s) edge[loop above] node {$r_{P^\prime}(s, s)$} (s) % curly loop
(s) edge node {$r_{P^\prime}(s, q)$} (q);
\end{tikzpicture}
\caption{Rekursionsschritt um einen Zustand rauszuwerfen. Die grau getönte Fläche ist $P^\prime \coloneqq P \setminus \{ s \}$. Die größere Fläche ist $P$. Wichtig: Die Kanten in diesem Graphen sind keine Transitionen, sondern sind mit einem regulären Ausdruck beschriftet, der die Sprache zwischen den Knoten beschreibt mit Zuständen aus dem Index!}
\label{fig:fwa}
\end{figure}
Falls das Verfahren jemanden bekannt vorkommt, könnte derjenige damit richtig liegen. Es handelt sich bei dem Algorithmus um eine Version des \textit{Floyd-Warshall-Algorithmus}, der in ''Datenstrukturen und Algorithmen`` in der Regel auch vorgestellt wird um günstigste Pfade in gewichteten Graphen zu finden.\par
Die Aufgabe selbst gehe ich jetzt nicht komplett durch, aber ein paar Rekursionsschritte sollten genügen um die idee zu verstehen.
\begin{figure}[h]
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick]
\node[state, initial, accepting, initial text=] (q0) at (0, 0) {$q_0$};
\node[state] (q1) at (4, 0) {$q_1$};
\path (q0) edge[bend left] node {$c$} (q1)
(q1) edge[loop above] node {$a, b$} (q1)
(q1) edge[bend left] node {$a$} (q0);
\end{tikzpicture}
\end{figure}
Wir suchen also einen regulären Ausdruck, der die Worte beschreibt mit denen man von $q_0$ nach $q_0$ kommt mit allen Zuständen, also den Ausdruck $r_Q(q_0, q_0)$. Wir wählen zunächst $s = q_1$ (eliminieren $q_1$):
$$
r_Q(q_0, q_0) = r_{\{ q_0 \}}(q_0, q_0) + r_{\{ q_0 \}}(q_0, q_1) r_{\{ q_0 \}}(q_1, q_1)^\ast r_{\{ q_0 \}}(q_1, q_0)
$$
Noch zu berechnen sind also $r_{\{ q_0 \}}(q_0, q_0), r_{\{ q_0 \}}(q_0, q_1), r_{\{ q_0 \}}(q_1, q_1), r_{\{ q_0 \}}(q_1, q_0)$. Wir berechnen $r_{\{ q_0 \}}(q_0, q_0)$ und eliminieren jetzt auch $q_0$ und können dann direkt den Basisfall einsetzen:
\begin{align*}
r_{\{ q_0 \}}(q_0, q_0) &= r_\emptyset(q_0, q_0) + r_\emptyset(q_0, q_0) r_\emptyset(q_0, q_0)^\ast r_\emptyset(q_0, q_0)\\
&\equiv \varepsilon + \varepsilon \varepsilon^\ast \varepsilon\\
&\equiv \varepsilon.
\end{align*}
Wir berechnen nun $r_{\{ q_0 \}}(q_0, q_1)$ und eliminieren wieder $q_0$:
\begin{align*}
r_{\{ q_0 \}}(q_0, q_1) &= r_\emptyset(q_0, q_1) + r_\emptyset(q_0, q_0) r_\emptyset(q_0, q_0)^\ast r_\emptyset(q_0, q_1)\\
&\equiv c + \varepsilon \varepsilon^\ast c\\
&\equiv c.
\end{align*}
Die letzten beiden lasse ich mal weg, damit die Aufgabe in späteren Jahrgängen noch verwendet werden kann. Die erhaltenen regulären Ausdrücke lassen sich aber später rekursiv wieder zusammensetzen und man erhält vereinfacht (falls ihr das noch selber machen wollt als Überprüfung):
$$
r_Q(q_0, q_0) = \varepsilon + c(a+b+ac)^\ast a.
$$
\subsection*{Von regulären Ausdrücken zu Automaten (Thompson-Konstruktion)}
Die andere Richtung, von regulären Ausdrücken zu endlichen Automaten ist deutlich bequemer mit der \textit{Thompson-Konstruktion}. Eine Variante davon wurde in der Vorlesung vorgestellt. Durch die rekursive Definition von regulären Ausdrücken lässt sich aus einem Ausdruck auch rekursiv ein \(\varepsilon\)-NFA aufbauen:\\
Basisfälle:
\begin{figure}[h]
\begin{minipage}{.3\textwidth}
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick, every state/.style={inner sep=0pt, minimum size=20pt}]
\node[state, initial, initial text=] (0) at (0, 0) {$p$};
\end{tikzpicture}
\caption{$r = \emptyset$}
\end{minipage}
\begin{minipage}{.3\textwidth}
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick, every state/.style={inner sep=0pt, minimum size=20pt}]
\node[state, initial, initial text=, accepting] (0) at (0, 0) {$p$};
\end{tikzpicture}
\caption{$r = \varepsilon$}
\end{minipage}
\begin{minipage}{.3\textwidth}
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick, every state/.style={inner sep=0pt, minimum size=20pt}]
\node[state, initial, initial text=] (0) at (0, 0) {$p$};
\node[state, accepting] (1) at (2, 0) {$q$};
\path (0) edge node {$a$} (1);
\end{tikzpicture}
\caption{$r = a$}
\end{minipage}
\end{figure}\\
Rekursive Fälle: Seien $\mathcal{A}_e, \mathcal{A}_{e^\prime}$ $\varepsilon$-NFAs für die regulären Ausdrücke $e, e^\prime$ mit Startzuständen $q_0, q_0^\prime$ und (verinfachte Darstellung mit nur einem Endzustand) akzeptierenden Zuständen $q_f, q_f^\prime$. In den Abbildungen~\ref{fig:plus},~\ref{fig:dot} und~\ref{fig:star} ist dargestellt wie die Komposition mit $+, \cdot und ^\ast$ funktioniert.
\begin{figure}[h]
\begin{minipage}{.49\textwidth}
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick, every state/.style={inner sep=0pt, minimum size=20pt}]
\node[state, initial, initial text=] (0) at (0, 0) {$p$};
\node at (1.7, 1.7) {$\mathcal{A}_e$};
\draw[black, rounded corners] (1.5, 1.5) rectangle (4.5, .5);
\node[state] (1) at (2, 1) {$q_0$};
\node[state, accepting] (2) at (4, 1) {$q_f$};
\node (d1) at (3, 1) {$\cdots$};
\node at (1.7, -1.7) {$\mathcal{A}_{e^\prime}$};
\draw[black, rounded corners] (1.5, -1.5) rectangle (4.5, -.5);
\node[state] (3) at (2, -1) {$q_0^\prime$};
\node[state, accepting] (4) at (4, -1) {$q_f^\prime$};
\node (d2) at (3, -1) {$\cdots$};
\path (0) edge node {$\varepsilon$} (1)
(0) edge node[below left] {$\varepsilon$} (3);
\end{tikzpicture}
\caption{$r = e + e^\prime$}
\label{fig:plus}
\end{minipage}
\begin{minipage}{.49\textwidth}
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick, every state/.style={inner sep=0pt, minimum size=20pt}]
\node[state, initial, initial text=, accepting] (0) at (0, 0) {$p$};
\node at (1.7, .7) {$\mathcal{A}_e$};
\draw[black, rounded corners] (1.5, .5) rectangle (4.5, -.5);
\node[state] (1) at (2, 0) {$q_0$};
\node[state] (2) at (4, 0) {$q_f$};
\node (d1) at (3, 0) {$\cdots$};
\path (0) edge node {$\varepsilon$} (1)
(2) edge[bend right=60] node[above] {$\varepsilon$} (0);
\end{tikzpicture}
\caption{$r = e^\ast$}
\label{fig:star}
\end{minipage}
\end{figure}
\begin{figure}[h]
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick, every state/.style={inner sep=0pt, minimum size=20pt}]
\node at (1.7, .7) {$\mathcal{A}_e$};
\draw[black, rounded corners] (1.5, .5) rectangle (4.5, -.5);
\node[initial, initial text=, state] (1) at (2, 0) {$q_0$};
\node[state] (2) at (4, 0) {$q_f$};
\node (d1) at (3, 0) {$\cdots$};
\node at (5.7, .7) {$\mathcal{A}_{e^\prime}$};
\draw[black, rounded corners] (5.5, .5) rectangle (8.5, -.5);
\node[state] (3) at (6, 0) {$q_0^\prime$};
\node[state, accepting] (4) at (8, 0) {$q_f^\prime$};
\node (d2) at (7, 0) {$\cdots$};
\path (2) edge node {$\varepsilon$} (3);
\end{tikzpicture}
\caption{$r = e \cdot e^\prime$}
\label{fig:dot}
\end{figure}
Es entstehen viele überflüssige \(\varepsilon\)-Transitionen, in der Hausaufgabe sollten diese aber besser nicht weggelassen werden. Die Konstruktion funktioniert immer und ist auch leichter zu implementieren als vielleicht effizientere Ansätze, die in FoSAP nicht behandelt werden.\par
Ein Minimalbeispiel:
$$
r = (a+b)^\ast c.
$$
Die Automaten für die Teilausdrücke $a, b, c$ sind klar, wir starten mit $(a+b)$ in Abbildung~\ref{fig:re1}.
\begin{figure}[h]
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick]
\node[state, initial, initial text=] (1) at (0, 0) {$q_1$};
\node[state] (2) at (2, 1) {$q_2$};
\node[state, accepting] (3) at (4, 1) {$q_3$};
\node[state] (4) at (2, -1) {$q_4$};
\node[state, accepting] (5) at (4, -1) {$q_5$};
\path (1) edge node {$\varepsilon$} (2)
(1) edge node[below left] {$\varepsilon$} (4)
(2) edge node {$a$} (3)
(4) edge node {$b$} (5);
\end{tikzpicture}
\caption{NFA für $(a + b)$}
\label{fig:re1}
\end{figure}
Um den Kleene'schen Abschluss zu bilden ergänzen wir einen (eigentlich überflüssigen, aber nach Konstruktion erforderlichen) Zustand $q_0^\ast$, der neuer Startzustand wird und akzeptierend wird. Die ursprünglichen akzeptierenden Zustände werden nicht-akzeptierend und bekommen Transitionen zum neuen Startzustand.
\begin{figure}[h]
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick]
\node[state, initial, initial text=, accepting] (0) at (-2, 0) {$q_0$};
\node[state] (1) at (0, 0) {$q_1$};
\node[state] (2) at (2, 1) {$q_2$};
\node[state] (3) at (4, 1) {$q_3$};
\node[state] (4) at (2, -1) {$q_4$};
\node[state] (5) at (4, -1) {$q_5$};
\path (0) edge node {$\varepsilon$} (1)
(1) edge node {$\varepsilon$} (2)
(1) edge node[below left] {$\varepsilon$} (4)
(2) edge node {$a$} (3)
(4) edge node {$b$} (5)
(3) edge[bend right=50] node[above] {$\varepsilon$} (0)
(5) edge[bend left=50] node {$\varepsilon$} (0);
\end{tikzpicture}
\caption{NFA für $(a + b)^\ast$}
\label{fig:re2}
\end{figure}
Zuletzt die Konkatenation von $c$: Dazu fügen wir eine \(\varepsilon\)-Transition vom (noch) akzeptierenden Zustand vom Automaten in Abbildung~\ref{fig:re2} zum Startzustand des trivialen Automaten für die Sprache $\{ c \}$. Der fertige Automat ist in Abbildung~\ref{fig:re3}.
\begin{figure}[h]
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick]
\node[state, initial, initial text=] (0) at (-2, 0) {$q_0$};
\node[state] (1) at (0, 0) {$q_1$};
\node[state] (2) at (2, 1) {$q_2$};
\node[state] (3) at (4, 1) {$q_3$};
\node[state] (4) at (2, -1) {$q_4$};
\node[state] (5) at (4, -1) {$q_5$};
\node[state] (6) at (-2, -3) {$q_6$};
\node[state, accepting] (7) at (0, -3) {$q_7$};
\path (0) edge node {$\varepsilon$} (1)
(1) edge node {$\varepsilon$} (2)
(1) edge node[below left] {$\varepsilon$} (4)
(2) edge node {$a$} (3)
(4) edge node {$b$} (5)
(3) edge[bend right=50] node[above] {$\varepsilon$} (0)
(5) edge[bend left=50] node {$\varepsilon$} (0)
(0) edge node {$\varepsilon$} (6)
(6) edge node {$c$} (7);
\end{tikzpicture}
\caption{NFA für $(a + b)^\ast c$}
\label{fig:re3}
\end{figure}
In den Hausaufgaben müsst ihr das nicht so ausführlich machen. Es reicht der Automat der Am Ende rauskommt. Ihr sollt aber das Verfahren aus der Vorlesung benutzen. Der Automat in Abbildung~\ref{fig:ref} ist zwar viel kleiner und äquivalent, aber nicht zulässig.
\begin{figure}
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick]
\node[state, initial, initial text=] (0) at (0, 0) {$q_0$};
\node[state, accepting] (1) at (2, 0) {$q_1$};
\path (0) edge[loop above] node {$a, b$} (0)
(0) edge node {$c$} (1);
\end{tikzpicture}
\caption{Ein minimaler NFA für die Sprache $L((a+b)^\ast c)$.}
\label{fig:ref}
\end{figure}
\end{document}
\ No newline at end of file
No preview for this file type
\documentclass[11pt, a4paper]{article}
\usepackage[left=3cm, right=3cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage[ngerman]{babel}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{mathtools}
\usepackage{array}
\usepackage{graphicx}
\usepackage{tikz}
\usepackage{listings}
\usepackage[justification=centering]{caption}
\usetikzlibrary{arrows, automata, graphs, shapes, petri, decorations.pathmorphing}
\parindent = 0pt
\let\emptyset\varnothing
% define environments
\theoremstyle{definition}
......@@ -28,7 +33,7 @@
\begin{document}
\maketitle
Bisher sind reguläre Sprachen durch Formalismen wie reguläre Ausdrücke und endliche Automaten charakterisiert worden. Nun soll eine Eigenschaft gefunden werden, die reguläre Sprachen auf einer stark mathematisch-strukturellen Ebene charakterisiert, d.h. mit Aussagen, die sich auf die Struktur
Bisher sind reguläre Sprachen durch Formalismen wie reguläre Ausdrücke und endliche Automaten charakterisiert worden. Nun soll eine Eigenschaft gefunden werden, die reguläre Sprachen auf einer stark mathematisch-struk\-tur\-ellen Ebene charakterisiert, d.h. mit Aussagen, die sich auf die Struktur
\[
(\Sigma^\ast, \cdot, \varepsilon)
\]
......@@ -83,7 +88,7 @@ Man benennt Äquivalenzklassen auch durch einzelne Repräsentanten, z.B. mit \(
Die Vereinigung aller Äquivalenzklassen zu einer Äquivalenz über einer Menge \( A \) bildet stets eine Partition von \( A \).
\subsection*{Finden der Äquivalenzklassen}
Lemma~\ref{kongruenzlemma} kann dafür verwendet werden um Äquivalenzklassen (der Myhill-Nerode-Äquivalenz \( \equiv_L \)) zu finden. Wir gehen dabei wie folgt vor:\\
Lemma~\ref{kongruenzlemma} kann dafür verwendet werden um Äquivalenzklassen (der Myhill-Nerode-Ä\-qui\-va\-lenz \( \equiv_L \)) zu finden. Wir gehen dabei wie folgt vor:\\
Wir starten mit dem leeren Wort \( \varepsilon \) und der zugehörigen Äquivalenzklasse \( [\varepsilon]_L \). Danach wiederholen wir folgende Schritte bis keine neue Äquivalenzklassen mehr gefunden werden:\\
Für jedes Symbol \( a \in \Sigma \) und jede bisher gefundene Äquivalenzklasse \( [u]_L \) betrachte die Äquivalenzklasse \( [ua]_L \). Ist \( [ua]_L = [v]_L \) für eine bereits gefundene Äquivalenzklasse, passiert nichts. Ist dies nicht der Fall, fügen wir \( [ua]_L \) als neue Äquivalenzklasse hinzu.\par
Beachte, dass dieses Verfahren nur für reguläre Sprachen terminiert. Nicht-reguläre Sprachen haben unendlich viele Äquivalenzklassen (s. Satz~\ref{nerode}).\par
......
No preview for this file type
\documentclass[11pt, a4paper]{article}
\usepackage[left=4cm, right=4cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage[ngerman]{babel}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{mathtools}
\usepackage{graphicx}
\usepackage{tikz}
\usepackage{listings}
\usepackage[justification=centering]{caption}
\usetikzlibrary{arrows, automata, graphs, shapes, petri, decorations.pathmorphing}
\parindent = 0pt
\let\emptyset\varnothing
% define environments
\theoremstyle{definition}
\newtheorem{definition}{Definition}
\newtheorem*{definition*}{Definition}
\theoremstyle{plain}
\newtheorem{theorem}[definition]{Theorem}
......@@ -27,29 +32,37 @@
\begin{document}
\maketitle
Die Definition 7.24 aus der Vorlesung (s. Abbildung~\ref{fig:pda2cfg}) beschreibt, wie sich aus einem Pushdown-Automaten, der mit leerem Stack akzeptiert eine kontextfreie Grammatik konstruieren lässt, die die selbe Sprache erzeugt. Das Verfahren ist eigentlich sehr einfach, allerdings ist die Funktionsweise nicht sehr intuitiv, da sich die Produktionsregeln der erzeugten Grammatik nicht so leicht interpretieren lassen (oder: sie lassen sich nicht so einfach von links nach rechts lesen).\par
\begin{figure}
\centering
\includegraphics[scale=.3]{pda2cfg.png}
\caption{Definition 7.24 aus der Vorlesung.}
\label{fig:pda2cfg}
\end{figure}
Wir betrachten also einen PDA, der mit leerem Stack akzeptiert \( \mathcal{A} = (Q, \Sigma, \Gamma, \Delta, q_0, Z_0) \) und konstruieren daraus die Grammatik \( \mathcal{G_A} = (N, \Sigma, P, S) \) wie in Abbildung~\ref{fig:pda2cfg} beschrieben. Die entscheidene Kernidee des Algorithmus ist folgende: Das Nichtterminalsymbol \( [pZq] \) repräsentiert einen Lauf von \( p \) nach \( q \) bei dem das Stacksymbol \( Z \) aus dem Stack entfernt wird (d.h. wir kommen dem leeren Stack ''einen Schritt näher``).\\
Ein Ableitungsschritt in der Grammatik entspricht dabei nicht einfach einer Transition im PDA (außer im Fall von \( [pZq] \to \sigma \), was der Transition \( (p, \sigma, Z, \varepsilon, q) \) entspricht), sondern auch der \textit{Hoffnung} den Stack, der sich in der Transition \( (p, \sigma, Z, Z_1 \ldots Z_k, p_0) \) aufbaut (für \( k > 0 \)) in einer der Zukunft wieder abzubauen. Die Nichtterminale \( [pZq] \) \textit{hoffen} also, dass der PDA von \( p \) mit Stackinhalt \( Z\gamma \) nach \( q \) kommt und dabei nur \( \gamma \) auf dem Stack stehen lässt, wobei \( \gamma \in \Gamma^\ast \). Wir gehen nun einmal auf die drei Arten der Produktionsregeln ein, hierfür sei \( \sigma \in \Sigma \cup \{ \varepsilon \} \):
Die folgende Definition aus der Vorlesung beschreibt, wie sich aus einem Pushdown-Automaten (PDA), der mit leerem Stack akzeptiert, eine kontextfreie Grammatik (CFG) konstruieren lässt, die die selbe Sprache erzeugt.
\begin{definition*}
Sei $\mathcal{A} = (Q, \Sigma, \Gamma, \Delta, q_0, Z_0)$ ein PDA, der mit leerem Stack akzeptiert. Die kontextfreie Grammatik $\mathcal{G}_\mathcal{A} = (N, \Sigma, P, S)$ sei wie folgt definiert:
\begin{itemize}
\item $S$ ist ein neues Startsymbol.
\item Nichtterminale $N \coloneqq \{S\} \cup \{[pZq] \mid p, q\in Q, Z \in \Gamma\}$.
\item Produktionsregeln
\begin{align*}
P &\coloneqq \{[pZq] \to \sigma [p_0Z_1p_1][p_1Z_2p_2]\ldots[p_{m-1}Z_mq] \mid\\
&\quad\quad (p, \sigma, Z, Z_1 \ldots Z_m, p_0) \in \Delta, p_1, \ldots, p_{m-1}, q \in Q\}\\
&\cup \{S \to [q_0Z_0q] \mid q \in Q\}.
\end{align*}
\end{itemize}
\end{definition*}
Das Verfahren ist eigentlich sehr einfach, allerdings ist die Funktionsweise nicht sehr intuitiv, da sich die Produktionsregeln der erzeugten Grammatik nicht so leicht interpretieren lassen (oder: sie lassen sich nicht so einfach von links nach rechts lesen).
Wir betrachten also einen PDA, der mit leerem Stack akzeptiert $\mathcal{A} = (Q, \Sigma, \Gamma, \Delta, q_0, Z_0)$ und konstruieren daraus die Grammatik $\mathcal{G_A} = (N, \Sigma, P, S)$ wie in der Definition beschrieben. Die entscheidene Kernidee des Algorithmus ist folgende: Das Nichtterminalsymbol $[pZq]$ repräsentiert einen Lauf von $p$ nach $q$ bei dem das Stacksymbol $Z$ aus dem Stack entfernt wird (d.h. wir kommen dem leeren Stack ''einen Schritt näher``).\\
Ein Ableitungsschritt in der Grammatik entspricht dabei nicht einfach einer Transition im PDA (außer im Fall von $[pZq] \to \sigma$, was der Transition $(p, \sigma, Z, \varepsilon, q)$ entspricht), sondern auch der \textit{Hoffnung} den Stack, der sich in der Transition $(p, \sigma, Z, Z_1 \ldots Z_k, p_0)$ aufbaut (für $k > 0$) in einer der Zukunft wieder abzubauen. Die Nichtterminale $[pZq]$ \textit{hoffen} also, dass der PDA von $p$ mit Stackinhalt $Z\gamma$ nach $q$ kommt und dabei nur $\gamma$ auf dem Stack stehen lässt, wobei $\gamma \in \Gamma^\ast$. Wir gehen nun einmal auf die drei Arten der Produktionsregeln ein, hierfür sei $\sigma \in \Sigma \cup \{ \varepsilon \}$:
\begin{itemize}
\item Mit dem Startsymbol \( S \) haben wir folgende Produktionsregeln: \( S \to [q_0 Z_0 q] \) \textbf{für alle} \( q \in Q \).\\
Die Akzeptanzbedingung des Automatenmodells ist allein vom Stack abhängig, in welchem Zustand ein Lauf terminiert ist also egal, deswegen bilden wir diese Regel für jedes \( q \). Hier rufen wir uns nochmal die Intuition der Nichtterminale (außer \( S \)) in Erinnerung: Gesucht wird also ein Lauf auf \( \mathcal{A} \) vom Startzustand \( q_0 \) zu einem beliebigen \( q \), sodass das Bottom-of-Stack-Symbol \( Z_0 \) weggenommen wird (d.h. nur noch \( \varepsilon \) auf dem Stack steht). Diese Regeln sind drücken also genau unseren gewünschten Lauf aus: Von der Startkonfiguration \( (q_0, Z_0) \) zu einer Konfiguration \( (q, \varepsilon) \).
\item Für die Transitionen der Form \( (p, \sigma, Z, \varepsilon, q) \) erhalten wir die Produktionsregel \( [pZq] \to \sigma \). Dies sind die Regeln in denen der Stack tatsächlich abgebaut wird ohne ihn vorher zu erweitern (s. nächster Punkt).
\item Regeln der Form \( [pZp_m] \to \sigma [p_0 Z_1 p_1][p1 Z_2 p_2] \ldots [p_{m-1} Z_m p_m] \) für eine Transition \( (p, \sigma, Z, Z_1 \ldots Z_m, p_0) \in \Delta \) und \textbf{alle möglichen(!)} Zustände \( p_1, \ldots, p_m \in Q \):\\
\item Mit dem Startsymbol $S$ haben wir folgende Produktionsregeln: $S \to [q_0 Z_0 q]$ \textbf{für alle} $q \in Q$.\\
Die Akzeptanzbedingung des Automatenmodells ist allein vom Stack abhängig, in welchem Zustand ein Lauf terminiert ist also egal, deswegen bilden wir diese Regel für jedes $q$. Hier rufen wir uns nochmal die Intuition der Nichtterminale (außer $S$) in Erinnerung: Gesucht wird also ein Lauf auf $\mathcal{A}$ vom Startzustand $q_0$ zu einem beliebigen $q$, sodass das Bottom-of-Stack-Symbol $Z_0$ weggenommen wird (d.h. nur noch $\varepsilon$ auf dem Stack steht). Diese Regeln sind drücken also genau unseren gewünschten Lauf aus: Von der Startkonfiguration $(q_0, Z_0)$ zu einer Konfiguration $(q, \varepsilon)$.
\item Für die Transitionen der Form $(p, \sigma, Z, \varepsilon, q)$ erhalten wir die Produktionsregel $[pZq] \to \sigma$. Dies sind die Regeln in denen der Stack tatsächlich abgebaut wird ohne ihn vorher zu erweitern (s. nächster Punkt).
\item Regeln der Form $[pZp_m] \to \sigma [p_0 Z_1 p_1][p1 Z_2 p_2] \ldots [p_{m-1} Z_m p_m]$ für eine Transition $(p, \sigma, Z, Z_1 \ldots Z_m, p_0) \in \Delta$ und alle möglichen(!) Zustände $p_1, \ldots, p_m \in Q$:\\
Dies ist die schwerste Art der konstruierten Produktionsregeln. Wir versuchen dies trotzdem einmal in einem Satz von links nach rechts zu beschreiben, auch wenn das etwas konstruiert wirkt:
Wir befinden uns in Zustand \( p \) mit \( Z \) oben auf dem Stack, welches wir entfernen wollen, und dabei den Zustand \( p_m \) erreichen mit einer Transition über \( \sigma \), wo wir den Stack mit \( Z_1, \ldots, Z_m \) auffüllen, welche wir dann in der Zukunft, d.h. in einem Lauf über \( p_0 \) bis \( p_m \), abbauen müssen über weitere Regeln dieser Form und -- schlussendlich -- über Regeln der Art aus dem vorigen Punkt.\\
Eine Ableitung eines Wortes repräsentiert also genau einen akzeptierenden (d.h. mit \( \varepsilon \) auf dem Stack am Ende) Lauf auf dem PDA.
Wir befinden uns in Zustand $p$ mit $Z$ oben auf dem Stack, welches wir entfernen wollen, und dabei den Zustand $p_m$ erreichen mit einer Transition über $\sigma$, wo wir den Stack mit $Z_1, \ldots, Z_m$ auffüllen, welche wir dann in der Zukunft, d.h. in einem Lauf über $p_0$ bis $p_m$, abbauen müssen über weitere Regeln dieser Form und -- schlussendlich -- über Regeln der Art aus dem vorigen Punkt.\\
Eine Ableitung eines Wortes repräsentiert also genau einen akzeptierenden (d.h. mit $\varepsilon$ auf dem Stack am Ende) Lauf auf dem PDA.
\end{itemize}
Um die Philosophie der Konstruktion einmal zusammenzufassen: Wenn in einem akzeptierenden Lauf der aktuelle Stackinhalt zu einem Zeitpunkt \( Z\gamma \) ist, dann wird zu einem späteren Punkt des Laufes der Stackinhalt einmal nur noch \( \gamma \) sein.\\
Um die Philosophie der Konstruktion einmal zusammenzufassen: Wenn in einem akzeptierenden Lauf der aktuelle Stackinhalt zu einem Zeitpunkt $Z\gamma$ ist, dann wird zu einem späteren Punkt des Laufes der Stackinhalt einmal nur noch $\gamma$ sein.\\
Wir betrachten als Beispiel den PDA, der mit leerem Stack akzeptiert in Abbildung~\ref{fig:pda}. Sei dafür
\[
$$
\mathcal{A} = (\{ p, q \}, \{ a, b \}, \{ Z \}, \{(p, a, Z, ZZ, p), (p, a, Z, Z, q), (q, b, Z, \varepsilon, q) \}, p, Z).
\]
$$
\begin{figure}
\centering
\begin{tikzpicture}[->, >=stealth', shorten >=1pt, auto, semithick]
......@@ -60,28 +73,28 @@ Wir betrachten als Beispiel den PDA, der mit leerem Stack akzeptiert in Abbildun
(p) edge[loop above] node {$(a, Z, ZZ)$} (p)
(q) edge[loop above] node {$(b, Z, \varepsilon)$} (q);
\end{tikzpicture}
\caption{PDA, der mit leerem Stack akzeptiert für die Sprache \( L = \{ a^n b^n : n \in \mathbb{N}_+ \} \).}
\caption{PDA, der mit leerem Stack akzeptiert für die Sprache $L = \{ a^n b^n : n \in \mathbb{N}_+ \}$.}
\label{fig:pda}
\end{figure}
Wir erhalten zunächst für die Grammatik \( \mathcal{G_A} = (N, \{ a, b \}, P, S) \) mit \( N = \{ S, [pZp], [pZq], [qZp], [qZq] \} \). Die Produktionsregeln \( P \) konstruieren wir nacheinander:
Wir erhalten zunächst für die Grammatik $\mathcal{G_A} = (N, \{ a, b \}, P, S)$ mit $N = \{ S, [pZp], [pZq], [qZp], [qZq] \}$. Die Produktionsregeln $P$ konstruieren wir nacheinander:
\begin{itemize}
\item Zunächst ist es uns egal in welchem Zustand wir terminieren (auch wenn ein akzeptierender Lauf offensichtlich nur in \( q \) enden kann), die einzige Bedingung, die wir an den Lauf stellen ist, dass er im Startzustand \( p \) beginnt mit dem Bottom-of-Stack-Symbol \( Z \) oben auf dem Stack. Insgesamt erhalten wir also die Regeln
\[
\item Zunächst ist es uns egal in welchem Zustand wir terminieren (auch wenn ein akzeptierender Lauf offensichtlich nur in $q$ enden kann), die einzige Bedingung, die wir an den Lauf stellen ist, dass er im Startzustand $p$ beginnt mit dem Bottom-of-Stack-Symbol $Z$ oben auf dem Stack. Insgesamt erhalten wir also die Regeln
$$
S \to [pZp] \,\vert\, [pZq] \in P.
\]
\item Nun betrachten wir die Transitionen, die den Stack abbauen. Davon gibt es nur eine im Loop über \( q \), d.h. \( (q, b, Z, \varepsilon, q) \). Wir erhalten also:
\[
$$
\item Nun betrachten wir die Transitionen, die den Stack abbauen. Davon gibt es nur eine im Loop über $q$, d.h. $(q, b, Z, \varepsilon, q)$. Wir erhalten also:
$$
[qZq] \to b \in P.
\]
\item Zuletzt noch die Transitionen, die den Stack vorübergehend aufbauen. Für die Transition \( (p, a, Z, ZZ, p) \) erhalten wir die Regeln
$$
\item Zuletzt noch die Transitionen, die den Stack vorübergehend aufbauen. Für die Transition $(p, a, Z, ZZ, p)$ erhalten wir die Regeln
\begin{align*}
[pZp] &\to a[pZp][pZp] \,\vert\, a[pZq][qZp],\\
[pZq] &\to a[pZp][pZq] \,\vert\, a[pZq][qZq] \in P
\end{align*}
und für die Transition \( (p, a, Z, Z, q) \) nur die Regel