More user feedback on Sets.py
David Eppstein
eppstein at ics.uci.edu
Mon Nov 10 02:29:29 EST 2003
In article <Rxlrb.6067$hB5.3380 at nwrdny02.gnilink.net>,
"Raymond Hettinger" <vze4rx4y at verizon.net> wrote:
> > For something concrete (that I thought about doing recently but haven't
> > actually done): conversion of NFA to DFA and then state minimization of
> > the resulting DFA. The converted DFA's states are sets of states of the
> > NFA, and the state minimization involves sets of DFA states.
>
> That would be a perfect way to test drive the sets module.
Here is the first half of this. I didn't do the state minimization
part. (For the example shown here, the output is already minimal.)
"""automata.py
Convert nondeterministic to deterministic finite automata.
D. Eppstein, UC Irvine, November 2003.
"""
from __future__ import generators
from sets import ImmutableSet,Set
if 'True' not in globals():
globals()['True'] = not None
globals()['False'] = not True
class InputError(Exception): pass
class DFA:
def __init__(self,Sigma,delta,S0,F):
"""Create deterministic finite automaton with alphabet Sigma,
transition function delta(state,letter)->state, initial state
S0, and predicate F(state)->boolean. The full sets of states and
final states are determined implicitly from the delta and F
functions.
"""
self.alphabet = ImmutableSet(Sigma)
self.transition = delta
self.initialState = S0
self.isfinal = F
def states(self):
"""Generate all states of the DFA."""
explored = Set()
unexplored = Set([self.initialState])
while unexplored:
s = unexplored.pop()
explored.add(s)
yield s
for c in self.alphabet:
t = self.transition(s,c)
if t not in explored:
unexplored.add(t)
def __call__(self,input):
"""Test whether input is accepted by the DFA."""
state = self.initialState
for c in input:
if c not in self.alphabet:
raise InputError("Symbol " + repr(c) +
" not in input alphabet")
state = self.transition(state,c)
return self.isfinal(state)
class NFA:
def __init__(self,Sigma,delta,S0,F):
"""Create nondeterministic finite automaton (without
epsilon-transitions). Arguments are the same as for a
deterministic finite automaton, except that the initial state
and result of the transition function are both sets.
"""
self.alphabet = ImmutableSet(Sigma)
self.transition = delta
self.initialStates = ImmutableSet(S0)
self.isfinal = F
def setTransition(self,states,c):
"""States reachable from input set by input c."""
result = Set()
for s in states:
result |= self.transition(s,c)
return ImmutableSet(result)
def finalSet(self,states):
"""Test whether any of given set of states is final."""
for s in states:
if self.isfinal(s):
return True
return False
def makeDeterministic(self):
"""Convert NFA to DFA."""
return DFA(self.alphabet,self.setTransition,
self.initialStates,self.finalSet)
def __call__(self,input):
"""Test whether input is accepted by the NFA."""
return self.makeDeterministic()(input)
# Example from Sipser, _Introduction to the Theory of Computation_
# (Preliminary Edition), Example 1.13, pages 47-48
if __name__ == "__main__":
# state:(states for transition on 0, states for transition on 1)
Sipser_1_13 = {
1: ([1], [1,2]),
2: ([3], [3]),
3: ([4], [4]),
4: ([], []),
}
def delta(s,i): return ImmutableSet(Sipser_1_13[s][int(i)])
def final(s): return s == 4
N2 = NFA("01",delta,[1],final)
def test(input):
print input,(N2(input) and "is" or "is not"),"in L(N2)"
test("000100")
test("0011")
print
print "Conversion to DFA:"
print
D2 = N2.makeDeterministic()
for s in D2.states():
print s
for c in "01":
print " --[" + c + "]-->", D2.transition(s,c)
--
David Eppstein http://www.ics.uci.edu/~eppstein/
Univ. of California, Irvine, School of Information & Computer Science
More information about the Python-list
mailing list