Findall/3错误地评估为false



我正在创建一个程序,该程序应允许通过图形进行搜索,但是当呼叫findall/3评估为false时,应返回后继节点列表的函数将失败。当我在Find_successors函数之外自行尝试Findall函数时,它可以完美地工作,但是由于某种原因,Find_successors函数中的某些原因,它只是读取false。踏上图形调试器,我什至可以看到它找到了所有解决方案。这是代码:

find_successors(Start, Out) :- 
    entity(Start),
    (findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []),
    (findall(X, is_a(X, Start), O), OL2 = O; OL2 = []),
    (findall(X, has(Start, X), O), append([], O, OL3); OL3 = []),
    (findall(X, has(X, Start), O), append([], O, OL4); OL4 = []),
    (findall(X, able_to(Start, X), O), append([], O, OL5); OL5 =[]),
    (findall(X, able_to(X, Start), O), append([], O, OL6); OL6 = []),
    (findall(X, used_to(Start, X), O), append([], O, OL7); OL7 = []),
    (findall(X, used_to(X, Start), O), append([], O, OL8); OL8 = []),
    append([OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out).
entity(wings).
entity(fly).
entity(bird).
entity(legs).
entity(feathers).
entity('body covering').
entity(animal).
entity(dog).
entity(fur).
entity(aves).
entity(reptile).
entity(snake).
entity(scales).
f_is_a(bird, aves).
f_is_a(bird, animal).
f_is_a(snake, reptile).
f_is_a(snake, animal).
f_is_a(dog, mammal).
f_is_a(dog, animal).
f_is_a(feathers, 'body covering').
f_is_a(fur, 'body covering').
f_is_a(mammal, animal).
f_is_a(reptile, animal).
f_is_a(aves, animal).
is_a(X, H) :- !, f_is_a(X, H).
is_a(X, H) :- !, +f_is_a(X, P), H = X.
is_a(X, H) :- !, is_a(X, P), is_a(P, H).
f_has(bird, wings).
f_has(bird, feathers).
f_has(bird, legs).
f_has(aves, wings).
f_has(aves, feathers).
f_has(aves, legs).
f_has(dog, legs).
f_has(dog, fur).
f_has(mammal, legs).
f_has(mammal, fur).
f_has(snake, scales).
f_has(reptile, scales).
has(X, H) :- !, f_has(X, H).
has(X, H) :- !, +f_has(X, P), H = X.
has(X, H) :- !, has(X, P), has(P, H).
used_to(wings, fly).
used_to(legs, walk).
able_to(bird, fly).
able_to(bird, walk).
able_to(dog, walk).
able_to(X, Y) :- used_to(X1, Y), has(X, X1).

您一直在尝试重复使用相同的变量,但是一旦变量绑定,您就无法再次使用它。所以所有这些:

        here              here
         |                  |
         v                  v
(findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []),
(findall(X, is_a(X, Start), O), OL2 = O; OL2 = []),
(findall(X, has(Start, X), O), append([], O, OL3); OL3 = []),
(findall(X, has(X, Start), O), append([], O, OL4); OL4 = []),
(findall(X, able_to(Start, X), O), append([], O, OL5); OL5 =[]),
(findall(X, able_to(X, Start), O), append([], O, OL6); OL6 = []),
(findall(X, used_to(Start, X), O), append([], O, OL7); OL7 = []),
(findall(X, used_to(X, Start), O), append([], O, OL8); OL8 = []),

这些线中的每一个都非常非常奇怪。我需要分解它,以实际弄清楚发生了什么。仅拿其中一个:

(   findall(X, used_to(Start, X), O),
    append([], O, OL7)
;   OL7 = []
)

(顺便说一句,您应该尝试编写析取,否则很容易误读)

append([], A, B)A = B相同。

那么,即使没有解决方案,findall/3也总是成功。它只是给您一个空列表!

?- findall(X, between(2, 1, X), Xs).
Xs = [].

因此,整个事情是完全不必要的,除了 findall/3的呼吁外,您也可以扔掉所有东西。

侧面注:您正在使用的脱节并不能执行您认为所做的事情。这是一个小例子:

?- ( A = 1 ; A = 2 ).

您认为发生了什么?

您应该向我们提出呼叫find_successors(Start, Out)并说预期值。

没有它很难说出您的代码在哪里错了,但是...有些没有特定顺序...

(1) append/3 condenate将第三个参数与获得的列表统一,从第一个列表和第二个列表中串联元素;所以

append([], O, OL1)

在没有元素的第一个参数的情况下,将OOL1统一,因此是无用的;您可以在表格中写下所有行

(findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []),

AS

(findall(X, is_a(Start, X), OL1) ; OL1 = []),

(2) findall/3当将第三个参数与空列表统一(当找不到值时)时,也返回true,所以我不明白为什么要写

(findall(X, is_a(Start, X), OL1) ; OL1 = []),

当第二部分(OL1 = [])从未执行(如果我没有错)时,当OL1[]统一时,findall/3一无所获;我认为您可以简单地写

findall(X, is_a(Start, X), OL1),

(3)我只知道一个带有三个参数的append;所以我不明白

的含义
append([OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out)

您的意图是写

append([], [OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out)

在这种情况下,占用(1)和(2),您可以简单地写find_successors/2

find_successors(Start, [OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8]) :- 
    entity(Start),
    findall(X, is_a(Start, X), OL1),
    findall(X, is_a(X, Start), OL2),
    findall(X, has(Start, X), OL3),
    findall(X, has(X, Start), OL4),
    findall(X, able_to(Start, X), OL5),
    findall(X, able_to(X, Start), OL6),
    findall(X, used_to(Start, X), OL7),
    findall(X, used_to(X, Start), OL8).

(4)我不喜欢剪切(!),所以也许我错了,但是...为什么将!作为is_a/2中的第一个元素?

is_a(X, H) :- !, f_is_a(X, H).
is_a(X, H) :- !, +f_is_a(X, P), H = X.
is_a(X, H) :- !, is_a(X, P), is_a(P, H).

如果我没有错,则第一个子句中的剪辑( !, f_is_a(X, H))禁用第二子句和第三子句,因此,如果f_is_a(X, H)失败,则永远不会验证第二子句和第三子句。

您确定您的意图不是

is_a(X, H) :- f_is_a(X, H), !.
is_a(X, H) :- +f_is_a(X, P), H = X, !.
is_a(X, H) :- is_a(X, P), is_a(P, H), !.

或更好的

is_a(X, H) :- f_is_a(X, H), !.
is_a(X, X) :- +f_is_a(X, _), !.
is_a(X, H) :- is_a(X, P), is_a(P, H), !.

根本不剪裁?

(5)has/3的相同切割问题;我怀疑

has(X, H) :- !, f_has(X, H).
has(X, H) :- !, +f_has(X, P), H = X.
has(X, H) :- !, has(X, P), has(P, H).

是错误的,您的意图是

has(X, H) :- f_has(X, H), !.
has(X, H) :- +f_has(X, P), H = X, !.
has(X, H) :- has(X, P), has(P, H), !.

或更好的

has(X, H) :- f_has(X, H), !.
has(X, X) :- +f_has(X, _), !.
has(X, H) :- has(X, P), has(P, H), !.

或根本不切断?

相关内容

  • 没有找到相关文章

最新更新