Floyd-Hoare triples

Extended execution relation

Towards a formal definition of Floyd-Hoare triples, we first extend the execution relation to perform exactly (as opposed to exactly one) execution steps:

  • , and
  • if and .

We write if there exists some such that . Furthermore, we write if there exists no configuration such that .

Formal Definition

A Floyd-Hoare triple consists of a precondition in Pred, a program statement , and a postcondition in Pred.

Intuitively, a triple is valid if every execution of program that starts in a state satisfying the precondition will not cause a runtime error (for example, by failing an assertion) and will eventually terminate in a state satisfying the postcondition .

Towards a formal definition, recall from the definition of our language that denotes the variables for which the state is defined. Moreover, let denote all free variables that appear in predicate . Then means that state assigns values at least to all variables in predicate .

The Floyd-Hoare triple is valid (for total correctness) if and only if for every state with , if , then

  1. (safety) there exists no such that ;
  2. (termination) there exists such that for every , ; and
  3. (partial correctness) if and , then .

Here, the first condition (safety) ensures that we cannot encounter a runtime error (for example an assertion failure) when starting execution in a state that satisfies the precondition. The second condition ensures termination, that is, we cannot perform execution steps ad infinitum. The third condition makes sure that we satisfy the postcondition whenever we manage to terminate without a runtime error.

We say that a triple is valid for partial correctness, whenever the third (but not necessarily the first or second) property holds.

In principle, we can directly apply the above definition of validity together with our operational semantics to check whether a triple is valid. However, in most cases this is not feasible, since we would have to consider all possible program executions.

Instead, we use verification conditions to reason about the validity of a triple in a symbolic way, that is by reasoning about predicates, without invoking the operational program semantics. In the lecture, we considered two such approaches for constructing verification conditions: weakest preconditions and strongest postconditions.