diff options
Diffstat (limited to 'edit-lens/src/Control/FST.lhs')
-rw-r--r-- | edit-lens/src/Control/FST.lhs | 33 |
1 files changed, 16 insertions, 17 deletions
diff --git a/edit-lens/src/Control/FST.lhs b/edit-lens/src/Control/FST.lhs index 9cc7524..165f247 100644 --- a/edit-lens/src/Control/FST.lhs +++ b/edit-lens/src/Control/FST.lhs | |||
@@ -47,12 +47,12 @@ import Text.Dot | |||
47 | \end{comment} | 47 | \end{comment} |
48 | 48 | ||
49 | \begin{defn}[Finite State Transducers] | 49 | \begin{defn}[Finite State Transducers] |
50 | Unter einem \emph{finite state transducer} verstehen wir ein 6-Tupel $(\Sigma, \Delta, Q, I, F, E)$ mit $\Sigma$ dem endlichen Eingabe-Alphabet, $\Delta$ dem endlichen Ausgabe-Alphabet, $Q$ einer endlichen Menge an Zuständen, $I \subset Q$ der Menge von initialen Zuständen, $F \subset Q$ der Menge von akzeptierenden Endzuständen, und $E \subset Q \times (\Sigma \cup \{ \epsilon \}) \times (\Delta \cup \{ \epsilon \}) \times Q$ der Transitionsrelation. | 50 | Unter einem \emph{finite state transducer} verstehen wir ein 6-Tupel $(\Sigma, \Delta, Q, I, F, E)$ mit $\Sigma$ dem endlichen Eingabe-Alphabet, $\Delta$ dem endlichen Ausgabe-Alphabet, $Q$ einer endlichen Menge an Zuständen, $I \subset Q$ der Menge von initialen Zuständen, $F \subset Q$ der Menge von akzeptierenden Endzuständen und $E \subset Q \times (\Sigma \cup \{ \epsilon \}) \times (\Delta \cup \{ \epsilon \}) \times Q$ der Transitionsrelation. |
51 | 51 | ||
52 | Semantisch ist ein finite state transducer ein endlicher Automat erweitert um die Fähigkeit bei Zustandsübergängen ein Symbol aus seinem Ausgabe-Alphabet an ein Ausgabe-Wort anzuhängen. | 52 | Semantisch ist ein finite state transducer ein endlicher Automat, erweitert um die Fähigkeit bei Zustandsübergängen ein Symbol aus seinem Ausgabe-Alphabet an ein Ausgabe-Wort anzuhängen (Siehe Definition \ref{defn:fst-eval}). |
53 | 53 | ||
54 | In Haskell lockern wir die Anforderung, dass die Ein- und Ausgabe-Alphabete endlich sein müssen und annotieren sie nur im Typsystem. | 54 | In Haskell lockern wir die Anforderung, dass die Ein- und Ausgabe-Alphabete endlich sein müssen und annotieren sie nur im Typsystem. |
55 | Zudem speichern wir die Transitionsrelation als multimap um effiziente lookups von Zustand-Eingabe-Paaren zu ermöglichen. | 55 | Zudem speichern wir die Transitionsrelation als multimap, um effiziente lookups von Zustand-Eingabe-Paaren zu ermöglichen. |
56 | 56 | ||
57 | \begin{code} | 57 | \begin{code} |
58 | data FST state input output = FST | 58 | data FST state input output = FST |
@@ -64,7 +64,7 @@ data FST state input output = FST | |||
64 | \end{defn} | 64 | \end{defn} |
65 | 65 | ||
66 | \begin{eg} \label{eg:linebreak} | 66 | \begin{eg} \label{eg:linebreak} |
67 | Als wiederkehrendes Beispiel betrachten wir einen Transducer $L_{80} = (\Sigma, \Delta, Q, I, F, E)$, der für ein beliebiges Alphabet $\Sigma \supseteq \{ \text{\tt ' '}, \text{\tt \textbackslash n} \}$ durch Umwandlung zwischen Leerzeichen und Zeilenumbrüchen sicherstellt, dass jede Zeile des Ausgabetextes möglichst wenige aber mindestens 80 Zeichen enthält, und nur an Wortgrenzen umbricht: | 67 | Als wiederkehrendes Beispiel betrachten wir einen Transducer $L_{80} = (\Sigma, \Delta, Q, I, F, E)$, der für ein beliebiges Alphabet $\Sigma \supseteq \{ \text{\tt ' '}, \text{\tt \textbackslash n} \}$ durch Umwandlung zwischen Leerzeichen und Zeilenumbrüchen sicherstellt, dass jede Zeile des Ausgabetextes möglichst wenige, aber mindestens 80 Zeichen enthält und nur an Wortgrenzen umbricht: |
68 | 68 | ||
69 | \begin{align*} | 69 | \begin{align*} |
70 | \Delta & = \Sigma \\ | 70 | \Delta & = \Sigma \\ |
@@ -103,7 +103,7 @@ data FST state input output = FST | |||
103 | \draw[-] (rest)--(i.north); | 103 | \draw[-] (rest)--(i.north); |
104 | \draw[-] (rest)--(si.west); | 104 | \draw[-] (rest)--(si.west); |
105 | \end{tikzpicture} | 105 | \end{tikzpicture} |
106 | \caption{\label{fig:linebreak} Ein Transducer der, durch Übersetzung zwischen Leerzeichen und Zeilenumbrüchen, sicher stellt, dass jede Zeile eines Texts mindestens 80 Zeichen hat} | 106 | \caption{\label{fig:linebreak} Ein Transducer der durch Übersetzung zwischen Leerzeichen und Zeilenumbrüchen sicher stellt, dass jede Zeile eines Texts mindestens 80 Zeichen hat} |
107 | \end{figure} | 107 | \end{figure} |
108 | \end{eg} | 108 | \end{eg} |
109 | 109 | ||
@@ -131,8 +131,8 @@ instance (Show state, Show input, Show output, Ord state, Ord input, Ord output) | |||
131 | \end{code} | 131 | \end{code} |
132 | \end{comment} | 132 | \end{comment} |
133 | 133 | ||
134 | \begin{defn}[Auswertung von FSTs] | 134 | \begin{defn}[Auswertung von FSTs] \label{defn:fst-eval} |
135 | Wir definieren die \emph{Auswertung} von finite state transducers induktiv indem wir zunächst angeben wie ein einzelner Auswertungs-Schritt erfolgt. | 135 | Wir definieren die \emph{Auswertung} von finite state transducers induktiv, indem wir zunächst angeben, wie ein einzelner Auswertungs-Schritt erfolgt. |
136 | 136 | ||
137 | Hierzu kommentieren wir die Haskell-Implementierung eines Auswertungs-Schritts. | 137 | Hierzu kommentieren wir die Haskell-Implementierung eines Auswertungs-Schritts. |
138 | Notwendigerweise ist die Auswertung eines FSTs nicht deterministisch, wir produzieren daher eine Liste von möglichen Resultaten in keiner besonderen Reihenfolge. | 138 | Notwendigerweise ist die Auswertung eines FSTs nicht deterministisch, wir produzieren daher eine Liste von möglichen Resultaten in keiner besonderen Reihenfolge. |
@@ -145,7 +145,7 @@ step :: forall input output state. (Ord input, Ord output, Ord state) | |||
145 | -> [(Maybe input, state, Maybe output)] -- ^ Tuples of unconsumed input, next state, and produced output | 145 | -> [(Maybe input, state, Maybe output)] -- ^ Tuples of unconsumed input, next state, and produced output |
146 | step FST{..} Nothing inS = (\s -> (inS, s, Nothing)) <$> Set.toList stInitial | 146 | step FST{..} Nothing inS = (\s -> (inS, s, Nothing)) <$> Set.toList stInitial |
147 | \end{code} | 147 | \end{code} |
148 | Ist kein vorheriger Schritt erfolgt so wählen wir einen initialen Zustand, konsumieren keine Eingabe, und produzieren keine Ausgabe. | 148 | Ist kein vorheriger Schritt erfolgt, so wählen wir einen initialen Zustand, konsumieren keine Eingabe und produzieren keine Ausgabe. |
149 | 149 | ||
150 | \begin{code} | 150 | \begin{code} |
151 | step FST{..} (Just c) inS = let | 151 | step FST{..} (Just c) inS = let |
@@ -154,7 +154,7 @@ step FST{..} (Just c) inS = let | |||
154 | in Set.toList $ Set.map (\(n, mOut) -> (Nothing, n, mOut)) consuming `Set.union` Set.map (\(n, mOut) -> (inS, n, mOut)) unconsuming | 154 | in Set.toList $ Set.map (\(n, mOut) -> (Nothing, n, mOut)) consuming `Set.union` Set.map (\(n, mOut) -> (inS, n, mOut)) unconsuming |
155 | \end{code} | 155 | \end{code} |
156 | Ansonsten wählen wir einen Eintrag aus der Transitionstabelle für den aktuellen Zustand, der entweder keine oder die gegebene Eingabe konsumiert. | 156 | Ansonsten wählen wir einen Eintrag aus der Transitionstabelle für den aktuellen Zustand, der entweder keine oder die gegebene Eingabe konsumiert. |
157 | Im Ergebnis geben wir den nächsten Zustand, die Ausgabe aus der Transitionstabelle, und ob die Eingabe konsumiert wurde an. | 157 | Im Ergebnis geben wir den nächsten Zustand, die Ausgabe aus der Transitionstabelle und ob die Eingabe konsumiert wurde, an. |
158 | 158 | ||
159 | \begin{code} | 159 | \begin{code} |
160 | runFST' :: forall input output state. (Ord input, Ord output, Ord state) | 160 | runFST' :: forall input output state. (Ord input, Ord output, Ord state) |
@@ -199,9 +199,8 @@ akzeptierenden Endzustände liegt. | |||
199 | \end{comment} | 199 | \end{comment} |
200 | \end{defn} | 200 | \end{defn} |
201 | 201 | ||
202 | Es ist gelegentlich nützlich nur die möglichen Ausgaben eines FST auf gegebener | 202 | Es ist gelegentlich nützlich nur die möglichen Ausgaben eines FST auf gegebener Eingabe zu bestimmen. |
203 | Eingabe zu bestimmen, wir führen eine Hilfsfunktion auf Basis von | 203 | Wir führen eine Hilfsfunktion auf Basis von {\ttfamily runFST'} ein: |
204 | {\ttfamily runFST'} ein: | ||
205 | 204 | ||
206 | \begin{code} | 205 | \begin{code} |
207 | runFST :: forall input output state. (Ord input, Ord output, Ord state) => FST state input output -> Seq input -> [Seq output] | 206 | runFST :: forall input output state. (Ord input, Ord output, Ord state) => FST state input output -> Seq input -> [Seq output] |
@@ -216,14 +215,14 @@ runFST = fmap (map $ catMaybes . fmap (view _2) . view _2) . runFST' | |||
216 | \end{comment} | 215 | \end{comment} |
217 | 216 | ||
218 | Wir können das Produkt zweier FSTs definieren. | 217 | Wir können das Produkt zweier FSTs definieren. |
219 | Intuitiv wollen wir beide FSTs gleichzeitig ausführen und dabei sicherstellen, dass Ein- und Ausgabe der FSTs übereinstimmen\footnote{Da wir $\epsilon$-Transitionen in FSTs erlauben müssen wir uns festlegen wann eine $\epsilon$-Transition übereinstimmt mit einer anderen Transition. Wir definieren, dass $\epsilon$ als Eingabe ausschließlich mit $\epsilon$ übereinstimmt.}. | 218 | Intuitiv wollen wir beide FSTs gleichzeitig ausführen und dabei sicherstellen, dass Ein- und Ausgabe der FSTs übereinstimmen\footnote{Da wir $\epsilon$-Transitionen in FSTs erlauben, müssen wir uns festlegen, wann eine $\epsilon$-Transition übereinstimmt mit einer anderen Transition. Wir definieren, dass $\epsilon$ als Eingabe ausschließlich mit $\epsilon$ übereinstimmt.}. |
220 | 219 | ||
221 | Hierfür berechnen wir das Graphen-Produkt der FSTs: | 220 | Hierfür berechnen wir das Graphen-Produkt der FSTs: |
222 | 221 | ||
223 | \begin{defn}[FST-Produkt] | 222 | \begin{defn}[FST-Produkt] |
224 | Gegeben zwei finite state transducer $T = (\Sigma, \Delta, Q, I, F, E)$ und $T^\prime = (\Sigma^\prime, \Delta^\prime, Q^\prime, I^\prime, F^\prime, E^\prime)$ nennen wir $T^\times = (\Sigma^\times, \Delta^\times, Q^\times, I^\times, F^\times, E^\times)$ das Produkt $T^\times = T \times T^\prime$ von $T$ und $T^\prime$. | 223 | Gegeben zwei finite state transducer $T = (\Sigma, \Delta, Q, I, F, E)$ und $T^\prime = (\Sigma^\prime, \Delta^\prime, Q^\prime, I^\prime, F^\prime, E^\prime)$ nennen wir $T^\times = (\Sigma^\times, \Delta^\times, Q^\times, I^\times, F^\times, E^\times)$ das Produkt $T^\times = T \times T^\prime$ von $T$ und $T^\prime$. |
225 | 224 | ||
226 | $T^\times$ bestimmt sich als das Graphenprodukt der beiden, die FSTs unterliegenden, Graphen wobei wir die Zustandsübergänge als Kanten mit Gewichten aus dem Boolschen Semiring auffassen: | 225 | $T^\times$ wird bestimmt als das Graphenprodukt der beiden die FSTs unterliegenden Graphen wobei wir die Zustandsübergänge als Kanten mit Gewichten aus dem Boolschen Semiring auffassen: |
227 | 226 | ||
228 | \begin{align*} | 227 | \begin{align*} |
229 | \Sigma^\times & = \Sigma \cap \Sigma^\prime \\ | 228 | \Sigma^\times & = \Sigma \cap \Sigma^\prime \\ |
@@ -271,7 +270,7 @@ productFST fst1 fst2 = FST | |||
271 | Es ist später erforderlich einen FST derart einzuschränken, dass er eine gegebene Ausgabe produziert. | 270 | Es ist später erforderlich einen FST derart einzuschränken, dass er eine gegebene Ausgabe produziert. |
272 | 271 | ||
273 | Hierzu nehmen wir das FST-Produkt mit einem FST, der, ungeachtet der Eingabe, immer die gewünschte Ausgabe produziert. | 272 | Hierzu nehmen wir das FST-Produkt mit einem FST, der, ungeachtet der Eingabe, immer die gewünschte Ausgabe produziert. |
274 | Da die Ausgaben der beiden FSTs übereinstimmen müssen produziert das Produkt mit einem derartigen FST (solange dessen Ausgabe in keinem Sinne von der Eingabe abhängt) die gewünschte Ausgabe. | 273 | Da die Ausgaben der beiden FSTs übereinstimmen müssen, produziert das Produkt mit einem derartigen FST (solange dessen Ausgabe in keinem Sinne von der Eingabe abhängt) die gewünschte Ausgabe. |
275 | 274 | ||
276 | Zur Konstruktion eines derartigen \emph{Wort-FST}s nehmen wir Indizes im Ausgabe-Wort (natürliche Zahlen) als Zustände. | 275 | Zur Konstruktion eines derartigen \emph{Wort-FST}s nehmen wir Indizes im Ausgabe-Wort (natürliche Zahlen) als Zustände. |
277 | Übergänge sind immer entweder der Form $n \rightarrow \text{succ}(n)$, konsumieren keine Eingabe ($\epsilon$) und produzieren als Ausgabe das Zeichen am Index $n$ im Ausgabe-Wort, oder der Form $n \overset{(\sigma, \epsilon)}{\rightarrow} n$, für jedes Eingabesymbol $\sigma$ (um die Unabhängigkeit von der Eingabe sicherzustellen). | 276 | Übergänge sind immer entweder der Form $n \rightarrow \text{succ}(n)$, konsumieren keine Eingabe ($\epsilon$) und produzieren als Ausgabe das Zeichen am Index $n$ im Ausgabe-Wort, oder der Form $n \overset{(\sigma, \epsilon)}{\rightarrow} n$, für jedes Eingabesymbol $\sigma$ (um die Unabhängigkeit von der Eingabe sicherzustellen). |
@@ -335,7 +334,7 @@ wordFST inps outs = FST | |||
335 | \end{figure} | 334 | \end{figure} |
336 | \end{eg} | 335 | \end{eg} |
337 | 336 | ||
338 | Da \texttt{wordFST} zur Konstruktion eine komprehensive Menge aller Eingabesymbole benötigt verwenden wir im folgenden eine optimierte Variante des Produkts mit einem Wort-FST. | 337 | Da \texttt{wordFST} zur Konstruktion eine komprehensive Menge aller Eingabesymbole benötigt, verwenden wir im Folgenden eine optimierte Variante des Produkts mit einem Wort-FST. |
339 | 338 | ||
340 | \begin{code} | 339 | \begin{code} |
341 | restrictOutput :: forall state input output. (Ord state, Ord input, Ord output) => Seq output -> FST state input output -> FST (Natural, state) input output | 340 | restrictOutput :: forall state input output. (Ord state, Ord input, Ord output) => Seq output -> FST state input output -> FST (Natural, state) input output |
@@ -381,7 +380,7 @@ restrictOutput :: forall state input output. (Ord state, Ord input, Ord output) | |||
381 | \begin{rem} | 380 | \begin{rem} |
382 | Es ist bemerkenswert, dass in Beispiel \ref{eg:l80timesw100} die zirkuläre Struktur von $L_{80}$ durch das Produkt mit einem Wort verloren geht. | 381 | Es ist bemerkenswert, dass in Beispiel \ref{eg:l80timesw100} die zirkuläre Struktur von $L_{80}$ durch das Produkt mit einem Wort verloren geht. |
383 | 382 | ||
384 | I.\@A.\@ ist das Produkt eines beliebigen FST mit einem Wort-FST zwar nicht azyklisch, erbt jedoch die lineare Struktur des Wort-FST in dem Sinne, dass Fortschritt in Richtung der akzeptierenden Zustände nur möglich ist indem der $(i, \sigma, w_i, i + 1)$-Klasse von Transitionen des Wort-FSTs gefolgt wird. | 383 | I.\@A.\@ ist das Produkt eines beliebigen FST mit einem Wort-FST zwar nicht azyklisch, erbt jedoch die lineare Struktur des Wort-FST in dem Sinne, dass Fortschritt in Richtung der akzeptierenden Zustände nur möglich ist, indem der $(i, \sigma, w_i, i + 1)$-Klasse von Transitionen des Wort-FSTs gefolgt wird. |
385 | \end{rem} | 384 | \end{rem} |
386 | 385 | ||
387 | \begin{comment} | 386 | \begin{comment} |