CISC 462 — Lecture 2

Configurations

When we talk about Turing machines, it's helpful to talk about the state that they're in. For Turing machines, the "state" of the machine is really a combination of three settings, which together are referred to as a configuration. A configuration specifies the particular state of a Turing machine during computation. More specifically, a configuration is defined by the state, the tape head position, and the contents of the tape.

For a state $q$ and two strings $u, v \in \Gamma^*$, we write $uqv$ for the configuration where the current state is $q$, the current tape contents is $uv$ and the tape head is located on the first symbol of $v$.

Some examples

First, we'll define a Turing machine for the language $L = \{a^n b^n \mid n > 0\}$. The operation of the machine can be described as follows:

  1. Read an $a$ and mark it.
  2. Sweep right across the word until we find a $b$ and mark it.
  3. Sweep left until we find a marked $a$ and move right to the unmarked $a$.
  4. Repeat this process until we have marked as many $b$'s as $a$'s.
  5. If there aren't enough $b$'s to mark, then the machine moves to the reject state and rejects the word.
  6. Otherwise, we have marked an equal number of $a$'s and $b$'s and the tape head is on the first marked $b$. Sweep to the right, ensuring that we are only reading marked $b$'s.
  7. If we encounter an unmarked symbol, the machine moves into the reject state. Otherwise, we should read a $\Box$ and accept.

A formal definition of this Turing machine was presented in class.

Palindromes

Next, we have the language of palindromes $L_{pal} = \{ x a x^r \mid x \in \Sigma^* , a \in \Sigma \cup \{\varepsilon\} \}$. We can describe the machine as follows:

  1. Read the first symbol and write a $\Box$ to the tape.
  2. Sweep across the word until we read a $\Box$ and move once to the left so we can read the last symbol.
  3. If the symbol is the same as the one we read at the beginning, then we move on to the next step. Otherwise, reject.
  4. Move left across the word until we encounter a blank and move right to the next symbol.
  5. Repeat the process of reading a symbol on the left and checking the remaining rightmost symbol, replacing each symbol with $\Box$ on the tape.
  6. If the rightmost symbol doesn't match the leftmost symbol that was read, reject.
  7. Accept when no more symbols can be found on the tape.

Element distinctness

Next, we'll move on to a language that is not as simple as something that can be recognized by a PDA. This example can be found as Example 3.12 in the textbook. The language that we are considering is $$L_e = \{\# x_1 \# x_2 \# \cdots \# x_\ell \mid x_i \in \{a,b\}, x_i \neq x_j, 1 \leq i,j \leq \ell, i \neq j \}.$$ This language is the list of strings separated by $\#$ and each string is different. The machine that decides this language works by comparing each word $x_i$ with every word $x_j$ for $j > i$. A description of the operation of the machine is as follows:

  1. On input $w$, mark the leftmost tape symbol. If the symbol is $\Box$, then accept. If the symbol is $\#$, then go to the next step. Otherwise, reject.
  2. Scan right to the next $\#$ and mark it. If no $\#$ is encountered, before a $\Box$, then only $x_1$ was present and we can accept.
  3. Compare the two strings to the right of the marked $\#$. If they are equal, reject.
  4. Move to the right of the rightmost marked $\#$. If no $\#$ is encountered before a $\Box$, unmark the leftmost marked $\#$ and mark the next $\#$ to its right, and move the mark from the rightmost $\#$ to the $\#$ just to the right of the first marked $\#$. Now, if there is no $\#$ for the rightmost mark, all the strings have been compared, and we can accept.
  5. Otherwise, go to step 3.

Decision problems

We still haven't explicitly linked the notion of computation as we understand it today with the Turing machines that we have been studying so far. All of the problems we've studied until now appear to be formal language problems. That is, we've been constructing Turing machines in order to decide various languages. However, we can look at these languages from the computational point of view. For instance, we can consider a Turing machine that decides the language $L_{pal}$ to be an algorithm for determining whether a given word is a palindrome.

In fact, it turns out we can view many computational problems as language inclusion problems. We say that a problem that results in an answer of yes or no is a decision problem. A decision problem $P$ has an associated language $L_P$. Then an input $w$ corresponds to a yes for problem $P$ if and only if $w \in L_P$.

Implicit in the correspondence between problems and languages is the assumption that all of our inputs are strings. We can always encode objects into string form. Suppose we have an object $O$. Then the string representation or encoding of $O$ is denoted by $\langle O \rangle$. If we have several objects $O_1, O_2, \dots, O_k$, then we denote their encoding into a single string by $\langle O_1, O_2, \dots O_k \rangle$. We assume that our objects can be encoded into a reasonable encoding which a Turing machine can decode.

An example that's not a language problem

Suppose we wanted to know whether a given undirected graph is connected. An undirected graph is connected if every node can be reached from every other node. In other words, we want a Turing machine that decides the language $$ L = \{ \langle G \rangle \mid \text{$G$ is a connected undirected graph} \}. $$

Now, we need to consider a proper encoding for graphs. Recall that a graph is a pair $G = (V,E)$, where $V$ is a set of nodes or vertices and $E$ is a set of edges, which are pairs of vertices. Then we can encode a graph $G = (V,E)$ by as follows: $$ \langle G \rangle = (v_1,v_2,\dots,v_n)((v_{e_1,1},v_{e_1,2}),(v_{e_2,1},v_{e_2,2}),\dots,(v_{e_m,1},v_{e_m,2})). $$ where $v_i \in V$ are vertices. This particular encoding is a list of all of the vertices in the graph followed by a list of all of the edges. Now, it is not too difficult to see how a Turing machine can decide $L$.

  1. Select the first node of $G$ and mark it.
  2. Repeat the following until no new nodes are marked:
  3. For each node in $G$, mark it if it is in an edge with a node that is already marked.
  4. Scan all nodes of $G$ to see if they are all marked. If they are, accept; otherwise, reject.