我正在创建一个程序,该程序应允许通过图形进行搜索,但是当呼叫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)
在没有元素的第一个参数的情况下,将O
与OL1
统一,因此是无用的;您可以在表格中写下所有行
(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), !.
或根本不切断?