Martin

John C. Martin · Fourth edition

Nondeterministic Finite Automata

The goal in the rest this chapter is to prove that regular languages, defined in Section 3.1, are precisely the languages accepted by finite automata. In order to do this, we will introduce a more general “device,” a nondeterministic finite automaton. The advantage of this approach is that it’s much easier to start with an arbitrary regular expression and draw a transition diagram for something that accepts the corresponding language and has an obvious connection to the regular expression. The only problem is that the something might not be a finite automaton, although it has a superficial resemblance to one, and we have to figure out how to interpret it in order to think of it as a physical device at all.

Example 3.6Accepting the Language {aa,aab}∗{b}\{aa,aab\}^*\{b\}

There is a close resemblance between the diagram in Figure 3.7 and the regular expression (aa+aab)∗b(aa+aab)^*b. The top loop corresponds to aaaa, the bottom one corresponds to aabaab, and the remaining bb-transition corresponds to the last bb in the regular expression. To the extent that we think of it as a transition diagram like that of an FA, its resemblance to the regular expression suggests that the string aaaabaabaaaabaab, for example, should be accepted, because it allows us to start at q0q_0, take the top loop once, the bottom loop once, the top loop again, and finish up with the transition to the accepting state.

This diagram, however, is not the transition diagram for an FA, because there are three transitions from q0q_0 and fewer than two from several other states. The input string aaaabaabaaaabaab allows us to reach the accepting state, but it also allows us to follow, or at least start to follow, other paths that don’t result in acceptance. We can imagine an idealized “device” that would work by using the input symbols to follow paths shown in the diagram, making arbitrary choices at certain points. It has to be nondeterministic, in the sense that the path it follows is not determined by the input string. (If the first input symbol is aa, it chooses whether to start up the top path or down the bottom one.) Even if there were a way to build a physical device that acted like this, it wouldn’t accept this language in the same way that an FA could. Suppose we watched it process a string xx. If it ended up in the accepting state at the end, we could say that xx was in the language; if it didn’t, all we could say for sure is that the moves it chose to make did not lead to the accepting state.

Figure 3.7

Using nondeterminism to accept {aa,aab}∗{b}\{aa,aab\}^*\{b\}.

Allowing nondeterminism, by relaxing the rules for an FA, makes it easy to draw diagrams corresponding to regular expressions. However, we should no longer think of the diagram as representing an explicit algorithm for accepting the language, because an algorithm refers to a sequence of steps that are determined by the input and would be the same no matter how many times the algorithm was executed on the same input.

If the diagram doesn’t represent an explicit accepting algorithm, what good is it? One way to answer this is to think of the diagram as describing a number of different sequences of steps that might be followed. We can visualize these sequences for the input string aaaabaabaaaabaab by drawing a computation tree, pictured in Figure 3.8.

A level of the tree corresponds to the input (the prefix of the entire input string) read so far, and the states appearing on this level are those in which the device could be, depending on the choices it has made so far. Two paths in the tree, such as the one that starts by treating the initial aa as the first symbol of aabaab, terminate prematurely, because the next input symbol does not allow a move from the current state. One path, which corresponds to interpreting the input string as (aa)(aab)(aab)(aa)(aab)(aab), allows all the input to be read and ends up in a nonaccepting state. The path in which the device makes the “correct” choice at each step ends up at the accepting state when all the input symbols have been read.

Open simulator
Figure 3.8

The computation tree for Figure 3.7 and the input string aaaabaabaaaabaab.

Transcription note

The printed tree labels its final nonaccepting leaf q1q_1; following Figure 3.7 gives q0q_0. The live tree and simulator follow the transition diagram.

If we had the transition diagram in Figure 3.7 and were trying to use it to accept the language, we could systematically keep track of the current sequence of steps, and use a backtracking strategy whenever we couldn’t proceed any further or finished in a nonaccepting state. The result would, in effect, be to search the computation tree using a depth-first search. In the next section we will see how to develop an ordinary finite automaton that effectively executes a breadth-first search of the tree, by keeping track after each input symbol of all the possible states the various sequences of steps could have led us to.

Example 3.9Accepting the Language {aab}∗{a,aba}∗\{aab\}^*\{a,aba\}^*

In this example we consider the regular expression (aab)∗(a+aba)∗(aab)^*(a+aba)^*. The techniques of Example 3.6 don’t provide a simple way to draw a transition diagram related to the regular expression, but Figure 3.10 illustrates another type of nondeterminism that does.

