Detecting some loops in Prolog goals that do not terminate universally

182 views Asked by At

TL;DR: This question is about one particular aspect of evaluating candidate failure-slices.

The following code of ancestor_of/2 expresses the of child_of/2:

ancestor_of(X, Y) :-
   child_of(Y, X).
ancestor_of(X, Z) :-
   child_of(Z, Y),
   ancestor_of(X, Y).

If we define child_of/2 and include several cycles ...

child_of(xx, xy).
child_of(xy, xx).
child_of(x, x).

... ancestor_of(X, Y) does not terminate universally:

?- ancestor_of(X, Y), false.
**LOOPS**

With SWI-Prolog, we can limit the amount of work invested in the execution of the query:

?- time(call_with_inference_limit((ancestor_of(_,_),false), 10000, R)).
% 10,008 inferences, 0.002 CPU in 0.002 seconds (100% CPU, 4579243 Lips)
R = inference_limit_exceeded ;
% 5 inferences, 0.000 CPU in 0.000 seconds (85% CPU, 235172 Lips)
false.

Alright, but it could be better!

  • First, we might be able to prove definitely that the goal loops.
  • Second, we might be able to do so with less effort.

Let's add an additional argument to ancestor_of/2 for transferring call stack information!

ancestor_of_open(X, Y, Open) :-
   G = ancestor_of(X,Y),
   (  member(G, Open)
   -> throw(loop(G,Open))
   ;  ancestor_of_aux(X, Y, [G|Open])
   ).

ancestor_of_aux(X, Y, _Open) :-
   child_of(Y, X).
ancestor_of_aux(X, Z, Open) :-
   child_of(Z, Y),
   ancestor_of_open(X, Y, Open).

Sample query:

?- time(ancestor_of_open(X,Y,[])).
% 4 inferences, 0.000 CPU in 0.000 seconds (92% CPU, 219696 Lips)
X = xy,
Y = xx ;
% 1 inferences, 0.000 CPU in 0.000 seconds (79% CPU, 61839 Lips)
X = xx,
Y = xy ;
% 1 inferences, 0.000 CPU in 0.000 seconds (79% CPU, 61084 Lips)
X = Y, Y = x ;
% 8 inferences, 0.000 CPU in 0.000 seconds (87% CPU, 317473 Lips)
X = Y, Y = xx ;
% 11 inferences, 0.000 CPU in 0.000 seconds (90% CPU, 262530 Lips)
ERROR: Unhandled exception: loop(ancestor_of(_G282,xx),[ancestor_of(_G282,xy),ancestor_of(_G282,xx)])

Is this it?! That was too easy. Does this cover the general case?

I feel like I'm missing something important, but I can't quite point my finger at it. Please help!

0

There are 0 answers