2016-03-17 172 views
3

開始使用prolog,我正在嘗試做一些簡單的練習,但是我很早就被卡住了......我想說的是:mike like anyone if這是一個男人或女人,它不是麥克。但X \= mike似乎被忽略:Prolog謂詞( =)/ 2被忽略

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]. 

我想這是因爲序言評估規則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的

+2

由於運算符優先級, '人(X);女人(X),X \ = mike.'被解釋爲'man(X); (女(X),X \ =麥克)。你可以用圓括號改變它,把';':'(man(X); woman(X)),X \ = mike.'分組。這也是你的第二個例子的問題之一。查看[運營商優先權]信息(http://www.swi-prolog.org/pldoc/man?predicate=op/3)。 – lurker

+1

說'上市(如)'!它立即向您顯示問題。 – false

+0

標題有點奇怪。實際上(\ =)/ 2不是一個規則,而是一個謂詞。這個謂詞用在規則中的字面上。 –

回答

2

問題是運算符優先級。在邏輯OR(;)中,只有C/C#/ Java/SQL和其他過程語言與邏輯AND(',')有不同的優先

在大多數程序語言,如

A || B && C 

的表達被解析爲

甲|| (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 . 

或更好,但打破你的謂語成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 . 
+0

感謝您的擴展解釋! – skamsie

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運算符。

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。有興趣的讀者可能希望通過承認有點老涉水,但仍然適用:

邏輯程序與否定的證明論
羅伯特·斯塔克,伯爾尼,1992年
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.29.2745&rep=rep1&type=pdf