我正在创建一个允许通过图形搜索的程序,但是当对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).
答案 0 :(得分: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 ).
您认为会发生什么?
答案 1 :(得分:0)
您应该建议我们致电find_successors(Start, Out)
并说出预期值。
如果没有它,很难说你的代码在哪里出错了......但某些点没有特别的顺序......
(1)append/3
concatenate将第三个参数与从第一个和第二个列表中连接元素的列表统一起来;所以
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),
统一时;我想你可以简单地写一下
append
(3)我只知道有append([OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out)
个三个论点;所以我不明白
append([], [OL1, OL2, OL3, OL4, OL5, OL6, OL7, OL8], Out)
你打算写
find_successors/2
在这种情况下,考虑到计数(1)和(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)
)中的cut会禁用第二个和第三个子句,因此,如果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), !.
失败,则永远不会验证第二个和第三个子句。< / p>
你确定你的意图不是
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), !.
或更好
has/3
还是根本不切?
(5)与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), !.
或更好
public class Lunch implements Parcelable {
private String mName;
private float priceStud;
private float priceEmp;
private float priceGuest;
private ArrayList<Lunch> m = new ArrayList<Lunch>();
public static final int PRICE_STUDENT = 0;
public static final int PRICE_EMPLOYEE = 1;
public static int PRICE_GUEST = 2;
public Lunch(Parcel in) {
setmName(in.readString());
setPriceStud(in.readFloat());
setPriceEmp(in.readFloat());
setPriceGuest(in.readFloat());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getmName());
dest.writeFloat(getPriceGuest());
dest.writeFloat(getPriceEmp());
dest.writeFloat(getPriceStud());
}
public static final Creator<Lunch> CREATOR = new Creator<Lunch>() {
public Lunch createFromParcel(Parcel in) {
return new Lunch(in);
}
public Lunch[] newArray(int size) {
return new Lunch[size];
}
};
还是根本不切?