Distributed backtracking
\label{des/ext/back}
Distributed backtracking
is an important issue for systems that wish
to support {\it don't know} non-determinism, in contrast
to {\it don't care}
nondeterminism where, once a choice is made,
all alternatives are thrown away.
The examples presented previously were deterministic
in the sense that only one solution needed to be produced.
The object presented in the following example, however, may
produce an infinite number of solutions.
\lprog{nat}{
.ds nat.pl
}
Its use is illustrated by
.ds nat.g
which will print all natural numbers, eventually.
Backtracking is done lazily, in that on backtracking
the object evaluating number will start to produce the next solution.
\n Note that the goal
:- nat!number(X), X = s(s(0)).
differs from the goal
:- nat!number(s(s(0))).
in that the latter only communicates success, whereas the former
has to communicate three bindings for X.
Backtracking in the presence of non-logical variables
\paragraphindex{backtracking}
\dlpindex{backtracking}
In the presence of non-logical variables mutual exclusion is
needed for reasons of protection.
Mutual exclusion takes effect for active objects only.
This protection, however, lasts until the first answer
is requested and received.
This procedure is motivated by the assumption that any important
change of the state of the object can be achieved during the period that
the first solution is produced.
Backtracking over the second and remaining solutions can be done
while other processes are active.
We will show how the state of an object can be fixed by binding it
to a non-logical variable.
Consider another variant of our, by now familiar, travel agency.
\lprog{travel}{
.ds travel4.pl
}
In the clause for reachable we have made explicit the binding of
the second argument of member to the value
of the city list.
Since an instance of travel is now an active object
the mutual exclusion mechanism prevents the city list
from being changed while the first answer for reachable is being produced.
After that, member may backtrack, but with the value of the city list
bound to L, as it was at the time of the call.
Now suppose that we declare travel in the following, somewhat contrived, manner.
\lprog{travel}{
.ds travel5.pl
}
The reader may check that in this case the city list may be updated,
by adding elements to the front, while the process
evaluating reachable is backtracking over the
possible solutions.
In general such interference is not desirable
but, as has been shown,
this can easily be avoided by binding the state of an object
to a logical variable.
Deterministic objects
In many cases we do not need the full power of backtracking over the
results in a rendez-vous.
For instance, asking the value of a counter
results in precisely one answer.
Such deterministic behavior is obvious when the call contains no
unbound logical variables, since the answer will then be either
failure or success.
To cope with the cases in which this cannot so easily be decided
we have provided a way
of declaring an object to be deterministic.
Our counter is clearly a deterministic object.
\dlpindex{deterministic}
\lprog{ctr}{
.ds ctr3.pl
}
The prefix deterministic enforces that only one
solution will be returned for each method call.