25.11.2014 Views

Algorithms and Data Structures

Algorithms and Data Structures

Algorithms and Data Structures

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

N.Wirth. <strong>Algorithms</strong> <strong>and</strong> <strong>Data</strong> <strong>Structures</strong>. Oberon version 210<br />

Appendix C. The Dijkstra loop<br />

E.W. Dijkstra [C.1] (see also [C.2]) introduced <strong>and</strong> justified a multibranch generalization of the<br />

conventional WHILE loop in his theory of systematic derivation of imperative programs. This loop proves<br />

convenient for expression <strong>and</strong> — most importantly — for verification of the algorithms which are usually<br />

expressed in terms of embedded loops, thus significantly reducing the effort of debugging.<br />

In the language Oberon-07 presented in [C.3], the syntax of this loop is defined as follows:<br />

WhileStatement<br />

= WHILE logical expression DO<br />

operator sequence<br />

{ELSIF logical expression DO<br />

operator sequence}<br />

END.<br />

If any of the logical expressions (guards) is evaluated to TRUE then the corresponding operator sequence is<br />

executed. The evaluation of the guards <strong>and</strong> the execution of the corresponding operator sequences is<br />

repeated until all guards evaluate to FALSE. So, the postcondition for this loop is the conjunction of<br />

negations of all guards.<br />

Example:<br />

WHILE m > n DO m := m - n<br />

ELSIF n > m DO n := n - m<br />

END<br />

Postcondition: ~(m > n) & ~(n > m), which is equivalent to n = m.<br />

The loop invariant must hold at the beginning <strong>and</strong> at the end of each branch.<br />

Roughly speaking, an n-branch Dijkstra loop corresponds to constructions with n usual loops that are<br />

somehow embedded one into another.<br />

The advantage of the Dijkstra loop is due to the fact that all the logic of an arbitrarily complex loop is<br />

expressed at the same level <strong>and</strong> is radically clarified, so that algorithms with various cases of embedded<br />

interacting ("braided") loops receive a completely uniform treatement.<br />

An efficient way to construct such a loop consists in enumerating all possible situations that can emerge,<br />

describing them by the corresponding guards, <strong>and</strong> for each guard — independently of the others —<br />

constructing operations that advance the algorithm towards its goal, togethers with the operations that<br />

restore the invariant. The enumeration of the guards is stopped when the disjunction (OR) of all guards<br />

covers the assumed precondition of the loop. It is useful to remember that the task of construction of a<br />

correct loop is simplified if one postpones worrying about the order of evaluation of the guards <strong>and</strong><br />

execution of the branches, optimizations of evaluation of the guards etc., until the loop is correctly<br />

constructed. Such lower-level optimizations are rarely significant, <strong>and</strong> their implementation is greatly<br />

simplified when the correctness of a complicated loop has already been ensured.<br />

Although in Dijkstra's theory the order of guard evaluations is undefined, in this book the guards are<br />

assumed to be evaluated (<strong>and</strong> branches selected for execution) in their textual order.<br />

In most programming languages the Dijkstra loop has to be modelled. In the older versions of Oberon<br />

(including Component Pascal) it is sufficient to use the LOOP construct, with the body consisting of a<br />

multibranch IF operator that contains the single loop EXIT operator in the ELSE branch:

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!