Skip to content
Snippets Groups Projects
Commit 480ec4e5 authored by Jan Maximilian Michal's avatar Jan Maximilian Michal
Browse files

initial commit

parents
No related branches found
No related tags found
No related merge requests found
from itertools import product
delta = """
S := AB | ABA
A := aA | a
B := Bb | eps
"""
class rule:
__slots__ = ['left', 'right']
def __init__(self, left, right, sep=""):
self.left = left
self.right = [c for c in right] if right != "eps" else []
def __str__(self):
return self.left + " := " + ''.join(self.right)
def __hash__(self):
return hash(str(self))
def __eq__(self, other):
return self.left == other.left and self.right == other.right
def parse(grammer):
grammer = grammer.strip()
terminals = set()
non_terms = set()
rules = set()
for line in grammer.split("\n"):
N, rule_list = line.split(":=")
rules |= {rule(N.strip(), right.strip()) for right in rule_list.split("|")}
non_terms |= {N}
for r in rules:
if r.right != 'eps':
terminals |= {T for T in r.right if T.islower()}
return rules, terminals, non_terms
P, T, N = parse(delta)
print(('\n'.join(map(str, P))))
print()
letters_to_kill = {p.left for p in P if not p.right}
new_P = set() | P
for p in P:
for l in letters_to_kill:
n = p.right.count(l)
r = ''.join(p.right).replace(l, "{}")
# 0 is a placeholder for empty string
for prod in product(l + "0", repeat=n):
new_P |= {rule(p.left, r.format(*prod).replace("0", ""))}
P = {p for p in new_P if p.right}
print(('\n'.join(map(str, P))))
print()
for t in T:
P |= {rule("T_" + t, t)}
print(T)
new_P = set() | P
for p in P:
p.right = ["T_" + p if p in T else p for p in p.right]
P = new_P
print(('\n'.join(map(str, P))))
print()
new_P = set() | P
for p in P:
if len(p.right) > 2:
pass
from DFA import *
from itertools import product
from graphviz import Digraph
class Automaton:
"""docstring for Automaton"""
__slots__ = ['states', 'sigma', 'delta', 'q0', 'F']
def __init__(self, states, sigma, delta, q0, F):
self.states = states
self.sigma = set(sigma)
self.delta = delta
self.q0 = q0
self.F = set(F)
def state_pairs(self):
return filter(lambda p: p[0] != p[1], product(self.states[:-1], self.states[1:]))
def bisimilar(self, k, z1, z2):
if k == 0:
return (z1 in self.F) == (z2 in self.F)
return self.bisimilar(k-1, z1, z2) and \
all(self.bisimilar(k-1, self.delta(z1, a), self.delta(z2, a))
for a in self.sigma)
def minimize(self):
# Initialize
k = 0
change = True
marker = {
pair: 0 for pair in self.state_pairs() if not self.bisimilar(0, *pair)}
# Iterate
while change:
change = False
for z1, z2 in (pair for pair in self.state_pairs() if pair not in marker):
if any(not self.bisimilar(k, self.delta(z1, a), self.delta(z2, a)) for a in self.sigma):
marker[(z1, z2)] = k+1
change = True
k += 1
# Finalize TODO
return marker
def generate_ilias(self):
gap = "[gap({points}P)]{luecke}[/gap]"
marker = self.minimize()
aufgabe = '''Minimieren Sie den folgenden deterministischen Automaten
[tex]M = {{%s},{%s},\\\\delta,{%s},{%s}}[/tex] oder zeigen Sie, dass der Automat
bereits minimal ist. Geben Sie die Tabelle mit den Zustandspaaren an, sowie den
minimierten Graphen.<br>\n\n''' % (', '.join(self.states), ', '.join(self.sigma),
str(self.q0), ', '.join(self.F))
aufgabe += '<p>' + self.graph_output() + '</p>'
aufgabe += '\n\n<p><table border-collapse: collapse; border-style: hidden; rules=\"all\">\n'
aufgabe += '<tr>\n\t<td> </td>\n\t<td>' + \
'</td>\n\t<td>'.join(self.states[1:]) + '</td></tr>\n'
for i, z1 in enumerate(self.states[:-1]):
aufgabe += '<tr>\n\t<td>{}</td>\n'.format(z1)
for j, z2 in enumerate(self.states[1:]):
content = '\t<td>{}</td>\n'
if j < i:
content = content.format(' ')
elif (z1, z2) not in marker:
content = content.format(gap.format(points=1, luecke='X'))
else:
content = content.format(
gap.format(points=1, luecke=marker[(z1, z2)]))
aufgabe += content
aufgabe += '</tr>\n'
aufgabe += '</table></p>'
return aufgabe.replace(r'"', r'\"')
def graph_output(self, file_format='svg'):
f = Digraph('finite_state_machine', format=file_format, engine='dot')
f.body.extend(['rankdir=LR', 'size="8,5"'])
f.attr('node', shape='doublecircle')
for node in self.F:
f.node(node)
f.attr('node', shape='circle')
f.node('', style='invis')
f.edge('', self.q0)
for state in self.states:
for a in self.sigma:
f.edge(state, self.delta(state, a), label=a)
return str(f.pipe(), encoding='utf-8')
def delta(state, char):
return {
('s0', 'a'): 's3',
('s0', 'b'): 's1',
('s1', 'a'): 's2',
('s1', 'b'): 's4',
('s2', 'a'): 's2',
('s2', 'b'): 's4',
('s3', 'a'): 's3',
('s3', 'b'): 's1',
('s4', 'a'): 's4',
('s4', 'b'): 's4'
}[(state, char)]
def delta2(state, char):
return {
('s0', 'a'): 's2',
('s0', 'b'): 's2',
('s1', 'a'): 's0',
('s1', 'b'): 's3',
('s2', 'a'): 's1',
('s2', 'b'): 's4',
('s3', 'a'): 's4',
('s3', 'b'): 's3',
('s4', 'a'): 's5',
('s4', 'b'): 's4',
('s5', 'a'): 's3',
('s5', 'b'): 's6',
('s6', 'a'): 's6',
('s6', 'b'): 's6',
}[(state, char)]
states = ["s{}".format(i) for i in range(5)]
states2 = ["s{}".format(i) for i in range(7)]
F = ["s2"]
F2 = ["s0", "s3", "s4", "s6"]
A = Automaton(states2, "ab", delta2, "s0", F2)
A.minimize()
print(A.generate_ilias())
from collections import deque
from functools import reduce
from graphviz import Digraph
# from pprint import pprint as print
class NEA:
"""docstring for NEA"""
__slots__ = ['states', 'sigma', 'delta', 'q0', 'F']
def __init__(self, states, sigma, delta, q0, F):
self.states = states
self.sigma = sigma
self.delta = delta
self.q0 = q0
self.F = set(F)
def to_dea(self):
done = []
new_steps = deque([{self.q0}])
table = []
while new_steps:
cur = new_steps.popleft()
table.append([cur])
for a in self.sigma:
next = reduce(lambda a, b: a | b, (self.delta(s, a)
for s in cur))
table[-1].append(next)
if next not in done:
new_steps.append(next)
done.append(next)
return table
def graph_output(self, file_format='svg'):
f = Digraph('finite_state_machine', format='pdf')
f.body.extend(['rankdir=LR', 'size="8,5"'])
f.attr('node', shape='doublecircle')
for node in self.F:
f.node(node)
f.attr('node', shape='circle')
f.node('', style='invis')
f.edge('', self.q0)
for state in self.states:
for a in self.sigma:
for next in self.delta(state, a):
f.edge(str(state), next, label=a)
f.view()
# return str(f.pipe(), encoding='utf-8')
def generate_ilias(self):
table = self.to_dea()
aufgabe = ''' Aufgabentext\n\n'''
tr = '<tr>\n{}</tr>\n'
td = '\t<td>{}</td>\n'
aufgabe += '<table border-collapse: collapse; border-style: hidden; rules=\"all\">\n'
aufgabe += tr.format(''.join(td.format(s) for s in ["delta", "a", "b"]))
for row in table:
aufgabe += tr.format(''.join(td.format(','.join(sorted(s))) for s in row))
aufgabe += '</table>'
print(aufgabe.replace('"', r'\"'))
print("{:>25}{:>25}{:>25}".format("delta", "a", "b"))
for row in table:
print("{:>25}{:>25}{:>25}".format(*map(', '.join, (sorted(s) for s in row))))
def delta(state, char):
return {
('s0', 'a'): {'s0', 's1'},
('s0', 'b'): {'s0', 's2'},
('s1', 'a'): {'s1', 's3'},
('s1', 'b'): {'s1'},
('s2', 'a'): {'s2'},
('s2', 'b'): {'s2', 's3'},
('s3', 'a'): set(),
('s3', 'b'): set(),
}[(state, char)]
states = ["s{}".format(i) for i in range(4)]
F = ["s3"]
N = NEA(states, "ab", delta, 's0', F)
N.to_dea()
# N.graph_output()
N.generate_ilias()
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment