You are on page 1of 17

NAME : S.

ABHISESHA
KUMAARA
REG NO :
RA2211026010487
SECTION : Z2
Week 13- Tutorial Assignment

Sample programs to Construct NFA and DFA using


Python
PROGRAM

1. Write a Python program to create an NFA that accepts strings


containing only the letter 'a'.
class NFA:
def __init__(self):
self.states = set()
self.start_state = None
self.accept_states =
set() self.transitions =
{}

def add_state(self,
state):
self.states.add(state)
def set_start_state(self, state):
self.start_state = state
self.add_state(state)
def add_accept_state(self, state):
self.accept_states.add(state)
self.add_state(state)
def add_transition(self, from_state, symbol, to_state):
if from_state not in self.states:
self.add_state(from_state)
if to_state not in self.states:
self.add_state(to_state)
if (from_state, symbol) in self.transitions:
self.transitions[(from_state, symbol)].add(to_state)
else:
self.transitions[(from_state, symbol)] = {to_state}
def is_accepted(self, input_string):
current_states = {self.start_state}
for symbol in input_string:
next_states = set()
for state in current_states:
if (state, symbol) in self.transitions:
next_states.update(self.transitions[(state, symbol)])
current_states = next_states
return bool(current_states.intersection(self.accept_states))

• Create an NFA for strings containing only


the letter 'a' nfa = NFA()
nfa.set_start_state(0)
nfa.add_accept_state(1)
nfa.add_transition(0, 'a',
1)

• Test the NFA with some strings


test_strings = ["a", "aa", "aaa",
"ab", "b"] for test_string in
test_strings:
if nfa.is_accepted(test_string):
print(f"'{test_string}' is accepted")
else:
print(f"'{test_string}' is not accepted")
1. Create a Python function to check if a given string is accepted
by an NFA that recognizes the pattern "ab|ba" (either "ab" or
"ba").
class NFA:
def __init__(self):
self.states = set()
self.start_state = None
self.accept_states =
set() self.transitions =
{}

def add_state(self,
state):
self.states.add(state)
def set_start_state(self, state):
self.start_state = state
self.add_state(state)
def add_accept_state(self, state):
self.accept_states.add(state)
self.add_state(state)

def add_transition(self, from_state, symbol, to_state):


if from_state not in self.states:
self.add_state(from_state)
if to_state not in self.states:
self.add_state(to_state)
if (from_state, symbol) in self.transitions:
self.transitions[(from_state, symbol)].add(to_state)
else:
self.transitions[(from_state, symbol)] = {to_state}

def is_accepted(self, input_string):


current_states = {self.start_state}
for symbol in input_string:
next_states = set()
for state in current_states:
if (state, symbol) in self.transitions:
next_states.update(self.transitions[(state, symbol)])

current_states = next_states
return bool(current_states.intersection(self.accept_states))

def is_accepted_by_nfa(input_string):
nfa = NFA()
nfa.set_start_state(0)
nfa.add_accept_state(1)
nfa.add_accept_state(2)
nfa.add_transition(0, 'a', 1)
nfa.add_transition(0, 'b', 3)
nfa.add_transition(1, 'b', 2)
nfa.add_transition(3, 'a', 2)
return nfa.is_accepted(input_string)

# Test the function with some strings


test_strings = ["ab", "ba", "abb", "baa",
"abc"] for test_string in test_strings:
if is_accepted_by_nfa(test_string):
print(f"'{test_string}' is accepted")
else:
print(f"'{test_string}' is not accepted")

1. Implement a Python script that converts a simple NFA into a


DFA with two states.
class NFA:
def __init__(self):
self.states = set()
self.start_state = None
self.accept_states = set()
self.transitions = {}

def add_state(self, state):


self.states.add(state)
def set_start_state(self, state):
self.start_state = state
self.add_state(state)
def add_accept_state(self, state):
self.accept_states.add(state)
self.add_state(state)
def add_transition(self, from_state, symbol, to_state):
if from_state not in self.states:
self.add_state(from_state)
if to_state not in self.states:
self.add_state(to_state)
if (from_state, symbol) in self.transitions:
self.transitions[(from_state, symbol)].add(to_state)
else:
self.transitions[(from_state, symbol)] = {to_state}
def is_accepted(self, input_string):
current_states = {self.start_state}
for symbol in input_string:
next_states = set()
for state in current_states:
if (state, symbol) in self.transitions:
next_states.update(self.transitions[(state, symbol)])
current_states = next_states
return bool(current_states.intersection(self.accept_states))

def convert_nfa_to_dfa(nfa):
dfa = NFA()

• Helper function to get epsilon closure of a set


of states def epsilon_closure(states):
closure = set(states)
stack = list(states)
while stack:
state = stack.pop()
if ('', state) in nfa.transitions: epsilon_transitions
= nfa.transitions[('', state)] for epsilon_state in
epsilon_transitions:

if epsilon_state not in closure:


closure.add(epsilon_state)
stack.append(epsilon_state)
return closure

• Initialize the DFA with the epsilon closure of the start state of
the NFA dfa_start_state = epsilon_closure({nfa.start_state})
dfa.set_start_state(tuple(sorted(dfa_start_state)))
• Create a queue to keep track of unprocessed DFA states
state_queue = [dfa_start_state]
while state_queue:
current_dfa_state = state_queue.pop(0)
for symbol in set(s for s, _ in nfa.transitions.keys() if s != ''):
next_states = set()
for nfa_state in current_dfa_state:
if (symbol, nfa_state) in nfa.transitions:
next_states.update(nfa.transitions[(symbol, nfa_state)])
epsilon_next_states = epsilon_closure(next_states)
if epsilon_next_states:
dfa_state = tuple(sorted(epsilon_next_states))
dfa.add_transition(current_dfa_state, symbol, dfa_state)
if dfa_state not in dfa.states:
dfa.states.add(dfa_state)
state_queue.append(dfa_state)

• Determine accept states of


the DFA for dfa_state in
dfa.states:
if any(state in dfa_state for state in nfa.accept_states):
dfa.accept_states.add(dfa_state)

return dfa

• Create a simple NFA nfa =


NFA()
nfa.set_start_state('A')
nfa.add_accept_state('B')
nfa.add_transition('A', 'a',
'B')

• Convert the NFA to a DFA


dfa =
convert_nfa_to_dfa(nfa)

• Define a function to check if a string is accepted


by the DFA def is_accepted_by_dfa(input_string,
dfa):
return dfa.is_accepted(input_string)
• Test the DFA with some strings
test_strings = ["a", "aa", "ab",
"ba", "b"] for test_string in
test_strings:
if is_accepted_by_dfa(test_string, dfa):
print(f"'{test_string}' is accepted")
else:
print(f"'{test_string}' is not accepted")

1. Write a Python program to construct a DFA that accepts binary


strings ending in '01'.
class DFA:
def __init__(self):
self.states = set()
self.start_state = None
self.accept_states =
set()

self.transitions = {}
def add_state(self, state):
self.states.add(state)
def set_start_state(self, state):
self.start_state = state
self.add_state(state)
def add_accept_state(self, state):
self.accept_states.add(state)
self.add_state(state)
def add_transition(self, from_state, symbol, to_state):
if from_state not in self.states:
self.add_state(from_state)
if to_state not in self.states:
self.add_state(to_state)
self.transitions[(from_state, symbol)] = to_state
def is_accepted(self, input_string):
current_state = self.start_state
for symbol in input_string:
if (current_state, symbol) in self.transitions:
current_state = self.transitions[(current_state, symbol)]
else:
return False
return current_state in self.accept_states

• Construct a DFA for binary strings


ending in '01' dfa = DFA()
dfa.set_start_state('A')
dfa.add_accept_state('B')
dfa.add_state('C')

