Homework 2
Last updated: Wed, 7 Oct 2020 12:06:42 -0400
Out: Wed Sept 23, 00:00 EST Due: Tues Sept 29, 23:59 EST
This assignment involves non-deterministic finite automata (NFAs).
Homework Problems
Submitting
Note: This assignment has a non-code component, see NFAs vs DFAs.
Submit the non-code part of this assignment at Gradescope hw2 non-code.
It must be a pdf or plain text file that is assigned to the correct problem when submitted.
Submit the code part of your solution to this assignment at Gradescope hw2.
The code submission must include the following files:- a Makefile with the following targets:
setup
run-hw2-nfa
run-hw2-union
run-hw2-nfa2dfa
a README containing the required information,
and the source code files needed by your Makefile.
1 Data Representation for NFAs
Q is a finite set of states,
\Sigma is a finite alphabet,
\delta:Q\times\Sigma_\epsilon\rightarrow \mathcal{P}(Q) is the transition function mapping a state and (possibly empty string) input to a set of states,
q_0\in Q is the start state, and
F\subseteq Q is the set of accept states.
Your Tasks
Design a data representation for the NFAs from the textbook. You may use objects, structs, or anything else available in your language.
Implement your data representation in your chosen language.
Write a predicate (a function or method that returns true or false) that takes an input string and an instance of your NFA and "runs" it on the NFA. It should return true if the NFA accepts the input, and false otherwise.
2 NFAs and the Language They Recognize
The language that a NFA recognizes is the set of all strings accepted by the NFA.
Your Tasks
Write a function or method that, given an XML file containing an automaton element (see Homework 0, Parsing XML Files), constructs an instance of your NFA.
NOTE: The XML structure for an NFA is the same as a DFA, except:
NFAs may have multiple transitions with the same from and read.
For example, Figure 1.27’s XML below has two transitions for from 1, read 1:
<transition><from>1</from><to>1</to><read>1</read></transition>
<transition><from>1</from><to>2</to><read>1</read></transition>
Also, the read element may be empty. This represents an \varepsilon empty string transition.
For example, Figure 1.27’s XML given below has:
<transition><from>2</from><to>3</to><read/></transition>
You must decide how to parse and organize these in your representation.Using your predicate from above, write a function or method that, given an NFA, prints all strings in the language that it recognizes, up to strings of length 5, one per line.
You may find your solution to the Sets and Alphabets problem useful here.
Your solution will be tested as follows:
Input (from stdin): XML file name, containing an NFA automaton element
Expected Output (to stdout): all strings in the language of the NFA, up to strings of length 5, one string per line
Makefile target name: run-hw2-nfa
Example:
You can test your program with this file named fig1.27-nfa.jff containing the NFA from figure 1.27 of the textbook.
printf "fig1.27-nfa.jff" | make -sf Makefile run-hw2-nfa
Output:00011
00101
00110
00111
01010
01011
01100
01101
01110
01111
10011
10100
10101
10110
10111
11000
11001
11010
11011
11100
11101
11110
11111
0011
0101
0110
0111
1010
1011
1100
1101
1110
1111
011
101
110
111
11
3 The Union Operation, on NFAs
Your Task
Implement the union operation for your NFAs. It should be much easier now with NFAs.
Specifically, write a function that, given:
an NFA recognizing language A_1, and
an NFA recognizing language A_2
To do this, you’ll need to be able to extract individual components of an NFA instance, e.g., the states, transitions, etc., and use them to create a new NFA.
NOTE: When combining NFAs be careful with duplicate state names. Since the given files may use the same state names, it may be a good idea to first rename them to something unique.
Your solution will be tested as follows:
Input (from stdin): the names of two XML files, separated by a space, each containing an automaton element representing an NFA
Expected Output (to stdout): an automaton XML string representing an NFA that is the union of the two inputs
Makefile target name: run-hw2-union
Example:
You can test your program with these files:printf "nfa-a.xml nfa-b.xml" | make -sf Makefile run-hw2-union
Output:<automaton>
<state id="q217" name="q217"><initial/></state>
<state id="1" name="1"></state>
<state id="2" name="2"><final/></state>
<state id="3" name="3"></state>
<state id="1214" name="1214"></state>
<state id="2215" name="2215"><final/></state>
<state id="3216" name="3216"></state>
<transition><from>q217</from><to>1</to><read/></transition>
<transition><from>q217</from><to>1214</to><read/></transition>
<transition><from>1</from><to>2</to><read>a</read></transition>
<transition><from>1</from><to>3</to><read>b</read></transition>
<transition><from>2</from><to>3</to><read>a</read></transition>
<transition><from>2</from><to>3</to><read>b</read></transition>
<transition><from>3</from><to>3</to><read>a</read></transition>
<transition><from>3</from><to>3</to><read>b</read></transition>
<transition><from>1214</from><to>3216</to><read>a</read></transition>
<transition><from>1214</from><to>2215</to><read>b</read></transition>
<transition><from>2215</from><to>3216</to><read>a</read></transition>
<transition><from>2215</from><to>3216</to><read>b</read></transition>
<transition><from>3216</from><to>3216</to><read>a</read></transition>
<transition><from>3216</from><to>3216</to><read>b</read></transition>
</automaton>
4 NFA -> DFA (Optional Bonus)
Implement the proof by construction of Theorem 1.39 from the textbook.
In other words, implement a function or method that converts an NFA from the Data Representation for NFAs problem to a DFA (from Homework 1, A Data Representation for DFAs problem).
Your solution should emit a DFA automaton XML element. Your solutions from HW1 should be useful here, specifically, use the solution from Create Your Own DFA to write the XML output, and use the solution from A Data Representation for DFAs to check that your output is actually a valid DFA.
Your solution will be tested as follows:
Input (from stdin): the name of an XML file containing an automaton element representing an NFA
Expected Output (to stdout): an automaton element representing an equivalent DFA
Makefile target name: run-hw2-nfa2dfa
Example:
You can test your program with this file: fig1.27-nfa.jff
printf "fig1.27-nfa.jff" | make -sf Makefile run-hw2-nfa2dfa
Output:<automaton>
<state id="()" name="()"></state>
<state id="(q1)" name="(q1)"><initial/></state>
<state id="(q2)" name="(q2)"></state>
<state id="(q1 q2)" name="(q1 q2)"></state>
<state id="(q3)" name="(q3)"></state>
<state id="(q1 q3)" name="(q1 q3)"></state>
<state id="(q2 q3)" name="(q2 q3)"></state>
<state id="(q1 q2 q3)" name="(q1 q2 q3)"></state>
<state id="(q4)" name="(q4)"><final/></state>
<state id="(q1 q4)" name="(q1 q4)"><final/></state>
<state id="(q2 q4)" name="(q2 q4)"><final/></state>
<state id="(q1 q2 q4)" name="(q1 q2 q4)"><final/></state>
<state id="(q3 q4)" name="(q3 q4)"><final/></state>
<state id="(q1 q3 q4)" name="(q1 q3 q4)"><final/></state>
<state id="(q2 q3 q4)" name="(q2 q3 q4)"><final/></state>
<state id="(q1 q2 q3 q4)" name="(q1 q2 q3 q4)"><final/></state>
<transition><from>()</from><to>()</to><read>0</read></transition>
<transition><from>()</from><to>()</to><read>1</read></transition>
<transition><from>(q1)</from><to>(q1)</to><read>0</read></transition>
<transition><from>(q1)</from><to>(q1 q2 q3)</to><read>1</read></transition>
<transition><from>(q2)</from><to>(q3)</to><read>0</read></transition>
<transition><from>(q2)</from><to>()</to><read>1</read></transition>
<transition><from>(q1 q2)</from><to>(q1 q3)</to><read>0</read></transition>
<transition><from>(q1 q2)</from><to>(q1 q2 q3)</to><read>1</read></transition>
<transition><from>(q3)</from><to>()</to><read>0</read></transition>
<transition><from>(q3)</from><to>(q4)</to><read>1</read></transition>
<transition><from>(q1 q3)</from><to>(q1)</to><read>0</read></transition>
<transition><from>(q1 q3)</from><to>(q1 q2 q3 q4)</to><read>1</read></transition>
<transition><from>(q2 q3)</from><to>(q3)</to><read>0</read></transition>
<transition><from>(q2 q3)</from><to>(q4)</to><read>1</read></transition>
<transition><from>(q1 q2 q3)</from><to>(q1 q3)</to><read>0</read></transition>
<transition><from>(q1 q2 q3)</from><to>(q1 q2 q3 q4)</to><read>1</read></transition>
<transition><from>(q4)</from><to>(q4)</to><read>0</read></transition>
<transition><from>(q4)</from><to>(q4)</to><read>1</read></transition>
<transition><from>(q1 q4)</from><to>(q1 q4)</to><read>0</read></transition>
<transition><from>(q1 q4)</from><to>(q1 q2 q3 q4)</to><read>1</read></transition>
<transition><from>(q2 q4)</from><to>(q3 q4)</to><read>0</read></transition>
<transition><from>(q2 q4)</from><to>(q4)</to><read>1</read></transition>
<transition><from>(q1 q2 q4)</from><to>(q1 q3 q4)</to><read>0</read></transition>
<transition><from>(q1 q2 q4)</from><to>(q1 q2 q3 q4)</to><read>1</read></transition>
<transition><from>(q3 q4)</from><to>(q4)</to><read>0</read></transition>
<transition><from>(q3 q4)</from><to>(q4)</to><read>1</read></transition>
<transition><from>(q1 q3 q4)</from><to>(q1 q4)</to><read>0</read></transition>
<transition><from>(q1 q3 q4)</from><to>(q1 q2 q3 q4)</to><read>1</read></transition>
<transition><from>(q2 q3 q4)</from><to>(q3 q4)</to><read>0</read></transition>
<transition><from>(q2 q3 q4)</from><to>(q4)</to><read>1</read></transition>
<transition><from>(q1 q2 q3 q4)</from><to>(q1 q3 q4)</to><read>0</read></transition>
<transition><from>(q1 q2 q3 q4)</from><to>(q1 q2 q3 q4)</to><read>1</read></transition>
</automaton>
5 NFAs vs DFAs
Give a proof of the following theorem:
For any language A, some DFA M recognizes A
if and only if some NFA N recognizes A.
You may assume the theorem from NFA -> DFA (Optional Bonus)
You may write up your proof in any form but the submission must either be a pdf or readable as plain text. Also, make sure you assign it to the proper problem in gradescope when submitting.