Im Folgenden habe ich eine Antwort für n
gleich 5 geschrieben, aber Sie können denselben Ansatz anwenden, um DFAs für jeden Wert n
und jedes Positionsnummernsystem zu zeichnen , z. B. binär, ternär ...
Zuerst den Begriff 'Vollständiger DFA' verwenden. Ein DFA , der für die vollständige Domäne in δ: Q × Σ → Q definiert ist, wird als 'Vollständiger DFA' bezeichnet. Mit anderen Worten können wir sagen; Im Übergangsdiagramm des vollständigen DFA fehlt keine Kante (z. B. ist von jedem Zustand in Q für jedes Sprachsymbol in Σ eine ausgehende Kante vorhanden). Hinweis: Manchmal definieren wir partielle DFA als δ ⊆ Q × Σ → Q (Lesen: Wie liest „δ: Q × Σ → Q“ in der Definition einer DFA ).
Design DFA akzeptiert Binärzahlen, die durch die Zahl 'n' teilbar sind:
Schritt 1 : Wenn Sie eine Zahl ω durch dividieren, n
kann die Erinnerung entweder 0, 1, ..., (n - 2) oder (n - 1) sein. Wenn der Rest ist 0
, bedeutet dies, dass ω durch n
sonst nicht teilbar ist . In meinem DFA gibt es also einen Zustand q r , der einem Restwert entspricht r
, wobei 0 <= r <= (n - 1)
und die Gesamtzahl der Zustände in DFA ist n
.
Nach der Verarbeitung einer Zahlenfolge ω über Σ impliziert der Endzustand q r , dass ω% n => r (% Erinnerungsoperator).
In allen Automaten ist der Zweck eines Zustands wie ein Speicherelement. Ein Zustand in einem Atomata speichert einige Informationen wie den Schalter des Lüfters, die erkennen können, ob sich der Lüfter im Zustand "Aus" oder "Ein" befindet. Für n = 5 entsprechen fünf Zustände in DFA fünf Erinnerungsinformationen wie folgt:
- Zustand q 0 erreicht, wenn Erinnerung 0 ist. Zustand q 0 ist der Endzustand (akzeptierender Zustand). Es ist auch ein Ausgangszustand.
- Der Zustand q 1 erreicht, wenn die Erinnerung 1 ist, einen nicht endgültigen Zustand.
- Zustand q 2, wenn Erinnerung 2 ist, ein nicht endgültiger Zustand.
- Zustand q 3, wenn Erinnerung 3 ist, ein nicht endgültiger Zustand.
- Zustand q 4, wenn Erinnerung 4 ist, ein nicht endgültiger Zustand.
Unter Verwendung der obigen Informationen können wir mit dem Zeichnen des Übergangsdiagramms TD von fünf Zuständen wie folgt beginnen:
Abbildung 1
Also 5 Zustände für 5 Restwerte. Nach der Verarbeitung einer Zeichenfolge ω, wenn der Endzustand zu q 0 wird , bedeutet dies, dass das Dezimaläquivalent der Eingabezeichenfolge durch 5 teilbar ist. In der obigen Abbildung ist q 0 als Endzustand als zwei konzentrische Kreise markiert.
Zusätzlich habe ich eine Übergangsregel δ definiert: (q 0 , 0) → q 0 als Selbstschleife für das Symbol '0'
im Zustand q 0 , weil das Dezimaläquivalent einer Zeichenfolge nur aus '0'
0 besteht und 0 durch teilbar ist n
.
Schritt 2 : TD oben ist unvollständig; und kann nur Strings von '0'
s verarbeiten. Fügen Sie nun einige weitere Kanten hinzu, damit die Zeichenfolgen der nachfolgenden Zahlen verarbeitet werden können. Die folgende Tabelle zeigt neue Übergangsregeln, die im nächsten Schritt hinzugefügt werden können:
┌───────────────────────────────────────┐
│ Zahl │ Binär │ Rest (% 5) │ Endzustand │
├───────────────────────────────────────┤
│Ein │1 │1 │q 1 │
├───────────────────────────────────────┤
WoZwei │10 │2 │q 2 │
├───────────────────────────────────────┤
HreDrei │11 │3 │q 3 │
├───────────────────────────────────────┤
OurVier │100 │4 │q 4 │
└───────────────────────────────────────┘
- Um eine binäre Zeichenfolge
'1'
zu verarbeiten, sollte es eine Übergangsregel δ geben: (q 0 , 1) → q 1
- Zwei: - Die binäre Darstellung ist
'10'
, der Endzustand sollte q 2 sein , und um zu verarbeiten '10'
, müssen wir nur eine weitere Übergangsregel hinzufügen δ: (q 1 , 0) → q 2
Pfad : → (q 0 ) ─1 → ( q 1 ) ─0 → (q 2 )
- Drei: - Binär ist der Endzustand
'11'
q 3 , und wir müssen eine Übergangsregel δ hinzufügen: (q 1 , 1) → q 3
Pfad : → (q 0 ) ─1 → (q 1 ) ─1 → (q 3 )
- Viertens: - Im Binärzustand
'100'
ist der Endzustand q 4 . TD verarbeitet bereits die Präfixzeichenfolge '10'
und wir müssen nur eine neue Übergangsregel δ hinzufügen: (q 2 , 0) → q 4
Pfad : → (q 0 ) ─ 1 → (q 1 ) ─ 0 → (q 2 ) ─ 0 → (q 4 )
Figur 2
Schritt 3 : Fünf = 101 Das
obige Übergangsdiagramm in Abbildung 2 ist noch unvollständig und es fehlen viele Kanten. Für ein Beispiel ist kein Übergang für δ definiert: (q 2 , 1) - ? . Und die Regel sollte vorhanden sein, um Strings wie zu verarbeiten '101'
.
Weil '101'
= 5 durch 5 teilbar ist, und um zu akzeptieren '101'
, füge ich δ hinzu: (q 2 , 1) → q 0 in der obigen Abbildung-2.
Pfad: → (q 0 ) ─1 → (q 1 ) ─0 → (q 2 ) ─1 → (q 0 )
Mit dieser neuen Regel wird das Übergangsdiagramm wie folgt:
Figur 3
Unten in jedem Schritt wähle ich die nächste nachfolgende Binärzahl aus, um eine fehlende Kante hinzuzufügen, bis ich TD als 'vollständigen DFA' erhalte.
Schritt 4 : Sechs = 110.
Wir können '11'
TD in Abbildung 3 wie folgt verarbeiten : → (q 0 ) ─11 → (q 3 ) ─0 → ( ? ). Da 6% 5 = 1 ist, bedeutet dies, eine Regel δ hinzuzufügen: (q 3 , 0) → q 1 .
Figur 4
Schritt 5 : Sieben = 111
┌─────────────────────────────────────────────────── ─┬────────────┐
│ Zahl │ Binär │ Rest (% 5) │ Endzustand │ Pfad │ Hinzufügen │
├─────────────────────────────────────────────────── ─┼────────────┤
│Seven │111 │7% 5 = 2 │q 2 │ q 0 ─ 11 → q 3 │ q 3 ─ 1 → q 2 │
└─────────────────────────────────────────────────── ─┴────────────┘
Abbildung 5
Schritt 6 : Acht = 1000
┌─────────────────────────────────────────────────┬ ─────────┐
│ Zahl │ Binär │ Rest (% 5) │ Endzustand │ Pfad │ Hinzufügen │
├─────────────────────────────────────────────────┼ ─────────┤
Ight Acht %1000 │8% 5 = 3 │q 3 │q 0 ─100 → q 4 │ q 4 ─0 → q 3 │
└─────────────────────────────────────────────────┴ ─────────┘
Abbildung 6
Schritt 7 : Neun = 1001
┌─────────────────────────────────────────────────┬ ─────────┐
│ Zahl │ Binär │ Rest (% 5) │ Endzustand │ Pfad │ Hinzufügen │
├─────────────────────────────────────────────────┼ ─────────┤
│Nein │1001 │9% 5 = 4 │q 4 │q 0 ─100 → q 4 │ q 4 ─1 → q 4 │
└─────────────────────────────────────────────────┴ ─────────┘
Abbildung 7
In TD-7 beträgt die Gesamtzahl der Kanten 10 == Q × Σ = 5 × 2. Und es ist ein vollständiger DFA, der alle möglichen binären Zeichenfolgen akzeptieren kann, deren Dezimaläquivalent durch 5 teilbar ist.
Design DFA akzeptiert ternäre Zahlen, die durch die Zahl n teilbar sind:
Schritt-1 Verwenden Sie genau wie für binär Abbildung-1.
Schritt 2 Fügen Sie Null, Eins, Zwei hinzu
┌────────────────────────────────────────────────── ─────┐
│ Dezimal │ Ternär │ Rest (% 5) │ Endzustand │ Hinzufügen │
├────────────────────────────────────────────────── ─────┤
EroZero │0 │0 │q0 │ δ: (q0,0) → q0 │
├────────────────────────────────────────────────── ─────┤
NeEin │1 │1 │q1 │ δ: (q0,1) → q1 │
├────────────────────────────────────────────────── ─────┤
WoZwei │2 │2 │q2 │ δ: (q0,2) → q3 │
└────────────────────────────────────────────────── ─────┘
Abbildung 8
Schritt 3 Fügen Sie drei, vier, fünf hinzu
┌────────────────────────────────────────────────── ────┐
│ Dezimal │ Ternär │ Rest (% 5) │ Endzustand │ Hinzufügen │
├────────────────────────────────────────────────── ────┤
HreDrei │10 │3 │q3 │ δ: (q1,0) → q3 │
├────────────────────────────────────────────────── ────┤
OurVier │11 │4 │q4 │ δ: (q1,1) → q4 │
├────────────────────────────────────────────────── ────┤
IveFive │12 │0 │q0 │ δ: (q1,2) → q0 │
└────────────────────────────────────────────────── ────┘
Abbildung 9
Schritt 4 Fügen Sie sechs, sieben, acht hinzu
┌────────────────────────────────────────────────── ────┐
│ Dezimal │ Ternär │ Rest (% 5) │ Endzustand │ Hinzufügen │
├────────────────────────────────────────────────── ────┤
│Six │20 │1 │q1 │ δ: (q2,0) → q1 │
├────────────────────────────────────────────────── ────┤
│Seven │21 │2 │q2 │ δ: (q2,1) → q2 │
├────────────────────────────────────────────────── ────┤
│ Acht │22 │3 │q3 │ δ: (q2,2) → q3 │
└────────────────────────────────────────────────── ────┘
Abbildung 10
Schritt 5 Fügen Sie neun, zehn, elf hinzu
┌────────────────────────────────────────────────── ────┐
│ Dezimal │ Ternär │ Rest (% 5) │ Endzustand │ Hinzufügen │
├────────────────────────────────────────────────── ────┤
IneNein │100 │4 │q4 │ δ: (q3,0) → q4 │
├────────────────────────────────────────────────── ────┤
│Ten │101 │0 │q0 │ δ: (q3,1) → q0 │
├────────────────────────────────────────────────── ────┤
LeEleven │102 │1 │q1 │ δ: (q3,2) → q1 │
└────────────────────────────────────────────────── ────┘
Abbildung 11
Schritt 6 Addiere zwölf, dreizehn, vierzehn
┌─────────────────────────────────────────────────── ─────┐
│ Dezimal │ Ternär │ Rest (% 5) │ Endzustand │ Hinzufügen │
├─────────────────────────────────────────────────── ─────┤
Zwölf wel110 │2 │q2 │ δ: (q4,0) → q2 │
├─────────────────────────────────────────────────── ─────┤
│Dreißig│111 │3 │q3 │ δ: (q4,1) → q3 │
├─────────────────────────────────────────────────── ─────┤
Our Vierzehn│112 │4 │q4 │ δ: (q4,2) → q4 │
└─────────────────────────────────────────────────── ─────┘
Abbildung 12
Die Gesamtzahl der Kanten im Übergangsdiagramm in Abbildung 12 beträgt 15 = Q × Σ = 5 * 3 (ein vollständiger DFA). Und dieser DFA kann akzeptieren, dass alle Zeichenfolgen über {0, 1, 2} bestehen. Diese Dezimaläquivalente sind durch 5 teilbar.
Wenn Sie bei jedem Schritt feststellen, gibt es in der Tabelle drei Einträge, da ich bei jedem Schritt alle möglichen ausgehenden Flanken aus einem Zustand hinzufüge um einen vollständigen DFA zu erstellen (und ich füge eine Kante hinzu, damit q r state für den Rest erhalten wird r
)!
Denken Sie daran, dass die Vereinigung zweier regulärer Sprachen ebenfalls eine reguläre ist. Wenn Sie einen DFA entwerfen müssen, der binäre Zeichenfolgen akzeptiert, ist dieses Dezimaläquivalent entweder durch 3 oder 5 teilbar. Zeichnen Sie dann zwei separate DFAs für teilbar durch 3 und 5, und vereinigen Sie dann beide DFAs, um das Ziel-DFA zu erstellen (für 1 <= n <= 10) Sie müssen 10 DFAs vereinen).
Wenn Sie aufgefordert werden, DFA zu zeichnen, das binäre Zeichenfolgen so akzeptiert, dass das Dezimaläquivalent durch 5 und 3 teilbar ist, suchen Sie nach DFA, das durch 15 teilbar ist (aber was ist mit 6 und 8?).
Hinweis: Mit dieser Technik gezeichnete DFAs werden nur dann minimiert, wenn es keinen gemeinsamen Faktor zwischen Zahl n
und Basis gibt, z. B. gibt es im ersten Beispiel keinen zwischen 5 und 2 oder im zweiten Beispiel zwischen 5 und 3, daher werden beide oben konstruierten DFAs minimiert DFAs. Wenn Sie mehr über mögliche Mini-Zustände für Zahlen n
und Basis b
lesen möchten, lesen Sie das Papier: Teilbarkeit und Zustandskomplexität .
Unten habe ich ein Python-Skript hinzugefügt. Ich habe es zum Spaß geschrieben, während ich die Python-Bibliothek pygraphviz gelernt habe. Ich füge es hinzu. Ich hoffe, es kann irgendwie für jemanden hilfreich sein.
Entwerfen Sie den DFA für die durch die Zahl 'n' teilbaren Zeichenfolgen der Basis 'b':
Wir können also den obigen Trick anwenden, um DFA zu zeichnen, um Zahlenfolgen in jeder Basis zu erkennen, 'b'
die durch eine bestimmte Zahl teilbar sind 'n'
. In diesem DFA ist die Gesamtzahl der Zustände n
(für n
Reste) und die Anzahl der Kanten sollte gleich 'b' * 'n' sein - das ist vollständig. DFA: 'b' = Anzahl der Symbole in der Sprache des DFA und 'n' = Anzahl der Staaten.
Mit dem obigen Trick habe ich unten ein Python-Skript geschrieben, um DFA für die Eingabe base
und zu zeichnen number
. Im Skript divided_by_N
füllt die Funktion die Übergangsregeln von DFA base * number
schrittweise aus. In jeder Schrittnummer konvertiere ich mit der Funktion num
in eine Zahlenfolge . Um zu vermeiden, dass jede Zahlenfolge verarbeitet wird, habe ich eine temporäre Datenstruktur verwendet . In jedem Schritt wird der Endzustand für die Zahlenzeichenfolge ausgewertet und gespeichert , um im nächsten Schritt verwendet zu werden.num_s
baseN()
lookup_table
num_s
lookup_table
Für den Übergangsgraphen von DFA habe ich eine Funktion draw_transition_graph
mit der Pygraphviz-Bibliothek geschrieben (sehr einfach zu bedienen). Um dieses Skript verwenden zu können, müssen Sie es installieren graphviz
. Um dem Übergangsdiagramm farbige Kanten hinzuzufügen, generiere ich zufällig Farbcodes für jede Symbolfunktion get_color_dict
.
import pygraphviz as pgv
from pprint import pprint
from random import choice as rchoice
def baseN(n, b, syms="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
""" converts a number `n` into base `b` string """
return ((n == 0) and syms[0]) or (
baseN(n//b, b, syms).lstrip(syms[0]) + syms[n % b])
def divided_by_N(number, base):
"""
constructs DFA that accepts given `base` number strings
those are divisible by a given `number`
"""
ACCEPTING_STATE = START_STATE = '0'
SYMBOL_0 = '0'
dfa = {
str(from_state): {
str(symbol): 'to_state' for symbol in range(base)
}
for from_state in range(number)
}
dfa[START_STATE][SYMBOL_0] = ACCEPTING_STATE
lookup_table = { SYMBOL_0: ACCEPTING_STATE }.setdefault
for num in range(number * base):
end_state = str(num % number)
num_s = baseN(num, base)
before_end_state = lookup_table(num_s[:-1], START_STATE)
dfa[before_end_state][num_s[-1]] = end_state
lookup_table(num_s, end_state)
return dfa
def symcolrhexcodes(symbols):
"""
returns dict of color codes mapped with alphabets symbol in symbols
"""
return {
symbol: '#'+''.join([
rchoice("8A6C2B590D1F4E37") for _ in "FFFFFF"
])
for symbol in symbols
}
def draw_transition_graph(dfa, filename="filename"):
ACCEPTING_STATE = START_STATE = '0'
colors = symcolrhexcodes(dfa[START_STATE].keys())
tg = pgv.AGraph(strict=False, directed=True, decorate=True)
for from_state in dfa:
for symbol, to_state in dfa[from_state].iteritems():
tg.add_edge("Q%s"%from_state, "Q%s"%to_state,
label=symbol, color=colors[symbol],
fontcolor=colors[symbol])
tg.add_node('null', shape='plaintext', label='start')
tg.add_edge('null', "Q%s"%START_STATE,)
tg.get_node("Q%s"%ACCEPTING_STATE).attr['shape'] = 'doublecircle'
tg.draw(filename, prog='circo')
tg.close()
def print_transition_table(dfa):
print("DFA accepting number string in base '%(base)s' "
"those are divisible by '%(number)s':" % {
'base': len(dfa['0']),
'number': len(dfa),})
pprint(dfa)
if __name__ == "__main__":
number = input ("Enter NUMBER: ")
base = input ("Enter BASE of number system: ")
dfa = divided_by_N(number, base)
print_transition_table(dfa)
draw_transition_graph(dfa)
Führ es aus:
~/study/divide-5/script$ python script.py
Enter NUMBER: 5
Enter BASE of number system: 4
DFA accepting number string in base '4' those are divisible by '5':
{'0': {'0': '0', '1': '1', '2': '2', '3': '3'},
'1': {'0': '4', '1': '0', '2': '1', '3': '2'},
'2': {'0': '3', '1': '4', '2': '0', '3': '1'},
'3': {'0': '2', '1': '3', '2': '4', '3': '0'},
'4': {'0': '1', '1': '2', '2': '3', '3': '4'}}
~/study/divide-5/script$ ls
script.py filename.png
~/study/divide-5/script$ display filename
Ausgabe:
DFA akzeptiert Zahlenfolgen in Basis 4, die durch 5 teilbar sind
In ähnlicher Weise geben Sie base = 4 und number = 7 ein, um zu generieren - dfa akzeptiert Zahlenzeichenfolge in base '4', die durch '7' teilbar sind.
Versuchen Sie, filename
zu .png
oder zu wechseln .jpeg
.
Verweist auf
diejenigen, die ich zum Schreiben dieses Skripts verwende: ➊ Funktion baseN
von "Ganzzahl in eine Zeichenfolge in einer bestimmten numerischen Basis in Python
konvertieren " ➋ So installieren Sie "pygraphviz": "Python sieht pygraphviz nicht"
➌ So lernen Sie die Verwendung von Pygraphviz: "Python- FSM "
➍ So generieren Sie zufällige Hex-Farbcodes für jedes Sprachsymbol: " Wie würde ich einen zufälligen Hexdigit-Code-Generator mit .join und for-Schleifen erstellen? "
n
das ist trivial, oder?