dfa.add_transition('A', '0', 'A')


dfa.add_transition('A', '1', 'C')
dfa.add_transition('C', '0', 'B')
dfa.add_transition('C', '1', 'C')
dfa.add_transition('B', '0', 'B')
dfa.add_transition('B', '1', 'C')

• Define a function to check if a string is accepted


by the DFA def is_accepted_by_dfa(input_string,
dfa):
return dfa.is_accepted(input_string)
• Test the DFA with some binary strings
test_strings = ["101", "1101", "001", "011",
"100", "0101"] for test_string in test_strings:
if is_accepted_by_dfa(test_string, dfa):
print(f"'{test_string}' is accepted")
else:
print(f"'{test_string}' is not accepted")

• Develop a Python function that takes an NFA and returns the set of
states that can be reached from a given state on a specific input symbol.
class NFA:
def __init__(self):
self.states = set()
self.start_state = None
self.accept_states =
set() self.transitions =
{}

• ... (other NFA methods)


def epsilon_closure(self, states):
closure = set(states)
stack = list(states)
while stack:
state = stack.pop()
if ('', state) in self.transitions:
epsilon_transitions = self.transitions[('', state)]
for epsilon_state in epsilon_transitions:
if epsilon_state not in closure:
closure.add(epsilon_state)
stack.append(epsilon_state)
return closure
def get_states_on_input(self, input_symbol, current_states):
next_states = set()
for state in current_states:
if (input_symbol, state) in self.transitions:
next_states.update(self.transitions[(input_symbol, state)])
return self.epsilon_closure(next_states)
def get_states_on_input_symbol(nfa, input_symbol, current_states):
return nfa.get_states_on_input(input_symbol, current_states)

• Example usage:
nfa = NFA()
• ... (Define your NFA)
start_state = 'A' # Replace with the actual start state
input_symbol = 'a' # Replace with the desired input symbol

reachable_states = get_states_on_input_symbol(nfa,
input_symbol, {start_state})
print("States reachable on input symbol", input_symbol,
"from state", start_state, "are:", reachable_states)

1. Create a Python script to minimize a simple DFA with


three states by merging equivalent states.
class DFA:
def __init__(self):
self.states = set()
self.start_state = None
self.accept_states = set()
self.transitions = {}
def add_state(self, state):
self.states.add(state)
def set_start_state(self, state):
self.start_state = state
self.add_state(state)
def add_accept_state(self, state):
self.accept_states.add(state)
self.add_state(state)
def add_transition(self, from_state, symbol, to_state):
if from_state not in self.states:
self.add_state(from_state)
if to_state not in self.states:
self.add_state(to_state)
self.transitions[(from_state, symbol)] = to_state

def is_accepted(self, input_string):


current_state = self.start_state
for symbol in input_string:
if (current_state, symbol) in self.transitions:
current_state = self.transitions[(current_state, symbol)]
else:
return False
return current_state in self.accept_states

• Construct a DFA for binary strings


ending in '01' dfa = DFA()
dfa.set_start_state('A')
dfa.add_accept_state('B')
dfa.add_state('C')

dfa.add_transition('A', '0', 'A')


dfa.add_transition('A', '1', 'C')
dfa.add_transition('C', '0', 'B')
dfa.add_transition('C', '1', 'C')
dfa.add_transition('B', '0', 'B')
dfa.add_transition('B', '1', 'C')

• Define a function to check if a string is accepted by


the DFA def is_accepted_by_dfa(input_string, dfa):
return dfa.is_accepted(input_string)
• Test the DFA with some binary strings
test_strings = ["101", "1101", "001", "011", "100",
"0101"] for test_string in test_strings:
if is_accepted_by_dfa(test_string, dfa):
print(f"'{test_string}' is accepted")
else:
print(f"'{test_string}' is not accepted")

1. Implement a Python function that checks if a given string is


accepted by a DFA that recognizes the pattern "ab*c".class DFA:
def __init__(self):
self.states = set()
self.start_state = None
self.accept_states = set()
self.transitions = {}

