findall/3错误地评估为false
我正在创建一个应该允许通过图进行搜索的程序,但是当findall/3的调用评估为false时,应该返回后继节点列表的函数失败。当我在find_successors函数之外尝试findall函数时,它完美地工作,但由于某种原因,在find_successors函数中,它只是读取false。通过图形调试器,我甚至可以看到它找到所有的解决方案。下面的代码:findall/3错误地评估为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
concatenate将第三个参数与获得的列表相结合,并将第一个和第二个列表中的元素连接起来;所以
append([], O, OL1)
与没有在它的元件的第一个参数,统一O
OL1
与如此是无用的;你可以写在表格中的所有行
(findall(X, is_a(Start, X), O), append([], O, OL1); OL1 = []),
为
(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), !.
或者不能切割?
平时每次都会出现最愚蠢的错误,我一直坚持让自己陷入堆栈溢出的困境......但是我对你的旁注感到困惑......运行该示例后,它给了我完全的答案我曾预料过它,那就是 'A = 1; A = 2' – bendl