I’ll print and bring worksheets to class, but if you lose one or want to have it in electronic format from some reason, you can get it here as well.
We will often work in groups. Periodically we will shuffle things up so you get to work with new people.
date | Topic | link(s) |
---|---|---|
Mon 1/31 | Some Counting Problems | |
Wed 2/02 | Pigeon Hole Principle | |
Fri 2/04 | Division Principle | |
Mon 2/07 | Donuts | |
Fri 2/11 | Probability | |
Mon 2/11 | Probability (cont’d) | |
Wed 2/16 | Conditional Probability 1 | |
Fri 2/18 | Conditional Probability 2 | |
Mon 2/21 | Random Variables | |
Wed 2/23 | Expected Value | |
Fri 2/25 | More Expected Value | |
Mon 3/7 | Probability Wrap-Up |
We will often work in groups. Periodically we will shuffle things up so you get to work with new people.
Choose your own groups!
date | Topic | link(s) |
---|---|---|
Wed 3/9 | Grammars | |
Fri 3/11 | Types of Grammars | |
Wed 3/16 | Automata | |
Fri 3/18 | Automata | |
Fri 3/18 | Nondeterministic Automata | |
Fri 3/25 | DFA vs NFA | |
Fri 3/25 | Regular Expressions and Languages | |
Mon 3/28 | Regular Expression -> NFA | |
Wed 3/30 | Regular Grammars and Automata | |
04/04 | DFA to regex | PDF, notes |
04/06 | Turing Machines | PDF, simulator |
04/11 | A language that is not regular | |
05/07 | Regular expressions in python | slides |
Note: You don’t have to turn in any homework for Python regular expressions, but you should work through some of these games and tutorials to hone your skills. This topic will be included on the final exam.
No homework for today’s topic. Instead I have some online regular expression games for you to play. (See above.)
For each grammar, look at each rule to see if it follows the restrictions of each type of grammar.
Example: \(G_1\)
Example: You can’t have \(A \to \lambda\) and \(A\) on the right side of rules in a context sensitive grammar. So you will need to remove one or the other to make this type 1. (There are other things that need doing as well.)
There is one case where the answer is no. Can you find it?
Despite the answer to Exercise 2, this is true. Do you see how to get around the issue in Exercise 2 when we talk about languages rather than grammars?
Using \(S\) as the start nonterminal and \(a\) and \(b\) as a terminals, the following grammar is type 2 but not type 1 (because we aren’t allowed to have \(S\) on the right side of a rule if we also have \(S\to\lambda\)):
But the language generated by the grammar is a type 1 language because we can use a different grammar to generate it:
Basically we just translate \(S\) to \(A\). This avoids the problem of having \(S\) on the right side of a production rule. This same trick can be applied to any type 2 grammar.
More generally, to tell whether a grammar is of a certian type, we just need to check the rules. But to tell whether a language is of a certain type, we need to ask whether there is any grammar of the appropriate type that can generate it.
Note: This language is actually also regular. Here is a regular grammar that generates the same language.
Answer: There is no place for context in the notation. The left side is always just a single non-terminal.
Example: Grammar 2
<S> ::= a<A> | b
<A> ::= aa
Here are example machines for a few of these. Note: I strongly advise using meaningful state names.
I’m doing these with “ASCII art”, so I won’t always include all of the transitions. Be sure to read the description that goes along. You might want to draw out the full machine for yourself.
The set of bitstrings that begin with two 0’s
Keep track of what has been seen so far. Here’s the core of the DFA:
-> [ ] -- 0 --> [ 0 ] -- 0 --> [[ 00 ]]
Now add:
The only way to get to the accepting state is to have the first two symbols be 0.
The set of bitstrings that contain exactly two 0’s
The core of this is similar to part a, but now we don’t need to have the 0’s consecutively, and we are not allowed to hae extra 0’s. Again, start with this:
-> [ no zeros ] -- 0 --> [ one 0 ] -- 0 --> [[ two 0s ]] -- 0 --> [more]
Now add some more transitions:
[more]
state, loop.The set of bitstrings that contain at least two 0’s
The only change to the previous machine is that if we ever get to [[ two 0’s]], then we stay there (loop on both 0 and 1). So we can delete the [more]
state.
-> [ no zeros ] -- 0 --> [ one 0 ] -- 0 --> [[ two 0s ]] -- 0 --> [more]
The set of bitstrings that contain two consecutive 0’s (anywhere in the string)
Again, very similar. But now, whenever we see a 1 before we see two consecutive 0’s, we “start over”. Once we see two consecutive 0’s, we know the string is accepted.
Here’s the core:
-> [ no zeros ] -- 0 --> [ one 0 ] -- 0 --> [[ good! ]]
Now add
[[ good !]]
for both 0 and 1.The set of bitstrings that do not contain two consecutive 0’s anywhere
We need to remember the same information as in the previous example, but we need to flip the result.
Here’s the core:
-> [[ no zeros ]] -- 0 --> [[ one 0 ]] -- 0 --> [ bad! ]
Now add:
[ bad! ]
for both 0 and 1.The set of bitstrings that end with two 0’s
This time, we need to remember the last two bits we have seen. So the core states are 00, 01, 10, and 11. We’ll need to add some states to get started: S, 0, nad 1. These states code what the last 2 bits were. Now see if you can figure out how to add the transitions and determine which states are accepting.
Note: Rosen likes to label his states \(s_0\), \(s_1\), etc. I find that clunky and I suggest that you not bother with subscripts when creating your own machines. You can use numbers, or letters, or even short words or phrases that identify what a state represents. The worksheet will show you both styles.
Hint: Think about the pebbling algorithm. How do the pebbles relate to states in a DFA?
Make sure you give this a good attempt before comparing your work to this solution.
It isn’t important where you put the states, but it is important that the edges and labels match.
In the worst case there is a state in the DFA for every possible set of states in the NFA. If the NFA has \(n\) states, how many subsets of states are there? Hint: to build a subset, you need to decide for each state whether it is in our out of the subset. Now you use your counting rules.
What strings belong to \(\{0, 01\}^2\)? Let’s add a vertical bar to show how the strings are formed. We need to have two pieces, and each piece must be either 0 or 01, so
Which of these strings belong to \(\{0, 01\}^*\)?
Which of these strings belong to \(\{101, 111, 11\}^*\)?
\(1\) is a symbol or a string with one symbol. \(\boldsymbol{1}\) represents a language with one string in it: \(\{1\}\).
\(\lambda\) is the empty string. \(\boldsymbol{\lambda}\) represents a language containing only the empty string: \(\{\lambda\}\).
\(\emptyset\) is the empty set. \(\boldsymbol{\emptyset}\) represents the empty language, but languages are sets, so the empty language is the empty set.
Describe in words the languages represented by each of these regular expressions:
All of the languages in this problem can be recognized by either a DFA or an NFA. Do you see how to design them?
This is will our topic for next time.
Start state: \(S\); Accepting states: \(S\) and \(X\)
state | 0 | 1 |
---|---|---|
\(S\) | \(\{X\}\) | \(\{A\}\) |
\(A\) | \(\{A\}\) | \(\{A\}\) |
\(X\) | \(\{\}\) | \(\{X\}\) |
It’s a good idea to check your work on a few strings to make sure the grammar and the NFA agree. You might try some of these:
Start state: \(S\); Accepting state: \(X\)
state | 0 | 1 |
---|---|---|
\(S\) | \(\{X\}\) | \(\{A\}\) |
\(A\) | \(\{B\}\) | \(\{A, X\}\) |
\(B\) | \(\{A, X\}\) | \(\{B\}\) |
\(X\) | \(\{\}\) | \(\{\}\) |
It’s a good idea to check your work on a few strings to make sure the grammar and the NFA agree. You might try some of these:
Three types of rules \(S\to\lambda\), \(A \to x B\), \(A \to x\) where \(S\) is the start state, capitals are non-terminals and lower case are terminals.
States of \(N\): one for each non-terminal in the grammar and one more (let’s call is \(X\) for extra).
Start state = start symbol
\(X\) is an accepting state; the only other state that might be accepting is start state.
Convert rules to transitions:
\(S\) is new lonely start state.
\(S\) is new lonely start state.
The algorithm works just the same if you start from an NFA or a GNFA.
As a side note, this implies that GNFAs are equivalent to NFAs. In particular, \(\lambda\)-NFAs (NFAs that allow transitions labeled \(\lambda\) that can be used without processing any input symbols) are equivalent. So our diagram looks like this
\[ \Large \begin{array}{ccccccc} \mathrm{DFA} & \longleftrightarrow & \mathrm{NFA} & \longrightarrow & \lambda\mathrm{-NFA} & \longrightarrow & \mathrm{GNFA} \\ && \downarrow \uparrow & \nwarrow & & \swarrow \\ & & \mathrm{regular}& & \mathrm{regular} \\ & & \mathrm{grammar}& & \mathrm{expression} \end{array} \] Some books and online resources will demonstrate the conversion
\[ \mbox{regular expression} \longrightarrow \lambda\mathrm{-NFA} \] since this is slightly easier than \[ \mbox{regular expression} \longrightarrow \mathrm{NFA} \] But then we would need an additional conversion \[ \lambda\mathrm{-NFA} \longrightarrow \mathrm{NFA} \;. \] This doable, but isn’t really any easier than building it into the the conversion from regular expressions to NFAs, the way we did it.
You should know how to perform all of the conversions illustrated in the diagram above.
Compare your descriptions to the descriptions below. Did you leave out anything important? Do the solutions below leave out anything important?
1a. regex \(\to\) NFA:
6 parts:
union: \(A \cup B\) where \(A = L(N_1)\) and \(B = L(N_2)\).
keep all states and transitions from \(N_1\) and \(N_2\)
add one new start state \(S\); \(S\) is final if either start state of \(N_1\) or start state of \(N_2\) is final
add some additional transitions
concatenation: \(AB\) where \(A = L(N_1)\) and \(B = L(N_2)\).
Kleene star: \(A = L(N_1)\)
keep all states and transitions from \(N_1\)
add a new start state that is a final state (because \(\lambda \in A^*\))
add new transitions from new start state (\(S\))
add new transitions to old start state (\(S_1\))
1b. DFA \(\to\) NFA
1c. NFA \(\to\) DFA
DFA states are subsets of NFA states (think: magnets on white board)
A is final in DFA if A contains a final state of NFA
Remember that \(\{ \}\) may be needed as one of the states in the DFA
1d. DFA (or NFA) \(\to\) reg grammar
\(A \stackrel{x}{\to} B\) becomes
\(A \to xB\)
also \(A \to x\) if B is final state
If S is final in NFA/DFA, then add \(S \to \lambda\)
Number of rules = number of transitions + number of transitions to final states + 1 more if the start state is final
1e. reg grammar \(\to\) NFA
states: non-terminals of grammar + one additional state \(F\) (a final state)
production rules become transitions in NFA
1f. DFA \(\to\) regular expression
Big idea: Make GNFAs with fewer and fewer states until we have a GNFA with two states (one the start state and the other the accepting state) and one transition between them, labeled with a regular expression.
If necessary, make two addjustments to the DFA before beginning
Pick any internal state \(R\) (not the start or accepting state) and “rip it out”.
In addition to the in class discussion, you might like to look at page 885 of the text.
The basic idea used to show that \(\{0^n1^n \mid n = 0, 1, 2, ... \}\) is not regular can be turned into a lemma that doesn’t mention DFAs at all.
Suppose \(L\) is a regular language. Then there must be a DFA \(M\) that recognizes \(L\). This machine has some number of states, let’s call that number \(N\).
Now suppose we have a long string \(x\) with more symbols than \(N\). (We will write this \(l(x) > N\). We can break our string into three parts:
Explain why each of these strings is in \(L\) if and only if \(x \in L\).
Putting this all together gives us the Pumping Lemma:
If \(L\) is a regular language, then there is a number \(N\) such that for any string \(x\) with \(l(x) > N\), we can write \(x\) as
\[ x = uvw \]
such that
Important things to note:
The Pumping Lemma says something about long strings. There is some length beyond which the \(x = uvw\) splitting is guaranteed. It may or may not work for shorter strings.
You do not get to choose \(u\), \(v\), and \(w\). The Pumping Lemma tells you that there is a way to split up \(x\), not that every way of splitting up \(x\) will work.
The length constraints on \(u\) and \(v\) are often important in applications. In particular, \(l(uv) \le N\).
Let’s try using the Pumping Lemma to show that \(\{0^n1^n \mid n = 0, 1, \dots \}\) is not regular.
Suppose \(L\) were regular. Let \(N\) be the number given by the Pumping Lemma. Consider \(x = 0^N1^N\).
Now consider the string \(uw\). \(uw\) must be in \(L\), but \(uw\) has fewer 0’s than 1’s, so it can’t be in \(L\). This means our assumption that \(L\) was regular must be false.
Note 1: Anything you can prove using the Pumping Lemma, you can also prove by going back to the underlying argument about repeated states (pigeon hole principle), loops, etc. So you can think of the Pumping Lemma as an (optional) alternative way to think about these problems. I don’t care which approach you take, as long as you do it correctly. Any problem that says “by the Pumping Lemma” may also be done from the underlying argument.
Note 2: Using \(x = 0^N1^N\) is sufficient since we read more more state than we have read symbols. (After reading the first symbol, we have seen the start state and a next state.)
But if you prefer to use \(x=0^{N+1}1^{N+1}\) just to make the argument easier, that’s fine too.