Skip to content

Commit ef6bd0d

Browse files
committed
Automata v.1.5.0
Turing Machine class implementation added with two examples of use for the irregualar language [0^n 1^n 2^n]
1 parent 910b6ad commit ef6bd0d

File tree

3 files changed

+301
-0
lines changed

3 files changed

+301
-0
lines changed

tm-example-1.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from tm import TM
2+
3+
if __name__ == "__main__":
4+
5+
# First example of TM Automata instance:
6+
# Language of the Automata:
7+
# Turing Machine to recognize the language;
8+
# L = {0^n 1^n 2^n: n >= 1}
9+
# All strings consisting of zero or more consecutive
10+
# '0's followed by an equal number of consecutive '1's",
11+
# and equal number of 2's then.
12+
13+
#* States:
14+
Q = {"q0", "q1", "q2", "q4", "q5"}
15+
16+
#* Alphabet
17+
#? (* is Blank Symbol):
18+
A = {"0", "1", "2", "X", "Y", "Z", "*"}
19+
20+
#* Transitions:
21+
#? (current_state, current_symbol, new_symbol, move_direction, next_state)
22+
T = [
23+
("q0", "0", "X", "R", "q1"),
24+
("q0", "Y", "Y", "R", "q4"),
25+
26+
("q1", "Y", "Y", "R", "q1"),
27+
("q1", "0", "0", "R", "q1"),
28+
("q1", "1", "Y", "R", "q2"),
29+
30+
("q2", "Z", "Z", "R", "q2"),
31+
("q2", "1", "1", "R", "q2"),
32+
("q2", "2", "Z", "L", "q3"),
33+
34+
("q3", "X", "X", "R", "q0"),
35+
("q3", "0", "0", "L", "q3"),
36+
("q3", "1", "1", "L", "q3"),
37+
("q3", "Y", "Y", "L", "q3"),
38+
("q3", "Z", "Z", "L", "q3"),
39+
40+
("q4", "Y", "Y", "R", "q4"),
41+
("q4", "Z", "Z", "R", "q4"),
42+
43+
("q4", "*", "*", "L", "q5")
44+
]
45+
46+
#* Initial state:
47+
S = "q0"
48+
49+
#* Accept states:
50+
F = {"q5"}
51+
52+
#? Automata:
53+
Automata = TM(Q, A, T, S, F)
54+
55+
Automata.show()
56+
57+
#/ Executes the Automata:
58+
while True:
59+
print()
60+
word = input("String: ")
61+
if Automata.accepts(word, stepByStep=True):
62+
print(f"The string \"{word}\" IS accepted!")
63+
else:
64+
print(f"The string \"{word}\" IS NOT accepted!")
65+
print()
66+
print("═"*40)

tm-example-2.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from tm import TM
2+
3+
if __name__ == "__main__":
4+
5+
# Second example of TM Automata instance:
6+
# Language of the Automata:
7+
# Turing Machine to recognize the language;
8+
# L = {0^n 1^n 2^n: n >= 1}
9+
# All strings consisting of zero or more consecutive
10+
# '0's followed by an equal number of consecutive '1's",
11+
# and equal number of 2's then.
12+
13+
Automata = TM()
14+
Automata.setStates({"q0", "q1", "q2", "q4", "q5"})
15+
Automata.setAlphabet({"0", "1", "2", "X", "Y", "Z", "*"})
16+
Automata.setInitial("q0")
17+
Automata.setFinals({"q5"})
18+
Automata.addTransition(("q0", "0", "X", "R", "q1"))
19+
Automata.addTransition(("q0", "Y", "Y", "R", "q4"))
20+
Automata.addTransition(("q1", "Y", "Y", "R", "q1"))
21+
Automata.addTransition(("q1", "0", "0", "R", "q1"))
22+
Automata.addTransition(("q1", "1", "Y", "R", "q2"))
23+
Automata.addTransition(("q2", "Z", "Z", "R", "q2"))
24+
Automata.addTransition(("q2", "1", "1", "R", "q2"))
25+
Automata.addTransition(("q2", "2", "Z", "L", "q3"))
26+
Automata.addTransition(("q3", "X", "X", "R", "q0"))
27+
Automata.addTransition(("q3", "0", "0", "L", "q3"))
28+
Automata.addTransition(("q3", "1", "1", "L", "q3"))
29+
Automata.addTransition(("q3", "Y", "Y", "L", "q3"))
30+
Automata.addTransition(("q3", "Z", "Z", "L", "q3"))
31+
Automata.addTransition(("q4", "Y", "Y", "R", "q4"))
32+
Automata.addTransition(("q4", "Z", "Z", "R", "q4"))
33+
Automata.addTransition(("q4", "*", "*", "L", "q5"))
34+
Automata.show()
35+
36+
#/ Executes the Automata:
37+
while True:
38+
print()
39+
word = input("String: ")
40+
if Automata.accepts(word, stepByStep=True):
41+
print(f"The string \"{word}\" IS accepted!")
42+
else:
43+
print(f"The string \"{word}\" IS NOT accepted!")
44+
print()
45+
print("═"*40)

