Refinement Calculus
Refinement Calculus
Editors
David Gries
Fred B. Schneider
REFINEMENT CALCULUS
A Systematic Introduction
With 27 lIIustrations
t Springer
Ralph-Johan Back
Joakim von Wright
Dapartment of Computer Scianca
Abo Akademi University
Lemminkisenkatu 14
FIN-20520 Tur1<u, Finland
[email protected]
[email protected]
Series Editors
David Gries
Fred B. Schneider
Department of Computer Science
Cornell University
Upson Hali
Ithaca, NY 14853-7501, USA
9 8 7 6 5 4 321
ISBN 978-0-387-98417-9
Preface
The refinement calculus is a framework for reasoning about correctness and re-
finement of programs. The primary application of the calculus is the derivation
of traditional imperative programs, where programs are constructed by stepwise
refinement. Each refinement step is required to preserve the correctness of the pre-
vious version of the program. We study the basic rules for this kind of program
derivation in detail, looking at specification statements and their implementation,
how to construct recursive and iterative program statements, and how to use proce-
dures in program derivations. The refinement calculus is an extension of Dijkstra's
weakest precondition calculus, where program statements are modeled as predicate
transformers.
that captures similarities between the domains, while higher-order logic serves as
a common logic that we can use to reason about entities in these domains.
We present a new foundation for the refinement calculus based on lattice theory and
higher-order logic, together with a simple theory of program variables. These topics
are covered in the first part of the book. Higher-order logic is described in a new way
that is strongly influenced by lattice theory. This part also introduces notions needed
for imperative programs, program variables, expressions, assignment statements,
blocks with local variables, and procedures. The second part of the book describes
the predicate transformer approach to programming logic and program semantics,
as well as the notion of program refinement. We also study the operational semantics
of contracts, games, and program statements, and show how it is related to the
predicate transformer interpretation of these. The third part of the book shows how
to handle recursion and iteration in the refinement calculus and also describes how
to use the calculus to reason about games. It also presents case studies of program
refinement. The last part of the book studies more specific issues related to program
refinement, such as implementing specification statements, making refinements in
context, and transforming iterative structures in a correctness-preserving way.
The refinement calculus has been a topic of investigation for nearly twenty years
now, and a great number of papers have been published in this area. However, a sys-
tematic introduction to the mathematical and logical basis for program refinement
has been missing. The information required to study this field is scattered through
many journal and conference papers, and has never been presented as a coherent
whole. This book addresses this problem by giving a systematic introduction to
the field. The book partly summarizes work that has been published earlier, by
ourselves and by other authors, but most of the material is new and has not been
published before.
The emphasis in this book is on the mathematical and logical basis of program re-
finement. Although we do give examples and case studies of program construction,
this is not primarily a hands-on book on how to construct programs in practice.
For reasons of space we have been forced to omit a great deal of material that we
wanted to include in the book. In particular, we decided not to include the important
topics of data refinement and parallel and reactive system refinement here (though
a simple approach to data refinement is described in Chapter 17). We plan to treat
these topics in a comprehensive way in a separate book.
The book is intended for graduate students and advanced undergraduates inter-
ested in the mathematics and logic needed for program derivations, as well as for
programmers and researchers interested in a deeper understanding of these issues.
The book provides new insight into the methods for program derivations, as well
as new understanding of program semantics and of the logic for reasoning about
programs.
Preface vii
The book should be easy to use in teaching. We have tried to explain things quite
carefully, and proofs are often given in reasonable detail. We have also included
quite a number of examples and exercises. A previous understanding of logic and
programming methodology is helpful but not necessary in order to understand the
material in the book. The first, second, and third parts of the book can be given as
successive courses, with suitable material added from the fourth part.
Acknowledgments
This book was inspired and influenced by a number of other researchers in the field.
In particular, Edsger Dijkstra's work on predicate transformers and his systematic
approach to constructing programs has been an important source of inspiration,
as has the work of Tony Hoare on the logic of programming. Jaco de Bakker's
work on programming language semantics has formed another strong influence, in
particular the stringent way in which he has approached the topic. We very much
appreciate Carroll Morgan's work on the refinement calculus, which has provided
many ideas and a friendly competitive environment that has been much appreciated.
Finally, Michael Gordon's work has shown the usefulness of higher-order logic as
a framework for reasoning about both hardware and software and about formal
theories in general.
Our close coworkers Reino Kurki-Suonio and Kaisa Sere deserve a special thanks
for many years of fruitful and inspiring collaboration in the area of programming
methodology and the logic for systematic program construction.
We are indebted to many other colleagues for numerous enlightening discussions on
the topics treated in this book. Our thanks go to Sten Agerholm, Roland Backhouse,
Eike Best, Michael Butler, Rutger Dijkstra, Wim Feijen, Nissim Francez, Marcel
van de Goot, David Gries, Jim Grundy, John Harrison, Ian Hayes, Eric Hehner,
Wim Hesselink, Peter Hofstee, Cliff Jones, Bengt Jonsson, He Jifeng, Joost Kok,
Rustan Leino, Alain Martin, Tom Melham, David Nauman, Greg Nelson, John
Tucker, Amir Pnueli, Xu Qiwen, Emil Sekerinski, Jan van de Snepscheut, Mark
Staples, Reino Vainio, and Wolfgang Weck.
We also want to thank our students, who have provided an inspiring environ-
ment for discussing these topics and have read and given detailed comments on
many previous versions of the book: Thomas Beijar, Martin Biichi, Eric Hedman,
Philipp Heuberger, Linas Laibinis, Thomas LAngbacka, Leonid Mikhajlov, Anna
Mikhajlova, Lasse Nielsen, Rimvydas Ruksenas, Mauno Ronkko, and Marina
Walden.
The Department of Computer Science at Abo Akademi University and Turku
Centre for Computer Science (TUCS) have provided a most stimulating working
environment. The sabbaticals at the California Institute of Technology, Cambridge
viii Preface
University, and Utrecht University have also been very fruitful and are hereby
gratefully acknowledged. The generous support of the Academy of Finland and
the Ministry of Education of Finland for the research reported in this book is also
much appreciated.
Last but not least, we want to thank our (sometimes more, sometimes less) patient
wives and children, who have been long waiting for this book to be finished: Barbro
Back, Pia, Rasmus, and Ida Back, Birgitta Snickars von Wright, Heidi, Minea, Elin,
and Julius von Wright.
Ralph-Johan Back
Joakim von Wright
Department of Computer Science
Abo Akademi University
June 30, 1997
Contents
Preface v
1 Introduction 1
1.1 Contracts . . . . . . . . . . . . 1
1.2 Using Contracts . . . . . . . . . 6
1.3 Computers as Agents . . . . . . 9
1.4 Algebra of Contracts . . . . . . . . . . . . . 10
1.5 Programming Constructs . . . . . . . . . . . . . . . . . . . 12
1.6 Specification Constructs. . . . . . . . . . . . . . . . . . . . 15
1.7 Correctness . . . . . . . . . . . . . . . . . . 18
1.8 Refinement of Programs. . . . . . . . . . . . . . . . . . . . 20
1.9 Background.......................... 21
1.1 0 Overview of the Book . . . . . . . . . . . . . . . . 24
I Foundations 27
3 Higher-Order Logic 57
3.1 Types and Terms . . . . . . . . . . . . . . . . . . . . . . . 57
3.2 Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.3 Deductive Systems . . . . . . . . . . . . . 63
3.4 Theories . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.5 Summary and Discussion . . . . . . . . . . . . . . . . . . . 66
3.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
x Contents
4 Functions 69
4.1 Properties of Functions 69
4.2 Derivations 73
4.3 Definitions . . . . . . 77
4.4 Product Type . . . . . 80
4.5 Summary and Discussion 82
4.6 Exercises . . . . . . . . 83
9 Relations 151
9.1 Relation Spaces 151
9.2 State Relation Category 153
9.3 Coercion Operators . . 154
9.4 Relational Assignment 155
9.5 Relations as Programs . 159
9.6 Correctness and Refinement. 161
9.7 Summary 164
9.8 Exercises . . . . . . 164
II Statements 185
13 Statements 213
13.1 Subtyping, Sublattices and Subcategories 213
13.2 Monotonic Predicate Transformers . . . . . . . . 217
13.3 Statements and Monotonic Predicate Transformers 219
13.4 Derived Statements 223
13.5 Procedures . . . . . . . . . . . . . . . . . . . . 227
xii Contents
20 Recursion 329
20.1 Fixed Points and Predicate Transformers 329
20.2 Recursion Introduction and Elimination . 334
20.3 Recursive Procedures . . . . . . . . . 336
20.4 Example: Computing the Square Root 342
20.5 Summary and Discussion 343
20.6 Exercises . . . . . . . . . . . . . . . 344
Appendix 497
References 501
Index 509
Part I
Foundations
1___________________________________
Introduction
1.1 Contracts
Let us start from the most general notion used, that of a contract. Consider a
collection of agents, where each agent has the capability to change the world
in various ways through its actions and can choose between different courses of
action. The behavior of agents and their cooperation is regulated by contracts.
Before going into this in more detail, a short remark on the notation that we use is
in order. We denote function application with an infix dot, writing j.x, rather than
the more traditional f (x). We write A --+ B for the set of all functions f : A --+ B.
Functions can be of higher order, so that the argument or value of a function can
be a function itself. For instance, if f is a function in A --+ (B --+ C) and a an
element of A, then f.a is a function in B --+ C. If b is an element of B , then (f.a).b
is an element of C. Function application associates to the left, so (f.a).b can be
written as just f.a.b.
We will use standard set-theoretic and logical notation in our informal discussion in
this and the next chapter. In particular, we write T, F, -.b, b 1\ c, b v c, b ::::} c, b == c
for, respectively, truth, falsity, negation, conjunction, disjunction, implication, and
equiValence in logical formulas. We write universal quantification as 01x b)
and existential quantification as (3x b). These notions will all be given precise
definitions when higher-order logic is introduced, but for now, we rely on an
informal understanding.
A special case is the identity function id : 1:: --+ 1::, which does not change the
world at all, id.(1 = (1. We write skip = (id) for the action that applies the identity
function to the present state.
We think of the state as having a number of attributes Xl, ,Xn , each of which can
be observed and changed independently of the others. Such attributes are usually
called program variables. The value of an attribute x, val.x, is a function that
depends on the state: val.x.(1 gives the value of attribute X in state (1. It models
an observation of some property of the state. For each attribute Xi, there is also
an update function set.Xi that we use to change the state so that attribute Xi gets a
specific value: set.x.a.(1 is the new state that we get by setting the value of attribute
X to a without changing the values of any of the other attributes.
Contracts
A contract regulates the behavior of an agent. The contract can stipulate that the
agent must carry out actions in a specific order. This is written as a sequential
action S) ; S2 ; ... ; Sm, where S), ... , Sm are the individual actions that the agent
has to carry out. For any initial state U = UQ, the agent has to produce a succession
of states U), .. ,Urn, where Ui is the result of performing action Si in state Ui-)'
A contract may also require the agent to choose one of the alternative actions
S), .. , Sm. The choice is written as the alternative action S) U ... U Sm. The
choice between these alternatives is free; Le., any alternative may be carried out
by the agent, but the agent must choose one of the given alternatives.
These two constructs, together with the basic actions described above, give us a
very simple language for contracts:
S ::= (f) I S) ; S2 I S) U S2 .
Each statement in this language describes a contract for an agent. We have restricted
ourselves to binary composition only. Arbitrary composition can be expressed in
terms of binary composition, as sequential and alternative composition are both
assumed to be associative: S) ; (S2 ; S3) = (S) ; S2) ; S3, and S) u (S2 u S3) =
(S) u S2) U S3. We assume that semicolon binds more strongly than choice.
We can observe certain other properties that this language of contracts is expected
to satisfy. For instance, we expect that
SuS= S and
S = x:= 0 ; (T ; x := x + I u Skip) ,
T = (y:= 1 U Y := 2) ; x := x +y .
The occurrence of T in the contract statement S signals that a asks agent b to carry
out its contract T.
We can combine the two statements S and T into a single contract statement that
regulates the behavior of both agents. Because this combined contract is carried
out by two different agents, we need to explicitly indicate for each choice whether
it is made by a or by b. The combined contract is described by
S = x:= 0; y := 1 Ub Y := 2) ; x := x + y ; x := x + 1 u a skip)
Thus, the combined contract is just the result of substituting the contract of T for
the calion T in the contract of S and explicitly indicating for each choice which
agent is responsible for it. For basic actions like skip and assignments, it does not
matter which agent carries out the state change, because the effect will be the same.
Assertions
An assertion is a requirement that the agent must satisfy in a given state. We express
an assertion as {g}, where g is a condition on the state. For instance, {x + y = O}
expresses that the sum of (the values of attributes) x and y in the state must be
zero. An example of a contract with an assertion is the following:
S = x:=l;(x:=x+y;{x>l}ux:=x+z);y:=x-l
Here we require that x > 1 must hold after the assignment in the first alternative
has been completed. If this assertion does in fact hold there when the agent carries
out the contract, then the state is unchanged, and the agent simply carries on with
the rest of the contract. If, however, the assertion does not hold, then the agent has
breached the contract.
Analyzing this example, we can see that the agent will breach the contract if y ::: 0
initially and the agent chooses the first alternative. The agent does not, however,
need to breach the contract, because he can choose the second alternative, which
does not have any assertions, and then successfully complete the contract.
1.1. Contracts 5
S = x :=0;
y := 1 Ub Y := 2; {false}b) ; x := x + 1 ua {false}a);
{y = x}a .
Here the index indicates which agent has the obligation to satisfy the assertion.
Assumptions
Besides assertions, there is another notion that is important when making a contract
between two parties. This is the assumptions that each of the parties makes, as their
condition for engaging in the contract. We will express an assumption as [g], where
g is a condition on the state. Consider as an example the contract
[x :::: 0] ; (x := x + y U x := x + z) ; y := x-I .
Here the assumption of the agent carrying out this contract is that x :::: 0 holds
initially. If this is not the case, then the agent is released of any obligation to carry
out his part of the contract.
The assumption [true] is always satisfied, so we have that [true] = skip. The
assumption [false] is never satisfied and will always release the agent from his
obligation to continue with the contract. It is thus an impossible assumption.
As with assertions, we permit assumptions to occur at any place in the contract
statement. For instance, consider the statement
x := 1 ; (x := x + y ; [x > 1] U x := x + z) ; y := x-I .
Here the agent assumes that x > 1 after carrying out the assignment of the first
choice. If this is not the case, the agent is released from its contract. Again, we
notice that the agent does not have to choose the first alternative; he can choose
the second alternative and carry out the contract to the end.
Finally consider combining the contracts for two agents. As with assertions and
choice, we also have to indicate explicitly for each assumption whether it is made
by agent a or agent b.
6 1. Introduction
Taking Sides
We will assume that the contract is always made between an agent whose goals we
want to further (our agent) and another agent whose goals are not important to us.
We denote our agent's choices by u, and the choice of the other agent by uO. In a
similar way, we distinguish between {g} and {g}O and between [g] and [g]o. This
avoids the introduction of arbitrary names for agents when analyzing a contract.
We extend the language for describing contracts to include combined contracts with
two different agents interacting. The syntax is then as follows, with assumptions
and assertions added as new contract statements:
S ::= (/) I {g} I {g}O I [g] I [g]O I SI ; S2 I SI U S2 I SI UO S2 .
Combining the two contracts
S = x:= 0; (T ; x := x + I ; {x = y} u skip) ,
T = [x ~ 0] ; (y := 1 u y := 2) ,
where contract S is for our agent and contract T is for the other agent, results in
the single contract
S = x:= 0; ([x ~ 0] ; (y := 1 UO Y := 2) ; x := x + 1 ; {x = y} U skip) .
The postcondition need not determine a unique final state. For instance, the agent
may want to achieve either x = 1 or x = 2. The agent can establish this condition
in an initial state where x = -lor x = 0 or x = 1.
Satisfying a Contract
We need to be more precise about what it means for an agent to achieve some
condition by satisfying a contract. Obviously, breaching the contract does not
satisfy the contract. On the other hand, an agent cannot be required to follow a
contract if the assumptions that it makes are violated. Violating the assumptions
releases the agent from the contract. As the fault is not with the agent, it is considered
to have satisfied the contract in this case.
We can illustrate these points by considering first the statement S that consists of
a single assertion action, say S = {x ~ OJ. An agent can establish a condition q
with this action only if x ~ 0 holds (so that the contract is not broken) and if in
addition, q already holds (as the state is not changed if x ~ 0 holds).
Consider next S = [x ~ 0]. If x ~ 0 holds initially, then the effect of the action
is just a skip. In this case q will be established provided that q already was true of
the state before the action. If x ~ 0 does not hold, then the assumptions that the
agent makes are violated, so the agent is considered to have satisfied its contract
to establish q.
We will say that the agent can satisfy contract S to establish postcondition q in
initial state (J if the agent either can achieve a final state that satisfies q without
breaching the contract or is released from the contract by an assumption that is
violated. Let us denote this by (J fl S ~ q.
Two Agents
Consider now the situation where the agent is not alone in carrying out its contract
but cooperates with another agent. Whether the contract can be used to establish
a certain postcondition will then also depend on what the other agent does. In
analyzing whether our agent can achieve a certain condition with S, we will assume
that the other agent does not breach S with its actions. We will say that (J fl S nq
holds if
(i) assuming that the assumptions that our agent makes are satisfied, and
(ii) assuming that the other agent does not breach the contract,
then from state (J, our agent can always establish a final state that satisfies condition
q without itself breaching the contract. When there is another agent involved, our
agent has to be able to satisfy the contract no matter how the other agent makes its
choices. This means that the agent has to take into account all possible alternatives
8 1. Introduction
that the other agent has and be able to establish the desired condition no matter
which alternatives are chosen by the other agent.
The above definition means that our agent satisfies the contract (for any condition
q) if the other agent breaches its contract. This relieves our agent from any further
duties to follow the contract. It is considered to have satisfied the contract, as the
fault was not with it.
In particular, this means that a total breach of contract by the other agent, {false}O,
has the same effect as if our agent had made the impossible assumption [false].
Thus {false}O = [false] when we consider only what it means to satisfy a contract.
In both cases, our agent is considered to have satisfied the contract, no matter what
condition was to be established.
Many Agents
We have assumed above that there are at most two agents, our agent and the other
agent. Let us now complete the picture by considering the situation where there are
more agents. Consider first the situation where we have three agents, a, b, and c.
Assume that a is our agent. Then it does not matter from our point of view whether
the two other agents b and c are really separate agents, each with its own free will,
or whether there is a single will that determines the choices made by both band c.
Therefore, in analyzing what can be achieved with a contract, we will denote U a
by U, and Ub and U c both by uo.
Similarly, if our agent a cooperates with agent b to achieve some common goals,
but agent c has different goals, then we would use U for U a and Ub, while we would
use UO for Uc
In general, situations with more than two agents can always be reduced to the case
where we only need to consider two agents: our agent and its allies, considered as
a single agent, and all the other agents together, also considered as a single agent.
Contracts as Games
Our main concern with a contract is to determine whether we (our agent) can use
the contract to achieve our stated goals. In this sense, our agent has to make the
right choices in its cooperation with other agents, who are pursuing different goals
that need not be in agreement with our goals. The other agents need not be hostile to
our goals; they just have different priorities and are free to make their own choices.
However, because we cannot influence the other agents in any way, we have to be
prepared for the worst and consider the other agent as hostile if we want to achieve
certainty of reaching a specific condition.
As far as analyzing what can be achieved with a contract, it is therefore justified to
consider the agents involved as the two opponents in a game. The actions that the
1.3. Computers as Agents 9
agents can take are the moves in the game. The rules of the game are expressed by
the contract S: it states what moves the two opponents can take and when. Given
an initial state (1, the goal for our agent is to establish a given postcondition q. The
other agent tries to prevent our agent from establishing this postcondition. We will
make this a little bit more dramatic and call our agent the angel and the other agent
the demon. In the game, we talk about an angelic choice when the choice is made
by our agent, and about demonic choice when the choice is made by the demon.
A player in a game is said to have a winning strategy in a certain initial state if
the player can win (by doing the right moves) no matter what the opponent does.
Satisfaction of a contract now corresponds to the existence of a winning strategy:
(1 ~ S D q holds if and only if the angel has a winning strategy to reach the goal q
when playing with the rules S, when the initial state of the game is (1.
If our agent is forced to breach an assertion, then it loses the game directly. If
the other agent is forced to breach an assertion, it loses the game, and our agent
then wins. In this way, the angel can win the game either by reaching a final state
that satisfies the stated condition, by forcing the demon to breach an assertion, or
by choosing an alternative where one of its own assumptions is false. In all other
cases, the angel loses the game.
achieve some goals. If we compare two contract statements for our agent, say S
and Sf, then we can say that the latter is at least as good as the former if any
condition that we can establish with the first contract can also be established with
the second contract. We then say that S is refined by Sf and denote this by S !; Sf.
More formally, we can define S !; Sf to hold if
x = 0 Ux := x +1~ x = 1
(Here, x = 0 stands for the predicate that holds in exactly those states in which the
value of x is 0, and similarly for x 1.) =
Consider then the contract x := x + 1 UO x := x + 2. In this case, the other agent
is making the choice. Hence, our agent can be certain to satisfy the contract to
achieve a certain final condition q (in initial state (J') if and only if he can satisfy
12 1. Introduction
(1 Ux := x + I UO x := x + 2 ~ q iff
(1 Ux := x + q q and (1 Ux := x + 2 h
This reflects the fact that our agent cannot influence the choice of the other agent,
and hence must be able to satisfy whichever contract the other agent chooses.
The contracts will in fact form a lattice with the refinement ordering, where u is
the join in the lattice and UO is the meet. Following standard lattice notation, we
will, therefore, in what follows write n for UO. The impossible assertion {false} is
the bottom of the lattice of contracts, and the impossible assumption [false] is the
top of the lattice.
We will generalize the notion of a contract to permit choices over an arbitrary set
of contracts, u{ Si liE I} and n{ Si liE I}. The set of contracts may be empty, or
it may be infinite. With this extension, the contracts will in fact form a complete
lattice.
The sequential composition operation is also important here. It is easy to see that
contracts form a monoid with respect to the composition operation, with skip as
the identity element. Contracts as we have described them above thus have a very
simple algebraic structure; i.e., they form a complete lattice with respect to ~, and
they form a monoid with respect to sequential composition.
A further generalization of contracts will permit the initial and final state spaces
to be different. Thus, the contract may be initiated in a state (1 in "E, but we permit
operations in the contract that change the state space, so that the final state may
be in another state space r. The simple monoid structure of contracts is then
not sufficient, and we need to consider the more general notion of a category of
contracts. The different state spaces will form the objects of the category, while the
morphisms of the category are the contracts. The skip action will be the identity
morphism, and composition of morphisms will be just the ordinary sequential
composition of actions.
We will explain these algebraic concepts in more detail in the next chapter. Here
we have only indicated the relevance of the lattice and category-theoretic concepts
in order to motivate the reader to study and appreciate these notions.
Conditional Contracts
Consider first a conditional statement such as
if x ~ 0 then x := x + 1 else x := x +2 fi .
We can consider this a conditional contract, defined in terms of previous constructs,
as follows:
if x ~ 0 then x := x + 1 else x := x + 2 fi =
{x ~ O} ; x := x + 1 u {x < O} ; x := x +2 .
Thus, the agent can choose between two alternatives. The agent will, however,
always choose only one of these, the one for which the guard x ~ 0 is true, because
choosing the alternative where the guard is false would breach the contract. Hence
the agent does not have a real choice if he wants to satisfy the contract.
We could also define the conditional in terms of choices made by the other agent
as follows:
if x ~ 0 then x := x + 1 else x := x + 2 fi =
[x ~ 0] ; x := x + 1 n [x < 0] ; x := x + 2 .
These two definitions are equivalent. The choice made by the other agent is not
controllable by our agent, so to achieve some desired condition, our agent has to
be prepared for both alternatives, to carry out x := x + 1 assuming x ~ 0, and to
carry out x := x + 2 assuming x < O. If the other agent is to carry out the contract
without violating our agent's assumptions, it has to choose the first alternative
when x ~ 0 and the second alternative when x ~ 0 is false.
The guarded conditional statement introduced by Dijkstra [53], of the form if gl ~
SID' .. 0 gm ~ Sm fi, is a generalization of the traditional conditional statement.
In this case, the guards gl, ... , gm need not be mutually exclusive (as they are in the
traditional conditional statement). The choice between executing Si or Sj is done
nondeterministically when the two guards gi and gj both hold. Dijkstra's interpre-
tation of the nondeterminism is that it should not be controllable. In our framework,
this means that the choice is demonic. This gives the following definition:
if gl ~ SID'" 0 gm ~ Sm fi =
{gl v .. V gm}; ([gd ; SI n .. n [gm]; Sm) .
The first assert statement tests that at least one of the guards is true in the state.
If not, then the result is an abortion of the execution, which amounts to our agent
breaching the contract. If at least one of the guards holds in the state, then the
14 1. Introduction
other agent will choose which alternative to continue with. To avoid breaching the
contract, the other agent chooses an alternative for which the guard is true.
If we take the first definition of the traditional conditional statement as the starting
point, we get another generalized conditional statement, which has a very different
interpretation. Here the nondeterminism is controllable by our agent; the choice is
angelic:
Recursive Contracts
We can make the language of contracts even more interesting from a programming
point of view by permitting recursive statements of contracts. This can be defined
by extending the syntax as follows:
Here X is a variable that ranges over contract statements, while (ILX S\) is the
contract statement S\, where each occurrence of X in S\ is interpreted as a recursive
invocation of the contract St.
lt is more customary to define a recursive contract by an equation of the form
X = SI,
where SI usually contains some occurrences of X. This defines the recursive
contract (ILX SI).
X = (x:= x + 1 ; X u Skip)
Here the agent can choose between increasing x by one and repeating the process,
or finishing. In this way, the agent can set x to any value that is equal to or greater
than the initial value of x.
We will later show that we can introduce recursive contracts in terms of infinite
choices, so we do not actually need to postulate recursive contracts. Like the
conditional contract, they can be introduced as convenient abbreviations defined
in terms of more primitive contracts.
1.6. Specification Constructs 15
Iteration
Iteration is defined in terms of recursion. For example, the standard while loop is
defined as follows:
For instance, if we want to specify that the variable x is to be set to some value
between 0 and 9, then we can express this as the contract
x := 0 n x := In n x := 9 .
Then our agent does not know precisely which alternative will be chosen by the
other agent, so whatever it wants to achieve, it should achieve it no matter which
alternative is chosen.
16 1. Introduction
This contract can be improved from the point of view of our agent by getting rid
of the uncertainty. We have, e.g., that
x := 0 n x := 1 n ... n x := 9 ~ x:= 3 .
This means that x := 3 is a correct implementation of the specification. Any
other statement x := n, n = 0, ... ,9, is also a refinement and thus a correct
implementation of the specification. Moreover, any choice that cuts down on the
number of alternatives will also be a refinement of the specification. An example
is
x := 0 n x := 1 n ... n x := 9 ~ x:= 3 n x := 7 .
This explains the central importance of the notion of refinement in analyzing
contracts: it captures and generalizes the notion of implementing a specification.
In some situations we need to consider an infinite number of alternatives. For
instance, to set x to any nonnegative value, we can use the following specification:
n {x := n I n ~ O} .
Here one of the statements x : = n is chosen from the infinite set of possible state-
ments. As an executable statement, this construct would be difficult to implement
in its full generality (in the sense that any possibility could be chosen in practice).
However, when we look at it as a contract, it is perfectly acceptable. It just states
some constraint on what the other agent can choose, where the constraint happens
to be such that it permits an infinite number of possible choices for the other agent.
Relational Assignments
We have assumed that an agent can change the state by applying a state-changing
function f to the present state. More generally, we can assume that the agent can
change the state by applying a relation R to the present state. In a given state a,
the agent is free to choose as next state any state a' that satisfies a R a'. Let us
write {R} for the action that changes the state in this way. We consider {R} to be
a contract that shows the freedom that the agent has in choosing the next state.
However, the agent must choose one of the states permitted by R. If there is no
state a' such that a R a' holds, then the agent is forced to breach the contract.
Thus the agent can satisfy the contract {R} to establish condition q in initial state
a if and only if there is some state a' such that a R a' and a' E q.
The contract {R} describes the freedom our agent has in choosing the next state.
The contract {R}O is denoted by [R). Here the choice of the next state is made
by the other agent, and our agent has no influence on this choice. If there is no
state a' such that a R a', then the other agent is forced to breach the contract.
This means that our agent can satisfy the contract [R) to establish condition q in
initial state a if a' E q for every a' such that a R a'. In particular, our agent will
1.6. Specification Constructs 17
satisfy the contract if there is no a' such that a R a'. Keeping the game-theoretic
interpretation of contracts in mind, we refer to {R} as an angelic update and to [R]
as a demonic update.
[x := n In> x] ~ x:= x +2 ,
so x : = x +2 is a possible implementation of this specification, because the number
of possible final states that the other agent can choose in a given initial state is
restricted to just one. Another possible implementation is x := x + 1 n x := x + 2,
which is less deterministic than the first, but still much more deterministic than the
original specification.
The angelic update can also be used as a specification. In this case, the contract
{x:= n In> x}
expresses that we are free to choose a new value for x that is greater than the
present value. A refinement in this case is a contract that gives our agent even more
freedom to choose. For instance,
{x := n In> x} ~ {x:= n I n ~ x} .
Here the refinement adds the possibility of not increasing the value of x, so there
is at lest one more alternative to choose from. In general, a refinement decreases
the number of choices for the other agent and increases the number of choices for
our agent.
Pre-postcondition Specifications
A common way to specify a program statement is to give a precondition p and a
postcondition q on the state that the implementation must satisfy, assuming that
only certain program variables are changed. Consider as an example the specifi-
cation with the precondition x ~ 0 and postcondition x' > x, where x' stands
for the new value of the program variable. Assume further that only the program
variable x may be changed. This pre-postcondition specification is expressed by
18 1. Introduction
the contract
{x ::: O} ; [x := xii x' > x]
Thus, the contract is breached unless x ::: 0 holds in the state initially. If this
condition is true, then x is assigned some value x' for which x' > x holds in the
initial state.
1. 7 Correctness
Let S be a contract statement, and let p and q be two predicates (the precondition
and the postcondition). Then we say that S is correct with respect to p and q,
1.7. Correctness 19
Correctness Problems
Our general goal is to construct program statements (or more general contract
statements) that are correct with respect to some given specification. This is the
programming problem. Of course, programs are also required to satisfy other cri-
teria, such as efficiency and portability, but we concentrate here on correctness.
There are, however, different ways of approaching this problem.
(i) We may assume that precondition p and postcondition q are given and that
statement S has already been constructed by some means. We are asked to
prove that peS nq holds. This is the correctness problem, the traditional
center of interest in programming logics.
(ii) The precondition p and postcondition q are given. Our task is to derive a
suitable program statement S such that peS nq holds. This is the program
derivation problem, which is one of the central topics of this book.
(iii) The program statement S is given. We want to find a suitable precondition p
and postcondition q such that peS n q holds. This is the program analysis
problem; we ask what the program does. This is sometimes referred to as
reverse engineering. If the postcondition q is also given, then we need to find
a suitable precondition p such that peS nq holds. This is precondition anal-
ysis: we want to determine the conditions under which the program behaves
as required. Alternatively, the precondition p could be given, and we should
20 1. Introduction
The word suitable above is important, because for many problems there are triv-
ial solutions that are immediately available. For the program derivation problem,
[false] will satisfy any pre- and postcondition. For precondition analysis we can
always choose the trivial precondition false, and for postcondition analysis we can
often at least get true as a feasible postcondition (when the program statement is
guaranteed to terminate).
The refinement calculus is a framework for studying these different kinds of ques-
tions. In what follows we will look at some of these paradigms in somewhat more
detail.
Besides this top-down method for program development, another idea that was
merged with the stepwise refinement method was that of program transformation.
Here a program is changed by applying a transformation that changes it in a way
that preserves the correctness of the original program. Transformations of source
text, such as loop folding and unfolding, data refinement, and program optimization,
are examples of this approach.
The refinement relation between contract statements is defined so that it preserves
correctness: If S !; S' and p nS nq holds, then p ns' nq will also hold. This is
the case for any choice of precondition p and postcondition q.
The formalization of the stepwise refinement method in the refinement calculus is
based on this observation. We start with an initial statement So that satisfies some
correctness criteria that we have been given; i.e., we assume that peSo nq. Then
we derive a sequence of successive refinements
So !; S) !; ... !; Sn .
By transitivity, we have that So !; Sn, and because refinement preserves correctness,
n
we have that p Sn nq also holds. Thus, we have constructed a new statement Sn
from the original statement So, where the new statement also satisfies our initial
requirement.
An individual refinement step Si !; Si+) can be established by, e.g., implementing
some specification statement in Si to get Si+J. by applying some transformation
rule to derive Si +) from Si, or by some other means. Sometimes, we need a whole
subderivation to establish that the refinement step Si !; Si+l is valid. The methods
that we use for calculating or validating a refinement step form a collection of
so-called refinement laws. These tell us how to find suitable refinement steps and
under what conditions these steps are valid.
The purpose of the derivation is to find a program Sn that in some ways is better
than the original program So. This program could be more space or time efficient, it
could be implementable on a specific computer system or in a specific programming
language (whereas the original one may not have been), or it could have other
desirable properties that the original program was missing. The determination of
these criteria and checking that the proposed refinements are indeed improvements
over the original statements is considered to be outside the scope of this book.
We focus on methods for proving that a refinement preserves correctness and on
finding general rules that are known to preserve correctness.
1.9 Background
We give below a brief overview of the background of the refinement calculus,
concentrating on earlier developments in this area. More recent work is described
and referenced in the subsequent chapters.
22 1. Introduction
The origins of the refinement calculus are in the stepwise refinement method for
program construction that was put forward by Edsger W. Dijkstra [51] and Niklaus
Wirth [141]; the transformational approach to programming, put forward by Susan
Gerhart [61] and by Rod Burstall and John Darlington [43]; and the early work on
program correctness and data refinement by C.A.R. Hoare [84, 87]. The purpose
of the refinement calculus is to provide a solid logical foundation for these meth-
ods, based on the weakest precondition approach to total correctness of programs
proposed by Dijkstra [53].
The refinement calculus is a further development of the weakest precondition the-
ory; it was invented by Ralph-Johan Back in his Ph.D. thesis in 1978 [6] and
shortly thereafter described in book form [7]. This work introduced the central
notions of the calculus: the refinement relation between program statements, with
the emphasis on preserving total correctness rather than partial correctness of pro-
grams; modeling program statements as predicate transformers; using specification
statements as primitive program statements; the emphasis on monotonic program
constructs to guarantee that component replacement preserves correctness; using
assertion statements for refinement in context; and data refinement. The basic re-
finement rules for program statements were identified and proved to be sound, as
were the basic rules for data refinement of program statements.
A few journal papers describing the approach followed in the next few years. Spec-
ifications treated as executable statements were described by Back in a 1981 article
[10]. The general notion of program refinement was also described that same year
[9], and the denotational semantics of statements with unbounded nondeterminism
(which was the result of adding arbitrary specification statements to a programming
language) was described in yet another article in the same year [8]. However, the
topic did not attract much interest from other researchers in the field at that time.
Interest in refinement calculus was revived around 1987-88. An overview and
update of the refinement calculus approach was published by Back [11, 12], with a
better treatment of iteration and recursion, among other things. Back and Kaisa Sere
applied the refinement calculus to stepwise construction of parallel and reactive
programs and to the refinement of atomicity in parallel programs [15,22,24]. This
work was based on the action system framework that had been developed earlier by
Back and Reino Kurki-Suonio [20]. This work uncovered a number of interesting
foundational issues in the refinement calculus and also convinced the authors of
the general usability of the approach in practice.
Carroll Morgan [102, 103, 104] and Joseph Morris [108] also started to publish
papers on this topic around 1987-88. Both were essentially using the original
refinement calculus framework, but they extended it with different specification
statements and with miraculous statements (our assumptions), which were not
allowed in the original calculus. Furthermore, Morris used a fixed-point approach to
handle recursion. Greg Nelson [113] also studied miraculous statements, although
he had a slightly different approach to program refinement (requiring both total and
1.9. Background 23
Morgan later published an influential book on program refinement [106]. This book
incorporated his extensions to the refinement calculus and contained a number
of case studies that described how to derive programs from specifications in the
refinement calculus framework. This established the applicability of the calculus
to practical programming problems. The book reformulates the original refinement
calculus in a notation that is influenced by the Z specification style [133].
Another driving force for the further development of the calculus was the need
to reengineer its mathematical basis. The lattice-theoretic study of refinement was
initiated in a paper by Back and Joakim von Wright in 1989 [25, 27] on the duality in
specification languages, where the fundamental program statements were identified
and analyzed. In particular, this work introduced the central themes of angelic and
demonic nondeterminism in the calculus. The use of lattice theory has led to a
considerable simplification of the theory, as compared to earlier attempts, and
made it much more streamlined. At the same time, the theory has also become
much more general, and new applications for these generalizations have suggested
themselves along the road.
The original formalization of the refinement calculus was done in infinitary logic
[10]. The need for a logic stronger than first-order logic was evident already then,
but the step to a full higher-order logic was taken only later by Back and von Wright
[28, 30]. The higher-order logic formalization has since then been extended and
reworked considerably, as documented in this book. A complete implementation
of the refinement calculus has also been made by von Wright [144] using the HOL
theorem-proving system [62]. The HOL system has influenced a number of design
decisions in our formalization of the calculus. Many of the theorems presented in
this book have been checked mechanically for correctness and now form the basis
for a mechanized program-refinement environment that is being developed in a
project led by von Wright [45, 97].
There are many other authors besides those mentioned above that have contributed
to the development of the refinement calculus. Some of the work has aimed at
extending the domain of applicability of the calculus to new areas, such as parallel
programs [23], reactive programs [14,31], and object-oriented programs [Ill, 129,
138]. Others have been looking at larger-scale applications of refinement methods
[21, 117]. Theory development has also continued and has brought many new
insights into this area [46, 58, 112]. A rather active research area is to build better
computer-supported tools for program refinement [47, 67]. There has also been
considerable work on transporting some of the techniques from the refinement
calculus framework to other formalisms for program development, such as the
CSP process algebra [44].
24 1. Introduction
The third part of the book introduces recursion and iteration of statements. Recur-
sion is explained in terms of fixed points of monotonic functions on lattices, and
iteration is explained in terms of recursion, in the way we have described above.
1.10. Overview of the Book 25
This chapter introduces the central mathematical structures that are needed to
formalize the refinement calculus: partially ordered sets (posets), lattices, and cat-
egories. We identify the basic properties of posets and lattices, and use them for
a classification of lattices. We also show how to construct new lattices out of old
ones as Cartesian products and function spaces. We study structure-preserving
mappings (homomorphisms) on lattices. Finally, we show how to form a certain
kind of category out of these lattices. The simple notions identified in this chapter
underlie the formal reasoning about properties of programs, specifications, and
contracts in general.
a~a, (~ reflexive)
a~b 1\ b~c => a~c, (~ transitive)
a~b=>b~a, (~ symmetric)
a~b 1\ b~a => a=b, (~ antisymmetric)
for any choice of a, b, c in A (note that we assume that ~ binds more strongly
than 1\, which in tum binds more strongly than =>; for a complete collection of
precedence rules we refer to Appendix A).
Here a small note on notation is in order. We could write a ~ b ~ c rather than
a ~ b 1\ b ~ c in the left-hand side of the transitivity rule. However, we will
restrict the use of such continued relations to a minimum; they will appear only to
indicate ranges of numbers of the form a ~ x ~ b and occasionally with continued
equalities of the form a = b = c.
The relation ~ is called a preorder if it is reflexive and transitive. The pair (A, ~)
is then called a preordered set, or a preset. If the preorder ~ is also symmetric, it
is said to be an equivalence relation. If the preorder ~ is antisymmetric, it is said
to be a partial order, and (A, ~) is then called a partially ordered set, or a poset.
Generally, a c:: b stands for a ~ b /\ ..., (b ~ a). For posets, this means that a c:: b
stands for a ~ b /\ a =j:. b. We also write a ;:) b for b ~ a and a :::J b for b c:: a.
The dual of the poset (A, D is the poset (A, ;:).
A partial order is linear (or total) if
(~ linear)
holds for every a, b E A. A linear partial order is called a linear order, and (A, ~)
is then a linearly ordered set.
In a discrete order, the only element that is comparable with an element a is a
itself. This order is thus defined by a ~ b if and only if a = b for any a, b E A. A
discrete order is clearly both a partial order and an equivalence relation.
Let B : A, B =j:. 0. Evidently, the restriction ~B of ~ to B is reflexive (transitive,
symmetric, antisymmetric, linear) on B if ~ is reflexive (transitive, symmetric,
antisymmetric, linear) on A. Hence, (B, ~B) is a poset whenever (A,~) is a
poset. We say that (8, !;B) is a subposetof (A, !;).
Assume that (A, !;) is a partially ordered set and that B is a subset of A. The
element a E B is the least element of B if a ~ x for every element x in B.
Similarly, b E B is the greatest element of B if x !; b for every element x in B.
The least and greatest elements are unique if they exist. The least element of the
whole poset A is called the bottom of the poset and is denoted by ..L. The greatest
element of the whole poset A is called the top of the poset and is denoted by T. A
poset is said to be bounded, if it has a least and a greatest element. For such posets,
we have
{a.b.c}
{}V{b}
T {a.b}
3
{a.b} {b.c}
1
2
{a} {c}
F o o
Truth-Value Poset
The set of truth values Bool = {F, T}, ordered by implication, is an important
poset. We have that F ~ F and T ~ T, so implication is reflexive. If b l ~ b2
and b2 ~ b 3 , then b l ~ b3 , so implication is transitive. Finally, if b l ~ b2 and
b2 ~ b l , then b l = b2 , so implication is also antisymmetric. Thus (Bool, ~) is a
poset. In fact, implication is a linear ordering, because either b l ~ b2 or b 2 ~ b l ,
for any choice of truth values for b l and b2 The truth-value poset is shown as a
Hasse diagram in Figure 2.la. The truth-value poset is evidently also bounded,
with F as the least and T as the greatest element.
Power-Set Poset
The set of subsets peA) of a given set A form another important poset. The pair
(P(A), ~) is a poset for any set A. This poset is described in Figure 2.lb for
A = {a, b} and in Figure 2.lc for A = {a, b, c}. Note that for A = {a}, we get a
poset with the same structure as the truth-value poset in Figure 2.1 a, if we make
the correspondence 0 = F and {a} = T. Inclusion is linear only when A = 0 or
A = {a}; for A = {a, b}, neither {a} ~ {b} nor {b} ~ {a} holds. The power-set
poset is also bounded, with 0 as the least element and A as the greatest element.
Natural-Numbers Poset
The usual arithmetic ordering::: on natural numbers Nat = to, 1,2, ... } is also a
partial order (Figure 2.ld). It is reflexive (n ::: n), transitive (n ::: m /\ m ::: k ~
n ::: k), and antisymmetric (n ::: m /\ m ::: n ~ n = m). Hence, (Nat, :::) is a
poset. In fact, it is a linearly ordered set, as m ::: n or n ::: m holds for any two
natural numbers n and m. Another example is the linearly ordered set of (positive
and negative) integers (Int, :::), with the usual ordering. The natural numbers have
32 2. Posets, lattices, and Categories
a least element, 0, but do not have a greatest element. The integers have neither a
least nor a greatest element.
a !;A a' 1\ b !;o b' => f.(a, b) !;c I.(a', b') . (f monotonic)
A function I is said to be antimonotonic if
a ~A a' =} f.a;!B f.a' . (f antimonotonic)
Antimonotonicity is really a monotonicity property: I as a function from poset
(A, ~A) to poset (B, !;B) is antimonotonic if and only if I as a function from
poset (A, !;A) to the dual poset (E, ;!B) is monotonic.
Squaring is an example of a monotonic function on the natural numbers: n :::: m
implies that n 2 :::: m 2 Squaring is antimonotonic on the negative numbers: for
natural numbers nand m, we have that -n :::: -m implies that n ~ m, which in
turn implies that (_n)2 ~ (_m)2.
Addition and multiplication of natural numbers are examples of functions that are
monotonic in both arguments: if n :::: n' and m :::: m', then n + m :::: n' + m' and
nm ::::n'm'.
b l n b2 ~ b l and b l n b2 ~ b2 , (n elimination)
a ~ bl 1\ a ~ b2 => a ~ b l n b2 . (n introduction)
The dual definition is as follows. The element a is the least upper bound (or
supremum, or join) of B if a is the least element of the set of upper bounds of B.
We denote the least upper bound of B by uB. We write b l U b2 for u{b l , b2}. The
least upper bound of a set B is unique if it exists.
The supremum of an arbitrary set B is characterized by the following two properties:
b l ~ b l U b2 and b2 ~ b l U b2 , (u introduction)
bl ~ a 1\ b2 ~ a => b l u b2 ~ a . (u elimination)
34 2. Posets. Lattices. and Categories
.l
Figure 2.2 illustrates meets and joins in a poset. We have that c = a U b and
d = a n b in the poset. The top T and bottom ..l of the poset are also indicated in
the figure.
We have the following basic correspondence between the partial ordering, the least
upper bound, and the greatest lower bound.
Proof We prove the required property for infimum. The proof for supremum is
analogous. We prove the equivalence by showing implication in both directions.
We first prove that a n b = a => a r;;:, b:
a =anb
=> {reflexivity of r;;:,}
a r;;:, anb
=> {n elimination and transitivity of r;;:,}
a';;b
a~aAa~b
=> {n introduction}
a ~ a nb
=> {a n b ~ a holds by n elimination}
a~anbAanb~a
We have here written the (informal) proofs as linear derivations, where each im-
plication is written and justified on a line of its own. In Chapter 4 we will introduce
a formal way of writing proofs that includes linear derivations such as these.
Because ..1 ~ a and a ~ T hold in any poset that has a top and a bottom, we have
as special cases of this lemma that
The conjunction a A b of truth values a and b satisfies the conditions for finite
meet: (i) a A b => a and a A b => b, so a A b is a lower bound of {a, b}; and (ii) if
c => a and c => b, then c => a A b, so a A b is the greatest lower bound of {a, b}.
Similarly, disjunction satisfies the properties of finite join. Thus, conjunction is the
meet and disjunction the join in Baal.
For the natural numbers (with ordering ~), it is easy to see that m n n = m min n,
while m u n = m max n, where min gives the smaller and max the larger of
the two elements. If K is an arbitrary nonempty set of natural numbers, then nK
always exists, but uK exists only if K is finite. If we extend the natural numbers
with the first infinite ordinal w (ordinals are treated in detail in Chapter 18) to get
Nat U {w}, then uK also exists for arbitrary sets of natural numbers (and is always
w when K is infinite).
36 2. Posets, Lattices, and Categories
2.2 Lattices
A poset (A, !;) (or, for simplicity, just A) is called a lattice if the meet an band
join a U b exist in A for all pairs a, b of elements of A. A direct consequence of
this is that a poset (A,!;) is a lattice if and only if nB and uB exist for all finite
nonempty subsets B of A. The poset (Bool, ~) is a lattice, as are (Nat, ~), (lnt, ~),
and CP(D), ) for any D. The posets in Figure 2.1 are thus lattices, as is the poset
in Figure 2.2.
The poset (A, !;) is called a meet semilattice if an b exists in A for all pairs a and
b of elements of A. A join semilattice is defined analogously.
If the partial order (A, !;) is a lattice, then meet and join are defined for any pair of
elements in A, so lattice meet and join can be seen as binary operations on A. They
thus form an algebra on A. These operations can be shown to have the following
properties:
ana =a aUa=a, (idempotence)
anb=bna aub=bua, (commutativity)
an (b n c) = (a n b) n c a u (b u c) = (a U b) u c , (associativity)
a n (a U b) = a a U (a nb) = a . (absorption)
Conversely, assume that we have an algebra A where the operations n and u satisfy
the above properties. Define a !; b to hold if and only if a = a n b (or a U b = b);
i.e., assume that the correspondence between meet (or join) and ordering holds.
Then we can show that (A, !;) is a lattice and that the operations n and u correspond
to meet and join in this lattice. Hence, lattices can be introduced either as a special
kind of algebra or as a special kind of poset We have above chosen the latter
approach.
Meet and join, seen as operations, are easily shown to be monotonic with respect
to the lattice ordering:
a !; a' 1\ b !; b' ~ a n b !; a' n b' , (n monotonic)
a ~ a' 1\ b ~ b' ~ a U b !; a' U b' . (u monotonic)
We next define a number of additional properties that lattices may have and give a
classification of lattices based on these properties. These additional properties tum
out to be very important and will occur in different disguises over and over again.
Complete Lattices
A lattice A is complete if nB and uB exist in A for all subsets B A. In particular,
greatest lower bounds and least upper bounds also must exist for empty B as well
as for any infinite B.
2.2. Lattices 37
Every complete lattice has a top and a bottom, so a complete lattice is always
bounded. The bottom can be characterized either as the greatest lower bound of the
whole lattice or as the least upper bound of the empty set. A dual characterization
holds for the top. We thus have that
The truth-value lattice is a complete lattice, because any finite lattice is complete.
Consider a set B = {bi liE I} of truth values. The set B must be either 0, {F},
{T}, or {F, T}. For B = 0, we already know that nB = T and uB = F, by the above
characterization. For B =f 0, we have that
Distributive Lattices
A lattice A is distributive if for any elements a, b, and c of A the following two
properties hold, referred to as meet distributivity and join distributivity, respec-
tively:
au (b n c) (a U b) n (a U c) , (n distributivity)
an (b u c) (a n b) u (a n c) . (u distributivity)
AU(niEloBi ) (niEloAUB i ),
An (Ui E loBi) = (Ui E loA n Bi ) .
Boolean Lattices
A complete distributive lattice A is called a complete Boolean lattice if every
element a in A has a unique complement --. a in A satisfying the conditions
Every complete Boolean lattice satisfies both infinite distributivity conditions. For
a proof of this fact, we refer to standard texts on lattice theory.
The following de Morgan rules also hold in any complete Boolean lattice:
(--. antimonotonic)
2.2. Lattices 39
The truth values form a Boolean lattice, where --, is negation of truth values: We
have that a /\ --, a = F and a v --, a = T. The following theorem summarizes the
properties of the truth-value lattice that we have noted above.
Theorem 2.2 The truth values with the implication ordering form a complete, Boolean, and
linearly ordered klttice.
In fact, it can be shown that any partially ordered set with at least two elements that
satisfies the conditions of Theorem 2.2 is isomorphic to the truth-value lattice. Thus
the truth-value lattice is completely characterized by the fact that it is a complete,
Boolean, and linearly ordered lattice.
The subset lattice is also a Boolean lattice. It is bounded and distributed, as we
have shown above. The complement of a subset A of D is the set --, A = D - A.
It is easy to see that A U --, A = D and A n --, A = 0, so the requirements on the
complement are met.
The natural numbers do not form a Boolean lattice. Even if we add the limit ordinal
w to Nat, so that we get a complete distributive lattice, we still do not have a Boolean
lattice.
Atomic Lattices
Let A be a lattice with a least element. The element a E A (where a =I- ..i) is called
an atom if the following condition holds for each b E A:
bl;;a ~ b=..1 v b=a.
Thus, an atom is an element that is one step above the bottom element in a Hasse
diagram.
A lattice A is said to be atomic if for each element x in A, we have that
x = u{a E A I a is an atom /\ a I;; x} .
The truth-value lattice is atomic. In fact, any finite complete Boolean lattice is
atomic. The representation theorem states that any atomic complete Boolean lattice
is isomorphic to the subset lattice of its atoms.
The subsets of a set also form an atomic lattice, where the atoms are the singleton
sets. The definition of atomicity then states that any set in the subset lattice is the
join (union) of its singleton subsets:
B = (UbEB{b}).
The following theorem summarizes the properties of the subset lattice that we have
noted and proved above.
Theorem 2.3 The subsets of a set D with the inclusion ordering form a complete, Boolean, and
atomic klttice.
40 2. Posets, Lattices, and Categories
Product Spaces
Let us first look at the Cartesian product. Let (A, ~A) and (B, I;;B) be two posets.
We define a partial ordering on the Cartesian product A x B componentwise, by
Lemma 2.4 Let (A, ~) and (B,~) be posets. Then (A x B,I;;) is also a poset when the
ordering I;; on A x B is defined componentwise. This poset is a lattice (complete,
bounded, distributive, Boolean lattice) if A and B are lattices (complete, bounded,
distributive, Boolean lattices).
The "if" in this lemma can be strengthened to "if and only if' when A and B are
nonempty.
Assume that A and B are (bounded. Boolean) lattices. Bottom. top. complement.
meet. and join in the product lattice are then componentwise extensions of the
corresponding operations of the component lattices:
1.. AxB (1.. A .1.. B ) (1.. ofpairs)
T AxB (T A T B) (T ofpairs)
--.(a.b) = (--.a. --.b) (--. ofpairs)
(a. b) n (a ' b') (a n a ' b n b') (n ofpairs)
(a. b) u (a ' b') (a u a ' b Ubi) . (u ofpairs)
These definitions are extended in the obvious way to the Cartesian product of an
arbitrary number of posets.
The lattice (b) in Figure 2.1 has the same structure as the product lattice Bool x
Bool. while lattice (c) in the same figure has the structure of the product lattice
Bool x Bool x Bool. These product lattices are shown in Figure 2.3.
Function Spaces
Let A be a set and B a poset. Recall that A ~ B stands for the set of all functions
f : A ~ B. Two functions f and g in A ~ B are equal if they give the same
values for each argument in A (this is known as the extensionality principle):
f = g == (Vx EA f.x = g.x) .
We use this same idea to define a partial order on A ~ B as the extension of the
partial order on B:
f !;A~B g == (Vx EA f.x !;B g.x) (!; offunctions)
for any functions f. g E A ~ B. This is the extensionality principle for functions
generalized to partial orderings. We say that the poset A ~ B is a pointwise exten-
sion of the poset B. The notion of pointwise extension is illustrated in Figure 2.4.
42 2. Posets, Lattices, and Categories
The function indicated by the dashed arrows is here greater than the function
indicated by solid lines.
We have the same result for the pointwise extension to function spaces as for
Cartesian products.
Lemma 2.5 Let B be a poset and A any set. Then the pointwise extension of B to A --+ B is
also a poset. Furthermore, this poset is a lattice (complete, bounded, distributive,
Boolean lattice) if B is a lattice (complete, bounded, distributive, Boolean lattice).
Note that atomicity is a property that is not inherited by this extension (Exercise
2.6).
The lattice operations in A --+ B are defined in terms of the corresponding
operations on B, when B is a (bounded, Boolean) lattice. For any x E A, we
define
Figure 2.5 gives an example of a function from one lattice to another. The mapping
indicated is a bottom and top homomorphism, and it is also a join homomorphism,
but it is not a meet homomorphism, as is easily seen (a n b = .L, but J.a n J.b = c
and f..L #- c).
a
c
holds for any set of elements {ai liE I} in A. We say that h is a positive meet
homomorphism if this condition holds for any nonempty set of elements {ai liE I}.
Dually, we say that h is a universal join homomorphism if the condition
Homomorphism Inclusions
The homomorphisms on a lattice are not independent of each other, as shown by
the following lemma.
(a) h is a universal meet (universal join) homomorphism ifand only ifh is a top
(bottom) homomorphism and a positive meet (positive join) homomorphism;
Proof We show the proof of (iii). The other properties follow directly from the
definitions. Assume that h is a meet homomorphism. Then
al;;b
={correspondence}
a =anb
=> {functionality}
h.a = h.(a n b)
={h is n-homomorphism}
46 2. Posets, Lattices, and Categories
/"
meet hom. join hom.
The implications between the different homomorphisms are shown in Figure 2.6.
In this hierarchy, monotonicity and top and bottom homomorphisms are the weak-
est properties, while universal meet and join homomorphisms are the strongest
properties.
Tabular Representation
Because there are many lattices and operations on lattices that we consider in this
book and there are also many homomorphism properties of interest, it becomes
cumbersome to list and memorize all the properties. On the other hand, the ho-
momorphism properties are extremely useful when reasoning about lattices, so it
is worth identifying them all. We therefore introduce a concise tabular represen-
tation for describing monotonicity and homomorphism properties of functions on
lattices.
The homomorphism properties of the binary lattice operations were discussed
above and are summarized in Table 2.1. The operations that we test for monotonic-
ity and homomorphism are listed on the left. The monotonicity property is listed
first on top of the table, in the column denoted 1;. The homomorphism properties
are then listed, with 1- standing for bottom homomorphism, T for top homomor-
phism, n for positive meet homomorphism, u for positive join homomorphism, and
--, for complement homomorphism. We do not treat finite meet (or join) homomor-
phism separately, because in most cases the same results hold for finite meet (join)
2.4. Lattice Homomorphisms 47
We write the label is in the top left comer to indicate that each table entry states
whether the following assertion is true:
The function! (on the left) is homomorphic with respect to the operation
g (on the top)
(for the relation !;, the assertion is that! is monotonic with respect to !;).
The table entry can be "yes" (meaning that this is always the case) or "no" (meaning
that this need not be the case), or it can be a qualified "yes," with an indication of
the condition under which the assertion holds. We write yes O for the case when the
function is a homomorphism (or is monotonic) onto the dual lattice.
is !; 1. T n u ....,
!.x=xna yes yes no yes yes l no
!.x=xua yes no yes yes2 yes no
f.x =""'x yes O yes O yes O yesO yes O yes
I. ..
when the lattIce IS mfimtely Jom dlstnbutlve
2when the lattice is infinitely meet distributive
is !; 1. T n u -.
extend yes yes yes yes yes yes
fst yes yes yes yes yes yes
snd yes yes yes yes yes yes
For the extension of lattices to a product of lattices, the corresponding result states
that projection onto the first or the second component preserves monotonicity and
is a lattice homomorphism. We have, e.g., that fst(1. AxB ) = 1. A , that fst.(a nb) =
f8t.a n f8t.b, and so on, as also shown in Table 2.2.
nr2J=T and nA = 1. .
Meet is antimonotonic,
is c ...L T n u --,
2.5 Categories
Consider a collection of lattices and the possible homomorphisms between them.
Take for instance all meet homomorphisms. We can see that the collection of meet
homomorphisms is closed with respect to composition: if h : A -+ B is a meet
homomorphism and k : B -+ C is a meet homomorphism, then k 0 h : A -+ C is
also a meet homomorphism, as is easily checked:
(k 0 h).(a n b)
= {definition of functional composition}
k.(h.(a n b
= {h is a meet homomorphism}
k.(h.a n h.b)
= {k is a meet homomorphism}
k.(h.a) n k.(h.b)
= {definition of functional composition}
(k 0 h).a n (k 0 h).b
In general, any collection of sets with a certain structure together with all the
structure-preserving functions (homomorphisms) between these sets forms a con-
crete category. The collection of all posets together with all monotonic functions
between the posets is another example of a concrete category. We can even consider
the collection of all sets with a certain structure. This need not be a set itself, so
the notion of a concrete category goes outside ordinary set theory. However, this
notion provides a very useful abstraction, because it permits us to study all possible
homomorphisms in a general way.
50 2. Posets, Lattices, and Categories
Abstract Categories
We can generalize the notion of a concrete category to an (abstract) category. A
category C consists of a collection of objects Obj(C) and a collection of morphisms
Mor(C). Each morphism has a source and a target, both of which are objects. We
write A -!.... B to indicate that / is a morphism with source A and target B.
Furthennore, there is a composition operator that takes a morphism A -!.... B and
a morphism B ...!.. c to the morphism A ~ B. Composition / ; g is defined
only if the target of / is the source of g. Composition is required to be uniquely
defined and associative. Finally, for every object A there is a special morphism 1A,
the identity morphism on A, which is an identity element for composition. If there
is no danger of confusion, we usually drop the index and simply write I for 1A.
Summarizing, the following always hold in a category:
/ ; (g ; h) = (f ; g) ; h , (; associative)
1;/=/ and /;1=/. (1 unit)
We write C(A, B) for the collection of all morphisms A -!.... Bin C. In category
theory, we do not need to assume that the morphisms fonn a set. If they do, then
the category is said to be small.
Figure 2.7 illustrates these notions. The objects are A, B, C, and D; the morphisms
are A -!.... B, B ...!.. c, B ~ D, C ~ D, D ~ B, the identity
morphisms for each object, and all morphisms that can be constructed from the
explicitly indicated morphisms by composition.
Any concrete category will be an abstract category, where the sets with structure
are the objects and the structure-preserving functions are the morphisms of the
category. In particular, the concrete category of sets with functions forms a cate-
gory. The sets A, B, ... are the objects and the functions f : A -+ B, ... are the
morphisms A ~ B. Composition in this category is forward functional com-
position, defined by (f g).x = g(f(x)), and the identity functions id : A -+ A
are the unit morphisms lA in the category. Functional composition is associative,
so the category properties hold.
We could also choose the functions f :B -+ A (the reverse direction) as the mor-
phisms A ~ B. In this case, composition is backward functional composition,
defined by (f og).x = f(g(x)), while the identity function id : A -+ A still serves
as the unit morphism 1A
The collection of all relations also forms a category. Each object is a set, and as
morphisms A ~ B we choose relations R ~ A x B. The identity relation
serves as the unit element, and composition is ordinary relational composition
R. Q, where (x, z) E R. Q iff (x, y) E Rand (y, z) E Q, for some y. This is an
example of a category that is not a concrete category.
A preorder can be seen as a special kind of category. The objects of the category are
the elements of the preorder. There is a morphism a ~ b between two elements
a and b if and only if a ~ b. Reflexivity guarantees that there is an identity
morphism, and transitivity guarantees that the composition of two morphisms is a
morphism in the poset category.
Order-Enriched Categories
The function space construction gives us new lattices where partial order and the
lattice operations are defined by pointwise extension. Since the elements are func-
52 2. Posets, Lattices, and Categories
tions, we can also compose them, and there is an identity element for functional
composition. Relations have a similar structure. The function space constructions
thus have both a lattice structure and a category structure. Most of the basic struc-
tures that are needed for the refinement calculus tum out to be categories of this
kind.
Consider a category C where for arbitrary objects A and B the morphisms C(A, B)
are ordered by a relation !;A,B. We say that C is an order-enriched category if
composition is monotonic in both arguments:
I !;A,B I' 1\ g !;B,C g' => I; g !;A,C /' ; g'
(any category can in fact be viewed as such an order-enriched category if we choose
the discrete partial order as the ordering). If composition is monotonic only in its
left argument,
I!; I' => I;g!;/,;g,
then we call the category a left order-enriched category. A right order-enriched
category is defined analogously. A category is obviously order-enriched if and only
if it is both left and right order-enriched. If the ordering relation is a preorder, poset,
lattice, etc., we call the category a preorder-enriched category, a poset-enriched
category, a lattice-enriched category, and so on.
The interaction between the order and category structures gives rise to numerous
distributivity possibilities. For example, we may want to know whether composition
distributes over lattice operations from the left or from the right. For instance, does
c;(anb) = c;anc;b (leftdistributivity over meet) hold, or does (anb);c = a;cnb;c
(right distributivity over meet) hold? If the morphisms for a given source and target
form a complete lattice, we may ask whether (n i E I aj) ; b = (n i E I aj ; b).
Similarly, we may ask whether meet and join distribute over composition. For
instance, is (a; b) n c = (a n c) ; (b n c)? In this case we need not distinguish left
from right distributivity, since meet and join are commutative.
= {definition of composition}
(g ; h).x
(h; f).x
= {definition of composition}
h.(f.x)
~ {assumptions; pointwise extension}
h.(g.x)
= {definition of composition}
(h; g).x
f n g) ; h).x
= {definition of composition}
(f n g).(h.x)
= {pointwise extended meet}
f.(h.x) n g.(h.x)
= {definition of composition}
(f; h).x n (g ; h).x
= {pointwise extended meet}
(f; h n g; h).x
so (f n g); h = f; h n g; h.
Right distributivity also holds for join, bottom, top, and complement. However,
left distributivity does not in general hold for any of the lattice operations. Forward
function composition again dually distributes from the left over lattice operations.
54 2. Posets, Lattices, and Categories
The category theory that we need in this book will be quite elementary. We mainly
use it as an organizational concept for the different kinds of algebraic structures
that we need for the refinement calculus. It also allows us to treat different kinds
of compositions in a uniform manner, in the same way as lattice theory allows us
to treat ordering in a uniform manner across many different kinds of structures.
The material on lattices presented here is rather standard and can be found in many
classical references such as Birkhoff [40] and George Gratzer [63]. In particular,
these references contain proofs of the theorems of infinite distributivity for com-
plete Boolean lattices and the representation theorem for atomic lattices. A modem
textbook is Davey and Priestley [50]. Good introductions to category theory and
its use in computer science have been written by Benjamin Pierce [116] and by
Barr and Wells [38].
We have chosen to start our exposition of the refinement calculus with an overview
of basic lattice-theoretic notions. The reason is that these simple ideas form the
basis for the formalization of higher-order logic that we will consider next. To a
large extent, reasoning about truth values, sets, relations, and program statements
can be seen as different instantiations of the same basic lattice-theoretic concepts
that we have described above. This has also motivated us to present the material in
somewhat more detail than what might be strictly needed, because it is important
to have a good intuitive grasp of the concepts involved.
2.7 Exercises
2.1 Let the set A = {I, 2, 3, 6, 8, 12} be ordered such that m ~ n means that m is
divisible by n. Find two numbers in A that do not have a least upper bound in A. Is
it possible to find two numbers in A that do not have a greatest lower bound in A?
2.2 Show that the composition of two monotonic functions is a monotonic function.
2.3 Assume that B is a lattice and A is an arbitrary set. Show that pointwise extension
to the function space A ~ B is a lattice homomorphism.
2.7. Exercises 55
2.4 Let L be the set of all cofinite sets of natural numbers (i.e., all sets that have a finite
complement), ordered by set inclusion. Show that L is a lattice but not a complete
lattice. Does it have a top or a bottom element?
2.5 Prove that the structure (Bool x Nat,!;) is a lattice, where !; is the following
ordering:
J.0 0,
J.{F} to} ,
f.{T} {x I x '" O} ,
I. Bool Nat.
Show that I is a homomorphic embedding.
2.10 Let A be an arbitrary set and ..L and T two elements not in A. Show that the set
AU {..L, T}, ordered by
a!;b == a=bva=..Lvb=T,
is a complete lattice.
2.11 Show that the meet operation in a complete lattice has the following property:
x = nA == (Vy' y !; x == (Va EA Y !; a .
Since the definition characterizes meet using two properties (that it is a lower bound
and that is greater than all lower bounds), this characterization can make proofs
about meets shorter. What is the dual characterization of join?
3_________________________________
Higher-Order Logic
We now introduce the logical basis for program refinement, higher-order logic.
This is an extension of the simply typed lambda calculus with logical connectives
and quantifiers, permitting logical reasoning about functions in a very general way.
In particular, it allows quantification over higher-order entities such as predicates
and relations, a feature that we will find very useful in our formalization. The power
of higher-order logic is similar to that of set theory. It is sufficient for expressing
most ordinary mathematical theories and has a simple set-theoretic semantics.
We describe the basic framework of higher-order logic in this chapter: the syntactic
entities of the logic, the semantic meaning of these entities, the notions of deduction
and proof, and the notion of a theory. In the next chapter we then give the specific
axioms and inference rules that are needed to reason about functions. These are
the usual rules of the simply typed lambda calculus. The axioms and inference
rules needed for reasoning about logical propositions in general are postponed to
Chapter 6.
Functions are constructed by A-abstraction. The function that maps each natural
number n to its successor n + 1 is written as the lambda abstraction
(An: Nat n + 1) .
Here Nat is a type that denotes the set of natural numbers. The part An : Nat
expresses that the argument of the function is denoted by n and ranges over the set
of natural numbers Nat. The value of the function for argument n is given by the
expression n + 1. The parentheses delineate the scope of the bound variable n.
Lambda abstraction permits us to be precise about the variables and constants in
an expression. For instance, we can make a distinction between the functions
(An: Nat n - m) and (Am: Nat n - m) .
In the first case, n is the argument of the function and m is a constant that is
assumed to have some fixed value (determined by the context). In the second lambda
expression, it is the other way around. We can also nest lambda abstractions, so
that, e.g.,
(Am: Nat (An: Nat n - m
is the function that maps each natural number m to the function (An: Nat n - m).
Applying a function to an argument is called application. Application is an oper-
ation that takes two terms, t denoting a function and s denoting an argument, and
gives as result the value of function t at argument s. The application of t to s is
written t.s. For example, we have that
Types
The types of higher-order logic are expressions that denote sets. Let AT be a type
structure, i.e., a set of type operators each having a name and an arity (an arity is a
natural number). Types over AT are defined by the following context-free grammar:
(types)
Here C is a nullary type operator (also called an atomic type) in AT, while l:1, ... , l:n
are types (we generally use l:, r, and !J. as metavariables for types). The type
operator -+ associates to the right, so that, e.g., l:1 -+ l:2 -+ l:3 abbreviates
l:1 -+ (l:2 -+ l:3). In the last alternative, Op is an n-ary type operator in AT that
constructs a new type out of the types l: 1, ... , l:n.
3.1. Types and Terms 59
Each type denotes some nonempty set. The atomic types denote designated sets
in the universe of all sets (this will be made more precise below). Higher-order
logic postulates two atomic types: Bool, which denotes the two-element set of truth
values, and Ind, which denotes an infinite set of individuals.
The function type I:I -+ I:2 stands for the set of all (total) functions from the set
denoted by I:I to the set denoted by I: 2. Thus, e.g., Ind -+ Bool denotes the set of
functions from individuals to truth values. Similarly, each type operator denotes a
set-forming operation, and Op(I:I, ... , I: n ) stands for the result of applying that
operation to the sets denoted by I:I, ... , I: n In fact, we can view -+ as a binary
type operator, mapping sets I:I and I:2 to the set I:I -+ I:2' However, we prefer
to give it special status, since it is so fundamental. It is possible to add new type
operators (including atomic types) to the logic. This is illustrated in Chapter 4 and
described in more detail in Chapter to.
Part of the power of higher-order logic comes from the fact that we can iterate type
construction to ever higher levels of functionality. For instance, (Ind -+ Bool) -+
Bool denotes the set of functions that take functions from individuals to truth
values as arguments and return truth values as results. This is a set of higher-order
functions.
Terms
The terms of higher-order logic are expressions that denote elements oftypes. Each
term t in higher-order logic is associated with a unique type.
We assume that two disjoint infinite sets of names are given, constant names and
variable names. A constant is a pair (c, I:), written CI;, where cis a constant name
and I: is a type. Similarly, a variable is a pair (v, I:), written VI;, where V is a
variable name and I: is a type.
Just as the definition of types is relative to a particular type structure AT, the
definition of terms is relative to a given set SG of constants, called a signature,
where each constant has a type over AT. The terms of higher-order logic are defined
by the following context-free grammar:
.. - VI; , (variable)
CI; , (constant)
tlt2 , (application)
(AvI; td (abstraction)
(we use sand t as metavariables for terms; c, f, andg as metavariables for constants;
and u, v, and w as metavariables for variables).
We associate a type with each term using the following rules:
(iii) If t is a term of type ~I -+ ~2 and tl a term oftype ~J, then the application
t.tl is a term oftype ~2'
(iv) If VEl is a variable and t2 a term of type ~2, then the abstraction (AVE, t2)
is a term oftype ~I -+ ~2.
A term t is well-typed if it has a type ~ according to the above rules. The type
of each well-typed term is uniquely determined by the syntax. We write t : ~ to
express that t has type ~. A well-typed term t : ~ denotes some element in the
set denoted by ~, in the way described intuitively above. From now on, we always
take 'term' to mean 'well-typed term'.
Type indications are usually omitted from constants and variables when this infor-
mation can be deduced from the structure of the term or from the context in which
the term is used. When needed, it is often sufficient to indicate the types of some
variables in lambda abstractions. In this case, we prefer to write (AV : ~ td for
(AVE' td, particularly if the type expression ~ is more complex.
Two different variables can have the same name, if they have different types. Two
different constants can also have the same name, provided that they have different
types. Both kinds of overloading are quite convenient, provided that one adds extra
type information or explanations whenever necessary to avoid ambiguity.
For some constants we use a prefix format, writing f x for j.x, with the same
precedence. In particular, we write negation and complement as prefix constants,
and similarly for meets and joins over sets. Prefix operators have lower precedence
than function application, but higher precedence than infix operators.
A small number of constants are written as postfix operators. Most postfix operators
are written as superscripts (e.g., So is the duality operator 0 applied to S). Postfix
operators have higher precedence than ordinary function application.
Abstraction is written as a mixfix, with delimiters (the parentheses) indicating the
scope of the abstraction. Abstraction has lower precedence than application. To
simplify nested applications, we can write (AVO (AV' t)) as (AV v' t).
3.1. Types and Terms 61
3.2 Semantics
We give a brief description of the meaning (semantics) of types and terms in higher-
order logic. The semantics is set-theoretic; a type L denotes a set in a universe of
sets, and a term t : L denotes an element in the set denoted by L.
Semantics of Types
A model for a type structure AT is given by associating every n-ary type operator
op in AT with some function I : un -+ U (the meaning of the operation).
We require that the type Bool be given a standard meaning as the set 2 and that the
function type constructor -+ be given a standard meaning as the function in U 2 -+
U that maps the pair (X, y) to the set of all (set-theoretic) total functions from X to
Y. Given a model for AT, every type L denotes a set M. L (the meaning OiL) in U.
In a standard model, M.Bool = 2 and M.(L -+ 1) = {f I I: M.L -+ M.r}.
For example, if x denotes Cartesian product, then (Baal x Baal) -+ Baal denotes
the set of all functions I : 2 x 2 -+ 2, i.e., functions that map pairs of truth values
to truth values.
Semantics of Terms
Now assume that type structure AT is given and that SG is a signature over AT. A
model for SG determines (1) a model for AT and (2) for every constant c : Lin SG
an element M.c E M.L (the meaning olc). In a standard model we require that
= : L -+ L -+ Baal be given its standard meaning as equality on the set denoted
by L.
Consider a term t. An environment E for the term is a set of variable-value pairs
{(XI, at), ... , (xn , an)} that assigns a valueai in M.L to every free variable Xi : L
that occurs in t. The meaning of a term with free variables is determined relative
to such an environment.
3.3. Deductive Systems 63
ME.C = M.c,
and the environment gives the meanings of variables,
ME.t.t' = (ME.t).(ME.t').
Thus, if t denotes a function I and t' denotes an element x, then t.t' denotes the
element I.x. Finally, the denotation ME.(Av : l: . t) oflambda abstraction is the
function I, defined by
I.a = MEd,
that maps any a E M.l: to ME..t, where E' is the same environment as E
except that v is mapped to a. In this way, the meanings assigned to the constants
determine the meanings of all terms that can be built out of these constants in a
given environment.
For a closed term t, the the meaning is independent of the environment (since there
are no free variables), and we can define M.t = Mf!j.t.
cJ>/-t, (sequent)
where cJ> is a finite set of formulas over SG (the assumptions of the sequent) and
t is a single formula over SG (the consequent of the sequent). A sequent cJ> /- t is
satisfied in a model of the types in AT and constants in SG if any environment (with
assignment of values to the free variables in cJ> and t) that makes every formula
in cJ> true also makes t true. A sequent is valid if it is satisfied in every standard
model.
64 3. Higher-Order Logic
An inference is a tuple of sequents (<1>1 I- t1, ... , <l>m I- tm, <I> I- t), m ::: O. An
inference is usually written as
(inference)
The sequents <1>1 I- t1, ... , <l>m I- tm are called the hypotheses and <I> I- t is called
the conclusion of the inference.
<1>1 I- t1 <l>m I- tm
{R} (inference rule)
<I> I- t
side condition.
The name of the inference rule is R. Here <1>1, , <l>m, <I> andt1, ... , tm, t may con-
tain metavariables. The side condition states the requirements that an instantiation
of the metavariables with actual terms has to satisfy.
An inference with no hypotheses (m = 0) is called an axiom. An inference rule
with no hypotheses is called an axiom scheme of OS. The line that separates the
(empty) set of hypotheses from the conclusion is usually omitted in axioms (but
usually not in axiom schemes).
Deductions
We can construct new inferences from old ones by composition. If
<I> 1 I- 11 , <l>i I- ti ... <l>n I- tn
<I> I- t
is an instance of inference rule R (and thus satisfies the side condition if there is
one) and
<l>i,1 I- li,1 ... <l>i,n I- ti,n
<l>i I- ti
3.4. Theories 65
is an instance of inference rule R' with a conclusion that is the same as the ith
hypothesis of the first inference, then their composition is the inference
<1>1 I- 11 <l>i,1 I- ti,1 <l>i,n I- ti,n . <l>n I- tn
<I> I- t
which we get from the first inference by replacing the hypothesis <l>i I- ti with the
hypotheses <l>i,1 I- ti,l, , <l>i,n I- ti,n'
A deduction in OS records the intermediate steps and the inference rules of OS that
we have used to construct an inference. The deduction for the above inference is
<l>i,1 I- ti,! . <l>i,n I- ti,n {R'}
<1>1 I- tl <l>i I- ti <l>n I- tn {R}.
<I> I- t
For each inference, we indicate the inference rule that determines it. The hypotheses
of this deduction are the sequents that are not conclusions of inferences, and the
conclusion of the whole derivation is <I> I- t. By composing inferences. we can
build deductions of arbitrary complexity.
A sequent <I> I- t is a theorem if there exists a proof of it, i.e., a deduction without
any hypotheses and with the sequent as its conclusion.
Deductions can also be built by composing inference rules rather than inferences.
In this case, we are building deduction schemes. One then has to be careful that the
side conditions of all rules that are used in the deduction are satisfied. Each such
deduction scheme gives us an inference rule where the conclusion is the final con-
clusion of the whole deduction scheme, the hypotheses are the topmost hypotheses
of the deduction scheme, and the side condition consists of the accumulated side
conditions of the rules used in the deduction. An inference rule arrived at in this
way is called a derived inference rule.
A derived inference rule without any hypotheses is called a theorem scheme. A
theorem scheme may thus have side conditions, and it may contain metavariables
that stand for arbitrary terms or sets of formulas (a theorem cannot contain any
metavariables ).
3.4 Theories
A theory is determined by a type structure AT, a set of constants SG over AT (the
signature). and a set of inference rules OS (the primitive rules of inference). The
first determines the types that can be formed in the theory. the first and second
together determine the terms and formulas that can be expressed in the theory, and
all three together determine the proofs (and thus also the theorems and derived
inference rules) in the theory.
66 3. Higher-Order Logic
A theory is consistent if there exists some sequent (over the signature of the theory)
that cannot be derived. Once we have introduced the notion of falsity F, we can
formulate this in a more familiar way; a theory is consistent if F cannot be proved
as a theorem within the theory.
A theory is sound (with respect to a given model) if every sequent that can be
proved in it is valid in the model. It is complete (with respect to a model) if any
valid theorem can be proved using the deductive system of the theory.
A theory is extended by adding new types, new constants, and new inference rules.
A theory extension thus makes the language more expressive and may permit new
theorems to be proved. Anything provable in the original theory is, however, also
provable in the extended theory.
An extension of a consistent theory need not be consistent. That is why it is desirable
to extend the theory in a conservative way. An extension is said to be conservative
if it does not extend the set of theorems over the old signature. This means that a
sequent of the original theory can be proved in the extension if and only if it can
be proved in the original theory. The advantage of a conservative extension is that
it has a standard model whenever the original theory has one. This means that a
conservative extension can never introduce inconsistency.
lose the simple set-theoretic interpretation that higher-order logic has. Overall, our
feeling is that classical higher-order logic closely matches the intuition of a working
mathematician, and that the loss of expressive power is not a serious drawback in
practice. The lack of subtypes is perhaps the biggest disadvantage of higher-order
logic, but we will show that there are some rather simple ways of getting around
this restriction.
3.6 Exercises
3.1 Assume that I; and r are types and that c : I; and g : r -+ Bool are constants.
Deduce the types of all subterms of the following term:
(AX: Bool Ay f.x.c = g.y) .
3.2 Show that the typing rules of higher-order logic rule out self-application of the
form t.t; i.e., show that a term can never be applied to itself.
3.3 We want to create a theory over a single type T with the following constants:
P:T-+T-+Bool,
A:T-+T-+Bool,
and with the following two inference rules:
I- A.t .t' I- P .t'.t"
I- A.t.t ' I- A.t.t"
(b) Show that if there are deductions of I- A.t.t' and I- A.t'.t" using only the two
inference rules above, then there is also a deduction of I- A.t .t".
4__________________________________
Functions
We start our overview of the basic axioms and inference of higher-order logic by
studying the rules for reasoning about functions. These are essentially the rules
of simply typed lambda calculus. A method of extending the logic by defining
new constants is described. In association with this we also describe two ways
of introducing new notation without extending the logic: abbreviations (syntactic
sugaring) and local definitions. Furthermore, we consider an important practical
issue: how to present proofs in a simple and readable way. The natural deduction
style is the traditional way of presenting proofs and is the one that we have described
in Chapter 3. However, we prefer an alternative derivational proofstyle, because we
find it more readable and it scales up better to large proofs. The natural deduction
style and the derivational proof style are just two different ways of writing proofs;
the underlying notion of a proof is the same in both styles. Finally, we postulate
a new type constructor that denotes a Cartesian product and investigate its basic
properties.
Equality
Equality is the most basic constant of higher-order logic. The following three
inference rules establish that equality is an equivalence relation.
(= reflexive)
f-t=t '
<l>f-t=t'
(= symmetric)
<l>f-t'=t
There are no side conditions associated with these inference rules. The metavari-
abIes t, t', and t" stand for arbitrary terms of arbitrary type. In particular, this means
that the rules are also valid for terms of new types that are added to the logic later.
The transitivity rule is easily seen to hold for an arbitrary number of intermediate
terms:
<1>, f- t, = t2 <1>2 f- t2 = t3 <1>.-, f- t._, = t.
<1>, U ... U <l>n-' f- t, = t.
-,----::-_--::---:_----:-:-----:::::- (= refl.}
_<I>-=--.I-....:...:.tl_=-..:.!t;L-"....I-..,..:...:t[:..:,v~:_=_t..:cd:...,=_t.!;.[v"..-:=_"-;tl7-'....:!']~___ (subst.} .
<I> I- t[v := tIl = t[v := t;1
We have here indicated the subterm that is replaced in the substitution within
quotation marks (" tl "). The quotation marks have no other significance; they
serve only to emphasize the part of the term that is being changed.
A function associates a unique value with each argument: if the arguments are
equal, then the values of the function on these arguments must also be equal. This
is expressed by the following inference rule:
In higher-order logic, there is also another possibility: we can have two different
terms that describe the same function. If these two terms are applied to the same
argument, the values should again be equal:
<I> I- t = t'
(abstraction)
<I> I- (Av t) = (Av t')
v is not free in <1>.
The side condition states that this rule may be used only with sequents where the
variable v does not occur free in any formula in <1>. That the side condition is
necessary is seen from the sequent x = 0 I- x + 1 = 1. This is obviously true, but
it does not follow that the function (Ax' x + 1) is the same as the function (Ax' 1),
because the equality of the function values is established only in the special case
when X = O.
Symmetry and transitivity of equality can be proved from the other rules that we
have given. Symmetry is proved using reflexivity and substitution:
_ _ _"..-_ (= reflexive}
_<I>_I-......:....t_=_t_'_ _<1>-=--.I-.,.--".:,..t_"_=......:....t_ _ _ _ _ (substitution} .
<l>l-t'=t
In a similar way, transitivity is proved using only substitution (Exercise 4.3).
72 4. Functions
Conversion Rules
The lambda calculus conversion rules provide the basic mechanism for manipulat-
ing terms that denote functions. 1\vo terms are considered equivalent if they differ
only with respect to the naming of bound variables. In other words, the names of
the bound variables are not significant. This property is expressed by the rule ofa
conversion:
(a conversion)
I-- (Av t) = (Aw t[v := w))
w does not occur free in t.
An example of this rule is that (Ax x +y) = (Az z+y). However, (Ax x +y) =
(Ay Y + y) does not follow by this rule (and indeed, is not true), because y occurs
free in (x + y). Remember that t [v : = w] stands for the substitution of variable w
for all free occurrences of v in t. The side condition guarantees that no free variable
win t becomes bound when we replace v with w.
The fJ conversion rule gives the basic property of function application:
(fJ conversion)
I-- (Av t).t' = t[v := t']
t' is free for v in t.
An example of this rule is that (Ax x + y).(y + I) = (y + I) + y.
Ignoring the side condition for fJ conversion is a common error in manipulating
lambda terms. Consider as an example the term (Ax (J..y x.y. If we carry out
the fJ conversion without considering the side condition, we get (Ax (Ay x.y =
(J..y. y), i.e., the identity function, which is obviously wrong (we should get the
function that returns y for any argument). The free variable y has become bound
in the resulting expression. Thus, we cannot apply the fJ-conversion rule directly
to simplify this term.
The correct method is first to use a conversion to replace the bound variable y
with another variable z that does not occur elsewhere in the formula, and then
use fJ conversion and transitivity to establish the required result. In practice, a
conversion is a basic step that is usually applied directly to a subterm, without
further explanation.
The T/ conversion rule expresses that any term t : L --+ r can be written as an
abstraction of an application:
(T/ conversion)
I-- (J..v t.v) = t
v is not free in t.
An example of this rule is that (Ax (J..z z + y).x) = (Az z + y). We can
understand the T/ conversion rule as essentially stating that abstraction is the inverse
4.2. Derivations 73
4.2 Derivations
The format for deductions that we have given above shows the structure of the
argument quite clearly but is not suitable for writing larger deductions (either
deductions with many inference steps or deductions where the terms are large),
as should be evident from the proof of extensionality given here. We therefore
introduce an alternative format for writing deductions that scales up better and that
we choose as the main format for writing proofs throughout the rest of the book.
This format is based on a few simple notational conventions: writing inference
rules and deductions sideways with indentation to show hypothesis and subproofs,
using assumptions with scope to avoid repeating the same assumption over and
over again in a deduction, and identifying the special role that transitivity and
substitution play in deductions. We refer to deductions in the format we propose
t'
where we assume that the subdeductions D\, D2, ... , Dm are also written sideways
in the same way. Thus, rather than presenting the deduction as an upward-growing
tree, we present it as a nested outline structure, with subdeductions shown as
indented deductions.
This format contains exactly the same information as the usual format, but the
information is arranged in a different way. Each part of the conclusion (the as-
sumption, the first term, the equality symbol, and the second term) is written on a
line of its own. The equality symbol is decorated with the name of the rule. The
subdeductions are written indented one step to the right (each one marked with a
bullet.). We add a small dot in front of the second term when necessary to show
the nesting more clearly. This dot has no semantic meaning.
In most cases the hypotheses have the same assumptions as the conclusion in an
inference. In such cases, the assumptions in the hypotheses are omitted, to make
the proof more concise. If a hypothesis adds some formulas to the assumptions
of the conclusion, then only the added assumptions are shown for the hypothesis,
within square brackets (examples of this will be shown in later chapters). In both
cases, the turnstile symbol I- is omitted. The turnstile symbol is used only when
we want to list the exact set of assumptions that are made for a hypothesis (thus
overriding the present scoping assumption).
On the abstract level of an inference rule, where a single symbol cl> is used for the
assumptions, this may seem like a small gain. However, in real proofs the assump-
tions may be very large formulas, and the gain is considerable. Most repetitions of
assumptions are implicit with this convention, and the proof is compressed con-
siderably. The convention is quite intuitive in the sideways format, where we can
4.2. Derivations 75
think of the assumption as having a scope that covers all nested subderivations
(unless the implied assumptions are explicitly replaced by a new set of assump-
tions, marked by the turnstile symbol). An assumption in square brackets adds a
new assumption to the assumptions already in force, so it is a local assumption.
The real advantage of the notational conventions above come when we also permit
inference steps to be strung together by transitivity. Consider the following proof:
where DDI, DD2,.'.' DDm are the subdeductions for each inference step (so
each DDi is a list of subdeductions Di.I. ... , Di.n). Note that the assumptions
c(> are the same in each hypothesis. We write this proof in the sideways format as
follows:
c(>
I- to
={Rd
DDI
tl
= {R 2 }
DDz
tz
tm-I
= {Rm}
DDm
tm
Example: Extensionality
The proof of extensionality is as follows when written as a derivation. The hypoth-
esis is <I> f- t.V = I'.V (recall that we assumed that v is not free in <1>, t, or I'). We
have that
<I>
f- I
= (TJ conversion; side condition satisfied by assumption}
(AV t.v)
= (abstraction, v not free in <I>}
I.v
= (hypothesis}
I'.V
(AV t'.V)
= (TJ conversion; side condition satisfied by assumption}
t'
<I>
f- t
= (1/ conversion; side condition satisfied by assumption}
(AV" t.V ")
= {abstraction, v not free in <1>, hypothesis}
(AV t'.V)
= (1/ conversion; side condition satisfied by assumption}
t'
4.3. Definitions 77
The derivational proofformat shows the proofs of hypotheses in-line, indented one
step to the right. This works as long as the indented proof is short. Deeply nested or
long subproofs make the derivation difficult to follow. It is then better to make the
proof of the hypothesis into a separate lemma that is proved either before or after
the main proof. Alternatively, one can use a word processor with an outliner to
construct the derivations. The outliner permits nested derivations to be hidden and
shown as required and thus allows a better overall view of the whole derivation.
An even better alternative is to have a proof editor with outlining capabilities, so
that the correctness of the inference steps can also be checked mechanically.
4.3 Definitions
The most secure way of extending a theory is to define new constants explicitly. This
is a conservative extension, so the consistency of the extended theory is guaranteed.
We describe this method of extending a theory below, together with another simple
mechanism, the use of local definitions.
Constant Definition
A new constant can be added to a theory by giving an (explicit) constant definition
of the form
A
C = t, (constant definition)
where t is a closed term. The definition adds the new constant c to the signature,
and the new axiom
I- c = t
to the inference rules. Explicit constant definition is a conservative extension, since
the added constant c has the same denotation as the term t. This means that any
proof that uses the constant c can be rewritten as an equally valid proof that uses t
instead of c.
An example of an explicitly defined constant is the function composition operator
o (written infix). It is typed as
o : (r --+ M --+ (1: --+ r) --+ (1: --+ M ,
and its definition is
Abbreviations
An alternative way of introducing new constructs into the logic is by using syntactic
sugaring, or abbreviations. The syntax of higher-order logic is very terse; this
makes the logic conceptually simple, but tenns can be difficult to read. We can
increase readability by introducing conventions that allow us to write terms in
a new way. This does not extend the signature; it merely adds a layer of "pretty-
printing" on top of the logic. This layer is very shallow; it is always possible to strip
it away and work with the underlying pure terms if one wants to do that. However,
by also stating inference rules in the sugared syntax, we can actually work on the
abbreviation level all the time, forgetting completely about the pure syntax. We use
4.3. Definitions 79
Local Definitions
A very useful example of syntactic sugaring is local definitions. We define the
following abbreviation:
A typical useful property that can be expressed nicely in this syntax is the following:
(vacuous let)
I- (let v = I' in I) =I
v not free in t.
The let construct is useful for introducing temporary (local) names for subterms
inside a term. This makes it possible to structure terms in a way that makes them
easier to read.
f.(x, y) = x +Y .
Here (x, y) is an element of the Cartesian product type Nat x Nat, and f itself
is of the type Nat x Nat _ Nat. In the second approach (currying), we write the
function as
f.x.y = x+y.
In this case, f is of the type Nat _ Nat _ Nat. This approach uses higher-order
functions in an essential way: f.x is a function of type Nat _ Nat. The advantage
of currying is that we can also talk about functions for which only part of the
arguments are given; e.g., f.x stands for the function (Ay x + y) : Nat - Nat.
This is useful in many situations, as we will notice, so we will in general prefer
currying for functions with many arguments. However, the other approach also has
its merits, as will also become evident later on.
We extend the type structure of higher-order logic with product types, which stand
for Cartesian products of types. Product types are added to higher-order logic in
the form of a binary type operator x (written infix). The operator x associates to
the right, so :EJ x :E2 X :E3 abbreviates :EJ x (:E2 x :E3) (so a triple is really a
nested pair). We also assume that the product constructor binds more strongly than
the function constructor, so :E _ r x t1 stands for :E - (r x t1). The product
type :E J x :E2 stands for the Cartesian product of the sets denoted by :EJ and :E2.
Thus Nat x Nat _ Nat x Nat denotes functions on pairs of natural numbers.
In order to make use of products, we extend the logic with three new constants.
Elements of the product :E x r are constructed using the pairing function (pair:
4.4. Product Type 81
r
E -+ -+ E x n.
In addition, we introduce projections (1st: E x -+ E and r
snd: E x r -+ n.
We use an infix comma for pairing, writing t, t' for pair.t.t'.
We postulate the following properties for the product operations:
The first three axioms state that pairing and projections are inverses of each other.
The last one states that pairing is a congruence and that equality on pairs is uniquely
determined by equality on its components. We assume that pairing associates to
the right, so that (t, t', til) stands for (t, (t', til.
where w is an arbitrary variable that does not occur free in t. Since the syntax
of higher-order logic does not allow paired abstraction, this is syntactic sugar;
we can write terms with paired abstraction, but such a term always stands for a
corresponding term in the basic syntax. The definition may not seem to be unique,
but the a-conversion rule shows that it does not matter how we choose w.
The paired abstraction (Au, v t) introduces names for the components of the
product, which can then be used inside the term, thus considerably simplifying the
term. An example of paired abstraction is the function
which maps pairs (n, n') of numbers to the number n + n'.1t is convenient to write
this expression as (An, n' : Nat n + n'); i.e., the type indication is given only once
for the preceding list of bound variables. Without paired abstraction we would have
to write this term as (Ax: Nat x Nat Ist.x + snd.x).
The conversion rules (a, p, and '1 conversion) can be generalized to paired abstrac-
tions. Thus, we have the following:
82 4. Functions
<l> I- (AU, V' t).(tl' t2) = t[u, v := tl, t2] ({3 conversion)
tl is free for U and t2 for v in t,
The rules above are easily justified using the basic conversion rules. For example,
paired {3 conversion is justified as follows:
<l>
I- (AU, v t).(tl' t2)
= {definition of paired abstraction syntax}
(AW' t[u, v:= fst.w, snd.w]).(tl, t2)
= {{3-conversion}
t[u, v:= fst.w, snd.wj(w:= (II, t2)]
= {properties of substitution; w not free in t}
t[u, v := fSt.(tl' t2), snd.(tl, t2)]
= {properties of projections}
t[u, v := tl, t21
the general rules of the simply typed lambda calculus, also due to Church [48]. An
overview of various lambda calculi is given by Henk Barendregt [37].
We have introduced derivations as an alternative format for writing proofs. This for-
mat is based on a few simple observations that permit a one-to-one correspondence
to be established between proofs in the style of natural deduction and derivational
proofs. This derivational style is used for proofs throughout the rest of the book.
Derivations as described here are inspired by the calculational proofformat intro-
duced by van Gasteren, Dijkstra, and Wim Feijen and advocated by many computer
scientists [54, 66, 60]. Although similar in spirit to their proof style, our approach
differs in some important aspects from theirs. The basic underlying framework that
we use is a sequent formulation of natural deduction for higher-order logic, while
their proof style is based on Hilbert-style proofs. They combine the proof steps
with a pointwise extended ordering relation, whereas we permit only simple order-
ing relations between proof steps. We also allow nested derivations in the proof.
Nested calculational proofs have been proposed by, e.g., Jan van de Snepscheut,
who suggested embedding calculational proofs within the comment brackets [131].
The approach taken here is more direct, in that the derivations are directly given in
a nested (outline) format.
The use of nested derivations is a big advantage when the terms become larger.
This is the case with program derivations, where the terms are program statements.
The proof style developed here also lends itself quite nicely to machine-supported
presentation, browsing, and construction of proofs. Work in this direction has been
done by Jim Grundy and Thomas Ungbacka [70].
4.6 Exercises
4.1 Write the proof of the rule "Substitute equals for equals" as a linear derivation.
4.2 Derive the rules of operator and operand congruence from the rule for replacing
equals for equals.
4.3 Derive the transitivity rule for equality using only the substitution rule.
4.4 Derive the rule of 1]-conversion using other rules given in this chapter.
4.5 Show that the function composition operation 0 is associative.
4.6 Derive the inference rules given for the let construct.
4.7 We define the constant twice by
(b) Simplify (twice 0 twice).(J..x x + 2).3 (note that this is not a case of self-
application).
4.8 Define three constants (known as combinators) as follows:
I.x x ,
S.f.g.x = f.x.(g.x) ,
K.x.y = x .
f- s + (t + u) = (s + t) + u '
f- s+e=s '
f- s + inv.s = e '
<l>f-s+t=e
<I> f- t = inv.s
Prove f- inv.(s + t) = inv.t + inv.s by a derivation.
5___________________________________
A morphism thus maps states to states. In this case, the two arrow notations f :
~ -+ r (function) and ~ ~ r (morphism) stand for the same thing.
A state transformer category is determined by a collection oftypes (state spaces) and
a collection of state transformers that includes the identity state transformers on the
state spaces. In addition, we require that the composition of two state transformers
in the category be again a state transformer in the category.
In particular, let Tranx be the state transformer category where the collection X
of types forms the objects (state spaces) in the category and the morphisms are
defined by
A sequence of updates to a state a, with XI first set to ai, then X2 set to a2, ,
Xm set to am, is described in terms of forward composition as set.xI.al) ...
(set.xm.am.a. In the category of state transformers, this is written as (set.xI.al ;
... ; set.xm.am).CT. We prefer the latter notation for composing state transformers.
Consider an attribute x. Setting this attribute to a specific value and then accessing
the attribute should yield the same value; i.e.,
val.x.(set.x.a.CT) = a. (a)
We also expect that the attributes can be set independently of each other. In partic-
ular, this means that setting the value of an attribute X does not change the value
of attribute y when X =f:. Y :
Next, an attribute can record only one value, so if we set the value of the attribute
twice in succession, then only the last value is stored. This can be captured by the
requirement
Also, the order in which two different attributes are set should not matter, so we
require that
Finally, we expect that setting an attribute to the value it already has does not
change the state:
Distinct attributes XI, ... ,Xn are called program variables if they satisfy these
independence requirements for any choice of X and y as two different attributes Xi
and X j in this list. The independence requirements essentially state the properties
of an abstract memory with independent locations for storing values, where each
location is associated with a specific type.
We often use a single name for a list of distinct state attributes, X = XI, ... , x m
Property (d) shows that it makes sense to write set.x.a.a if a is a correspond-
ing list of values. Similarly, val.x.a can be used to stand for the list of values
val.xI.a, ... , val.xm.CT.
We can use these properties to determine the value of a program variable in a given
state. For instance, assume that we first set XI to 3, then X2 to 5, and then finally set
88 5. States and State Transformers
Since we have postulated properties for state attributes, we need to show that they
have a model. To show that the properties for a collection Xl : Ll, ... , Xm : Lm
of attributes is consistent, it is sufficient to consider the model where L = Ll X
... x Lm is the state space and Xi is the ith projection function on L. Furthermore,
it is possible to show that the properties are complete with respect to this model,
in the sense that any state change in L can be described as a sequence of state
changes using update functions set.xi (in fact, in a normal form where no attribute
is updated more than once), and any state function f : L ~ 11 can be described
as a function over the access functions.
Expressions
A central use of program variables is in assignment statements like X := X + y.
Intuitively, this says that (the value of) program variable X is changed to the sum
of (the values of) program variables X and y. In terms of attributes, this means
that the state 0' is changed by setting the attribute X to a new value a, where
a = val.x.O' + val. Y.O'. The value a depends on the state 0' , so the expression X + y
is a function from states to values.
An expression e on state space L is determined by the following grammar:
<i.a 0
La
(-.:... !I).a -(/J.a)
(fl + h)a (f).a) + (ha)
This expression contains two access functions, gl and g2; the pointwise-extended
variable z; the pointwise-extended constant i; and two pointwise-extended binary
+
operations, and -.:....
The access functions that we use in an expression on I:: are the access functions of
the attributes that we assume for the state space I::. Thus, if we assume that I:: has
attributes XI, ... , X m , then the access functions for I:: are val.xI, ... , val.x m The
expression would then be written as
(val.xI - 1) + (val.x2 + z) ,
90 5. States and State Transformers
assuming that gl and g2 are the access functions of attributes XI and X2. In practice, it
is cumbersome to indicate the access of each attribute explicitly. Most programming
languages therefore have the convention that the attribute name also stands for the
access function of the attribute. We follow this convention by postulating that for
any attribute X we also have an access function with the same name X (both will
usually be assumed to be variables) such that
X = val.x. (I)
Note that on the left-hand side we have X : ~ -+ r and on the right-hand side
x : (~ -+ r) x (r -+ ~ -+ ~), so the two variables have the same name but
different types; hence they are two different variables. We will choose this as our
last assumption about program variables.
With assumption (I), we can finally write the expression in a standard form, as it
would be written in most imperative programming languages:
(XI - 1) + (X2 + z) .
We will assume that expressions are written in this way, using access functions X
directly, rather than going via the attributes (vaI.x).
As expressions are just ordinary terms of higher-order logic, we can prove prop-
erties of expressions in the usual way. As an example, consider proving that
(x + y) - y = x. We have that
(x + y) - y
= {71-conversion}
(Au x + y) - y).u)
= {pointwise extension}
(Au (x.u + y.u) - y.u)
= {arithmetic}
(Au x.u)
= {71-conversion}
x
Note that the justification "arithmetic" is used for an equality of the form (a +
b) - b = a, on the level of natural numbers, while the equality that we prove has
the same form but on the level of expressions. In Chapter 8 we will show how this
kind of proof is generally done in a single step.
Assignment
The update operation is a simple form of assignment, where an explicit value is
assigned to an attribute (used as a program variable). More generally, we want to
5.3. Reasoning with Program Variables 91
(x:= x) = id.
Properties (a)-(d) allow us to prove a result like (x := a) ; (x := x) = (x := a),
showing that an assignment of the value of an attribute to the same attribute is
the identity function if the component has been assigned a value at least once.
However, we cannot deduce (x := x) = id from the other properties, Le., that the
same assignment is an identity also when it is the first assignment to the component
(Exercise 5.2).
The assignment is easily generalized to permit an assignment to a list of attributes,
so called multiple assignment:
(a) for attribute x, Pb.x.y for assumption (b) for x and y, and so on. We write
for the set of properties assumed to hold for program variables Xl, .. , X m More
precisely, this set consists of the assumptions
We establish a property like t = t', where t and t' are two expressions or two state
transformers in program variables Xl, . ,Xm , by proving that
var XJ, , Xm I- t = t' .
Thus, in proving the equality of the two terms, we may assume that the indepen-
dence assumptions hold for attributes Xl, . , Xm that occur in the terms.
Higher-order logic is monotonic, in the sense that adding assumptions to a theorem
(sequent) produces a new theorem. This is reflected in the inference rule
<I> I- t
<1>, t f I- t .
In the context of program variables, this means that if we have proved a property
like t = t' for program variables Xl, , X m , then this property will hold also if
we assume that there are more program variables on the state. In other words, we
have
Another simple inference rule that we need when reasoning about program vari-
ables is the following:
Substitution Property
The following result (the substitution lemma) turns out to be of central importance
to reasoning about programs with attributes and expressions.
Theorem 5.1 Assume that x and y are state attributes. Furthermore, assume that e and I are
expressions over x, y, both 01 the same type as x. Then
var x, y I- e.x:= I).a) = e[x := !l.a .
Note that on the left-hand side we have the assignment operation x := I, defined by
(x := f).a = set.x.(j.a).a, while on the right-hand side we have a substitution,
where the term (expression) I is substituted for variable x in the term (expression)
e. We can use substitution on the right-hand side, because x is an access function,
i.e., a variable (of function type).
Proof The proof is by structural induction. First, assume that e is just an attribute.
If e is access function x, then we have
x . (set.x .(j.a ).a )
= {attribute properties (a), (t)}
Ia
= {property of substitution}
x[x:= !l.a
If e is an attribute y that is different from x, then we have
y. (set.x .(j.a).a )
= {attribute properties (b), (O}
y.a
= {property of substitution}
y[x:= I].a
If e is a pointwise extended variable y, then we have
y.x := f).a)
= {definition of y}
y
= {definition of y}
y.a
= {y has no subterms}
y[x:= I].a
Finally, assume that e is an expression of the form g.e). .em, m ~ 0, where
eJ, ... , em are expressions, and that the theorem holds for e), ... , em (the induction
94 5. States and State Tra nsformers
This last case covers also the case when e is a constant, by choosing m = O. 0
Note that the assumptions in var x, y form a subset of var x, y, ZI, ... , Zm, for
any collection of additional attributes ZI, ... , Zm. Therefore, the proof will in fact
establish
for any collection of program variables that includes x, y. This is the monotonicity
principle that we already referred to above.
In fact, we can see the substitution lemma as stated in this form by considering
X : = f as a multiple assignment, with X = XI, ... , Xm and f = /J, ... , fm. From
now on, we let X := e stand for a multiple assignment, unless we explicitly state
that X is a single attribute.
Proof We prove the result for the case when x is a single attribute; the general
case is proved in the same way.
x := e) ; (x := f).a
= {definition of function composition}
(x := f).x := e).a)
= {definition of assignment}
set.x.(f.x := e).a.x := e).a)
= {definition of assignment}
set.x.(f.x := e).a.(set.x.(e.a).a)
= {attribute property (c)}
set.x.(f.x := e).a.a
= {substitution lemma}
set.x.(f[x := e).a).a
= {definition of assignment}
(x := f[x := e]).a
o
Theorem 5.3 requires that the two assignments be compatible, in the sense that
they update exactly the same variables. The following lemma shows how we can
make two assignments compatible.
96 5. States and State Transformers
Lemma 5.4 Assume that x and yare disjoint lists of attributes. Then
var x, y I- (x:= e) = (y, x := y, e) .
(y, x := y, e).a
= {definition of multiple assignment}
(set.y.(y.a); sel.x.(e.a.a
= {definition of sequential composition}
sel.x.(e.a).(sel.y.(y.a).a)
= {attribute property (e)}
sel.x.(e.a).a
= {definition of assignment}
x :=e
Theorem 5.3 together with Lemma 5.4 can now be used to compute the sequential
composition of two arbitrary assignments. Assume, for example, that x, y, and z
are distinct attributes. Then
Immediate consequences of Theorem 5.3 are the following rules for independent
assignments:
Corollary 5.5 (a) Assume that x and yare disjoint (lists of) attributes. Then
We can use the framework built thus far to model straight-line programs, i.e.,
programs that perform only a sequence of successive changes to a state. These can
be defined by the following very simple grammar:
f ::= id I x := e I f1 ; fz .
Here x is a state attribute, e an expression, and f, f1' and fz straight-line programs.
Note that this definition does not introduce a new syntactic category. Instead, it
identifies a specific subclass of state transformers: those that can be constructed in
the manner described by the production rules.
Consider a simple straight-line program like
s = (x:= x + y) ; (y := x - y) ; (x := x - y) .
The attributes here are (at least) x and y. The type of these attributes determines
the state space of S. If x is an attribute on E, then S : E -+ E; if x is an
attribute on r, then S : r -+ r. The straight-line program itself is of exactly
the same form in both cases. We will in such cases say that S : E -+ E and
S : r -+ r are similar. Similarity captures the notion that two state transformers
expressed in terms of program variables are syntactically the same but may operate
on different underlying state spaces. Properties of S that are expressed in terms
of attributes of the state do not depend on whether the underlying state space is
E or r. This is the main advantage of using state attributes with expressions and
the assignment notation: we can prove properties that hold for the whole family of
similar statements, rather than establishing a property only for a specific statement
on a specific state space.
Alternatively, we can think of straight-line programs as being polymorphic. This
means that we consider the underlying type E as a type variable that can be
98 5. States and State Transformers
5.5 Procedures
Let us now also show how to extend the simple straight-line programs with a
procedure mechanism. This mechanism is quite simple and will be used as such
also for the more complicated program models that we will describe later on.
Let us write the state transformer for swapping the values of program variables x
and y in the previous section in full, without the abbreviations for assignments and
5.5. Procedures 99
This state transfonner will only swap the values of the program variables x and y.
We could define a function of more general use by defining a constant swap that
does what we want for any two attributes:
swap ~ (Ax y x := x + y ; y := x - y ; x := x - y) .
Then the application of this function to some other attributes a and b, of the same
type as x and y, is just
swap.a.b.
A simple calculation shows that
swap.a.b = (a:= a + b; b := a - b; a := a - b) .
Lambda abstraction and application are thus available for program variables just
as they are available for any other variables.
Let us compare this with the standard tenninology used in programming languages.
The swap function is actually aprocedure that can be used in straight-line programs.
The constant name swap is the procedure name, the attributes x and y that we have
used to define the constant are the formal parameters, and the tenn that we use to
define the constant is the procedure body. An application of the constant to other
variables, like swap.a.b, is known as aprocedure call, where a and b are the actual
parameters. The specific method for parameter passing that we get by the above
conventions is usually referred to as call by reference. Thus, the basic mechanisms
of higher-order logic already contain all the features that we need for defining a
procedure mechanism for straight-line programs. This same mechanism is also
applicable as such to define procedures in the more expressive program models
that we will study later on.
Aliasing
Assuming that we have shown property (*) for swap.x . y, what do we know about
the properties of, say, swap.a.a. In other words, what happens if we give the same
program variable a as actual parameter for both x and y? In programming logics
this is known as aliasing: two formal parameters are identified in the procedure
call.
The problem with aliasing is that the independence assumptions actually imply that
the program variables must be different attributes (provided that there is a state
attribute that can take two distinct values). To see this, assume that var x, y holds
and that in addition, val.x = val.y. Consider a state a, a state a' = set.x.1.a, and
a state a" = set.x.2.a'. Then
2
= {assumption (a)}
val.x.a"
= {assumption val.x = val.y}
val.y.a"
= {assumption (b)}
val.y.a'
= {assumptions val.x = val.y and (a)}
1
which is a contradiction. Therefore, x and y must be different attributes. In a similar
way, we can show that the assumption set.x = set.y also leads to a contradiction.
The property (*) thus implies that swap.x.y = (x, y := y, x) holds for any two
different attributes x and y that satisfy var x, y. This means that we know nothing
about swap.x.y when x and y are the same variable: the proof has established
property (*) only for the case when x and y are different.
Aliasing as such is not illegal or wrong. On the contrary, the procedure call swap.a.a
is a well-formed term that denotes a specific state transformer. We can even show
that var a f- swap.a.a = (a := 0) holds, but this requires a new proof; it cannot be
deduced from (*).
5.6. Blocks and Value Parameters 101
This means that we always have to apply a procedure with two or more formal
arguments to different program variables. This is known as the nonaliasing require-
ment for passing parameters by reference. In our context, it is a direct consequence
of the way we have formalized procedures with parameters.
Local Variables
Now assume that the state space 1: has program variables Xl, . ,Xm satisfying
the independence assumptions. Also assume that r is another state space with pro-
gram variables Xl, . , X m, Yl, .. ,Yn satisfying the independence assumptions.
102 5. States and State Transformers
!
r r
~I" r end
1:
1
1:
begin;!; end
Furthennore, assume that a state extension pair between E and r satisfies the
following properties:
Conditions (h), (j), and (k) state that there is a correspondence between the program
variable Xl, ,Xm on the two state spaces. Condition (I) states that a change in
Yj does not cause a change in the underlying global state, so the program variables
Yl, ... , Yn are local to r. These conditions are illustrated as commuting diagrams
in Figure 5.2. They generalize in a straightforward way to multiple assignments.
For reference, we write all the state attribute properties in the same fonnat and
collect them in Table 5.1.
x:= z y:= e
r .r r val.x r .r
end ~
1: 1:
~ end end
~>A
1: val.x
end~~
1:
x:= z
Let us introduce a special syntax for a block where these assumptions are satisfied:
where el, ... , em are expressions over the global state space I; (i.e., expressed in
terms of program variables Xl, , Xm). The initialization Yj := e j 0 end makes
the initial value of Yj the value of expression e j in the global state. The variables
Yl , ... , Yn are called local variables in the block.
One may wonder whether it is possible to define state attributes in such a way that
conditions (g)-(l) are satisfied. To see that this is indeed possible, assume that state
space I; is given, with program variables Xl, , X m By letting r be of the form
11 x I;, where 11 has program variables Yl, ... , Yn, we can define the attributes
over r in terms of the attributes over I; and 11 as follows:
Xi !;; Xi 0 snd ,
Yj !;; Yj 0 fst .
The conditions (g)-(l) are then satisfied when begin.a = (y', a) and end.y =
snd. y, for some arbitrary y' in r.
We permit local program variables to have the same name as global program
variables. In this case, the corresponding access and update functions inside the
block always refer to the local rather than the global attribute. This corresponds to a
redeclaration of a variable that hides the corresponding attribute of the global state,
making it inaccessible to the statement inside the block (except to the initialization).
This attribute is, of course, available as usual outside the block.
As an example consider the following state transformer:
begin var y, Z := X + Y, X - Y ; X := Y + Z ; v := X + vend;
v:= X +v .
Here the initial state space I; has program variables v, x, and Y (it may have other
program variables as well). The state transformer (x := Y + z) ; (v := X + v)
104 5. States and State Transformers
operates on a state space r that has program variables v, x, y, z, where v and x are
global and y and z are local. The local program variables y and z are initialized to
the values x + y and x - y, where x and y access the global program variables.
Note that the state transformer v := x + v inside the block is similar to but not the
same as the state transformer v := x + v outside the block. The state transformer
inside the block works on the extended state space of the block body, while the
state transformer outside the block works on the global state space. The state
attributes involved have the same names, but they have different domains. The use
of expressions and assignment notation allows us to ignore this difference when
writing programs. In most cases, this is a good convention, because the distinctions
between the two statements are not important. However, when reasoning about
general properties of statements in the refinement calculus, we need to keep this
distinction in mind. The distinction can always be made explicit by indicating the
types of the state attributes involved, so there is no confusion on the logical level,
where typing makes the two state transformer terms distinct.
The expression e that is used to initialize the value of the local program variable
may depend on the values of the global variables at block entry. A traditional block
initializes the local program variables to some fixed value, which mayor may not
be known. For instance, if y is of type Nat, then we may choose e to be some
arbitrary natural number, or we may choose e to be O. In either case, once the
convention is known, we do not need to indicate e explicitly in the syntax of the
block and can write the block simply as begin var y; fend.
x,y:=y,x
= {characterization of state extension pair, local variable z}
begin; "end" ; x, y := y, x
= (block property U)}
begin; z := x ; "end; x, y := y, x ..
= {properties (g) and (h)}
begin;" z := x; x, y := y, x"; end
= {assignment reasoning (Exercise 5.6)}
begin; z := x ; x := y ; y := z ; end
= {definition of block syntax}
beginvar z:= x;x:= y; y:= z end
5.6. Blocks and Value Parameters 105
Here the first three steps accomplish an instance of what can be seen as a general
principle of block introduction:
Value Parameters
Recall the definition of procedures in Section 5.5. In principle, we can get along
with just call by reference for procedures. In practice, other parameter-passing
mechanisms are also useful for procedures, and the block construct gives us a
way of handling these. The most important other mechanism is call by value. A
procedure declaration usually indicates for each parameter whether it should be
called by reference or called by value (or in some other way). Assume that we have
a procedure declaration of the form
proc/(var x, val y) = s .
Here we use standard notation, with var x indicating that parameter x is to be passed
by reference and val y indicating that y is to be passed by value. This procedure
declaration is seen as syntactic sugaring for the following definition of constant I:
f.x.y ~ s.
A call on the procedure I is assumed to be of the form I (u, e), where u is some
attribute and e an expression. This call is again seen as syntactic sugaring:
to this variable. We need to assume that no recursive calls on f are made within
the body of f, because straight-line programs are not expressive enough to model
recursive procedures. Recursive procedures will be treated in detail in Chapter 20.
let f = (Ax yo s) in
... begin var y' := e ; f.u.y' end
Here the dots ( ... ) surrounding the procedure call indicate that the call is part
of a state transformer. We choose y' such that there is no name clash with u.
The difference, compared with global procedures, is that f is now not a constant
but a variable that has a local meaning inside the body of the let construct. The
definition shows a body with only a single procedure call, but statements with
multiple procedure calls work in exactly the same way.
As an example consider the following state transformer:
proc Incr(var x, val y) = (x := x + y) in
Incr(a, a + b) ; b := 0
The following derivation shows what statement this is
proc Incr(var x, val y) = (x := x + y) in
Incr(a, a . b) ; b := 0
= {definition of procedure}
let Incr = (Ax y x := x + y) in
begin var y := a . b; Incr(a, y) end; b := 0
= {definition of let}
(Alncr' begin var y := a . b; Incr(a, y) end; b := O).(Ax y x := x + y)
= {tJ-conversion}
begin var y := a . b; (Ax y x := x + y).(a, y) end; b := 0
= {tJ-conversion}
begin var y := a . b ; a := a + y end; b := 0
5.7. Summary and Discussion 107
Note that this is exactly what the meaning of Incr(a, a + b) ; b := 0 would have
been if Incr had been defined as a global procedure (constant).
One advantage of local procedures is that we can focus on the body of a procedure
definition and rewrite it, since it is part of the term that we are transforming. For
example, we can use the results of earlier derivations as follows:
proc Swap(var x, y) = " (x, y := y, x) "in
Swap(a, b) ; Swap(c, d)
= {replace according to earlier derivation}
proc Swap(var x, y) = begin var z := x ; x := y; y := z end in
Swap(a, b) ; Swap(c, d)
5.8 Exercises
5.1 Show that the following property follows from the independence assumptions:
5.2 Show that the following property follows from the independence assumptions
(aHd):
(x := a) ; (x := x) = (x:= a) .
Verify informally that it is still not possible to prove (x := x) = id from the same
assumptions.
5.3 Assume a state space Nat where the two program variables b : Bool and x : Nat
are encoded as follows. For given state u : Nat we let val.b.u = even.u and
val.x.u = u div 2. Describe the operations set.b and set.x.
5.7 Assume that a function f : E --+ r is given. Show that f has a left (right) inverse
if and only if f is injective (surjective).
5.8 When computing a sum, a local variable can be used to collect intermediate sums.
Show the following equality:
varx,y,z,s I-
Y :=x+ y +z =
begin var s := 0; s := s + x; s := s + y ; s := s + z ; y := send.
5.9 Assume the following procedure definition:
Truth Values
(~ reflexive)
now states that ~ is reflexive. This inference rule may be taken as an axiom if
we want to postulate that the relation ~ is reflexive. Alternatively, it may also be
possible to derive it from other axioms and inference rules for the relation ~.
The collection of inference rules that hold for Boolean lattices are summarized in
Table 6.1. These inference rules are really schemes, where any concrete choice for
the constants ~, 1-, T, n, U, and -. gives a collection of inference rules stating that
these constants form a Boolean lattice.
T Bool , (true)
F Bool , (false)
Bool ~ Bool , (not)
::::} Bool ~ Bool ~ Bool , (implies)
/\ Bool~ Bool ~ Bool, (and)
V Bool ~ Bool ~ Bool . (or)
We prefer to use the symbol == (rather than =) for equality on Bool. We consider
t {= t' as an alternative way of writing t' ::::} t. The constants ::::}, /\, and V are
(exactly like = and ==) written infix and associate to the right. These constants are
all intended to have their traditional meanings.
The infix logical connectives have lower precedence than other infixes (e.g., arith-
metic operators and equality). Conjunction /\ has highest precedence, followed
by the operations v, ::::}, and ==, in that order. The precedence is overridden when
necessary by explicit parenthesis. Note that == and = are actually the same op-
eration on Bool, but they have different precedences. For a complete list of infix
precedences, see Appendix A.
Negation is a prefix operator. It has higher precedence than all infix operators
except for the function application dot.
Inference Rules
We postulate that the truth values form a Boolean lattice with implication ::::} as
the ordering relation. Falsity F is the bottom, truth T is the top, conjunction /\ is
meet, disjunction v is join, and negation......, is complement. This means that the
above-listed inference rules for Boolean lattices hold for the truth values. This
112 6. Truth Values
gives us the inference rules for truth values shown in Table 6.2.
The truth-value lattice has two additional properties that are special to it. The first
property is that it is linearly ordered. This is expressed by the following axiom:
The second property is that we identify truth with theoremhood. This is expressed
by the following axiom:
i='T . (truth)
deduction. However, we prefer to use derivations rather than deductions also for
reasoning about logical formulas in general. There is then one small problem. The
format requires that each proof step must be of the form t t; t', where t; is a
preorder. Only equality and implication are of this form. How should we give a
derivational proof for sequents of the form <I> I- t1 1\ t2 or <I> I- t1 V t2?
The following inference rule shows the way out of this dilemma. It essentially says
that stating a proposition is the same as stating that it is equivalent to the constant
T (which stands for truth):
I- t == (t == T) .
(== T rule)
Similarly, we have a rule that says that stating the negation of a proposition is the
same as stating that it is equivalent to the constant F (which thus stands for falsity):
I- -. t == (t == F) .
(== F rule)
The proofs of these rules are left as exercises to the reader (Exercise 6.1). The
proofs are rather long, involving antisymmetry of ==, substitution, and properties
ofT and F.
In fact, the following variations of these rules are also valid
(T ::::} rule)
I- t == (T::::} t) ,
(::::} F rule)
I- -. t == (t ::::} F) ,
, (TA rule)
f-TAt==t
, (TV rule)
f-Tvt==T
, (FA rule)
f-FAt==F
(Fv rule)
f-Fvt==t
Let us consider the first one of these, as an example of a simple derivational proof
in logic.
f- t
=} {A introduction}
t
=} {T greatest}
T
t
=} {reflexivity}
TAt
This establishes that I- t =} TAt. The opposite implication (T /\ t =} t) is an
instance of A elimination, so TAt == t follows by antisymmetry.
Two-Valued Logic
Another important property is that there are exactly two truth values. This is stated
by the following inference rule:
(Boolean cases)
I- (t == T) V (t == F) .
Higher-order logic is thus a two-valued logic. We prove this rule with a derivation,
rewriting the goal in the form f- T == (t == T) v (t == F). The following derivation
establishes the theorem:
I- (t == T) v (" t == F ")
6.4. Quantification 115
== {substitution; == F rule}
(t == T) v .... t
== {substitution; == T rule}
(t == T) v .... (1 == T)
== {exhaustiveness}
T
Modus Ponens
The modus ponens rule is the following:
<I> U <1>'
I-T
=? {T =? rule; first hypothesis}
t
=? {second hypothesis}
t'
The derivation establishes <I> U <1>' I- T =? t', from which the required result follows
by the T =? rule.
6.4 Quantification
The inference rules postulated above formalize propositional logic, but forquantifi-
cation we need additional constants and inference rules. We introduce the following
operations for quantification:
Following standard practice, we use binder notation for quantifiers, writing 0/v' t)
forV.(Av t) and (3v' t) for3.(Av t). This notation has the same (low) precedence
as A-abstraction.
0/ introduction)
<I> I- s 0/v t)
=}
v not free in s or <1>.
General meet elimination gives us the elimination rule for universal quantification:
0/ elimination)
I- 0/v' t) =} t[v := t f ]
t f is free for v in t.
(3 introduction)
I- t[v := t'] => (3v t)
t ' is free for v in t.
(3 elimination)
<1> I- (3v t) => s
v not free in s or <1>.
Again, the hypothesis in the elimination rule states that t => s holds for every value
of v in 1: (because v is not free in s or in <1.
The introduction rule simply states that if we have proved a property for some
element (denoted by a term t'), then there exists a v such that the property holds.
The elimination rule again says that if we are able to prove that s follows from t
without making any assumptions about which value is chosen for v, then the mere
existence of some value v that makes t true implies s.
The lattice-theoretic arguments for the introduction and elimination rules should
be seen as arguments for the validity of these rules. Formally, we need to postulate
the quantifier introduction and elimination rules above for the truth values 8001,
because they cannot be derived from the other rules that have been postulated
for truth values. Table 6.3 shows some other useful inference rules for reasoning
about quantified formulas, which are derivable from the basic introduction and
elimination rules that we have presented here.
We also define the exists-unique quantifier 3! by
Bounded Quantification
The scope of the bound variable in a universal or existential quantification can
be restricted to satisfy some additional condition b. The bounded universal and
existential quantification is defined by
(de Morgan)
6.5 Assumptions
A sequent <I> I- t states that t follows from <1>. Hence, assumptions and implication
are closely related. In fact, we can consider assumptions as just a convenient device
for working with implications.
The two basic rules for handling assumptions show how we can move the left -hand
side of an implication into the assumption and vice versa:
<1>, t I- t'
(discharge)
<l>l-t=>t' ,
The first rule is also known as the deduction theorem (following standard practice,
we write <1>, t for <I> U {t} in inference rules). Together these two rules show that
assumptions and sequents are just a variant of implication, and that we can move
between these two representations quite freely. However, it is important to note
the difference between an inference and an implication. For example, the rule of
generalization allows us to infer I- ("Ix t) from I- t, but the implication t '* (Vx t)
is generally not a theorem.
Derived Rules
We exemplify the above rules of inference by using them in the derivation of some
further rules that are useful in practice.
The first inference rule says that we may always conclude a formula that is taken
as an assumption:
(assume)
<I>,tl-t
This rule is a direct consequence of the reflexivity of implication and undischarging:
----::---:----
{'* reflexivity}
_<I>_I-_t_'*--'-t-:--:-_____ {undischarge} .
<I>,tl-t
The following inference rule formalizes the basic method of splitting up a proof of
a theorem t' into a subproof where a lemma t is proved first and then later used to
prove the main theorem:
t
::::} {undischarge in hypothesis 4>, t I- tf}
tf
-.t
::::} {undischarge in hypothesis 4>f, -. t I- t f }
tf
tf
Here we have a derivation with a mix of == and::::}, and the conclusion is then that
T ::::} tf. In general, we can mix relations in a derivation, and the overall conclusion
then states that the initial and the final terms are related by the composition of the
relations involved. Composition of relations will be treated formally in Chapter 9.
Here it is sufficient to note that a composition of::::} and == is ::::}.
4> I- t
(add assumption)
4>, t f I- t
4>, s I- t
(change free variables)
4>, s[x := Xf] I- t[x := Xf]
x is not free in 4>, Xf free for x in sand t.
This follows from the inference rules for assumption discharging and undischarg-
ing, together with the rules for introduction and elimination of universal quantifi-
cation.
cI>, t f- t1 == t2
This rule shows that when we focus on one conjunct t1 of a Boolean term t 1\ t1, we
may use t as an additional assumption in the subderivation. A dual rule shows that
when focusing on a disjunct we may assume the negation of the other disjunct:
cI>, ~t f- t1 == t2
cI> f- t V t1 == t V t2
Using the fact that implication can be rewritten using negation and disjunction, we
immediately get rules for focusing on the subterms of an implication:
cI>, t f- t1 == t2
cI> f- t :::} t1 = t :::} t2 ' cI> f- t1 :::} t == t2 :::} t
The following small example shows how local assumptions are used in proofs. We
prove the tautology
The derivation illustrates the rule for focusing on the consequent of an implication.
Thus. we can focus on the subterm t in f.t and work with the partial order in the
subderivation. Here the partial order can be arbitrary (including =* and {:::: on truth
values). Furthermore. it can be shown that the rules for local assumptions are valid
also when working with =* or {:::: rather than == (Exercise 6.7).
Since the quantifiers are monotonic with respect to implication (and reverse impli-
cation). it is possible to focus inside quantifiers. However. it should be noted that
if we focus on t in an expression (Ov t) (where 0 is a quantifier or a binder).
then no assumptions involving the variable v are available. since the subterm t is
not within the scope of that variable v. This problem can always be avoided by
a-converting the expression so that v is replaced by a fresh variable (by afresh
variable we mean a variable that does not appear free in any of the terms that we
are currently considering).
Note that in the case of antimonotonic functions (such as negation on truth values)
the subderivation works with the ordering in the opposite direction to the main
derivation.
As an example. we prove one-half of the one-point rule for the existential quantifier:
(in the last step we use another quantifier rule. see Exercise 6.8).
Here we have skipped the details of the subderivation, where we focus both inside
a quantifier and inside a conjunction. Since the conjunction is within the scope of
the bound variable v. we may use the assumption v = t in the subderivation.
6.7. Summary and Discussion 123
This derivation also illustrates (in the step justified by /\ elimination) how we do a
replacement in a single step, rather than starting a subderivation that would make
the proof unnecessarily long.
In practice, we can omit some of the intermediate steps of a derivation like this and
simply introduce the procedure in one step and the calls to it in another step.
proofs and proofs in the style of natural deduction. The derivations that we give
here generalize the traditional calculational style in that they pennit manipulation
of assumptions inside proofs and permit nested derivations.
Andrews' textbook [3] gives a comprehensive overview of type theory and higher-
order logic. The version of higher-order logic that we describe in this book is closer
to the version underlying the interactive theorem-proving system HOL [62]. The
main difference is that we do not have polymorphic types and that we have chosen
a different set of basic axioms and inference rules for the logical operations. For
more detailed description and analysis of the semantics of higher-order logic, we
refer to these same authors.
Both Andrews and Gordon and Melham attempt to fonnalize higher-order logic
with as few constants and inference rules as possible and define most of the logical
constants explicitly in tenns of the few postulated constants. Gordon and Melham
choose as primitive inference rules (variants of) assume, reflexivity of equality,
a and fJ conversion, substitution, abstraction, discharge, and modus ponens plus
a rule of type instantiation. In addition, they have five axioms: Boolean cases,
antisymmetry of implication, T/ conversion, introduction, and infinity (we will
meet the last two of these in the next chapter). Andrews has a slightly different
collection of axioms and inference rules for higher-order logic.
We have here presented an alternative, lattice-based fonnalization of higher-order
logic. The correspondence between lattice theory and logic is well known and
old, dating back to George Boole in the nineteenth century. The advantage of
fonnalizing higher-order logic in this way is that we can build a single collection
of inference rules that are applicable across a large range of different domains, from
reasoning about logical tenns and sets to refinement of program statements and
large modular systems. This cuts down on the conceptual overhead that is needed
in program construction and clearly identifies the common patterns of reasoning
in the different domains of discourse.
The idea of using focusing and subderivations in posets (and generally in structures
other than Bool) builds on the refinement diagrams of Back [16], the hierarchical
reasoning method of Robinson and John Staples [122] (window inference), and
Grundy's extension to this method [68, 69].
6.8 Exercises
6.1 Prove the == T and == F rules using only the general rules of higher-order logic and
the basic inference rules for truth values.
6.2 Prove that meet and join in a lattice are commutative, using only antisymmetry and
the introduction, elimination, and distributivity rules for meet and join.
6.8. Exercises 125
using only rules given in this chapter (hint: use case analysis; first prove I- ...., T == F
and I- ...., F == T).
6.5 Prove that implication can be expressed with negation and disjunction:
I- 1 => l' == ...., t V t' .
6.6 Prove the rule for focusing on a conjunct:
ct>, t I- t\ == t2
ct> I- 1 /\ 1\ = 1 /\ 12
(hint: do case analysis on 1).
6.7 Prove the rule for focusing on a conjunct under implication:
ct>, t I- 1\ => t2
ct> I- 1 /\ 1\ => 1 /\ 12 .
Then formulate and prove the corresponding rules for disjunction and implication.
6.S Derive the rules for dropping vacuous quantifications:
I- (Vv 1) == t I- (3v 1) == 1
v not free in 1, v not free in 1.
6.9 Derive the one-point rule for universal quantification:
I- (Vv v = 1 => t') == t'[v := 1]
v not free in t.
6.10 Derive the rules for focusing inside let expressions.
7---------------------------------
Predicates and Sets
p A : E -+ Bool satisfying p A.(1 == Tif and only if (1 EA. Thus, we have two ways
of describing sets, either using the traditional set-theoretic framework or using
functions that range over truth values.
The pointwise extension of the implication ordering on Bool gives us an ordering
of predicates:
The operations on predicates are inherited from the operations on truth values, and
so is the naming of these operations: false is the identically false predicate and true
the identically true predicate. Predicate meet is referred to as conjunction of predi-
cates, predicate join is called disjunction of predicates, and predicate complement
is called negation of a predicate.
Implication and equivalence on predicates are also defined pointwise, by
p = q == CVa (p == q).a) .
Sets as Predicates
The predicate ordering coincides with subset inclusion: A B if and only if
PA PB. Predicate false corresponds to the empty set, pVJ = false, and predicate
true corresponds to the universal set, Pr. = true. Meet (or conjunction) of predicates
is intersection: a E A n B if and only if (PAn p B).a == T, and similarly, join (or
disjunction) of predicates is union, and complement (negation) of predicates is set
complement.
The traditional set-theoretic notation is introduced as an abbreviation in higher-
order logic:
7.1. Predicates and Sets 129
Properties of Predicates
The general properties for Boolean lattices hold for predicates. For instance, ~ is
a partial ordering, so the transitivity rule holds,
== {definition of inclusion}
(Va A.a => A.a)
== {reflexivity of =>}
(Va T)
== {drop vacuous quantification}
T
A~BI\B~C
== {definition of inclusion}
(Va A.a =} B.a) 1\ (Va B.a =} C.a)
== {quantifier rule}
(Va (A.a =} B.a) 1\ (B.a =} C.a))
=} {transitivity of implication; monotonic context}
(Va A.a =} C.a)
== {definition of inclusion}
A~C
For a fixed f, the image im.f : 1'(I;) ~ 1'(r) is a function from one lattice to
another. Hence, we may ask about the homomorphism properties of this function.
These are easily established: the image is monotonic,
is ~ ..1 T n u ....,
im./ yes yes no no yes no
preim./ yes yes yes yes yes yes
()..a (ni E 1 a.i yes yes I yes yes no no
()..a (ui E I . a.i yes yes yes I no yes no
(AI (ni E 1 a.i yes O yes O yes O no yes O no
(AI (uj E 1 a.i yes yes yes no yes no
when mdex set I IS nonempty
im.f.0 0,
im.f.(A U A') im./.A U im.f.A ' .
For the preimage preim./ : P(f) --+ P(I.:), we have even stronger homomorphism
properties. The preimage is both bottom and top homomorphic, it is monotonic,
and it is meet and join homomorphic. It is even negation homomorphic. The ho-
momorphism properties of the image and preimage operation are summarized in
Table 7.1.
We have used the indexed set notation earlier in an informal way, in connection
with meets and joins of arbitrary sets in a poset. Let us now define it formally in
terms of images. The indexed set {a.j I j E I} is really a set image. For a : I.: --+ r
and 1 ~ I.:, we define
{t I j E l} ~ im.()..j t).1
for t a term of type r. The indexed set is thus determined by an index function
()..i t) and an index range 1. The index i itself is a bound variable. The traditional
notation {aj liE l} is also used as an alternative for {a.i liE l}.
similar to quantification, whereas binary meet and binary join are operations on
pairs of elements.
If the set is given as an index set {t liE I}, then we can use the indexed notation
for its meet and join. We define
(general n elimination)
t f Ell- (n i E 1 t) 1; t[i := tf]
t f is free for i in t,
(general U introduction)
t f Ell- t[i := tf] t; (u i E 1 t)
t f is free for i in t,
<1>, i Ell- t 1; s
(general u elimination)
<I> I- (u i E 1 t) 1; s
i not free in s, <1>, or 1.
We can split up an index range into smaller sets using the following range split
property:
(n i E I U J a.i) = (n i E I a.i) n (n i E J a.i) , (range split)
(u i E I U J a.i) = (u i E I aj) u (u i E J a.i) .
These properties follow directly from the homomorphism properties of the meet,
join, and range operators. Thus, indexed joins are bottom and join homomorphic
onto r, while indexed meets are bottom and join homomorphism onto the dual
lattice roo These properties are summarized in Table 7.1.
I . t). Thus, bounded quantification is a special case of indexed meet and join,
and has properties that follow directly from the general properties by specializing.
In particular, the rules for introduction and elimination of bounded quantification
given in the previous chapter are instances of the general rules for indexed meets
and joins, as is easily shown.
The homomorphism properties for indexed meets and joins also hold for bounded
quantification. For example, universal quantification is antimonotonic, and exis-
tential quantification is monotonic in the index range:
<1>, i E I I- p ~ qi
(general n introduction)
<I> I- p ~ (n i E I qi)
i not free in p, <1>, or I.
Selection
We need to postulate one more constant to get the full power of higher-order logic.
This is the selection operator of type
( introduction)
<I> I- (3v t) => t[v := (V t)] ,
<l>l-t=>s
( elimination)
<I> I- t[v := (V t)] => s
v is not free in <I> or s.
The first rule states that if there is an element that makes t true, then ( V t) denotes
such an element. The second rule is justified in the same way as the 3 elimination
rule.
The selection operator allows us introduce a constant denoting an arbitrary element
for any type:
Since the selection operation is always defined, arb always returns some value.
However, we have no information about arb: L other than it is of type L.
Figure 7.1 illustrates the way in which this requirement forces the interpretation of
Ind to be infinite. For the finite set {O, 1,2, 3}, it is easy to see that there is no way
in which we can define a function on this set that is injective but not surjective.
However, for an infinite set {O, 1,2,3, ... }, the figure on the right-hand side gives
an example of a function that is injective but not surjective (0 is not in the range
of this function). In this case, the function illustrated is the successor function on
the natural numbers. Later we show how this idea can be used to define the natural
numbers as a set that is isomorphic to a subset of the individuals.
~4
3 3
3~3
2 2
2~2
o o O~:
FIGURE 7.1. Injective functions on finite and infinite sets
The remaining axioms and inference rules of higher-order logic were also pre-
sented. These axioms postulate that there exists an infinite set, and that we can
choose some element from any set. Individuals were introduced as a new stan-
dard type, in addition to Bool. In this respect, we give the same foundation for
higher-order logic as Andrews [3] and Gordon and Melham [62]. Church's orig-
inal formulation had an operator for definite description rather than the selection
operator [48].
7.7 Exercises
7.1 A set B over a type :E is really a function B : :E -+ Bool. This means that we can
talk about the image im.B.A of another set A under B. This image is a set of truth
values. Show the following:
(b) im.B.0 = 0 .
Under what condition is im.B.A = {F}? Under what condition is im.B.A = {F, T}?
7.2 Show that images and inverse images are related as follows:
im.j.U-1.y) ~ y and x ~ j-l.(im.j.X) .
7.3 Show that the complement ~ in a complete Boolean lattice is a bijective function.
7.4 The index-function homomorphism properties for lattices have counterparts for
bounded quantification. For example, image monotonicity for meets corresponds
to the following rule:
In the previous chapter we showed how to reason about predicates and sets in
general. In programming, predicates arise in two different disguises. First, they are
used to describe control structures with branching, like conditional statements and
loops. Second, they are used to express correctness conditions for programs. In
both cases, the predicates are expressed in terms of program variables, so they are
really Boolean expressions. In this chapter, we will look more closely at Boolean
expressions and at how to reason about their properties.
Let e be an expression. We define the base term e associated with the expression
e as follows:
XE--+rXr ,
y
= y,
.....------'-
j.g) .... gm fg) .. gm .
For Boolean expressions, we also define
(Vi E I b) = (Vi E I b) ,
(3i E I b) = (3i E I b).
For each expression e of type 1: .... r, this determines a term e of type r. For
instance, repeated rewriting using the definitions above gives
Proof Assume that the substitution x), ... ,Xm := XI.U, ... , Xm.U is written as
x := x.u. We prove this theorem scheme by induction over the structure of the
expression e. When e is the access function of attribute x, then we have that X.U =
x[x := x.u]. When e is y, we have that y.u = (Au' y).u = Y = y[x := x.u].
Consider next the case when e is an application i.el . ... .em. We then have that
j.el' ... .em.u
= {definition of pointwise extension}
f.(el.u)." . .(em.u)
= {induction hypothesis}
f.(el[x := x.u)). . (em [x := x.u))
= {property of substitution, f is a constant}
(f.el. .em)[x:= x.u]
The case when e is a quantified Boolean expression is proved in a similar way. 0
8.2. Reasoning About Boolean Expressions 141
Note that Lemma 8.1 states that a certain property holds for all expressions. Since
the property of being an expression is not defined inside higher-order logic, the
proof is necessary informal, in the sense that it is outside the logic. The rule in
Lemma 8.1 is a theorem scheme, and e is a metavariable that can be instantiated
to any expression (but not to an arbitrary term of higher-order logic).
Corollary 8.2 Let Xl, , Xm be the auributes of the Boolean expression b. Then
X::::y
= {set theory}
{a I (x :::: y).a}
= {Corollary S.2}
{a I 3x y x = x.a 1\ y = y.a 1\ " X :::: y "}
~ {focus on Boolean term}
X:::: y
=} {arithmetic}
x<y+2
{a I 3x y x = x.a 1\ y = y.a 1\ x < y + 2}
= {Corollary 8.2}
x<y+2
Notice how the corollary allows us to focus on proving an implication between
Boolean terms in order to establish inclusion between the Boolean expressions. In
the same way, we can establish equality of two Boolean expressions by proving
equivalence for their corresponding base terms. We refer to this way of establishing
inclusion or equality of a Boolean expression as reduction.
142 8. Boolean Expressions and Conditionals
In practice, this level of detail in a proof is unnecessary. We will omit the details
of the reduction in subsequent proofs. The above derivation is then
x~y
~ {reduction}
x ~ y
=> {arithmetic}
x<y+2
'x<y+2
The fact that the step is justified as a reduction signals that the inner derivation is
done on Boolean formulas and not on Boolean expressions. In simple cases like
this one, we will usually omit the nested derivation altogether and make implicit
use of reduction:
x~y
~ {arithmetic}
x<y+2
Here the use of ~ (rather than = shows that we are relating two Boolean
expressions rather than two Boolean terms.
Alternative Reduction
We can also reduce b ~ c directly to an implication between base terms, as shown
by the following lemma.
Lemma 8.3 Let band c be Boolean expressions, and let x = Xl. , Xm be the attributes that
occur in these. Then
(a) f-- (VXI'" Xm b => C) => b ~ c ,
(b) var Xl, ... ,Xm f-- (VXI'" Xm b => C) == b ~c .
Proof Let x := x.a stand for Xl, ... , Xm := Xl.a, ... , Xm.a. We have for (a) that
f-- (Vx\ .. ,Xm' b => c)
=> {specialization; a a fresh variable}
b[x := x.a] => c[x := x.a]
== {substitution property}
b.a => c.a
and the result then follows by generalization.
For (b), we also have to prove the reverse implication:
8.3. Conditional Expressions 143
I-bc
== {definition of inclusion}
("1(1' b.(1 ::::} c.(1)
== {substitution property}
("1(1. b[x := x.(1] ::::} c[x := x.(1])
::::} {specialize, (1' := (set.xI.xI ; ... ; set.xm .xm ).(1}
b[x := x.(1'] ::::} c[x := x.(1']
== {property of state attributes: Xi .(1' = Xi}
b::::}c
The result then follows by generalization, as the variables XI, ,xm are not free
in band c, nor in var XI, , X m 0
Conditionals
Let us define a new constant, the conditional cond : Bool --+ :E --+ :E --+ :E. The
intended meaning is that cond.t .t,.t2 is t, if t == T and t2 otherwise:
We can make the conditional operator more palatable by adding some syntactic
sugar:
Similarly as for let terms, the condition (or its negation) becomes a local assumption
when focusing on either branch of a conditional. This is justified by the following
rules:
<1>, I I-- I, ~ I;
<I> I-- (if 1 then I, else 12 fi) ~ (if I then 1; else 12 fi)
8.3. Conditional Expressions 145
and
II> f-- (if t then t( else t2 fi) ~ (if t then t( else t~ fi) ,
where ~ is an arbitrary relation.
Theorem 8.4 Let f, f', g, and g' be state transformers and b a predicate. Then
(if b then f else g fi) = (if b then f' else g' fi) -
b ~ (f = f') 1\ ...., b ~ (g = g/) .
This follows directly from the definitions and the inference rules for conditionals.
The condition b ~ (f = 1') is a kind of conditional equality. It says that the
functions f and f' have to have the same values in a state whenever the state
satisfies b.
We can identify a number of other useful equality rules for working with conditional
expressions and conditional state transformers.
Theorem 8.5 The following rules hold for conditional state functions:
Let us add conditional state transformers to the straight-line programs that we have
described earlier. The language is thus defined by the following syntax:
Pointwise Functionality
Any function / is a congruence with respect to equality; a = b implies that
/.a = /.b. In many cases, functionality is not sufficient, and we need a stronger
property. Let us say that a function / is pointwise functional if
8.4. Proving Properties About Conditional State Transformers 147
Lemma B.6 Let e and e' be two expressions and let h be another expression. Then
(x +y = z) x + y) * z = z * z) .
so the state transformers x := x max y and x := yare equal in those states where
x:::: y.
Sequential composition is pointwise functional in its first argument:
Example Proof
Let us illustrate these proof rules by showing that the little straight-line program
for computing the maximum of two program variables that we have given above
is correct, i.e., that it is the same state transformer as (x := x max y):
(x:= x max y)
= {conditional expression rule}
if x :::: y then (x := x max y) else (x := x max y) fi
= {equality of conditionals, generalization}
x:::: y
~ {derivation above}
(x := x max y) = (x := y)
x> y
~ {reduction and assignment property}
(x := x max y) = (x := x)
if x:::: y then x := y else" x := x "fi
= {property (e) of attributes}
if x :::: y then x := y else id fi
They take pointwise functionality (which they call punctuality) as the basic rule,
in combination with the everywhere operator [b], which corresponds to universal
quantification in our framework: [b] == (Va b.a). With these correspondences,
the laws for predicate expressions derived by Dijkstra and Scholten can be derived
in our framework too. The approach that we have chosen here is closer to traditional
logic, in that we compare Boolean expressions directly for inclusion or equality
and use the reduction theorem to move between reasoning on the predicate level
and reasoning on the truth-value level.
8.6 Exercises
8.1 Show that if tl and t2 are Boolean terms, then
Relations
Let us next look at how relations are handled in higher-order logic. Relations,like
predicates, form a complete Boolean lattice and thus have essentially the same
set of inference rules as predicates. We can define new operations on relations,
giving additional properties. In partiCUlar, relations combine a lattice and a category
structure. Relations also provide us with a more expressive way of describing state
changes, where the effect can be nondeterministic in some states and undefined in
other states.
Lattice of Relations
The relation space arises as a pointwise extension of the predicate space. For two
relations P, Q E E B- r, the partial ordering is defined by
Id.u.y ~ u = y , (identity)
(P _ Q).u ..5 ~ (3y P.U.y A Q.y ..5) . (composition)
As with functional composition, the range type of P must be the same as the
domain type of Q for the typing to be correct.
The inverse of relation R is R- 1, defined by
A special kind of state relation category is Rei x, which has all types in X as objects
and all relations between two objects as morphisms; i.e.,
Relx(1::, r) ~ 1:: ~ r .
We write Rei for Relx when the collection X of state spaces is not important. We
leave it to the reader to verify that Rei is indeed a category (Exercise 9.5), i.e., that
(P; Q) ; R = P ; (Q ; R) , (; associative)
Id ; R = R and R ; Id =R . (Id unit)
It is easy to see that composition is monotonic with respect to relation ordering:
P ~ pi A Q ~ Q' => P; Q ~ pi ; Q' . (; monotonic)
Composition does not, however, distribute over meets and not over top (Exercise
9.6).
We can construct relations from predicates and functions using coercion operations.
Let p : 1: --+ Bool and I : 1: --+ r. We define the test relation Ipi: 1: B- 1: and
the mapping relation III : 1: B- r, by
The test constructor I . I : 1'(1:) --+ Rel(1:, 1:) is easily seen to be monotonic. In
addition, it preserves bottom, positive meets and universal joins. However, it does
not preserve top or negation. Furthermore, we have the following properties:
Itruel Id,
Ipnql Ipl; Iql .
It is also easily checked that the mapping relation operator preserves identity and
sequential composition:
lidl Id,
I/;gl III; Igl .
is c 1. T n u ...., 1 ,
(Ap' Ipi) yes yes no yes yes no yes yes
CAt'lfl) yes - - - - - yes yes
(AR'dom.R) yes yes yes no yes no yes no
(AR ' ran.R) yes yes yes no yes no yes no
Partial Functions
A relation R : 1: B- r is said to be deterministic (or functional) if every a E 1: is
related to at most one y E r, i.e., if
Theorem 9.4 Assume that x is a list of program variables and that b and c are Boolean
expressions. Then
9.4. Relational Assignment 157
Proof We show the proof of case (d), for the case when x is a single state attribute.
The generalization to the case when x is a list of variables is straightforward.
(x := x' I b) :: (x := x' I c)
== {definition of ::, Lemma 9.3}
('Iu y' (3x' Y = set.x.x'.u /\ b.u) ::::} (3x' Y = set.x.x'.u /\ c.u
== {quantifier rules}
('Iu y x' y = set.x.x'.u /\ b.u ::::} (3x' Y = set.x.x'.u /\ c.u
== {one-point rule (rename captured variable)}
('Iu x' b.u ::::} (3x" set.x.x'.u = set.x.x".u /\ c[x' := x"].u
== {state attribute properties say set.x.x'.u = set.x.x".u == x' = x"}
(Vu x' b.u ::::} (3x" x' = x" /\ c[x' := x"].u
== {one-point rule}
(Vu x' b.u ::::} c.u)
== {pointwise extension}
('Ix' b :: c)
Cases (a)-(c) are proved in a similar style. 0
The rules for meet and join are easily extended to arbitrary meets and joins:
The rules in Theorem 9.4 require that the relational assignments involved all update
exactly the same variables. When reasoning about assignments that work on differ-
ent collections of variables, we can use the following rule to make the assignments
compatible:
Lemma 9.5 Assume that x and y are lists of program variables and that b is a Boolean
expression in which y' does not occur free. Then
var x, y f- (x:= x' I b) = (x, y := x', y' I b /\ y' = y) .
158 9. Relations
Proof The proof follows the idea of the proof of Theorem 9.4, rewriting with
definitions and using state attribute properties. 0
Theorem 9.7 Assume that x is a list of program variables, e is an expression, and band care
Boolean expressions. Furthermore, assume that x' does not occur free in b or e.
Then
Corollary 9.8 Assume that x and yare disjoint (lists of) attributes.
(a) If y' does not occur free in b, and x' does not occur free in c, then
var x, y I- (x:= x' I b) ; (y := y' I c) =
(x, y := x', y' I b /\ c[x := x']) .
(b) If x and x' do not occur free in c, and y and y' do not occur free in b, then
var x, y I- (x:= x' I b) ; (y := y' I c) = (y := y' I c) ; (x := x' I b) .
Two other special cases of Theorem 9.6 (b) are the following rules for adding
leading and trailing assignments:
Corollary 9.9 (a) Ifx' and y' are not free in e, then
Relations are more expressive than (tota!) functions and are therefore better suited
to model programs. The simplest program model (apart from a total function) is
that of a partial function, which permits us to say that a program is defined only
for certain initial states. For instance, we might want to say that the assignment
x := x/y is defined only in an initial state where y I: O. Similarly, we can model
nontermination of a program with undefinedness. This is a rather classical approach
to modeling programs.
With relations we can also model nondeterminism. In this case, a program may
have two or more possible final states, but we do not know which one is going to
be chosen (demonic nondeterminism), or we can ourselves choose the final state
(angelic nondeterminism).
160 9. Relations
We can also make the syntax of relations more program-like by adding condi-
tional state relations, in the same way as we defined conditional state transfonners.
Consider first the relation Ipi ; R,where P is a predicate. The intuition is that this
relation maps initial states in p as R does, but initial states outside p are mapped
to the empty set. We then define the conditional state relation if p then P else Q fi
by using this as a building block:
R* ~ (U iii ~ O Ri) ,
where
RO 1\ Id,
Ri+1 1\ R; R i , i = 0, 1,2 ....
We obviously also get two different notions of correctness for state relations. We
say that R is angelically correct with respect to precondition p and postcondition
q if
Deterministic Programs
If the relation R is deterministic, then we have a partial function. A choice between
two or more alternatives is then not possible, but there is still the possibility that R is
not defined for some initial states. In this case the angelic correctness requirement
states that for any initial state a that satisfies p there must exist a final state a'
reachable from a such that q .a' holds. In other words, the execution must terminate
in a final state that satisfies q. Angelic nondeterminism for deterministic relations
thus amounts to what is more commonly known as total correctness.
On the other hand, demonic correctness states that for any initial state a that
satisfies p, if there exists a final state a' reachable from a, then q .a' must hold.
Demonic nondeterminism for deterministic relations thus captures the notion of
partial correctness.
The difference between these two notions of correctness for deterministic programs
is whether we consider the situation in which there is no final state as good or bad.
If we have an angelic interpretation, then our agent is supposed to carry out the
execution, so a missing final state is a breach of contract and is thus bad. In the
demonic interpretation the other agent is making the choices, so a missing final
state is good for our agent.
Refinement
Since we have two notions of correctness, there are also two different kinds of
refinement for state relations, depending on whether we assume that the nondeter-
minism expressed by the relation is angelic or demonic. If it is angelic, then we
can define refinement by
The definition of refinement says that R !; R' holds iff u 0R &q ~ u 0R' Dq
holds for every u and every q. With an angelic interpretation this is the case if and
only if R ~ R' (Exercise 9.10). Intuitively, this means that a refinement can only
increase the set of final states among which our agent can choose and hence makes
it easier for it to satisfy the contract.
In this case the refinement decreases the set of final states among which the other
agent can choose, and hence it can only make it easier for our agent to satisfy the
contract.
Relations as Specifications
Relations are very useful for describing the intended effect of programs, i.e., to
give specifications. The nondeterminism is then interpreted as a don't care non-
determinism: the implementer is given freedom to choose any of the permitted
outcomes. This is demonic nondeterminism, where the user is prepared for any
choice that the system makes. Consider our example specification from the intro-
duction, computing the square root of x with precision e. This can be expressed
by the relational assignment
(x := y I- e< x -l < e) .
Any program that yields a final result that satisfies this relation is then acceptable.
We might be more specific and request the square root to be computed only if
x ~ 0 and e > 0 initially. This is captured by the following relation:
if x ~ 0 A e > 0 then (x := y I- e< x -l < e) else True fi
We do not require anything of the final state when x < 0 or e ~ O. We can also be
more specific if we want, and state that in this case nothing should be done. This
would correspond to the specification
9.7 Summary
This chapter introduced state relations and described their lattice- and category-
theoretic properties. We showed how relations can be used to model programs
where there is only one kind of nondeterminism, either angelic or demonic. We also
looked at the notions of correctness and refinement for both these interpretations
of state relations. For deterministic programs, angelic correctness is the same as
total correctness, and demonic correctness is the same as partial correctness. There
is a long tradition of modeling programs as relations. An early textbook where this
approach is described was written by de Bakker [36]. A relational view is also at
the heart offormalisms such as VDM [94] and Z [133]. The origin of the relational
view is in the relation calculus of Alfred Tarski [135].
Relational assignments are useful for specifying the required behavior of programs
without overspecification. We described a simple programming language based on
relations that is more expressive than the straight-line programs and discussed the
notions of correctness and refinement for programs described in this language.
The notion of a relational assignment is based on the nondeterministic assignment
statement originally proposed by Back [6] and further studied in [12].
The relational model is restricted in that we cannot have both angelic and demonic
nondeterminism at the same time in a program. Neither does it permit us to express
either kind of nondeterminism together with non termination. This shows that the
relational model has its limitations, and that there are situations in which we need
to choose a more general model for programs, such as the predicate transformer
model that we will describe shortly. However, for many purposes, the relational
model is quite sufficient.
9.8 Exercises
9.1 Show that any relation space is an atomic lattice.
9.2 Show that the identity relation is deterministic and that composition of two deter-
ministic relations is deterministic.
9.3 Prove Theorem 9.4 (a). Then explain why there is no rule of the form (x := xii T) =
True.
9.4 Show that the conditional relation preserves determinism; i.e., if relations Q and R
are deterministic, then any relation of the form if p then Q else R fi is deterministic.
9.5 Verify that Rei is a category.
9.6 Show that in the category of state relations, composition distributes over bottom
and join both from the left and from the right. Give a counterexample showing that
composition does not distribute over meet or over top.
9.8. Exercises 165
9.7 Show that if R is a state relation, then the following properties hold:
Idom.RI ~ R; R- 1 ,
Iran.RI ~ R- 1 ; R .
9.8 Prove Corollary 9.9.
9.9 Prove the following:
R*; R* = R*,
(R*)* = R*.
9.10 Show that relations R and R' satisfy
(Vq a {R}.q.a :::} {R'}.q.a)
where the initialization predicate b is a predicate over the global variables and y.
Show that begin var y I b ; Id end = Id.
10______________________
So far, we have assumed a fixed collection of types, type operators, constants and
axioms in the logic. We next consider how to extend our theories to model new
domains of discourse by defining new types with associated constants and inference
rules. Either we can postulate a new type by giving a collection of axioms and
inference rules that determine the properties of the type, or we can construct a new
type as being isomorphic to a subset of some existing type. We describe both these
methods below. We use the axiomatic approach to introduce the important type of
natural numbers. As another example, we show how to define lists and disjoint
sums. The latter can be seen as the category-theoretic dual to Cartesian products.
The constructive approach is illustrated by showing an alternative definition of
natural numbers.
We then look at how to define the standard data structures commonly used in
programming languages: records, arrays and pointers. We show how to formalize
their properties as rather straightforward extensions of the way we formalized
program variables. We also show how to reason about such structures.
Natural Numbers
The type Nat of natural numbers is an atomic type. It has constants 0 : Nat and
sue: Nat ~ Nat (the successor function). We introduce the type Nat by adding 0
and sue to the signature and postulating Peano's axioms:
I- (\In ...... (sue.n = 0 ,
I- (\1m n' sue.m = sue.n =} m = n) ,
I- (\Ip' p.O /\ (\In' p.n =} p.(sue.n =} (\In' p.n
(from now on, we will generally write axioms and theorems without outermost uni-
versal quantifiers and without leading turnstile if there are no assumptions). The
first axioms states that 0 is not a successor. The second axiom states that the suc-
cessor function is injective. The last axiom is the induction axiom. Peano's axioms
are sufficient for developing arithmetic in higher-order logic, because addition and
multiplication (and other operations on naturals) can be defined as new constants.
Note that the induction principle is stated as a single theorem in higher-order logic,
using quantification over all predicates p. In a first-order logic, we would need to
use an axiom scheme to define induction.
The numerals 1,2, ... can be seen as a (potentially) infinite collection of new
constants, each with its own definition (1 = sue.O, 2 = sue.I, etc.).
Sequences
A sequence is a finite ordered collection of elements that are all of the same type.
We shall here introduce sequences by postulating a number of axioms, much in the
same way as we introduced the natural numbers. There are two basic constants over
sequences: the empty sequence ( ) : Seq of I: and the (infix) sequence constructor
& : (Seq of I:) ~ I: ~ (Seq of I:), which extends a sequence with an element.
The postulates are the following:
s&x # () ,
s&x = s' &x' =} s = s' /\ X = x' ,
p.( ) /\ (\Is X p.s =} p.(s&x =} (\Is' p.s .
Note how these axioms resemble the axioms for the natural numbers. In addition
to the two basic constants, we introduce two other constants, last : Seq of I: ~ I:
and butlast : Seq of I: ~ Seq of I:, with axioms
last,(s&X) = x ,
butlast,(s&x) = s .
Since all functions are total, last applied to () will return some value, about which
we know nothing.
In practice, we use angle bracket notation for concrete sequences, so (I, 2, 3) stands
for( )&1)&2)&3.
10.1. Postulating a New Type 169
Sum Type
Dually to products, we extend the type structure of higher-order logic with sum
types, standing for disjoint unions. Sums are added through a binary type operator
+, written infix. Exactly as for products, we assume that + associates to the right,
so ~ + r + fj. stands for ~ + (r + M. Furthermore, we assume that + has higher
precedence than --+ but lower than x.
Elements of the sum are constructed from elements of ~ and r using the injection
functions inl :~ --+ ~ + rand inr : r --+ ~ + r. In addition to the injection func-
tions, we introduce four other new constants for handling sums. The test functions
isl : ~ + r --+ Bool and isr : ~ + r --+ Bool tell us where an element in the sum
originates, and the projection functions outl : ~ + r --+ ~ and outr : ~ + r --+ r
project an element from the sum back into the component where it originates.
Thus the sum type is characterized by the following property, for an arbitrary
8: ~+r:
Note that outl : ~ +r --+ ~ and outr : ~ +r --+ r are not uniquely defined by these
equations; we do not say anything about the value of outl.(inr.y) or outr.(inl.O').
Equality on sums is as follows:
inl.O' = inl.O" _ 0' = 0" , (sum equality)
inl.O' = inr.y _ F,
inr.y = inr.y' _ y = y' .
If ~ and r each is equipped with an ordering, then we assume that the sum ~ + r
is ordered as follows:
Thus the orderings within ~ and r are preserved, but every element of ~ is smaller
than every element of r.
170 10. Types and Data Structures
Another way of extending a theory with a new type is to construct the new type
in terms of existing types. We extend higher-order logic with a new type T by
asserting that this type is isomorphic to a nonempty subset A of some existing type
L. The new type T is not a subset of L, because all types in higher-order logic
must be disjoint. Rather, there is a bijection between the elements of T and the
elements in A. Using the bijection, we can then define operations over the new
type in terms of already existing operations over the old type.
The principle of extension by type definition in higher-order logic allows us to
introduce a new type in this way. The resulting extension of the logic is conservative,
so this approach also guarantees consistency of the extension. The steps required
are the following:
T ~ A. (type definition)
where T is the name of the new type and A : L -+ Bool is a closed term such that
(3x A.x) is a theorem (so A denotes a nonempty set). This extends the theory
with a new type T, the new constants abs : L -+ T and rep : T -+ L, and the
following theorem:
f- (Vx: T abs.(rep.x) = x) /\ (Vy lYE A rep.(abs.y) = y) .
This theorem states that correspondence between the type T and the representing
set A is given by the abstraction function abs and the representation function rep.
This construction is illustrated in Figure 10.1.
rep
abs
The type 1: can contain uninstantiated types 1: 1, , 1:.; in this case T becomes
an n-ary type operator.
Unit Type
As a first simple example, we introduce the type Unit, which contains exactly one
element. This can be done by choosing the value T : Bool to represent the unique
element of Unit. We have that {T} = (Ax : Bool x), so we define the type by
Now we can define unit to be the single element of Unit, using an ordinary constant
definition:
Natural Numbers
As a more elaborate example, we show how the natural numbers themselves can
be defined in terms of the individuals. Here we make use of the infinity axiom; we
assume that the function f : Ind ---+ Ind is injective but not surjective (see Chapter
7). We will not go through all the details of the construction, since we only want
to illustrate how the type-definition mechanism works.
The natural numbers can be built so that 0 is represented by an arbitrary element
outside the range of f (such an element exists since f is not surjective), i.e.,
(EX x ran.f). Furthermore, the successor function is represented by f. The
subset of Ind that we then choose to represent the natural numbers is the small-
est subset that contains (EX' x ran.f) and is closed under f. This set N is
characterized as
Ind
2 -- - ------- ______________ _
t
r--- ---- ----
suc
suc
o -----------
Now we can define 0 and the successor function using the abstraction and repre-
sentation functions that the type definition has added:
o ~ abs.(EX x ran./)
suc.n ~ abs.(f.(rep.n)).
This definition is illustrated in Figure 10.2.
The Peano postulates can now be proved as theorems rather than asserted as axioms.
The first two postulates follow directly from the fact that f is injective (this ensures
that the successor function is injective) and not surjective (this ensures that 0 is not
a successor). The proof of the induction postulate is more complicated. so we omit
it here.
We can also define a type with specific attributes directly, as a record type. Let us
define a new m-ary type operator record for each m ~ 1. Let us write
y[k] A val.k.y,
y(k +- a) A set.k.a.y
val,kj.y = 1lt(rep.y) ,
set.kj.a.y = abs.(update~.a.(rep.y.
Here 1lt denotes the i th component in the tuple with m components, and update~ .a
denotes the operation that changes the ith component of a tuple to the value a,
without changing the other components. These operations are straightforward to
define for any particular values of m and i.
With these definitions, it is easy to show that the record type satisfies the indepen-
dence axioms that we have postulated for it above (Exercise 10.9).
for f' = array(l:1, $). Here 1:1 is the index type, and $ is the component type.
Let us postulate two operations, val : 1:1 --* f' --* $ for retrieving the value of an
array, and set : 1:1 --* $ --* f' --* f' for updating a specific array element. Thus
val,x.y stands for the value of array y at index x, while set.x.,p.y stands for the
new array that we get from y by setting the element indexed by x to the value ,p.
Note the difference here as compared to records and program variables, for which
the access functions returned the first or second component of an attribute. Here
the access and update functions are really functions on the index set. We use the
same abbreviations for arrays as for records:
y[xJ A val,x.y,
y(x +- a) A set.x.a.y
We will assume that val.x and set.x satisfy the independence axioms for all possible
values of x E 1:1. In other words, we postulate the axioms in Figure 10.1 (x and
y are indices and a, b array element values). We also assume extensionality for
arrays:
176 10. Types and Data Structures
The above formalization of arrays assumes that a type is given as the index type.
Thus, array Nat of Bool is an array that permits any natural number to be used as
an index, so the array itself is an infinite data structure. Programming languages
usually constrain the indices to some subset of the index type: we would define
something like array 10 ... 120 of Nat to indicate that only indices in the range
10 ::5 x ::5 120 are permitted. An array specified in this way is defined by adding the
index constraint to the index axioms. As an example, if the index range is m ... n,
then the second axiom becomes
10.4. Array Types 177
The identification axiom would then state that two arrays are the same if they have
the same values for all indices in the permitted range.
(swap.x.y.y)[z] = I y[y]
y[x]
y[z]
if z = x,
if z = y,
otherwise.
All constants over arrays (and records) are automatically also available as pointwise
extended constants. Thus, e.g., we have that
(swap.i.j.A).cr = swap.(i.cr).(j.cr).(A.cr).
This means that we can always apply reduction to expression with arrays and
records.
As another example, we define what it means for the restriction of an array to a
certain index set to be sorted (here, and in what follows, we take Nat as the default
index set for arrays):
We can then use the explicit definition to derive properties for sorted. For example,
we have that
sorted.y.0
== {definition}
(Vx y I x E 0/\ Y E 0 x ~ y =} y[x] ~ y[y])
== {quantification over empty range}
T
node while q is a pointer to another node. We then define the whole dynamic data
structure as a type of the form
r = array I of recordd:T;q:lend.
Here the index set I is the set of pointer values, while the nodes in the structure
are records, with d : T as the basic data field and q the pointer field.
We can declare a program variable D : r to contain the whole (dynamic) data
structure, usually referred to as the heap. In the spirit of Pascal, most programming
languages do not declare the heap explicitly. Declaring the heap as a state attribute
makes the fact that dynamic data structures are just (infinite) arrays explicit. Ac-
cessing a node determined by pointer p is then simply expressed as D[p]; i.e.,
it is an array expression. Similarly, updating a node determined by p in the data
structure is expressed as D[p] := D[p](d +- e) or D[p] := D[p](q +- e),
depending on which field we want to change in the node. We can write this even
more concisely as D[p][d] := e or D[p][q] := e.
Dynamic data structures differ from ordinary arrays in that we have a way of
generating new pointer (index) values that have not been used before. A simple
way is to use Nat as the index set for the heap D and keep a separate counter new
for the heap to give the next unused index, with {I, 2, ... , new.a - l} being the
indices that already have been used in state a. This permits us to generate new
indices dynamically whenever needed and to use index value 0 (called nil) for a
pointer that is never used.
Summarizing the above, a declaration of the form
type T = record ... end;
var p : pointer to T
can be seen as a shorthand for the following declaration:
type T = record ... end;
var D : array Nat of T;
varnew: Nat:= 1;
var p: Nat
Here D is the heap variable associated with the record type T, and new is the
variable that records the least unused index in D.
We then write p t for D[p] so that the heap is kept implicit, p t x for the ac-
cess D[p][x] and pt x := e for the update operation D[p][x] := e. The state
transformer new p is define by
This approach to modeling pointers is very simple, but it shows the basic ideas in-
volved. In particular, it shows that dynamic data structures with pointers in essence
are nothing but (infinite) arrays. We can forbid pointer arithmetic by choosing, e.g.,
Ind rather than Nat as the pointer type, and arb1nd as the value nil. We then have
to explicitly record the set of all pointer values that have been generated this far.
More elaborate pointer types can easily be defined, where we can have two or more
heaps, each with its own pointer type. A more detailed discussion of dynamic data
structures with examples is, however, outside the scope of this book.
10.7 Exercises
10.1 Construct a type tri with three elements A, B, and C and then define a function of
type tri -+ Bool that maps A and B to T and C to F.
182 10. Types and Data Structures
10.2 Construct product types using E --+ r --+ Bool as the type representing E x r.
What is the predicate that characterizes the appropriate subset of E --+ r --+
Bool? How are pair. fst. and snd defined? Prove that the characteristic properties of
products are in fact theorems under your definitions.
10.3 The sum type operator can be defined explicitly as follows:
E+r ~ {(b.a.y):BoolxExrl(b/\y=arb)V(-.b/\a=arb)}
Define the injection. test. and projection functions (inl. inr. isl. isr. out!. outr) and
prove that they have the properties given in Section 1O.l.
10.4 Use the axioms and definitions for sequences given in the text to derive the following
properties:
s =f ( ) :::} (butlast.s )&(last.s) = s
s = ( ) V (3s' x s = s' &x) .
10.5 We have seen how the higher-order capabilities of higher-order logic allow the
induction principle to be stated as a theorem. Another important feature of the
natural numbers that can also be derived within the logic is the principle of function
definition by primitive recursion. In fact. it is possible to derive the following
theorem from the Peano axioms:
01e f 3!g g.O =e /\ (Vn g.(sue.n) = f.(g.n).n .
We can then define (see exercises below) a new constant natree that has the
following properties:
natree.e.f.O = e
natree.e.f.(suc.n) = f.(natrec.e.f.n).n .
This constant can be used as a tool for defining recursive functions. For example.
we define
even ~ natree.T.(Ab n -. b) .
Show that even has the following property:
(even.O == T) /\ (Vn even.(sue.n) == -. (even.n .
10.6 Define the constant +. standing for addition of natural numbers. as follows:
Statements
11 _ _ _ _ _ _ _ _ _ __
Predicate Transformers
We described the basic notion of a contract between independent agents in the in-
troduction and showed a number of properties that it would be reasonable to expect
contracts to have. We did not, however, say what kind of mathematical entities con-
tracts are. The interpretation of contracts depends on what features are considered
essential and what are inessential. We now make the assumption that the essential
feature of a contract is what can be achieved with it. From this point of view,
contracts can be interpreted as predicate transformers, functions from predicates
to predicates. We will explore this approach below in detail, concentrating first on
basic mathematical properties of predicate transformers and on how contracts are
interpreted as predicate transformers.
Let us look at the language of contract statements introduced in the first chapter:
Consider first the update (f). It has the effect of changing the present state u to a
new state f.u. There is no choice involved here, neither for our agent or the other
agent, since there is only one possible next state. In this case, we obviously have
that u ~ (f) nq holds if and only if f.u E q.
The assertion {g} has no effect on the state if g holds, but otherwise it will breach
the contract. Hence, u ~ {g} nq holds if and only if u E g n q. Condition g must
hold initially in order to avoid breaching the contract, and condition q must hold
initially if it is to hold for the final state, because the state is not changed.
The assumption [g) also has no effect on the state if g holds, but if g does not hold,
then the assumption is false and the contract is satisfied trivially. Thus, u U[g) nq
holds iff either u E -. g or u E q, i.e., iff U E -. g U q.
Consider next the angelic choice Sl US2. Our agent gets to choose the alternative, so
itis sufficient that either one ofthe two contracts can be satisfied. Thus u ~ Sl U S2 nq
holds iff either u ~ Sl nq or u ~ S2 nq holds.
For the demonic choice Sl nS2, we have thatu ~ Sl nS2 nq holds iffbothu ~ Sl nq
n
and u ~ S2 q hold. Because the other agent gets to choose the alternative, our
agent must be able to satisfy both contracts in order to satisfy the whole contract.
Weakest Preconditions
For any contract S and any condition q to be established, we define wp.S.q as the
set of all initial states from which S can be satisfied to establish q:
wp.S.q ~ {u I u ~ S Hq} .
We refer to wp. S.q as the weakest precondition for satisfying S to establish q.
We can use this definition to give an alternative definition of satisfaction for se-
quential composition: u ~ Sl ; S2 nq holds iff u ~ Sl n(WP.S2.q). Strictly speaking,
this is equivalent to the previous definition only if we assume that if a contract
establishes a condition q, then it will also establish any weaker condition q'. This
monotonicity property of weakest preconditions for contracts will be shown to hold
in Chapter 13.
state space. Thus, wp. S is a predicate transformer. From the definitions of satisfac-
tion above, we can immediately determine wp. S for the statements of our simple
language for contracts:
wp.(f).q f-I.q,
wp.{g}.q gnq,
wp.[g).q ~gUq,
cr ~ S aq == wp.S.q.cr .
There are, however, definite advantages in formalizing the notion of satisfaction in
terms of predicate transformers rather that in terms of a ternary relation. This will
become obvious as the theory is further developed.
skip = ()..q.q).
(S 0 T) 0 U =S 0 (T 0 U) , (0 associative)
skip 0 S = S and S 0 skip = S . (skip unit)
The reader should notice that we use forward composition in state transformer cat-
egories and in state relation categories, while composition in predicate transformer
categories is backward.
Since the morphisms in a predicate transformer category are functions ordered by
pointwise extension and the composition operator is backward function composi-
tion, we have the monotonicity property from Section 2.5:
S ~ S' =} S; T ~ S' ; T .
However, composition is not monotonic in its second argument (this is because
predicate transformers are not necessarily monotonic).
The predicate transformer category Ptranx has the collection of state spaces X as
objects and all predicate transformers between two state spaces as its morphisms:
magic; T magic,
abort; T abort,
(-.S); T -.S; T ,
(SI n S2); T = SI; T n S2; T
(SI u S2); T = SI; T u S2; T
The last properties generalize to meets and joins for arbitrary statements; i.e.,
The definitions of weakest preconditions for basic contract statements then simplify
to
wp.{f) (f) ,
wp.{g} {g} ,
wp.[g] [g] .
On the left-hand side we have a wp applied to a contract statement; on the right-hand
side we have a predicate transformer.
We can express the main constants of the predicate transformer category in terms
of the functional update, assertion, and assumption predicate transformers:
abort = {false},
skip (id) = {true} = [true],
magic = [false].
wp.skip == skip.
Any contract statement S defined by the language above can thus be directly
expressed as a weakest-precondition predicate transformer. The function wp is
really a homomorphism from the syntactic algebra of contract statements to the
semantic algebra of predicate transformers. For instance, we have that
wp.(f); (h) ; {false} u skip); (k)) = (f); (h); abort u skip); (k)
Again, on the left-hand side we have the weakest precondition of a contract state-
ment, on the right-hand side a predicate transformer. This permits us to consider
contracts directly as predicate transformers. The context will usually tell whether
we have a contract statement or a predicate transformer.
The names for the bottom and top of the predicate-transformer lattice are by now
traditional. They arise from interpreting predicate transformers as describing the
execution of program statements. Then abort is seen as a failure: the computation
has to be aborted because something went wrong. The execution may have gone
into an infinite loop, there may have been a run-time error, or something else bad
might have happened. The essential thing is that we lose control of the execution
and do not know what happens after an abort. Our interpretation of contracts
interprets abort as the assertion that is impossible to satisfy and thus always leads
to a contract violation, preventing our agent from satisfying the contract, no matter
what condition was supposed to be achieved.
In the program execution interpretation magic is a statement that immediately
achieves whatever condition our program was supposed to, as if a miracle had
occurred. This does not have any direct counterpart in existing programming lan-
guages, as this statement is not implementable. However, it serves as a convenient
abstraction when manipulating program statements. In this respect, it is similar to
the use of imaginary numbers: these simplify calculations even though they strictly
speaking do not have any counterpart in reality. In our interpretation of contracts,
magic is the assumption that is impossible to satisfy and thus will always discharge
our agent from any obligation to follow the contract. Interpreting the statements
we have introduced as talking about contracts in general, rather than just about
program execution, allows us to give simple and intuitive interpretations to both
abort and magic. As we have already shown, program statements can then be seen
as a special kind of contract.
in a state a where x.a ~ y.a + 2 but leads to a breach of the contract in states
where this condition is not satisfied. Using the definition of assert statements, we
can, e.g., determine that
Theorem 11.2 Let x be an attribute (or a list ofattributes), e an expression (or a list ofexpressions),
and q a Boolean expression. Then
var x I- (x:= e).q = q[x := e] .
We usually omit the explicit angular brackets for assignment statements when the
context makes it is clear that an assignment statement rather than an assignment is
intended.
As an example, we can use this rule to calculate the weakest precondition for
x := x + y; y := y + 1 establishing condition x ~ y. We have that
This shows how the calculation of weakest preconditions is kept simple using the
assignment rule.
11.4. Relational Updates 195
g
(R]
a
a. U) (b)
(a)
{R}
a
(c)
FIGURE 11.1. (a) Functional update, (b) demonic update, (c) angelic
update
x component is changed so that the square of its new value differs by less than the
value of e from its old value.
We can also derive substitution rules for the relational assignment statements.
These rules make use of the pointwise extension of the existential and universal
quantifiers that we have defined above, in connection with meets and joins over
arbitrary sets of predicates.
Theorem 11.3 Assume that x is a list ofprogram variables and band q are Boolean expressions
in which x' does not occur free in q. Then
Proof We prove the first case here; the second one is established by analogous
reasoning.
{x:= x' I b}.q.a
== {definition of angelic update}
(3y (x := x' I b).a.y 1\ q.y)
== {characterization of relational assignment}
(3y (3x' y = set.x.x'.a 1\ b.a) 1\ q.y)
== {properties of existential quantification}
(3y x' y = set.x.x'.a 1\ b.a 1\ q .y)
== {one-point rule}
(3x' b.a 1\ q.(set.x.x'.a))
== {substitution property}
(3x' b.a 1\ q[x := x'].a)
== {pointwise extension}
(3x' b 1\ q[x := x'D.a
o
From now on, we will omit the assumption var x from theorems and rules unless
there is some special reason to state it.
Consider as an example the demonic assignment statement [x := x' I x' > x + y].
We have by the above rule that
[x := x' I x' > x + y].(x > y)
= {rule for demonic assignment}
(Vx' x' > x + y ::::} x' > y)
198 11. Predicate Transformers
= {reduction, arithmetic}
x~O
11.5 Duality
The dual SO : 1: ~ r of a predicate transformer S : 1: ~ r is defined by
{p)".q
= {definitions of assert and duals}
...., (p n ....,q)
= {lattice properties}
....,pUq
= {definition of guard}
[p].q
Thus, the basic operations for constructing predicate transformers come in pairs,
each one with its dual. Functional update and sequential composition are their own
duals. The characterization of the constant predicate transformers also implies that
Since (SOt = S, all the duality properties listed above can be read in reverse.
Thus, for example, [p]O = {p} and abortO = magic.
11.6. Preconditions and Guards 199
(i) The states in m.S from which any postcondition can be established. These
are the initial states in which our agent can choose to be discharged from its
obligations to satisfy the contract.
(ii) The states in a.S from which no postcondition can be established. These are
the states in which our agent cannot avoid breaching the contract.
n g.S from which some postconditions can be established
(iii) The states in t.S
and some cannot. These are the states in which a discharge of obligation is
impossible for our agent, and a breach of contract can be avoided, so some
postcondition will be established.
8.S
as the demonic update), and de Bakker [36] used a meet (choice) operation on
predicate transformers. Miracles (guard and magic) were added by Morgan [104],
Morris [108], and Nelson [113] for basic sequential statements, and by Back [15]
to model enabledness of statements executed in a parallel context. Angelic nonde-
terminism was added (as an angelic assignment) by Back [13] and by Gardiner and
Morgan [59] (as a "conjunction operation"). The full collection of basic predicate
transformers as described here were first identified by Back and von Wright [25].
Duality was used in reasoning about predicate transformers already by Pedro Guer-
reiro in [71]. The specification language of Back and von Wright [26, 27] is based
on the fundamental dualities between demonic and angelic nondeterminism and be-
tween nontermination and miracles. Dijkstra and Scholten [54] introduce a notion
of converse predicate transformers that is closely related to duals.
The original formalization of the refinement calculus [7] was based on infinitary
logic [95, 127], in order to permit a simple characterization of iteration. First-
order predicate calculus is not very suitable as a basis for the refinement calculus,
because the very definition of refinement involves a quantification over functions
(all possible postconditions), which cannot be expressed directly in the syntax
of first-order logic. Higher-order logic permits quantification over functions, so
it is a good framework for the formalization of refinement calculus. The first
systematic investigation of higher-order logic as a basis for the refinement calculus
was undertaken by Back and von Wright [30].
The assignment rule derived here is exactly the definition of the weakest-precondition
semantics for assignments of Dijkstra [53], which in tum is based on the assignment
axiom of Hoare [84]. Thus we can recover Dijkstra's syntactic characterization of
weakest preconditions as theorems in our more general framework.
202 11. Predicate Transformers
11.8 Exercises
11 .1 Show that {p} ~ [p] holds for an arbitrary predicate p.
11.2 Relation R is said to be total if (VU 3y R.u.y) holds. Show that [R] ~ {R}
holds if and only if the relation R is total.
11 .3 Prove the following properties of the test and map relations for an arbitrary predicate
p and arbitrary function f:
{ Ipl } = {p} , [ Ipl ] = [p] ,
{ If I } = (f) , [ If I ] = (f) .
11.4 Prove the following:
(b)(x, y := x + z, y - z).(x = y) .
The predicate transformers that we use to model contracts are constructed from
other predicate transformers or from simpler elements, like state predicates, state
transformers, or state relations. The predicate transformer constructors can thus
be seen as functions that map elements in one domain to the domain itself or to
another domain. The basic question that we investigate in this chapter is to what
extent the lattice and category structure is preserved by these constructors, i.e., to
what extent the constructors are monotonic and homomorphic.
ers between the state spaces. In general, we will refer to these categories as state
categories.
Essentially, all the state categories are order-enriched categories. Relations fonn a
complete Boolean lattice-enriched category, while predicate transfonners fonn a
left complete Boolean lattice-enriched category. State transfonners fonn a discrete
order-enriched category (we assume only the discrete ordering for state spaces, so
I r;;;g == I=g)
The reader may verify that the defining properties for a category are satisfied
(Exercise 12.6):
It is easy to see that composition is monotonic with respect to the predicate ordering:
We let Predx denote the state predicate category with objects X and all predicates
on}; as morphisms Predx(};, };).
Since composition is also a lattice operation, we will not make much direct use of
the fact that Pred is a category.
12.1. State Categories 205
Rel(l:, r) = 1: ~ Pred(r)
r
r
Bool
means that we can often choose the level in the refinement calculus hierarchy at
which to carry out an argument. It is usually preferable to argue at as high a level
as possible. The notation is then more concise, and the proof is more algebraic
and shows the structure of the argument more clearly. However, if an argument
at one level becomes too involved, we can reduce the level by writing out the
pointwise extension explicitly. This movement between levels in the refinement
calculus hierarchy is typical of arguments in the calculus.
12.2 Homomorphisms
We will here be particularly interested in the monotonicity and homomorphism
properties of predicate transformer constructors. We are interested in questions
such as whether the structure of predicates is preserved by the guard and assert
constructors, and whether the structure of functions and relations is preserved
by the updates. Knowing the basic algebraic properties of the basic constructors
allows us to easily determine the algebraic properties of program statements that
are defined in terms of these.
12.2. Homomorphisms 207
Sequential Composition
All the basic predicate transformers. considered as mappings from elements of other
domains to predicate transformers. preserve sequential composition and identities.
Thus they are homomorphisms. Duality is also a homomorphism on predicate
transformers.
Theorem 12.2 Thefollowing homomorphism properties holdfor the basic predicate transformers:
{p n q}.r
= {definition}
pnqnr
= {definition of assert}
(p}.(q nr)
= {definition of assert}
(p}.({q}.r)
= {definition of sequential composition}
({p}; {q}).r
The homomorphism properties for sequential composition and identity are sum-
marized in Table 12.1.
Theorem 12.3 The assert and guard constructors satisfy the following properties:
The assert constructor (Ap {p}) : peE) --+ (~ t-+ ~) is thus monotonic, and
it preserves bottom, positive meets, and universal joins. The guard constructor
(Ap [p]) : P(~) --+ (~ t-+ ~), being the dual of assert, is antimonotonic. It
preserves bottom, positive meets, and universal joins onto the dual lattice (~ t-+
~)o.
In fact, the equivalences in Theorem 12.3 show that the assert constructor homo-
morphically embeds the predicates P(~) in ~ t-+ ~. This means that reasoning
about asserts can be reduced to reasoning about predicates. Similarly, the guard
constructor homomorphically embeds the predicates into the dual of the predicate
transformer lattice.
Updates
We have the following results for the homomorphic properties of functional and
relational updates.
is c .1 T n u ...... 1 ,
(Ap {p}) yes yes no yes yes no yes yes
(Ap [p]) yesO yesO no yeso 1 yesO no yes yes
(Af (f)) yes - - - - - yes yes
(AR {R}) yes yes no no yes no yes yes
(AR [R]) yesO yesO no no yesO no yes yes
1
when the meet IS taken over nonempty sets
Theorem 12.4 The update constructs satisfy the following lattice-theoretic properties:
(a) f=g - (f) = (g) ;
(b) PC;;Q - {PI ~ {Q} ,
PC;;Q - [P] ;:! [Q] ;
(c) {False} = abort,
[False] = magic;
(d) lUi e I Rd (uieI{Ri}) ,
lUi e I Rd (nieI[R i ]) .
is ~ .1 T n u ...., 1 ;
0..8 S; T) yes yes yes yes yes yes no no
(1S n T)
S yes yes no yes yes no no no
(1S' S u T) yes no yes yes yes no no no
(1S ....,S) yes O yesO yes O yesO yes O yes no no
(1S. SO) yes O yes O yesO yes O yesO yes yes yes
Theorem 12.5 Let S and T be predicate transformers. Then the following properties hold.
(a) S r;; T => m.S ~ m.T ,
S r;; T => t.S ~ t.T ;
(b) m.abort = false,
t.abort = false;
(c) m. ma9ic true,
t.ma9ic true;
(d) m.(ni E I Sj) = (niEIm.Sj),
t.(ui E I Sj) (U i E I t.Sj) .
Example
As an example of using homomorphisms in proofs, we show that the property
(f) ; [/-'] r;; skip holds for an arbitrary state transformer f:
(f) ; [/-']
= {properties of mapping relation construct}
[If I]; [r']
= {homomorphism}
[ Ifl;r']
r;; {ldom.RI ~ R ; R-' by Exercise 9.7}
[ Idom.lfll ]
= {all functions are total}
[ Itruel ]
is c 1.. T n u .....
(ASm.S) yes yes yes no yes no
(AS,t.S) yes yes yes yes no no
(AS a.S) yes O yes O yesO no yes O no
(AS 9.S) yes O yes O yesO yes O no no
Note how the derivation uses homomorphism properties to move between different
levels in the refinement calculus hierarchy. A similar derivation proves the dual
property skip!; U- 1 } ; (f) (Exercise 12.5).
We have looked here at the operations within this structure and in particular studied
to what extent these operations preserve the lattice and category structures of
their domains. Homomorphic properties of predicate transformers have, to our
knowledge, not been investigated in this way systematically before, although many
of the homomorphism properties that we have listed above are well known from the
literature. Algebraic collections of laws for programs in a relational setting have
been given by Hoare et a!. in [90]. Hesselink uses algebraic properties to define
his notion of command algebras, for which positive meet-homomorphic predicate
transformers provide models [80]. The homomorphism properties are important in
practical reasoning, because they form the main method by which an argument on
one level of the refinement calculus hierarchy can be reduced to a simpler argument
on another (in most cases lower) level of the hierarchy.
Another important aspect of the refinement calculus hierarchy that we have iden-
tified above is that it clearly demonstrates the different semantic models for pro-
gramming languages that are available. Methods for program derivations based
on these different models (partial functions, relations, and predicate transformers)
need not be seen as competing but rather as complementary. A theory of func-
tional programming is in fact embedded as a subtheory in the theory of predicate
transformers. Similarly, relational programming and the denotational semantics of
deterministic programs form subtheories of the predicate transformer theory. The
homomorphism properties show how results in one theory can be carried over to
another theory. It also shows that mixed program derivations are quite feasible.
For instance, a functional program derivation might well start with a relational or
212 12. The Refinement Calculus Hierarchy
12.4 Exercises
12.1 Use suitable rules to simplify the following in a detailed derivation:
(a) (x := x + y) ; (y := x - y) .
Statements
In this chapter we show that the basic predicate transformers that we have intro-
duced to model contracts (asserts, guards, functional updates, demonic and an-
gelic updates) are all monotonic. In addition, composition, meet, and join preserve
monotonicity. Conversely, any monotonic predicate transformer can be described
in terms of these constructs, in a sense to be made more precise below. In fact, it
is possible to write any monotonic predicate transformer in a normal form.
There are also other reasons for considering the monotonic predicate transformers
in more detail. By restricting our attention to monotonic predicate transformers,
we get that sequential composition is monotonic in both arguments. This means
that we have a complete lattice-enriched category. Without mono tonicity, we have
only a left Boolean lattice-enriched category. Although we now lose the Boolean
lattice property, we gain a simpler category structure.
Subtyping
We have until now assumed that a poset is a pair (I;, ~), where I; is a type and
~: I; ~ I; ~ Bool is a relation on I;. In practice, this is too restrictive; we also
need to consider posets (A, !;A), where A is a subset of E. In set theory, we would
then choose !;A to be the restriction of!; to A, so that !;A S; A x A. In higher-order
logic, we would like to define!; A: A ~ A ~ Baal. This is not, however, possible,
because A is not a type, except when A = E.
Instead, we choose to relativize the notions needed for posets and lattices. We say
that the relation!;: E ~ E ~ Baal is reflexive on A if a !; a holds for every
a E A, that it is transitive on A if a !; b 1\ b !; c => a !; c for any a, b, C E A,
and so on. In fact, the definitions that we have given for posets and lattices in
the introductory chapter are already relativized, because we were careful in each
definition to point out that the requirement expressed need hold only for elements
in the set A. Thus, we can talk about the bottom of A, the top of A, the meet in A,
the join in A, the negation in A, and so on. We say that (A, !;) is a poset if!; is
reflexive, transitive, and antisymmetric on A. The lattice definitions are relativized
in a similar way.
We also have to relativize the notion of functions from one poset to another. Let
(A, !;\) and (B, !;2) be two posets, where AS; E, B S; r, !;\: E ~ E ~ Bool,
and !;2: r ~ r ~ Baal. The function f : E ~ r is said to be monotonic on A
if a !;\ a' => f.a !;2 f.a' holds for any a, a' E A. Order-preserving functions and
congruences are relativized in the same way.
Consider next the function space construction. For A S; E and B 0:; r, we would
like to say that f is a function from A to B; i.e., f : A ~ B. However, again we
have the problem that A ~ B is not a type. We solve this problem by defining the
set
Antisymmetry does hold in ~ --+ B, i.e., when the domain is chosen to be a type,
because I =1; g is the same as I = g. Generally, the pointwise extension theorem
holds for any extension of B to ~ --+ B.
We could fix the pointwise extension theorem by making a small adjustment in our
definition of the function space. Defining A --+ B instead as (f : ~ --+ r I C'lx E
A I.x E B) " (Vx rt A I.x = arb)}, we would also get antisymmetry, and
the pointwise extension theorem would be in full force. This trick implies that all
functions I E A --+ B have the same value outside domain A, so they are equal
if and only if they have the same value for each element in A. We do not choose
this approach here, because for our purposes it will be sufficient to consider only
pointwise extensions of the form ~ --+ B.
The ordering relation ~: ~ -# ~ is thus the same in both the poset A and in its
subposet B. However, the supremum and infimum in these posets may depend on
the elements that are included in the poset, and hence need not be the same. This is
illustrated in Figure 13.1. Let A consist of all the elements in this lattice, and let B
consist of the elements that are marked black. Then the supremum of the set {a, b}
is d in the poset A and c in the poset B. Hence, we may need to indicate explicitly
in which poset the supremum and the infimum are taken, writing a UA b = d and
a UB b = c.
216 13. Statements
If we view a lattice A as an algebra (A, nA, UA), then the sublattice definition boils
down to requiring that the subset B of A must be a subalgebra; i.e., the operations
nB and UB must be defined for any a, b in B (with values in B), and they must
give the same result as nA and UA for any two elements a, bin B: a nB b = anA b
and a UB b = a UA b.
This notion of a subalgebra leads to the notion of a subcategory, as follows. Let
C be a category, with objects Obj and morphisms Mor, and C' a category with
objects obl and morphisms Mor'. Then C' is a subcategory of C if obl ~ Obj,
Mor' ~ Mor, and if units and composition are the same in C' as in C.
Monotonicity
Assume that posets A and B are given. We write A --+ m B for the set of monotonic
functions from A to B:
Theorem 13.1 Let (~, ~)and (B,~) be posets. Then the pointwise extension of these posets to
(~ --+m B,~) is also a poset. This poset is a (complete, distributive) sublattice of
(~ --+ B,~) if B is a (complete, distributive) lattice.
Note that the property of being a Boolean lattice is not preserved, because the point-
wise extension of a complement is not a complement in the lattice of monotonic
functions. If f is monotonic and a !; b, then
a!;b
~ {functionality}
fa!; f.b
== {negation is antimonotonic}
..... (f.a) ~ ..... (f.b)
== {pointwise extension}
(..... f).a ~ (..... f).b
so ..... f is antimonotonic and not monotonic.
The pointwise extension theorem (Theorem 13.1) gives us the following result.
Sequential Composition
In Section 12.2 we described those monotonicity and homomorphism properties
that hold in general for the basic predicate transformer constructors. We get more
homomorphism properties when we restrict our attention to monotonic predicate
transformers only. Sequential composition in particular is monotonic only with
respect to the refinement ordering in its first argument, as shown in Section 12.2.
However, it is monotonic also in its second argument if the first argument is a
monotonic predicate transformer (Table 13.1).
Lemma 13.4 Let TI and T2 be arbitrary predicate transformers and S a monotonic predicate
transformer. Then
Proof
S monotonic, TI ~ T2
I- (S; T1).q
= {definition of composition}
S.<TI.q)
~ {monotonicity of S, assumption T1.q ~ T2.q}
S.(hq)
= {definition of composition}
(S; T2).q
o
Lemma 13.4 is in fact a special case of the more general fact that a function f is
monotonic if and only if gl ~ g2 ::::} f 0 gl ~ f 0 g2 (Exercise 13.1).
Combining Lemma 13.4 with the fact that sequential composition is always mono-
tonic in its left argument, we have the following central result.
Corollary 13.5 Let SI, S2, T1, and T2 be monotonic predicate transformers. Then
SI ~ S2 /\ TI ~ T2 ::::} SI; TI ~ S2 ; T2 .
= {definition of assert}
{p}.q'
The proofs for [p], (f), {R}, and [R] are similar.
The results for meets and joins follow from Theorem 13.1. 0
Lemma 13.8 is illustrated in Table 13.2. This table shows for each operation on
the left whether it preserves the homomorphism property indicated on the top. As
a direct consequence of this lemma, we get the following important result.
Normal Form
We do not usually distinguish between a statement as a term in higher-order logic
(syntax) and the monotonic predicate transformer that it denotes (semantics). We
can make the distinction if we need to, by talking about the statement term and
the statement denotation, respectively. We shall now show that any monotonic
predicate transformer term can in fact be written as a statement term.
Theorem 13.1 0 Let S be an arbitrary monotonic predicate transformer term. Then there exist state
relation terms P and Q such that S = {P} ; [Q].
is 1; preserves C
{p} yes yes
[p] yes n yes
(f) yes u yes
{R} yes
[R] yes
The use of the arbitrary meet and join in a syntax definition needs a little bit of
explanation. An indexed meet (n i E [ Sj) can always be written more explicitly
as
(niE[,Si) = n(im.S.l),
where S is a function that assigns to each index i a statement S.i, and [ is some
subset of all possible indices. A similar argument holds for indexed joins. As before,
the statement syntax does not define a new syntactic category, but merely serves
to identify a specific subclass of predicate transformers.
Shunting Rules
The duality between assert and guard predicate transformers gives rise to the
following useful shunting rules.
Lemma 13.12 Let p be an arbitrary predicate and S and S' arbitrary monotonic predicate
transformers. Then
13.4. Derived Statements 223
Proof Part (a) follows directly from the definitions and from the shunting rule for
predicates (i.e., p n q ~ r == p ~ ..... q U r). For part (b), we have
S ~ S'; {p}
== {definition}
(Vq. S.q ~ S'.(p nq))
=* {specialization q := ..... p U q}
S.( ..... pUq) ~ s'.(pn( ..... pUq))
== {lattice properties of predicates}
S.(-'pUq) ~ s'.(pnq)
=* {S' monotonic}
S.(-'pUq) ~ S'.q
== {definition of guard}
(S; [p]).q ~ S'.q
Let us next consider two other important derived statements: conditional statements
and blocks with local variables. We have met these constructs before, as state
transformers and state relations. Now we show how to define these as predicate
transformers. Other important derived statements, such as recursion and iteration,
will be introduced later on, in Chapters 20 and 21.
224 13. Statements
Conditional Statements
As we already showed in the introduction, we can define the deterministic condi-
tional statement by
From the definition it follows that this determines the following predicate trans-
former:
(ifgthenS\elseS2fi).q = (-.gUs\.q)n(gUs2.q)
or, equivalently,
The assert statement tests that at least one of the guards is true in the state. If not,
then we have abortion; otherwise one of the alternatives for which the guard is true
is chosen demonically and executed. In contrast with the deterministic conditional,
this statement may be genuinely (demonically) nondeterministic. This happens
when two or more guards are satisfied in a given state, and the effect of executing
the corresponding statements is different.
Because we have an explicit definition of the conditional statement, we can de-
rive its homomorphism properties from the corresponding properties of its basic
constituents. For instance, the deterministic conditional constructor is Gointly)
monotonic in its predicate transformer arguments:
Blocks
The block construct for state transformers allows us to model a situation where
the state space is temporarily extended. In exactly the same way, we can define a
block construct for predicate transformers that permits us to embed statements on
a "larger" state space into a statement on a "smaller" state space.
The block construct for predicate transformers is defined in analogy with the state
transformer block:
Lemma 13.13 Assume that begin var y := e ; S end is a block statement where the expression e
does not mention variable y and the body S is written using only program variable
notation, and that q is a Boolean expression over the global variables. Then
Proof We have
(begin var y := e ; S end).q
= {definitions of block and sequential composition}
(begin).(y := eo end).(S.(end).q)))
226 13. Statements
The fact that S is using only program variable notation guarantees that the assign-
ment axiom can be applied in the second step of the derivation. We leave it to the
reader to show that (end).q = q. Similarly, we leave it to the reader to show that
(begin).q = q if q does not mention the local variable. 0
The block constructor (AS begin var y := e; S end) is very regular, as it satisfies
all basic homomorphism properties that can be expected of statements. These
properties are summarized in Table 13.3.
Theorem 13.14 The block constructor is monotonic:
where the global variables are x and y. This is the swapping example of Chapter 5
lifted to the level of statements. In fact, it is possible to prove (Exercise 13.13) the
following homomorphism property for blocks:
is c: ..L T n U ~
1 ;
(AS, T if g then S else T fi) yes yes yes no no no yes no
(AS" ... , Sn if g, -+ S, 0 ... 0 gn -+ Sn fi) yes yes yes no no no yes no
(AS begin var y := e; Send) yes yes yes yes yes no yes no
where b is a Boolean expression that can mention both global and local variables.
A derivation like the one in the proof of Lemma 13.13 shows which predicate
transformer this block is:
Exactly as for state transformer blocks, we can also permit implicit initialization
conventions. Thus,
13.5 Procedures
The notion of procedures can be lifted directly from the state transformer level
(Section 5.6) to the predicate transformer level. Thus, a definition of the form
As an example, consider the following procedure, which stores the smaller of the
values m and n in the variable x:
A typical call to this procedure could look as follows, where y and z are program
variables:
Min(y, z + 1, y) .
228 13. Statements
Local procedures on the statement level are handled exactly as on the state trans-
former level. We define a statement with local procedure as follows:
let N =(Ax y S) in
... begin var y' := e; N.u.y' end
Procedures and calls to them can be introduced and eliminated on the statement
level in exactly the same way as for state transformers.
The following example illustrates the use of a local procedure:
proc Min(var x, val m, n) =
il m ::: n ~ x := m Dm ;:;.: n ~ x := n Ii
in
Min(y, y, z) ; Min(x, x, y) .
In this chapter we have shown how contract statements can be interpreted as mono-
tonic predicate transformers. The monotonic predicate transformers form a sublat-
tice and subcategory of predicate transformers, so we can reason about monotonic
predicate transformers in the larger context of all predicate transformers. We have
defined predicate transformer statements as predicate transformer terms that are
built in terms of the basic predicate transformers and three algebraic composition
operators: sequential composition, meet, and join. We have shown that any such
statement is a monotonic predicate transformer. Conversely, we have also shown
that predicate transformer statements can be taken as a normal form for monotonic
predicate transformers: any monotonic predicate transformer that can be expressed
as a higher-order logic term can also be expressed as such a statement. We also de-
fined three standard programming constructs (conditional statements, blocks with
local variables, and procedures) in terms of more basic constructs.
We use a two-phase approach to defining the language of contracts, specifications,
and programs. First, we introduce basic predicate transformers and predicate trans-
former constructors, which have been chosen so that they have simple and regular
13.6. Summary and Discussion 229
We use the same constructs for both contract statements and predicate transformer
statements. This allows us to identify these two whenever convenient and rea-
son about contract statements as if they were predicate transformers. This way of
identifying contract statements with their associated predicate transformers is an
important device, because it allows a purely algebraic treatment of contract, speci-
fication, and program statements, where the specific syntax chosen for expressing
statements is irrelevant.
Another consequence of this is that we do not need to make the distinction between
syntax, semantics, and proof theory that is traditional in programming logics.
The syntax for predicate transformer statements is just the syntax of higher-order
logic, with a little bit of syntactic sugaring here and there. The semantics is the
semantics of higher-order logic. This is a simple set-theoretic semantics, as we
have shown. The special properties that these statements have are a consequence
of the operations that we have introduced by explicit constant definitions in higher-
order logic. The proof theory that we use is also the proof theory of higher-order
logic. The refinement calculus is a theory within higher-order logic, and as such, it
uses exactly the same set of basic axioms and inference rules as any other theory in
higher-order logic. What is new in the refinement calculus is expressed as theorems
and derived rules of inference, which are proved (not postulated) in higher-order
logic.
Of course, this alone does not prove that the theorems are also correct in the sense
that they are true in an operational interpretation of contract statements, which
230 13. Statements
explains a contract in terms of the possible behaviors that it permits for the agents
involved. That this is also the case will be demonstrated in the next chapter, where
the operational semantics of contract statements is defined.
This is also the reason why we need to distinguish between contract statements
and predicate transformer statements. The predicate transformer interpretation, al-
though extremely useful for reasoning about properties of contracts, is still just one
possible interpretation of contracts. The operational interpretation gives another
semantics for contracts. A third interpretation of contract statements will also be
presented, where we show how to interpret contracts as special kinds of functions
on the initial state.
A notation where every monotonic predicate transformer term is expressible as
a statement was originally introduced by Back and von Wright [26, 27], with
an original normal form theorem. The normal form theorem presented here was
proved by von Wright [143]. The guarded conditional was originally introduced
by Dijkstra [53]. Blocks and procedures have been handled formally by Hoare [85]
and Gries and Levin [65], among others.
13.7 Exercises
13.1 Prove that if r and A are partially ordered, then
f monotonic ==
(Vgl : r -+ A Vg2 : r -+ A gl ~ g2 '* f; gl ~ f; g2)
S) !; ~ 1\ S2 !; Si ::}
if g then S) else Sz fi !; if g then ~ else Si fi .
13.9 Prove the following rule:
if g then S) n S2 else S fi =
if g then S) else S fi n if g then Sz else S fi .
13.1 0 Recall the definitions of the chaos and choose statements:
Statements as Games
game (statement) S, we also need to give the initial position (initial state) (f E 1:
of the game and a goal (a postcondition) q r that describes the set of final states
that are winning positions.
For a given postcondition q, the angel tries to reach a final state that satisfies q
starting from the initial state (f. The demon tries to prevent this. Both follow the
rules of the game, as described by the statement S. The statement determines the
turns of the game, as well as the moves that are permitted for each player. The game
proceeds by a sequence of moves, where each move either leads to a new state or
forces the player that is to make the move to quit (and hence lose the game). Each
move is carried out by either the angel or the demon.
There are two basic moves, described by the demonic and the angelic update
statements. The angelic update statement {Q} is executed by the angel in state (f
by choosing some state y such that Q.(f. y holds. If no such state exists, then the
angel cannot carry out this move and quits (loses). The demonic update statement
[Q] is similar, except that it is carried out by the demon. It chooses some state y
such that Q.(f. y holds. If no such state exists, then the demon cannot carry out the
move and quits.
Skip, abort, and magic statements, as well as guards, asserts, and functional up-
dates, can all be seen as special cases of demonic and angelic updates. Thus, we
do not need to define the meaning of these constructs in the operational semantics.
Similarly, the operational semantics also explains the execution of derived state-
ments (like the conditional statement) that are built out of the constructs, for which
we give an explicit interpretation.
Operational Semantics
We define the game interpretation of statements using structured operational se-
mantics. The basic notion in such a semantics is that of a transition relation -+
between pairs (configurations) (S, (f) where S is a contract statement and (f a state.
The relation (S, (f) -+ (S', (f') holds (and we say that a transition from configura-
tion (S, (f) to configuration (S', (f') is possible) if one execution step of statement
S in state (f can lead to state (f', with statement S' remaining to be executed. Ex-
14.l. Game Interpretation 235
ecution terminates when a configuration (A, 0') is reached, where A is the empty
statement symbol.
In our operational semantics, a configuration is a pair (S, 0'), where
We take the point of view of the angel with regard to the notions of failure and
success. Thus, success means that the angel has won while failure means that the
angel has lost. From the demon's point of view, success is something to avoid.
The transition relation (Le., the permitted moves) is inductively defined by a col-
lection of axioms and inference rules. The relation -+ is defined to be the smallest
relation that satisfies the following:
Angelic update
R.O'.y R.O' = 0
({R}, 0') -+ (A, y) , ({R}, 0') -+ (A,..1) ,
Demonic update
R.O'.y R.O' = 0
([R], 0') -+ (A, y) , ([R], 0') -+ (A, T) ,
Sequential composition
(S"O')-+(S;,y), S;;i:A (S" 0') -+ (A, y)
(S, ; S2, 0') -+ (S; ; S2, y)
Angelic choice
kel 1=0
u i E 1 Si), 0') -+ (Sk, 0') , Ui e I Si), 0') -+ (A,..1)
Demonic choice
kel 1=0
ni e I Si), 0') -+ (Sk, 0') , ni e I Si), 0') -+ (A, T)
These axioms and inference rules formalize the informal description given above
of the moves in the game.
236 14. Statements as Games
Classification of Configurations
Since there are no rules for empty configurations of the form (A, 0'), moves are
possible only in configurations (S, 0') where S is a proper statement. Furthermore,
by inspecting the rules, we notice that for any given configuration (S, 0'), at most
one of the axioms and inference rules is applicable. If S is an angelic update or
an angelic choice (join) of statements, then only the angel can make a move. In
this case we say that the configuration (S, 0') is angelic. Dually, if S is a demonic
update or a demonic choice of statements, then only the demon can make a move,
and the configuration is called demonic. Finally, if S is a sequential composition,
S = S) ; S2, then the possible transitions are given by the possible transitions of
S). In this case, we say that the configuration is angelic if (S), 0') is angelic and
demonic if (S) , 0') is demonic. This means that every configuration is either empty,
demonic, or angelic.
Plays
A play of the game S in initial state 0' is a sequence of configurations
Co --+ C) --+ C2 --+ ...
where
(i) Co = (S,O'),
(ii) each move C j --+ C j +1 is permitted by the axiomatization above, and
(iii) if the sequence is finite with last configuration Cn' then C n = (A, y), for
some y E r U {T, .L}.
Intuitively, a play shows us, step by step, what choices the demon and the angel
have made in a sequence of moves. A finite play cannot be extended, since no
moves are possible from an empty configuration (in fact, infinite plays are never
possible; see Lemma 14.1 below).
The game interpretation of contract statement S, denoted by gm.S, is a function
that maps each initial state 0' to the set of plays of S in initial state 0'. The game
interpretation of S thus describes for each initial state 0' the possible behaviors of
the angel and the demon when following contract S.
For a given goal q, we say that the angel wins a play of a game (or the play is a
win) if the final configuration (A, 0') satisfies 0' E q U {T}.
Example Game
Let us illustrate the concepts introduced above with the following simple game. A
state of the game is given by an integer x. Let inc.x.x' == (0 ~ x < x' ~ 2) and
14.1. Game Interpretation 237
dec.x .x' == (0 ~ x > x' ~ -2), where x ranges over the integers. The rules of the
game are given by the statement
In both these cases the angel wins the play, since the state component of the final
(empty) configuration is in both cases in the set q = {-2, 2}.
238 14. Statements as Games
Figure 14.1 shows all possible sequences of moves of the game described above
when the initial state is x = 0 (in this figure, we have decorated the transition
arrows with A and D to indicate whether the angel or the demon makes the move).
As this example shows, a given initial configuration can permit a variety of plays,
with very diverse outcomes (final configurations). In accordance with our game-
theoretic point of view, we are interested in what sets of outcomes the angel can
force the game to reach, regardless of how the demon makes its moves. We shall
consider this in the next section, but first we show that all plays are necessarily
finite.
2 2 -2 -1 2
A D A D A A A A
2 1. T 1. -2 1. 1.
Termination
A game always ends with either the demon or the angel winning. This is because
all plays of a game S are finite. Intuitively, we can justify this by noting that every
move decreases the size of the game that remains to be played. The formal argument
requires us to be explicit about what we mean by the size of a game. This again
requires us to use ordinals. Readers who are not familiar with these may at this
point choose to first read Chapter 18 on well-founded sets and ordinals, before
going through the proof of the lemma.
Proof Define the following inductive ordinal measure on statement terms (includ-
ing the empty statement):
M.A 0,
M.{R} I ,
M.[R] I
M.(S,; S2) M.S2 + M.S,
M.(ni E I Sj) (limi E I M.Sj) +I
M.(u i E I . Sj) = (limi E I M.Sj) +I
This measure is well-defined, since I is always a set (this guarantees that the
measure of every statement is an ordinal). By induction on the structure of the
statement S, one can show that any move according to the transition relation --+
decreases this measure in the statement part of a given configuration (S, a). Since
the ordinals are well-founded, this guarantees that no configuration can permit
more than a finite number of moves. 0
Even though every play is finite, it is possible to devise games in which there is
no upper bound on the number of moves needed to play the game. The following
example shows this. Let R be an arbitrary relation and define statements Sn for each
natural number n by So = [R] and Sn+l = [R] ; Sn. Then consider the statement
(u n E Nat So) in any initial state a.1f we are given some purported bound m on
the number of moves, then the angel can start by making the move
We shall now use the operational semantics to define what a strategy is and what
it means for the angel to have a winning strategy for game S in initial state a with
240 14. Statements as Games
respect to goal (postcondition) q. The idea is that a strategy (for the angel) tells the
angel what to do in each angelic configuration and that a strategy is winning if the
angel can win a game by always moving according to the strategy.
A strategy (for the angel) is a function I that maps configurations to configurations
in such a way that C ~ I.C holds for all angelic configurations C. Thus, given
an arbitrary angelic configuration C, a strategy I determines a transition (a move
for the angel) C ~ I.C.
Now assume that we are given statement S and initial state a. A strategy I admits
a play Co ~ C, ~ ... ~ Cn if Co = (S, a) and if C;+, = I.C; whenever
configuration C; is angelic.
The strategy I is a winning strategy for game S in initial state a with respect to
goal q if for every play (S, a) ~ ... ~ (A, y) admitted by I, the condition
y E q U {T} holds. Thus, I is a winning strategy if the angel is guaranteed to win
when it makes its moves according to I.
Obviously, we can define the notion of a strategy for the demon dually. However,
since the notion of winning is connected to the angel, we concentrate on strategies
for the angel.
Proof The proof is by induction over the structure of the statement S. In the
proof, we need a few additional notions about strategies. To simplify the reasoning,
we assume that strategies can be "undefined" for configurations that we are not
interested in (this undefinedness can be accomplished by augmenting the collection
of all configurations with an extra "undefined" element). The domain Dom.I of
a strategy I is the set of configurations for which I is defined. We further define
the domain 01 interest for a strategy I with respectto configuration (S, a) (written
IDom(j, S, a to be the set of all angelic configurations in all plays of (S, a)
admitted by I. Obviously, 1's restriction to IDom(j, S, a) determines whether
I is a winning strategy or not, since configurations outside IDom(j, S, a) cannot
occur while the game is being played.
14.2. Winning Strategies 241
We now consider the five cases of the inductive proof. Cases I and 2 are the base
cases (the two relational updates), while cases 3, 4, and 5 are step cases (meet, join,
and sequential composition).
(i) For the demonic update [R), the domain of interest of any winning strategy is
empty, since the angel never makes any moves. Thus,
winning strategy exists for [R) in a with respect to q
== {definitions}
for every transition ([R), a) -+ (A, y) we must have y E q U {T}
== {operational semantics}
R.a ~q
== {definition of update}
wp.[R).q.a
(ii) For the angelic update {R}, the reasoning is similar. In this case, the domain of
interest contains the single configuration ({R), a), and a winning strategy is one
that maps this configuration to some (A, y) where y E q U {T}. Thus,
winning strategy exists for {R} in a with respect to q
== {definitions}
there is a transition ({R), a) -+ (A, y) such that y E q U {T}
== {operational semantics}
R.a nq #0
== {definition of update}
wp.{R}.q.a
(iii) Next, we consider meets. For this part of the proof, we need to define a merge
of strategies. Assume that a set of strategies {I; liE I} is given. A strategy / is a
merge of this set if the following holds for all configurations (S, a):
configuration that is in the domain of interest of both (f, S, CT) and (f', S', CT'),
then both strategies must lead to a win from this configuration.
The induction assumption for the meet is now that for all i E I there is a winning
strategy for game Sj in initial state CT with respect to postcondition q if and only if
wp.Sj.q.CT holds. Then we have
f is winning strategy for (n i E I Sj) in CT with respect to q
=> {operational semantics, definition of winning strategy}
f is winning strategy for each Sj in CT with respect to q
== {induction assumption}
CVi E I . wp.Sj.q.CT)
== {definition of meet}
wp.(ni E I Sj).q.CT
so the existence of a winning strategy for the meet implies wp. (n i E I . Sj).q.CT.
For the reverse implication, the induction assumption tells us that for each i E I,
there exists a winning strategy ii for Sj in CT with respect to goal q. Let f/ be
the result of restricting strategy ii to the domain of interest of (ii, Sj, CT). The
observation above then guarantees that any merge of the strategies 1;' is a winning
strategy for (n i E I Sj).
(iv) Now consider join. First,
f is winning strategy for (u i E I . Sj) in CT with respect to q
=> {operational semantics, definition of winning strategy}
f is winning strategy for Sj in CT with respect to q, for some i E I
== {induction assumption}
(3i E I wp.Sj.q.CT)
== {definition of join}
wp.(Ui E I Sj).q.CT
so the existence of a winning strategy for the join implies (u i E I Sj ).q.CT. For
the opposite implication here, we note that if f is a winning strategy for Sj in CT
with respect to q, then we can adjust f so that f.ui E I Sj), CT) = (Sj, CT) to
get a winning strategy for (u i E I . Sj). This works because u i E I Sj), CT) is
necessarily outside IDom(f, Sj, CT).
(v) Finally, we consider sequential composition. First, we note from the definition
of the operational semantics that a play of the game SI ; S2 is of the form
(a) (SI, CTo) -+ ... -+ (A, CTrn) is a play of the game SI in initial state CTo, and
14.2. Winning Strategies 243
(b) (S2, am) --+ ... --+ (A, an) is a play of the game S2 in initial state am.
The induction assumption is that the statement of the theorem is true for S) and
S2. Assume that f is a winning strategy for S) ; S2 in initial state a with respect
to q and let p be the set containing all second (state) components of the final
configurations of plays of (S), a) admitted by f. Then define a strategy f' by
f'.(S, y) = f.(S; S2, y) so that f' is a winning strategy for S) in a with respect
to p. The induction assumption then tells us that wp.S\.p.a holds. Furthermore,
we know that f is a winning strategy for S2 in any initial state yEp with respect
to q, so the induction assumption tells us that (V'y E P WP.S2.q .y). Then
For the opposite direction, we assume that wp.(S) ; S2).q.a. Again, this means that
we have, with p = WP.S2.q,
The induction assumption then tells us that there is a winning strategy f for S)
in initial state a with respect to p and that for every yEp there is a winning
strategy gy for S2 in initial state y with respect to q. Now define f' such that
f'.(S; S2, 8) = (T ; S2, y) whenever f.(S, 8) = (T, y) for all S and all 8, and
f is undefined everywhere else. Next let g~ be the result of restricting gy to
IDom(gy, S2, y) for all yEp, and let g be a merge of f' and all the strategies in
{g~ lYE pl This makes g a winning strategy for S) ; S2 in initial state a with
respect to q, and the proof is finished. 0
Theorem 14.2 shows that the operational semantics uniquely defines the predicate
transformer semantics. Since the operational semantics contains information not
only about input-output behavior, but also about intermediate states, it is obviously
not possible in general to go the other way.
244 14. Statements as Games
= {simplify}
x=O
Let us then look more closely at refinement of contract statements. In the predicate
transformer semantics, the refinement S !; Sf is valid if and only if 01q u S.q.u =}
Sf .q .u) holds. With the game interpretation, this means that for any choice of goal
q and any choice of initial state u, if the angel has a winning strategy in S, then
it must also have a winning strategy in Sf. Thus, a refinement has to increase the
angel's possibilities of winning, or at least keep them the same.
The angel's possibilities of winning can be increased in two ways, either by adding
some choices for the angel or by removing some choices for the demon. Figure 14.2
shows a refinement of the previous game, where we have added two new choices
for the angel and removed two choices for the demon (the latter shown as dashed
lines). Note that when we remove the demon's only choice, then the result is an
empty choice for the demon, i.e., a miracle. As a result, the angel now also has a
winning strategy for establishing x = -I v x = I in initial state 0, besides also
being able to establish x = -2 v x = 2 as before.
n n
0 0
2 0 0
1\ 2
1\ !\ 2 -2 -1
i'\~
2
.~ A~
0
A Do D A A Ao
0
2 .L T .L -2 -1 .L .L
David Harel [72] introduced the idea of developing programs using AND/OR -trees.
These are quite similar to the games that we have presented here. The notion that
game semantics is a suitable operational interpretation for monotonic predicate
transformers was originally put forward by Back and von Wright [25].
The idea of viewing the interaction between a system and its environment as a game
has also been considered by Martin Abadi, Leslie Lamport and Pierre Wolper [1],
and by Moschovakis [110]. A different, operationally flavored, semantics using the
notion of games is given for a language similar to ours by Hesselink [82]. There
are also a number of similarities with the process algebras developed by Hoare
[88] and Robin Milner [101], in particular with the notions of internal and external
nondeterrninism. Process algebras do not, however, consider state-based programs.
The notion of total correctness is also not used there; instead, correctness is seen
as a simulation relation between automata.
14.5 Exercises
14.1 Consider the game
where dim = (x := x'II < x /\ x - 2 ~ x' < x) under declaration var x : Nat.
Assume an initial state where x = 6 and goal q = (x = 0). Compute two different
plays for this game, one of which is a win.
14.2 Assume that the program variable x ranges over the natural numbers. Draw trees
to illustrate the operational semantics of the following two statements:
Although S] and S2 denote the same predicate transformer (prove this!), the trees
are different. Is it possible to define an equivalence relation on this kind of tree
such that the trees representing two statements S and S' are equivalent if and only
if S and S' denote the same predicate transformer?
14.3 Consider the game
[x := x' I T] ; {y := y' I T}
under declaration var x, y : Nat. Assume an arbitrary initial state and goal q =
(x = y). Describe a winning strategy. Compare this problem with proving that
(Vx' 3y x = y) is a theorem.
(a) Show that this game denotes the same predicate transformer as the game given
in the preceding exercise.
(b) Assume an arbitrary initial state and goal q = (x '" 2). Describe a winning
strategy for S.
15______________________
Choice Semantics
S.u.q ~ S.q.u.
In other words, S is almost the same function as S, except for the ordering of the
arguments u and q. Obviously, S.u is a set of predicates, Le., a set of sets, so the
defining condition can be written equivalently as
q E S.U == S.q.u.
Lemma 15.1 Let S be a monotonic predicate transformer and u an arbitrary state. Then S.U is
upward closed; i.e.,
Lemma 15.2 Given an upward closedfamily ofsets ofstates Au ~ p(r) for every state u, there
is a unique monotonic predicate transformer S such that S.U = Au for all u.
q E S.U
== {definition of S and of S}
({AU Y' Y E Au}; [AY {,. {, E y]).q.u
== {statement definitions}
(3y y E Au /\ (V{" {, E Y :::} {, E q
== {subset inclusion is pointwise extension}
(3y Y E Au /\ Y ~ q)
== {Au was assumed to be upward closed}
q E Au
Choice Semantics
We now define the choice semantics ch.S of a contract statement S inductively, so
that ch.S is a function that maps every initial state to a set of predicates over the
final state space. The contract statement S (viewed through the game semantics) is
equivalent to the simple game in which the angel chooses a predicate q E ch.S.u,
and the demon then chooses a final state y E q. If ch.S.u is empty, then the angel
loses, since it cannot choose any predicate. Similarly, if the angel chooses the empty
predicate false, then it wins, since the demon cannot choose any state in false.
The choice semantics is defined inductively by the following rules, for arbitrary
contract statement S:
The intuition behind the definitions for the updates, meet, and join should be clear.
For sequential composition, the intuition requires some explanation. For each set
p that the angel offers the demon according to S" the demon chooses some state
u' E p. Thus, the angel can guarantee only what is common to all such states
(hence the intersection over u').
252 15. Choice Semantics
The derivation for the other base case (demonic update) is similar.
Next we consider the three step cases. First we have sequential composition, with
the induction assumption that ch.SI = WP,SI and Ch.S2 = WP.S2:
WP,(SI ; S2).q.a
== {definition of sequential composition}
wp.SI.(WPS2.q).a
== {induction assumption for Sd
(WP,S2.q) E (ch,SI.a)
== {induction assumption for S2}
{a' I q E Ch.S2.a'} E ch,SI.a
==
{ "'{=:*: choose p := {a' I q E Ch.S2.a'}
p ~ {a' I q E Ch.S2.a'} and upward closure
(3p E ch,SI.a 010" E P q E Ch.S2.a'))
== {set theory}
q E (U P E ch,SI.a (nO" E p' Ch.S2.a'))
For meet (the second step case) we have the following derivation, with the induction
assumption that ch.Sj = wp.Sj for all i E I:
wp.(ni E I Sj).q.a
== {definition of meet}
01i E I wp.Sj.q.a)
15.2. Comparing Semantics for Contract Statements 253
== {induction assumption}
(Vi E I . q E Ch.Si.a)
== {set theory}
q E (ni E I ch,Si.a)
Computing ch.S.a for a given statement S and initial state a can be very tedious.
since the inductive definition for sequential composition is complicated. Thus The-
orem 15.3 is an important help; it shows that we can compute the choice semantics
directly from the predicate transformer semantics.
Using the definitions of derived statements. we also get the following equations
for assertions. guards. and functional updates (Exercise 15.1):
Ch.{p}.a = {qlaEpnq}.
ch.[p].a = {q I a E ...., P U q} ,
ch.(f).a {q I I.a Eq}.
In particular.
ch.abort.a 0.
ch.magic.a P<r) ,
ch.skip.a {qlaEq}.
wp.S = ws.(gm.S).
The result that we proved about choice semantics and weakest precondition se-
mantics states that
ch.S = wp.S.
Let us further define ws'.G.a.q = ws.G.q.a. Then
ws'.G = ws.G .
254 15. Choice Semantics
Contract statements
Game semantics
ws~ws,
/
Predicate transformer ....4t------.......
~ Choice semantics
semantics
ch.S = ws'.(gm.S).
Thus, the diagram in Figure 15.1 is really a commuting diagram. It shows all three
semantic interpretations and the way these interpretations are related to each other.
As the figure shows, the game semantics is the most detailed one, while the two
other semantics are abstractions of the game semantics and derivable from each
other.
Corollary 15.4 The refinement relation on predicate transformers corresponds to pointwise set
inclusion for choice semantics; for all contract statements S, we have
Proof
wp.S ~ wp.S'
== {definition of refinement}
(Vq a wp.S.q.a => wp.S'.q.a)
== {definition ofS}
(Vq a wp.S.a.q => wp.S'.a.q)
== {pointwise extension}
(Va wp.S.a ~ wp.S'.a)
== {Theorem 15.3}
(Va ch.S.a ~ ch.S'.a)
o
Thus, refinement means adding sets of possible final states for the angel to choose
between. In terms of the game-theoretic interpretation, this implies that refinement
increases the choices of the angel. By duality, it is obvious that decreasing the
demon's choices is also refinement. Because the set ch.S.a is upward closed,
removing elements from a set of states that the angel can choose implies adding
new sets for the angel to choose between (a smaller set has more supersets).
The extended hierarchy of poset- and lattice-enriched categories is illustrated in
Figure 15.2.
PIran(l;, r)
~
Tran(l;, r) Pred(r)
r Bool
15.5 Exercises
15.1 Derive the choice semantics for the assert, guard, and functional update:
ch.{p}.a {q I a E p nq} ,
ch.[p].a {qlaE--.pUq} ,
ch.(f).a {q I f.a E q} .
15.2 Recall that a set A of sets is upward closed if the following holds:
01 A B A E A 1\ A ~ B :::} B E A) .
Show that if A and B are upward closed sets, then A n B is also upward closed.
15.3 Recall the definitions of Res and Stran:
15.5. Exercises 257
(b) Show that both Res and Stran are categories when composition in Res is set
intersection and composition in Stran is defined as follows:
(f; g).a = (U P E f.a (na ' E p. g.a '
for f : Stran(E, r) and g : Stran(r, ,1.).
15.4 Use the inductive definition to compute the choice semantics for statement
{dim} ; [dim] ; {dim} ,
where dim = (x := x' I 1 < x 1\ x - 2 ::::: x' < x). Assume a state space Nat (so
x.a = a) and initial state x = 5.
15.5 Derive the choice semantics for if g then SI else S2 fi.
16______________________
Subclasses of Statements
Not only monotonicity, but also other homomorphism properties of predicate trans-
formers tum out to be important in modeling programming constructs. In this chap-
ter we study homomorphic predicate transformers, i.e., predicate transformers that
preserve some of the predicate lattice structure. We consider the four basic ho-
momorphism properties - bottom, top, meet, and join homomorphism - to see
to what extent the constructs in our statement language preserve these properties.
These homomorphism properties are closely linked to distributivity properties of
statements.
Homomorphism Properties
The homomorphism properties of basic statements are given in the following
theorems.
Theorem 16.1 Let state transformer f, state predicate p, and state relation R be arbitrary. Then
(a) {p} is conjunctive and universally disjunctive.
Proof We show the proof for conjunctivity of assert; the other proofs are similar.
/ nonempty
I- {p}.(ni E / . qi)
= {definition of assert}
16.1. Homomorphic Predicate Transformers 261
p n (n i E I qi)
= {infinite distributivity, I nonempty}
(n i E I P n qi)
= {definition of assert}
(ni E I ' (P}.qi)
o
Table 16.1 shows the homomorphism properties of the basic statements. In this
table, as in others, n and u stand for arbitrary nonempty meets and joins. We
see that the functional update (f) has all possible homomorphism properties as a
predicate transfonner: it even preserves negations. The assert {p) is nearly as well
behaved, but it does not necessarily preserve top or negation. Dually, the guard [p]
does not in general preserve bottom or negation. The relational updates have even
fewer homomorphism properties.
Since the basic statement constructors (sequential composition, meet, and join)
can have two or more statement arguments, we consider joint preservation of
homomorphism properties. For example, joint strictness preservation of sequential
composition means that SI ; S2 is strict whenever SI and S2 are both strict.
(a) Sequential composition preserves joint strictness and joint termination, joint
conjunctivity and joint disjunctivity, and joint negation homomorphism.
is .1 T n u ...,
{p} yes no yes yes no
[p] no yes yes yes no
(f) yes yes yes yes yes
{R} yes no no yes no
[R] no yes yes no no
sds2.(ni E I qi
= {S2 conjunctive}
S,.(ni E I S2.qj)
= {S, conjunctive}
(ni E I SdS2.Qi
= {definition of composition}
(n i E I (S, ; S2).Qi)
Table 16.2 shows for each statement constructor (composition, meet, and join)
which homomorphism properties it preserves. Thus, we have that sequential com-
position is the most weIl behaved, preserving all homomorphism properties. The
other operations are less weIl behaved. For instance, meets do not preserve join
homomorphisms or negation homomorphisms, while joins do not preserve meet
homomorphisms or negation homomorphisms. These results generalize directly to
indexed meets and joins.
As a direct consequence of the above theorems, we find that skip has all homo-
morphism properties, abort is conjunctive and universally disjunctive, and magic is
disjunctive and universally conjunctive. For the other derived statements we have
the foIlowing result.
Theorem 16.3 The derived statement constructors preserve homomorphism properties in their
statement arguments as follows:
(b) The guarded conditional preserves (joint) strictness, termination, and con-
junctivity.
preserves 1.. T n u
yes yes yes yes yes
n no yes yes no no
U yes no no yes no
preserves J.. T n u -.
(AS, T if g then S else T fi) yes yes yes yes yes
(ASI, ... , Sn if gl -+ SID'" 0 gn -+ Sn fi) yes yes yes no no
(AS begin var y := e ; Send) yes yes yes yes no
Left Distributivity
Sequential composition always distributes from the right over lattice operations (see
Section 12.2) but does not in general distribute from the left over these operations.
To get distributivity from the left, we need additional homomorphism assumptions
on the components of the sequential composition, in the same way as we needed
additional assumptions for monotonicity of sequential composition.
Theorem 16.4 Let S and Si be predicate transformers,for i in some nonempty index set I. Then
S; abort abort if S is strict,
S; magic magic if S is terminating,
S; (n i E I Si) (niEIS;Si) if S is conjunctive,
S ; (u i E I . Si) (u i E I . S; Si) if S is disjunctive,
S; (-'T) -.(S; T) if S is -.-homomorphic.
Theorem 16.5 Assume that procedure N(var x, val y) is defined as statement S, either globally or
locally. Then any call N(u, e) is strict (terminating, conjunctive, disjunctive) if S
is strict (terminating, conjunctive, disjunctive).
Proof By the definition, a procedure call N (u, e) is equal to a statement of the form
begin var y' := e; N.u.y' end. The result now follows, since N.u.y is the same
as S, except for a change in variable names, and since deterministically initialized
blocks preserve the four basic homomorphism properties. 0
Since both conjunctivity and disjunctivity imply monotonicity, we find that Ctran
and Dtran are both subcategories of Mlran. Similarly, Ftran is a subcategory of both
Ctran and Dtran (see Figure 16.1).
Lemma 16.6 also shows that we get subcategories of Ptran when we use strict-
ness and termination as restricting properties. We consider these as giving a sec-
ondary classification and use superscripts (..L and T) on the names to indicate these
additional restrictions. Thus, for example,
Ptran
Mlran
The reader should be warned that not all homomorphism properties are visible
from a name; if S E Clran, then S is not only conjunctive but also monotonic (since
conjunctivity implies monotonicity).
Some of the subcategories of Ptran that we have identified come in dual pairs. For
example, Clran T and Dtran.L are dual. Because of the general duality principle,
every property of a class immediately implies a dual property for the dual class.
16.4 Exercises
16.1 Show that the assert {p} is universally disjunctive but not terminating.
16.2 Show that the demonic update [R] is universally conjunctive.
16.3 Prove Theorem 16.3.
16.4 In Dijkstra,'s original formulation of the "healthiness conditions" for predicate
transformers, finite conjunctivity was required, rather than the (positive) conjunc-
tivity used here. A predicate transformer S is finitely conjunctive if
We define the notion of correctness for predicate transformer statements and show
how to establish the correctness of statements. The relationship between correctness
and refinement is analyzed. We then show how to derive correct programs from
given specifications, using the stepwise refinement paradigm. Finally, we show how
the properties of predicate transformers that we have derived in previous chapters
permit us to find and justify individual refinement steps.
17.1 Correctness
Recall the definition of correctness for contract statements: S is correct with respect
to precondition p and postcondition q, written p ~ S ~ q, if (Va I a E p. a ~ S ~ q).
Hence, we have that
p ~S~q == p ~ wp.S.q
This motivates us to define the notion of correctness also directly for predicate
transformers: The predicate transformer S is correct with respect to precondition
p and postcondition q, denoted by p ~ S ~ q, if p ~ S.q holds.
Correctness Rules
For basic statements, correctness is reduced to properties of predicates, functions,
and relations.
(a) p fl {r} Dq == p ~ r nq ,
(b)pfl[r]Dq==pnr~q ,
Proof The results follow directly from the statement definitions and the definition
of correctness. 0
The last two correctness rules of this theorem can be written equivalently as follows:
p fl abort ~ q - p = false ,
pflskipDq - p~q,
p fl magic Dq - T.
For the compound statements, we have the following rules. These rules allow
us to reduce the correctness of a compound statement to the correctness of its
constituents.
p ~ SI.r, r ~ S2.q
I-p
~ {first assumption}
SI.r
~ {second assumption, S monotonic}
Sd S2.q)
= {definition of composition}
(SI ; S2).q
Hence the implication from right to left follows by the rule for eliminating existen-
tial quantification. Implication in the other direction follows directly by choosing
r = SI.q. 0
Note that the correctness rule for angelic choice Goin) permits the alternative Sj
that is chosen to depend on the present state (]" .
From the rules for update statements we can derive rules for assignment statements
when the precondition and the postcondition are Boolean expressions:
p nx := e ~ q - p ~ q[x := e] ,
p n[x := x'lb] ~ q - p ~ (Vx' b => q[x := x'D,
p n {x := x'lb} ~ q - p ~ (3x' b A q[x := x'D.
Rules for the correctness of derived statements are easily derived from the basic
rules. For the conditional statements, we have
We can use these rules from left to right (top-down) to reduce the correctness of
a larger program statement to a smaller one. This is the method that we use to
determine whether a given program statement is correct with respect to given pre-
and postconditions. The application of the rules in this direction is straightforward,
except for the sequential composition rule, which requires us to invent an inter-
mediate condition. The situation will be similar later on, when we consider how
to establish the correctness of loops. There we also have to invent an intermediate
condition, known as the loop invariant.
We can also use the rules from right to left (bottom-up), to gradually build up more
and more complex program statements. This could be one way to do explorative
programming.
There is an important difference between the Hoare-like axioms and inference rules
for establishing correctness, and the use of the predicate transformer semantics as
originally proposed by Dijkstra for the same purpose (aside from the fact that
Hoare's axiomatization is concerned with partial correctness and Dijkstra's with
total correctness). The former permits us to prove that a program is correct, if
indeed it is, but does not allow us to say anything about an incorrect program. In
the predicate transformer approach, the correctness assertion p fl S D q is just a
formula like any other, so we can try to prove it correct, or we can try to prove
it incorrect, or we can prove other desirable properties of statements. Hence, the
predicate transformer approach is more flexible than Hoare-like axiomatizations.
In addition, the predicate transformer formulation of correctness is done without
introducing any new axioms or inference rules, being essentially just an application
of higher-order logic. Hoare logic, on the other hand, requires a completely new
axiom system to be built, with its own notion of terms and formulas and its own
axioms and inference rules, usually built on top of a standard first-order logic.
17.2. Stepwise Refinement 273
Example
The following simple derivation illustrates the way in which these rules are used
to establish correctness of a statement. We show that
true nx := n; [y := y' I y' > x] D y > n .
Here x and y are program variables, and n can be either a constant, a free variable,
or a program variable (the derivation looks the same regardless of which alternative
is chosen). We have that
true Ux := n ; [y := y' I y' > x] D y > n
{= {sequential rule, x = n as intermediate predicate}
(" true Ux := n Dx = n ") J\ (x = n n[y := y' I y' > x] D y > n)
== {assignment rule}
"true ~ (n = n) " J\ (x = n U [y := y' I y' > x] G y > n)
== {reduction}
T J\ (x = n n[y := y' I y' > x] D y > n)
== {T greatest, demonic assignment rule}
(x = n) ~ 0/y' y' > x ::} y' > n)
== {reduction:0/x n x = n ::} 0/y' y' > x ::} y' > n)}
T
Proof
S!; S'
== {definition of refinement}
(Vq ." S.q ~ S'.q ")
274 17. Correctness and Refinement of Statements
== {mutual implication}
S.q ~ S'.q
=> {transitivity of inclusion}
(Vp. p :: S.q => p ~ S'.q)
S.q ~ S'.q
_ {reflexivity, T => rule}
S.q ~ S.q => S.q ~ S'.q
{= {specialization, p : = S.q}
(Vp. p :: S.q => P ~ S'.q)
(Vp q p ~ S.q => p :: S'.q)
== {definition of correctness}
(Vp q. p ~ S h => p fl S' h)
Note that the proof uses only the reflexivity and transitivity of the refinement
ordering, so it would hold even if refinement were only a preorder.
Plran
Correctness as Refinement
We have shown that refinement can be described in terms of correctness. We can also
describe correctness in terms of refinement. Let predicates p and q be given. Then
the statement {p}; [q] is a pre-post specification statement, where q = (ACT' q) is
the pointwise extension of the predicate q to a relation. This specification statement
establishes postcondition q whenever precondition p holds in the initial state.
An example of a pre-post specification is the statement
Proof
S monotonic
f- {p} ; [q] !; S
== {semantics of pre-post specification}
(\Ir CT p.CT 1\ q ~ r ::::} S.r.CT)
276 17. Correctness and Refinement of Statements
== {mutual implication}
C'lr u p.u 1\ q ~ r =? S.r.u)
=? {specializer:= q, simplify}
(Vu p.u =? S.q.u)
C'lr u p.u 1\ q ~ r =? " S.r.u ")
{:::: {monotonicity of S,local assumption q ~ r}
C'lr u p.u 1\ q ~ r =? S.q.u)
_ {quantifier rules}
(3r q ~ r) =? C'lu p.u =? S.q.u)
- {antecedent is trivially true}
C'lu p.u =? S.q.u)
(Vu p.u =? S.q.u))
== {pointwise extension}
p ~ S.q
From this we see that Sn is correct with respect to the original pre- and postcondition
pair:
p nSn Hq .
We can actually treat any statement as a specification. This enlarges the class of
specifications to abstract statements. An abstract statement need not be imple-
mentable, because it is not intended to be executed. It is just intended to serve as a
high-level description of the kind of behavior that we are interested in achieving.
Any refinement of the abstract statement is an implementation of it (the implemen-
tation mayor may not be executable). The notion of abstract statements permits
us to treat both implementation of specifications and program transformations as
two special cases of the general notion of refining a statement.
17.2. Stepwise Refinement 277
{x ::: O} ; (x := factorial.x) .
This requires that the initial state satisfy the condition x ::: 0 and that the final
state be such that x is set to the factorial of the original x without changing other
program variables.
An even more powerful way of specifying what final states are acceptable is to use
a relation Q between initial and final states, rather than just a predicate q on the
final state. This gives us a specification of the form {p} ; [Q], which we refer to
as a conjunctive specification statement. This requires that the precondition p be
satisfied and that for any initial state a E p the final state be in the set Q.a. If
this set is empty for some a, then the specification is impossible to satisfy for that
specific initial state.
This requires that x ::: 0 1\ e > 0 initially and that x be set to the integer square
root of its initial value with tolerance e.
Such a specification can always be reduced to the form with a single demonic
assignment (Exercise 17.5):
Specification Constants
A specification constant is a free variable introduced to name a certain value (for
example, the initial value of some variable) in a subsequent derivation. In this
section we justify the use of specification constants and show how they make it
possible to work with pre-post specifications {p} ; [q] rather than general con-
junctive specifications {p}; [Q] without losing generality. This will be particularly
useful in connection with loops, since there is a simple rule for refining a pre-post
specification into a loop (Section 21.6).
A specification constant is introduced as a fresh (free) variable in a statement.
Specification constants are not intended to appear in specifications or programs;
they are used as a vehicle for performing program derivations.
The following theorem justifies the use of specification constants.
Theorem 17.5 Let b be a Boolean expression with possible free occurrences of Xo. The following
rule for handling specification constants is then generally valid:
Proof We want to derive {3xo' b} ; S !; S' from (Vxo' {b} ; S !; S'). We have
<I>
I-- (VXo' {b} ; S I;; S')
== {definition of refinement}
(Vxo q a' b.a/\ S.q.a => S'.q.a)
== {quantifier rules, Xo not free in S or S'}
(Vq a (3xo' b.a) /\ S.q.a => S'.q.a)
== {pointwise extension}
(Vq a (3xo' b).a /\ S.q.a => S'.q.a)
== {definition of refinement}
{3xo b} ; S !; S'
The rule is used as follows. If we want to refine the statement {3xo t} ; S (where
Xo is variable that does not occur free in S), we start a subderivation from {t} ; S.
The assertion can then be used to simplify and refine S. Whenever we reach a
statement S' that does not contain Xo free, we can close the subderivation and
deduce {3xo t} ; S !; S'. Thus the specification constant does not occur free on
the outermost level in the derivation.
17.2. Stepwise Refinement 279
The simplest and most common use of specification constants is where Xo stands
for the initial value of some program variable x. Then the predicate t is x = xo,
and the assertion {3xo t} is trivially equal to skip.
Implementing Specifications
Using specification constants, we can derive a rule for reducing a refinement to a
correctness condition with program variables.
Theorem 17.6 Assume that statement S is built from assignments to program variables x and
y using statement constructors. The following rule for reducing refinement to
correctness is valid:
(p 1\ X = Xo 1\ Y = Yo) 0S ~ (b[x, x' := xo, x] 1\ Y = Yo)
{p}; [x := x' I b] !; S
Proof The assumption that S is built from assignments to x and y makes it possible
to prove (by induction over the structure of S) the following:
pOSh =>
(Au' p.u 1\ 17 =170) 0S ~ (Au' q.u 1\ (3x' y' 17 =set.x.x'.(set.y.y'.uo))) .
We then have (where bo abbreviates b[x, x' := xo, x])
(p 1\ x = Xo 1\ Y = Yo) 0S ~ bo 1\ Y = Yo
== {property above}
(Au' p.u 1\ 17 = 170 1\ x.u = Xo 1\ y.u = Yo)
OH
(Au' 3x, y, bo.u 1\ 17 = set.x.x,.(set.y.y,.uo) 1\ y.u = Yo)
== {use state attribute properties to rewrite}
(Au' p.u 1\ 17 = 170 1\ x.u = Xo 1\ y.u = Yo)
OS~
(Au' 3x, bo.u 1\ 17 = set.x.x,.(set.y.yo.uo) 1\ y.u = Yo)
== {Lemma 17.4}
{Au' p.u 1\ 17 = 170 1\ x.u = Xo 1\ y.u = Yo} ;
[Au 17' 3x, bo.u' 1\ 17' = set.x.x,.(set.y.yo.u) 1\ y.u' = Yo]
!; S
== {use assertion to rewrite}
{Au' p.u 1\ 17 = 170 1\ x.u = Xo 1\ y.u = Yo} ;
[Au 17' 3x, bo.u' 1\ 17' = set.x.x,.uo]
280 17. Correctness and Refinement of Statements
!; S
::::} {subderivation below, transitivity of!;}
{AO' p.O' /\ 0' = 0'0 /\ x.O' = Xo /\ y.O' = YO};
[AO' a' (3x' a' = set.x.x'.O' /\ b.O')]
!; S
== {rewrite to assignment notation}
{AO' p.O' /\ 0' = 0'0 /\ x.O' = Xo /\ y.O' = Yo}; [x := x' I b] !; S
and the result then follows from Theorem 17.5. The subderivation referred to above
is as follows:
{AO' p.O' /\ 0' = 0'0 /\ x.O' = Xo /\ y.O' = Yo} ;
[AO' a' . (3x' a' = set.x.x'.O' /\ b.O')]
!;
{AO' p.O' /\ 0' = 0'0 /\ x.O' = Xo /\ y.O' = Yo};
[AO' a' . 3Xl b[x, x' := Xo, x].O" /\ a' = set.x.xl'O'O]
== {use the rule {p}; [P] !; {p}; [Q] == Ipl; Q ~ P (Exercise 17.8)}
(VA a' Xl p.O' /\ 0' = 0'0 /\ x.O' = Xo /\ y.O' = Yo /\
b[x,x':=xo,x].O" /\O"=set.x.xl.O'O::::}
(3x' a' = set.x.x'.O' /\ b.O'))
== {one-point rule}
(Va' Xl pO'o /\ X.O'o = Xo /\ yO'o = Yo /\
b[x, X' := Xo, x].(set.x.xl'O'O) ::::}
(3x' set.x .XI.O'O = set.x .x'.O'o /\ b.O'o))
== {use Xl as existential witness}
T
The details of the last step are left as an exercise to the reader. 0
This shows that any refinement of the form {p} ; [x := x' I b] !; S can be proved
by proving a corresponding correctness condition. The correctness condition can
then be decomposed using the rules given earlier in this chapter, and in the end,
proving the refinement has been reduced to proving theorems that do not include
any programming constructs.
a conclusion of the form S = S' can also be used as a refinement law. We use
refinement laws to establish that the individual refinement steps are correct in a
derivation So ~ SI ~ ... ~ Sn.
We have already encountered numerous refinement laws. Essentially all the mono-
tonicity and homomorphism properties of statements proved in previous chapters
can be used as refinement laws. The monotonicity and homomorphism properties
that we have established for other entities in the refinement calculus hierarchy (state
transformers, state predicates, and state relations) are also very useful in program
derivation, because refinement of statements is often reduced to ordering or homo-
morphism properties at lower levels in the hierarchy. Below we look more closely
at some of the basic classes of refinement laws and justify their use in program
derivations.
Monotonicity Laws
The monotonicity properties that we have identified in earlier chapters are central
to the stepwise refinement paradigm. For example, we can write the monotonicity
law for assert as follows:
CI> I- p ~ pi
CI> I- {p} ~ {pi}
This rule tells us that if we prove CI> I- p ~ pi (in a subderivation), then we have
established {p} ~ {pi}, where CI> is the set of current assumptions. In practice, the
predicates p and pi are usually Boolean expressions, so proving p ~ pi can be
further reduced to proving implication between two Boolean terms. In this way,
refinement between statements is reduced to implication between Boolean terms,
two steps down in the refinement calculus hierarchy. This kind of reduction in the
hierarchy is very common. This is the reason why we have put so much emphasis
on all domains within the refinement calculus hierarchy.
CI> I- SI ~ S; CI> I- S2 ~ S~
CI> I- SI ; S2 ~ S; ; S;.
A step according to this rule in a program derivation has two subderivations, one
to establish CI> I- SI ~ S; and another to establish CI> I- S2 ~ S;'. In practice, we
usually leave one of the two substatements unchanged, and the trivial subderivation
(of the form S ~ S) is then omitted.
The general refinement rule for monotonic statement constructs is just a reformu-
lation of the monotonicity property:
282 17. Correctness and Refinement of Statements
<I> f- b l ~ b2 [x' := e]
(introduce assignment)
<I> I- {bIl ; [x := x' I b2] !; (x := e)
x' not free in <I> or bl.
To show that this is in fact a special case of the rule given above, we show corre-
spondence between the hypotheses. Assume that p is the Boolean expression bl ,
I is (x := e), and Q is (x := x' I b2). Then
Ipl;1/1 ~ Q
== {definitions of coercions, composition, and relation order}
0/u u" (3u' u' = U /\ p.u /\ U" = I.u') ::::} Q.u.u")
== {one-point rules}
0/u p.u ::::} Q.u.(f.u
== {assumption about p and f}
(Vu bl.u ::::} Q.u.(set.x.(e.u).u))
== {assumption about Q}
0/u bl.u ::::} (3x' ." set.x.(e.u).u = set.x.x'.u .. /\ b 2.u
== {state algebra property (Exercise 5.1)}
0/u bl.u ::::} (3x' e.u = x' /\ b2.U
17.3. Refinement Laws 283
== {one-point rule}
(Va bl.a ~ b2 [X ' := e].a)
== (pointwise extension}
b l ~ b2 [X ' := e]
[x:= x' I b); [y:= y' I c[x':= x)) = [x, y:= x', y' I b /\ c) .
Furthermore, if x and x' do not occur free in c and y and y' do not occur free in b,
then
S
= {exhaustion, unit}
[gU--'g];S
= {homomorphism}
([g] n [--. g]); S
= {distributivity}
[g];Sn[--'g];S
= {characterization of conditional}
if g then S else S fi
The following derivation outlines how the principle works in the case of block
introduction when S is a simple demonic assignment, where y does not occur free
inb:
[x := x' I b)
~ {properties of begin and end}
begin var Yip; skip end; [x := x' I b)
= {(end) = [y := y' IT] ; (end) by state attribute properties}
begin var Yip; [y := y' I T] end; [x := x' I b)
= ((end) ; [x := x' I b) = [x := x' I b) ; (end) by state attribute properties}
begin var yip; [y := y' IT] ; [x := x' I b) end
= {(end) = [y := y' I T] ; (end) by state attribute properties}
begin var yip; [y := y' I T] ; [x := x' I b) ; [y := y' I T] end
Now the assignments to y can be made more deterministic and/or merged with
other assignment statements. In this case, we can arrive at the following:
For a more complex statement S, the same idea is used, pushing the end of the
block past all substatements and adding assignments to y. The added variable y
is a ghost variable; it appears only in assignments to itself. However, once it has
been introduced, further refinement steps can make it play an active role in the
computation.
The rule for local variable introduction has refinement rather than equality, because
the initialization and the added assignment to the local variables may introduce
miracles. Thus it cannot directly be used for block elimination. However, if all the
assignments to a local (ghost) variable are nonmiraculous, then it can be eliminated.
Thus, if S is a statement built by statement constructors from assignment statements,
asserts, and guards only; and y occurs in S only as a ghost variable, and the
initialization p and all assignments to y are nonmiraculous; and y does not occur
free in q, and z does not occur free in p, then
Block Shunting
An alternative to the rules for block introduction and elimination is the following
shunting rule for blocks:
Theorem 17.7 Assume that the block begin var y := e; S end is well-defined, with global vari-
able(s) x, and that S is constructed by statement constructors from assignment
statements, asserts, and guards only. Then
{p 1\ Y = e}; [x, y := x', y' I b] !; S ==
{p}; [x := x'I b] !; begin var y := e; Send,
provided that y and y' are notfree in p or b.
Proof For the forward implication we do not need the assumption about S. An
outline of the proof is as follows:
{p 1\ Y = e}; [x, y := x', y' I b] !; S
=> {monotonicity of the block construct}
begin var y := e; {p 1\ Y = e}; [x, y := x', y' I b] end !;
begin var y := e; Send
== {drop redundant assertion}
begin var y := e; {p}; [x, y := x', y' I b] end!; begin var y := e; Send
== (push (end) leftward, use properties of state attributes}
(begin) ; (end) ; {p} ; [x := x' I b] !; begin var y := e; Send
== {homomorphism, begin; end = id}
{p}; [x := x'I b] !; begin var y := e; Send
The reverse implication in the first step is tricky to prove, since it depends on the
fact that the only state changes caused by statement S are changes in the attributes
x and y (this can be proved by induction on the structure of statement S). The full
proof is long and not very informative, so we omit it. For an indication of the idea
used, we refer to the proof of Theorem 17.6. 0
x := 0; y := x +1 !; x:= 0; y := 1
This holds even though y := 1 is not a refinement of y := x + 1. To prove
this refinement, we use the .fact that x must have the value 0 right after the first
assignment. Therefore (and this is easily verified using statement definitions)
x := 0 ; y := x +1 = x:= 0 ; {x = O} ; y := x +1 .
Intuitively, this holds because the added assert statement will necessarily act as a
skip. Next we note that
{x = O} ; Y := x +1 !; y:= 1 .
Transitivity then gives us the required result. The assert statement {x = O} is known
as a context assertion, and the refinement {x = OJ ; y := x + 1 !; y:= 1 is a
refinement in context. Intuitively, this says that y := x + 1 is refined by y := 1
when x = 0 initially.
We collect information about the context of statement S in a context assertion {p},
and then refine {pI ; s. A derivation that takes the context into account thus has
the following structure:
C[S]
= {introduce context assertion}
C[{p}; S]
!; {prove {pI ; S !; S', monotonicity}
C[S']
If we are faced with a statement S that has no initial assertion, then we can always
add the trivial assertion {true} (i.e., skip).
An important special case is where S is a detenninistic assignment. In this case we
get the rule
(p};(x:=e) = {p};(x:=e);{3xo x=e[x:=Xo]}.
We can also use guard statements [p] to indicate assumptions about the context
of a subcomponent to be refined. The use of such context assumptions is dual to
the use of context assertions. We will study the rules for adding context assertions
and assumptions in much more detail in Chapter 28 and will also study refinement
in context for different kinds of statements. Here we have limited ourselves to
introducing the basic ideas involved in this refinement technique.
When a block construct initializes a local variable, the initialization can be used as
context information when refining the block further. If S is written using program
variable notation (with global variables x) and the block adds local variables, then
we can generalize the local variable introduction in a simple way:
begin var z I b' ; {p} ; Send !; begin var y, z I b /\ b' ; {p /\ b} ; S' end,
provided that y does not appear in b' or S. Here S' is similar to S, possibly with
assignments to y added. The special case in which there are no local variables to
start with reduces to the following:
{p};S !; beginvarylb;{p/\b};S'end.
We leave the verification of this rule to the reader as an exercise (Exercise 17.12).
Example Derivation
We illustrate these rules by developing a program fragment that computes the
minimum of two numbers. We do not assume a min operator; instead we start from
a relational assignment.
[z := z' I (z' = x /\ x :::: y) v (z' = Y /\ X :::: y)]
= {introduce conditional}
17.5. Refinement with Procedures 291
let N = (Ax Y S) in
... begin var y' := e; N.u.y' end
sc S'
proc N(var x, val y) = Sin T 1; proc N(var x, val y) = S' in T
In practice, we assume that T is built from basic statements and procedure calls
N(u, e) using monotonic constructors only, so the rule can be applied.
292 17. Correctness and Refinement of Statements
In the first step S2 is syntactically like SI, but with assignments to c added (recall
that c is a ghost variable if it appears only in assignments to c). The added assign-
ments are chosen such that a certain relationship between c and a (the abstraction
invariant) always holds. This relationship is then used to refine S2 into S3, where
c has taken over the role that a played before and a has become a ghost variable.
Finally, in the block elimination S4 is syntactically like S3 but with all assignments
to a removed.
17.6. Example: Data Refinement 293
holds at every point of the block. After that, we make small changes to the program
text with the aim of making A a ghost variable.
=
{Vy yEA Y < m A C[y]} ;
[x := x' I x' A A (Vy y A => x' :-:: y)]
end
= {rewrite with local assumption (Vy. y E A' =elem.y.B)}
begin var A : Set of Nat, C : array Nat of Bool;
[A, C:= A', C ' I (Vy. Y E A' =elem.y.B) A
(Vy. elem.y.B =y < m A C/[y])];
[x := x'I (x' ~ m V ..... C[X/)) A (Vy Y ~ m V ..... C[y] => x' :-:: y)]
end
17.7. Summary and Conclusions 295
~ {split assignment}
begin var A : Set of Nat, C : array Nat of Baal;
[A := A' I 01y YEA' == elem.y.B)] ;
[C := C' I 01y elem.y.B == y < m A C'[y])] ;
[x:= x'i (x' 2: m V ""'C[x']) A 01y y 2: m v ..... C[y] =? x' ~ y)]
end
~ {eliminate local ghost variable A}
begin var C : array Nat of Baal;
[C := C' I 01y elem.y.B == y < m A C'[y])] ;
[x:= x' I (x' 2: m V ""'C[x']) A 01y y 2: m v ..... C[y] =? x' ~ y)]
end
Now we have reached a version in which the array C is used to represent the set of
numbers that occur in the array B. This version can be implemented in an efficient
way using rules for introducing loops (Chapter 21, Exercise 21.9).
John Reynolds [121], and Hehner [75]. An overview of earlier work is given by
Krysztof Apt [4].
The notion of refinement as a total correctness-preserving relation between program
statements and its formulation in terms of predicate transformers was introduced by
Back [6, 7]. Back [9] generalized the notion of refinement to preserving arbitrary
correctness properties and showed how this notion is related to the denotational se-
mantic view of approximation of statements, and to the Smyth ordering [119, 130].
He also introduced a notion of refinement that preserves partial correctness and
showed that the refinement relation that preserves both partial and total correct-
ness is equivalent to the Egli-Milner ordering [35, 118, 123] of (demonically)
nondeterministic program statements.
Specification statements as a way of expressing input-Qutput properties directly in
a programming language were introduced by Back [6], replacing correctness rea-
soning with a calculus of refinement. Morgan [104] used the pre-post specification
(with syntax x : [p, q]) together with rules for introducing structures rather than
correctness rules.
Specification constants have been a standard method of making postconditions
refer to initial values of program variables. Morgan developed a block with a
"logical constant" (essentially an angelically initialized local variable) to make
specification constants part of the programming notation [106].
Stepwise refinement, essentially in the form of top-down program refinement, was
originally introduced as a systematic programming technique by Dijkstra in the late
'60s and early '70s [51]. Wirth was also an early proponent of the technique, and
he published an influential paper on the practical application of the stepwise refine-
ment method to program derivation [141]. Hoare's axiomatic correctness calculus
was also inspired by the stepwise and top-down method for program construction,
and he illustrated a formal approach to top-down program construction in an early
paper [86]. The formalization of this method based on Dijkstra's weakest precon-
dition calculus was the original motivation for developing the refinement calculus
[6,7]. Since then, the refinement calculus has become much broader in scope and
aim, but the stepwise refinement method is still one of the main motivations for
studying and applying this calculus.
The top-down program derivation method has continued to be one of the main
programming methods taught in programming courses. The basic idea is one of
separation of concerns, articulated by Dijkstra in his early work: one should try
to separate the issues and design decisions to be made, and attack one problem
at a time. The simple top-down derivation method has also some disadvantages.
It tends to lead to large, monolithic, single-purpose programs that are difficult to
reuse.
The advantage of the refinement calculus for top-down program construction is
the possibility of using specification statements and the possibility of combining
17.8. Exercises 297
17.8 Exercises
17.1 Prove the following rules for total correctness:
17.2 Prove the correctness rules for the deterministic conditional and for the block
construct.
17.3 Use the rules for relational assignments to prove the following correctness asser-
tions:
<I> I- Ipi ; If I C Q
<I> I- {p}; [Q] !; (f) .
298 17. Correctness and Refinement of Statements
17.10 Use rules for introducing conditionals and assignments to refine the following
specification:
z :=x;
if y < z then z := y else skip fi .
17.12 Verify the principle of block introduction with context information:
var x f- {p}; S ~ begin var y I b; {p 1\ b} ; S' end,
where S' is similar to S, provided that y does not appear in S.
17.13 Recall that statement S is finitely conjunctive if s.(pnq) = s.pns.q for arbitrary
predicates p and q. Define Corr(p, q) (the correctness category for precondition
p : peE) and postcondition q : per~ to be the set of all finitely conjunctive
statements S satisfying pUS ~ q. Show that for any given collection of underlying
state spaces, the collection of all Corr(p, q) is a category.
17.14 Prove the following property of the correctness category:
p n S.true !; S.q.
Now let S = (x := 0) U (x := 1) and T = {x = l}, with predicates p = true,
q = (x = 0), and r = (x = 0). First show that S; T = (x := 1). Then prove that
p 0S Dq and q 0T Dr, but not p 0S ; T Dr.
18______________________
So far, we have looked at lattices as a special kind of posets. In this chapter, we focus
on another important special kind of posets: well-founded sets and well-ordered
sets. Well-founded sets are partially ordered sets with the additional property that
it is possible to use induction to prove that all elements have a given property.
Well-ordered sets are simply well-founded sets on which the order is total.
Lemma 18.1 Assume that the set (W, !;) is well-founded and that
Wo ::J WI ::J W2 ::J
Proof If the chain is not finite, then the set {wn I n E Nat} does not have a minimal
element. 0
Well-Founded Induction
In any well-founded set W, the principle of well-founded induction is valid. This
principle states that in order to prove that a property p holds for all elements in W,
it is sufficient to prove that p holds for arbitrary w, assuming that p holds for all
v E W such that v c w. Thus, if W is well-founded, then
In the special case of the natural numbers, the principle of well-founded induction
is called complete induction. In fact, this principle can be shown to be equivalent
to the ordinary principle of induction on Nat (see Exercise 18.2).
Well-Ordered sets
Recall that a partial order is linear if for arbitrary a and b, either a !; b or b !; a
holds. A partial order that is both linear and well-founded is called a well-order.
Well-orders are central to the foundations of mathematics because of the well-
ordering principle, which states that every set can be well-ordered. This principle
can be shown to be equivalent to the axiom of choice, which states that for an
arbitrary collection A of nonempty sets there exists a choice function f that satisfies
f.A E A for all A E A. Because higher-order logic contains a choice operator,
the axiom of choice can be proved as a theorem (see Chapter 7). We return to the
well-ordering principle in Section 18.4 below.
The natural numbers is an example of a well-ordered set. Any subset of the natural
numbers is also well-ordered. Ordinals, introduced in Section 18.4 below, are also
well-ordered.
rep...zero " 0,
rep..suc.B " B U {EY : Ind' y B} .
304 18. Well-founded Sets and Ordinals
Ind
3-------
2-------
1 ______ _
o ------
Nat
We intend rep..zero (the empty set of individuals) to represent zero and rep_sue to
represent the successor function.
We can now describe the set that represents the naturals:
Natset ~
n {B : P(P(lnd I rep..zero E B /\ (VB B E B => rep_sue.B E B)}
This makes Natset the smallest set that contains rep..zero and is closed under rep..sue
(Exercise 18.3). We use here the convention that lower-case letters stand for el-
ements, upper-case letters for sets, and script letters for collections of sets. The
construction of the natural numbers type is illustrated in Figure 18.1.
We can now prove the following characterization lemma, which shows that Natset
is a suitable set to represent the natural numbers:
Nat ~ Natset.
As described in Chapter 10, this means that the abstraction and representation
functions abs : P(lnd) -+ Nat and rep : Nat -+ P(lnd) satisfy the following
properties:
18.3. Primitive Recursion 305
0/n abs.(rep.n) = n) ,
0/B B E Natset => rep.(abs.B) = B) .
Zero and the successor function now have obvious definitions; they are the abstrac-
tions of rep..zero and rep-suc defined earlier:
o 1\ abs.rep..zero,
suc.n 1\ abs.(rep-suc.(rep.n))
Having defined 0 and suc, we really do not want to refer to the functions abs and
rep any more when reasoning about the natural numbers. This is made possible by
a single theorem that characterizes the natural numbers completely, and which we
will describe next.
A detailed proof of Theorem 18.3 is beyond the scope of this text; it involves
proving numerous properties about the set that represents Nat (see Exercise 18.4).
Let us look at the primitive recursion theorem in some detail. It asserts that if we
are given an element g] of I; and a function g2 : I; ~ Nat ~ I;, then there always
exists a uniquely defined function f such that g] is the value of f at 0 and such
that g2 gives the value of f at any successor suc.n in terms of n and of the value
of f at n. This is a foundation for making primitive recursive function definitions.
Given g, and g2, the principle of constant definition then permits us to give a name
to the function whose existence is guaranteed by the primitive recursion theorem.
As a simple example of function definition by primitive recursion, we show how
to define evenness. We give the recursive definition in the form
Note that this is not a proper definition in higher-order logic, since even is "defined"
in terms of itself. In fact, we are here using the primitive recursion theorem with
306 18. Well-founded Sets and Ordinals
Induction
The primitive recursion theorem allows us to deduce that induction over Nat is
valid. To show this, we let p : Nat .... Bool be arbitrary and instantiate the type 1:
in the primitive recursion theorem to BooI:
(V81 82' 3!f : Nat .... Bool
(/.0 == 81) /\ (Vn f.(suc.n) == K2.(/.n).n
=> {definition of unique existence}
(VKI 82 fit h .
(/1.0 == KI) /\ (Vn ft.(suc.n) == K2.(/I.n).n) /\
(/2.0 == 8d /\ (\In h.(suc.n) == 82.(/2.n ).n)
=>
fl = fz)
=> {specialize fl := (>..m T) and h := p}
(VKI K2'
KI /\ (Vn K2.T.n ) /\ (p.O == KI) /\
(Vn p.(suc.n) == K2.(p.n).n)
=>
(>"m'T) = p)
18.4. Ordinals 307
Further Properties
It is also possible to prove the other Peano postulates as theorems, by specializing
g] and g2 in the primitive recursion theorem in suitable ways. The details are left
to the reader as an exercise (Exercise 18.5).
Since the Peano postulates are proved as theorems, we know that our construction
of Nat in fact gives us the natural numbers. Thus, the primitive recursion theorem
gives an abstract characterization of the natural numbers; no other facts are needed
in order to build the whole theory of arithmetic.
18.4 Ordinals
All natural numbers are constructed by repeated application of the successor oper-
ation, starting from zero. We now generalize this construction process by adding
limits. The objects that we construct using repeated application of the successor
308 18. Well-founded Sets and Ordinals
and the limit operations are called ordinals. It is well known that this characteri-
zation cannot be realized consistently in set theory; the collection of all ordinals is
"too big" to be a set. Thus there is no way of introducing the ordinals as a type in
higher-order logic. However, we introduce the notion of ordinals over a given type
1; and show that by choosing 1; in a suitable way, we have access to arbitrarily
large ordinals.
Construction of Ordinals
Assume that a type 1; is fixed. We shall now show how the type of ordinals over 1; is
constructed. Exactly as for the natural numbers, we let every ordinal be represented
by a set over 1;. Intuitively speaking, we get successively larger sets by adding one
element at a time or by taking the union of all sets constructed so far.
We first make the following constant definitions:
We now define the successor and limit operations for the ordinals, in the obvious
way:
suc.a ~ abs.(rep_osuc.(rep.a)),
Iim.A ~ abs.(rep_olim.{rep.a I a E An .
Intuitively speaking, these definitions imply that we simply take over the notions of
successor and limit from the representing set. We allow binder notation for limits,
writing (lim a EA f.a) for lim.{f.a I a E A}.
The least and greatest ordinals over ~ can now be defined in terms of the lim
operator:
o " Iim.0,
maxord " Iim.Ord.
The greatest ordinal maxord has a slight anomaly; it has the undesirable property
of being its own successor (Exercise 18.8).
An Order on Ordinals
We define an order on ordinals, corresponding to subset inclusion on the represent-
ing set:
Lemma 18.6 Every ordinal over ~ except maxord is either a successor ordinal or a limit ordinal
(but not both):
We have that Natset ~ Ordset(lnd); i.e., the set that represents the type Nat is
a subset of the set that represents the type of ordinals over Ind. Furthermore,
UNatset represents a nonzero limit ordinal (Exercise 18.7). This ordinal is called
310 18. Well-founded Sets and Ordinals
("omega") and is the first infinite ordinal. The ordinals thus extend the natural
(J)
numbers past the first infinite ordinal. The ordinals (over some sufficiently large
type 1:) form a "sequence" of the form
0, 1, 2, 3, ... , (J), (J) + 1, (J) + 2, (J) + 3, ... , (J) 2, (J) 2 + 1, . .. .
This theorem gives a foundation for defining functions by recursion over the or-
dinals. Since 0 is the limit of the empty set of ordinals, we do not need a separate
conjunct for the zero case. In practice, though, functions are usually defined by
giving three clauses: one for zero, one for successors, and one for (nonzero) limits.
Note that the successor clause is qualified; this is because maxord is its own suc-
cessor. Since every ordinal (except maxord) is either a successor ordinal or a limit
ordinal (but not both), the limit clause applies only when the successor clause does
not apply.
As an example, we define addition for ordinals. Rather than writing the definition
as one big conjunction, we give the three clauses separately:
a+O a,
a + (suc.b) suc.(a + b)
a+b lim{a + c I c < b} for nonzero limit ordinals b.
This makes addition a generalization of addition on Nat. Note that in the second
clause we permit b = maxord, since this makes both sides trivially equal to maxord.
Ordinal addition has certain surprising properties, such as not being commutative
(see Exercise 18.9).
finite, then the number of ordinals is also finite and the successor operation cannot
generate new ordinals forever. If ~ is infinite, then the limit operator sometimes
generates new ordinals but sometimes not. These facts have already shown up when
we needed to qualify the clauses in the recursion theorem for ordinals. We shall
now show that similar qualifications appear when we prove results that correspond
to the Peano postulates for Nat.
From the ordinal recursion theorem, it is possible to derive a principle of ordinal
induction (also known as transfinite induction):
Theorem 18.8 The following induction principle holds for arbitrary type ~ and arbitrary predi-
cate p : Ord(~) ~ Bool:
(Va a # maxord 1\ p.a =} p.(suc.a 1\
(Va isJimit.a 1\ (Vb b < a =} p.b) =} p.a)
=}
(Va p.a) .
In practice, we split an inductive proof into three cases; the zero case is considered
separately from the nonzero limits.
We can also prove a result corresponding to the second Peano postulate for the
natural numbers.
Lemma 18.9 With the exception ofmaxord, distinct ordinals have distinct successors:
Proof First, linearity is proved by proving that the subset order on Ordset is linear.
Then, well-foundedness is proved by showing that for an arbitrary nonempty set
A of ordinals, the ordinal
abs.(na EA rep.a)
is the smallest element in A. 0
312 18. Well-founded Sets and Ordinals
Induction Example
As an example of ordinal induction, we prove the following property of addition:
O+a = a.
The proof is by induction on a. The zero case follows directly from the definition
of addition. For the successor case, we have the following derivation:
o+ a = a, a oF maxord
I- 0 +suc.a
= {definition of addition}
suc.(O+a)
= {induction assumption}
suc.a
Finally, we have the limit case:
isJimit.a, a oF 0, CrIb b < a :::} 0 + b = b)
I-O+a
= {definition of addition}
lim.{O+b I b < a}
= {induction assumption}
lim.{b I b < a}
= {a is limit ordinal}
a
The ordinal induction principle now asserts that 0 + a = a holds for an arbitrary
ordinala.
Lemma 18.11 Assume that a type E is given. Then there exists a type Ord of ordinals such that
there is no injectionfrom Ord to E.
18.6. How Far Can We Go? 313
Proof Choose P(I:) as the underlying set for the construction of the ordinals.
The construction in Exercise 18.11 shows that the cardinality ofOrd(I:) is always
at least the same as the cardinality of P(I:). The result then follows from the fact
that for an arbitrary nonempty set A there can be no injection from P(A) to A. 0
We call a set of the form {a : Ord(I:) I a < ao} an initial segment of the ordinals
over I:. It is possible to show that for any two types of ordinals, Ord(I:) and Ord(r),
one is always order-isomorphic to an initial segment of the other. Thus, whenever
we have used two different types of ordinals in some reasoning, we can replace
the "smaller" by the "bigger". In fact, one can show that for any two well-ordered
sets, one is always order-isomorphic to an initial segment of the other. In particular,
we can consider Nat to be an initial segment of the ordinals. Thus, there is really
no confusion using the constants 0 and sue for both the natural numbers and the
ordinals.
Using the ordinals as an index set, we can also construct generalized ordinal-
indexed chains. If (A, ~) is any partially ordered set, an ordinal-indexed chain is
a monotonic function f : Ord -+ A. Ordinal-indexed chains are typically defined
by ordinal recursion, and ordinal induction can be used to reason about them. They
are useful for generalized limit arguments, in situations where the natural numbers
are not sufficient.
314 18. Well-founded Sets and Ordinals
18.8 Exercises
18.1 The lexicographical order!; on Nat x Nat is defined as follows:
18.3 Prove that the set Natset contains rep..zero and is closed under rep..suc, where
Natset =
n {B : Ind ~ Booll rep..zero E B 1\ (Vx' X E B =} rep..suc.x E B)}
Deduce that Natset is the smallest set that contains rep..zero and is closed under
rep..suc.
18.4 In the text, we have assumed that the primitive recursion theorem (Theorem 18.3)
is proved before any other properties of Nat. Show that it is possible to go the other
way, proving the primitive recursion theorem from the Peano postulates.
18.5 Prove the following two Peano postulates from the primitive recursion theorem:
(Vn : Nat 0 oF suc.n) ,
(Vm n : Nat suc.m = suc.n =} m = n) .
18.9 Prove the following properties of ordinal addition for any type of ordinals that
includes the first infinite ordinal co (see Exercise 18.7).
co+ 1 = suc.co,
1 +co = co.
This shows that addition of ordinals is not commutative.
18.1 0 Prove that the successor and limit operations on the ordinals are monotonic, in the
following sense:
a :5 b =} suc.a:5 suc.b ,
(Va EA 3b E B a :5 b) =} Iim.A:5 Iim.B .
Furthermore, prove the following property for the order on the ordinals:
18.11 Let some type 1: be given. Define a function I that maps any ordinal a =f. maxord
over 1: to the unique element b E 1: such that b rep.a 1\ b E rep.(suc.a). Show
that the restriction of this function to B = {a I a =f. maxord} is bijective. Now
define the relation:::: on B as follows:
Fixed Points
Proof We show that f has a least fixed point; the prooffor the greatest fixed point is
dual. In fact. we show that the least fixed point is given by (n x E A I f.x ~ x x).
We have
f.(nx E A I f.x ~ x x)
~ (f monotonic implies f.(nX) ~ (nx EX f.x)}
(nx E A I f.x ~ x f.x)
~ {replace every element by a larger element}
(nx E A I f.x ~ x x)
and
T
~ {derivation above}
f.(nx E A I f.x ~ x x) ~ (nx E A I f.x ~ x x)
~ {f monotonic}
f.(f.(nx E A I f.x ~ x x)) ~ f.(nx E A I f.x ~ x x)
== {general rule p.a == a E {b I p.b}}
f.(nx E A I f.x ~ x x) E {x E A I f.x ~ x}
~ {general rule x E A ~ nA ~ x}
(nx E A I f.x ~ x x) ~ f.(nx E A I f.x ~ x x)
so (nx E A I f.x ~ X x) is a fixed point. For arbitrary YEA. we have
fy=y
~ {a = b implies a ~ b}
fy ~ y
== {general rule p.a == a E {b I p.b}}
y E {x E A I f.x ~ x}
~ {general rule x E A ~ nA !; x}
(nx E A I f.x ~ x x) ~ y
so (n x E A I f.x !; x x) is in fact the least fixed point. 0
The least fixed point of f is denoted by lk.J. while the greatest fixed point is
by denoted by v.f. The set A is assumed to be the whole underlying type unless
otherwise stated explicitly. If there is danger of confusion. we write lk A.J to indicate
that we are considering the least fixed point on the set A. and similarly for the
greatest fixed point. The proof of the Knaster-Tarski theorem gives the following
explicit constructions of the least and greatest fixed points:
Thus the least fixed point is the meet of all prefixed points (a is a prefixed point of
f if f.a ~ a). Dually, the greatest fixed point is the join of all postfixed points (a
is a postfixed point if a ~ f.a).
We permit the use of J.t and v as binders. Thus, we can write (J.tx t) rather
than J.t.()..x t) and (v x t) for v.(J..x t). Similarly, we can use index notation
(J.tx EA t) for J.tA'(J..X t) and (v.x EA t) for VA.(J..X t).
The least fixed point of f is characterized by the following two properties (Exercise
19.1):
Lemma 19.2 Assume that A is a complete lattice and that the functions f E A ~m A and
g E A ~m A satisfy (Vx EA f.x ~ g.x). Then J.tA.f ~ J.tA.g and vA.f ~ VA.g.
Proof
f monotonic, g monotonic, f ~ g
is !;
(At /L.!) yes
(A/v.f) yes)
monotonic f
f.(/L.g) !; /L.g
== {unfolding least fixed point}
I(/Lg) !; g.(/L.g)
== {assumption I !; g, pointwise order}
T
The proof for the greatest fixed point is dual. 0
Theorem 19.3 Assume that a complete lattice A ~ 1: is given. Then there exists an ordinal y
such that for any junction f E A ~m A the least fixed point of f in A satisfies
I-t.f = fY ...1.
Proof The full proof is fairly long, so we only outline it here. First we note that
(by induction over ordinals)
Note from the proof of Theorem 19.3 that the ordinal y can be chosen so that it
does not depend on the function I, only on the complete lattice A.
In Chapter 22 we show that if the function I is continuous on A, then the natural
numbers are sufficient to index the approximations, so we need not go beyond the
first infinite ordinal w.
For greatest fixed points, the dual result holds, using coapproximations:
Corollary 19.4 Assume that a complete lattice A E is given. Then there exists an ordinal y
such thatlor arbitrary I E A ~ m A the greatest fixed point satisfies v. I = Iy. T,
where the coapproximations la.x are defined as lollows:
fo.x = x,
la+1. X I. (fa'x) for arbitrary ordinals a,
la. x (nf3 I f3 < a ffJ.x) for nonzero limit ordinals a.
Proof We show that h.(fa ...l) = ga ...l for an arbitrary ordinal a, under the
assumption hoi = g 0 h. The result then follows from Theorem 19.3. The base
case h ...l = ..l follows because h is continuous. The successor case is proved as
follows:
h.(f" ...l) = ga ...l
I- h.(fa+1 ...l)
= {definition of approximation}
19.3. Properties of Fixed Points 323
f
1:
1: 1l-f.1:
1 1 h
~
1 h
r r Il-g:r
g
h.(f.(f" ..1
= {assumption h 0 f = g 0 h}
g.(h.(/" ..1
= {induction assumption}
g.(g" ..1)
= {definition of approximation}
g,,+l ..1
Corollary 19.6 Assume that f : (r --+ r) --+ (r --+ r) and g : r --+ r are monotonic functions
on complete lattices and that x : r is fixed. Then
Proof Since the function (Ak k.x) is continuous (Exercise 19.3), we have
T
== {fusion theorem with h := (Ak k.x)}
(Ak k.x) 0 1 = g 0 (>"k k.x) =} (>"k k.x).(JL.f) = JL.g
== {definition of composition, extensionality}
CVh (Ak k.x).(f.h) = g.>..k k.x).h) =} (Ak k.x).(JL.f) = JL.g)
== {beta reduction}
CVh f.h.x = g.(h.x) =} JL.f.x = JL.g)
D
Lemma 19.7 Assume that A and B are complete lattices and that 1 E (A ~ B) ~m (A ~
B) and 1 preserves monotonicity. Then JLA-+B.J = JLA-+mB.f and VA-+B 1 =
VA-+mBI
Proof We show the proof for least fixed points. The existence of both fixed points is
guaranteed by Tarski's theorem. We show that each approximation /'" of JLA-+B.f
is monotonic. This guarantees that the approximations for JLA-+B.I and JLA-+mB.f
are pairwise equal, so the fixed points are also equal. For the base case, we have
1 ..1 monotonic
== {definition of approximation}
.lA-+B monotonic
== {constant function is monotonic}
T
Next, the successor case:
/'" ..1 monotonic
f- /"'+ I . .1 monotonic
== {definition of approximation}
f.(/'" ..1) monotonic
== {f preserves monotonicity by assumption, induction assumption}
T
19.3. Properties of Fixed Points 325
Generally, we say that J.t preserves property P if P.(J.t.f) holds whenever the
monotonic function I preserves P (and similarly for v). The above lemma then
shows that the fixed-point operators preserve monotonicity.
Lemma 19.8 Least fixed points preserve disjunctivity and strictness, while greatest fixed points
preserve conjunctivity and termination.
Proof We consider only least fixed points, as the properties for greatest fixed points
are dual. To prove that 11- preserves strictness we follow the same idea as in the proof
that J.t preserves monotonicity (Lemma 19.7); i.e., we show that all approximations
la of the fixed point J.t.1 are disjunctive if I preserves disjunctivity. For the base
case we know that abort is disjunctive. For the successor case the assumption that I
preserves disjunctivity tells us that I.(j",) is disjunctive if I", is disjunctive. Finally,
the limit case follows from the fact that joins preserve disjunctivity. Preservation
of strictness is proved in the same way as preservation of disjunctivity. 0
The following counterexample can be used to show that least fixed points do not
I
preserve conjunctivity. Let the function I : (Unit 1-+ Nat) ~ (Unit 1-+ Nat) be
defined as follows:
chaos if S C chaos,
[A.U x x ~ i + 1] if S C [A.U x x ~ i + 1] and
IS = S ~ [A.U x x ~ i] for i E Nat,
cho~se; [A.n x x ~ n] if S = choose; [A.n x x ~ n],
magic otherwise.
326 19. Fixed Points
This function is monotonic, so /L. f exists. From the definition itfollows that /L. f =
choose; [An x x ~ n] is the least fixed point (the only other fixed point is magic).
However, /L.f is not conjunctive, even though f preserves conjunctivity (f maps
all predicate transformers except /L.f to conjunctive predicate transformers). To
see that /L.f is not conjunctive, consider the collection of predicates {Pi liE Nat}
where Pi.X == x ~ i. Then /L.f establishes any Pi but not their meet (false). We
leave it to the reader to fill in the details of this argument.
In spite of the above counterexample, it is still possible that any least fixed point
(A/L X S) preserves conjunctivity when S is a statement built from asserts, demonic
updates, sequential composition, meet, and the statement variable X. This is true
in the case of tail recursion, since any tail-recursive statement can be written using
iteration statements that preserve conjunctivity (see Chapter 21), We leave the
general case as an open question; our conjecture is that it is in fact true.
preserves c 1. T n u
/L yes yes no no yes
v yes 1 no yes yes no
1for monotonicity preserving f
19.5 Exercises
19.1 Show that the least fixed point of a monotonic function I on a complete lattice is
characterized by the following two properties:
f.(/1-.j) = /1-./,
f.x !; x => /1-./!; x .
Furthennore, show that if the equality in the first property is weakened to !;, the
resulting two properties still characterize the least fixed point.
19.2 Show that the empty set is directed. Then show that every cpo must have a least
element. Finally, show that continuity implies strictness.
19.3 Show that the function (AI f.x) is continuous (in fact, it is a universal join
homomorphism).
20______________________
Recursion
(/-L X S; X n skip) .
This contract is executed by the demon first choosing either the left- or right-hand
side of the meet. If the first alternative is chosen, then S is executed, after which X
is replaced by (/-L X S; X n skip) and execution continues with this substatement. If
the second alternative is chosen, then the skip is executed and execution terminates.
This narrows the scope of what the weakest precondition of a recursive contract
can be, but does not determine it uniquely, as there may be more than one fixed
point for any given function. It is also possible that a function has no fixed point,
in which case the definition would not give a weakest precondition interpretation
to all contract statements.
The latter problem is settled by fixed-point theory. The predicate transformer wp.S
is built out of basic predicate transformers and X using sequential composition,
meets, and joins. Hence T !; T' ::} (AX wp.S).T !; (AX wp.S).T', when T
and T' are both monotonic predicate transformers (T and T' must be monotonic so
that sequential composition is monotonic in both arguments). Thus, (AX' wp.S)
is a monotonic function on the set of monotonic predicate transformers 1: 1-+ m 1:.
As 1: I-+m 1: is a complete lattice, the Tarski-Knaster fixed-point theorem shows
that this function has a (least and greatest) fixed point.
This means that we can study the satisfaction of recursive contract statements by
considering recursive predicate transformers (/-LX S) (standing for /-L.(AX S.
In this way, the properties of recursive contract statements, as far as satisfaction
of contracts goes, is reduced to properties of least fixed points of functions on
predicate transformers.
20.1. Fixed Points and Predicate Transformers 331
IO.abort abort,
r+l.abort = f.(r .abort) for arbitrary ordinals cx,
I" .abort = (lim.B I .B < cx If! .abort) for nonzero limit ordinals cx.
Theorem 19.3 then shows that J-L. I = fY .abort for some ordinal y. For v.f, we
have a dual formulation with coapproximations starting from magic.
For a given contract statement (J-L X S), we can define the approximations
S" .{false} of (J-L X S) in the same way as for predicate transformers. Each of
these approximations denotes a contract statement (remember that we also permit
contract statements that are joins over infinitely indexed sets of contract statements).
Assume that the approximation S" .{false} is executed in an initial state from which
execution of (J-L X S) is guaranteed to terminate. We can then think of a counter
initially set at the ordinal cx. Each time the recursive definition is unfolded, the
counter is decreased. If the ordinal is chosen large enough, then termination occurs
before cx = 0, and the effect of sa .{false} will be the same as the effect of (J-L.X S)
in this initial state. If the number of unfoldings needed is too large, then the effect
of S". {false} will be a breach of contract in this state.
As the ordinal cx is chosen larger and larger, more and more unfoldings are pos-
sible, and for more and more initial states S" .{false} will have the same effect
as (J-L X S). At y, we reach the point where all terminating executions are ac-
counted for. For those initial states from which unfolding is infinite, every ap-
proximation acts as abort. Hence, the effect of (J-L X S) will be the same as
the effect of SY.{false}, as far as satisfaction of the contract to establish some
postcondition goes. Hence wp.(J-LX S) = wp.(SY.{false}) for some y. By the
definition of weakest preconditions for contract statements, we then have that
wp.(SY.{false}) = (AX wp.SV.abort = (J-LX wp.S). This shows that the weak-
est precondition of a recursive contract statement should be taken as the least fixed
point of the corresponding function on monotonic predicate transformers in the
general case also.
This explains why S" can be seen as an approximation of the recursive contract
statement (J-L X S). In some initial states, the number of unfoldings needed for
(JL X S) to establish the postcondition may be so small that S" gives the same
result, but in some other states, cx may not be sufficiently large, so S" leads to a
breach of contract.
332 20. Recursion
Example
It may not be evident why we need to use ordinals when defining the approxima-
tions, i.e., why is it not sufficient to consider only the natural numbers (and their
limit (J). Let us therefore give an example where transfinite ordinals are needed to
reach the least fixed point. Consider the statement
The behavior of this statement in initial state x =1= 0 is to decrease the value of x
until x = I, when the execution terminates. In initial state x = 0, the program
variable x is first assigned some arbitrary nonzero natural number, after which the
same steps of decreasing x are carried out, eventually leading to termination when
x=l.
So = abort,
SI {x = I} ,
S2 {1~x~2};x:=1
Sn+1
= {definition of approximation}
{x = O}; [x := xii x' :::: 1] ; Sn U {x = I} u {x > I} ; x := x-I; Sn
= {induction assumption}
{x = O} ; [x := xii x' :::: 1] ; {I ~ x ~ n}; x := 1 u
{x = I} u
{x > I} ; x := x-I; {I ~ x ~ n} ; x := 1
= {simplification}
abort u {x = I} u {2 ~ x ~ n + I} ; x := 1
= {easily verified equality}
{I ~ x ~ n + I} ; x := 1
(for the rules used in the last two steps see Exercises 20.3 and 20.4).
Note that this statement behaves as abort when x = O. We can still continue the
process of computing approximations, getting
20.1. Fixed Points and Predicate Transformers 333
S",+l x:= I
S",+2 x:= I
(again, we get Sa+l by substituting Sa for X in the recursion body). At this point,
we have reached the ordinal where no new approximations are produced. This
means that the least fixed point is the functional update x := 1.
The need for transfinite ordinals does not, of course, not mean that execution of
a recursive statement could terminate after an infinite number of recursive calls.
Rather, this argument shows that if we want to set a counter at the start so that its
value can be decreased at each recursive call, then we have to set the counter to It)
(or higher) at the start.
X = skip n S ; X .
skip n S n S; S n S; S; S n . .. .
p ~ (U W E W Pw) ,
P<w ~ (U V E W I v < w Pv) .
Thus, p holds if some ranked predicate holds, while P<w holds if some ranked
predicate with a "lower rank" than that of pw holds.
We use ranked predicates to establish that a sequence of nested recursive calls
must eventually terminate. Essentially, the idea is as follows. Assume that the first
call is made in a state where some ranked predicate is true, i.e., in a state where
p holds. We need to show that each nested call is made in a state that satisfies
a lower-ranked predicate than that which the state of the previous call satisfied.
Thus, if a call is made in a state that satisfies the ranked predicate Pw, then the
nested call should be made in a state that satisfies P<w. Because the set of ranked
predicates is well-founded, there can then be only a finite number of nested calls,
and hence the recursion must terminate.
Recursion Introduction
We shall now derive a rule for recursion introduction based on the use of ranked
predicates. This rule states under what conditions it is possible to refine a statement
S by a recursive statement I-L.J. The rule is based on the following theorem.
Theorem 20.1 Assume that W is a well-founded set, f a monotonic function on monotonic pred-
icate transformers, and {Pw I w E W} a collection of state predicates indexed by
W. Then the following holds:
Proof Assume that {Pw} ; S ~ f. ({p <w} ; S) holds for all w E W. First we show
that
Thus,
{p}; S
= {definition of p}
{U WE W Pw}; S
= {homomorphism property of assertion, distributivity}
(u W E W {Pw}; S)
!; {(*) above}
{t./
From Theorem 20.1 we get the following rule for introducing a recursive statement,
when I is a Boolean expression and t an expression that ranges over some well-
founded set:
Recursion Elimination
The recursion introduction rule shows how we can introduce recursion in a deriva-
tion. The opposite, recursion elimination, is also sometimes useful. As already
noted, the principle of least fixed point induction is itself a rule for /J- elimination.
Another rule that can be used is the following:
(/J- elimination)
I-(/J-XS)=S
X not free in S.
In fact, this rule can be used both to introduce and to eliminate a (vacuous) recursion.
Similarly, the principle of greatest fixed point induction is itself a rule for v intro-
duction, while a (vacuous) greatest fixed point construct can be eliminated (and
introduced) using
(v elimination)
I- (v X S) = S
X not free in S.
Here each Zi is one of the variables Xl, ... , Xm , Yl, ... , Yn (the parameters), each
ej is an expression in the parameters, and the Zi are all distinct. Note that we do
not permit references to "global" program variables in a procedure body.
Intuitively, a call N(ZI, .. , Zm, el, ... , en) is executed as a statement
begin var Yl, ... , Yn := e" ... , en ; S[Xl, ... , Xm := Z" ... , Zm] end ,
and calls to N inside S are executed in the same way, recursively. If a formal value
parameter Yj has the same name and type as an actual reference parameter, then
the local variable Yj has to be renamed. To simplify the presentation, we assume
that no such name clashes occur.
Note that the intuitive interpretation of recursive calls means that the execution
builds up a collection of nested blocks with local variables. The same happens if a
recursive call to N inside S is within the scope of a local variable declaration.
20.3. Recursive Procedures 337
The following example should make this clear. Assume the following recursively
defined procedure with a single recursive call:
begin var z := 0 ;
(/LX ... (uxo, zoO {x, z = Xo, zo} ;x, y,z:= y,x + z,O;
X; x, y, z := xo, x, zo) ... )
end.
Before the recursive call, the old values of x and z are stored, while x plays the
role of y and y and z are reinitialized. After the call, x and z are restored, and y
takes back its old role.
Again, we assume for simplicity that if the procedure N is called from a state in
which a global variable z is used as a reference parameter, then the local variable
of the body has been renamed to avoid a name clash.
Procedure Introduction
From the rule for recursion introduction (Section 20.2) we can derive a rule for intro-
duction of recursive procedures. For simplicity, we assume only a single recursive
call in the body of the procedure definition.
Assume that N is a recursive procedure defined as
We show the proof for the special case when x = x. i.e., when the reference
parameters take their own places in the recursive calls. The proof of the general case
20.3. Recursive Procedures 339
Note the use of ellipsis to hide a context in this proof. We will use this device quite
frequently to shorten a derivation and to highlight the places where changes are
made in a term. Ellipses are used together with quotation marks: when we quote
a subterm in one step, then the ellipses denote the part of the term outside the
quotation marks in the next step.
340 20. Recursion
Here the hypothesis is that the required refinement holds for the formal procedure
parameters x and y, both of which may be lists of program variables. The conclusion
then permits us to infer that the required refinement holds for the actual reference
parameters x (a list of distinct program variables) and actual value parameters e (a
list of expressions). The proof is a short derivation:
{plY := e]}; [x := x' I b[y := e)] !; N(x, e)
;: {definition of procedure call}
{ply := e' ]} ; [x := x' I b[y := e)) !; begin var y := e; N.x.y end
;: {Theorem 17. 7}
(plY := e) /\ y = e} ; [x, y := x', y' I b[y := e)) !; N.x.y
;: {use assertion information to simplify}
{p /\ Y = e}; [x, y := x', y' I b) !; N.x.y
<= {weaken assertion}
{p} ; [x, y := x', y' I b) !; N.x.y
After this, we can replace any specification of the form {p[x, y := u, e]} ; [u :=
u' I b[x, x', y := u, u' , e)] with a procedure call N(u, e).
We want the argument n : Nat to be a value parameter and the result to be stored
in a reference parameter x : Bool. Thus our specification is
x:= even.n
20.3. Recursive Procedures 341
or, equivalently, {T} ; [x := x' I x' = even.n]. As invariant we use true and as
variant n. The derivation of the procedure is as follows:
{n = w}; [x, n := x', n' I x' = even.n]
!; {introduce conditional, simplify if-branch}
if n = 0 -+ x:= T
Dn > 0 -+ .. {n = w /\ n > O}; [x, n:= x', n' I x' = even.n]"
fi
= {characterization of even, context information}
.. {n = w /\ n > O}; [x, n:= x', n ' I x' = --.even.(n - I)]
= {split assignment}
.. {n = w /\ n > O}; [x, n := x', n' I x' = even.(n -1)]; x := --'X'"
Note how the refinement theorem for the procedure itself contains the value param-
eters as program variables, making the left-hand side look a bit more complicated
than we might want (here we must use a demonic assignment rather than a deter-
ministic one). However, the important thing is that we have a rule for deriving a
procedure that allows us to replace program statements with procedure calls.
Mutual Recursion
A mutually recursive definition is of the form
342 20. Recursion
We then have the following derivation, where S stands for the statement [x :=
x' I xl2 :5 n < (x' + 1)2]:
{12 :5 n < r2 /\r - I = w}; [x, n, I,r:= x',n',I',r' I xl2 :5 n < (x' + 1)2]
= {make assignment more deterministic}
{12 :5 n < r2 /\ r - I = w} ; [x := x' I xl2 :5 n < (x' + 1)2]
= {introduce conditional, simplify assertions}
if 1+ 1 = r -+- " {12 :5 n < r2 /\ r - I = w} ; s"
D1+1 + r)2/4 :5 n -+-
=1= r /\ (I
{I +1< r + r)2/4 :5 n /\ 12 :5 n < r2 /\ r - I = w); S
/\ (I
D1+ 1 =1= r /\ (l + r)2/4 > n -+-
{I + 1 < r /\ n < (I + r)2/4 /\ 12:5 n < r2 /\ r - I = w); S
fi
!; {introduce assignment}
20.5. Summary and Discussion 343
if 1 + 1 = r ~ x := 1
01+ 1 -:/= r A (I + r)2 /4 ~ n ~
{I +1< r A (I + r)2 /4 ~ n A z2 ~ n < r2 A r -I = w}; S
01+ 1 -:/= r A (I + d /4> n ~
{I + 1 < rAn < (I + r)2/4 A z2 ~ n < r2 A r -I = w}; S
fi
I;:; {weaken assertions}
if I +1= r ~ x := I
01+ 1 -:/= r A (I + r)2 /4 ~ n ~
{(l +r)2/4 ~ n < r2 Ar - (l +r)/2 < w}; S
01+ 1 -:/= r A (I + r)2/4 > n ~
{/2 ~ n < (l + r)2/4 A (I + r)/2 -I < w} ; S
fi
shown how recursive procedures with value and reference parameters are derived
and used.
Dijkstra's original weakest precondition calculus [53] did not handle recursion,
it did not use fixed points for defining loops, and it required that loop bodies
be continuous. The weakest precondition calculus was extended to recursion by
Hehner in [74]. A predicate transformer semantics for general recursion (including
mutual recursion) is given by Hesselink [78].
Ordinals were first used to describe recursion in terms oflimits by Boom [41], who
described his results in the framework of constructive mathematics. Dijkstra and
van Gasteren used fixed-point reasoning and well-founded induction for loops, to
avoid the restriction to continuity [55]. However, most authors have preferred to stay
within the realm of bounded nondeterminism (Le., continuity), where the natural
numbers are sufficient. A continuous semantics for unbounded nondeterminism can
be given, as shown by Back [8], but such a semantics cannot then be fully abstract;
Le., it requires additional information not related to the input-output behavior of
the program [5].
The original refinement calculus in [7] had only iteration constructs, and no general
recursion. Recursion with noncontinuous statements was added to the refinement
calculus by Back [12] using ordinals, essentially following Boom [41]. A fixed-
point version of recursion in the refinement calculus was given by Morris [108].
The rule for recursion introduction in the refinement calculus was first described
by Back in [11].
Greatest fixed points are used in a partial correctness framework but have not
attracted much attention in total correctness formalisms. An exception is David Park
[114], who used greatest fixed points to describe parallelism and fair termination.
Rules for introducing and reasoning about procedures, including recursive pro-
cedures, within the refinement calculus framework were given by Back [11].
Independently, Morgan also derived rules for procedures, but without recursion
[103].
20.6 Exercises
20.1 Show that the approximation Sw in the example in Section 20.1 is {I :::: x}; x : = 1,
while Sw+l is x := 1.
20.2 Assume that each predicate Pw in the ranked collection {Pw I W E W} (where W
is a well-founded set) is of the form I A t = w, where W does not occur free in I
or t. Show that the predicate (U W E W Pw) is 1.
20.3 Prove the following rules, which were used in Section 20.1:
20.6. Exercises 345
for an arbitrary value a. This shows that the statement (u Yo I (y = yo};S;y:= Yo)
manages to execute S but then restore y to its initial value.
20.6 Prove the following result used in the proof of the rule for procedure introduction:
(UYo I {y = Yo}; {p}; [x:= xii b]; y:= Yo) = {p}; [x:= xii b] .
20.7 Prove the following result used in the proofs of the procedure rules:
{p} ; x := xii b] !; begin var y := e; Send -
{p /\ Y = e}; [x, y := x', y' I b] !; S
20.9 Derive a recursive procedure for computing the greatest common factor (also
known as the greatest common divisor) for two positive natural numbers, using the
following properties of gef, whenever x and y are positive:
gef.x.x = x ,
x :5 Y => gef.x.y = gef.x.(y - x) ,
gef.x.y = gef.y.x .
The recursive constructs provide powerful programming tools. In the general case,
the body S of a recursion (11 X S) or (v X S) can be an arbitrary term of
predicate transformer type. An important special case of recursion is iteration, i.e.,
the repeated execution of a statement. In this chapter we consider different kinds
of iterations.
We introduce two basic iteration constructs, a strong iteration statement given by
the least fixed point construct and a weak iteration statement given by the greatest
fixed point construction. We study the monotonicity and homomorphism properties
of these statements and give rules for reasoning about iteration statements.
We then show how to describe ordinary program constructs such as while loops as
derived statements in terms of iterations. In particular, we derive correctness and
introduction rules for iteration statements and loops using the corresponding rules
for recursive statements.
21.1 Iteration
Let S be a monotonic predicate transformer. We define two basic iteration constructs
over S, strong iteration and weak iteration, as the following fixed points:
Predicate-Level Characterization
The two iterations can also be described using fixed points on the predicate level.
Tail Recursion
The choice of skip as the exit alternative (Le., as the second argument of the meet
in the body of the recursion) in the definitions of the iterations may seem arbitrary,
and in a sense it is. The following lemma shows how we get an iteration with an
arbitrary exit alternative T.
Lemma 21.2 Let Sand T be arbitrary monotonic predicate transformers. Then
(IL X S ; X n T) ,
(v X S; X n T) .
21.1. Iteration 349
Proof We have
SW ; T = (/-L X S; X n T)
== {definitions}
(/-L X S; X n skip) ; T = (/-L X S; X n T)
<= {fusion (Theorem 19.5) with h.X = X; T}
('IX (S ; X n skip) ; T = S; (X ; T) n T)
== {distributivity}
T
which proves (a). The proof for weak iteration is similar. 0
Statements of the form (/-L X S ; X n T) are important, since they model tail
recursion, i.e., recursion in which the body of the recursion has no substatement
that sequentially follows the recursive call. Thus Lemma 21.2 shows how tail
recursion can be written using strong iteration.
Lemma 21.3 Assume that S is a monotonic predicate transformer. Then soo.q = /-L.S.
Proof
(/L X S; X).q = /L.S
<= {Corollary 19.6}
('IT (AX S; X).T.q = S.(T.q
= {Il reduction, definition of composition}
T
o
Thus, soo.q = /-L.S for an arbitrary postcondition q. Intuitively, this means that
the predicate /-L.S characterizes those states from which repeated execution of S
eventually terminates miraculously.
Infinite repetition can be expressed using strong iteration (Exercise 21.5):
SOO = SW; magic .
This justifies considering the strong and weak iteration statements are more basic
that the repetition statement.
350 21. Iteration and Loops
Theorem 21.4 The iterative constructs S*, S"', and SOO are monotonic when restricted to a mono-
tonic argument S. Furthermore, they preserve monotonicity: if S is monotonic,
then so are S, S"', and Soo.
S!; S'
::} {monotonicity properties of statements}
("IX S; X n skip!; S' ; X n skip)
::} {monotonicity of pointwise extension}
(J..X S ; X n skip) !; (J..X S' ; X n skip)
::} {monotonicity ofleast fixed point, Lemma 19.2}
(/LX S; X n skip) !; (/LX S' ; X n skip)
== {definition of strong iteration}
S'" !; S''''
Monotonicity of S* is proved with the same argument.
is !;
(AS SW) yes
(>"S SO) yes l
(>..S SOO) yes 1
I monotonic S
Theorem 21.5 The iterations S* and SW and the infinite repetition SOO have the/ollowing proper-
ties:
(a) Weak and strong iterations are always strict, and infinite repetitions preserve
strictness.
S.false
= {Lemma 21.1 }
(v x S.x n false)
= {predicate calculus}
(v x false)
= {fixed point of constant function}
false
The proof for strong iteration is similar.
Next, Lemma 19.8 is used to show that weak iteration preserves conjunctivity and
that infinite repetition preserves disjunctivity. That infinite repetition preserves
conjunctivity follows directly from the fact that SOO .(n i E I p;) and (n i E
I soo .Pi) are both equal to ?L.S when I is nonempty.
To see that S preserves termination, we have the following derivation:
S terminating
f-- S .true
= {Lemma 21.1 }
(v x S.X n true)
= {predicate calculus}
(vx' S.x)
352 21. Iteration and Loops
preserves !; l.. T n u
(AS S"') yes yes no yes no
(AS S*) yes yes yes yes no
(AS. SOO) yes yes no yes yes
We leave the proof that infinite repetition preserves strictness as an exercise to the
reader (Exercise 21.6). 0
In fact, it can be shown that strong iteration also preserves conjunctivity. However,
the proof of this is most easily done after some further properties of conjunctive
statements have been investigated, so we postpone it to Chapter 29 (Theorem 29.7).
Proof Part (a) is really a special case of greatest fixed point induction:
T
== {specialize greatest fixed point induction}
r ~ (Ax S.x n r).r => r ~ (v x S.x n r)
== {,B reduction, Lemma 21.1 }
(r ~ S.r nr) => r ~ S*.r
21.4. loops 353
Note the similarities between the two rules in Theorem 21.6. The rule for strong
iteration is somewhat more complicated, as it makes use of ranked predicates. The
basic idea is that each execution of the statement S has to decrease the rank of the
predicate in order to guarantee termination.
Since preconditions can be strengthened and postconditions weakened, we imme-
diately get the following corollary for strong iteration.
Corollary 21.7 Assume that p and q are predicates and S is a monotonic predicate transformer.
Assume that trw I W E W} is a ranked collection of predicates. Then
if
(i) p ~ r,
21.4 Loops
We now consider a derivative of the strong iteration SW, the while loop and its
generalizations. The while loop is less general than strong iteration, and its syntax
is more restrictive. It models the standard while loop of imperative programming
languages.
While Loops
We define the construct while g do S ad as follows:
Proof We have
while g do S od.q
= {Lemma 21.8, definitions}
([g]; S)"'.(g U q)
= {Lemma 21.1}
(ILX ([g]; S).x n (g U q
= {definitions of sequential composition and guard}
(ILX ( .... g U S.x) n (g Uq
= {predicate property}
(ILX (g n S.x) U ( .... g nq
which proves the lemma. 0
21.4. Loops 355
do g, -+ S, 0 ... 0 gn -+ Sn od ~
while g, U ... U gn do [gIl; S, n ... n [gn] ; Sn od .
This gives the while loop as a special case, when n = 1:
Properties of Loops
We now investigate the monotonicity and homomorphism properties of loops.
Theorem 21.10 The while loop and guarded iteration are both monotonic with respect to mono-
tonic predicate transformer arguments. Furthermore, both loop constructs preserve
monotonicity.
Proof For the while loop, both properties follow from Lemma 21.8 and the
corresponding properties of strong iteration, the guard statement and sequential
composition. The properties for guarded iteration are then easily derived from the
properties for while loops and guarded conditionals. D
Theorem 21.10 shows that we can extend our syntax of monotonic statements with
the while loop and guarded iteration. Thus, whenever S is a monotonic statement,
while g do S od is then also a monotonic statement, and similarly for do ... od.
Tables 21.3 and 21.4 show the monotonicity properties ofloops.
The homomorphism preservation properties of loops are as follows.
Theorem 21.11 While loops and guarded iterations both preserve strictness. Furthermore, while
loops preserve disjunctivity.
Proof Since guards are conjunctive, sequential composition and strong iteration
both preserve conjunctivity, and while g do S od = ([g] ; S)W ; [..... g], it follows
that while loops preserve conjunctivity. Next, from Lemma 19.8 it follows that
while loops preserve disjunctivity. The proof of strictness is left to the reader as an
exercise. The properties of guarded iterations follow directly from the properties
of while loops and guarded conditionals. D
In fact, while loops and guarded iterations also preserve conjunctivity. This will
be proved in Chapter 29 (Theorem 29.7).
Note that the infinite repetition statement is a special case of the while loop
(Exercise 21.5):
preserves c .l T n u
(AS while g do Sod) yes yes no yes yes
(ASl ... Sn do gl -. Sl U ... Ugn -. Sn od) yes yes no yes no
Theorem 21.12 Assume that g is a predicate and S a monotonic predicate transformer. Assume
that trw I W E W} is a ranked collection ofpredicates. Then
Theorem 21.13 Assume that gl ... gn. p. and q are predicates and Si are monotonic statements
for i = 1... , n. Furthermore, assume that trw I W E W} is a ranked collection
ofpredicates. Then
p 0do gl - SID'" 0 gn - Sn od ~ q
provided that
358 21. Iteration and Loops
(i) p r,
(ii) (Vw E W rw n gj fl Sj ~ r <w),Jor i = 1, ... , n, and
(iii) r n -.g q.
where g = gl V .. V gn.
The first condition in Theorem 21.13 states that the loop invariant r holds initially;
the second condition asserts that each iteration of the loop preserves the loop
invariant while decreasing the rank of the particular predicate rw; and the third
condition states that the postcondition q is established upon termination of the
loop.
Once we have found a loop invariant, we may use it to modify the loop guard. We
have the following general inference rule for this:
<l> I- p (g = g')
<l> I- {p}; while g do Sod = {p} ; while g' do Sod '
provided that p is preserved by the loop; i.e., (g n p n S.true) fl S ~ p.
Example
As a simple example of loop correctness, we consider the following loop:
The first and third conditions are straightforward arithmetic truths. The second
condition is reduced using the assignment rule to get the following condition:
Theorem 21.14 Assume that g, p, I, and b are Boolean expressions such that x does not occur free
in b. Furthermore, assume that state expression t ranges over some well-founded
set. Then
(i) P ~ I,
{~g};whilegdoSod ~ skip
Example: Exponentiation
As an example of program refinement using loop introduction, we develop a pro-
gram for computing x Y , where x and y are program variables that range over natural
numbers. We start from the following specification:
[x,y,r:=x',y',r'lr'=x Y ].
360 21. Iteration and Loops
The idea is to compute the exponentiation step by step, storing intermediate results
in r. Note that the specification allows x and y to be changed arbitrarily. We will
make use of this freedom, but first we must introduce specification constants to
stand for the initial values of x and y.
We divide the derivation into two parts. The first part introduces specification
constants and a loop in which y is successively decreased. The loop body is a
demonic assignment, and in the second part we implement it in an efficient way.
x = Xo 1\ Y = Yo 1\ r =1 =} r x Y = x{;' ,
and the exit condition is
x 2Y = (X, X)Y
{y > 0 A r . x Y = x~};
x, y, r .=
[
x I , y I , r I I r
I
x Iy' = XoYo A Y I
< Y]
= {introduce conditional}
if even.y then
{even.y A y > 0 A r . x Y = x~} ;
[x, y, r := x', y', r' I r' . x ,y' = X6 A y' < y]
else
{odd.y A y >0 A r . xY = x~} ;
[x, y, r := x', y', r' I r' x 'Y' = x~ A y' < y]
fi
~ {introduce assignment in both branches}
if even.y then x, y := x . x, y/2
else y, r := y - 1, x . r
fi
We leave it to the reader to verify that the assignment introductions are correct.
Thus we have reached the following refinement of our initial specification:
[x, y, r := x', y', r' I r' = x Y ]
~ {above derivations, switch to guarded iteration}
r:= 1;
while y > Odo
if even.y then x, y := x . x, y/2
else y, r := y - 1, x . r fi
od
21.8 Exercises
21.1 Recall that an iteration operation for relations was defined in Chapter 9. Show that
the following homomorphism property holds:
[R]* = [R*].
21.2 Show the following properties for the weak iteration of an arbitrary statement S:
S;S* !; S*;S,
S*;S* = S*,
(S*)* = S*.
21.3 Investigate to what extent the properties of weak iteration in Exercise 21.2 hold for
strong iteration also.
21.4 Show that (x := x + 1)'" = abort and (x := x + 1)* = [x := x' I x ~ x'].
21.5 Show that the following characterizations of the infinite repetition statement are
correct:
SOO = S"'; magic ,
SOO while true do S od .
21.8. Exercises 363
(i) p ~ r, and
(ii) (Vw E W rw nS nr <w).
22 _______________________
In Chapter 19, we used ordinals to express fixed points as limits. In practice, the
natural numbers are sufficient as long as all statements involved are continuous.
In this chapter we will study the notion of continuity more closely and show how
fixed points and recursion are handled in the continuous case.
Continuity is a homomorphism property. A predicate transformer is continuous if
it preserves limits, and since limits are a special kind of join, continuity is in fact
a restricted form of join homomorphism. We consider continuity of statements,
identifying which statements are continuous and which constructors preserve con-
tinuity.
Continuity is important in computer science because it is connected with the notion
of what can be computed in finite time from a finite amount of input information.
We use continuity as a guiding principle in defining a subclass of statements that
one can consider as executable. The executable statements that we define generalize
the traditional guarded commands language to interactive statements, in which the
user can carry on a continued dialogue with the computer.
We first look at the algebraic notions of complete partial orders and continuity
in general. In subsequent sections, we then investigate in more detail continuity
properties of predicate transformers.
Recall that a subset C of a poset (A, ~) is directed if every finite subset is bounded
above and that the poset (A, ~) is a complete partial order (a cpo) if the limit
lim C (i.e., uC) exists for every directed subset C of A. A monotonic function
f : A --+ B, where A and B are complete partial orders, is continuous if it
preserves limits.
Note that a complete lattice is always a cpo. Any unordered set can be made into
a cpo by adding a bottom element (such a cpo is called aflat cpo).
We write A --+ c B for the set of all continuous functions f E A --+ B from a cpo
A to a cpo B. When A is a type 1;, then this set is itself a cpo with the pointwise
extended order. In general, A --+ c B need not be a cpo even if A and B are cpos.
The reason is the same as for monotonic functions A --+m B; antisymmetry need
not hold.
Lemma 22.1 Let type 1; and set B be cpos. Then the pointwise extension of B to 1; --+c B is
also a cpo.
Since limits preserve continuity (Exercise 22.2), we have the following result.
Lemma 22.2 The cpo (1; --+ c B, 1;) is a subposet of (1; --+ m B, 1;). Furthermore, limits give
the same result in (1; --+c B ,I;) as in (1; --+m B ,1;).
Lemma 22.3 Assume that f is a continuous function on a cpo A. Then f has a least fixed
point /-t.f. Furthermore, /-t.f can be described as a limit of a countable set of
approximations:
Basic Statements
Since limits are a special kind ofjoin, universally disjunctive predicate tmnsformers
are always continuous (note that since the empty set is directed, a continuous
predicate tmnsformer is always strict). Hence, we get the following result as an
immediate consequence of Theorem 16.1:
Corollary 22.4 The assert statement, the functional update, and the angelic update are all contin-
uous.
The demonic update need not be continuous, however. As a counterexample,
consider the demonic update
[x :=x' In.
This chaotic assignment assigns an arbitmry natuml number to x. Define qi to
be the predicate x < i, for i E Nat. Then {qj liE Nat} is an ascending chain.
368 22. Continuity and Executable Statements
which shows that [R].(limi E I qi) (limi E I [R].qi). Since the reverse
ordering follows by monotonicity, we have shown that if R is image-finite, then
[R] is continuous.
In order to prove the reverse implication, we now assume that R is not image-finite.
In particular, let a be arbitrary but fixed and assume that R .a. y holds exactly for
a set of distinct states y E {yj liE Nat}. (This argument assumes that R.u is
countable; otherwise we have to partition R .a into a countable number of nonempty
subsets and change the argument accordingly.) Define the ascending chain {qi liE
Nat} as follows:
qi = {Yj Ij < i} .
Then qi is a proper subset of R.a for all i. We have
However,
[R].(limi E Nat qi).U
== {definition of qi}
[R].(R.u).u
== {definition of [R]}
(Vy R.u.y ===> R.u.y)
== {predicate calculus}
T
which shows that [R] cannot be continuous. This shows that if [R] is continuous,
then R must be image-finite. 0
A basic constraint that we would expect any computing machine to satisfy is that it
should not be able to choose among an infinite number of alternatives in finite time.
If the machine attempts to make such a choice, then either the execution might not
terminate, because it has to spend some minimum amount of time on each case, or
else it systematically considers only a finite subset of the possible choices. In either
case, the machine would be guaranteed to terminate when executing the demonic
update [R] only if R is image-finite. In this way, continuity and executability
are linked, with continuity being a necessary (but not sufficient) condition for
executability. A more detailed discussion on executability, or computability, is
outside the scope of this book.
Statement Constructors
We shall now see that both sequential composition and joins preserve continuity,
while meets in general do not. However, meets preserve continuity under the same
condition as the demonic update statement does, i.e., when the choice is finite.
Theorem 22.6 Sequential composition and joins of predicate transformers preserve continuity.
Furthermore, SI n S2 is continuous ifboth SI and S2 are continuous.
Proof For finite meet, assume that SI and S2 are continuous and let {qi liE l}
be a directed set of predicates. Then
(SI n S2).(limi E I . qi)'U
== {definition of meet}
SI.(limi E I qi).U/\ S2.(limj E I qj).u
== {continuity, predicate calculus}
(3i E I SI.qi .u) /\ (3j E I S2.qj.U)
== {for ===> choose k with qi ~ qk and qj ~ qk; for {= choose i = j = k}
(3k E I SI.qk.U/\ S2.qk.U)
22.3. Continuity of Derived Statements 371
== {definition of meet}
(lim k E I (Sl n S2).Qk).0'
which shows that SI n S2 is continuous. The proofs for sequential composition and
join are left to the reader as exercises (Exercise 22.4). 0
The following counterexample shows that limits do not preserve conjunctivity (it
is deriVed from the counterexample for least fixed points given in Section 19.3).
Define a chain {Sj : Unit ~ Nat liE Nat} of conjunctive predicate transformers
by Sj = [Au x x ~ i). The limit of this chain is the predicate transformer
choose; [An x x ~ n), which is not conjunctive.
372 22. Continuity and Executable Statements
preserves .L T n u
lim yes no no yes
Table 22.2 presents a row for limit that can be added to Table 16.2 of homomorphism
properties.
We now consider to what extent conditionals, iterations, and loops preserve conti-
nuity.
Theorem 22.8 Both the deterministic and the nondeterministic conditional preserve continuity.
Proof The result follows immediately by rewriting the conditionals using asserts,
guards, and sequential composition and applying Corollary 22.4 and Theorem 22.6.
o
Next, consider iterations and loops. Strong iteration, infinite repetition, while loops,
and guarded iteration can all be defined as least fixed points, and hence as limits.
Thus they should all preserve continuity.
Theorem 22.9 Strong iteration, infinite repetition, while loops, and guarded iteration all preserve
continuity.
Proof We outline the proof for strong iteration; the other proofs are similar. Assume
that S is a continuous predicate transformer. Then SW is the limit of an ordinal-
indexed sequence of approximations starting from abort. By ordinal induction, it is
easily shown that every approximation in this sequence is continuous. For the base
case, we know that abort is continuous. For the step case, it follows from earlier
results that S ; X n skip is continuous if S is continuous. Finally, the limit case
follows from Theorem 22.7.0
Ho.g.S.q = false,
Hn+l.g.S.q = (-.g n q) U S.(Hn.g.S.q)
Then for continuous predicate transformer S and arbitrary predicates g and q,
22.4. Executable Statements 373
preserves lim
(AS, S2 if g then S, else S2 fi) yes
(AS, ... Sn if g, --+ S, 0 ... 0 gn --+ Sn fi) yes
(AS. SW) yes
~SS' 00
(AS. SOO) yes
(AS while g do Sod) yes
(AS, ... Sn do g, --+ S, 0 ... 0 gn --+ Sn ad) yes
is continuous. This follows from the fact that skip is continuous and that sequential
and conditional composition both preserve continuity. Next, we use Lemma 22.3
to construct the sequence
So = abort,
Sn+' = if g then S; Sn else skip fi ,
for which while g do Sod = (limn E Nat Sn). It is now possible to show (by
induction on n, Exercise 22.8) that Sn.q = Hn.g. S.q for all n and from the definition
of limits it follows that (limn E Nat Sn).q.u == (3n Hn.g.S.q.u). 0
We will enlarge the notion of execution of a program by considering not only the
computer that executes the program but also the user of the program, who executes
the program in order to achieve some specific goals. The user takes on the role of
the angel, while the computer has the role of the demon.
S .. - abort, (abortion)
skip, (empty statement)
x :=e, (multiple assignment)
SI; S2 , (sequential composition)
if gl .... SID... 0 gn .... Sn fi , (conditional composition)
do gl .... SID... 0 gn .... Sn od . (iterative composition)
Here x = Xl, ... , Xm is a list of program variables, e = el, ... ,em a correspond-
ing list of expressions, and gl, ... , gn Boolean expressions. We assume that the
standard types of higher-order logic are available, in particular truth values, natural
numbers, and integers, as well as records and arrays.
Let us extend this simple language by permitting general assert statements, blocks
with local variables, and procedure definitions and calls:
S .. -
{b} , (assert)
begin var X := e; Send, (block)
proc P(var x, val y) = SI in S2 , (procedure)
P(x, e) . (procedure call)
Here X and y are lists of program variables, and e is a list of expressions. The
procedure declaration may be recursive.
The basic statements (abort, the assert statement, skip, and the assignment state-
ment) are all conjunctive and continuous predicate transformers (and hence also
monotonic and strict). Sequential composition preserves both conjunctivity and
continuity, and so do conditional and iterative composition (Exercises 22.7 and
22.9) and blocks. Procedure calls are conjunctive and continuous if the procedure
bodies are.
We consider the extended guarded command language as a small executable pro-
gramming language (assuming that the expressions e in assignments and the guards
g in assertions, conditionals, and iterations can be evaluated). Hence, these state-
ments form a suitable goal for a program derivation. The demonic nondeterminism
22.4. Executable Statements 375
Doo abort,
DO i +1 [gIl; SI ; DO i n ... n [gn] ; Sn ; DOi n [--, (gl U ... U gn)]
In the game semantics, the angelic choice is executed by the angel. If there is an
i ~ 0 such that DOi .true holds in the current state, then we have that DOm = DOi for
each m ~ i. The angel chooses an alternative DOi for which DOi .true holds in the
current state. By the equivalence, it does not matter which alternative satisfying this
condition is chosen, as all have the same effect. If there is no alternative for which
this condition holds, then the angel has to choose one alternative nonetheless, but
will lose the game eventually because the demon can play the game so that the
abort statement inside the chosen DO i is eventually reached. After the choice, the
game continues with playing the selected DOi.
The notion of iteration in the execution of the iteration statement arises from
the way in which we suppose that the computer simulates the angel in choosing
the right alternative. We assume that the computer scans through the alternatives
Doo, DOl, D02, ... in this order, until it finds a statement DOn that satisfies the
required condition. If such a statement is found, then execution continues with it.
If, however, there is no such statement, then the scanning of the alternatives never
terminates, because there are infinitely many of these. Hence, we get an infinite
execution. The angel, on the other hand, can with infinite foresight immediately pick
the right number of iterations and so chooses the right approximation directly. The
different ways in which the computer and the angel execute a loop are illustrated
in Figure 22.l.
The computer execution of iteration is closely related to the game interpretation.
The computation can be infinite (nonterminating), but it is always finitely wide for
continuous statements (i.e., there is never a choice of more than a finite number
of alternatives). In the game interpretation, there are no infinite computations, but
there may be infinitely wide choices. If these choices are scanned in some order
one at a time, then the infinitely wide choice point becomes a possible infinite
computation.
Even though the user plays the role of the angel and in principle should choose the
right number of iterations, this is not necessary, because there is at most one right
choice. If there is a number of iterations n that is sufficient for termination, then the
computer can choose the right alternative DOn by scanning through the alternatives,
and thus do the job of the user. If no n is sufficiently large, then the computer will
22.5. Interactive Guarded Commands 377
[g];S ~g]
[g];S [g];S [g];S Ihg]
~g] [g];S [g];S hg]
hg]
""", ~g]
be stuck in an infinite loop. The result is then the same; i.e., no postcondition is
established.
S .. -
{x:= xii b} , (input statement)
if gl :: SI D .. Dg. :: S. fi , (conditional choice)
do gl :: SI D ... Dg. :: S.od . (iterative choice)
The input statement is the angelic assignment statement. We interpret {x := x' I b}
as a request to the user to supply a new value x' for the program variable x. This
new value must satisfy the condition b in the current state.
The conditional choice construct was already mentioned in the introduction:
if gl :: SI D ... Dg. :: Sn Ii ~
{gd ; SI U ... U {gn} ; S.
The effect of the conditional choice is to let the user choose one of the alternatives
Si for which the enabledness condition gi is true in the current state.
The iterative choice was also mentioned in the introduction, as describing an event
loop:
do gl :: SI D ... Dgn :: Sn od ~
(/L X {gd ; SI ; Xu .. U {gn} ; Sn ; X u skip) .
378 22. Continuity and Executable Statements
The effect of the iterative choice is to let the user repeatedly choose an alternative
that is enabled and have it executed until the user decides to stop.
Using distributivity, the iterative choice can be written in the form (Jl X S; X uskip)
(note that this is the dual construct of weak iteration). We have
S = do z ::: 2 :: z := z - 2 0 z ::: 5 :: z := z - 5 od .
Intuitively, this is executed as follows. On every iteration, the user can choose to
decrease z by 2 or 5, if possible, or to stop. The predicate S.(z = 0) holds in those
states from which it is possible to make a sequence of choices such that z = 0
holds when we choose to stop. An intuitive argument indicates that we should get
S.(z = 0) = (z = 0 v z = 2 v z ::: 4) .
We have
S.(z = 0)
(Jl x ({z ::: 2} ; z := Z - 2 u {z ::: 5} ; z := z - 5).x v (z = 0)) .
When we compute approximations Pi for this least fixed point, we find
Po = false,
PI = (z = 0) ,
P2 (z = 0 v z = 2 v z = 5) ,
~ ~=Ovz=2vz=4vz=5vz=7vz=lm,
P3 = (z = 0 v z = 2 v 4 :::; z :::; 7 v z = 9 v z = 10 v z = 12 v z = 15) ,
and so on. Every approximation Pn holds in those states from which it is possible
to reach z = 0 in fewer than n steps by making suitable choices. We show the
calculation of P2:
22.5. Interactive Guarded Commands 379
P2
= {definition of approximation}
({z 2} ; z := z - 2 u {z ~ 5} ; z := z - 5),PI V (z = 0)
~
s .. -
magic, (magic)
[b], (guard statement)
[x:= xii b) . (demonic assignment)
Statements in the specification language are not necessarily continuous, but they
are monotonic. Hence, we are free to replace any component statement with its
refinement, preserving correctness of the whole statement. We have shown earlier
how to use specification statements in program derivations making essential use
of this monotonicity property. We will analyze specification statements in more
380 22. Continuity and Executable Statements
Statements
Specification commands
Interactive commands
[=-J
FIGURE 22.2. Guarded commands extensions
detail in Chapter 27. The languages defined here form a hierarchy as shown in
Figure 22.2.
Note that specifying programs by pre- and postconditions is not sufficient anymore
for interactive guarded commands. For extended guarded commands they are suf-
ficient, as will be shown in Chapter 26 when we study normal forms for different
classes of statements. However, when the programs may involve nontrivial user
interaction, then we need more expressive specifications for programs.
assignment [6] and used infinitary logic to reason about programs [10]. A number
of other authors also challenged Dijkstra's definition of the semantics ofloops; they
used either abstract fixed-point properties (Hebner [74]) or limits of ordinal-indexed
chains (Boom [41]).
In general, one could argue that continuity is much overrated as a semantic restric-
tion. Most arguments go through quite easily without the continuity assumption.
In general, our view is that complete lattices with monotonic functions provide
a much better foundation (both easier and more intuitive) for programming lan-
guage semantics than cpos with continuous functions. It is interesting to note that
Scott's original formulation of the fixed-point theory for program semantics did use
complete lattices (and continuous functions). The complete lattices were dropped,
because a cpo was a weaker structure that was sufficient for the theory, and the
miraculous top element was difficult to justify in the context of a semantics that
essentially was concemed only with partial functional statements. In the more gen-
eral framework of the refinement calculus, the complete lattices are well justified,
and the mathematical framework is simpler and more regular. Continuity can be
assumed whenever needed, as this chapter has tried to show, but there is no point
in restricting the mathematical treatment to only continuous statements.
We have looked at the mathematical properties of continuous statements and have
also defined a simple yet very expressive programming language that can be con-
sidered as executable. The extended guarded commands add some features to the
traditional guarded commands, like blocks with local variables and procedures. The
interactive guarded commands are a real strengthening of the expressive power of
the language. They allow us to describe permitted user interaction with a com-
puter and also to analyze what the user can achieve through this interaction. The
interactive guarded commands are continuous but not conjunctive, and can be seen
as executable if a wider interpretation of this term is used. The analogue here is
computability with an oracle that is studied in computability theory.
22.7 Exercises
22.1 Show that if f is a monotonic function and K is a directed set, then im.f.K is also
directed.
22.2 Show that limits preserve continuity; i.e., if F is a directed set of continuous
functions on a cpo, then (u f E F f) is continuous.
22.3 Show that if the relation R is total, then [R].false = false.
22.4 Complete the proof of Theorem 22.6.
22.5 Continuity of a function f from a cpo (A, !;) to a cpo (B, !;) is sometimes defined
using chains indexed by natural numbers (w-chains) rather than directed sets. We
say that f is w-continuous if it preserves limits of w-chains, i.e., if
382 22. Continuity and Executable Statements
(b) If f is strict and w-continuous and A and B are countable sets, then f is
continuous.
Hint: a set A is countable if there exists a bijection (a function that is one-to-one
and onto) from Nat to A.
In this chapter we look at how to construct programs that work on more advanced
data structures, concentrating in particular on arrays. No new theory needs to be
introduced for this purpose, as all the tools needed have already been built. We
illustrate array manipulation techniques by constructing some searching and sorting
algorithms. The case studies in this chapter also give us the opportunity to show
how to structure somewhat larger program derivations.
Note that if n < m then this specification is equivalent to [A := A' I T], since
alireset.A'.m.n is then trivially satisfied.
Introduce Loop
We start by introducing a new local variable that we will use as a loop counter:
[A := A' I alireset.A'.m.n] ;
!; {introduce local variable j}
begin var j : Nat; j := m ;
"{j = m}; [A, j := A', j' I alireset.A'.m.n] "
end
Next, we introduce the loop itself. The loop invariant is in this case very simple. It
states that the initial part of the array, up to j - 1, has already been set to zero. In
addition, it must state that the termination function is bounded from below (in this
case by zero). We choose n + 1 - j as the termination function. Let us introduce
an abbreviation for the invariant:
We need to check that the conditions for loop introduction are satisfied:
j=m
I- (Vi I m ~ i < j. A[i] = 0) 1\ j ~ n + 1
== {assumption}
(Vi I m ~ i < m A[i] = 0) 1\ m ~ n + 1
== {empty range, m ~ n}
T
23.1. Resetting an Array 385
Introduce Assignment
We then implement the loop body. This is now done with a single assignment
statement, as follows:
{resetbelow.A.j.m.n /\ j ~ n} ;
[A, j := A', j' I resetbelow.A'.j'.m.n /\ n + I - j' < n + I - j]
r:; {introduce assignment statement}
A[j], j:= 0, j +I
We have to show that the assignment introduction is correctly done:
resetbelow.A.j.m.n /\ j ~ n =}
resetbelow.A'.j'.m.n /\ n + I - j' ~ n +I - j ,
where
A' A(j +- 0) ,
j' j+l.
We have
(\Ii I m ~ i < j . A[i] = 0) /\ j ~ n + 1 /\ j ~ n
f- (Vi I m ~ i < j + 1 A(j +- O)[i] = 0) /\
j + 1 ~ n + 1 /\ n + 1 - (j + 1) < n + 1 - j
== {assumption j ~ n}
(\Ii I m ~ i < j + 1 A(j +- O)[i] = 0) /\ T /\ T
== {range split}
(\Ii I m ~ i < j . A(j +- O)[i] = 0) /\ A(j +- O)[j] = 0
== {array indexing}
(Vi I m ~ i < j . A[i] = 0) /\ 0 = 0
== {assumption}
T
386 23. Working with Arrays
Note how the array property is proved by splitting the range of the universal
quantifier into two parts, one for the index being changed (here j) and the other
for the other index values, which are not changed by the array assignment.
Final Implementation
Let us define the procedure
proc Reset(var A, val m, n) =
begin var j : Nat; j := m ;
while j ~ n do AU], j := 0, j + I ad
end
We leave the details of the loop introduction and assignment introduction steps
to the reader. The invariant and variant of the introduced loop are seen from the
388 23. Working with Arrays
body of the loop; the invariant is k ::: n + 1 /\ minaU.A.m.k, while the variant is
n + l-k.
We summarize the result of our derivation in a procedure definition. We define
proc FindMin(var i, val A, m, n) =
begin var k := m + 1 ; i := m ;
do k ::: n /\ A[k] < A[i] ~ i, k := k, k + 1
Ok::: n /\ A[k] ~ A[i] ~ k := k +1
od
end
The derivation uses a specification constant Ao to stand for the initial value of the
array A. A program implementing the given specification is derived as follows:
23.3. Selection Sort 389
end
~ {introduce assignment}
begin var i, j := 0,0;
while i < n - 1 do
[j := j' I minat.j'.A.i.n] ;
A := swap.i.j.A ;
i := i +1
od
end
~ {procedure call rule}
begin var i, j := 0,0 ;
while i < n - 1 do
FindMin(j, A, i, n - 1) ;
A := swap.i.j.A ;
i := i +1
od
end
We need to prove that the conditions for introducing the loop and introducing the
assignment in the next-to-Iast step are satisfied. For the assignment introduction,
the proof obligation is
minat.j.A.i.n /\ 0:5 i < n - 1 /\ perm.Ao.A.n /\ part.A.i.n =>
perm.Ao.A'.n /\ part.A'.(i + 1).n ,
where
A' = swap.i.j.A.
The first conjunct of the conclusion follows by the results of Exercise 10.11. The
rest of this proof obligation and the proof for the loop introduction are left as an
exercise (Exercise 23.2).
We assume that the array range is not empty and that the values in A are all in the
range l..k:
m ~ n A (Vi / m ~ i ~ nI ~ A[i] ~ k) .
The array A will not be changed by the program. Instead, we assume that the sorted
array is constructed in another array segment B[m .. n]:
B : array Nat of Nat .
Here, A, m, n, k, and I are constants (meaning that we can take the restrictions
on them as global assumptions rather than initial assertions), while B is the only
global program variable.
A First Solution
The basic solution idea is the following. We introduce an auxiliary array
C : array Nat of Nat;
that contains an entry for each value in the range l..k. Thus we only use the array
segment C[k .. l], which is what makes the space complexity of the algorithm linear
in the length of the range. We then record in C[i] the number of times the value i
occurs in the array A. This step will establish the condition
From this we can compute the sorted array B. One possible way is to scan through
the value range i = I, I + 1, ... , k -1, k, and successively insert the number C[i]
of values i into B for each i. However, this would make our algorithm linear in
the value range, which usually would be much larger than the size of the array A
itself. We will therefore derive another method below, which will be linear in the
size of the array A.
Based on these considerations, we derive an initial solution to the programming
problem:
Let us next consider how to implement the first step, counting the occurrences of
the different values in array A. We decide to first reset the array elements in C to
zero before starting the actual counting:
[C := C' I countedocc.C']
!; {introduce sequential composition}
Reset(C,I, k);
{alireset.C.l.k} ;
[C := C' I countedocc.C']
Here the first step establishes the condition alireset.C .l.k which then can be assumed
by the second step.
Thus, we arrive at the following first implementation of our specification:
[C := C' I countedocc.C'] ;
{countedocc.C} ;
[B, C := B', C' I sort.B' /\ perm.A.B'] ;
end
This reduces our task to implementing the following two steps: counting the value
occurrences and then constructing the final sorted array.
Counting Occurrences
Our next task is to count the occurrences of the different values in A. This is simply
done by scanning through the array A and updating the appropriate counter in C
each time. We give the derivation first and then show that the individual steps are
indeed correct.
{allreset.C.I.k} ;
[C := C' I countedocc.C'] ;
!; {introduce local variable j}
begin var j : Nat; j := m ;
" {allreset.C.l.k /\ j = m};
[C, j := C', j' I countedocc.C'] ";
end
!; {introduce loop, choose n + 1 - j as termination function}
.. while j:::: n do
" {countedbelow.C.j /\ j :::: n};
[C, j := C', j' I countedbelow.C'.j' /\ n + 1 - j' < n + 1 - j] "
od ...
!; {introduce assignment statement}
... C[A[jll, j := C[A[jll + 1, j + 1 ...
!; {substitute back}
begin var j : Nat; j := m ;
while j :::: n do C[AUll, j := C[AU]] + 1, j + 1 od
end
countedbelow.C.j ~
(Vi II :::: j :::: k C[i] = occur.i.A[m .. j - 1]) /\ j .:::: n + 1 .
394 23. Working with Arrays
The invariant here states that the elements in the initial part of the array, up to j - 1,
have already been counted.
The initialization condition holds, because
(Vi II ::: i < j C[i] = 0) /\ j = m
I- (Vi II ::: i ::: k C[i] = occur.i.A[m .. j - 1]) /\ j ::: n + 1
== {assumption j = m}
(Vi II ::: i ::: k C[i] = occur.i.A[m .. m - 1]) /\ m ::: n + 1
== {array has empty range, m ::: n}
(Vi II ::: i ::: k C[i] = 0) /\ T
== {assumption}
T
We have
(Vi Il ::: i ::: k C[i] = occur.i.A[m .. j - I)) /\
j:::n+l/\j:::n
I- (Vi Il ::: i ::: k C(A[j] +- C[A[j)] + 1)[i] = occur.i.A[m .. j]) /\
j + 1 ::: n + 1/\ n + 1 - (j + 1) < n + 1 - j
== {assumption j ::: n}
(Vi II ::: i ::: k C(A[j] +- C[A[j)) + l)[i] = occur.i.A[m .. j])
== {range split}
(Vi Il ::: i ::: k /\ i =I A[j]
C(A[j) +- C[A[j)] + 1)[i] = occur.i.A[m .. j)) /\
" (Vi II ::: i ::: k /\ i = A [j]
C(A[j] +- C[A[j)) + 1)[i] = occur.i.A[m .. j)) "
== {one point rule}
.. C(A[j] +- C[A[j)] + l)[A[j)) = occur.A[j).A[m .. j] ...
== {array indexing rule, arithmetic}
.. C[A[j)] +1=
occur.A[j].A[m .. j - 1] + occur.A[j].A[j.. j] ...
== {arithmetic, occur.A[j).A[j.. j] = 1}
... C[A[j)) + 1 = occur.A[j].A[m .. j - 1] + 1
== {arithmetic}
.. C[A[j)) = occur.A[j].(A[m .. j - I)) ...
== {substitute back}
(Vi II ::: i ::: k 1\ i =I A[j]
" C(A[j) +- C[A[j)) + l)[i] = occur.i.A[m .. j] ") /\
(Vi II ::: i = A[j) C[i] = occur.i.A[m .. j
::: k /\ i - I))
== (array indexing rule, assume i "# A[j) }
... C[i] = occur.i.A[m .. j] ...
== (arithmetic, assume i "# A[j) }
.. C[i] = occur.i.A[m .. j - 1] ...
== {substitute back}
(Vi II ::: i ::: k /\ i =I A[j] C[i] = occur.i.A[m .. j - I)) /\
(Vi II ::: i ::: k /\ i = A[j] C[i] = occur.i.A[m .. j - I))
== {merge ranges}
(Vi II ::: i ::: k C[i] = occur.i.A[m .. j - I))
396 23. Working with Arrays
== {assumption}
T
The range split method thus works well also in the more general case where we
have an array index that itself is an array access. In this way, we can work with
indirect references in an array without any further complications.
!; {exercise}
begin var j : Nat; j := I + 1 ;
while j ~ k do C[j], j := C[j] + C[j - 1], j + 1 od
end
We leave this step as an exercise for the reader, and concentrate on the final, most
difficult step in the last section.
{countedcum.c} ;
[B, C := B', C' I sort.B' 1\ perm.A.B'];
!; {introduce local variable}
begin var j : Nat; j := n;
" {countedcum.C 1\ j = n} ;
[B, C, j:= B', C', j' I sort.B' A perm.A.B'] "
end
!; {introduce loop}
while j ~ m do
"{movedpart.j.B.C 1\ j ~ m};
[B, C, j := B', C', j' I movedpart.j'.B'.C' 1\ j' < j]"
od ...
!; {introduce assignment}
... B[C[A[j]]], C[A[j)), j := A[j], C[A[j)) - 1, j - 1 ...
!; {substitute back}
begin var j : Nat; j := n;
whilej~mdo
movedpart.j.B.C ~
Crti II ~ i ~ k occur.i.A[m .. j] = C[i] - cumsum.(i - I).A) 1\
== {assumption j = n}
Crti II ~ i ~ k occur.i.A[m ..n] = C[i] - cumsum.(i - 1).A) 1\
Crti r II ~ i ~ k 1\ C[i] < r ~ cumsum.i.A B[r] = i) 1\ T
== {assumption, abbreviation A for A[m ..n]}
Crti II ~ i ~ k occur.i.A = cumsum.i.A - cumsum.(i - 1).A) 1\
Crti r II ~ i ~ k l\.cumsum.i.A < r ~ cumsum.i.A B[r] = i) 1\ T
== {definition of cumsum, empty range}
T
I-T
23.4. Counting Sort 399
:::} {assumptions, j =m - 1}
01i 11 ~ i ~ k occur.i.Alm ..m - 1] = C[i]- cumsum.(i - 1).A) 1\
01i r 11 ~ i ~ k 1\ C[i] < r ~ cumsum.i.A Blr] = i)
:::} {occur.i.A[m ..m - 1] = O}
0/i 11 ~ i ~ k C[i] = cumsum.(i - 1).A) 1\
0/i r 11 ~ i ~ k 1\ cumsum.(i - 1).A < r ~ cumsum.i.A Blr] = i)
:::} {cumsum.l.A ~ cumsum.(l + 1).A ~ ... ~ cumsum.k.A}
01 j rim ~ j ~ r ~ n B[j] ~ B[r]) 1\
01i 11 ~ i ~ k occur.i.B = cumsum.i.A - cumsum.(i - 1).A)
== {definition of sorted and cumsum}
sort.B 1\ 0/i 11 ~ i ~ k occur.i.B = occur.i.A)
== {definition of perm}
sort.B 1\ perm.A.B
j' j-l,
h A[j] ,
C' = C(h +- C[h] - 1) ,
B' = B(C[h] +- h) .
The proof is as follows:
0/i II ~ i ~ k occur.i.A[m .. j] = C[i] - cumsum.(i - 1).A) A
== {assumption m ~ j}
" 0/i 11 ~ i ~ k occur.i.A[m .. j - 1] = C'[i] - cumsum.(i - l).A) " 1\
0/i r 11 ~ i ~ k 1\ C'[i] < r ~ cumsum.i.A B'[r] = i) 1\ T 1\ T
== {range split}
.. 0/i 11 ~ i ~ k 1\ i "# h
occur.i.A[m .. j - 1] = C'[i] - cumsum.(i - 1).A) 1\
400 23. Working with Arrays
Final Result
Combining the separate refinements, we get the following theorem:
[B := B' I sort.B ' 1\ perm.A.B' ]
!; {above derivation}
23.4. Counting Sort 401
Finally, we move the local variable j to the outermost level (we leave the proof of
this to the reader as an exercise) and get the following final version of the program:
[B := B' I sort.B' 1\ perm.A.B']
~ {merge blocks (Exercise 23.5)}
begin var C : array Nat of Nat, j : Nat;
j:= I;
while j ~ k do C[j], j := 0, j + 1 od ;
j:=m;
while j ~ n do C[A[j]], j := C[A[j]] + 1, j + 1 od ;
j :=m+ 1;
while j ~ k do C[j], j := C[j] + c[j - 1], j + 1 od ;
j :=n;
whilej~mdo
23.6 Exercises
23.1 Prove that the conditions for introducing a loop and for introducing an assignment
are satisfied in the derivation of the linear search algorithm.
23.2 Prove that the conditions for introducing a loop and for introducing an assignment
are satisfied in the derivation of the selection sort algorithm.
23.3 In the derivation of the selection sort program we assumed that n > O. Show that
the final program in fact gives the right result also when n = O. In a situation like
this, the following rule can be useful:
{p} ; S !; Sf {q} ; S !; Sf
{p U q} ; S !; Sf
Let us start by analyzing the problem domain in somewhat more detail and finding
out some basic facts. The number of queens (and the size of the board) is n : Nat. We
think of the board as a matrix with rows and columns numbered 0, ... , n -1. A pair
of numbers (r, c) represents a position on the board, with r and cin 0, ... , n - 1.
It is obvious that in a solution there must be one queen in each row. Thus we can
represent a solution as a sequence of numbers Co, ... , Cn-I, where Ci is the column
number of the queen in row i.
We allow sequences to be indexed; s[i] stands for the ith element in s (for i =
0, ... , len.s - I, where len.s is the length of sequence s). However, indexing is not
considered implementable, so it must not appear in the final program.
c=5
7
6
5 r = c- 3
r 4
3
2 l-....;----;.-.;---~~-____; r =2
0234567
c
First let us define what it means for two queens in positions (i, x) and (j, y) not to
threaten each other:
nothreat.(i, x).(j, y) ~
i#jAx#yAi+x#j+yAi+y#j+x.
These four conditions are illustrated in Figure 24.1. They guarantee that the two
queens are not on the same row, the same column, the same downward diagonal,
or the same upward diagonal.
Next, we define safecon.s.n to mean that the sequences represents legally placed
queens on an n-by-n board that do not threaten each other:
safecon.s.n ~
(Vi I i < len.s s[i] < n) 1\
(Vi j Ii < j < len.s nothreat.(i, s[i)).(j, s[j))) .
We can then define when a sequence q is a solution to the n-queens problem:
Our idea is to solve the problem as follows. We start from an empty board. Then
queens are added, one by one. If at some point it is impossible to place a queen,
24.1. Analyzing the Problem 405
then we recursively backtrack to the previous queen and try a new place for this
queen.
Before starting the derivation, we define the following functions:
(note that if s = ( ), then this reduces to the original specification of the problem).
By rewriting the conditional specification as a basic one (Exercise 17.5) and using
the initial assertion, we find that the specification can be rewritten as
{n > 01\ len.s ~ n 1\ q = ( ) 1\ safecon.s.n 1\ n -Ien.s = w};
[q := q' I if qinit.s.n then sq' 1\ solution.q'.n else q' = ( ) til .
Although this form may be harder to read, it is easier to use in formal manipulations.
For brevity, we introduce the abbreviation S.s.q.n for the demonic assignment in
this specification statement.
if len.s = n -+ q := s
olen.s < n-+
{n > 01\ len.s < n 1\ q = ( ) 1\ safecon.s.n 1\ n -Ien.s = w};
S.s.q.n
fi
= {unfold abbreviation}
if len.s = n -+ q := s
olen.s < n-+
" {n > 01\ len.s < n 1\ q = ( ) 1\ safecon.s.n 1\ n -Ien.s = w};
[q := q' I if qinit.s.n then sq' 1\ solution.q'.n else q' = ( ) fil ..
fi
!; {introduce local variable x with assignments}
... begin var x := 0;
" {x = 0 1\ n > 0 1\ len.s < n 1\ q = {}1\ safecon.s.n 1\ n - len.s = w} ;
[q, x := q', x' I if qinit.s.n then sq' 1\ solution.q'.n else q' = ( ) fi] ..
end .
!; {introduce loop}
... while x < n 1\ q = ( ) do
" {x < n 1\ len.s < n 1\ q = ( ) 1\ safecon.s.n 1\ n -Ien.s = w} ;
[q := q' I if qinit.(s&x).n then (s&x)q' 1\ solution.q'.n
else q' = ( ) fil .. ;
x :=x + 1
od ..
= {fold abbreviation}
.. {x < n 1\ len.s < n 1\ q = () 1\ safecon.s.n 1\ n -Ien.s = w};
S.(s&x).q .n .
408 24. The N-Queens Problem
Loop Introduction
We now show the proof of the loop introduction in the derivation above, using
Theorem 21.14. The idea of the loop introduction is to find a suitable placement x
of the next queen. We let x count from 0 and stop when either qinit.(s&x).n holds
(meaning that a suitable position is found) or when x = n /\ q = ( ) (meaning that
no suitable position exists).
(in the second half of this invariant, the first disjunct holds when a position has not
yet been found for the next queen, and the second disjunct holds when a position
has been found). The variant is simply n - x.
Next, we must show that the loop body preserves the invariant and decreases the
variant. Since x is increased by the loop body, the variant is obviously decreased.
For the invariant, we must prove
Both conditions can be proved using the properties of sequences given earlier.
= {substitute back}
if len.s = n .... q := s
olen.s < n ....
begin var x := 0 ;
while x < n A q = () do
if safeadd.s.x ....
(n > OAlen.(s&x) ~ n Aq = () A
safecon.(s&X).n A n - len.(s&x) < w};
S.(s&x).q.n
o. . . safeadd.s.x .... skip
fi;
x :=x+ 1
od
end
fi
= {move block to outennost level}
begin var x := 0 ;
if len.s = n .... q := s
olen.s < n ....
whilex<nAq=()do
if safeadd.s.x ....
(n > 0 tden.(s&x) ~ n A q = ( ) A
safecon.(s&X).n An -Ien.(s&x) < w};
S.(s&x).q.n
o. . . safeadd.s.x .... skip
Ii;
x :=x + 1
ad
fi
end
24.6. Summary and Discussion 411
Queens(var q. val s. n)
"
begin var x := 0 ;
illen.s = n --+ q := s
olen.s < n --+
while x < n I\.q = () do
if saleadd.s.x --+ Queens(q. s&x. n)
o. . . saleadd.s.x --+ skip
Ii;
x :=x+ 1
od
Ii
end
Queens(q. ( ). n)
so the procedure Queens indeed gives us a solution to the n-queens problem.
24.7 Exercises
24.1 Derive properties (*)-(****) for sequences given in the text.
24.2 Complete the details of the proof for the loop introduction in the derivation of the
Queens procedure.
25______________________
In terms of the game semantics for statements, this means that we are only inter-
ested in a game where the postcondition is false. In this case, normal termination,
nontermination, and abortion all imply that Player has lost, and only miraculous
termination is a win for Player.
The state has only one attribute, x, the number of matches, ranging over the natural
numbers. Thus, we can consider the state space to be the type Nat.
We introduce the abbreviation Move for the state relation (x := x' I x - 2 :::: x' <
x) (since we are talking about natural numbers, we follow the convention that
m - n = 0 when m :::: n). Then the game can be expressed in the following simple
form:
The game can be explained as follows. The loop guard true shows that the game
never ends in a draw in finite time. The body shows the sequence of moves that is
repeated until the game ends (or indefinitely). First, the guard statement [x =I- 0]
is a check to see whether Player has already won (Opponent has lost if the pile of
matches is empty when it is Player's move). If there are matches left (x =I- 0), then
Player moves according to the relation Move, i.e., removes one or two matches
(decreases x by I or 2). Now the dual situation arises. The assert statement {x =I- O}
is a check to see whether Player has lost. If there are matches left, then Opponent
moves according to the relation Move, Le., removes one or two matches.
25.2. Winning Strategies 415
By instantiating in the correctness rule for loops, we get the following rule for
proving the existence of winning strategies in two-person games.
Corollary 25.1 Player hils a winning strategy for game while g do Sod under precondition p.
provided that the following three conditions hold for some ranked collection of
predicates trw I W E W}:
(i) p ~ r.
(i) p ~ r.
(ii) (Vw E W g n rw 0S Rr<w). and
(iii) ...., g n r ~ false.
Straightforward simplification now shows that the third of these conditions is equiv-
alent to r ~ g and also to (Vw E W rw ~ g). This can then be used to simplify
the second condition. 0
416 25. Loops and Two-Person Games
We prove (*) by calculating S.(x mod 3 I 1/\ X < n) in two parts. First, we find
the intermediate condition:
({x> O} ; [Move]).(x mod 3 I 1/\ x < n)
= {definitions}
x > 0/\ 01x' X - 2 ~ x' < x :::} x' mod 3 I 1/\ x' < n)
= {reduction, arithmetic}
xmod3=I/\x~n
Thus we have shown that (*) holds, i.e., that the game has a winning strategy.
25.3. Extracting Winning Strategies 417
(i) Q' ~ Q,
TwU
=} {second assumption and (*)}
Q'.u I- 0 A (Vy. Q'.u.y =} [R].(Uv E W I v < w, Tv).y)
=} {simplify}
The three conditions in Lemma 25.2 can be interpreted as follows. The first con-
dition implies that the new game while g do {Q'} ; [R] od is compatible with the
old one, in the sense that the only difference is that Player has fewer alternatives
to choose from. In other words, Opponent is not disadvantaged if we replace Q
by Q' in the game. The second condition tells us that under Q', Player always has
a move available. Thus, there is a proof of a winning strategy for the new game.
Finally, the third condition implies that Q' only offers alternatives that preserve
the invariant, i.e., Q' offers only winning alternatives.
Whenever the conditions of Lemma 25.2 hold, we say that {T };[Q'] is a specification
fOT a progTam that plays the role of PlayeT in the game. The justification for this
is that whenever a ranked predicate Tw holds (and the setup is such that a ranked
predicate in fact always holds when Player is to move), any move permitted by
the relation Q' takes Player closer to a win. Later, in Section 25.4, we consider
the question of what Player should do in situations in which the invariant does not
hold.
(i) Q' Q,
(ii) (Vu T.U A q.u =} Q'.u I- 0), and
(iii) (Vw E W Tw nq ([Q']; S').T <w)
25.3. Extracting Winning Strategies 419
The easiest way to find a relation that satisfies these three conditions is to use the
first and third conditions to find a candidate,
Thus we have shown that a specification for a Player program is the following:
This describes Player's winning strategy as follows: if x mod 3 is zero, then remove
two matches; if it is 2, then remove one match. If x mod 3 = 1, then the strategy
says simply to give up (since the statement aborts in this case). Giving up in this
way is reasonable when playing against a perfect opponent, but in practice it is
not a very useful strategy. Instead, we would want a strategy that might work if
an imperfect opponent makes a mistake. Below, we shall see how refinement and
heuristics together can be used to improve the strategies of both contestants in such
away.
25.4. Strategy Improvement 421
Next, we note that Player cannot force Opponent to establish the invariant x mod 3 '"
1 unless it holds when Player is to move. Thus, we cannot essentially improve
Player's strategy further. It could be argued that the best way of implementing
the nondeterministic choice in the third branch of the conditional is by randomly
choosing to remove either one or two matches, since this makes it hard for an
opponent to figure out what strategy is used.
that r ~ [R' ].(-. p) for as weak a predicate r as possible. This guarantees that if
Player makes a move that establishes r, then Opponent can break the invariant, at
least temporarily.
In the example of nim, this idea is used as follows. The invariant p is x mod 3 -:F I,
and the specification for Opponent's move is [x := x'I x - 2 ~ x' < x]. This can
be made more deterministic by changing it to x := x-I (provided that x > 0) or
x := x - 2 (provided that x > 1). The assignment x := x-I establishes -. p if
x mod 3 = 2, and the assignment x := x - 2 establishes -. p if x mod 3 = O. Thus
an improved strategy for Opponent is
25.6 Exercises
25.1 Prove the refinement equivalence
{x > 0" x mod 3 -:F I};
[x := x' I x - 2 ~ x' < x "X' > 0 " x' mod 3 = 1]
25.6. Exercises 423
=
if x> 01\ X mod 3 = 0 ~ x := x - 2
o x mod 3 = 2 ~ x := x-I
Dxmod3=1~abort
fi .
25.2 There is a dual version of nim in which the winner is the one who takes the last
match. Describe this game using the statement notation (when Player can move
first) and investigate under what precondition there is a winning strategy.
25.3 Tick-tack-toe (or noughts and crosses) on a 3 x 3 board can be represented using
three sets A, B, and C of natural numbers 1, ... ,9. The squares on the board are
numbered so that every line-of-three adds up to 15 (i.e., as in a magic square).
The set A contains the numbers of the empty squares, B contains the numbers of
the squares where Player has placed a marker, and C contains the numbers of the
squares where Opponent has placed a marker. A move consists in removing one
number from A and adding it to B (player's move) or C (Opponent's move). The
game ends when either A is empty (a draw) or when either B or C contains three
numbers that add up to 15. Describe this game using statement syntax and outline
a proof that if Player starts by placing a cross in the center square and Opponent
then places one in a comer square, then Player has a winning strategy.
Part IV
Statement Subclasses
26______________________
In Chapter 16, we showed how the homomorphism properties give rise to a number
of subcategories of statements. In this chapter, we study the most interesting of
these subcategories in more detail and show how they can be expressed with a
subset of the statement constructors. We concentrate on universally conjunctive and
conjunctive statements, on disjunctive statements, on (partial and total) functional
statements, and on continuous statements.
For each of these subcategories, we also give a normal form for statements. We
will later see that these normal forms correspond to specification statements in the
different statement subclasses. Because they are normal forms, any requirement
can be expressed as a specification statement of this kind. On the other hand, these
normal forms contain a minimum of information about how the statement would
actually be implemented.
Theorem 26.1 For arbitrary I; and r, Ctran T (I;, r) is a complete lattice. Meets in Ctran T (I;, r)
give the same result as in Mtran(I;, r), but joins generally do not. The top element
ofCtran T (I;, r) is magic, and the bottom element is the arbitrary demonic update
chaos = [True].
From Theorems 16.1 and 16.2 we see that guards, functional updates, and demonic
updates are always universally conjunctive and that furthermore, sequential com-
position and meets preserve universal conjunctivity. This means that if we restrict
ourselves to these constructs, then we only generate predicate transformers that are
universally conjunctive. Hence, any statement generated by the following syntax
is universally conjunctive:
S ::= [g)I{f)I[R)IS1;S21(niElS;).
Of the derived constructs, the deterministic conditional, v-recursion, and weak
iteration also preserve universal conjunctivity, so they can also be used in a syntax of
universally conjunctive statements. As the normal form theorem below shows, any
universally conjunctive predicate transformer that can be expressed in higher-order
logic can be expressed as a universally conjunctive statement.
Normal Form
The normal form theorem for Mtran (Theorem 13.10) showed that every monotonic
predicate transformer can be written as a sequential composition of an angelic and
a demonic update. This result has a counterpart in Ctran T :
Theorem 26.2 Let S be an arbitrary universally conjunctive predicate transformer. Then there
exists a unique relation R such that
S = [R).
Proof We first note that for universally conjunctive S, the following holds for all
predicates q and all states a:
S.q.a == (np I S.p.a p) ~ q .
The proof of this is left to the reader as an exercise (Exercise 26.2).
Now set R.a = (n pi S.p.a p). Then
[R).q.a
== {definition}
(Va' (np I S.p.a p).a' ===> q.a')
== {pointwise extension}
(np I S.p.a p) ~ q
== {(*) above}
S.q.a
which shows that [R) = S. For uniqueness we have
26.2. Conjunctive Predicate Transformers 429
[Rj = [R'j
== {antisymmetry}
[Rj ~ [R'j /\ [Rj ;) [R'j
== {order embedding}
R:2 R' /\ R ~ R'
== {antisymmetry}
R=R'
Theorem 26.2 shows that if we want to prove some general property about uni-
versally conjunctive predicate transformers, it is sufficient that we prove it for
predicate transformers of the form [Rj, where R is an arbitrary relation. From the
homomorphism properties of the demonic choice constructor, we see that the rela-
tion space is in fact embedded inside the predicate transformer space as universally
conjunctive predicate transformers.
transformer constructors and still stay within the realm of conjunctive predicate
transformers.
Normal Form
The normal form theorem for universally conjunctive predicate transformers can
be generalized to Ctran:
Theorem 26.4 Let Sbe an arbitrary conjunctive predicate transformer. Then there exists a unique
predicate p and a relation R such that
S = {p}; [R] .
Proof Recall that the termination guard of Sis t.S = S.true.1t is easily seen that
we must choose p = t.S:
S={p};[R]
=> {congruence, definitions}
S.true = p n [R].true
== {demonic update is terminating}
S.true = p n true
== {predicate calculus, definition of t. S}
t.S = p
Then [t.S] ; S is universally conjunctive (Exercise 26.1), and we know from the
proof of Theorem 26.2 that[t.S]; S = [R] where R.O" = (n pi ([t.S]; S).p.O" p).
Then
({t.S} ; [R]).q
= {definition}
({t.S}; [t.S] ; S).q
= {definitions}
t.S n (. . . t.S U S.q)
= {general lattice property}
t.S n S.q
= {definition of t. S}
S.true n S.q
= {S monotonic}
S.q
Corollary 26.5 For arbitrary ~ and r, Dtran.l(~, r) is a complete lattice. Joins in Dtran.l(~, r)
give the same result as in Mtran(~, r), but meets generally do not. The bottom
element of Dtran.l(~, r) is abort, and the top element is the arbitrary angelic
update choose = {True}.
The previous results show that assert, functional update, and angelic update are
universally disjunctive, and that sequential composition and joins preserve univer-
sal disjunctivity. The basic universally disjunctive statements are thus defined by
the following syntax:
Corollary 26.6 Let S be an arbitrary universally disjunctive predicate transformer. Then there is
a unique relation R such that
S = {R}.
432 26. Statement Classes and Normal Forms
This shows that the angelic update is a normal form for universally disjunctive
predicate transformers and that the relation space is embedded inside the predicate
transformer space as universally disjunctive predicate transformers.
Exactly as for conjunctivity, relaxing universal disjunctivity to plain disjunctivity
means we get a slightly larger collection of predicate transformers, Dtran, which
has properties dual to those of Ctran.
Corollary 26.7 For arbitrary E and r, Dtran(E, r) isa complete lattice. Joins in Dtran(E, r) give
the same result as in Mtran(E, r), but meets generally do not. The bottom element
ofDtran(E, r) is abort, and the top element is magic.
Next, Theorem 26.4 immediately has the following dual:
Corollary 26.8 Let S be an arbitrary disjunctive predicate transformer. Then there exists a unique
predicate p and a relation R such that
S = [p];{R}.
Thus, the form [p]; {R} is a normalformfor disjunctive predicate transformers. The
disjunctive statements are defined in the obvious way, by adding guard statements
to the syntax of universally disjunctive statements.
Theorem 26.10 If the predicate transformer S is both universally conjunctive and universally
disjunctive, then there is a unique state transformer f such that S = (f).
26.4. Functional Predicate Transformers 433
The normal fonn for Ftran uses asserts, guards, and functional updates. This justifies
calling these predicate transfonners functional; they can be expressed without using
nondetenninistic constructs such as relational updates, meets, and joins.
Theorem 26.14 Assume that S is a functional predicate transformer. Then there are predicates p
and q and a state transformer f such that
Proof Assume that S is both conjunctive and disjunctive. By earlier normal fonn
theorems, we know that S can be written in the fonn {p} ; [P] but also in the fonn
[q] ; {Q}, for predicates p and q and relations P and Q such that
Proof The proof rests on the fact that a continuous function f : peA) -+ PCB)
(where A and B are countable) is uniquely defined by its behavior on the finite
subsets of A (the proof of this fact is beyond the scope of this book).
Assume that a continuous S E Ptran(~, r) is given. The construction is then almost
as in the normal form theorem for monotonic predicate transformers (Theorem
13.10). However, now we consider an intermediate state space consisting of all
finite nonempty subsets of r (to be really precise, we would have to construct a
new type that is isomorphic to this set of subsets, but that is a complication without
real significance). One can then define P and Q exactly as in the proof of Theorem
13.10 and show that S = {P} ; [Q] (see also the proof of Theorem 26.18 below).
o
Thus {P}; [Q], where Q is total and image-finite, is a normalformfor continuous
predicate transformers. Furthermore, for S : ~ t-+ ~ with ~ countably infinite
it can be shown that both P and Q can be chosen to be relations over ~ (this is
because the finite subsets of a countably infinite set can be mapped bijectively into
the set itself).
R
.u
= {(n{EYq IT}S.q.u q) ift.S.u,
otherwise
(the set {EY T} is a singleton containing some unspecified state Y E r). The same
argument as in the proof of Theorem 26.4 now shows that S = {t.S}; [R). Thus, we
have only to show that R.u is nonempty and finite. This is obviously true if -. t. S.U ,
since R.u in that case is a singleton. Now assume t.S.u. Then S.true.u == T, so the
set {p I S.p.u} is nonempty. Furthermore, we get
S.(R.u).u
== {S conjunctive, definition of R}
(Vq I S.q.u S.q.u)
== {trivial quantification}
T
Since continuity implies S.false = false, this shows that R.u must be nonempty.
Finally, we prove that R.u is finite by contradiction. Let C be the collection of
all finite subsets (predicates) of R.u. Note that C, ordered by set inclusion, is a
directed set. Assume that R.u is infinite. Then
(limq E C S.q).u
== {pointwise extension}
(3q E C S.q.u)
== {R.u infinite implies S.q.u == F for all q E C}
F
26.6. Homomorphic Choice Semantics 437
However, we have
S.(limq E C q).u
== {the limit of C is R.u, because of countability}
S.(R.u).u
== {above}
T
which contradicts continuity of S. Thus R.u must be finite. D
This theorem shows that {p} ; [R] (where R is total and image-finite) is a normal
form for conjunctive continuous predicate transformers.
Homomorphism Properties
Recall the function that maps any predicate transformer S : l: i--j> r to a generalized
state transformer S : l: -+ p(p(r, defined by
S.u = {q I S.q.u} .
Thus S maps initial state u to the set of all postconditions that S is guaranteed
to establish. We shall now consider how homomorphism properties translate into
generalized state transformer equivalents. We have already noted in Chapter 14
that monotonicity of S corresponds to upward closedness of S.
We first consider strictness and termination.
438 26. Statement Classes and Normal Forms
Note how the three basic cases for initial state a (abortion, nonnal tennination,
miracle) are reflected in the choice semantics. Statement S aborts ifS.a = 0, it is
miraculous if 0 E S.a, and it tenninates nonnally otherwise.
We next show that conjunctivity corresponds to intersection closedness. Duality
then gives a characterization of disjunctivity.
Theorem 26.20 Predicate transformer S is conjunctive if and only if
(3iEIPiES.a) == (UiEIPi)ES.a
holds for an arbitrary nonempty collection {Pi liE I} of predicates and for all
states a.
Proof First assume that S is conjunctive and let the state a and a nonempty
collection {Pi liE I} of predicates be given. Then
S conjunctive, I i= 0
l-(niEIPi)ES.a
== {definition ofS}
S.(ni E I Pi).a
== {S conjunctive, pointwise extension}
(Vi E I S.Pi.a)
26.6. Homomorphic Choice Semantics 439
== {definition of'S}
(Vi E I Pi E S.u)
Now assume that (n i E I Pi) E S.u == (Vi E I Pi E S.u) holds for an arbitrary
state 0' and an arbitrary nonempty collection {Pi liE I} of predicates. Then, for
I =1= 0,
s.(n i E I Pi).U
== {definition ofS}
(n i E I Pi) E S.u
== {assumption}
(Vi E I Pi E S.u)
== {definition ofS}
(Vi E I S.Pi.U)
== {pointwise extension}
(ni E I S.Pi).U
so S is conjunctive. The proof for disjunctivity is dual. D
8.0' ~ (n P I S.p.u p) .
y E [R).u == R.u.y .
-------~~ Stran
r a
S;.a U Sz.a
- (Va S.a ; S.a) .
The relationship between the semantic functions and the four domains involved
(Mlran, Clran T, Siran, and 1: --+ P(r)) can be described nicely if we first define
the function cr that recovers S from S:
cr.T.a = {q I T.a ; q}
Conjunctivity
If S is conjunctive but possibly nonterminating, we have only to define S slightly
differently, compared with the universally conjunctive case. Now S is a function
in 1: --+ {..l} + p(r) (thus we have added an artificial bottom element ..1 to the
state space), and
S 1\ {..l ifS.a = 0,
.a = (n p I S.p.a p) otherwise.
26.6. Homomorphic Choice Semantics 441
In fact, S then gives the relati~al interpretation often used to justift weakest
precondition semantics. Again, S can immediately be recovered from S, and the
refinement relation has the following characterization:
Disjunctivity
For disjunctive predicate transformers, the results are dual to those for the conjunc-
tive case, so we outline only the universally disjunctive case here. From Theorems
26.20 and 26.19 it follows that S.u is uniquely determined by its singleton elements,
so we define S.u to contain all members of singleton elements of S.u:
-
S.u =
A
{u
,
I {u}, -
E S.u} .
Determinism
Determinism means that the final state of a normally terminating computation is
always uniquely determined for a given initial state. For deterministic predicate
!!ansformers, we thus want to simplify the state transformer interpretation so that
S.u is the final state that is reached when S is executed in initial state u.
We first consider the special case S E TFtran, when predicate transformer S is
deterministic (i.e., both conjunctive and disjunctive) and also terminating and non-
miraculous. In this case, Theorem 26.10 shows that S = (I) for the state function
I defined by
I.u = (fY (Vp I S.p.u p.y ,
and from Chapter 14 we know that
S.U = {p I I.u E p} .
In other words, S.U contains all those predicates that contain I.u. Thus we lose
no information if we give the simpler semantics
S ~ I
that identifies S with a function S: E ~ r. Since TFtran is discretely ordered,
refinement reduces to eqUality.
442 26. Statement Classes and Normal Forms
(a) 0 S.a,
(b) p E S.a 1\ q E S.a =} p nq E S.a, and
(c) p E S.a 1\ p S; q =} q E S.a;
i.e., S.a is either empty or (in topological terminology) ajilter.
Furthermore, if we strengthen the conjunctivity condition, requiring S to be uni-
versally conjunctive and strict, then S.a is a principal filter, i.e., a filter generated
by a specific set of states.
26.7. Summary and Discussion 443
statement classes and derive properties for such new mixtures. Of course, our
framework is also restricted, in the sense that we interpret our programs as predicate
transformers, so we are essentially considering only the input-output behavior of
programs.
26.8 Exercises
26.1 Show that if S is conjunctive, then [t.S] ; S is universally conjunctive.
26.2 Show that if S is universally conjunctive, then the following holds for all predicates
q and all states a:
26.3 Show that the demonic update chaos = [True] is the bottom element of Ctran T,
i.e., the least universally conjunctive predicate transformer.
26.6 In this chapter, we defined the various homomorphic choice semantics by applying a
suitable transformation to the original choice semantics. Another possibility would
be to define the homomorphic choice semantics recursively over the syntax for the
corresponding subclass of contract statements and then show that the two choice
semantics are related as stated in the text. For the universally conjunctive case we
define
ch'.[R].a _ R.a,
ch'.(S\ ; S2).a - im (Ch'.S2).(ch'.S\.a) ,
ch'.(ni E I Sj).a - (Ui E I ' ch'.Sj.a), I =f. 0 .
ch.S.a == {q I ch'.S.a ~ q}
for S E Ctran T.
26.7 Recall the definitions of S and er.S for universally conjunctive S given in the text.
Prove that the diagram in Figure 26.1 commutes and then prove the following
homomorphism property for demonic choice:
if ch.S.u = 0,
ch'.S.u = {~Ch.S.U otherwise.
26.9 A set is said to be cofinite if its complement is finite. Since predicates are sets of
states, it makes sense to talk abut cofinite predicates also. Let S be the predicate
transformer in Mtran(Nat, Nat) defined as follows:
S.q.u == q is cofinite.
Show that S is finitely conjunctive, i.e., that S.(p n q) = S.p n S.q for arbitrary
predicates p and q. S is not conjunctive, however. Show this by exhibiting a set of
predicates {qi liE Nat} such that S.(ni E Nat qi) #- (ni E Nat S.qi). Hint:
a set of natural numbers A is cofinite if and only if there is n E Nat such that A
contains all numbers that are greater than or equal to n.
27______________________
Specification Statements
27.1 5 pecifications
In preceding chapters we have shown that subclasses of statements can be char-
acterized by nonnal fonns for statements. We shall now show that these nonnal
fonns really correspond to specifications of program behaviors. By a specification
we mean a statement that indicates in a simple way what is to be computed without
saying how it is computed. For example, the statement
x := factorial.x
specifies that the output value of x should be the factorial of the input value. If the
programming language used has an explicit factorial operator, then this would also
be an executable statement. By a sequence of refinement steps (a derivation), we can
refine this to an implementation that, e.g., uses only multiplications and additions.
We will not address here the question of what operations are implemented, as this
differs from programming language to programming language. A programming
language implementation of a statement is a refinement of the statement that is
directly expressible in the chosen programming language and hence executable on
the chosen computer.
Conjunctive Specifications
A conjunctive specification is a predicate transfonner of the fonn {p} ; [Q]. This
is a nonnal fonn for conjunctive predicate transfonners; i.e., every conjunctive
predicate transfonner tenn can be written in this fonn. Furthennore, it describes a
computation in a concise fonn: the relation Q shows how the final state is related to
the initial state, while the predicate p (the precondition) characterizes those initial
states that we are interested in. An implementation of the specification {pI ; [Q]
must behave as pennitted by Q whenever p holds in the initial state. Arbitrary
behavior (even nontennination) is acceptable in states where p does not hold.
If the precondition is the predicate true, then the specification is in fact a universally
conjunctive specification. We do not consider universally conjunctive specifications
separately; we simply treat them as special cases of conjunctive ones. An example
(with x, y : Nat) is
[y := y' I yr2 ~ X < (y' + 1)2] ,
which assigns to y the (natural number) square root of x. Note that even though the
square root is uniquely defined for arbitrary x, it would be much more complicated
to specify it as a function of x. This is a strong argument in favor of conjunctive
specifications even when specifying a deterministic computation: we can specify
by giving constraints rather than by giving an explicit function.
Other Specifications
Dually to the conjunctive specification, the statement [p] ; {Q} is a disjunctive
specification and {Q} is a universally disjunctive specification. Similarly, {p} ;
(f) is a partial function specification. An example of a universally disjunctive
specification is
{x, e := x', e' 10< e' < x'} .
This specifies setting x and e to any (angelically chosen) nonnegative values with
0< e < x.
An example of a partial functional specification is
{x > O}; z := yjx ,
which specifies that z is assigned the result of the division y j x, with precondition
x > O. If x ~ 0, then any behavior, even nontermination, is acceptable.
The partial functional specification is easily seen to be a special case of the con-
junctive specification, since any functional update can be rewritten as a demonic
update. Even though the partial functional specification predicate transformer is
sufficient to specify arbitrary partial functions, the natural number square root ex-
ample above shows that it can be more convenient to specify a function using the
more general conjunctive specifications.
Theorem 27.1 The following rules holdfor arbitrary predicates p, p': arbitrary state transformers
f, f': and arbitrary relations P, P', Q, and Q'.
(a) {P}; [Q] !; {P'} ; [Q'] <= P ; P' 1\ Q' ; Q ,
(b) {p}; [Q] !; {p'} ; [Q'] == p ; p' 1\ Ipi ; Q' ; Q ,
(c) [Q]!; [Q'] == Q' ; Q ,
(d) [p]; {Q} !; [p']; {Q'} == p' ; P 1\ Q ; Ip'l; Q' ,
(e) {Q}!; {Q'} == Q ; Q' ,
(t) {p}; (f) !; {p'} ; (f') == p ; p' 1\ Ipi ; If I ; 1f'1 ,
(g) (f)!; (f') == f = f' .
Proof We first note that (a) holds by homomorphism and monotonicity properties.
To prove (b) we have
Note that rules (b)-(g) in Theorem 27.1 are all equivalences, so they can be used
for refinements in both directions. All the rules 'in Theorem 27.1 give conditions
for refinement in terms of predicates, functions, and relations. This is important;
it allows us to reduce refinement of statements to properties on lower levels in the
predicate transformer hierarchy: to properties of functions, relations, and predi-
cates. When the rules are applied to a concrete specification, the conditions can
27.2. Refining Specifications by Specifications 451
easily be reduced further to first-order formulas. For example, the second conjunct
on the right-hand side in (0 can be rewritten as
Theorem 27.1 may seem like an unnecessarily long list. In fact, as noted in the
proof, three of the cases (c, e, and g) are direct special cases of the others. From now
on, we will not consider these specifications (universally conjunctive, universally
disjunctive, and total functional) separately.
Theorem 27.2 The following holds for arbitrary predicates p, p'; arbitrary state transformer f;
and arbitrary relations P, P', and Q.
(a) {P}; [Q] !; {p'} ; [Q'] == dom.P p' A p- 1 ; Q' Q ,
(b) {p}; [Q] !; {p'}; (f') == p p' A Ipl ; If'l Q ,
(c) {P}; [Q] !; [p']; {Q'} == Ip'l; P Q'; Q-l ,
(d) {Q}!; {p'}; (f') == dom.Q p' A Q 1f'1 .
Next, we find that (b) is in fact a special case of Theorem 27.1 (b), specializing Q'
to If'l. For (c) we have a derivation similar to the one for (a). Finally, (d) follows
as a special case of (a) with P := Q, Q := Id, and Q' := 1f'1, together with a
small derivation to show Q-l ; If'l ; Id == Q ; 1f'1. 0
In the rule in Theorem 27.2 (d) it is sufficient to have the universally disjunctive
specification {Q} on the left-hand side rather than the disjunctive specification
[p) ; {Q} because the refinement
is equivalent to
and can be handled by the rule in Theorem 27.1 (b). Another similar example can
be found in Exercise 27.3.
Example
As an example, we consider refining the conjunctive specification {x > O} ; [x :=
x' I x' < x). We propose to refine this by replacing the demonic assignment with
a functional one. Theorem 27.2 (b) gives us a rule for proving the refinement
Since both specifications have the same precondition, the proof obligations are
simplified. We have
{x > O} ; [x := x' I x' < x) !; {x > O} ; x := x - I
== {Theorem 27.2 (b)}
Ix > 01 ; Ix := x - I I ; (x:= x' I x' < x)
<= {reduction to Boolean terms}
01x x' x> 0 A x' = X - I => x' < x)
== {aritJunetic}
T
27.3. Combining Specifications 453
Theorem 27.3 Let predicates p and q and relations P and Q be arbitrary. Then
Proof We use the following assertion propagation rule for conjunctive S, which
the reader can easily verify (Exercise 27.4):
S; {pI = {S.p}; S .
For (a), we have
{p}; [P]; {q}; [Q]
== {assertion propagation}
{p}; ([P].q}; [P]; [Q]
== {homomorphisms}
{p n [P].q}; [P; Q]
and for (b),
({p} ; [P] n {q} ; [Q]).r.a
== {definitions}
454 27. Specification Statements
p.u A (Vy P.U.y => r.y) A q.u A (Vy. Q.u.y => r.y)
== {predicate calculus}
p.u Aq.u A (Vy. P.u.y V Q.u.y => r.y)
== {definitions}
({p n q); [P U Q)).r.u
which finishes the proof. 0
(e) Id\R = R .
The proof is left as an exercise to the reader (Exercise 27.7).
Lemma 27.4 (c) shows that the quotient can be given the following intuition: if
we want to divide relation R into relations Q and P so that Q ; P ~ R, and Q is
given, then for P we can take Q-l \R.
The relational quotient can be used to give a simple characterization of least
conjunctive upper bounds.
27.3. Combining Specifications 455
Theorem 27.5 The least conjunctive upper bound of two conjunctive specifications {p} ; [P) and
{q}; [Q) is given by
{pUq};[lpl\pnlql\Q).
Proof We develop the proof by finding what characterizes a specification ({r); [R))
that refines both {p} ; [P) and {q}; [Q).
{p}; [P) r:;:: {r}; [R) 1\ {q}; [Q) r:;:: {r}; [R)
== {Theorem 27.1 (d)}
p ~ r 1\ Ipi ; R ~ P 1\ q ~ r 1\ Iq I ; R ~ Q
== {Lemma 27.4 (c), Ipl-l = Ipl}
p ~ r 1\ q ~ r 1\ R ~ Ipl\P 1\ R ~ Iql\Q
== {lattice properties}
(pUq) ~ r I\R ~ Ipl\P n Iql\Q
This shows that the least conjunctive upper bound is {p U q}; [lpl\P n Iql\Q). 0
We call the least conjunctive upper bound of Sl and S2 the least conjunctive re-
finement, written SIUS2' The expression for S1US2 given in Theorem 27.5 is fairly
complicated. However, if the conjunctive specification (pI ; [P) is normalized so
that relation P is full wherever p does not hold (Le., (Va' ..... p.a ~ (Vy P.a.y),
and similarly for {q}; [Q), then the expression for the least conjunctive upper bound
reduces to the simpler form
(pUq};[pnQ).
Showing this is left to the reader as an exercise (Exercise 27.9).
In the special case in which the two preconditions are the same, the least conjunctive
refinement can also be simplified.
Proof
{p}; [P] u{p}; [Q)
= {Theorem 27.S}
{pI ; [lpl\P n Ipl\Q]
= {definitions}
{p}; [Aa y (p.a =} P.a.y) 1\ (p.a =} Q.a.y)]
= {use assertion (Exercise 27.8)
{pI ; [Aa y' p.a 1\ (p.a =} P.a.y) 1\ (p.a =} Q.a.y)]
456 27. Specification Statements
= {predicate calculus}
{p}; [AO" y. p.O" /\ P.O".y /\ Q.O".y]
= {use assertion (Exercise 27.S}
{p}; [AO" y. P.O".y /\ Q.O".y]
= {definitions}
{p};[pnQ]
o
The least conjunctive upper bound can be seen as a way of combining specifications.
If we specify different aspects of a program separately, we want the implementation
to satisfy (refine) each of the component specifications. Theorem 27.5 gives us a
rule for computing the combined specification. Since the result is the least upper
bound, we do not lose any refinement potential when combining the component
specifications if we have decided that the refinement must be conjunctive.
S2 = {sorted. A /\ sorted.B};
[C := C' I (Vi occur.C'.i = occur.A.i + occur.B.i)] .
The result of combining the two specifications Sl and S2 is, by Theorem 27.6,
{sorted.A /\ sorted.B} ;
[(C := C' I sorted.C') n
(C := C' I (Vi occur.C'.i = occur.A.i + occur.i]
= {combine relations}
{sorted. A /\ sorted.B} ;
[(C := C' I sorted'c' /\ (Vi occur.C'.i = occur.A.i + occur.B.i]
Note that although both component specifications were nondeterministic, the result
of combining them is deterministic.
27.4. Refining Conjunctive Specifications 457
Theorem 27.7 Let predicates p and q and relations p. Q. and R be arbitrary. Then
p c; p n [Q).q 1\ Ipi ; Q ; R c; P
== {property of meet}
p c; [Q).q 1\ Ipl ; Q ; R c; P
The rule in (b) follows from Theorems 27.3 (b) and 27.1 (b). We leave it to the
reader to verify this. D
first consider refinements of the form {p} ; [Q] !; S, where {p} ; [Q] is a given
conjunctive specification. This expresses Theorem 17.6 in a more general form.
Theorem 27.8 Assume that p and q are predicates, Q a relation, and S a monotonic predicate
transformer. Then
Proof We have
{p};[Q]!;S
={definitions}
(Vq a p.a 1\ Q.a S; q ::::} S.q.a)
={mutual implication; subderivations}
(Vq a p.a 1\ Q.a S; q ::::} S.q.a)
::::} {specialization q := Q.a; simplification}
(Va' p.a ::::} S.(Q.a).a)
(Vq a p.a 1\ Q.a S; q ::::} S.q.a)
{:: {S monotonic}
(Va p.a ::::} S.(Q.a).a)
(Va' p.a ::::} S.(Q.a).a)
o
Note that Lemma 17.4 follows as a special case of this, by choosing Q := (Aa' q).
The reader can verify that Theorem 27.8 can be reformulated as follows:
Proof
Smonotonic
I-- {Q} !; S
= {definitions, rewriting implication}
(Vq a (3a' Q.a.a' 1\ q.a') ::::} S.q.a)
460 27. Specification Statements
two demonic updates is just the demonic update for conjunction of the relations
involved: [P] u [Q] = [P n Q]. This has sometimes been taken as an argument
for why a relational semantics for programs is superior to a predicate transformer
approach [76, 89]. As we have tried to show here, this argument is not really valid,
because relational semantics forms a subclass of predicate transformer semantics.
Hence, we do not lose anything by choosing predicate transformer semantics, but
rather we gain expressibility. A relational specification can be built, combined
and analyzed within the relational domain, and once the different requirements
have been combined into a good specification, refinement can continue on the
statement/predicate transformer level. The problem of conjunctive upper bounds
and ways of finding the least one has been studied by a number of authors, including
Morgan [107] and Back and Butler [19].
The quotient operator on relations is very close to the weakest prespecijication
operator that Hoare and He use as a basis for a method of stepwise refinement [91]
within a relational framework.
We also gave a general rule for refining any (conjunctive or universally disjunctive)
specification statement with an arbitrary statement. This shows that refinement be-
tween programs can always be reduced to a correctness formula in the weakest
precondition calculus, and thus refinement provides a bridge in the other direction
between refinement calculus and weakest precondition calculus for total correct-
ness (the other direction being the definition of the refinement relation itself). This
characterization of refinement was originally given by Back [7] in terms of strongest
postconditions. A similar characterization was also given by Morgan [104].
27.7 Exercises
27.1 Show that Theorem 27.1 (d) follows from (b) by duality.
27.2 Show that the refinement
27.4 Show that the following equality always holds when S is a conjunctive predicate
transformer:
S; {pI = {S.p}; S .
462 27. Specification Statements
27.5 Show that {p Uq}; [P n Q] is always a refinement of both {p}; [P] and {q}; [Q].
This means that {pUq}; [P n Q] is an upper bound of {p}; [P] and {q}; [Q]. Give
a counterexample showing that {p U q} ; [P n Q] need not be the least conjunctive
upper bound.
27.6 Prove that the following equivalence holds:
Refinement in Context
The refinement relation is very restrictive, as it requires that the refining statement
preserve the correctness of the original statement no matter what pre- and post-
conditions are assumed for the original statement. In practice, we are interested
mostly in refining a statement that occurs as a component of a larger statement.
This context will then restrict the pre- and postconditions that need to be preserved
for the whole statement to be refined.
We described in Section 17.4 how to carry out such refinements in context. In this
chapter, we will look at this technique in more detail, in particular on the methods
for propagating context information inside a program statement. We consider only
conjunctive commands here, though a dual theory can be built up for disjunctive
commands (see the exercises).
does not hold, but for which C[S] !; C[S'] would still hold. In other words, the
replacement of S by S' preserves the correctness of the whole statement.
This can indeed be done in a systematic way, as follows: First find a statement
So such that C[S] = C[Sa]. Then find a refinement S' of So. The refinement
C[S] !; C[S'] then follows by monotonicity and transitivity. The less refined So
is, the more freedom it gives us in the subsequent refinement.
Kernel Equivalence
Refinement in context can be described in terms of kernel equivalence. Given an
arbitrary function f : :E --+ r, we define = f, the kernel equivalence of f, by
We can now show that the smallest element shown to exist in Lemma 28.1 has a
desirable property.
Lemma 28.2 Assume that :E and r are complete lattices and that the function f : :E --+ r is
meet homomorphic. Then the following holds, for arbitrary x. y : :E:
(n z I x = f z z) !; y ::::} fx!; fy .
28.1. Taking the Context into Account 465
Proof
(n z I z = / x z) !; y
f- f.y
;) {assumption, n-homomorphism implies monotonicity}
f.(n z I z = / x' z)
= tn-homomorphism}
(n z I z = / x f.z)
= {kernel equivalence}
(nz I z =/ x' f.x)
= {meet of singleton set}
fx
o
For predicate transformers, the two lemmas above show the following. Consider a
statement C[S] where C[.] is a meet homomorphic context. Then there always ex-
ists a smallest predicate transformer So such that C[S] = C[So], and furthermore,
a refinement C[So] !; C[S'] holds whenever So !; S' holds. We can build meet
homomorphic contexts by using guards, asserts, demonic updates, sequential com-
position, meets, least and greatest fixed points, iterations, and all other constructs
that are conjunctive or preserve conjunctivity.
Context Assertions
Assume that C[S] is given, with S a predicate transformer and C[.] a meet homo-
morphic context. It may not be feasible to find the least predicate transformer So
such that C[S] = c[So]. In practice, we can make considerable progress by finding
a (reasonably strong) predicate p (a context assertion) such that C[S] = C[{p}; S].
When we then refine {p} ; S, we are really refining S under the (contextual) knowl-
edge that the predicate p can be assumed to hold in any initial state from which S
is executed.
For this to work we need rules for propagating context assertions. We can start
with outermost assertions {true} (i.e., skip) and then propagate these inwards until
the assertions meet at the subcomponent that we want to refine. The structure of
the derivation is then
C[S]
= {skip = {true}}
{true} ; C[S] ; {true}
!; {propagate context assertions}
466 28. Refinement in Context
C[{p}; {q}; S]
= {merge assertions, {p}; {q} = {p nq}}
c[{pnq};S]
~ {prove {p n q} ; S ~ S', monotonicity}
C[S']
Note that we here have generalized the method for propagating context assertions,
as compared to Section 17.4, by permitting both forward and backward propagation
of assertions. In practice, forward propagation seems to be the most useful method.
A restricted refinement puts weaker constraints on the refining statement:
Example
Consider, as an example, the following statement, where x and y are assumed to
be program variables ranging over the natural numbers:
x := x + 1 ; Y := x + 2; if Y ~ 3 then skip else abort fi .
Let us simplify this statement. The rules for assertion propagation to be given
below permit us to construct the following derivation:
x := x + 1 ; Y := x + 2; if Y ~ 3 then skip else abort fi
= {add initial and final trivial assertions}
{true} ; x := x + 1 ; y := x + 2; if Y ~ 3 then skip else abort fi ; {true}
~ {propagate assertion forward}
x := x + 1 ; {x ::: I}; y := x + 2; if Y ~ 3 then skip else abort fi; {true}
~ {propagate assertion backwards}
x := x + 1 ; {x ::: I} ; y := x + 2; {y ~ 3}; if Y ~ 3 then skip else abort fi
= {propagate assertion backwards}
x := x + 1 ; {x ::: I}; {x ~ I}; y := x + 2; if Y ~ 3 then skip else abort fi
= {merge assertions}
x := x + 1 ; {x = I}; y := x + 2; if Y ~ 3 then skip else abort fi
= {refinement in context}
x := x + 1 ; Y := 3 ; if Y ~ 3 then skip else abort fi
28.2. Rules for Propagating Context Assertions 467
This derivation illustrates the way in which statements preceding the component
to be replaced, as well as statements following this component, can contribute to
the context assertion that we can assume when refining the component.
S !; [p); {p} ; S .
Now we can refine S in context {p}. Furthermore, we need rules by which we can
show that C[[p] ; {p} ; S] = C[{p} ; S]; i.e., the context assumption [p] can be
discharged. The rules for propagating the guard [p] backwards in order to discard
are described below. If we have chosen the context assumption correctly, then the
propagated guard statement is eventually reduced to skip and can then be removed.
This will then establish that C[S] = C[{p}; S], from which we then continue with
a refinement in context as before.
Restricted refinement can also be expressed in terms of context assumptions. From
Lemma 13.12 we know that {p} ; S !; S' == S!; [p] ; S', so we could first carry
out refinements that add context assumptions, C[S] = C[[p] ; S'], and then show
that the guard statement can actually be removed.
statement. For meet, we need a rule that to one conjunct adds assertions induced by
the other conjuncts (we refer to this as sideways propagation). Intuitively speaking,
forward propagation carries information about the results of previous computations,
while backward and sideways propagation carries information about what states
can be treated arbitrarily, since they would lead to nontermination in the subsequent
computation.
Theorem 28.3 Let SandS' be arbitrary conjunctive predicate transformers and p and q predi-
cates. Then
Proof Assume that S and S' are conjunctive. Since dropping an assertion is always
a valid refinement, we need only consider left-to-right refinement in the proof. For
(a), we have
{p};S!;{p};S;{q}
== {definitions}
0Ir' p n S.r ~ p n S.(q n r
== {S conjunctive}
0Ir p n S.r ~ p n S.q n S.r)
== {lattice property x !; x n y == x !; y}
(Vr p n S.r ~ S.q)
== I=> by specialization (r := true), {= by monotonicity (r ~ true)}
p n S.true ~ S.q
The proofs of (b) and (c) are similar. 0
In general we are interested in adding the strongest (i.e., least with respect to the
refinement ordering) assertions possible, since a stronger assertion carries more
information than a weaker one. Theorem 28.3 (b) and (c) immediately give us rules
for finding the strongest possible assertion to be added. In (a), we do not give a
closed expression for the strongest forward-propagated assertion. However, one
can show that such an assertion always exists:
28.2. Rules for Propagating Context Assertions 469
Lemma 28.4 Let conjunctive predicate transformer S : ~ t-+ r and predicate p over ~ be given.
Then the strongest predicate q such that {p} ; S = {p} ; S; {q} is the following:
(nq I p n S.true ~ S.q q) .
Proof We give the predicate (nq I p n S.true ~ S.q q) the name qo. First we
show that qo satisfies the desired condition:
{p} ; S = {p} ; S; {qo}
== {Theorem 28.3 (a), definition of qo}
p n S.lrue ~ s.(nq I p n S.lrue ~ S.q q)
== {S conjunctive}
p n S.lrue ~ (nq I p n S.true ~ S.q S.q)
== {general rule (Vx EA Y !; x) == y !; nA}
T
We then show that qo is in fact the strongest of all predicates satisfying the condition
in question:
{p}; S = {p}; S; {q}
== {Theorem 28.3 (a)}
p n S.true ~ S.q
== {rewrite}
q E {q I p n S.true ~ S.q}
=> {general rule x E A => nA !; x}
(nq I p n S.true ~ S.q q) ~ q
== {definition of qo}
qo ~ q
Corollary 28.5 Assume that predicates p and q are given and that S is a conjunctive predicate
transformer. Then
{p};{q} {p};{q};{pnq} ,
{p}; [q] = {p};[q];{pnq} ,
{p} ; (f) {p} ; (f) ; {imfp} ,
{p} ; [Q] {p}; [Q]; {im.Q.p} .
Recall here that im.f.p = {y I (3u p.u 1\ Y = j.u)} (the image of p under f),
while im.Q.p = {y I (3u p.u 1\ Q.u.y)} (the image of p under relation Q).
For backward propagation, we immediately get the following rules for basic state-
ments:
{q};{p} {pnq};{q};{p} ,
[q] ; {p} {-"qUp};[q];{p} ,
(f) ; {p} {f-l.p} ; (f) ; {p} ,
[Q] ; {p} {Au Q.u ~ p} ; [Q]; {p} .
Example Derivation
The following derivation illustrates how one works with assertions. We start from
the following statement over program variables x, y : Nat:
x := x + 1 ; (y := x + 1 n {x < 2} ; y := x) .
The main aim is to refine the substatements y := x + 1 and y := x.
x := x + 1 ; (y := x + 1 n {x < 2} ; y := x)
= {add vacuous assertion}
{true} ; x := x + 1 ; (y := x + 1 n {x < 2} ; y := x)
= {forward propagation for functional update, simplify}
x := x + 1 ; {x > O} ; (y := x +1 n {x < 2} ; y := x)
= {sideways propagation (Exercise 28.2)}
x := x + 1 ; {x > O} ; ({x < 2} ; y := x +1 n {x < 2} ; y := x)
= {distributivity, merge assertions (homomorphism property)}
x := x + 1 ; ({x = I}; y := x +1 n {x = I}; y := x)
The final step here was to drop all assertions, in order to make the final statement
easier to read. We could also leave the assertions in the code, since they convey
information that might be used if the result is to be refined further.
Conditionals
The rules for sequential composition and meet can be used to derive rules for other
constructors. For the deterministic conditional, we have the following rule:
Theorem 28.6 Assertions are propagated into and out of a deterministic conditional as follows:
{p} ; [g] ; {p n g} ; S; {q} ; {q} n {p} ; [--. g] ; {p n --. g} ; S' ; {q} ; {q}
= {distributivity}
{p} ; ([g] ; {p n g} ; S; {q} n [--. g] ; {p n --. g} ; S'; {q}) ; {q}
= {definition of deterministic conditional}
{p} ; if g then {p n g} ; S; {q} else {p n --. g} ; S' ; {q} fi ; {q}
Loops
For loops, we derive a rule for adding an invariant as a context assertion. In addition
to the invariant, the guard of the loop gives information; it always holds when the
body is executed, and it cannot hold after the loop has terminated.
{p};whilegdoSod = {p};whilegdo{png};S;{p}od;{--.gnp}.
{g n p} ; S = {g n p} ; S; {p}
(use Corollary 28.5). Now define functions f and h by
{p};abort = {p};abort;{--.gnp},
28.3. Propagation in Derived Statements 473
which is obviously true. For the successor case, we assume that (*) holds for a.
Then
{p} ; (1"+ 1.abort)
= {definition of f}
{p} ; if g then S ; (I" .abort) else skip fi
= {assertion propagation rule, skip = {true}}
{p}; if g then {g n p}; S; (I" .abort) else { .... g n p} fi
= {assumption of the lemma}
{pI ; if g then {g n p} ; S; {pI ; (I" .abort) else { ..... gnp} fi
= {induction assumption}
{p}; if g then {g n p}; S; {p}; (ha.abort); { ..... g n p} else { ..... g n p} fi
= {assertion propagation rule}
{p}; if g then {g n p} ; S; {p}; (h a .abort) else skip fi; { ..... gnp}
= {definition of h a+1}
{pI ; (h a +1.abort) ; { ..... gnp}
Finally, we have the limit case, assuming that (*) holds for all ordinals fJ < a:
{pI ; (fa .abort)
= {definition of r}
{pI ; (u fJ I fJ < a jP .abort)
= {distributivity (assert is disjunctive)}
(UfJ I fJ < a' {p}; (fP.abort
= {induction assumption}
(ufJ I fJ < a' {p}; (hP.abort); { ..... g n p})
= {distributivity}
{p}; (ufJ I fJ < a' hP.abort); {..... g n p}
= {definition of hal
{pI ; (h a .abort) ; { ..... gnp}
Thus (*) holds for an arbitrary ordinal. and the proof is finished. 0
Note that the predicate p in Theorem 28.7 is a weak invariant: the body S has to
preserve p only if S terminates. This is different from the strong invariant used
in total correctness proofs of loops. Propagation of assertions in the loop does not
require the loop to terminate.
The generalization of Theorem 28.7 to guarded iteration is straightforward: if
gi n p n Si.true ~ Si.P for i = I, ... , n, then
474 28. Refinement in Context
{p} ; do gl ~ SI 0 ... 0 gn ~ Sn od =
{p};dogl ~ S; 0 Ogn ~ S~od;{ ..... gnp},
Blocks
For blocks we need two rules: one for propagating an assertion into the block
from the left and one to propagate an assertion out from the block on the right.
For simplicity, we use the general demonic (nondeterministically initialized) block
construct in the rule, since the other block constructs are special cases of this one.
Theorem 28.8 Assume that p, q, and r are Boolean expressions such that y does not occur free
in p or q. Furthermore, assume that p and p' are similar, and that r and r' are
similar. Then
Proof Both proofs are straightforward, using the definition of the block. We show
the crucial derivation for the second part. We have
{r} ; (end) I; (end) ; {3y r}
== {definitions}
{AY 17' r.y 1\17 = end.y} I; {AY 17 '17 = end.y 1\ (3y' r).I7}
<= {homomorphism}
(Vy 17 'r.y 1\ 17 = end.y "* 17 = end.y 1\ (3y' r).I7)
== {one-point rule}
(Vy 'r.y "* (3y' r).(end.y
== {pointwise extension}
(Vy 'r.y "* (3y' r.(end.y)))
== {use y.y as existential witness}
T
and the rule now follows from the definition of the block. 0
Similar rules can also be derived for propagating assertions backwards into and
out of blocks (Exercise 28.4).
28.4. Context Assumptions 475
Theorem 28.9 Guard statements can be propagated backwards according to the following rule
whenever S is conjunctive:
S; [q] !; [S.q]; S .
Proof
S; [q] !; [S.q] ; S
== {Lemma 13.12}
{S.q}; S!; S; {q}
== {Theorem 28.3 (b)}
T
o
We can now state rules for individual program constructs that can be used in
practical program derivations. Most of the rules follow directly from Theorem
28.9.
Theorem 28.10 The following rules are available for basic statements:
Theorem 28.11 The following rules are available for derived statements:
(a) if g then S else Sf fi; [q] = if g then S; [q] else Sf; [q] fi .
(b) if g then [q]; S else [qfJ; Sf fi = [(g nq) U (--, g nqf)]; if g then S else Sf fi .
476 28. Refinement in Context
(c) begin var yip; Send; [q] = begin var yip; S; [q] end provided that y
does not occur free in q.
(d) begin var yip; [q] ; Send = [Vy. p =} q] ; begin var yip; S end .
Proof The rules for conditional and block are proved in the same way as the
corresponding rules for propagating assertions. 0
The idea behind guard propagation is that we want to eliminate guards from our
program. By propagating guards backwards we hope to weaken the predicate inside
the guard statement, so that it eventually reduces to true and the whole guard
statement can be removed. Note that there is no rule for loops; we assume that
whenever a loop is introduced, sufficient information about the loop is added as an
assertion after the loop.
As an example, we show how context assumptions are used to refine a simple
sequential composition. Here we introduce the pair [x = 0] ; {x = O} at a point
in the program where we (by looking at the preceding assignment) feel confident
that x = must hold.
x, Z := 0, z z; y := x + 1
!; {add context assumption pair; skip!; [p] ; {p}}
x, z := 0, z . z ; [x = 0] ; {x = o} ; y := " x + 1 "
= {use assertion for refinement in context}
x, z := 0, z . z; [x = 0] ; y := 1
= {propagate guard statement}
[true] ;x,Z:= O,z Z; y:= 1
= {[true] = skip}
x, Z:= 0, z Z; y:= 1
To show that the context assumption approach allows propagating smaller amounts
of information, we also show an alternative derivation using context assertion
propagation only:
x, Z:= 0, z Z; y:= x + 1
= {add initial assertion; skip = {true}}
{true} ; x, Z := 0, Z z; y := x + 1
= {propagate assert}
x, Z := 0, z Z; {x = /\ (3zo Zo . Zo = z)} ; y := x +1
= {use assertion for refinement in context}
x, Z := 0, z Z; {x = /\ (3zo Zo . Zo = z)} ; y := 1
28.5. Summary and Discussion 477
!; {drop assert}
x, z := 0, z . z; y := 1
These two examples also show the duality between the two approaches; the justi-
fications in the first derivation are very similar to those in the second derivation,
but in reverse order.
Theorem 28.12 Assume that predicates p and q are given and that S is a conjunctive predicate
transformer. Then
Proof The result follows directly from Corollary 28.5 and Lemma 13.12. 0
Exactly as in the case of the corresponding result for assertions (Corollary 28.5),
this result can be useful when we assume a certain correctness condition and want
to use it in an algebraic manipulation of statements.
The propagation rules for context assertions and context assumptions are also inter-
esting in their own right. They give a general paradigm for transporting information
relevant for total correctness around in a program statement. Although one might
expect otherwise, these rules are not the same as one would get by considering a
proof system for partial correctness. There are a number of places where the context
assertions and assumptions propagate in a different way than partial correctness
assertions, which essentially express reachability of states.
478 28. Refinement in Context
28.6 Exercises
28.1 Prove the following rules for forward propagation of context assertions through
different statements:
{p};{q} = {p};{q};{pnq} ,
{p};[q] = {p};[q);{pnq} ,
{pI ; (f) = {p}; (f) ; {imfp} ,
{pI ; [Q] {pI ; [Q] ; {im.Q.p}
28.2 Show that the following rule follows from Theorem 28.3 (c):
28.3 Give an example of a statement {p} ; S for which there is no predicate q satisfying
{p};S = S;{q}.
Conclude that it is impossible to give a rule for forward propagation of assertion
without loss of information.
28.4 Derive rules for propagating assertions backwards into and out of blocks.
28.5 In a language of disjunctive statements, assertions can also be used to indicate
context information. In the disjunctive case, assertions have to be interpreted
differently. For example, the assertion introduction
S = S;{p}
now means that for all initial states there is a possible execution of S such that p
holds in the final state. However, the principle of restricted refinement can still be
used. Derive rules for introducing assertions before and after the angelic update
command. Is there a rule for adding an assertion to one element of a join?
28.6 Complete the proof of Theorem 28.10.
28.7 Complete the proof of Corollary 28.5 (a); i.e., prove that
Fixed-Point Diagonalization
The following diagonalization lemma gives a way of moving between fixed points
over one variable and fixed points over multiple variables. Exactly as for A-
abstraction, the notation (/-LX Y t) abbreviates (/-Lx (/-L Y t.
Lemma 29.1 Assume that the type E is a complete lattice and that the junction f :E -+ E -+ E
is monotonic in both its arguments, Then
Then
(f-Lx f.x.x) !; (f-Lx y. f.x.y)
{= {least fixed point induction with f := (AX f.x.x))
f.(f-Lx y. fx.y).(f-LX y. fx.y) ~ (f-Lx y. fx.y)
== {unfold least fixed point with f := (AX (f-L Y f.x .y))}
f(f-Lx y. f.x.y).(f-LX y. fx.y) ~ (f-LY f.(f-LX y. fx.y).y)
== {unfold least fixed point with f := (Ay f.(f-Lx y. f.x.y).y)}
f.(f-Lx y. fx.y).(f-LX y. f.x.y) !;
f(f-Lx y. f.x.y).(f-LY f(f-Lx y. fx.y).y)
== {fold least fixed point with f := (Ax (f-L y. f.x.y}
f.(f-Lx y. f.x.y).(f-LX y. fx.y) ~ f.(f-LX y. fx.y).(f-LX y. fx.y)
== {reflexivity}
T
o
f.(J-L.(g 0 f J-L.(f 0 g) ,
f(v.(g 0 f)) v.(f 0 g) .
Proof We prove the first part; the proof for the greatest fixed point is similar.
We first note that fog and g 0 f are both monotonic, so the fixed points are
well-defined. Now we prove mutual ordering:
and
f(J-L(g 0 f) ~ J-L.(f 0 g)
== {definition of composition, change to binder notation for J-L}
f(J-Lx g.(f.x) ~ (J-Lx f.(g.x))
== {unfold least fixed point}
f(J-Lx g'(f'x)) ~ f(g.(/-Lx f.(g.x)
{= {f monotonic}
(/-Lx g.(f.x)) ~ g.(J-Lx f(g.x
{= {least fixed point induction}
g.(f. (g. (J-Lx f(gx)) ~ g.(J-Lx f.(g.x))
== {fold least fixed point}
g.(J-Lx f.(g.x)) ~ g.(J-LX f.(g.x))
== {reflexivity}
T
o
Theorem 29.3 Assume that h is a monotonic function on predicate transformers and S is a mono-
tonic predicate transformer. Then (AX h.(S ; X and (AX S; h.X) are also
monotonic functions, and
The other consequence is the following rolling property for least fixed points of a
sequential composition:
p,.(S; T) = S.(p,.(T; S .
Proof Use Lemma 29.2 with f := Sand g := T. 0
(Ypq-s.pns.(s*.q)nq = s.(pns*.q)nq)
== {S conjunctive}
T
We leave it to the reader to show that ()..q - {q} ; S) is continuous for arbitrary
monotonic S (this guarantees that the second step of the derivation is valid). The
second part of the lemma can be proved in a similar way, showing {IL.S} ; S* =
S* ; {IL.S} using the dual of fusion (with greatest fixed points) and relying on the
fact that the function (AS - {q} ; S) is cocontinuous (Exercise 29.2). 0
Recall that IL.S characterizes those states from which repeated execution of S is
guaranteed to terminate. Thus Lemma 29.5 shows how the strong iteration SO) can
be divided into two parts; the assertion checks for possible nontermination, and the
weak iteration performs the repeated execution of S. This is reminiscent of the tra-
ditional decomposition of total correctness into termination and partial correctness.
The same correspondence can also be expressed using infinite repetition:
SW = S*nSoo.
Now we can prove the result that was announced in Chapter 21.
Theorem 29.7 Strong iterations, while loops, and guarded iterations preserve conjunctivity.
The results for while loops and guarded iterations now follow directly, since they
can be rewritten using strong iteration. 0
Leapfrog Properties
The following lemma states that conjunctive iterations have what is sometimes
called the leapfrog property.
Lemma 29.8 Assume that predicate transformer S is conjunctive and T monotonic. Then
= {S conjunctive}
(v X S; T; X n S)
= {Lemma 21.2}
(S; T)*; S
The proof of Lemma 29.8 rests heavily on the conjunctivity of S. If S is not assumed
to be conjunctive, it is possible to show the following (Exercise 29.3):
The leapfrog property can now be used to prove a rule for manipulating while
loops.
Lemma 29.9 Assume that SandT are conjunctive and that g and g' are predicates such that
g fl S Rg' and..., g fl S R..., g'. Then the following refinement holds:
S ; while g do T ; S od !;; while g' do S ; Tad; S .
Decomposition Properties
The following iteration decomposition lemma shows that it is possible to rewrite
iterations of meets in a form that contains only sequential composition and iteration:
Lemma 29.10 Assume that predicate transformer S is conjunctive and T monotonic. Then
(S n T)* = S*; (T ; S*)* ,
(S n T)'" = S"'; (T ; SW)'" .
486 29. Iteration of Conjunctive Statements
Proof We show the proof for strong iteration (the proof for weak iteration is
similar).
S conjunctive, T monotonic
f- (S n T)'"
= {definition}
(J..L X (S n T) ; X n skip)
= {distributivity}
(J..L X S; X n T; X n skip)
= {diagonalization (Lemma 29.1)}
(J..L X J..L Y S; Y n T ; X n skip)
= {Lemma 21.2}
(J..LX S"'; (T; X nskip
= {Theorem 29.3}
S"'; (J..LX T; S"'; X n skip)
= {definition of strong iteration}
S"'; (T; S"')'"
D
Combining Lemma 29.10 with the leapfrog properties in Lemma 29.8 we imme-
diately get the following corollary:
Corollary 29.11 Assume that predicate transformer S is conjunctive and T monotonic. Then
Proof
while g U h do if g then S else T fi do
= {rewrite loop using iteration}
([g U h] ; if g then S else T fi)'" ; [ ...... (g U h)]
= {rewrite conditional}
([g U h] ; ([g] ; S n [......g] ; T"'; [...... (g U h)]
= {distributivity, homomorphism, lattice properties}
([g]; S n [. . . g n h] ; T)"'; [......g n . . . h)]
= {decomposition (Lemma 29.1O)}
[g]; S)"'; [ ...... g n h] ; T)"'; ([g] ; S)"'; [ ...... g n . . . h)]
= {homomorphism}
[g]; S)"'; [ ...... g] ; [h]; T)'" ; ([g] ; S)"'; [ ......g] ; [ ...... h]
= {leapfrog (Lemma 29.8)}
([g]; S)"'; ["""g]; ([h]; T; ([g]; S)"'; [ ...... g])"'; [ ...... h]
= {rewrite iterations into loops}
while g do S od ; while h do T ; (while g do Sod) od
D
Theorem 29.12 may not seem very useful at first sight, but if the inner loop on the
right-hand side can be refined by a simple statement, then the right-hand side may
be a more efficient loop than that on the left-hand side (it may involve a smaller
number of repetitions).
while g U h do S od =
while h do S od ; while g do S ; (while h do Sod) od
for arbitrary predicates g and h.
Next, we consider a rule that allows us to remove (or add) a redundant loop:
Theorem 29.14 Assume that S is monotonic. Then
Proof We have
while g do S cd ; while g do S od
= {rewrite loop using iteration}
([g); S)"'; [ ..... g]; ([g); S)"'; [ ..... g]
= {unfold iteration}
([g) ; S)'" ; [.....g]; ([g) ; S; ([g) ; S)'" n skip) ; [ .....g]
= {distributivity}
([g); S)"'; ([ ..... g]; [g) ; S; ([g) ; S)'" n [ .....g]; skip) ; [ ..... g]
= {skip is unit, guard homomorphism}
([g); S)"'; ([ .....g n g) ; S; ([g) ; S)'" n [. . .g)); [ .....g] ;
= {guard property}
([g) ; S)"'; (magic; S; ([g) ; S)'" n [ .....g)); [ .....g]
= {magic properties}
([g) ; S)'" ; [ .....g]; [ .....g]
= {guard property}
([g) ; S)"'; [ .....g]
= {rewrite into loop}
whileg do S cd
whileg do Sod
= {Theorem 29.12 with h := g n h}
while g n h do S od ; while g do S ; (while g n h do Sod) od
= {first part of theorem}
while g n h do S cd ; while g n h do S od ;
while g do S ; (while g n h do Sod) od
= {Theorem 29.12}
while g n h do S od ; while g do Sod
D
29.6. Example: Finding the Period 489
When constructing the iterated sequence, two things can happen. Either the iteration
generates new values forever, or else at some point fk+n. x = fk. x for some k and
some n > O. In the latter case the sequence has a period.
Now assume that f : Nat ~ 1:: is a function such that iteration of f from 0 has a
period, i.e., assume
The problem is to find the minimal period p and a value x in the period. Using the
definition
First Solution
Let us give the name ko to the smallest number of iterations that takes us into the
period of f:
ko ~ min.{k I 3n n > 01\ fk+n.o = fk .O} .
The assumption (*) guarantees that the set is nonempty, so it has a well-defined
smallest element (because the natural numbers are well-ordered).
A simple way of finding the period would be to compute the iteration sequence (by
executing x := f.x repeatedly, starting from x = 0) and at every step compare the
new value with all the previous values. When the first repetition is found, we have
reached the point where x = flco.O and fP.x = x, and we know both the period
and a value in the period. However, this solution consumes too much of both time
and space, so we want to find a more efficient solution.
We still want to use the idea of executing x := f.x repeatedly, starting with x = 0,
but without having to store the values generated so far. One way of doing this is to
introduce an extra variable y and repeatedly execute x, y := f.x, f.(f.y), starting
from x = 0 1\ Y = f.O. An informal argument for this is as follows:
490 29. Iteration of Conjunctive Statements
(i) When x = fk o.0, we know that y must also be a value inside the period, since
y races ahead of x (and since both are then inside the period, y is also behind
x).
(ii) When we continue, we know that y moves inside the period one step closer
to x every time x, y : = f.x, f. (f. y) is executed.
This means that when y = x, we can be sure that x is inside the period. After this,
we can find the length of the period separately.
The idea described above is the basis for dividing the problem into subproblems:
Here the first step divides the derivation into two parts: first we find a value x in
the period, and then we find the length p of the period. The second step adds the
local variable y, and the third step divides finding the right value for x into two
parts (in accordance with the argument above): first we make x equal to fk o.0, and
then we continue until we can detect that x is in fact within the period. The last
step rewrites the assertion from stating that y is ahead of x to stating that y is both
ahead of and behind x. This information will be crucial in later loop introductions.
The verification of the two sequential composition introductions and the block
introduction is straightforward, so we leave them to the reader.
Introducing Loops
We are now in a position to introduce the repeated assignments to x and y that
were announced earlier. We start from the first demonic assignment:
[x, y:= x', y' I x' = fko.O A (3m 1m> O y' = fm. x ')]
I; {add initial assignment}
x, y := 0, f.O; {x = 0 A Y = f.O} ;
[x, y:= x', y' I x' = fko.O A (3m 1m> O y' = fm. x ')]
I; {introduce loop}
x, y := 0, f.O;
while x =F fko.O do
[x, y:= x',y' I x' = f.x A (3m 1m> O y' = fm. x ')]
od
The loop invariant here is (3k k ~ leo AX = fk .0) A (3m 1m> O y = fm .x), "x
has not passed fko .0, and y is ahead of x". The variant is leo - min.{k I x = fk .O},
"the number of iterations remaining" (the minimum operator min is discussed in
Exercise 29.11). Note that by initializing y to f.O we make sure that y is initially
ahead of x. The nondeterminism in the loop body allows y to be updated freely on
every iteration, as long as it is "ahead of" x.
Next we can introduce a loop for the second part (an assertion plus a demonic
assignment):
{x = fko.O A (3m 1m> O Y = r .x) A (3n x = r .y)} ;
[x, y := x', y' I (3n minper.f.n.x')];
I; {introduce loop}
while x =F y do x, y := f.x, f2.y od
In this case the loop invariant is (3m 1m> O y =
fm .x) A (3n x =r
.y), "y
is both ahead of and behind x". The variant is min.{m I x = fm .y}, the number of
iterations remaining.
492 29. Iteration of Conjunctive Statements
Finally, we introduce a loop for finding the period once x has its correct value (the
final combination of an assertion and a demonic assignment):
{3n minper.j.n.x};
[p, y := p', y' I minper.j.p'.x]
!; {add initial assignment}
p, y := 1, f.x ;" {p = 1/\ Y = f.x /\ (3n' minper.f.n.x)};
[p, y := p', y' I minper.f.p'x] "
!; {introduce loop}
... while x =1= y do p, y := p + 1, f.y od
Here the loop invariant is (3n minper.f.n.x /\ 0 < p ::: n /\ y = fP.x), "p has
not passed the value of the period". The variant is min.{n In> 0/\ r.x = x} - p,
the number of iterations remaining.
which is trivially true. We then show invariance and termination separately. The
loop body must preserve the invariant:
x =1= y A (3m 1m> O Y = r .x) A (3n x = r .y) =?
(3m 1m> O f2.y = fm+l.x) /\ (3n' f.x = r+ 2.y)
={quantifier rules}
(Vm n x =1= y /\ m > 0 A Y = fm .x A X = r.y =?
(3m 1m> O f2.y = r+l.x) A (3n' f.x = r+2.y
This is not hard; we choose m + 1 and n - 1 as existential witnesses (from x =1= y
it follows that n > 0).
Next, the loop body must decrease the variant:
(Vw' x =1= y A (3m 1m> O' y =r .x) A (3n x =r .y) A
min.{m I x = fm.y} = w =?
min.{m I f.x = r+2.y} < w)
={quantifier rules}
(Vm n x =1= yAm> 0 A Y = fm.x A x = ry =?
min.{m I f.x = r+ .y) < min.{m I x = rY})
2
29.6. Example: Finding the Period 493
Here the argument is that for every element min {m I x = fm.y}, the number
m - 1 must be in {m I f.x = f m +2. y } (the antecedent implies that 0 is not in
{m I x = fm .y} and that the sets are nonempty). The full formal proof requires
some properties of the min operator (see Exercise 29.11).
Finally, the postcondition must hold on exit:
Final Refinements
Collecting the loop introductions, we get the following version of the program:
begin var y : Nat;
x, y:= 0, f.O;
.. while x =f. f"".O do
[x, y := x', y' I x' = f.x 1\ x' =f. y' 1\ (3m y' = fm .x')]
od;
while x =f. y do x, y := f.x, f2.y od";
p, y := 1, f.x ;
while x =f. y do p, y:= p + 1, f.y od
end.
There is still a loop guard that mentions the unknown value leo. However, if the
body of that loop can be made the same as the body of the following loop, then we
can try to merge the two loops. To do that, we first make the first loop body more
deterministic and then use the loop invariant of the first loop to rewrite the guard:
while x =f. flco.O do
.. [x, y := x', y' I x' = f.x 1\ (3m 1m> O y' = fm .x')] "
od;
while x =f. y do x, y := f.x, f2.y od
= {make loop body more deterministic}
while" x =f. flco.O" do x, y := f.x, f2.y od;
while x =f. y do x, y := f.x, f2.y od
= {use loop invariant to rewrite guard}
while x =f. y 1\ x =f. flco.O do x, y := f.x, f2.y od;
494 29. Iteration of Conjunctive Statements
29.8 Exercises
29.1 Prove that if predicate transformer S is conjunctive, then the following holds:
S;S = S;S.
Compare this with Exercise 21.2.
29.8. Exercises 495
29.2 The dual of the fusion theorem guarantees that if h is universally meet homomor-
phic, then
29.7 Prove the following variation on the loop decomposition rule, for conjunctive S
andT:
1. / div mod x
2. + --+
3. ~ < :::: >
4. 0 \
5. n n
498 Appendix
6. u U U
7. '-
8. I; c ~ c
9. E
10. A
11. v
12.:::} {;;;
13. ... 0 ... D... ... 0 ... D.. ,
14. ==
Negated operators have the same precedence as the original operator.
B: Homomorphism Tables
In these tables we use the following abbreviations for statement constructors:
is c 1.. T n u lim ~
is c 1.. T n u lim ~ 1 ;
(Ap {p}) yes yes no yes! yes yes no yes yes
(Ap- [p]) yesO yesO no yeso! yeso yesO no yes yes
(i..j' (f)) yes - - - - - - yes yes
(AR {R}) yes yes no no yes yes no yes yes
(AR' [R]) yesO yes O
no no yesO yesO no yes yes
(AS' S; T) yes yes yes yes yes yes yes no no
(AT S; T) yes yes 2 yes3 yes 4 yess yes6 yes 7 no no
(AS, T S; T) yes yes yes no no no no no no
(AS' S n T) yes yes no yes yes yes no no no
(AS, T' Sn T) yes yes yes yes no no no no yesO
(AS' S u T) yes no yes yes yes yes no no no
(AS, T' S u T) yes yes yes no yes yes no no yesO
(AS' ~S) yesO yesO yesO yesO yesO yesO yes no no
(AS' SO) yesO yesO yesO yes O yesO yesO yes yes yes
(AS' SO) yes yes no no no no no yes no
(AS. SW) yes yes no no no no no no no
(AS. SOO) yes yes no no no no no no no
IIThen yes yes yes no no no no no no
If yes yes no no no no no no no
While yes no no no no no no no no
Do yes no no no no no no no no
! when the meet is taken over nonempty sets 2if S is strict 3if S is terminating
4if S is conjunctive sif S is disjunctive 6if S is continuous 7if S is ~-homomorphic
For each operation on the left, the entry indicates whether the construct preserves
(or has) the homomorphism property indicated in the column: !; (monotonicity);
..i (bottom), T(top), n (meet), U (join), and ..... (negation). Duality (yesO) indicates
that the property holds for the dual lattice.
References
[31 ]RJ. Back and 1. 'von Wright. Trace refinement of action systems. In B. Jonsson and
J. Parrow, editors, Proc. CONCUR-94, Volume 836 of Lecture Notes in Computer
Science, Uppsala, Sweden, 1994. Springer-Verlag.
[32]R.J. Back and I. von Wright. Games and winning strategies. Information Processing
Letters, 53(3):165-172, February 1995.
[33]R. Backhouse and B. Carre. Regular algebra applied to path finding problems. J.lnst.
Math. Appl., 15:161-186, 1975.
[34]R. Backhouse et ai. Fixpoint calculus. Information Processing Letters, 53(3),
February 1995.
[35]I.W. de Bakker. Semantics and termination of nondeterministic programs. In
S. Michaelson and R. Milner, editors, Proc. 3th International Colloqium on Au-
tomata, Languages and ofProgramming, 435-477, Edinburgh, Scotland, July 1976.
Edinburgh University Press.
[36]I.W. de Bakker. Mathematical Theory ofProgram Correctness. Prentice-Hall, 1980.
[37]H. Sarendregt. The Lambda calculus: Its Syntax and Semantics. North-Holland, 1984.
[38]M. Barr and C. Wells. Category Theory for Computing Science. Prentice-Hall. 1990.
[39]E. Best. Notes on predicate transformers and concurrent programs. Technical Report
145, University of Newcastle Computing Laboratory. 1980.
[40]G. Birkhoff. Lattice Theory. American Mathematical Society, Providence, 1961.
[41]HJ. Boom. A weaker precondition for loops. ACM Transactions on Programming
Languages and Systems, 4(4):668-677, October 1982.
[42]M. Broy. A theory for nondeterminism, parallellism, communications and concur-
rency. Theoretical Computer Science, 46:1-61,1986.
[43]R.M. Burstall and I. Darlington. Some transformations for developing recursive
programs. Journal of the ACM, 24(1):44--67,1977.
[44]MJ. Butler. A CSP Approach to Action Systems. Ph.D. thesis, Oxford University,
Oxford, England, 1992.
[45]MJ. Butler, J. Grundy, T. LAngbacka, R. Ruksenas, and I. von Wright. The Refinement
Calculator: Proof support for Program refinement. Proc. Formal Methods Pacific
(FMP'97), Wellington, New Zealand. Springer Series in Discrete Mathematics and
Theoretical Computer Science, 1997.
[46]M.J. Butler and C.C. Morgan. Action systems, unbounded nondeterminism and
infinite traces. Formal Aspects of Computing, 7(1):37-53, 1995.
[47]D. Carrington, I.I. Hayes, R. Nickson, G. Watson, and J. Welsh. Refinement in Ergo.
Technical Report 94-44, Department of Computer Science, University of Queensland.
QLD 4072, Australia, Dec. 1994.
[48]A. Church. A formulation of the simple theory oftypes. Journal of Symbolic Logic,
5:56-68.1940.
[49]T. Coquand and G. Huet. The Calculus of Constructions. Information and
Computation. 76:95-120,1988.
[50]S.A. Davey and H.A. Priestley. Introduction to Lattices and Order. Cambridge
University Press, 1990.
[51]E.W. Dijkstra. Notes on structured programming. In O. Dahl. E.W. Dijkstra, and
C.A.R. Hoare, editors, Structured Programming. Academic Press, 1971.
[52]E.W. Dijkstra. Guarded commands, nondeterminacy and the formal derivation of
programs. Communications of the ACM, 18:453-457, 1975.
504 References
[16]E. Hehner. Predicative programming, part I. Communications ofthe ACM, 21(2): 134-
143,1984.
[11]W.H. Hesselink. An algebraic calculus of commands. Report CS 8808, Department
of Mathematics and Computer Science, University of Groningen, 1988.
[18]W.H. Hesselink. Interpretations of recursion under unbounded nondeterminacy.
Theoretical Computer Science, 59:211-234,1988.
[19]W.H. Hesselink. Predicate-transformer semantics of general recursion. Acta Infor-
matica, 26:309-332,1989.
[80]W.H. Hesselink. Command algebras, recursion and program transformation. Formal
Aspects of Computing, 2:60-104,1990.
[81]W.H. Hesselink. Programs, Recursion and Unbounded Choice. Cambridge Univer-
sity Press, 1992.
[82]W.H. Hesselink. Nondeterminism and recursion via stacks and games. Theoretical
Computer Science, 124:213-295, 1994.
[83]1. Hintikka. Language Games and information. Clarendon, London, 1912.
[84]C.A.R. Hoare. An axiomatic basis for computer programming. Communications of
the ACM, 12(10):516--583, 1969.
[85]C.A.R. Hoare. Procedures and parameters: An axiomatic approach. In E. Engeler,
editor, Symposium on Semantics of Algorithmic Languages, volume 188 of Lecture
Notes in Mathematics, 102-116. Springer-Verlag, 1911.
[86]C.A.R. Hoare. Proof of a program: Find. Communications of the ACM, 14:39-45,
1911.
[81]C.A.R. Hoare. Proofs of correctness of data representation. Acta Informatica,
1(4):211-281,1912.
[88]C.A.R. Hoare. Communicating Sequential Processes. Prentice-Hall, 1985.
[89]C.A.R. Hoare. Programs are predicates. In C.A.R. Hoare and J. Shepherdson, editors,
Mathematical Logic and Programming Languages, 141-155. Prentice-Hall, 1985.
[90]C.A.R. Hoare, I.I. Hayes, J. He, C.C. Morgan, A.W. Roscoe, I.W. Sanders,
LH. Sorensen, J .M. Spivey, and A. Sufrin. Laws of programming. Communications
of the ACM, 30(8):612-686, August 1981.
[91]C.A.R. Hoare and J. He. The weakest prespecification. Information Processing
Letters, 24:121-132,1981.
[92]0. Jacobs and O. Gries. General correctness: A unification of partial and total
correctness. Acta Informatica, 22:61-83, 1985.
[93]P.T. Johnstone. Notes on logic and set theory. Cambridge University Press, 1981.
[94]C.B. Jones. Systematic Software Development Using VDM. Prentice-Hall Interna-
tional, 1986.
[95]C.R. Karp. Languages with Expressions of Infinite Length. North-Holland, 1964.
[96]0. Knuth. The Art of Computer Programming: Fundamental Algorithms. Addison-
Wesley, 1913.
[91]T. Ungbacka, R. RuUenas, and I. von Wright. TkWinHOL: A tool for doing win-
dow inference in HOL. Proc. 1995 International Workshop on Higher Order Logic
Theorem Proving and its Applications, Salt Lake City, Utah, USA. Volume 971 of
Lecture Notes in Computer Science, Springer-Verlag, 1995.
506 References
[142]J. von Wright. Program inversion in the refinement calculus. Information Processing
Letters, 37(2):95-100, January 1991.
[143]1. von Wright. The lattice of data refinement. Acta Informatica, 31:105-135, 1994.
[l44]J. von Wright. Program refinement by theorem prover. In Proc. 6th Refinement
Workshop, London, January 1994. Springer-Verlag.
Index