swi prolog提供了太多的解决方案

时间:2014-05-23 16:32:25

标签: prolog dcg

我的prolog程序应该返回一个术语中包含的所有变量的列表。它确实可以正常工作,因为我的结果是所有变量的列表。但是现在Prolog应该停止,而是继续并且给我相同的变量列表八次。在找到解决方案后,我无法理解为什么它不会停止。任何人都可以向我解释我的错误是什么吗?

variablen(X,[]):-
   number(X).
variablen(X,[X]):-
   atomic(X),
   not(number(X)).

variablen(X+Y,R):-
   not(number(X)), atomic(X), R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(Y+X,R):-
   not(number(X)), atomic(X), R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(X+Y,R):-
   variablen(X,P), variablen(Y,Q), append(P,Q,R).

variablen(X-Y, R):-
   not(number(X)), atomic(X), R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(Y-X, R):-
   not(number(X)), atomic(X), R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(X-Y,R):-
   variablen(X,P), variablen(Y,Q), append(P,Q,R).

variablen(X*Y,R):-
   not(number(X)),atomic(X), R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(Y*X, R):-
   not(number(X)), atomic(X),R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(X*Y,R):-
   variablen(X,P), variablen(Y,Q), append(P,Q,R).

variablen(X/Y, R):-
   not(number(X)), atomic(X), R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(Y/X, R):-
   not(number(X)), atomic(X), R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(X/Y,R):-
   variablen(X,P), variablen(Y,Q), append(P,Q,R).

1 个答案:

答案 0 :(得分:3)

这里有几个问题。

首先,variablen(a,R).成功R = [a]。你说列表应该包含所有变量。所以也许你想要收集所有对你来说都有变量意义的原子。

其次,通过相应的ISO内置not/1替换特定于实现的(\+)/1

现在,找到冗余解决方案。我将只看一个特定的查询:

?- variablen(a/b,L).
L = [b, a] ;
L = [a, b] ;
L = [a, b].

因此,规则适用的方式有多种。我只需要/

variablen(X/Y, R):-
   \+number(X), atomic(X), R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(Y/X, R):-
   \+number(X), atomic(X), R1 = [X], variablen(Y,R2), append(R2,R1,R).
variablen(X/Y,R):-
   variablen(X,P), variablen(Y,Q), append(P,Q,R).

对于a/b,所有三条规则均适用。因此你的冗余。

最好的解决方案是使用Definite Clause Grammars,因为它们更优雅地处理连接:

variablen(N) -->
   {functor(N,_,0)}, !,   % rare green cut
   ( {number(N)} ; {atom(N)}, [N] ).
variablen(A+B) -->
   variablen(A),
   variablen(B).
variablen(A-B) -->
   variablen(A),
   variablen(B).
variablen(A*B) -->
   variablen(A),
   variablen(B).
variablen(A/B) -->
   variablen(A),
   variablen(B).

现在,您可以使用它:

?- phrase(variablen(a/b),L).
L = [a,b].