The new feature is a “Λ\Lambda-transition,” which allows the device to change state with no input. If the input aa is received in state 0, there are three options: take the transition from state 0 corresponding to the aa in aabaab; move to state 3 and take the transition corresponding to aa; and move to state 3 and take the transition corresponding to the aa in abaaba. The diagram shows two aa-transitions from state 3, but because of the Λ\Lambda-transition, we would have a choice of moves even if there were only one.

Figure 3.11 shows a computation tree illustrating the possible sequences of moves for the input string aababaaababa. The Λ\Lambda-transition is drawn as a horizontal arrow, so that as in the previous example, a new level of the tree corresponds to a new input symbol.

Figure 3.10

Using nondeterminism to accept {aab}∗{a,aba}∗\{aab\}^*\{a,aba\}^*.

Open simulator
Figure 3.11

The computation tree for Figure 3.10 and the input string aababaaababa.

The string is accepted, because the device can choose to take the first loop, execute the Λ\Lambda-transition, and take the longer loop from state 3.

The transition diagrams in our first two examples show four of the five ingredients of an ordinary finite automaton. The one that must be handled differently is the transition function δ\delta. For a state qq and an alphabet symbol σ\sigma, it is no longer correct to say that δ(q,σ)\delta(q,\sigma) is a state: There may be no transitions from state qq on input σ\sigma, or one, or more than one. There may also be Λ\Lambda-transitions. We can incorporate both of these features by making two changes: first, enlarging the domain of δ\delta to include ordered pairs (q,Λ)(q,\Lambda) as well as the pairs in Q×ΣQ\times\Sigma; and second, making the values of δ\delta sets of states instead of individual states.

Definition 3.12A Nondeterministic Finite Automaton

A nondeterministic finite automaton (NFA) is a 5-tuple (Q,Σ,q0,A,δ)(Q,\Sigma,q_0,A,\delta), where

  • QQ is a finite set of states;
  • Σ\Sigma is a finite input alphabet;
  • q0∈Qq_0\in Q is the initial state;
  • A⊆QA\subseteq Q is the set of accepting states;
  • δ:Q×(Σ∪{Λ})→2Q\delta:Q\times(\Sigma\cup\{\Lambda\})\to2^Q is the transition function.

For every element qq of QQ and every element σ\sigma of Σ∪{Λ}\Sigma\cup\{\Lambda\}, we interpret δ(q,σ)\delta(q,\sigma) as the set of states to which the FA can move, if it is in state qq and receives the input σ\sigma, or, if σ=Λ\sigma=\Lambda, the set of states other than qq to which the NFA can move from state qq without receiving any input symbol.

In Example 3.9, for example, δ(0,a)={1}\delta(0,a)=\{1\}, δ(0,Λ)={3}\delta(0,\Lambda)=\{3\}, δ(0,b)=∅\delta(0,b)=\varnothing, and δ(0,a)={3,4}\delta(0,a)=\{3,4\}.

Transcription note

The final expression is printed as δ(0,a)={3,4}\delta(0,a)=\{3,4\}. Figure 3.10 gives δ(3,a)={3,4}\delta(3,a)=\{3,4\}. The union below uses the printed aa; its general form uses σ\sigma.

In the case of an NFA M=(Q,Σ,q0,A,δ)M=(Q,\Sigma,q_0,A,\delta), we want δ∗(q,x)\delta^*(q,x) to tell us all the states MM can get to by starting at qq and using the symbols in the string xx. We can still define the function δ∗\delta^* recursively, but the mathematical notation required to express this precisely is a little more involved, particularly if MM has Λ\Lambda-transitions.

In order to define δ∗(q,xσ)\delta^*(q,x\sigma), where x∈Σ∗x\in\Sigma^* and σ∈Σ\sigma\in\Sigma, we start by considering δ∗(q,x)\delta^*(q,x), just as in the simple case of an ordinary FA. This is now a set of states, and for each state pp in this set, δ(p,σ)\delta(p,\sigma) is itself a set. In order to include all the possibilities, we need to consider

⋃{δ(p,a)∣p∈δ∗(q,x)}\bigcup\{\delta(p,a)\mid p\in\delta^*(q,x)\}

Finally, we must keep in mind that in the case of Λ\Lambda-transitions, “using all the symbols in the string xx” really means using all the symbols in xx and perhaps Λ\Lambda-transitions where they are possible. In the recursive step of the definition of δ∗\delta^*, once we have the union we have just described, we must consider all the additional states we might be able to reach from elements of this union, using nothing but Λ\Lambda-transitions.

