They define the semantics of an imperative programming 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. 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.
|Published (Last):||19 July 2017|
|PDF File Size:||7.34 Mb|
|ePub File Size:||18.71 Mb|
|Price:||Free* [*Free Regsitration Required]|
So-called "guarded commands" are introduced as a building block for alternative and repetitive constructs that allow non-deterministic program components for which at least the activity evoked, but possibly even the final state, is not necessarily uniquely determined by the initial state.
For the formal derivation of programs expressed in terms of these constructs, a calculus will be shown. CR-category: 4. Guarded commands, non-determinacy and a calculus for the derivation of programs.
In section 2, two statements, an alternative construct and a repetitive construct will be introduced, together with an intuitive mechanistic definition of their semantics. The basic building block for both of them is the so-called "guarded command", a statement list prefixed by a boolean expression: only when this boolean expression is initially true, is the statement list eligible for execution.
The potential non-determinacy allows us to map otherwise trivially different programs on the same program text, a circumstance that seems largely responsible for the fact that now programs can be derived in a more systematic manner than before.
In section 3, after a prelude defining the notation, a formal definition of the semantics of the two constructs will be given, together with two theorems for each of the constructs without proof. In section 4, it will be shown how upon the above a formal calculus for the derivation of programs can be founded. We would like to stress that we do not present "an algorithm" for the derivation of programs: we have used the term "a calculus" for a formal discipline --a set of rules-- such that, if applied successfully 1 it will have derived a correct program 2 it will tell us that we have reached such a goal.
In choosing the term "calculus" we have been inspired by the "integral calculus" and the "propositional calculus" where we have a very similar situation. Two statements made from guarded commands. If the reader accepts "other statements" as indicating, say, assignment statements and procedure calls. The semicolons in the guarded list have the usual meaning: when the guarded list is selected for execution its statements will be executed successively in the order from left to right; a guarded list will only be selected for execution in a state such that its guard is true.
Note that a guarded command by itself is not a statement: it is component of a guarded command set from which statements can be constructed. Our syntax gives two ways for constructing a statement out of a guarded command set.
The alternative construct is written by enclosing it by the special bracket pair: "if If in the initial state none of the guards is true, the program will abort, otherwise an arbitrary guarded list with a true guard will be selected for execution.
If the empty guarded command set were allowed "if fi" would be semantically equivalent to "abort". End of note. Here a state in which none of the guards is true will not lead to abortion but to proper termination; the complementary rule, however, is that it will only terminate in a state in which none of the guards is true: when initially or upon completed execution of a selected guarded list one or more guards are true, a new selection for execution of a guarded list with a true guard will take place.
When the repetitive construct has terminated properly, we know that all its guards are false. If the empty guarded command set were allowed "do od" would be semantically equivalent to "skip".
To conclude this section we give a program where not only the computation but also the final state is not necessarily uniquely determined. Eventually k should be the place of a maximum. Formal definition of the semantics.
Notational prelude. In the following sections we shall use the symbols P , Q and R to denote predicates defining boolean functions defined on all points of the state space; alternatively we shall refer to them as "conditions", satisfied by all states for which the boolean function is true. Two special predicates that we denote by the reserved names "T" and "F" play a special role: T denotes the condition that, by definition, is satisfied by all states, F denotes, by definition, the condition that is satisfied by no state at all.
The way in which we use predicates as a tool for defining sets of initial or final states for the definition of the semantics of programming language constructs has been directly inspired by Hoare , the main difference being that we have tightened things up a bit: while Hoare introduces sufficient pre-conditions such that the mechanisms will not produce the wrong result but may fail to terminate.
More specifically: we shall use the notation "wp S, R " , where S denotes a statement list and R some condition on the state of the system, to denote the weakest pre-condition for the initial state of the system such that activation of S is guaranteed to lead to a properly terminating activity leaving the system in a final state satisfying the post-condition R. Together with the rules of propositional calculus and the semantic definitions to be given below, the above four properties take over the role of the "rules of inference" as introduced by Hoare .
We take the position that we know the semantics of a mechanism S sufficiently well if we know its predicate transformer, i. This position is taken in full acknowledgement of the fact that in the case of non-deterministic mechanisms, the knowledge of the predicate transformer does not give a complete description: for those initial states that do not necessarily lead to a properly terminating activity, the knowledge of the predicate transformer does not give us any information about the final states in which the system might find itself after proper termination.
Example 1. Example 2. Example 3. The alternative construct. In order to define the semantics of the alternative construct we define two abbreviations. The first term "BB" requires that the alternative construct as such will not lead to abortion on account of all guards false, the second term requires that each guarded list eligible for execution will lead to an acceptable final state.
Let "t" denote some integer function, defined on the state space, end let "wdec S, t " denote the weakest pre-condition such that activation of S is guaranteed to lead to a properly terminating activity leaving the system in a final state such that the value of t is decreased by at least 1 compared to its initial value.
In terms of "wdec" we can formulate the very similar Theorem 2. Note which can be skipped at first reading. The relation between "wp" and "wdec" is as follows. Let its smallest solution for t0 be tmin X. Here we have added the explicit dependence on the state X. Then tmin X can be interpreted as the lowest upper bound for the final value of t if the mechanism S is activated with X as initial state. Intuitively, Hk R can be interpreted as the weakest pre-condition guaranteeing proper termination after at most k selections of a guarded list, leaving the system in a final state satisfying R.
Via mathematical induction we can prove Theorem 3. Note that the antecedent of Theorem 3 is of the form of the consequents of Theorems 1 and 2. Because T is the condition by definition satisfied by all states, wp S, T is the weakest pre-condition guaranteeing proper termination for S. This allows us to formulate an alternative theorem about the repetitive construct, viz. Theorem 4. In connection with the above theorems "P" is called "the invariant relation" and "t" is called "the variant function".
Formal derivation of programs. In the mean time we have proved that the maximum of two values is always defined, viz. As an example of the deriviation of a repetitive construct we shall derive a program for the greatest common divisor of two positive numbers, i. The formal machinery only gets in motion, once we have chosen our invariant relation and our variant function.
The program then gets the structure establish the relation P to be kept invariant"; do "decrease t as long as possible under invariance of P" od. In other words we are invited to massage the value pair x, y in such a fashion that their gcd is not changed. Besides that we must require guaranteed decrease of the variant function t.
In both cases the final game has been to find a large enough set of such guarded lists that BB, the disjunction of their guards, was sufficiently weak: in the case of the alternative construct the purpose is avoiding abortion, in the case of the repetitive construct the goal is getting BB weak enough such that P and not BB is strong enough to imply the desired post-condition R.
Concluding remarks. It was only after this observation that we saw that the formal techniques we had already developed for the derivation of the synchronizing conditions that ensure the harmonious co-operation of cyclic sequential processes, such as can be identified in the total activity of operating systems, could be transferred lock, stock and barrel to the development of sequential programs as shown in this article.
While the design of an alternative construct now seems to be a reasonably straightforward activity, that of a repetitive construct requires what I regard as "the invention" of an invariant relation and a variant function. For me, the main value of the calculus shown in section 4 is that it has strengthened my skepticism about some of the claims or goals of "automatic programming"; me presenting this calculus should not be interpreted as me suggesting that all programs should be developed that way: it just gives us another handle.
The calculus does, however, explain my preference for the axiomatic definition of programming language semantics via predicate transformers above other definition techniques: the definition via predicate transformers seems to lend itself most readily to being forged into a tool for the goal-directed activity of program composition.
Finally I would like to say a word or two about the role of the potential non-determinacy. I quote in this connection C. Hoare: "A system which permits user programs to become non-deterministic presents dreadful problems to the maintenance engineer: it is not a "facility" to be lightly granted. I myself had to overcome a considerable mental resistance before I found myself willing to consider non-deterministic programs seriously.
It is, however, fair to say that I could not have discovered the calculus shown before having taken that hurdle and I leave it to the environment whether the non-determinacy is eventually resolved by human intervention or mechanically, in a reproducible manner or not. It is only in an environment in which all programs should be deterministic, where non-reproducible behaviour is interpreted as machine malfunctioning: I can easily think of an environment in which non-reproducible user program behaviour is quite naturally and almost always correctly taken as an indication that the user in question has written a non-deterministic program!
In connection with this effort its members R. Burstall, C. Hoare, J. Horning, J. Reynolds, D. Ross, G. Wirth and M. Woodger deserve my special thanks. Besides them, W. Feijen, D. Knuth, M. Rem and C. Scholten have been directly helpful in one way or another. ACM 12 Oct. Peter, Ed. ACM 3 May - 26th June
Predicate transformer semantics
Each named step is passed two blocks: an ensure block that defines a test for a necessary and sufficient condition of the step, and a using block that will cause that condition to obtain. If the using block is ommitted, the step acts as a simple assertion. If step is called in void context i. If do is given arguments, they will be passed to the ensure block and if necessary the using block. Defines a new guarded command step. If called in void context, the step is executed immediately. If called in scalar or array context i.
Guarded commands, non-determinacy and a calculus for the derivation of programs
Only permissible final states are possible and each permissible final state is possible. Formal definition of the semantics. Notational prelude. The way in which we use predicates as a tool for defining sets of initial or final states for the definition of the semantics of programming language constructs has been directly inspired by Hoare , the main difference being that we have tightened things up a bit: while Hoare introduces sufficient pre-conditions such that the mechanisms will not produce the wrong result but may fail to terminate , we shall introduce necessary and sufficient —i. We take the position that we know the semantics of a mechanism S sufficiently well if we know its predicate transformer, i. We consider the semantics of S only defined for those initial states for which has been established a priori that they satisfy wp S, T , i.