我正在学习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级。
答案 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=a
,X=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+1
,LEVEL
但是已经基于0
而0+1
是1
。因此它在顶层失败。
决议可能会使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).