One reason why we studied Hoare logic is that its basic principles (pre/postconditions, invariants, separation of termination and partial correctness, …) are useful to the practice of writing code.
Another reason is that Hoare logic is one of the earliest examples of a successful attempt of developing mathematics of software engineering.
In this lecture, we take another look at this, starting from an idea we only touched upon in the previous lecture, namely Hoare's rule for assignment.
The interesting idea we discovered when discussing the rule is that it works backwards on predicates, from the postcondition backward to the precondition.
One thing I want to show you is that this is not a strange quirk, but rather a general principle.
To do this, let us first insert an excursion on discrete maths. Bear with me, you will be rewarded.
We reviewed the basic notation about sets and function in a previous lecture. But back then, we just gave the definition but didn't have time to talk more about the inverse image of a function.
If
is a function,[1] then we think of it as working "forwards",
taking an element
But while a function is working forwards on elements, it is working backwards on subsets.
To see how this works, let
Exercise: Think of ways of defining a subset of
There may be different ways of doing this, but the one I am after is what we may call the "weakest pre-condition of
The terminology of "weakest precondition" is appropriate since a subset
The next question is a bit of a distraction, so you can skip it.
Question: What is the strongest precondition? [^strongest]
Notation: If
The next question one should address is the following. If
Notation: We define
Exercise: We collect some useful facts about
We can use this notation to state succinctly that if we have
"going forward" then we also have
"going backwards".
The second item of the exercise says that subsets "are the same thing" as functions into the Booleans. We explore this a bit more in the following
Remark: There is an important alternative to understand what a subset is. Instead of saying
and a subset
we can put them together (using sequential composition) as
That is, a subset on
More Notation (not so important now, but useful later): If you look at
And, in fact, this notation for sets of functions is widely used. So we often find the set of functions
and again we have an elegant formula to compute the number of functions
The relationship between
Another feature one likes to have in a duality is that there is a bijective relationship between the "forward functions" and the "backward functions". This is can be made to work here and if you know about Boolean algebras you can try the following exercise.[4]
Miniproject: The aim is to show that not only for every map
This observation above is one of the most important ones in all of mathematics, logic, and computer science.
In programming terms, we can think of elements of
Accordingly, then, we may call
The importance of duality lies in part in the possibility of going from predicate transformers to state transformers, that is, from specifications to programs.
This idea has been turned into a whole field of study of how to derive programs systematically (and perhaps automatically) from specifications. For some references, look up predicate transformer semantics. A development of this is the Bird-Meertens formalism. If you like functional programming have a look at Bird, de Moor: Algebra of Programming .
Here I want to show you that you have seen a similar duality already in high-school when you used algebraic methods to solve geometric problems.
Recall how the equation
describes a straight line with slope m intersecting the
This equation defines a predicate on the plane of points
Indeed, we
Note that there are infinitely many points on the line and that the totality of these infintely many points is completely described by the equation
To make the analogy with programming, the equation
Now let me come to the main point of the excursion into geometry. As we are all aware from high-school mathematics, equations such as
What is even more important is that there is a whole calculus, algebra and analysis, that allows to manipulate these equations and compute with them.
To develop similarly powerful mathematics in order to manipulate specifications and programs instead of geometric figures is the dream of software engineering.
One reason to spend quite a bit of time on Hoare logic is that Hoare logic is one of the earliest and most successful attempts in developing such a mathematics of software engineering.
(more to be added…)
Some further references can be found in the wikipedia articles on
predicate transformer semantics
and the
If you like functional programming have a look at Bird, de Moor: Algebra of Programming .
For our purposes it may be helpful of thinking of
Thinking about
If we think of a "condition" as a subset, then a weaker condition is a larger subset and a stronger condition is a smaller subsets. More formally, a condition on
The technical notions are reviewed here (never got around writing this and we didnt need it for the course). ↩︎
The analogy is not perfect because we cannot explain here what really is the analogue of programs in geometry … this would require more time and lead too far away from where we want to go. But the main difference between computer science and geometry can be easily sloganized: In computer science we are interested in irreversible operations in time, in geometry we are interested in reversible transformations in space. ↩︎