Predicate transformer semantics were introduced by
Edsger Dijkstra in his seminal paper "
Guarded commands, nondeterminacy and formal derivation of programs". They define the semantics of an
imperative programming
In computer science, imperative programming is a programming paradigm of software that uses Statement (computer science), statements that change a program's state (computer science), state. In much the same way that the imperative mood in natural ...
paradigm by assigning to each ''statement'' in this language a corresponding ''predicate transformer'': a
total function between two ''
predicates'' on the state space of the statement. In this sense, predicate transformer semantics are a kind of
denotational semantics
In computer science, denotational semantics (initially known as mathematical semantics or Scott–Strachey semantics) is an approach of formalizing the meanings of programming languages by constructing mathematical objects (called ''denotations'' ...
. Actually, in
guarded commands, Dijkstra uses only one kind of predicate transformer: the well-known weakest preconditions (see below).
Moreover, predicate transformer semantics are a reformulation of
Floyd–Hoare logic. Whereas Hoare logic is presented as a
deductive system, predicate transformer semantics (either by weakest-preconditions or by strongest-postconditions see below) are complete strategies to build
valid deductions of Hoare logic. In other words, they provide an effective
algorithm
In mathematics and computer science, an algorithm () is a finite sequence of Rigour#Mathematics, mathematically rigorous instructions, typically used to solve a class of specific Computational problem, problems or to perform a computation. Algo ...
to reduce the problem of verifying a Hoare triple to the problem of proving a
first-order formula. Technically, predicate transformer semantics perform a kind of
symbolic execution
In computer science, symbolic execution (also symbolic evaluation or symbex) is a means of analyzing a program to determine what inputs cause each part of a program to execute. An interpreter follows the program, assuming symbolic values for i ...
of statements into predicates: execution runs ''backward'' in the case of weakest-preconditions, or runs ''forward'' in the case of strongest-postconditions.
Weakest preconditions
Definition
For a statement ''S'' and a
postcondition ''R'', a weakest precondition is a predicate ''Q'' such that for any
precondition ,
if and only if
. In other words, it is the "loosest" or least restrictive requirement needed to guarantee that ''R'' holds after ''S''. Uniqueness follows easily from the definition: If both ''Q'' and ''Q' '' are weakest preconditions, then by the definition
so
and
so
, and thus
. We often use
to denote the weakest precondition for statement ''S'' with respect to a postcondition ''R''.
Conventions
We use '' T '' to denote the predicate that is everywhere true and '' F '' to denote the one that is everywhere false. We shouldn't at least conceptually confuse ourselves with a Boolean expression defined by some language syntax, which might also contain true and false as Boolean scalars. For such scalars we need to do a type coercion such that we have T = predicate(true) and F = predicate(false). Such a promotion is carried out often casually, so people tend to take T as true and F as false.
Skip
Abort
Assignment
We give below two equivalent weakest-preconditions for the assignment statement. In these formulas,