You can probably see at this point how the following definition will be helpful in our discussion.

Definition 3.13The Λ\Lambda-Closure of a Set of States

Suppose M=(Q,Σ,q0,A,δ)M=(Q,\Sigma,q_0,A,\delta) is an NFA, and S⊆QS\subseteq Q is a set of states. The Λ\Lambda-closure of SS is the set Λ(S)\Lambda(S) that can be defined recursively as follows.

  1. S⊆Λ(S)S\subseteq\Lambda(S).
  2. For every q∈Λ(S)q\in\Lambda(S), δ(q,Λ)⊆Λ(S)\delta(q,\Lambda)\subseteq\Lambda(S).

In exactly the same way as in Example 1.21, we can convert the recursive definition of Λ(S)\Lambda(S) into an algorithm for evaluating it, as follows.

AlgorithmTo Calculate Λ(S)\Lambda(S)

Initialize TT to be SS. Make a sequence of passes, in each pass considering every q∈Tq\in T and adding to TT every state in δ(q,Λ)\delta(q,\Lambda) that is not already an element. Stop after the first pass in which TT is not changed. The final value of TT is Λ(S)\Lambda(S). ■\blacksquare

A state is in Λ(S)\Lambda(S) if it is an element of SS or can be reached from an element of SS using one or more Λ\Lambda-transitions.

With the help of Definition 3.13 we can now define the extended transition function δ∗\delta^* for a nondeterministic finite automaton.

Definition 3.14The Extended Transition Function δ∗\delta^* for an NFA, and the Definition of Acceptance

Let M=(Q,Σ,q0,A,δ)M=(Q,\Sigma,q_0,A,\delta) be an NFA. We define the extended transition function

δ∗:Q×Σ∗→2Q\delta^*:Q\times\Sigma^*\to2^Q

as follows:

  1. For every q∈Qq\in Q, δ∗(q,Λ)=Λ({q})\delta^*(q,\Lambda)=\Lambda(\{q\}).
  2. For every q∈Qq\in Q, every y∈Σ∗y\in\Sigma^*, and every σ∈Σ\sigma\in\Sigma,
δ∗(q,yσ)=Λ(⋃{δ(p,σ)∣p∈δ∗(q,y)})\delta^*(q,y\sigma)=\Lambda\left(\bigcup\{\delta(p,\sigma)\mid p\in\delta^*(q,y)\}\right)

A string x∈Σ∗x\in\Sigma^* is accepted by MM if δ∗(q0,x)∩A≠∅\delta^*(q_0,x)\cap A\ne\varnothing. The language L(M)L(M) accepted by MM is the set of all strings accepted by MM.

For the NFA in Example 3.9, which has only one Λ\Lambda-transition, it is easy to evaluate δ∗(aababa)\delta^*(aababa) by looking at the computation tree in Figure 3.11. The two states on the first level of the diagram are 0 and 3, the elements of the Λ\Lambda-closure of {0}\{0\}. The states on the third level, for example, are 2, 3, and 4, because δ∗(0,aa)={2,3,4}\delta^*(0,aa)=\{2,3,4\}. When we apply the recursive part of the definition to evaluate δ∗(0,aab)\delta^*(0,aab), we first evaluate

⋃{δ(p,b)∣p∈{2,3,4}}=δ(2,b)∪δ(3,b)∪δ(4,b)={0}∪∅∪{5}={0,5}\begin{aligned}\bigcup\{\delta(p,b)\mid p\in\{2,3,4\}\}&=\delta(2,b)\cup\delta(3,b)\cup\delta(4,b)\\&=\{0\}\cup\varnothing\cup\{5\}\\&=\{0,5\}\end{aligned}

and then we compute the Λ\Lambda-closure of this set, which contains the additional element 3.

For an NFA MM with no Λ\Lambda-transitions, both statements in the definition can be simplified, because for every subset SS of QQ, Λ(S)=S\Lambda(S)=S.

We illustrate the definition once more in a slightly more extended example.

Example 3.15Applying the Definitions of Λ(S)\Lambda(S) and δ∗\delta^*

