Open In App

Turing Machine Simulator Using Python

Turing machines and deterministic finite automata (DFAs) are two fundamental concepts in computer science and automata theory. Both these concepts are used to model and analyze computational systems and are essential tools in understanding the limits of computation. A Turing machine is a theoretical model of a computing machine that was introduced by Alan Turing in 1936. It is a simple, but powerful, abstract machine that can simulate any algorithmic process. A deterministic finite automaton (DFA), on the other hand, is a simpler model of computation than a Turing machine.

Difference between DFA and Turing Machine 



Required Modules

pip install tk

Steps

Let’s see how to create a simple Turing Machine Simulator. Below is the Python code which uses the Tkinter library to make the simulator more interactive: 



Step 1. Import necessary libraries and make the class for the application :




import tkinter as tk
from tkinter import messagebox
import webbrowser
  
class TuringMachineSimulator(tk.Tk):
  # All the required functions will go in this class
    
 if __name__ == '__main__':
    app = TuringMachineSimulator()
    app.mainloop()

Step 2. Creating GUI window 

super().__init__() calls the constructor of the parent class, which is typically tkinter.Tk in a GUI application. This line initializes the main application window. self.title(“Turing Machine Simulator”) sets the title of the main window to “Turing Machine Simulator”.self.geometry(“600×500”) sets the size of the main window to 600 pixels wide and 500 pixels tall. 




def __init__(self):
  super().__init__()
  self.title("Turing Machine Simulator")
  self.geometry("600x500")
  self.create_welcome_page()

Step 3. Creating a Welcome Page :

This function creates the welcome page of the simulator, with a label and a button to proceed to the options page. It sets the background color of the page and adds a label and a button to the window.




def create_welcome_page(self):
    self.configure(bg="#1E90FF")
  
    tk.Label(self, text="Turing Machine Simulator",
             bg="#1E90FF", fg="white",
             font=('Helvetica', 32, "bold")).pack(pady=50)
  
    tk.Button(self,
              text="Get Started",
              bg="#FFFACD",
              font=('sans-serif', 22, "bold"),
              command=self.create_options_page).pack(pady=50)
  
    self.credits()

Step 4. Creating an Option Page 

This function creates the options page of the simulator, where the user can select the type of Turing machine to simulate. It clears the previous page (if any), sets the background color of the page, adds a label and radio buttons to the window, and adds a button to proceed to the input page.




def create_options_page(self):
    for widget in self.winfo_children():
        widget.destroy()
        self.configure(bg="#ADD8E6")
  
        tk.Label(self, text="Select an option:", bg="#ADD8E6",
                 font=('Verdana', 16)).pack(pady=20)
  
        options = [
          ("String should accept odd one's and even zero's", 0),
           ("String should accept even one's and odd zero's", 1),
            ("String should accept even one's and even zero's", 2),
           ("String should accept odd one's and odd zero's", 3)]
        self.selected_option = tk.IntVar()
  
        for option, value in options:
            tk.Radiobutton(self, text=option, bg="#ADD8E6", font=(
                'Verdana', 12), 
                      variable=self.selected_option, 
                      value=value).pack(pady=10)
  
            tk.Button(self, text="Next", bg="#FFFACD", font=(
                'sans-serif', 12), 
                   command=self.create_input_page).pack(pady=30)
  
            self.credits()

Step 5. Creating an Input Page 

This function creates the input page of the simulator, where the user can input the string to be checked by the selected Turing machine. It clears the previous page (if any), sets the background colour of the page, adds a label and an entry field to the window, and adds a button to check the input string.




def create_input_page(self):
    for widget in self.winfo_children():
        widget.destroy()
  
    self.configure(bg="#90EE90")
    tk.Label(self, text="Enter a string:", bg="#90EE90",
             font=('Verdana', 16)).pack(pady=20)
  
    self.string_input = tk.Entry(self, font=("Calibri", 14))
    self.string_input.pack(pady=10)
  
    tk.Button(self, text="Check", bg="#FFFACD", font=(
        'sans-serif', 12), command=self.check_string).pack(pady=30)
  
    self.credits()

Step 6. Creating Function Check the input String

This function checks the input string using the selected Turing machine and displays the result in a message box.It calls the appropriate Turing machine function based on the selected option and input string and displays the result in a message box. It also adds buttons to restart or exit the simulator. These are the Turing machines implemented by the simulator to check the input strings. They take an input string as an argument and return True if the input string is accepted by the corresponding Turing machine, and False otherwise. Each function implements a different Turing machine based on the requirement specified in the corresponding option.




