Prolog if 子句 returns false

Prolog if clause returns false

我正在学习Prolog,我有一个小问题。 我正在研究一个 "builds" 塔的例子。

所以我定义了3个块a,b和c。 第三块 c 位于 a 和 b 之上 -> 所以它被 a 和 b 支撑。

block(a).
block(b).
block(c).

%supported(BLOCK, BY1, BY2)
supported(c,a,b).


level(BLOCK, LEVEL) :-
      supported(BLOCK, X, _)
   -> (level(X, LEV1), LEVEL is LEV1 + 1)
   ;  LEVEL is 0.

我还有一个计算方块等级的函数。我遇到的问题如下:

?- level(X, 0).
false.

?- level(X, 1).
X = c.

为什么它对级别 0 返回 false,我该如何解决? 我想要一个方法 returns 我 a 和 b 级别 0.

考虑一下

?- level(a,0).
true.

很明显,当 BLOCK 空闲时,supported(BLOCK, X, _) 成功,将规则强加在意外的连词 level(X, LEV1), LEVEL is LEV1 + 1 上,这确实失败了。

要更正此行为,请绑定 BLOCK:

level(BLOCK, LEVEL) :-
  block(BLOCK),
  (supported(BLOCK, X, _) -> level(X, LEV1), LEVEL is LEV1 + 1 ; LEVEL is 0).

可以使用 trace.(添加缩进)进行调试:

[trace]  ?- level(X, 0).
   Call: (6) level(_G2697, 0) ? creep
     Call: (7) supported(_G2697, _G2771, _G2772) ? creep
     Exit: (7) supported(c, a, b) ? creep
     Call: (7) level(a, _G2771) ? creep
       Call: (8) supported(a, _G2771, _G2772) ? creep
       Fail: (8) supported(a, _G2771, _G2772) ? creep
     Redo: (7) level(a, _G2771) ? creep
       Call: (8) _G2770 is 0 ? creep
       Exit: (8) 0 is 0 ? creep
     Exit: (7) level(a, 0) ? creep
     Call: (7) 0 is 0+1 ? creep
     Fail: (7) 0 is 0+1 ? creep
   Fail: (6) level(_G2697, 0) ? creep
   false.

所以发生了什么事?

首先调用level(X,0). 这个谓词调用支持supported(BLOCK,X,_). 有一个统一的答案:BLOCK=aX=b_=c。所以这意味着 if-then-else 语句使用 then-part.

在 then 部分,它再次使用 level(b,LEV1) 查询 level/2,现在这个调用导致调用 support(b,LEV1,_)。对于这个调用,它无法解析调用,因为没有第一个值为 bsupport 谓词。所以现在我们来看 else 部分。我们统一 LEV1 is 0,因此 LEV1=0 和我们 return.

在return部分(在then-部分),level(b,0)是结果。现在我们统一 LEVEL is LEV1+1,但是 LEVEL 已经被定义为 00+11。因此它在顶层失败。

分辨率大概是把supported做的更细一些,定义为:support/2.

程序如下:

block(a).
block(b).
block(c).

%supported(BLOCK, BY1, BY2)
supported(c,b).
supported(c,a).
supported(b,a).

现在 level 谓词为:

level(B,L) :-
    supported(B,C),
    level(C,LC),
    L is LC+1.
level(_,0).