Prolog: check transitivity for simple facts

天大地大妈咪最大 提交于 2019-12-07 15:08:30
mat

Yes, Prolog is flooding the local stack this quickly.

To see this, it suffices to only consider the following program fragment:

trusts(A, C) :-
        trusts(A, B),
        false,
        trusts(B, C).

This is called a : I have inserted false/0, so that everything after false/0 can be ignored. I indicate parts that can be ignored with strikeout text.

This means that the snippet is actually equivalent to:

trusts(A, C) :-
        trusts(A, B),
        false.

Now, with either of the above snippets, we immediately get:

?- trusts(p5, p6).
ERROR: Out of local stack

To get rid of this problem, you have to change the remaining fragment. For this reason, such a fragment serves as an explanation of the problem.

For example, consider the following version:

trusts(A, B) :-
        trust_direct(A, B).
trusts(A, C) :-
        trust_direct(A, B),
        trusts(B, C).

Sample query:

?- trusts(p5, p6).
true ;
false.

This now works as expected. It is declaratively equivalent to the version you posted, and has much better termination properties:

?- trusts(X, Y), false.
false.

This shows that the program now terminates universally.

Alternative solutions are:

  • use your Prolog system's tabling facilities
  • use the definition of transitive closure
  • etc.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!