Homework 2
Objectives
- Continue exploring deterministic finite automata (DFAs) using code
- Build upon previous assignments’ code
- Practice simulating computation
Homework Problems
-
Simulating Computation for DFAs (3 points)
-
DFAs and the Language They Recognize (2 points)
-
DFA->XML (2 points)
-
The Union Operation (2 points)
-
README.md (1 point)
Total: 10 points
Submitting
Submit your solution to this assignment in Gradescope.
A submission must include the following files (NOTE: everything is case-sensitive):
-
a
Makefile
with the following targets:-
setup
(optional) -
run-hw2-dfa
-
run-hw2-dfalang
-
run-hw2-dfa2xml
-
run-hw2-union
-
-
a
README.md
containing the required information, -
and, files containing the solution to each problem.
1. Simulating Computation for DFAs
Recall the formal definition of computation from page 40 of the textbook:
A finite automata $M = (Q,\Sigma,\delta,q_0,F)$ accepts a string $w = w_1,\ldots,w_n$, where each character $w_i \in \Sigma$, if there exists a sequence of states $r_0,\ldots,r_n$, where $r_i \in Q$, and:
-
$r_0=q_0$
-
$\delta(r_i,w_{i+1}) = r_{i+1}, for i = 0,\ldots,n-1$
-
$r_n\in F$
This problem asks you to demonstrate, with code, that you understand this concept.
Your Tasks
-
Write a “run” predicate (a function or method that returns true or false) that takes two arguments, an instance of your DFA representation (as defined in an earlier assignment]) and a string, and “runs” the string on the DFA.
The function should return true if the DFA accepts the string, and false otherwise.
-
Then write a program that reads from
stdin
and feeds that input, along with the Figure 1.4’s DFA (i.e., the one created in an earlier assignment) to your “run” predicate. This program writesaccept
tostdout
if the DFA accepts the input andreject
otherwise.Your solution will be tested as follows:
-
Makefile
target name:run-hw2-dfa
-
Input (from
stdin
): a (randomly generated) string in alphabet $\Sigma = {0,1}$ -
Expected Output (to
stdout
):-
accept
, if Figure 1.4’s DFA accepts input, -
otherwise
reject
otherwise
-
-
Example:
printf "000111" | make -sf Makefile run-hw2-dfa
Output:
accept
printf "10" | make -sf Makefile run-hw2-dfa
Output:
reject
-
2. DFAs and the Language They Recognize
The language that a DFA recognizes is the set of all strings accepted by the DFA.
Your Tasks
-
Write a function or method that, given an XML file containing an automaton element, constructs an instance of your DFA representation. You’ve already done the part of this which extracted the states, so now just extract the transitions.
-
Using your predicate from Simulating Computation for DFAs, write a function or method that, given a DFA, prints all strings in the language that it recognizes, up to strings of length 5, one per line.
You may find your solution to Homework 0 useful here.
Your solution will be tested as follows:
-
Makefile
target name:run-hw2-dfalang
-
Input (from
stdin
): XML file name, containing a DFA automaton element -
Expected Output (to
stdout
): all strings in the language of the DFA, up to strings of length 5, one string per line (order doesn’t matter, since we’re printing a set) -
Example:
You can test your program with this file named
fig1.4.jff
containing the DFA from Figure 1.4 of the textbook.printf "fig1.4.jff" | make -sf Makefile run-hw2-dfalang
Output:
00001 00011 00100 00101 00111 01001 01011 01100 01101 01111 10000 10001 10011 10100 10101 10111 11001 11011 11100 11101 11111 0001 0011 0100 0101 0111 1001 1011 1100 1101 1111 001 011 100 101 111 01 11 1
Example2:
You can test your program with this file named
dfa-empty.jff
containing a DFA that only accepts the empty string.printf "dfa-empty.jff" | make -sf Makefile run-hw2-dfalang
Output:
(it’s an empty line)
3. DFA->XML
Your Tasks
-
Write a function that converts an instance of your DFA to an XML string corresponding to an automaton element.
-
Implement the “three 1’s” DFA from class as an instance of your DFA representation.
-
Write a program that when run, calls your DFA->XML function with this DFA as argument, and prints the result to
stdout
.
Your solution will be tested as follows:
-
Makefile
target name:run-hw2-dfa2xml
-
Input (from
stdin
): none -
Expected Output (to
stdout
): XML representing the “three 1s” DFA from class
Note: Whitespace doesn’t matter for XML. So something like:
`<state id="q1" name="q1"><initial/></state>`
is equivalent to:
<state id="q1" name="q1">
<initial/>
</state>
4. The Union Operation
This question will ask you to demonstrate, with code, that you understand the proof showing that the union operation is closed for regular languages (Theorem 1.25).
To do so, you will have to put together everything you’ve done so far in the homeworks.
Your Task
Implement a union operation for your DFAs. Specifically, write a function that, given:
-
a DFA recognizing language $A_1$, and
-
a DFA recognizing language $A_2$
returns a DFA recognizing $A_1 \cup A_2$.
This solution implements the algorithm from Theorem 1.25 of the textbook (so rereading that will be helpful), thus proving it.
Your solution will be tested as follows:
-
Makefile
target name:run-hw2-union
-
Input (from
stdin
): the names of two XML files, separated by a space, each containing an automaton element representing a DFA -
Expected Output (to
stdout
): an automaton XML string representing a DFA that is the union of the two inputs -
Example:
You can test your program with these files:
printf "dfa-a.xml dfa-b.xml" | make -sf Makefile run-hw2-union
Output:
<automaton>
<state id="(1 1)" name="(1 1)"><initial/></state>
<state id="(1 2)" name="(1 2)"><final/></state>
<state id="(1 3)" name="(1 3)"></state>
<state id="(2 1)" name="(2 1)"><final/></state>
<state id="(2 2)" name="(2 2)"><final/></state>
<state id="(2 3)" name="(2 3)"><final/></state>
<state id="(3 1)" name="(3 1)"></state>
<state id="(3 2)" name="(3 2)"><final/></state>
<state id="(3 3)" name="(3 3)"></state>
<transition><from>(1 1)</from><to>(2 3)</to><read>a</read></transition>
<transition><from>(1 1)</from><to>(3 2)</to><read>b</read></transition>
<transition><from>(1 2)</from><to>(2 3)</to><read>a</read></transition>
<transition><from>(1 2)</from><to>(3 3)</to><read>b</read></transition>
<transition><from>(1 3)</from><to>(2 3)</to><read>a</read></transition>
<transition><from>(1 3)</from><to>(3 3)</to><read>b</read></transition>
<transition><from>(2 1)</from><to>(3 3)</to><read>a</read></transition>
<transition><from>(2 1)</from><to>(3 2)</to><read>b</read></transition>
<transition><from>(2 2)</from><to>(3 3)</to><read>a</read></transition>
<transition><from>(2 2)</from><to>(3 3)</to><read>b</read></transition>
<transition><from>(2 3)</from><to>(3 3)</to><read>a</read></transition>
<transition><from>(2 3)</from><to>(3 3)</to><read>b</read></transition>
<transition><from>(3 1)</from><to>(3 3)</to><read>a</read></transition>
<transition><from>(3 1)</from><to>(3 2)</to><read>b</read></transition>
<transition><from>(3 2)</from><to>(3 3)</to><read>a</read></transition>
<transition><from>(3 2)</from><to>(3 3)</to><read>b</read></transition>
<transition><from>(3 3)</from><to>(3 3)</to><read>a</read></transition>
<transition><from>(3 3)</from><to>(3 3)</to><read>b</read></transition>
</automaton>