Prolog 中的块堆栈

Stack of blocks in Prolog

我想在 Prolog 中做一些非常简单的事情,但由于某种原因它不起作用,我也不知道为什么。我正在使用 SWI。

我有一堆积木,标记为 a 到 f,它们都堆叠在一起,a 在底部,f 一直在顶部。像这样:

on(b, a).
on(c, b).
on(d, c).
on(e, d).
on(f, e).
above(X, Y) :- on(X, Y).
above(X, Y) :- on(X, Z), above(Z, Y).

所以一个方块在另一个方块之上,如果它下面有某个方块在那个方块之上。对我来说很有意义。

所以现在我想定义一个谓词,告诉我某个块下面是否恰好有 3 个块。在我的示例中,这将是块 d。所以我开始:

exactlyThree(X) :- above(X, Y), above(Y, Z), above (Z, W), \+ above(W, _).

如果 X 在方块 Y 上方,如果 Y 在方块 Z 上方,如果 Z 在方块 W 上方且方块 W 不在任何方块上方,那么 X 在其下方有 exacty 个方块。 但那是行不通的。

所以我尝试了这个,实际上是一样的:

bottomBlock(X) :- \+ above(X, _).
exactlyThree(X) :- above(X, Y), above(Y, Z), above (Z, W), bottomBlock(W).

那也没用。作为测试,它尝试了:

?-bottomBlock(a).
true.

有道理,但后来我尝试了:

?-bottomBlock(X).
false.

这是怎么回事?为什么序言不说 X=a?为什么我的谓词没有做它们应该做的事?

从底部开始(呵呵):

?-bottomBlock(X).
false.

Why doesn't prolog say X=a?

因为它不会发明东西来匹配变量。您需要断言某事,而不仅仅是否定。

bottomBlock(X) :- on(_, X), \+ above(X, _).
exactlyThree(X) :- above(X, Y), above(Y, Z), above (Z, W), \+ above(W, _).

这应该匹配 3 个或更多块:如果 X 在 Y 之上,则可能在 10 个块以上。您需要使用 on 以保证它恰好在 3 个街区外。