Can't understand why is prolog looping infinitly

只谈情不闲聊 提交于 2019-12-23 18:53:28

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!