考虑这段代码
:- use_module(library(clpfd)).
p(1).
p(3).
p(5).
p(7).
predecessor(A, B) :- A #= B - 1. % is true for pairs
q(X) :- predecessor(P, X), \+ p(P).
如果我查询?- p(X)
我正确地得到了结果
? - p(X)。
X = 1;
X = 3;
X = 5;
X = 7。
但是如果我查询?- q(X)
,那么我会得到false
。
我意识到\+
实际上不是否定,而是要证明,但是如果不能证明某些东西足以让另一个谓词成立呢?
我想给出一个合理的用例/示例,这就是我使用clpfd的原因。即使不使用它,我还有另一个例子,我可以提出:
likes(betty, butter).
likes(betty, jam) :- fail.
dislikes(betty, Item) :- \+ likes(betty, Item).
这个例子也有一个缺点,likes(betty, jam) :- fail.
并没有真正做任何事情。但我希望我能够理解我的观点。
prolog有没有办法来定义这种依赖?
答案 0 :(得分:3)
如果您希望Prolog在该领域提供解决方案,您必须明确定义可能性的“负面宇宙”。
例如,\+ p(X)
无法告诉您X
的具体值,因为尚未定义符合此条件的可能X
。你要求Prolog发明X
可能是什么,这是不可能的。
您可以定义所有可能值的范围,然后您可以定义\+ p(X)
的含义:
:- use_module(library(clpfd)).
p(1).
p(3).
p(5).
p(7).
predecessor(A, B) :- A #= B - 1. % is true for pairs
q(X) :- predecessor(P, X), P in 0..9, label([P]), \+ p(P).
然后你得到:
2 ?- q(X).
X = 1 ;
X = 3 ;
X = 5 ;
X = 7 ;
X = 9 ;
X = 10.
3 ?-
在这里,我们告诉Prolog,P
可能选择的范围由P in 0..9
定义。然后,调用\+ p(P)
可以产生特定结果。不幸的是,使用\+
,您仍需在测试label([P])
之前应用\+ p(P)
,但您明白了。
在likes
的另一个例子中,问题是同一个问题。你定义了:
likes(betty, butter).
likes(betty, jam) :- fail.
正如您所指出的那样,您通常不会包含likes(betty, jam) :- fail.
,因为由于缺少成功的事实或谓词而导致失败。但是,您的收录实际上是对可能选择范围进行定义的初步尝试。如果没有这个定义,Prolog就无法“发明”从中挑选出来以测试不喜欢的内容。因此,更完整的解决方案将是:
person(jim).
person(sally).
person(betty).
person(joe).
food(jam).
food(butter).
food(eggs).
food(bread).
likes(betty, butter).
然后你可以写:
dislikes(Person, Food) :-
person(Person),
food(Food),
\+ likes(Person, Food).