2014-01-10 44 views
0

我有幾個事實,如下所示Prolog的問題,與和&或符號

letter(monica, suzane, '2012-02-13'). 
letter(suzane, janet, '2012-02-14'). 
letter(suzane, monica, '2012-02-14'). 
letter(tom, phillip, '2012-02-14'). 
letter(phillip, suzane, '2012-02-14'). 
letter(monica, phillip, '2012-02-15'). 

我想創建一個返回所有誰交換了一封信給X和Y的人的名字的規則,在指定日期之前。例如,如果X是monica,Y是suzane,D是2012-02-16,那麼它應該只返回phillip,因爲monica和suzane與phillip交換了一封信。

目前,我有這個規則;

letterexch(X,Y,D):- 
(( (letter(X, Z, D1); letter(Z, X, D1)), \+ Z = Y); 
( (letter(Y, Z, D1); letter(Z, Y, D1)), \+ Z = X)), D1 @<D, nl, print(Z),false. 

我認爲或符號()之後「+ Z = Y)」應該是一個和(,)符號,而不是一個或符號(;),但是當我設置有與符號的規則( ,)和查詢,如下所示:

?- letterexch(monica, suzane, '2012-02-16'). 

我得到:

false 

但如果我設置規則等上述具有或符號()和查詢它如下:

?- letterexch(monica, suzane, '2012-02-16'). 

我得到:

phillip 
janet 
phillip 

不過,我只需要菲利普打印。 (我不介意菲利普是否因爲我知道如何擺脫它而重複)。

因此,我需要知道爲什麼當和符號(,)使用時,我得到錯誤,而不是菲利普印兩次。

任何幫助將不勝感激。

預先感謝您。

+1

無論是「和」還是「或」都是在上下文中有意義的邏輯問題。在這種情況下,你的表達'(字母(X,Z,D1);字母(X,Z,D1))'應該是'(字母(X,Z,D1);字母(Z,X,D1) ,除非你想要求X和Z之間的「字母」關係是雙向的,否則「或」是正確的。 – lurker

回答

1

無論是「和」還是「or」都是在上下文中有意義的邏輯問題。在這種情況下,你的表達

(letter(X, Z, D1); letter(X, Z, D1)) 

應該

(letter(X, Z, D1); letter(Z, X, D1)) 

的OR意味着你要表達的成功如果任X有信Z,或者如果Z有信X。如果你使用AND,那麼你的意思是你希望它只在兩個方向都有字母(XZZY)時才能成功。如果這就是你的意思,那就用「and」(,)。

要更大的表達式:

( (letter(X, Z, D1); letter(X, Z, D1)), \+ Z = Y) ; 
( (letter(Y, Z, D1); letter(Y, Z, D1)), \+ Z = X)) 

在這種情況下,你真的正在尋找AND,OR不因爲你想交易的兩組同時是真實的。另一個問題是你可能不想在兩套交易所中規定同一日期(D1)。你可能想表達這種:

letterexch(X,Y,D):- 
    (letter(X, Z, D1); letter(Z, X, D1)), % look for exch 'twixt X Z on date D1 
    (letter(Y, Z, D2); letter(Z, Y, D2)), % look for exch 'twixt Y Z on date D2 
    \+ Z = Y, 
    \+ Z = X, 
    print(Z), nl, 
    false. 

如果你運行它,你會得到:

| ?- letterexch(monica, suzane, '2012-02-16'). 
phillip 

no 

一種解決方案。我確實將D作爲單身人士離開,我將其作爲練習來確定如何處理D


附錄

在這樣一個問題上工作時,關於Prolog中方便的事情是作爲調試工具找出什麼期望你可以手型的作品。舉例來說,如果你輸入:

| ?- (letter(monica, Z, D1); letter(Z, monica, D1)). 

D1 = '2012-02-13' 
Z = suzane ? a 

D1 = '2012-02-15' 
Z = phillip 

D1 = '2012-02-14' 
Z = suzane 

(1 ms) no 

,然後類似地爲suzane

| ?- (letter(suzane, Z, D2); letter(Z, suzane, D2)). 

D2 = '2012-02-14' 
Z = janet ? a 

D2 = '2012-02-14' 
Z = monica 

D2 = '2012-02-13' 
Z = monica 

D2 = '2012-02-14' 
Z = phillip 

(1 ms) no 

然後將它們結合起來:

| ?- (letter(monica, Z, D1); letter(Z, monica, D1)), 
     (letter(suzane, Z, D2); letter(Z, suzane, D2)). 

D1 = '2012-02-15' 
D2 = '2012-02-14' 
Z = phillip ? a 

你可以看片走到一起,解決問題作爲你走。

+0

我在你指出的規則中犯了一個錯字。這是我的實際規則:letterexch(X,Y,D): - (((字母(X,Z,D1);字母(Z,X,D1)),\ + Z = Y); (Y,Z,D1);字母(Z,Y,D1)),\ + Z = X)),D1 @ user3182311

+0

我也嘗試了你告訴我的規則,但它不起作用,它只是給我錯誤 – user3182311

+0

@ user3182311,這是因爲我從原始條款複製的規則聲明日期必須始終爲'D1'。爲了解決這個問題,我們需要將第二個語句「D2」的日期做出來,這樣它就不會被強制執行。查看更新。但是,那麼你需要決定:你想比較'D'的什麼? – lurker