Lecture 16: More on Finite State Machines

Summary from last lecture


Alright... onto the new stuff.

The underlying topic for today is to discuss NFAs with more depth and compare/contrast them to DFAs. In other words, we'll see a striking equivalence of the two which will help us understand the regular languages with more depth (since we'll now have two different perspectives for looking at the same thing and adding another perspective is always useful).

Subset construction

Note that subset construction is also referred to as the powerset construction.

At brief high-level, I think the Wikipedia page for "Powerset construction" gives a nice definition:

Subset Construction:
The powerset construction or subset construction is a standard method for converting a nondeterministic finite automaton into a deterministic finite automaton which recognizes the same formal language.

Recall the tabular form of a DFA. From there, we can represent that table (also possible in software if you'd like) as we saw last lecture. We can perform a similar process with an NFA to form a table. From there on, we can also represent it through software and since we can form the table (see below) in the first place, we can represent the NFA as a DFA.

The key here is that we can assign "subsets" as states instead of just original singular states. See the conversion below.

First, we have our NFA:

Now we represent it via table:

And from this, we form our DFA:

(Note: see "Guide to Subset Construction" for more implementation details).

Philosophies of subset constructions

It is indeed the case that whatever you can do with an NFA, you can also do with a DFA. But as one might imagine, the amount of states and transitions in the DFA version of some NFA could be exponentially larger.

This fact helps use give clarity to the notion that one might suggest at this point: "Why would we build NFAs instead of DFAs if they both can represent the same language?". As stated above, they can be much more compact.

Moreover, certain things which we'll see later, are easier to worth with DFAs than NFAs and vise versa. See 37:00 from lecture for a good example.

An important result on regular languages

Recall from last lecture where we showed "A language LL is called a regular language if there exists a DFA DD such that L(D)=L\mathscr{L}(D)=L.". Since we just stated that NFAs are functionally the same as DFAs, we also can extrapolate the above theorem to this:

A language LL is called a regular language if there exists a NFA NN such that L(N)=L\mathscr{L}(N)=L.

So a regular language can now be thought of a language as an NFA or also a DFA. And to answer the philosophical question posed above, such a result means that we can work with NFAs instead (and vise versa) for certain problems which could lead to a new discovery/a new way of looking at things.


Properties of Regular Languages

Let us now discuss and probe some more properties about regular languages (RLs). We will toy around with some set theory operations by framing them as propositional logic connectives with languages as statements.

If L1L_1 and L2L_2 are regular languages, is L1L2L_1 \cup L_2?

Yes... just make an NFA with two ϵ\epsilon-transitions like so:

This is like the "or" case (existential).

If L1L_1 and L2L_2 are regular languages, is L1L2L_1 \cap L_2 as well?

This is like the "and" case and is also much harder to show than the "or" case. Let us try to see if this is true.

This is pretty interesting actually. We can indeed get the "and" case by applying De Morgan's Law to set theory. We can form "and" in propositional logic using just ~ and or via: ~(~p or ~q) which, in this context using languages and compliments, we get: L1orL2\overline{\overline{L_1} or \overline{L_2}}

You might imagine that constructing some machine for this would be a multi-step process (e.g. lots of DFA-NFA, NFA-DFA conversions).

Concatenation

Works the same as you've seen in programming languages. If you have ww and ee, the concatenated version is notated as wewe.

Note, some interesting properties which could be useful during manipulations:

We can also perform concatenations over languages instead of just strings. Formally, we define concatenation over two languagesL1L_1 and L2L_2 as:

Concatenation:
L1L2={wXΣwL1xL2} \mathbb{L}_{1} \mathbb{L}_{2}=\left\{w_{X} \in \Sigma^{*} \mid w \in L_{1} \wedge x \in L_{2}\right\}

This is, in some ways, like the cartesian product of two languages where L1L2L_{1}L_{2} is "the set of all strings that can be made by concatenating string in L1L_{1} with a string in L2L_{2}.".
You can also think of it as "The set of strings that can be split into two pieces: a piece from L1L_{1} and a piece from L2L_{2}.". See 53:00 for more about the "splitting" intuition and an example use case. Briefly speaking, concatenating two automaton is like having each individual one complete some task, then the other would complete another task, then combine them together into one. We combine them by saying "do this, then do this".

Concatenating together two machines

Definitively, we can define a series of steps for concatenating together two machines:

  1. Take the accepting states of machine 1, and draw ϵ\epsilon-transitions to the start state of machine 2.
  2. Flip the accepting states in machine 1 to rejecting states.

Language exponentitian

We talked about how concatenation is almost like a "product". So consider some language LL. We perform the concatenation of LL with LL to get LLLL. We can do it again to get LLLLLL. And again: LLLLLLLL. Looks a little like exponentials in some sense right?

We have the following characteristics:

L0={ε} L^{0}=\{\varepsilon\}

and, inductively:

Ln+1=LLn L^{n+1}=L L^{n}


The Kleene Star

We now introduce one more operation which is somewhat nuanced, but useful nonetheless:

Kleene Closure:
L={wΣnN,wLn} L^{*}=\left\{w \in \Sigma^{*} \mid \exists n \in \mathbb{N}, w \in L^{n}\right\}
which is mathematically equivalent to:

wLnN.wLn w \in L^{*} \quad \leftrightarrow \quad \exists n \in \mathbb{N} . w \in L^{n}

See 1:08 for a more detailed explanation. Briefly speaking, recall Σ\Sigma^{*}. This is applying the same notion to languages (operating on strings instead of languages internally) via the notation LL^{*}.

Closure properties

Remember how we defined closure properties in the previous lecture. Notice that we just examined a bunch of closure properties here.

If L1L_{1} and L2L_{2} are regular languages over an alphabet Σ\Sigma, then so are the following languages: