1-3. Designing DFAs

Designing DFAs

So far we have discussed how to determine the language of a DFA:

We want to also perform the reverse, given a language , design a DFA such that the language of is .

Example Task 1

Design a DFA such that consists of all the strings of s and s ending with .

  1. Determine what to remember about the input string, while the head is reading through it, from left to right.
  2. Add the transitions telling how the possibilities rearrange, and select the initial state and the favourable states.
  3. Test the automaton.

It is sufficient to remember three ‘states’ of the string read so far:

  • The string does not end in . (it is either or ends in ) initial state (waiting for )
  • String is or ends in . (waiting for )
  • String ends in . favourable state
digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; p;
	node[shape=circle];
	init->s
	
	s->s [label=0]
	s->q [label=1]
	q->s [label=0]
	q->p [label=1]
	p->s [label=0]
	p->p [label=1]
}

Example Task 2

Design a DFA such that consists of all the strings of and whose length is divisible by . Consider that:

digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; s;
	node[shape=circle];
	init->s
	
	s->s [label="0,3,6,9"]
	p->p [label="0,3,6,9"]
	q->q [label="0,3,6,9"]
	s->p [label="1,4,7"]
	p->q [label="1,4,7"]
	q->s [label="1,4,7"]
	p->s [label="2,5,8"]
	p->q [label="2,5,8"]
	q->s [label="2,5,8"]
}

Pattern Matching

Design a DFA such that consists of all the strings of s and s that contain as a substring.

digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; aab;
	node[shape=circle];
	init->s
	
	s->s [label=b]
	s->a [label=a]
	a->s [label=b]
	
	a->aa [label=a]
	
	aa->aa [label=a]
	aa->aab [label=b]
	
	aab->aab [label=a]
	aab->aab [label=b]
}
Link to original

4. Nondeterminism

DFA as a theoretical model for programming

unusual / visual, different from conventional programming languages major concepts of imperative programming (e.g. sequences, branching, loops) can be simulated elegant, simple to use (visual), has a developed theory all pattern matching can be described limited expressive power (constant amount of memory)

Combining two automata

High-level languages typically implement things such as method calling and modularity, in this section we try to determine if we can do the same with finite automata.

Design an automaton such that consits of all the strings of s and s that have either two consecutive s or two consecutive s.

Since we already have the ‘methods’ to solve the problem for s and s, we could design a ‘main program’ that would just call the given methods. One possible solution would be to combine the initial states.

Automaton such that

digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; r1, r2;
	node[shape=circle];
	init->s
	
	s->s [label=a]
	s->s [label=b]
	
	s->q2 [label=b]
	q2->s [label=a]
	q2->r2 [label=b]
	r2->r2 [label=a]
	r2->r2 [label=b]
	
	s->q1 [label=a]
	q1->s [label=b]
	q1->r1 [label=a]
	r1->r1 [label=b]
	r1->r1 [label=a]
}

Observe that the state transition diagram on the previous slide no longer represents a DFA:

  • there is more than one -arrow leaving state
  • there is more than one -arrow leaving state

We say that this automaton is nondeterministic, this is because given a state and reading from the input tape, the device has a choice to either move to state or . In order words, the next state is not determined by the previous state and the symbol read.

Link to original

5. NFAs transition table, acceptance

Nondeterminism

Apart from having a choice in certain situations, there are other permitted features in nondeterministic finite automata (NFA):

  • There can be states and symbols such that no arrow labelled by that symbol leaves thes tate in question: reading that symbol in the state the device would get stuck.
  • We also allow the machine to jump from a state to another state, without ‘consuming’ any input symbol from the tape (the head doesn’t move). The allowed ‘state-jumps’ will be indicated on the state transition digrams by arrows labelled by the empty word .
digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; s;
	node[shape=circle];
	init->s
	
	s->q [label=ε]
	q->s [label=a]
	
	s->r [label=b]
	r->r [label=a]
	
	r->q [label=a]
	r->q [label=b]
}

NFA Transition Table

From the NFA described above, we know that the states are , the input alphabet is , the initial state is and the favourable state is . We find the table:

This table has a few notable features:

  • There can be ‘cells’ in the table containing no or more than one states.
  • The table has an -column (for any jumps).

An NFA can be regarded as a DFA if all cells in the -column are empty, and in vevery other column every cell contains a single state.

Acceptance of words by NFAs

In an NFA, there can be more than one computation on an input word. Some of these may end up in a favourable state, some may not.

A word is accepted by NFA if there is a computation of on input that ends up in some favourable state.

title: There may be other bad computations.
title: Getting stuck in a favourable state may not mean acceptance. The entire word needs to be read.

In any other case, rejects the input word. So an NFA can reject an input word if every computation on is either ‘stuck’ or ends up in a non-favourable state.

Link to original

6. NFA Example 1

NFA Example 1

Given the following NFA:

digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; s;
	node[shape=circle];
	init->s
	
	s->q [label=ε]
	q->s [label=a]
	r->q [label=a]
	r->q [label=b]
	r->r [label=a]
	s->r [label=b]
}
Link to original

