Prolog谓词(\=)/2已忽略
开始使用prolog,我正在尝试做一些简单的练习,但是我很早就被卡住了。。。我想说的是:迈克喜欢任何男人或女人,而不是迈克。但是,Prolog谓词(\=)/2已忽略,prolog,Prolog,开始使用prolog,我正在尝试做一些简单的练习,但是我很早就被卡住了。。。我想说的是:迈克喜欢任何男人或女人,而不是迈克。但是,X\=mike似乎被忽略了: man(mike). man(danny). man(samuel). man(henry). woman(samantha). woman(jane). woman(betty). woman(jenny). likes(mike, X) :- man(X); woman(X), X \= mike. 迈克
X\=mike
似乎被忽略了:
man(mike).
man(danny).
man(samuel).
man(henry).
woman(samantha).
woman(jane).
woman(betty).
woman(jenny).
likes(mike, X) :-
man(X);
woman(X),
X \= mike.
迈克出现了
?- findall(X, likes(mike, X), L).
L = [mike, danny, samuel, henry, samantha, jane, betty, jenny].
我认为这是因为prolog首先计算规则man(X)
,所以mike是true
。但是,如果我将其更改为:
likes(mike, X) :-
X \= mike,
man(X);
woman(X).
我只会得到女人
?- findall(X, likes(mike, X), L).
L = [samantha, jane, betty, jenny].
问题是如何做到这一点?谢谢注意:我正在使用swi prolog问题在于或运算符(;): 您的解决方案:
likes(mike, X) :- (man(X);woman(X)),X\=mike.
另一种解决方案(使用与OR运算符等效的运算符)可以是:
likes(mike, X) :- man(X), X\=mike.
likes(mike, X) :- woman(X).
请注意,您不需要OR运算符。问题在于运算符优先级。只有C/C#/Java/SQL和其他过程语言,在Prolog中,逻辑OR(
;
)的优先级与逻辑and(“,”)的优先级不同
在大多数过程语言中,表达式
A || B && C
被解析为
A | |(B&C)
在Prolog中,类似于您的表达式
A ; B , C
像写的一样被解析
A ; (B,C)
那么你的
likes(mike, X) :-
man(X);
woman(X),
X \= mike.
本质上是
likes(mike,X) :- man(X) ; ( woman(X) , X \= mike ) .
你是说迈克喜欢任何一个
- 男人(包括他自己),或
- 不是迈克的女人
likes(A,B) :- ( man(B) ; woman(B) ) , A \= B .
或者更好的方法是,将谓词分成两个子句,并使其成为泛型:
likes(A,B) :- man(B) , A \= B .
likes(A,B) :- woman(B) , A \= B .
通过将性别作为实体(一个人)的属性而不是事实本身来进一步改善事物:
person( mike , male ) .
person( danny , male ) .
person( samuel , male ) .
person( henry , male ) .
person( samantha , female ) .
person( jane , female ) .
person( betty , female ) .
person( jenny , female ) .
那么likes/2
就更简单了,因为人们可以喜欢两性的人:
likes(A,B) :- person(B,_) , A \= B .
除了OR问题之外,还有另一个问题。谓词(\=)/2不是约束,意味着它本质上不是完全声明性谓词 谓词通常是通过作为失败的否定来引导的,而作为失败的否定本身并不是完全声明的 谓词从普通统一中引导,如下所示:
X \= Y :- \+ X = Y.
另一种定义是:
X \= X :- !, fail.
_ \= _.
如果你真的想绕过这个不等式,你应该使用带有约束的Prolog系统,然后求助于dif/2
使用dif/2,您可以编写:
likes(mike, X) :-
(dif(X, mike),
man(X)
; woman(X)).
或以下各项:
likes(mike, X) :-
(man(X),
dif(X, mike)
; woman(X)).
你会得到同样的结果。这在(\=)/2
中是不可能的
再见
备注:(\=)/2
出现问题的原因。作为失败的否定有时不仅充当失败的否定,而且还充当失败的否定。感兴趣的读者可能想涉猎一些公认的古老但仍然适用的内容:
逻辑程序的否定证明理论
罗伯特·斯特尔克,伯尔尼,1992年由于运算符优先级,
man(X);女人(X),X\=mike。
被解释为男人(X);(女人(X),X\=mike)。。您可以用括号来更改,将分组代码>:(男人(X);女人(X)),X\=迈克。
。这也是第二个例子的问题之一。查看有关的信息。比如说列出(喜欢)
!它会立即向您显示问题。标题有点奇怪。实际上(\=)/2不是规则,而是谓词。这个谓词用于规则中的文本。
likes(mike, X) :-
(man(X),
dif(X, mike)
; woman(X)).