\documentstyle[11pt,twoside]{article}
\input{defs-6045}
\def\implies{\mbox{ implies }}
\renewcommand{\mid}{:}
\def\Ic{\mathify{\{c,I\}}}
\def\Kt{K_{\rm tot}}
\def\jump#1{^{(#1)}}

\begin{document}

\handout{lecture16}{Notes on Lecture 16}{March 11, 1992}

\reading{Martin 16.4, 17.4, 18.1}	

\section{Universal Turing Machines}

The first part of the lecture covered the material on universal Turing
machines, from section 17.4 of Martin.

\section{Language Acceptance and Recognition, and Function
Computation, by Turing Machines}

So far, we have given many different versions of Turing machines, and
various kinds of simulation constructions for them.
In doing so, we have encountered some subtleties in the 
various notions of what Turing machines compute.
We have seen that they can be acceptors of languages, as well as
computers of functions.  
We now review and study these notions in more depth.

\begin{definition}
A Turing machine {\em accepts} a language $L$ which is a subset of
$\Sigma^*$, where $\Sigma$ is the input alphabet,
if the following holds:
when the machine
is started with $x \in L$ on its tape, it eventually halts,
and when it is started with $x \notin L$ on its tape, it never halts.
\end{definition}

A variation on this definition would be a machine that was required to
decide in either case -- yes if $x \in L$ and no if $x \notin L$.
To define this more carefully, we base the appropriate definition on
the definition of the computation of a function.

\begin{definition}
A Turing machine {\em computes} a partial function $f: S \rightarrow
\Gamma^*$, where $S \subseteq \Sigma^*$, provided that when it is
started with $x \in S$ on its tape, it eventually halts with $f(x)$ on
the tape, and when it is started with $x \notin S$ on its tape, it
never halts.

A special case of a partial function is a total function, where $S =
\Sigma^*$. 
\end{definition}

\begin{definition}
A Turing machine {\em decides} (or equivalently, {\em recognizes}) a
language $L$ if it computes the total function $\chi_L$.

Here, $\chi_L$ is the {\em characteristic function} for $L$, defined to
be $1$ if $x \in L$ and $0$ otherwise.
\end{definition}

\begin{definition}
We say that a language is {\em Turing-acceptable} if it is accepted by
some Turing machine, and it is {\em Turing-decidable}, or
equivalently, {\em recursive}, if it is decided by some Turing machine.

We also say that a partial function (which means a function that can
be undefined on some strings) is {\em partial Turing-computable} or
equivalently, {\em partial recursive}, if it is computed by some
Turing machine.

We say that a total function is {\em total Turing-computable} or {\em
total recursive} if it is partial Turing-computable or partial
recursive, respectively.
\end{definition}

Sometimes we leave the word ``total'' off either of these last two
definitions, so that, e.g., saying that a function is recursive means
that it is total recursive. Note that the word ``recursive'' here
doesn't have anything to do with the usual notion of recursive
programs, recursive calls, etc.  Here, it just refers to the power of
the general computation model.

The classes of Turing-acceptable and recursive languages are of very
fundamental importance for the theory of computation.
Likewise for the partial and total recursive functions.
It's very important to get the terminology straight.

{\bf Terminology Summary}
\begin{itemize}
\item Turing-acceptable language 

\item Turing-decidable language = recursive language

\item partial Turing-computable function = partial recursive function

\item total Turing-computable function = total recursive function =
      Turing-computable function = recursive function
\end{itemize}

Note the very important difference between the notions of
Turing-acceptable and Turing-decidable languages: In both cases, the
machines are guaranteed to halt if $x \in L$.  However, if $x \notin
L$, there is a difference -- in the Turing-acceptable case, the
machine does not halt, but rather crashes or loops, whereas in the
Turing-decidable case, the machine must halt and indicate rejection
(that is, it must halt with 0 on the tape).

Note that when we say ``loop'' here, we don't just mean that the
machine must get into a loop of repeating states, but just that the
machine continues to compute forever.
There are other ways that a machine can continue to compute forever
besides just executing a repeating loop; for instance, it can write
$1$'s forever, down the entire infinite tape.  We have loosely categorized
this kind of behavior as looping also.

The difference between the two kinds of behavior is not very important
in the case of crashes -- a machine that crashes could easily be
modified so that it recognizes the crash and halts with a rejection
notice.  However, the difference {\em is}
important in the case of general looping
(computing forever).  In general, it is not possible to detect
nonterminating computations.  In fact the two language classes,
Turing-acceptable and Turing-decidable (recursive) are different
language classes.
We have inclusion one way:

\begin{theorem}
If $L$ is Turing-decidable then $L$ is Turing-acceptable.
\end{theorem}

\begin{proof}
Since $L$ is Turing-decidable, we can assume that we have a Turing
machine $M$ that decides $L$.
We must design a Turing machine $M'$ that accepts $L$.
On input $x$, let $M'$ simulate $M$. 
When $M$ halts (it must, by definition), $M'$ examines the output.
If the output is $1$, then $M'$ also halts.
If the output is $0$, $M'$ instead goes into an infinite loop, never halting.
\end{proof}

However, the converse of the theorem above is not true.
There are Turing-acceptable languages that are not Turing-decidable.
We don't have the techniques yet for proving this, since we have not
yet learned any methods for showing that a language is {\em not}
recursive.

\end{document}
