假设你有两个事实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个参数?
答案 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基本上按预期工作,但您只能获得true
或false
的答案。这种行为的原因是否定。由于存在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
)表示,就像在初始尝试中一样。但在这里,它们实际上代表了二阶结构。