We start by evaluating the Λ\Lambda-closure of the set {v}\{v\} in the NFA whose transition diagram is shown in Figure 3.16. When we apply the algorithm derived from Definition 3.13, after one pass TT is {v,w}\{v,w\}, after two passes it is {v,w,q0}\{v,w,q_0\}, after three passes it is {v,w,q0,p,t}\{v,w,q_0,p,t\}, and during the next pass it remains unchanged. The set Λ({s})\Lambda(\{s\}) is therefore {v,w,q0,p,t}\{v,w,q_0,p,t\}.

Figure 3.16

Evaluating the extended transition function when there are Λ\Lambda-transitions.

Transcription note

The preceding paragraph prints Λ({s})\Lambda(\{s\}) after starting with {v}\{v\}. The calculated set is Λ({v})={v,w,q0,p,t}\Lambda(\{v\})=\{v,w,q_0,p,t\}. The simulator follows Figure 3.16.

If we want to apply the definition of δ∗\delta^* to evaluate δ∗(q0,aba)\delta^*(q_0,aba), the easiest way is to begin with Λ\Lambda, the shortest prefix of abaaba, and work our way up one symbol at a time.

δ∗(q0,Λ)=Λ({q0})={q0,p,t}\begin{aligned}\delta^*(q_0,\Lambda)&=\Lambda(\{q_0\})\\&=\{q_0,p,t\}\end{aligned}
δ∗(q0,a)=Λ(⋃{δ(k,a)∣k∈δ∗(q0,Λ)})=Λ(δ(q0,a)∪δ(p,a)∪δ(t,a))=Λ(∅∪{p}∪{u})=Λ({p,u})={p,u}\begin{aligned}\delta^*(q_0,a)&=\Lambda\left(\bigcup\{\delta(k,a)\mid k\in\delta^*(q_0,\Lambda)\}\right)\\&=\Lambda(\delta(q_0,a)\cup\delta(p,a)\cup\delta(t,a))\\&=\Lambda(\varnothing\cup\{p\}\cup\{u\})\\&=\Lambda(\{p,u\})\\&=\{p,u\}\end{aligned}
δ∗(q0,ab)=Λ(⋃{δ(k,b)∣k∈{p,u}})=Λ(δ(p,b)∪δ(u,b))=Λ({r,v})={r,v,w,q0,p,t}\begin{aligned}\delta^*(q_0,ab)&=\Lambda\left(\bigcup\{\delta(k,b)\mid k\in\{p,u\}\}\right)\\&=\Lambda(\delta(p,b)\cup\delta(u,b))\\&=\Lambda(\{r,v\})\\&=\{r,v,w,q_0,p,t\}\end{aligned}
δ∗(q0,aba)=Λ(⋃{δ(k,a)∣k∈{r,v,w,q0,p,t}})=Λ(δ(r,a)∪δ(v,a)∪δ(w,a)∪δ(q0,a)∪δ(p,a)∪δ(t,a))=Λ({s}∪{v}∪∅∪∅∪{p}∪{u})=Λ({s,v,p,u})={s,v,p,u,w,q0,t}\begin{aligned}\delta^*(q_0,aba)&=\Lambda\left(\bigcup\{\delta(k,a)\mid k\in\{r,v,w,q_0,p,t\}\}\right)\\&=\Lambda(\delta(r,a)\cup\delta(v,a)\cup\delta(w,a)\cup\delta(q_0,a)\cup\delta(p,a)\cup\delta(t,a))\\&=\Lambda(\{s\}\cup\{v\}\cup\varnothing\cup\varnothing\cup\{p\}\cup\{u\})\\&=\Lambda(\{s,v,p,u\})\\&=\{s,v,p,u,w,q_0,t\}\end{aligned}

The evaluation of Λ({r,v})\Lambda(\{r,v\}) is very similar to that of Λ({v})\Lambda(\{v\}), since there are no Λ\Lambda-transitions from rr, and the evaluation of Λ({s,v,p,u})\Lambda(\{s,v,p,u\}) is also similar. Because δ∗(q0,aba)\delta^*(q_0,aba) contains the accepting state ww, the string abaaba is accepted.

A state rr is an element of δ∗(q,x)\delta^*(q,x) if in the transition diagram there is a path from qq to rr, in which there are transitions for every symbol in xx and the next transition at each step corresponds either to the next symbol in xx or to Λ\Lambda. In simple examples, including this one, you may feel that it’s easier to evaluate δ∗\delta^* by looking at the diagram and determining by inspection what states you can get to. One reason for having a precise recursive definition of δ∗\delta^* and a systematic algorithm for evaluating it is that otherwise it’s easy to overlook things.