否定两个以上的事实

时间:2017-10-25 02:31:28

标签: prolog

假设你有两个事实F1(x,y)和F2(x,y),你需要将关系定义为R(X,Y) - :F1(X,Y); F1(Y,X); F2(X,Y); F2(Y,X)。现在这将工作,虽然它将有多个返回值。为了避免这种情况,我使用了DeMorgan的定理(也许有更好的方法)并且得到了

R(X,Y) :- \+( \+F1(X,Y), \+F1(Y,X), \+F2(X,Y), \+F2(Y,X) ). 

然而,这导致错误存在错误(过程,(\ +)\ 4),R \ 2

所以它不知何故它认为我要求R(X,Y)有4个参数?

1 个答案:

答案 0 :(得分:4)

正如评论中指出的那样,你需要在否定和它的参数之间加一个空格,而大写字母在Prolog中开始变量名。在一阶逻辑中,您不能将变量用于仿函数。这仅适用于二阶和更高阶逻辑(请参阅下面的示例)。但首先,让我们更正你的代码,看看会发生什么。为了论证,让我们为f1 / 2和f2 / 2添加两个事实:

f1(a,b).
f2(x,y).

r(X,Y) :- \+ ( \+ f1(X,Y), \+ f1(Y,X), \+ f2(X,Y), \+ f2(Y,X) ).

如果你查询该谓词它会成功,但是你没有获得使关系成立的任何变量替换:

?- r(X,Y).
true.

?- r(a,Y).
true.

?- r(a,b).
true.

?- r(a,z).
false.

上述查询显示r / 2基本上按预期工作,但您只能获得truefalse的答案。这种行为的原因是否定。由于存在f1 / 2和f2 / 2的事实,以下查询失败:

?- \+ f1(X,Y).
false.

?- \+ f2(X,Y).
false.

由于这些查询没有解决方案,因此您无法替换变量。因此,再次否定它们只会得到答案true,但仍然没有替代:

?- \+ \+ f1(X,Y).
true.

?- \+ \+ f2(X,Y).
true.

另一方面,没有否定的定义会带来这样的替代:

r2(X,Y) :-
   f1(X,Y).
r2(X,Y) :-
   f1(Y,X).
r2(X,Y) :-
   f2(X,Y).
r2(X,Y) :-
   f2(Y,X).

?- r2(X,Y).
X = a,
Y = b ;
X = b,
Y = a ;
X = x,
Y = y ;
X = y,
Y = x.

如果您可以理解,不希望为每个对称关系编写两个规则,您可以选择为要考虑的所有谓词的仿函数添加事实。在这种情况下,只有两个关系f1 / 2和f2 / 2:

rel(f1).
rel(f2).

在此基础上,您可以像这样定义谓词r3 / 2和rsym / 3:

rsym(F,X,Y) :-
   call(F,X,Y).  % calling the predicate with functor F and args X,Y
rsym(F,X,Y) :-
   call(F,Y,X).  % calling the predicate with functor F and args Y,X

r3(X,Y) :-
   rel(F),       % the relation in question has to have a functor described in rel/2
   rsym(F,X,Y).  % and is a symmetric relation

如果查询此谓词,则会得到与r2 / 2相同的结果:

?- r3(X,Y).
X = a,
Y = b ;
X = b,
Y = a ;
X = x,
Y = y ;
X = y,
Y = x.

只有两个关系f1 / 2和f2 / 2这没有太大的区别,但如果你有更多这样的关系,你只需要为每个关系的仿函数添加一个事实rel / 2。请注意,仿函数在r3 / 2和rsym / 3中用变量(F)表示,就像在初始尝试中一样。但在这里,它们实际上代表了二阶结构。