Aspen SCM‎ > ‎Expert System‎ > ‎2. Flow of Control‎ > ‎

2.b IN and WHILE Loops and BREAK


Aspen SCM Expert System supports looping by means of the IN and WHILE statements. The behaviour of IN and WHILE loops is similar, the difference being that IN loops are over an existing set whereas WHILE loops are over a numeric counter which is subject to an absolute upper limit, CNTLE(LOOP,1).

A BREAK statement breaks a loop over the specified loop variable. If a BREAK statement is executed and the specified variable is not then a loop variable (e.g. because the loop has been completed), the interpreter stops and reports an error.

The execution of WHILE loops is usually terminated by a BREAK statement; they can also be used to terminate IN loops once some condition has been satisfied.

Overloading of IN

IN is overloaded and is a test if the variable is bound when the statement is interpreted.

A slightly better version of our rule for demonstrating Goldbach’s conjecture is as follows:

IF      ?X = 3 OR ?X = 5 OR ?X = 7 OR ?X = 11 OR ?X = 13
AND     ?Y = ?Z - ?X
AND     ?Y EQ 3 OR ?Y EQ 5 OR ?Y EQ 7 OR ?Y EQ 11 OR ?Y EQ 13

When the statement SUM_OF ?X ?Y 12 is asserted, the interpreter starts by setting ?X = 3. It then calculates ?Y = 12 – 3 = 9. It then tests ?Y EQ 3; this fails so it tests ?Y EQ 5, and so on until it has failed at each of the possible tests for ?Y. At this point it backtracks, sets ?X = 5 and then sets out again, calculating ?Y = 7 and testing it against acceptable values. This time it succeeds at the test ?Y EQ 7. This enables it to prove the predicate and so the rule resolves TRUE with the predicate SUM_OF 5 7 12.

We can replace the statements assigning values to ?X and testing values of ?Y with IN statements:

AND     ?Y = ?Z - ?X

where ODDPRIME is the set {3, 5, 7, 11, 13}.

Here ?X IN ODDPRIME is a loop because ?X is free but ?Y IN ODDPRIME is a test because ?Y is instantiated when the statement is executed.

How Loops Behave

One key feature of Aspen SCM Expert System loops is that there is no END statement for the loop. Instead the THEN statement is, in effect, the end of the loop. We shall refer to the statement which contains the IN or the WHILE statement as the loop statement and the variable over which the loop is executed as the loop variable. For an IN loop, the loop variable loops over the loop set.

When a loop statement is executed, the loop variable is given its first value. The code then executes as it would have done if the loop statement had been a simple assignment until the interpreter has got as far as it can, either forwards to the THEN clause or forwards until it has found all branches below the loop statement FALSE and then backtracked to the loop statement. In either case it then sets the loop variable to the next value, frees all local variables which were written to in the tree below the loop statement and tries again.

In our Goldbach example if we are trying to prove SUM_OF ?X ?Y 12 the interpreter starts by setting ?X to 3. It calculates ?Y = 12 – 3 = 9 and then tests whether 9 is a member of the set ODDPRIME. It is not. The rule therefore backtracks and sets ?X to the next element of the set, 5. It calculates ?Y = 7 for which the test ?Y IN ODDPRIME succeeds. It then proceeds to prove the predicate SUM_OF 5 7 12.

In the previous Goldbach example, the interpreter then stopped. This time it continues. It sets ?X to 7, calculates ?Y = 5 and proves the predicate as SUM_OF 7 5 12. It then sets ?X to 11, calculates ?Y as 1 and fails the test ?Y IN ODDPRIME. Finally it sets ?X to 13, calculates ?Y = -1 and again fails the test ?Y IN ODDPRIME. Although the loop ended FALSE, it had proved the predicate at least once. The last successful resolution of the predicate was SUM_OF 7 5 12 so this is what is passed back to the calling rule, together with the predicate status TRUE.

Of course, if a loop is being used in procedural code, it simply executes each time down to the predicate and then jumps back to the start of the loop, sets the loop variable to the next value and continues.

Failing to Prove the Predicate and UNKNOWN

If the loop set for an IN loop is empty, the loop terminates immediately and the loop statement resolves as UNKNOWN.

WHILE loops generally end at a user-written BREAK clause, e.g.

IF      WHILE ?I

If this BREAK clause is triggered before the predicate has been proved, the WHILE loop (and hence the rule) resolves as UNKNOWN. If there is a loop outside the WHILE loop, the interpreter jumps to the next outer loop, increments its loop counter and continues from there.

If a WHILE loop iterates to the absolute maximum loop count specified in CNTLE(LOOP,1) the interpreter actually ends the loop using an implicit BREAK statement. The rule ends UNKNOWN if the predicate was never proved.

Thus a rule with a loop can end UNKNOWN if the predicate is never proved and:

  • it has been stopped by a BREAK; or

  • it has an IN loop over a null set.

Rules with loops can end FALSE if the predicate is never proved and:

  • the outer loop is an IN loop without a BREAK statement.

(If the outer loop is an IN loop which has a BREAK statement, the BREAK will be executed on a backtrack if it is not executed going forwards).

If the outermost loop in a rule is ended by a BREAK, processing stops immediately, even if the predicate has not been proved and even if there is an OR in the Code ready to be tried as an alternative path. Thus OR blocks are only useable where a rule either does not loop or where the outer loop is an IN loop without a BREAK.

Consequences of a Rule Ending UNKNOWN

The parameter CNTLE(EOU,1) determines whether a statement which resolves UNKNOWN is regarded as an error or not. With versions before Aspen SCM 2004.1 a rule which ended UNKNOWN because the predicate had not been proved was treated as ending FALSE regardless of the setting of CNTLE(EOU,1). The interpreter regarded as an error an UNKNOWN which occurred because a statement was not valid syntax and could not be matched against any potential predicate.

This meant that setting CNTLE(EOU,1) = YES trapped coding errors but allowed loops to be broken before a predicate had been proved provided the calling rule could handle this. Calling rules typically contained statements such as


With versions from Aspen SCM 2004.1 onwards, whatever the reason that a rule ends UNKNOWN, an error is triggered if CNTLE(EOU,1) = YES. This means that if an application contains code written for versions before Aspen SCM 2004.1, it has to be run with CNTLE(EOU,1) = NO. This allows the code to execute as it did before, but means that mistakes are not detected automatically where an invalid predicate is asserted. See section 2.d for further discussion of this.


A loop statement acts like an AND if the interpreter reaches the THEN clause and an OR if it does not. However, unlike an ordinary AND, the THEN clause does not need to be proved for each value of the loop variable in order for the rule to end TRUE: it suffices for it to be proved once. We could say that a loop is a procedural AND (i.e. the code must be executed for each value of the loop variable) but a logical OR (i.e. it suffices to prove the predicate for one value of the loop variable).

Back                                Next