tm.py

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
'''
2+
TURING MACHINE
3+
'''
4+
5+
class TM:
6+
7+
#/ Attributes #
8+
States: list = []
9+
Alphabet: list = []
10+
Transitions: list = []
11+
Initial: str = ""
12+
Finals: list = []
13+
14+
#* Constructor #
15+
def __init__(self, states: set={}, alphabet: set={}, transitions: list=[], initial: str="", finals: set={}):
16+
17+
'''
18+
CONSTRUCTOR:
19+
NOTE: ALL THE PARAMETERS ARE OPTIONAL;
20+
NOTE: YOU CAN ADD ELEMENTS WITH RESPECTIVE FUNCTIONS:
21+
"TM" creates an instance of a Turing Machine.
22+
It receives:
23+
24+
1. "states" (set of strings): In a set, add strings to represent
25+
each state of the Turing Machine. Example:
26+
{"q0", "q1", "q2", "qf", "qx", "dx"};
27+
28+
2. "alphabet" (set of strings): In a set, add all the symbols that
29+
the Turing Machine reads. If you add two characters as a symbol,
30+
note that it will be considered as a single unique symbol.
31+
NOTE: Upper and lower case generate different symbols.
32+
Example:
33+
{"ea", "ra", "faszaa"} <- Three-symbol alphabet;
34+
{"A", "a", "B", "b"} <- Four-symbol alphabet;
35+
{"a", "b", "c", "d", "d", "d", "d"} <- Four-symbol alphabet;
36+
37+
3. "transitions" (set of *transitionObject* (tuples)):
38+
*transitionObject* looks like this:
39+
("q0", "a", "b", "R", "q1");
40+
Where:
41+
* "q0" is the current state of the transition;
42+
* "a" is the symbol that the Turing Machine reads on the current state;
43+
* "b" is the symbol that the Turing Machine writes on the current position;
44+
* "R" or "L" specifies the direction the Turing Machine head moves after the transition;
45+
* "q1" is the next state after the transition.
46+
Example of a transitions set:
47+
{ ("q0", "a", "b", "R", "q1"), ("q0", "b", "c", "L", "q1"), ("q1", "a", "a", "R", "q1") };
48+
NOTE: FOR THE BLANK SYMBOL USE "*".
49+
50+
4. "initial" (string): Represents the initial state of the Turing Machine.
51+
If it is not included in "states", it will be added to the set of states.
52+
Example: "q0";
53+
54+
5. "finals" (set of strings): Set of final states of the Turing Machine.
55+
Example: {"q1", "q2", "qf"};
56+
57+
RETURNS AN INSTANCE OF THE TURING MACHINE;
58+
'''
59+
60+
# The values of the automata #
61+
self.States = states
62+
self.Alphabet = alphabet
63+
self.Transitions = transitions
64+
self.Initial = initial
65+
self.Finals = finals
66+
67+
#* Getter:
68+
def __getattribute__(self, __name: str):
69+
return super(TM, self).__getattribute__(__name)
70+
71+
#* Setters:
72+
#/ For Automata States:
73+
def addState(self, state: str):
74+
self.States.append(state)
75+
def setStates(self, states: set):
76+
self.States = list(states)
77+
78+
#/ For Automata Alphabet:
79+
def addSymbol(self, symbol: str):
80+
self.Alphabet.append(symbol)
81+
def setAlphabet(self, alphabet: set):
82+
self.Alphabet = list(alphabet)
83+
84+
#/ For Automata Transitions:
85+
def addTransition(self, transition: tuple):
86+
self.Transitions.append(transition)
87+
def setTransitions(self, transitions: list):
88+
self.Transitions = transitions
89+
90+
#/ For Automata Initial State:
91+
def setInitial(self, initial: str):
92+
if not initial in self.States:
93+
self.States.append(initial)
94+
self.Initial = initial
95+
self.actual = initial
96+
97+
#/ For Automata Final States:
98+
def addFinal(self, final: str):
99+
self.Finals.append(final)
100+
def setFinals(self, finals: set):
101+
self.Finals = list(finals)
102+
103+
104+
#? Methods:
105+
def show(self):
106+
'''Prints Turing Machine data'''
107+
print()
108+
print("═"*50)
109+
print("\nTURING MACHINE\n")
110+
print("═"*50)
111+
print(f"\nStates: {set(self.States)}")
112+
print(f"Alphabet: {set(self.Alphabet)}")
113+
print(f"Initial state: \"{self.Initial}\"")
114+
print(f"Final states: {set(self.Finals)}")
115+
for t in self.Transitions:
116+
t1 = t[1] if t[1] != "" else "λ"
117+
t2 = t[2] if t[2] != "" else "λ"
118+
print(f"* δ(\"{t[0]}\", \"{t1}\") = (\"{t[3]}\", \"{t2}\", \"{t[4]}\")")
119+
print()
120+
print("═"*50)
121+
122+
def transite(self, symbol: str, printStep: bool = False):
123+
'''
124+
Receives the current reading symbol;
125+
Based on the current state and the transitions,
126+
it changes the current state and performs the necessary actions.
127+
'''
128+
129+
# Check if the transition exists:
130+
validTransitions = []
131+
for transition in self.Transitions:
132+
if self.actual == transition[0] and symbol == transition[1]:
133+
validTransitions.append(transition)
134+
135+
# If the Turing Machine has no valid transitions or more than one valid transition
136+
if len(validTransitions) != 1:
137+
print(f" * Invalid transition in \"{self.actual}\" reading \"{symbol}\"!")
138+
self.error = True
139+
return
140+
141+
# Perform the transition:
142+
else:
143+
if printStep:
144+
print(f" * \"{self.actual}\" reads \"{symbol}\", writes \"{validTransitions[0][2]}\", moves {validTransitions[0][3]}, goes to \"{validTransitions[0][4]}\";")
145+
146+
self.actual = validTransitions[0][4]
147+
self.tape[self.head] = validTransitions[0][2]
148+
149+
# Move the head and extend the tape if necessary:
150+
if validTransitions[0][3] == "R":
151+
self.head += 1
152+
if self.head == len(self.tape):
153+
self.tape.append("*")
154+
elif validTransitions[0][3] == "L":
155+
self.head -= 1
156+
if self.head < 0:
157+
self.tape.insert(0, "*")
158+
159+
def accepts(self, string: str, stepByStep: bool = False):
160+
'''
161+
Receives a string to process;
162+
Returns True if the string is accepted;
163+
Returns False if the string is not accepted;
164+
'''
165+
166+
# Initialize the actual state as the initial state and the tape with the string:
167+
self.actual = self.Initial
168+
self.error = False
169+
self.tape = list(string)
170+
self.head = 0
171+
172+
# It shows the step-by-step path for the string:
173+
if stepByStep:
174+
print(f"\nFor string \"{string}\":\n")
175+
176+
# Process each symbol on the tape:
177+
while self.actual not in self.Finals and not self.error:
178+
symbol = self.tape[self.head]
179+
self.transite(symbol, stepByStep)
180+
181+
print()
182+
183+
# Check if the string was accepted or not:
184+
if self.error:
185+
return False
186+
187+
if self.actual in self.Finals:
188+
return True
189+
else:
190+
return False

0 commit comments

Comments
 (0)