\documentclass{article}
\usepackage{611-lecture}
\usepackage{611}
\usepackage{amsthm, amsmath, amssymb, amsfonts}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% CS611: Please fill in these macros as appropriate:
\lecture{14}                  %% Lecture number
\title{Axiomatics Semantics II and Hoare Logic}		   %% Title of lecture
%\author{Bryant Adams, Mia Minnes}       %% name of scribe
%\lecturer{Michael Clarkson}
\date{29 September 2006}     %% Date of lecture, e.g., 1 January 2001
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% See 611.sty for a variety of macros that will be helpful in
% typesetting the lecture. Here are a few of particular interest:
%
% "x"	 	x in keyword font (e.g., "if", "#t")
% _x_	 	x in italics
% \nm{n}   	n in slanted font (used for abbreviations)
%          	(if x is more than a single character, use \Tr{x}{y})

\theoremstyle{definition}
\newtheorem*{defn}{Definition}
\newcommand{\nondet}{\left[\!\kern1pt\right]}
\renewcommand\phi\varphi
\renewcommand\wp[2]{\mathsf{wp}~{#1}~{#2}}
\newcommand\wlp[2]{\mathsf{wlp}~{#1}~{#2}}
\renewcommand\({\begin{eqnarray*}}
\renewcommand\){\end{eqnarray*}}

\newcommand\LOOKUP[2]{\mathrm{LOOKUP}~{#1}~{#2}}
\newcommand\UPDATE[3]{\mathrm{UPDATE}~{#1}~{#2}~{#3}}
\newcommand\MALLOC[2]{\mathrm{MALLOC}~{#1}~{#2}}
\newcommand\EMPTY{\mathrm{EMPTY\mbox{-}STORE}}
\renewcommand\dom[1]{\mathrm{dom}\,{#1}}
\newcommand\p[2]{\langle{#1},\,{#2}\rangle}
\newcommand\bigcdot{\mathrel{\raisebox{1pt}{$\scriptscriptstyle\bullet$}}}
\newcommand\holed[1]{[\,#1\,]}
\newcommand\hole{\holed\bigcdot}
\newcommand\context[1]{E\kern1pt\holed{#1}}
\newcommand\contextHole{\context\bigcdot}
\newcommand\goesto[2]{\underset{#2}{\overset{#1}\longrightarrow}}
\newcommand\ifthenelse[3]{\mathsf{if\ }#1\mathsf{\ then\ }#2\mathsf{\ else\ }#3}
\newcommand\whiledo[2]{\mathsf{while\ }#1\mathsf{\ do\ }#2}
\newcommand\letin[3]{\mathsf{let\ }#1 = #2\mathsf{\ in\ }#3}
\newcommand\letrec[5]{\mathsf{letrec\ }#1 = #2\mathsf{\ and\ \ldots\ and\ }#3 = #4\mathsf{\ in\ }#5}
\newcommand\letrecone[3]{\mathsf{letrec\ }#1 = #2\mathsf{\ in\ }#3}
\newcommand\true{\ensuremath{\mathsf{true}}}
\newcommand\false{\ensuremath{\mathsf{false}}}
\newcommand\error{\ensuremath{\mathsf{error}}}
\newcommand\pca[3]{\{#1\}\kern1pt{#2}\kern1pt\{#3\}}

\begin{document}

\maketitle

\section{Axiomatic Semantics II}
\subsection{Refinement}

For nondeterministic programs "S" and "T", we say that  "S" _refines_ "T" iff for any starting state, the set of possible final states of "S" is a (not necessarily strict) subset of the set of possible final states of "T".

Consider for example
\begin{eqnarray*}
"S" &\definedas& "if"~x=1 \to y:=1~\nondet~x\neq 1 \to "skip"~"fi" \\
"T" &\definedas& "if"~x=1 \to y:=1~\nondet~x=1 \to y:=2~\nondet~x \neq 1 \to "skip"~"fi"
\end{eqnarray*}
For input state $(x=a,y=b)$, the only possible final states of "S" are $(x=1,y=1)$ if $a=1$ and $(x=a,y=b)$ if $a\neq 1$, whereas the possible final states of "T" are $\{(x=1,y=1), (x=1,y=2)\}$ if $a=1$ and just $(x=a,y=b)$ if $a\neq 1$, therefore "S" refines "T".

The refinement relation is usually used only with programming languages with some form of nondeterministic choice as a relative measure of how nondeterministic a program is.  A correctness specification might be written using nondeterministic choice, since often we may be happy with any one of a range of outcomes.  Any deterministic program that refines the specification is considered correct.

\subsection{Weakest Liberal Preconditions}

Recall that the weakest precondition of a program "S" and a postcondition $\phi$ is the weakest precondition that guarantees that "S" halts and satisfies $\phi$ upon halting.

The _weakest liberal precondition_ ("wlp") of a program "S" and a postcondition $\phi$ is the weakest precondition that guarantees that if "S" halts, then it satisties $\phi$ upon halting.  The weakest liberal precondition of "S" and $\phi$ is denoted $\wlp S\phi$.

The difference between $\wp S\phi$ and $\wlp S\phi$ is that $\wp S\phi$ implies that "S" terminates, whereas $\wlp S\phi$ does not.  Since $\wlp S\phi$ is weaker than $\wp S\phi$, it is presumably easier to establish.

Recall that weakest preconditions of the "do" construct of GCL are not necessarily expressible in first-order logic.  In fact, the same will be true of the weakest liberal preconditions.  However, we may be able to find _some_ precondition that will be sufficient to establish correctness, even though that precondition may not necessarily be the weakest.  In other words, we will find $\psi$ such that $\psi\Rightarrow\wlp S\phi$.

Recall that "if" and "do" statements look like
\[
\begin{array}c
"if"~B_1 \rightarrow S_1 \nondet B_2 \rightarrow S_2 \nondet \cdots \nondet B_n \rightarrow S_n~"fi"\\[6pt]
"do"~B_1 \rightarrow S_1 \nondet B_2 \rightarrow S_2 \nondet \cdots \nondet B_n \rightarrow S_n~"od"
\end{array}
\]
Define
\(
B &\definedas& \bigvee_{i=1}^n B_i.
\)
We will look for a property $\psi$ such that
\begin{enumerate}
\renewcommand\labelenumi{(\roman{enumi})}
\item
$\psi\wedge B\ \ \Rightarrow\ \ \wlp{("if"~B_1 \rightarrow S_1 \nondet B_2 \rightarrow S_2 \nondet \cdots \nondet B_n \rightarrow S_n~"fi")}\psi$
\item
$\psi\wedge\neg B\ \ \Rightarrow\ \ \phi$.
\end{enumerate}
Property (i) says that $\psi$ is a _loop invariant_: if it holds before execution of the body of the "do" loop, and if at least one clause in the body is enabled, then it holds after one execution of the body.  It follows by induction that if $\psi$ holds before execution of the "do" loop, then it will hold after any number of iterations of the loop.  Property (ii) says that if $\psi$ holds and no clause of the loop is enabled (so that the loop will fall through), then the postcondition $\phi$ is satisfied.

These observations say that the following proof rule is valid:
\[
\frac
{\psi\wedge B\ \Rightarrow\ \wlp{("if"~B_1 \rightarrow S_1 \nondet B_2 \rightarrow S_2 \nondet \cdots \nondet B_n \rightarrow S_n~"fi")}\psi\qquad \psi\wedge\neg B\ \Rightarrow\ \phi}
{\psi\ \Rightarrow\ \wlp{("do"~B_1 \rightarrow S_1 \nondet B_2 \rightarrow S_2 \nondet \cdots \nondet B_n \rightarrow S_n~"do")}\phi}.
\]

Note that a loop invariant need not hold continuously throughout the execution of the body of the loop.  It is enough that it holds when the loop iteration is complete.

For example, consider the following program, which for some function $f: "Int" \to "Bool"$ finds the least $x$ such that $f(x)$ (assume that such an $x$ exists, so that the program will terminate).
\begin{tabbing}
\hspace{2.3in}\=\hspace{1em}\=\kill
\> $x:=0$;\\
\> $"do"~\neg f(x)\rightarrow x:=x+1~"od"$
\end{tabbing}
An appropriate postcondition that specifies what it means for the program to be correct is
\(
\phi &\stackrel\triangle\Longleftrightarrow& f(x)\ \wedge\ \forall y\ \ 0 \leq y \lt x\ \Rightarrow\ \neg f(y).
\)
(read as ``$f$ holds of $x$ and does not hold of any number smaller than $x$'').  One method of finding a good loop invariant is to look at ways of weakening the postcondition, thereby allowing more states to satisfy the predicate.  In this case, we can eliminate the conjunct asserting that we have already found a good $x$.  This yields the invariant
\(
\psi &\stackrel\triangle\Longleftrightarrow& \forall y\ \ 0 \leq y \lt x\ \Rightarrow\ \neg f(y).
\)
One can show that this is indeed an invariant and satisfies the two premises of the proof rule above with $B=\neg f(x)$, therefore
\(
\psi &\Rightarrow& \wlp{("do"~\neg f(x)\rightarrow x:=x+1~"od")}\phi.
\)

The definitions of $\wlp S\phi$ for the other basic constructs of GLC are the same as $\wp S\phi$ except for "if", which is
\(
\wlp{("if"~B_1 \rightarrow S_1 \nondet \cdots \nondet B_n \rightarrow S_n~"fi")}\phi &\definedas& \bigwedge_{i=1}^n (B_i\Rightarrow\wlp{S_i}\phi).
\)
Note that we no longer require $B$ as with "wp", since we do not have to ensure halting.

\section{Hoare Logic}

As we have seen, calculating preconditions by hand is hard and not always tractable.  We will now define a logic which allows us to reason about when assertions hold and therefore (hopefully) bypass most of these kinds of computations.

\subsection{Partial vs.\ Total Correctness}

Two approaches to program verification are:
\begin{itemize}
\item _Partial correctness_: check if program is correct when it terminates.  This is characterized by "wlp" and the Hoare logic we will define shortly.  The termination issue is handled separately.
\item _Total correctness_: ensure both that the program terminates and that it is correct.  This is characterized by "wp".
\end{itemize}
Partial correctness is the more common approach nowadays, since it separates the two issues of correctness and termination.  These two verification tasks use very different methods, and it is helpful to separate them.  Often partial correctness is easier to establish, and once this is done, the correctness conditions can be used in conjunction with a well-founded relation to establish termination.

\subsection{Syntax of Hoare Logic}

To define Hoare logic, we need to define the well-formed formulas in the logic.  Hoare logic is built on top of another conventional logic, such as first-order logic.  For now, let us take first-order logic as our base logic.  Let $\phi,\psi,\ldots$ denote first-order formulas.  The formulas of Hoare logic are _partial correctness assertions_ (PCA's), also known as _Hoare triples_.  They look like
\[
\pca\phi{"S"}\psi.
\]
Informally, this means, ``if $\phi$ holds before execution of "S", and if "S" terminates, then $\psi$ will hold upon termination.''  This is equivalent to
\(
\phi &\Rightarrow& \wlp S\psi.
\)

\subsection{Proof Rules}

We will discuss the semantics of Hoare logic later.  For now, we just give the deduction rules for the language IMP with programs
\begin{eqnarray*}
c & ::= & "skip" \bnf x:=a \bnf c_0;c_1 \bnf \ifthenelse b{c_1}{c_2} \bnf \whiledo bc.
\end{eqnarray*}
The rules are
\newlength\tl
\settowidth\tl{(sequential composition)}
\begin{enumerate}
\item[] \parbox\tl{("skip")} $\pca\phi{"skip"}\phi$
\item[] \parbox\tl{(assignment)} $\pca{\subst\phi ax}{x:=a}\phi$
\item[] \parbox\tl{(sequential composition)} $\displaystyle\frac{\pca\phi{c_1}\psi\quad\pca\psi{c_2}\sigma}{\pca\phi{c_1;c_2}\sigma}$
\item[] \parbox\tl{(conditional)} $\displaystyle\frac{\pca{b\wedge\phi}{c_1}\psi\quad\pca{\neg b\wedge\phi}{c_2}\psi}{\pca\phi{\ifthenelse b{c_1}{c_2}}\psi}$
\item[] \parbox\tl{(while)} $\displaystyle\frac{\pca{b\wedge\phi}c\phi}{\pca\phi{\whiledo bc}{\phi\wedge\neg b}}$
\item[] \parbox\tl{(weakening)} $\displaystyle\frac{\phi\rightarrow\phi'\quad\pca{\phi'}c{\psi'}\quad\psi'\rightarrow\psi}{\pca\phi c\psi}$.
\end{enumerate}
In the assignment rule, $\subst\phi ax$ denotes the safe substitution of the arithmetic expression $a$ for the variable $x$ in $\phi$.  As with the $\lambda$-calculus, there may be bound variables in $\phi$ bound by quantifiers $\forall$ and $\exists$, and these may have to be renamed to avoid capturing the free variables of $a$.  In the weakening rule, the operator $\rightarrow$ is implication in the underlying logic.  Note the parallels between these rules and the definitions of "wlp".

\subsection{Soundness and Completeness}

A deduction system defines what it means for a formula to be _provable_, whereas a semantics defines what it means for a formula to be _true_.  Given a logic with a semantics and a deduction system, two desirable properties are
\begin{itemize}
\item _Soundness_: Every provable formula is true.
\item _Completeness_: Every true formula is provable.
\end{itemize}

Soundness is a basic requirement of any logical system.  A logic would not be good for much if its theorems were false!  With respect to the small-step or big-step semantics of IMP, Hoare logic is sound.

Completeness, on the other hand, is a much more difficult issue.  Hoare logic, as presented, is not complete in general.  However, it is _relatively complete_ given an oracle for truth in the underlying logic, provided that logic is expressive enough to express weakest preconditions.  This is a famous result of Cook.  Although first-order logic is not expressive enough to express weakest preconditions over arbitrary domains of computation, it is expressive enough over the natural numbers.  Therefore Hoare logic is relatively complete for IMP programs over the integers.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}
