-
Notifications
You must be signed in to change notification settings - Fork 10
/
non_deterministic.py
94 lines (70 loc) · 2.79 KB
/
non_deterministic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# Non-Deterministic Turing Machine Simulator
class Queue():
def __init__(self):
self.queue = []
def enqueue(self, state, head, string, iter_count):
self.queue.append((state, head, string, iter_count))
def dequeue(self):
item = self.queue[0]
self.queue = self.queue[1:]
return item
def is_empty(self):
return len(self.queue) == 0
class TuringMachine():
def __init__(self, transitions, accepted_states, max_iterations):
self.transitions = transitions
self.accepted_states = accepted_states
self.max_iterations = max_iterations
def validate_string(self, string):
head = 0
state = self.transitions[0][0]
iter_count = 1
self.queue = Queue()
self.queue.enqueue(head, state, string, iter_count)
outputs = self.validate_symbol()
return self.output(outputs)
def validate_symbol(self):
if self.queue.is_empty():
return [0]
(state, head, string, iter_count) = self.queue.dequeue()
outputs = []
symbol = string[head]
for (current_state, current_symbol, next_symbol, move, next_state) in self.transitions:
if state == current_state and (symbol == current_symbol or current_symbol == 'x'):
if next_state in accepted_states and head == len(string) - 1:
return [1]
if iter_count > max_iterations:
outputs = outputs + ['u']
else:
head_copy, string_copy = head, string
if next_symbol != 'x':
string_copy[head] = next_symbol
(head_copy, string_copy) = self.update_values(head_copy, string_copy, move)
self.queue.enqueue(next_state, head_copy, string_copy, iter_count + 1)
outputs = outputs + self.validate_symbol()
return outputs
def update_values(self, head, string, move):
if move == 'r':
head += 1
if head == len(string):
string = string + ['_']
elif move == 'l':
head -= 1
if head == 0:
string = ['_'] + string
return (head, string)
def output(self, outputs):
if 1 in outputs:
return 'Accepted'
if 0 in outputs:
return 'Rejected'
return 'Undefined'
# Example: Automata that accepts strings that ends with 'b'
transitions = [(0, 'x', 'x', 'r', 0), (0, 'b', 'b', 's', 1)]
accepted_states = [1]
max_iterations = 50
input_strings = ['aa', 'ab', 'aaab', 'ababab', 'bba']
turing_machine = TuringMachine(transitions, accepted_states, max_iterations)
for string in input_strings:
output = turing_machine.validate_string(list(string))
print(string, output)