7. NFA Example 2

NFA Example 2

Given the following transition table:

Produces the NFA:

digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; q;
	node[shape=circle];
	init->s
	
	s->s [label=0]
	s->p [label=0]
	s->q [label=1]
	s->p [label=ε]
	q->p [label=0]
	p->q [label=1]
}
Link to original

8. Designing NFAs

Designing NFAs

Nondeterminism can be viewed as a sort of parallel computing model, within which several processes can be running concurrently.

NDAs are much easier to design than DFAs, whatever can be done by an NDA can also be done (in a more complicated way) in a DFA. Nondeterminism does not increase computation power of finite automata.

NFAs are used in hardware / chip design:

  • Given a task, NFA is designed.
  • NFA is turned into a DFA.
  • Resulting DFA is ‘minimised’.
  • Obtained minimal DFA is hard-wired.

Pattern Matching

Revisiting 1-3. Designing DFAs > Pattern Matching.

Design a finite automaton such that consists of all the strings of s and s that contain as a substring.

digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; z;
	node[shape=circle];
	init->u
	
	u->u [label=a]
	u->u [label=b]
	u->x [label=a]
	x->y [label=a]
	y->z [label=b]
	z->z [label=a]
	z->z [label=b]
}

Given the same task, it is much easier to design an NFA than a DFA for it:

  • we don’t have to worry about all computations
  • we need to ensure that if a word is accepted, then there is at least one ‘good’ computation for it
  • if a word should be rejected, there is no ‘good’ computation for it
Link to original

9. The subset construction

Subset Construction

The Subset Construction is an algorithm that carries out a conversion from a nondeterministic automaton to its deterministic equivalent.

Equivalence of DFAs and NFAs

Given two automata and that accept the same language are said to be equivalent. For every NFA , there is a DFA equivalent to .

Converting NFA to DFA

Given an NFA as follows, turn it into an equivalent DFA.

digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; s;
	node[shape=circle];
	init->s
	
	s->r [label=b]
	s->q [label=ε]
	q->s [label=a]
	r->q [label=a]
	r->q [label=b]
	r->r [label=a]
}

In a DFA, we are not allowed multiple choices, being stuck or to use -jumps. We need to define:

  • new states: named after subsets of the original NFA’s states
  • new initial state: the set containing the original NFA’s initial state, plus all states that are reachable from it by some -jumps
  • new favourable states: those subsets that contain at least one of the original NFA’s favourable states
digraph {
	init[shape=point]
	node[shape=doublecircle]; s, sq, sr, sqr;
	node[shape=circle];
	init->sq
	
	s   [label="{s}"]
	sq  [label="{s,q}"]
	sr  [label="{s,r}"]
	sqr [label="{s,q,r}"]
	
	0  [label="{}"]
	r  [label="{r}"]
	q  [label="{q}"]
	qr [label="{q,r}"]
}

The new states are named after subsets of the old states:

digraph {
	label="for each symbol x in the input alphabet"
	rankdir=LR
	P->a
	a[label="?"]
}

Where is the set of all those states that are reachable from some state in the set , either by a -arrow or by an -arrow followed by possibly one or more -jumps (but not -jump then -arrow).

In a DFA every state must have one -arrow out and one -arrow out. We being with the initial state an compute where two arrows go from it:

We look at the NFA again to find that:

  • from we cannot reach anything by an -arrow
  • from we can reach by an -arrow
  • from we can reach by an -arrow followed by an -jump

Hence the -arrow from state goes to state itself.

  • from we can reach by a -arrow
  • from we cannot reach anything by a -arrow

The -arrow from state goes to state .

Next, for every obtained new state, we compute where the -arrow and the -arrow goes from it. We do this until there are no newly obtained states.

Final DFA
digraph {
	rankdir=LR
	init[shape=point]
	node[shape=doublecircle]; sq, sqr;
	node[shape=circle];
	init->sq
	
	sq  [label="{s,q}"]
	sqr [label="{s,q,r}"]
	
	0  [label="{}"]
	r  [label="{r}"]
	q  [label="{q}"]
	qr [label="{q,r}"]
	
	sq->sq   [label=a]
	sq->r    [label=b]
	r->qr    [label=a]
	r->q     [label=b]
	qr->sqr  [label=a]
	qr->q    [label=b]
	q->sq    [label=a]
    q->0     [label=b]
	sqr->sqr [label=a]
	sqr->qr  [label=b]
	0->0     [label=a]
	0->0     [label=b]
}
Link to original

10. State minimisation

State minimisation

An important field where finite automata are being used is in hardware design, some components of hardware (chips) are based on simulating DFAs.

  • Given a task, an NFA is designed, since it is easier to design than a DFA.
  • This NFA is turned into a DFA doing the same thing (using subset construction). The number of states of the resulting DFA may increase significantly. The worst case scenario is .
  • The resulting DFA is ‘minimised’, to obtain a DFA that has the minimum possible number of states for the given task.
    title: There are various ways to do this, see recommended literature.
  • Finally, obtained DFA is hard-wired.
Link to original