Prolog谓词只返回一个结果

时间:2016-09-29 21:23:44

标签: prolog trace

我有一个名为spider的谓词,代码如下:

person(ada).
person(beda).
person(calle).
knows(ada,beda).
knows(ada,calle).
knows(beda,calle).

% Returns true for arguments X and Y if either knows(X,Y) or knows(Y,X) is true.
xknowsy(X,Y) :- knows(X,Y).
xknowsy(X,Y) :- knows(Y,X).

subsetsof([],[]).
subsetsof([A|B],[A|D]) :- subsetsof(B,D).
subsetsof([A|B],D) :- subsetsof(B,D).

dontknowlist([]).
dontknowlist([A]).
dontknowlist([A,B|C]) :- not(xknowsy(A,B)), dontknowlist([A|C]), dontknowlist([B|C]).

listknowsconspirator([],C).
listknowsconspirator([A|B],C) :- knowssomeone(A,C), listknowsconspirator(B,C).

knowssomeone(A,[]).
knowssomeone(A,[B|C]) :- xknowsy(A,B).
knowssomeone(A,[B,C|D]) :- knowssomeone(A,[C|D]).

spider(X) :- person(X), findall(A,xknowsy(X,A),B), subsetsof(B,C), dontknowlist(C),!,
findall(E,person(E),F), removespider(F,X,G), removeconspirators(G,C,L),!,
listknowsconspirator(L,C),!.

removespider([],X,L) :- L = [].
removespider([A|B],X,L) :- A = X, L = B.
removespider([A|B],X,L) :- not(A = X), removespider(B,X,M), L = [A|M].

removeconspirators([],D,L) :- L = [].
removeconspirators(E,[],L) :- L = E.
removeconspirators([A],[B],L) :- A = B, L = [].
removeconspirators([A],[B],L) :- not(A = B), L = [A].
removeconspirators([A,B|C],[D],L) :- A = D, L = [B|C].
removeconspirators([A,B|C],[D],L) :- not(A = D), removeconspirators([B|C],[D],M), L = [A|M].
removeconspirators([A|B],[S,T|U],L) :- removeconspirators([A|B],[S],M),
removeconspirators(M,[T|U],N), L = N.

对蜘蛛(ada),蜘蛛(beda)和蜘蛛(calle)的调用都单独返回true。但是当我调用spider(X)时,我没有得到X的所有三个解决方案。我只得到第一个解决方案,即X = ada。我不明白为什么因为person(X)确保我得到所有三个可能的X值来运行谓词的其余部分。在跟踪模式下调用spider(X)似乎没有显示任何明显的解释,但我的编译器SWI-Prolog似乎忽略了其他情况。为什么在调用spider(X)时没有打印出所有三个解决方案?

1 个答案:

答案 0 :(得分:0)

上述行为的原因是您在spider / 1谓词中使用的剪切。如果你删除它们并写:

spider(X) :- person(X), findall(A,xknowsy(X,A),B), subsetsof(B,C),dontknowlist(C),
findall(E,person(E),F), removespider(F,X,G), removeconspirators(G,C,L),
listknowsconspirator(L,C).

然后如果你查询:

?- final_spider(X).
X = ada ;
X = ada ;
X = ada ;
X = beda ;
X = beda ;
X = beda ;
X = calle ;
X = calle ;
X = calle.

这通过回溯提供所有解决方案,但它提供了多次正确的解决方案。这是不容易避免使用!因为它也会削减一些正确的答案。 只有在编写一个谓词后才能保留正确的解决方案:

final_spider(X):-findall(Y,spider(Y),L),sort(L,L1),member(X,L1).

现在,如果您查询:

?- final_spider(X).
X = ada ;
X = beda ;
X = calle.

它只提供一次正确的解决方案。