\documentclass[letterpaper]{article}
\usepackage{hyperref} % to force pdflatex to export letterpaper size
\usepackage{611-lecture}
\usepackage{amsmath}
\newcommand{\nondet}{\left[\!\right]}

\lecture{13}
\title{Predicate Transformers}
%\lecturer{Michael Clarkson}
%\author{Asif-ul Haque and Ryan Peterson}
\date{27 September 2006}

\renewcommand\phi\varphi
\renewcommand\wp[2]{\mathsf{wp}~{#1}~{#2}}

\begin{document}

\maketitle

\section{Axiomatic Semantics}

So far we have focused on _operational semantics_, which are natural for
modeling computation or talking about how state changes from one step
of the computation to the next.  In operational semantics, there is a
well-defined notion of _state_.  We take great pains to say exactly what
a state is and how it is manipulated by a program.

In _axiomatic semantics_, on the other hand, we do not so much care what
the states actually are, but only the properties that we can observe
about them.  This approach emphasizes the relationship between the properties of the
input (preconditions) and properties of the output (postconditions).
This approach is useful for specifying what a program is supposed to do and talk
about a program's correctness with respect to that specification.  

\section{Preconditions and Postconditions}

The _preconditions_ and _postconditions_ of a program
say what is true before and after the program
executes, respectively.  Often the correctness of the program
is specified in these terms.  Typically this is expressed as a contract: as long
as the caller guarantees that the initial state satisfies some set of preconditions, then
the program will guarantee that the final state will satisfy some
desired set of postconditions.  Axiomatic semantics attempts to say exactly
what preconditions are necessary for ensuring a given set of postconditions.

\section{An Example}

Consider the following program to compute $x^p$:

\medskip

\begin{tabbing}
\hspace{2.7in}\=\hspace{1em}\=\kill
\> $y=1$;\\
\> $q=0$;\\
\> $"while"~(q \lt p)~\{$\\
\> \> $y = y\,x$;\\
\> \> $q = q+1$;\\
\> $\}$
\end{tabbing}

\medskip\noindent
The desired postcondition we would like to ensure is $y=x^p$; that is, the
final value of the program variable $y$ is the $p$th power of $x$.  We would
also like to ensure that the program halts.  One
essential precondition needed to ensure halting is $p \ge 0$, because the program
will only halt and compute $x^p$ correctly if that holds. Note that $p \gt 0$ will also
guarantee that the program halts and produces the correct output,
but this is a stronger condition (is satisfied by fewer states, has more logical consequences).
\begin{eqnarray*}
\underbrace{p \gt 0}_{\mathrm{stronger}} &\Rightarrow& \underbrace{p \ge 0}_{\mathrm{weaker}}
\end{eqnarray*}
The weaker precondition is better because it is less restrictive of the
possible starting values of $p$ that ensure correctness.  Typically, given a
postcondition expressing a desired property of the output state, we would 
like to know the _weakest precondition_ that guarantees that the program
halts and satisfies that postcondition upon termination.

\section{Weakest Preconditions}

Given a program $S$ and a postcondition $\phi$, the weakest property of the input
state that guarantees that $S$ halts in a state satisfying $\phi$ is
called the _weakest precondition_ of $S$ and $\phi$ and is denoted $\wp S\phi$.
This says that
\begin{itemize}
\item
$\wp S\phi$ implies that $S$ terminates in a state satisfying $\phi$ ($\wp S\phi$ is a precondition of $S$ and $\phi$),
\item
if $\psi$ is any other condition that implies that $S$ terminates in a state satisfying $\phi$, then $\psi\Rightarrow\wp S\phi$ ($\wp S\phi$ is the _weakest precondition_ of $S$ and $\phi$).
\end{itemize}

As in the $\lambda$-calculus, juxtaposition represents function application, so
$\mathsf{wp}$ can be viewed as a higher-order function that takes a program $S$ and a postcondition $\phi$
and returns the weakest precondition of $S$ and $\phi$. 
The function $\mathsf{wp}$ can also be viewed as taking a program and returning a function
that maps postconditions to preconditions. For this reason, axiomatic
semantics is sometimes known as _predicate-transformer semantics_.

\section{Guarded Commands}

Dijkstra introduced the Guarded Command Language (GCL) with the grammar
\[
\begin{array}{lcl}
S &::=& "skip" \bnf x := E\bnf S_1;~S_2\\[6pt]
&& \bnf "if"~B_1 \rightarrow S_1 \nondet B_2 \rightarrow S_2 \nondet \cdots \nondet B_n \rightarrow S_n~"fi"\\[6pt]
&& \bnf "do"~B_1 \rightarrow S_1 \nondet B_2 \rightarrow S_2 \nondet \cdots \nondet B_n \rightarrow S_n~"od"
\end{array}
\]
where the $B_i$ are Boolean expressions.  The $B_i$ are called _guards_ because they guard
the corresponding statements $S_i$.  The symbol $\nondet$ is the _nondeterministic choice operator_ and is not to
be confused with $|$. In "if" and "do" statements, a clause $B_i \rightarrow S_i$ is said to be _enabled_ if
its guard $B_i$ is true.

Informally, when executing the "if" statement, at least one of its clauses must be enabled, otherwise it is a runtime error.  One of the enabled clauses $B_i \rightarrow S_i$ is chosen nondeterministically and the corresponding statement $S_i$ is
executed. The "do" statement works similarly, except that there is no requirement that at least
one clause be enabled.  If none are enabled, execution just falls through to the following statement.
If at least one is enabled, then one of the enabled clauses is chosen nondeterministically for execution.
After the clause is executed, the guards are reexamined, and the process is repeated.  This process
repeats until all guards become false.

\section{Weakest Preconditions in GCL}

We now show how to determine the weakest preconditions for each part
of GCL, as well as provide generic examples and special cases of
the $\mathsf{wp}$ function.

\subsection*{"Skip"}

Since "skip" does not do anything, we have $\wp{"skip"}\phi\ \Leftrightarrow\ \phi$.  Examples:
\begin{itemize}
\item $\wp{"skip"}{(x=1)}\ \ \Leftrightarrow\ \ x=1$
\item $\wp{"skip"}{"false"}\ \ \Leftrightarrow\ \ "false"$.
\end{itemize}

\subsection*{Assignments}

For assignments $x:=E$,
\begin{eqnarray*}
\wp{(x := E)}\phi &\Leftrightarrow& \subst\phi Ex.
\end{eqnarray*}
Here $\subst\phi Ex$ denotes safe substitution of $E$ for $x$ in the formula $\phi$, in which variables bound by quantifiers $\forall x$ or $\exists x$ are renamed if necessary to avoid capture.  Note that the mapping $\phi\mapsto\subst\phi Ex$ goes right-to-left; that is, $\subst\phi Ex$ is the precondition that must hold of the input state in order to ensure that the postcondition $\phi$ holds of the output state.
Examples:
\begin{itemize}
\item $\wp{(x := 1)}{(x = 1)}\ \Leftrightarrow\ "true"$.  In words, $x=1$ is true after $x:=1$ no matter what holds before execution.
\item $\wp{(y := 1)}{(x = 1)}\ \Leftrightarrow\ x = 1$.
\item $\wp{(x := y)}{(x = 1)}\ \Leftrightarrow\ \subst{(x=1)}yx\ \Leftrightarrow\ y = 1$.
\item $\wp{(x := x + 1)}{(x = 3)}$\\[2pt]
\begin{tabular}{ll}
\quad $\Leftrightarrow\ \subst{(x = 3)}{x+1}x$ & by definition of assignment\\[2pt]
\quad $\Leftrightarrow\ x + 1 = 3$ & by substitution\\[2pt]
\quad $\Leftrightarrow\ x = 2$ & by arithmetic,
\end{tabular}\\[2pt]
so $\wp{(x := x + 1)}{(x = 3)}\ \Leftrightarrow\ x = 2$.
\end{itemize}

\subsection*{Sequential Composition}

To determine the weakest precondition for which $\phi$ holds after
executing $S_1;S_2$, we first find the weakest precondition for which
$\phi$ holds after the execution of $S_2$, and then determine the weakest
precondition that ensures that property after $S_1$:
\begin{eqnarray*}
\wp{(S_1;S_2)}\phi &\Leftrightarrow& \wp{S_1}{(\wp{S_2}\phi)}.
\end{eqnarray*}
Examples:
\begin{itemize}
\item $\wp{(x := 1;~y := 2)}{(x = 1 \wedge y = 2)}$\\[2pt]
\begin{tabular}{ll}
\quad $\Leftrightarrow\ \wp{(x:=1)}{(\wp{(y:=2)}{(x=1 \wedge y=2)})}$ & by definition defn of\ ;\\[2pt]
\quad $\Leftrightarrow\ \wp{(x:=1)}{(x=1 \wedge 2=2)}$ & by definition of assignment\\[2pt]
\quad $\Leftrightarrow\ 1=1 \wedge 2=2$ & by definition of assignment\\[2pt]
\quad $\Leftrightarrow\ "true"$ & by predicate calculus.
\end{tabular}\\[6pt]
\end{itemize}
\begin{itemize}
\item $\wp{(x := x+1;~y := y-1)}{(x\leq y)}$\\[2pt]
\begin{tabular}{ll}
\quad $\Leftrightarrow\ \wp{(x:=x+1)}{(\wp{(y:=y-1)}{(x\leq y)})}$ & by definition defn of\ ;\\[2pt]
\quad $\Leftrightarrow\ \wp{(x:=x+1)}{(x\leq y-1)}$ & by definition of assignment\\[2pt]
\quad $\Leftrightarrow\ x+1\leq y-1$ & by definition of assignment\\[2pt]
\quad $\Leftrightarrow\ y-x\geq 2$ & by arithmetic.
\end{tabular}
\end{itemize}

\subsection*{"If"}

In an "if" statement, at least one guard $B_i$ must be true.  This condition
is expressed by the disjunction $B \definedas \bigvee_i B_i$.  The $S_i$ that
is chosen for execution is chosen nondeterministically among all enabled clauses,
and in order to guarantee the postcondition $\phi$, all enabled clauses had better
guarantee $\phi$.  Thus
\begin{eqnarray*}
\wp{("if"~B_1 \rightarrow S_1 \nondet \cdots \nondet B_n \rightarrow S_n~"fi")}\phi &\Leftrightarrow& B \wedge \bigwedge_i\ (B_i \Rightarrow \wp{S_i}\phi).
\end{eqnarray*}
Example: The following program computes the maximum of two numbers.
\begin{eqnarray*}
\nm{MAX} &\definedas& "if"\ x \ge y \rightarrow z := x\ \nondet\ y \ge x \rightarrow z := y\ "fi"
\end{eqnarray*}
To prove that the program halts and correctly computes the maximum of $x$ and $y$ regardless of input state, it suffices to show that "true" is the weakest precondition corresponding to the postcondition $z=\max x,y$.

\medskip\noindent
\begin{tabular}{ll}
$\wp{\nm{MAX}}{(z = \max x,y)}$\\[2pt]
\quad $\Leftrightarrow\ x \ge y \vee y \ge x$\\[2pt]
\qquad $\wedge\ (x \ge y \Rightarrow (\wp{(z:=x)}{(z=\max x,y)})$\\[2pt]
\qquad $\wedge\ (y \ge x \Rightarrow (\wp{(z:=y)}{(z=\max x,y)})$ & by definition of "if"\\[2pt]
\quad $\Leftrightarrow\ "true"$\\[2pt]
\qquad $\wedge\ (x \ge y \Rightarrow x=\max x,y)$\\[2pt]
\qquad $\wedge\ (y \ge x \Rightarrow y=\max x,y)$ & by predicate calculus and the definition of assignment\\[2pt]
\quad $\Leftrightarrow\ "true"$ & by predicate calculus.
\end{tabular}

\subsection*{"Do"}

Since "do" has the complication that it may not terminate, it is
difficult to formalize its weakest precondition.  In fact, over arbitrary
structures, first-order predicate logic is not sufficiently expressive
to formulate weakest preconditions for this construct.  However, we can use
infinitary logic (logic with infinite conjunctions and disjunctions).
We can write
\begin{eqnarray*}
\wp{("do"~B_1 \rightarrow S_1 \nondet \cdots \nondet B_n \rightarrow S_n~"od")}\phi &\Leftrightarrow& \bigvee_k P_k,
\end{eqnarray*}
where informally $P_k$ is the weakest precondition ensuring that the "do" statement
terminates in exactly $k$ iterations and satisfies $\phi$ upon termination. Formally,
let $E$ be the body of the "do" statement (thus the statement is $"do"~E~"od"$),
and let $B = \bigvee_i B_i$ as above. Define inductively
\begin{eqnarray}
P_0 &\definedas& \neg B\wedge\phi,\label{eqn:P0}\\
P_{k+1} &\definedas& B\wedge\wp{("if"~E~"fi")}{P_k}.\label{eqn:Pk}
\end{eqnarray}
The basis condition (\ref{eqn:P0}) says that no clause is enabled and $\phi$ is true of the input state, which is equivalent to the condition that the body $E$ of the "do" statement is executed exactly 0 times and terminates in a state satisfying $\phi$.  The inductive condition (\ref{eqn:Pk}) says that $B$ is true, thus the body $E$ of the "do" statement is executed at least once, and after executing the body once, $P_k$ will hold, implying that the "do" statement will execute exactly $k$ more times and satisfy $\phi$ upon termination.

If you don't like infinitary logic, you can do the same thing with the $\mu$-calculus predicate
\[
\mu P.\,(\neg B\wedge\phi) \vee (B\wedge\wp{("if"~E~"fi")}P),
\]
which denotes the least fixpoint of the monotone map $\lam P{(\neg B\wedge\phi) \vee (B\wedge\wp{("if"~E~"fi")}P)}$ on predicates.

\end{document}