def check_string(self):
        string = self.string_input.get()
        option = self.selected_option.get()
        if option == 0:
            if self.accepts_odd_ones_even_zeros(string):
                messagebox.showinfo("Result"
                          f"The string '{string}' is accepted.")
            else:
                messagebox.showinfo("Result"
                          f"The string '{string}' is not accepted.")
        elif option == 1:
            if self.accepts_even_ones_odd_zeros(string):
                messagebox.showinfo("Result"
                             f"The string '{string}' is accepted.")
            else:
                messagebox.showinfo("Result"
                    f"The string '{string}' is not accepted.")
        elif option == 2:
            if self.accepts_even_ones_even_zeros(string):
                messagebox.showinfo("Result"
                     f"The string '{string}' is accepted.")
            else:
                messagebox.showinfo("Result"
                    f"The string '{string}' is not accepted.")
        elif option == 3:
            if self.accepts_odd_ones_odd_zeros(string):
                messagebox.showinfo("Result"
                    f"The string '{string}' is accepted.")
            else:
                messagebox.showinfo("Result"
                          f"The string '{string}' is not accepted.")
                  
        restart_button = tk.Button(self, text='Restart',
                          font=('sans-serif', 12), command=self.restart)
        restart_button.pack(side="left", padx=115, pady=30)
          
        exit_button = tk.Button(self, text='Exit', padx=10,
                          font=('sans-serif', 12), command=self.exit)
        exit_button.pack(side="left", padx=125, pady=30)
      
    def accepts_odd_ones_even_zeros(self, string):
        state = 0
        for symbol in string:
            if state == 0:
                if symbol == '0':
                    state = 2
                elif symbol == '1':
                    state = 1
                else:
                    return False
            elif state == 1:
                if symbol == '0':
                    state = 3
                elif symbol == '1':
                    state = 0
                else:
                    return False
            elif state == 2:
                if symbol == '0':
                    state = 0
                elif symbol == '1':
                    state = 3
                else:
                    return False
            elif state == 3:
                if symbol == '0':
                    state = 1
                elif symbol == '1':
                    state = 2
                else:
                    return False
        return state == 1
  
    def accepts_even_ones_odd_zeros(self, string):
        state = 0
        for symbol in string:
            if state == 0:
                if symbol == '0':
                    state = 2
                elif symbol == '1':
                    state = 1
                else:
                    return False
            elif state == 1:
                if symbol == '0':
                    state = 3
                elif symbol == '1':
                    state = 0
                else:
                    return False
            elif state == 2:
                if symbol == '0':
                    state = 0
                elif symbol == '1':
                    state = 3
                else:
                    return False
            elif state == 3:
                if symbol == '0':
                    state = 1
                elif symbol == '1':
                    state = 2
                else:
                    return False
        return state == 2
  
    def accepts_even_ones_even_zeros(self, string):
        state = 0
        for symbol in string:
            if state == 0:
                if symbol == '0':
                    state = 1
                elif symbol == '1':
                    state = 2
                else:
                    return False
            elif state == 1:
                if symbol == '0':
                    state = 0
                elif symbol == '1':
                    state = 3
                else:
                    return False
            elif state == 2:
                if symbol == '0':
                    state = 3
                elif symbol == '1':
                    state = 0
                else:
                    return False
            elif state == 3:
                if symbol == '0':
                    state = 2
                elif symbol == '1':
                    state = 1
                else:
                    return False
        return state == 0
      
    def accepts_odd_ones_odd_zeros(self, string):
        state = 0
        for symbol in string:
            if state == 0:
                if symbol == '0':
                    state = 2
                elif symbol == '1':
                    state = 1
                else:
                    return False
            elif state == 1:
                if symbol == '0':
                    state = 3
                elif symbol == '1':
                    state = 0
                else:
                    return False
            elif state == 2:
                if symbol == '0':
                    state = 0
                elif symbol == '1':
                    state = 3
                else:
                    return False
            elif state == 3:
                if symbol == '0':
                    state = 1
                elif symbol == '1':
                    state = 2
                else:
                    return False
        return state == 3

7. Creating ‘credits()’ function and function to restart and exit the application 