def add_state(self, state):


self.states.add(state)
def set_start_state(self, state):
self.start_state = state
self.add_state(state)
def add_accept_state(self, state):
self.accept_states.add(state)
self.add_state(state)
def add_transition(self, from_state, symbol, to_state):
if from_state not in self.states:
self.add_state(from_state)
if to_state not in self.states:
self.add_state(to_state)
self.transitions[(from_state, symbol)] = to_state
def is_accepted(self, input_string):
current_state = self.start_state
for symbol in input_string:
if (current_state, symbol) in self.transitions:
current_state = self.transitions[(current_state, symbol)]
else:
return False
return current_state in self.accept_states
# Construct a DFA for binary strings ending in '01'
dfa = DFA()
dfa.set_start_state('A')
dfa.add_accept_state('B')
dfa.add_state('C')
dfa.add_transition('A', '0', 'A')
dfa.add_transition('A', '1', 'C')
dfa.add_transition('C', '0', 'B')
dfa.add_transition('C', '1', 'C')
dfa.add_transition('B', '0', 'B')
dfa.add_transition('B', '1', 'C')

• Define a function to check if a string is accepted by


the DFA def is_accepted_by_dfa(input_string, dfa):
return dfa.is_accepted(input_string)
• Test the DFA with some binary strings
test_strings = ["101", "1101", "001", "011", "100",
"0101"] for test_string in test_strings:
if is_accepted_by_dfa(test_string, dfa):
print(f"'{test_string}' is accepted")
else:
print(f"'{test_string}' is not accepted")

1. Write a Python program to create an NFA that accepts strings


with an odd number of '1's.
class NFA:
def __init__(self):
self.states = set()
self.start_state = None
self.accept_states = set()
self.transitions = {}

def add_state(self, state):


self.states.add(state)
def set_start_state(self, state):
self.start_state = state
self.add_state(state)

def add_accept_state(self, state):


self.accept_states.add(state)
self.add_state(state)
def add_transition(self, from_state, symbol, to_state):
if from_state not in self.states:
self.add_state(from_state)
if to_state not in self.states:
self.add_state(to_state)
if (from_state, symbol) in self.transitions:
self.transitions[(from_state, symbol)].add(to_state)
else:
self.transitions[(from_state, symbol)] = {to_state}
def is_accepted(self, input_string):
current_states = {self.start_state}
for symbol in input_string:
next_states = set()
for state in current_states:
if (state, symbol) in self.transitions:
next_states.update(self.transitions[(state, symbol)])
current_states = next_states

return any(state in self.accept_states for state in current_states)

• Create an NFA that accepts strings with an odd


number of '1's nfa = NFA()
nfa.set_start_state('A')
nfa.add_accept_state('B')
nfa.add_state('C')

nfa.add_transition('A', '0', 'A')


nfa.add_transition('A', '1', 'B')
nfa.add_transition('B', '0', 'B')
nfa.add_transition('B', '1', 'A')
nfa.add_transition('C', '0', 'C')
nfa.add_transition('C', '1', 'C')
# Test the NFA with some strings
test_strings = ["1", "11", "111", "0", "00",
"000"] for test_string in test_strings:
if nfa.is_accepted(test_string):
print(f"'{test_string}' is accepted")
else:
print(f"'{test_string}' is not accepted")

1. Develop a Python function that converts a simple regular


expression like "a(b|c)*" into inequivalent NFA.
def convert_regex_to_nfa(regex):
def epsilon_transition():
return {'': set()}
def new_state():
nonlocal state_counter
state = f'q{state_counter}'
state_counter += 1
return state
def parse(regex):
stack = []
concat = False
i=0
while i < len(regex):
if regex[i] == '(':
stack.append('(')
elif regex[i] == ')':
while stack and stack[-1] != '(':
process_operation(stack.pop())
stack.pop() #

You might also like