Prolog谓词(\ =)/ 2被忽略

时间:2016-03-17 22:45:04

标签: 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.
麦克出现了......

?- findall(X, likes(mike, X), L).
L = [mike, danny, samuel, henry, samantha, jane, betty, jenny].

我假设它是因为prolog首先评估规则man(X)所以迈克是true。但是,如果我将其更改为:

likes(mike, X) :-
    X \= mike,
    man(X);
    woman(X).

我只会得到女性。

?- findall(X, likes(mike, X), L).
L = [samantha, jane, betty, jenny].

问题是如何做到呢?谢谢!
注意:我正在使用swi-prolog

3 个答案:

答案 0 :(得分:2)

问题是运营商优先级。只是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 ) .

你断言Mike喜欢

的任何人
  • 一个男人(包括他自己),或者
  • 一个不是迈克的女人。

当你的意思是迈克喜欢任何人 - 男性或女性 - 而不是他自己。

所以......你需要用括号明确优先级,

likes(A,B) :- ( man(B) ; woman(B) ) , A \= B .

或者更好的是,将您的谓词分解为2个子句并使其成为通用的:

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 .

答案 1 :(得分:1)

问题在于 OR 运算符(; ):

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.

另一种解决方案(使用等效于OR运算符)可以是:

likes(mike, X) :- man(X), X\=mike.
likes(mike, X) :- woman(X).

请注意,您不需要OR运算符。

答案 2 :(得分:1)

除了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无法做到这一点。

再见

P.S。:(\=)/2出现问题的原因。作为失败的否定\+ A有时不仅充当~A,还充当~exists X1,..,Xn A。感兴趣的读者可能会喜欢勉强通过这个小老,但仍然适用:

具有否定的逻辑程序的证明理论
RobertStärk,伯尔尼,1992年 http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.29.2745&rep=rep1&type=pdf