The restart function is a method of the TuringMachineSimulator class that is called when the user clicks the “Restart” button. It destroys all the widgets on the current page and then creates the welcome page again by calling the create_welcome_page method. The exit function is also a method of the TuringMachineSimulator class that is called when the user clicks the “Exit” button. It calls the destroy method on the Tk instance to exit the application. The credits function is a method of the TuringMachineSimulator class that creates a label at the bottom of the page with a hyperlink to the GitHub repository of the project. When the user clicks the hyperlink, the repository is opened in their default web browser using the webbrowser module.




def restart(self):
    for widget in self.winfo_children():
        widget.destroy()
    self.create_welcome_page()
 
def exit(self):
    for widget in self.winfo_children():
        widget.destroy()
      
    self.exit_frame = tk.Frame(self)
    self.exit_frame.pack(pady=30)
      
    self.exit_label = tk.Label(self.exit_frame
                     , font=('Helvetica', 24))
      
    self.exit_label.config(text='Thank' 
                +'You for using the Simulator')
    self.exit_label.pack()
      
    self.after(1000,self.destroy)
      
def credits(self):
    made_by_label = tk.Label(self, text='GFG'
                             font=('Helvetica', 10)
                       , fg='blue', cursor='hand2')
    made_by_label.pack(side='bottom', pady=10)
    made_by_label.bind('<Button-1>'
    , lambda e: webbrowser.open_new("https:"
                     +"//www.geeksforgeeks.org/"))

Complete Code 




