Abgabe als .py-Datei (bei mehreren Dateien als .zip komprimiert) an e.nie@campus.lmu.de bis 11.11.2021 (Keine Pflicht).
In dieser Woche wird ein Deterministischer Endlicher Automat als Klasse in Python implementiert und dann mithilfe der Python-Bibliothek graphviz
visualisiert.
In dieser Aufgabe soll ein Deterministischer Endlicher Automat implementiert werden.
Für diese Aufgabe werden die Datenstrukturen der Parameter für den Konstruktur (=__init__
) der Klasse wie folgt definiert:
set
von Symbolen.set
von Zahlen (den Namen der Zustände)set
, eine Teilmenge von Qset
mit tuple
-Objekten der Länge 3, mit der Form (q_from, label, q_to)
a) Denke dir Beispieldaten nach dem obrigen Schema aus, die später benutzt werden, um den Automaten zu initialisieren. Definiere dazu eine Variable für jedes der Symbole, und weise einen passenden, selbstgewälten Wert zu. Acht darauf, dass ein deterministischer, endlicher Automat entsteht.
*Tipp: Unter Umständen hilft es, einen einfachen Automaten zu zeichnen, den du dann umsetzt. Dann wird es später leichter, zu prüfen, ob deine Klasse funktioniert.
b) Schreibe eine neue Klasse DEA
, deren __init__
-Funktion die obrigen 5 Elemente annimmt.
c) Immer über das set
zu iterieren ist ineffizient. Der Lookup mithilfe eines dict
ist viel schneller. Ändere deshalb die __init__
-Funktion so, dass die Übergangsfunktion $\delta$ als Dictionary gespeichert wird. Die key
-Einträge sollen dabei Kombinationen von Zustand und Label sein, die value
-Einträge das Ziel des Übergangs. Die Form des key
-value
-Paares sieht aus wie (q_from, label) : q_to
.
d) Schreibe eine Methode transition(self, q_from, label)
, die einen Zustand oder None
zurückliefert, je nachdem, ob es von q_from
einen Übergang mit Label label
gibt. Wenn es den Übergang gibt, dann wird der Zielzustand q_to
zurückgegeben. Benutze für diese Methode das schnelle dict
aus Aufgabe c).
e) Füge eine Methode accept(self, sequence)
hinzu, die eine Sequenz von Eingabesymbolen annimmt, und die boolschen Werte True
oder False
zurückliefert, je nachdem, ob dieser Automat die Eingabe akzeptiert. Benutze dazu die Funkion transition
aus der letzten Aufgabe.
Achtung: Die folgenden Szenarien muss man beachten:
f) Teste deine accept
-Methode mit einigen Eingaben.
Zeit, den Automat zu zeichnen! Wir benutzen dazu die Bibliothek graphviz
. Um es in Python zu benutzen, brauchsr du sowohl die Python-API (https://pypi.org/project/graphviz/) als auch das Rendering (https://www.graphviz.org/download/).
a) Stelle sicher, dass eine Instanz der DEA
-Klasse folgende Attribute hat:
sigma
liefert ein set
von Symbolenstates
liefert ein set
von Zustandsnamen (Zahlen)initial_state
liefert den Startzustandfinal_states
liefert ein set
von Finalzuständendelta
liefert ein set
von 3-Tupeln der Form (q_from, label, q_to)
Hinweis: Um delta
als ein set
von 3-Tupeln abzurufen, wird es dazu @property
empfohlen, den Decorator @property
zu verwenden.
Beispiel:
class DEA:
def __init__(self, delta): # ...
# ...
self._delta = # Verwende dict, um die Übergangsfunktion zu speichern.
@property
def delta(self):
# liefere delta als set aus self._delta
return # set von 3-Tupeln
aut = DEA()
aut.delta # greife auf Übergangsfunktion in Tupelform zu
b) Ersetze das TODO
durch eine Instanz der DEA
-Klasse, um deinen Automat an die Funktion zu übergeben und ihn zu zeichnen.
import graphviz
def draw_automaton(aut):
g = graphviz.Digraph('Automaton')
for state in aut.states:
if state in aut.final_states:
g.attr('node', style='bold')
if state == aut.initial_state:
g.node(str(state), label='-> ' + str(state))
else:
g.node(str(state))
g.attr('node', style='solid')
for x, label, z in aut.delta:
g.edge(str(x), str(z), label=' ' + label + ' ')
return g
# Aufruf durch
g = draw_automaton(TODO)
g.render('graphviz/aut.gv', view=True)