Prolog if子句返回false

时间:2015-03-26 17:41:28

标签: prolog

我正在学习Prolog,我有一个小问题。 我正在研究一个“建造”塔楼的例子。

所以我定义了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,我该如何解决? 我想有一个方法可以返回a和b为0级。

2 个答案:

答案 0 :(得分:1)

考虑

?- 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).

答案 1 :(得分:1)

可以使用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 语句使用然后 -part。

在后续部分中,它会使用level/2再次查询level(b,LEV1),现在此调用会调用support(b,LEV1,_)。对于此通话,它无法解析通话,因为没有support谓词的第一个值为b。所以现在我们采取其他部分。我们统一LEV1 is 0,然后LEV1=0,然后我们返回。

在返回部分(在then部分中),level(b,0)是结果。现在我们统一LEVEL is LEV1+1LEVEL但是已经基于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).