import tkinter as tk
from tkinter import messagebox
import webbrowser
  
  
class TuringMachineSimulator(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Turing Machine Simulator")
        self.geometry("600x500")
        self.create_welcome_page()
  
    def create_welcome_page(self):
        self.configure(bg="#1E90FF")
  
        tk.Label(self, text="Turing Machine Simulator", bg="#1E90FF",
                 fg="white"
                    font=('Helvetica', 32, "bold")).pack(pady=50)
  
        tk.Button(self, text="Get Started", bg="#FFFACD", font=(
            'sans-serif', 22, "bold"), 
             command=self.create_options_page).pack(pady=50)
  
        self.credits()
  
    def create_options_page(self):
        for widget in self.winfo_children():
            widget.destroy()
        self.configure(bg="#ADD8E6")
  
        tk.Label(self, text="Select an option:", bg="#ADD8E6",
                 font=('Verdana', 16)).pack(pady=20)
  
        options = [
          ("String should accept odd one's and even zero's", 0),
          ("String should accept even one's and odd zero's", 1),
          ("String should accept even one's and even zero's", 2),
          ("String should accept odd one's and odd zero's", 3)]
        self.selected_option = tk.IntVar()
  
        for option, value in options:
            tk.Radiobutton(self, text=option, bg="#ADD8E6", font=(
                'Verdana', 12), 
                 variable=self.selected_option, value=value).pack(pady=10)
  
        tk.Button(self, text="Next", bg="#FFFACD", font=(
            'sans-serif', 12), 
             command=self.create_input_page).pack(pady=30)
  
        self.credits()
  
    def create_input_page(self):
        for widget in self.winfo_children():
            widget.destroy()
  
        self.configure(bg="#90EE90")
        tk.Label(self, text="Enter a string:", bg="#90EE90",
                 font=('Verdana', 16)).pack(pady=20)
  
        self.string_input = tk.Entry(self, font=("Calibri", 14))
        self.string_input.pack(pady=10)
  
        tk.Button(self, text="Check", bg="#FFFACD", font=(
            'sans-serif', 12),
                  command=self.check_string).pack(pady=30)
  
        self.credits()
  
    def check_string(self):
        string = self.string_input.get()
        option = self.selected_option.get()
        if option == 0:
            if self.accepts_odd_ones_even_zeros(string):
                messagebox.showinfo(
                    "Result", f"The string '{string}' is accepted.")
            else:
                messagebox.showinfo(
                    "Result", f"The string '{string}' is not accepted.")
        elif option == 1:
            if self.accepts_even_ones_odd_zeros(string):
                messagebox.showinfo(
                    "Result", f"The string '{string}' is accepted.")
            else:
                messagebox.showinfo(
                    "Result", f"The string '{string}' is not accepted.")
        elif option == 2:
            if self.accepts_even_ones_even_zeros(string):
                messagebox.showinfo(
                    "Result", f"The string '{string}' is accepted.")
            else:
                messagebox.showinfo(
                    "Result", f"The string '{string}' is not accepted.")
        elif option == 3:
            if self.accepts_odd_ones_odd_zeros(string):
                messagebox.showinfo(
                    "Result", f"The string '{string}' is accepted.")
            else:
                messagebox.showinfo(
                    "Result", f"The string '{string}' is not accepted.")
  
        restart_button = tk.Button(self, text='Restart', font=(
            'sans-serif', 12), command=self.restart)
        restart_button.pack(side="left", padx=115, pady=30)
  
        exit_button = tk.Button(self, text='Exit', padx=10, font=(
            'sans-serif', 12), command=self.exit)
        exit_button.pack(side="left", padx=125, pady=30)
  
    def accepts_odd_ones_even_zeros(self, string):
        state = 0
        for symbol in string:
            if state == 0:
                if symbol == '0':
                    state = 2
                elif symbol == '1':
                    state = 1
                else:
                    return False
            elif state == 1:
                if symbol == '0':
                    state = 3
                elif symbol == '1':
                    state = 0
                else:
                    return False
            elif state == 2:
                if symbol == '0':
                    state = 0
                elif symbol == '1':
                    state = 3
                else:
                    return False
            elif state == 3:
                if symbol == '0':
                    state = 1
                elif symbol == '1':
                    state = 2
                else:
                    return False
        return state == 1
  
    def accepts_even_ones_odd_zeros(self, string):
        state = 0
        for symbol in string:
            if state == 0:
                if symbol == '0':
                    state = 2
                elif symbol == '1':
                    state = 1
                else:
                    return False
            elif state == 1:
                if symbol == '0':
                    state = 3
                elif symbol == '1':
                    state = 0
                else:
                    return False
            elif state == 2:
                if symbol == '0':
                    state = 0
                elif symbol == '1':
                    state = 3
                else:
                    return False
            elif state == 3:
                if symbol == '0':
                    state = 1
                elif symbol == '1':
                    state = 2
                else:
                    return False
        return state == 2
  
    def accepts_even_ones_even_zeros(self, string):
        state = 0
        for symbol in string:
            if state == 0:
                if symbol == '0':
                    state = 1
                elif symbol == '1':
                    state = 2
                else:
                    return False
            elif state == 1:
                if symbol == '0':
                    state = 0
                elif symbol == '1':
                    state = 3
                else:
                    return False
            elif state == 2:
                if symbol == '0':
                    state = 3
                elif symbol == '1':
                    state = 0
                else:
                    return False
            elif state == 3:
                if symbol == '0':
                    state = 2
                elif symbol == '1':
                    state = 1
                else:
                    return False
        return state == 0
  
    def accepts_odd_ones_odd_zeros(self, string):
        state = 0
        for symbol in string:
            if state == 0:
                if symbol == '0':
                    state = 2
                elif symbol == '1':
                    state = 1
                else:
                    return False
            elif state == 1:
                if symbol == '0':
                    state = 3
                elif symbol == '1':
                    state = 0
                else:
                    return False
            elif state == 2:
                if symbol == '0':
                    state = 0
                elif symbol == '1':
                    state = 3
                else:
                    return False
            elif state == 3:
                if symbol == '0':
                    state = 1
                elif symbol == '1':
                    state = 2
                else:
                    return False
        return state == 3
  
    def restart(self):
        for widget in self.winfo_children():
            widget.destroy()
        self.create_welcome_page()
  
    def exit(self):
        for widget in self.winfo_children():
            widget.destroy()
  
        self.exit_frame = tk.Frame(self)
        self.exit_frame.pack(pady=30)
  
        self.exit_label = tk.Label(self.exit_frame,
                                   font=('Helvetica', 24))
  
        self.exit_label.config(text='Thank You for"+ 
                "using the Simulator')
        self.exit_label.pack()
  
        self.after(1000, self.destroy)
  
    def credits(self):
        made_by_label = tk.Label(self, text='GFG', font=(
            'Helvetica', 10), fg='blue', cursor='hand2')
        made_by_label.pack(side='bottom', pady=10)
        made_by_label.bind(
            '<Button-1>', lambda e: webbrowser.open_new("https:"
                               +"//www.geeksforgeeks.org/"))
  
  
if __name__ == '__main__':
    app = TuringMachineSimulator()
    app.mainloop()

Output 

GIF


Article Tags :