2016-11-30 88 views
0

我正在创建一个应该允许通过图进行搜索的程序,但是当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). 

回答

2

你不断努力,以重复使用相同的变量,但是一旦一个变量绑定,无法再次使用它。所以所有这些:

 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). 

你觉得怎么样?

+0

平时每次都会出现最愚蠢的错误,我一直坚持让自己陷入堆栈溢出的困境......但是我对你的旁注感到困惑......运行该示例后,它给了我完全的答案我曾预料过它,那就是 'A = 1; A = 2' – bendl

0

你应该建议我们致电find_successors(Start, Out)并说出预期值。

如果没有它,很难说你的代码在哪里出错,但是......有一点没有特定的顺序......

(1)append/3 concatenate将第三个参数与获得的列表相结合,并将第一个和第二个列表中的元素连接起来;所以

append([], O, OL1) 

与没有在它的元件的第一个参数,统一OOL1与如此是无用的;你可以写在表格中的所有行

(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), !. 

或者不能切割?