Prolog:检查简单事实的传递性

Prolog: check transitivity for simple facts

我的目的是在 Prolog 中实现传递性的一个简单示例(仅供我自己使用)。

这些是我的事实:

trust_direct(p1, p2).
trust_direct(p1, p3).
trust_direct(p2, p4).
trust_direct(p2, p5).
trust_direct(p5, p6).
trust_direct(p6, p7).
trust_direct(p7, p8).
trust_direct(p100, p200).

我写这个谓词是为了检查 A 是否信任 C,只要有 B 信任 CA 相信这个 B:

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

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

谓词 returns true 例如 trusts(p1, p2)trusts(p1, p5),但是 trusts(p5, p6) 已经 returns ERROR: Out of local stack

Prolog 如此快速地填充堆栈吗?

或者我的 idea/implementation of trusts 坏/浪费系统内存?

是的,Prolog 正在这么快地淹没本地堆栈。

要看到这一点,考虑以下程序片段就足够了:

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

这叫做 :我插入了 false/0,因此 false/0 之后的所有内容都可以忽略 。我用 删除线 文本表示可以忽略的部分。

这意味着代码片段实际上等同于:

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

现在,使用上述任何一个片段,我们立即得到:

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

要解决这个问题,您必须更改剩余的片段。因此,这样的片段作为问题的解释

例如,考虑以下版本:

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

示例查询:

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

这现在可以正常工作了。它在声明上等同于您发布的版本,并且具有更好的终止属性:

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

这表明程序现在普遍终止

替代解决方案是:

  • 使用您的 Prolog 系统的 制表 设施
  • 使用transitive closure
  • 的定义
  • 等等