# Title: Reading Machine Minds # It can be difficult to predict what strings a finite state machine will # accept. A tricky finite state machine may not accept any! A finite state # machine that accepts no strings is said to be *empty*. # # In this homework problem you will determine if a finite state machine is # empty or not. If it is not empty, you will prove that by returning a # string that it accepts. # # Formally, you will write a procedure nfsmaccepts() that takes four # arguments corresponding to a non-derministic finite state machine: # the start (or current) state # the edges (encoded as a mapping) # the list of accepting states # a list of states already visited (starts empty) # # If the finite state machine accepts any string, your procedure must # return one such string (your choice!). Otherwise, if the finite state # machine is empty, your procedure must return None (the value None, not # the string "None"). # # For example, this non-deterministic machine ... edges = { (1, 'a') : [2, 3], (2, 'a') : [2], (3, 'b') : [4, 2], (4, 'c') : [5] } accepting = [5] # ... accepts exactly one string: "abc". By contrast, this # non-deterministic machine: edges2 = { (1, 'a') : [1], (2, 'a') : [2] } accepting2 = [2] # ... accepts no strings (if you look closely, you'll see that you cannot # actually reach state 2 when starting in state 1). # Hint #1: This problem is trickier than it looks. If you do not keep track # of where you have been, your procedure may loop forever on the second # example. Before you make a recursive call, add the current state to the # list of visited states (and be sure to check the list of visited states # elsewhere). # # Hint #2: (Base Case) If the current state is accepting, you can return # "" as an accepting string. # # Hint #3: (Recursion) If you have an outgoing edge labeled "a" that # goes to a state that accepts on the string "bc" (i.e., the recursive call # returns "bc"), then you can return "abc". # # Hint #4: You may want to iterate over all of the edges and only consider # those relevant to your current state. "for edge in edges" will iterate # over all of the keys in the mapping (i.e., over all of the (state,letter) # pairs) -- you'll have to write "edges[edge]" to get the destination list. def nfsmaccepts(current, edges, accepting, visited): # write your code here # visited? if current in visited: return None # final state? if current in accepting: return '' visited.append(current) # traverse all the next possible states for key in edges: if key[0] == current: for node in edges[key]: ret = nfsmaccepts(node, edges, accepting, visited) if ret is not None: return key[1] + ret # This problem includes some test cases to help you tell if you are on # the right track. You may want to make your own additional tests as well. print "Test 1: " + str(nfsmaccepts(1, edges, accepting, []) == "abc") print "Test 2: " + str(nfsmaccepts(1, edges, [4], []) == "ab") print "Test 3: " + str(nfsmaccepts(1, edges2, accepting2, []) == None) print "Test 4: " + str(nfsmaccepts(1, edges2, [1], []) == "")