问题
From Bratko's book, Prolog Programming for Artificial Intelligence (4th Edition) We have the following code which doesn't work -
anc4(X,Z):-
anc4(X,Y),
parent(Y,Z).
anc4(X,Z):-
parent(X,Z).
In the book, on page 55, figure 2.15, is shown that parent(Y,Z)
is kept calling until stack is out of memory.
What I don't understand is that prolog does a recursiv call to anc4(X,Y), and not to parent (Y,Z) first. Why doesn't prolog goes over and over to the first line, anc4(X,Y)
, and rather goes to the second line?
Can you please elaborate why is the line parent(Y,Z)
is kept being called?
Thank you.
回答1:
The origin of your 'problem' (i.e. goals order) is deeply rooted in the basic of the language.
Prolog is based on the simple and efficient strategy of chronological backtracking, to implement SLD resolution, and left recursive clauses, like anc4/2
, cause an infinite recursion.
Indeed, the comma operator (,)/2
stands for
evaluate the right expression only if the left expression holds
So, order of goals in a clause is actually an essential part of the program.
For your concrete case,
... , parent(Y,Z).
cannot be called if
anc4(X,Y),
doesn't hold.
The counterpart to goals order is clauses order.
That is, the whole program has a different semantics after the clauses are exchanged:
anc4(X,Z):-
parent(X,Z).
anc4(X,Z):-
anc4(X,Y),
parent(Y,Z).
To better understand the problem, I think it's worth to try this definition as well.
回答2:
Prolog cannot handle left recursion by default without a tabling mechanism. Only some Prolog systems support tabling and usually you need to explicitly declare which predicates are tabled.
If you're using e.g. XSB, YAP, or SWI-Prolog, try adding the following directive on top of your source file containing the definition for the anc4/2
predicate:
:- table(anc4/2).
and retry your queries. The tabling mechanism detects when a query is calling a variant (*) of itself and suspends execution of that branch until a query answer is found and tries an alternative branch (provided in your case by the second clause). If that happens, execution is resumed with that answer.
(*) Variant here means that two terms are equal upon variable renaming.
来源:https://stackoverflow.com/questions/52219327/cant-understand-why-is-prolog-looping-infinitly