\documentstyle[12pt,pocs-header]{article}
\Scribes{Jim O'Toole and Ellen Spertus}
\Lecturer{Bill Weihl}
\LectureNumber{2}
\LectureDate{September 17, 1990}
\begin{document}
\MakeScribeTop

\section{Administration}
TA announced: Jonathan Amsterdam, NE43-809, x3-0778.  Office hours:
Fridays, 1:00--2:30.  Email address: jba@ai.mit.edu.

\noindent Three handouts were distributed:
\begin{itemize}
\item Handout \#5: Problem Set \#1, due 9/24.
\item Handout \#6: ``A Hash Table Implementation''.
\item An unnumbered handout: ``Specifying Distributed Systems'', by Butler W. Lampson. 
\end{itemize}
Additionally, ``scribe'' signup sheet was circulated.

\section{Specifications for Sequential Systems}

For the next few weeks, we will ignore concurrency and will study 
the specification, verification, and performance of sequential systems.

\paragraph{Definition of Correctness}

Informally, an implementation is {\it correct} if the user cannot tell the
difference between it and the specification, i.e. it always acts in a way
that the specification could act.

Abstractly, the behavior of a procedure is a mapping from inputs
(arguments and initial state) to outputs (return values and changed<
state).  (Note that this is only true for sequential systems.)  This
is a relation, {\it not} a function, because one set of inputs might
have multiple legal results, i.e. the procedure could be {\it
nondeterministic}, as the following examples illustrate:
\begin{itemize}
\item A square root procedure that took a floating point number could
be allowed to return any value within $\epsilon$ of the actual square
root.
\item A search routine that took an array and a value might be allowed
to return any index whose associated array element had that value.  
\item A resource allocation routine might be allowed to return any
free disk page, regardless of where it occurred on the disk.
\end{itemize}

The specification of the search routine could look like this:
\begin{tt}
\begin{verbatim}
APROC search(a: SEQ[int], x: INT) RETURNS (int) RAISES (NotFound) =
  < VAR i: int | 0 <= i /\ i < a.size /\ a[i] = x 
            => RET i
    [*]        RAISE NotFound >
\end{verbatim}
\end{tt}
Note that conjunctions are evaluated from left to right, as in C, so
that the array won't be indexed at $i$ unless $i$ is within bounds.
In this example, the relation of inputs and outputs in the
specification, $R_s$, has the 
type $ seq \times int \rightarrow int \cup {NotFound}$.  If we let
$R_i$ denote the relation abstracted from the implementation, the
implementation is correct if $R_i \subseteq R_s$.

\paragraph{Partial and Total Correctness}

This definition raised the question of termination.  For example, if
$R_i$ was $\emptyset$, it would trivially satisfy the subset relation,
although it would not terminate and return a value where the
implementation could.  Weihl announced that we will be primarily
concerned with {\it partial correctness}, as opposed to {\it total
correctness}.  Partial correctness requires that whenever the
procedure terminates, it returns a legal value, while total
correctness would demand that it always terminate on whatever inputs
the specification does.

\section{Axiomatic Semantics for SPEC}

The language SPEC is based on Dijkstra's guarded command language.
In order to carry out formal correctness proofs about programs written
in SPEC, we use {\it Axiomatic Semantics}.  The axiomatic approach
uses a system of inference rules and primitive axioms to prove
assertions about the state of the system.  The assertions relate the
state of the system prior to program execution to the state after
program execution.

An assertion about a statement will be written: $ P\{S\}Q$.
This may be read as ``If the state of the system satisfies the
predicate $P$, then the state of the system after the execution of the
statement $S$ satisfies the predicate $Q$.''  $P$ is called the {\it
precondition} and $Q$ is called the {\it postcondition}, in this example.

The axioms for SPEC are as follows:

\begin{itemize}

\item % [sequence]
The inference rule for sequential composition of statements, ignoring exceptions:
\[
\begin{array}{c}
P \{ S1 \} R \\
R \{ S2 \} Q \\
\hline 
P \{ S1;S2 \} Q
\end{array}
\]

\item % [cond]
The inference rule for conditional choice among statements:
\[
\begin{array}{c}
P \wedge P1 \{ S1 \} Q \\
P \wedge P2 \{ S2 \} Q \\
\hline 
P \{ P1 => S1 [] P2 => S2 \} Q
\end{array}
\]
SPEC also provides the notation $[*]$ as a kind of ``else clause'':
\[
\begin{array}{c}
P \wedge P1 \{ S1 \} Q \\
P \wedge \neg P1 \{ S2 \} Q \\
\hline 
P \{ P1 => S1 [*] S2 \} Q
\end{array}
\]

\item % [guard]
The inference rule for a single guarded command:
\[
\begin{array}{c}
P \wedge P1 \{ S1 \} Q \\
P \wedge \neg P1 \Rightarrow Q \\
\hline 
P \{ P1 => S1 \} Q
\end{array}
\]
(this is syntactic sugar for an empty else clause.)

\item % [elim]
We use two simple rules for weakening postconditions:
\[
\begin{array}{c}
P \{ S \} R \\
R \Rightarrow Q \\
\hline 
P \{ S \} Q
\end{array}
\]
and strengthening preconditions:
\[
\begin{array}{c}
P \Rightarrow R \\
R \{ S \} Q \\
\hline 
P \{ S \} Q
\end{array}
\]
but we'll often rely on these two rules implicitly.

\item % [assign]
The inference rule for an assignment statement:
\[
\begin{array}{c}
Q[E/x] \{ x := E \} Q
\end{array}
\]
assumes that no variable aliasing is possible.  The notation $Q[E/x]$
means ``subsitute $E$ for $x$ in $Q$.''

\item % [loop]
The inference rule for the looping construct makes use of
a loop invariant:
\[
\begin{array}{c}
I \wedge P \{ S \} I \\
\hline
I \{ do\ P => S\ od \} I \wedge \neg P
\end{array}
\]
This rule uses an invariant $I$ which must be preserved by the
execution of $S$.  If and when the loop terminates, the invariant is
strengthened by the loop termination condition, $\neg P$.

\end{itemize}

\subsection{Termination}

All the non-looping statements are assumed to terminate.  In order to
prove that a loop terminates, we use a so-called {\it clock} function.
The clock function maps the program state to a well-ordered set.
A well-ordered set is a totally ordered set in which every subset
has a least element.  An example of such a set is the natural numbers.

Here is the inference rule for loops for use when proving termination
in addition to correctness:
\[
\begin{array}{c}
I \wedge P \wedge C=c \{ S \} I \wedge C<c \\
\hline
I \{ do P => S od \} I \wedge \neg P
\end{array}
\]
In this rule, $C$ plays the role of the clock function, and $c$ is a
fresh variable which is used to represent the value of the clock
function applied to the ``before'' state.  The antecedent in this rule
requires that we prove that the clock function will strictly decrease
in value from one iteration to the next.  Because $C$'s value is taken
from a well-ordered set, it cannot continue decreasing forever.

\subsection{Guards, Exceptions, and Mutation}

The inference rules given above ignore the possibility of exceptional
conditions or state mutations taking place in the guard predicates
of the SPEC program.  Later we will see how to write the axioms for
SPEC with greater care.


\section{Proofs of Correctness for Modules}

Data abstraction allows us to go from the correctness of individual
procedures to entire modules.  Tools we use, to be discussed later,
are:
\begin{itemize}
\item Abstraction functions.
\item Representation invariants.
\end{itemize}

Because modules, unlike procedures, may have internal state, we use
sequences of inputs and outputs in our proofs.  For example, input and
output sequences for the memory module could be:

\begin{center}
\vspace{.15in}
\begin{tabular}{c|c|c|l}
Input & Legal Sequence & Illegal Sequence & Comment\\
\hline
Init(d)	& Ret	& Ret 	& Initialize all values to d\\
R(a1)	& d	& x	& Read location a1\\
W(a2, x)& Ret	& Ret	& Write x to location a2\\
R(a2)	& x	& d	& Read location a2\\
\end{tabular}
\end{center}
The second sequence is illegal because it returns $x$ for the first read,
although the location should have the value $d$, and because it fails
to return $x$ after it has been written to $a2$.  Thus, the
specification for a module is a relation of input sequences to output
sequences.  As with procedures, an implementation is correct if $R_i
\subseteq R_s$, where $R_i$ is the relation abstracted from the
implementation and $R_s$ the one from the specification.

\paragraph{State Machines}

Because it would be impossible to enumerate all sequences, proofs are
done inductively.  The {\it state machine} is a useful abstraction.
For the memory example, suppose that A, the set of memory locations, is \{1, 2,
3, 4\} and D, the set of possible values, is \{a, b, c\}.  The state of memory
at a given time might be:

\vspace{.15in}
\begin{center}
\begin{tabular}{|c|c|l}
\cline{1-2}
1 & a \\
\cline{1-2}
2 & c & $\hookleftarrow$ \\
\cline{1-2}
3 & b & (R(1), a)\\
\cline{1-2}
4 & a \\
\cline{1-2}
\end{tabular}
\vspace{.15in}
\end{center}
The diagram indicates that when the call R(1) is made in the above state,
it returns $a$ and remains in the same state.

If a write were done, it would change the state as follows:

\vspace{.15in}
\begin{center}
\begin{tabular}{|l|l|c|l|l|}
\cline{1-2} \cline{4-5}
1 & a & & 1 & a	\\
\cline{1-2} \cline{4-5}
2 & c & $\longrightarrow$ & 2 & b \\
\cline{1-2} \cline{4-5}
3 & b & (W(2,b), ret) & 3 & b \\
\cline{1-2} \cline{4-5}
4 & a & & 4 & a \\
\cline{1-2} \cline{4-5}
\end{tabular}
\end{center}
\vspace{.15in}

Similarly, there could be the following transition:

\vspace{.15in}
\begin{center}
\begin{tabular}{|l|l|c|l|l|}
\cline{1-2} \cline{4-5}
1 & a & & 1 & a	\\
\cline{1-2} \cline{4-5}
2 & c & $\longrightarrow$ & 2 & a \\
\cline{1-2} \cline{4-5}
3 & b & (Init(a), ret) & 3 & a \\
\cline{1-2} \cline{4-5}
4 & a & & 4 & a \\
\cline{1-2} \cline{4-5}
\end{tabular}
\vspace{.15in}
\end{center}

Proofs for the memory/cache module would be a bigger problem.  Each
state would be a triple of the contents of memory, the cache, and the
cache size.  Consider the following state:

\begin{center}
{\it {\ \ \ \ \ \ \ \ }Memory \   Cache (size 2)}

\begin{tabular}{|l|l|}
\cline{1-2}
1 & a \\
\cline{1-2}
2 & c \\
\cline{1-2}
3 & b \\
\cline{1-2}
4 & c \\
\cline{1-2}
\end{tabular}
\begin{tabular}{|l|l|}
\hline
2 & b \\
\hline
4 & a \\
\hline
\end{tabular}
\end{center}
If a read of location 3 is performed, the state will change, unlike in
the example without a cache.  The line corresponding to location 3 in
memory will be copied into the cache, replacing {\it either} line of
the cache, which will change memory, because the cache is write-back.
The state transition diagram would thus be nondeterministic, because
either line could legally be knocked out of the cache.


\end{document}
