2015-07-21 62 views
4

我似乎無法讓我的if語句工作。序言如果其他語法

  1. 約翰,弗雷德和哈利是男人,瑪麗,朱莉,蘇珊和安妮是女人。
  2. 約翰有金色的頭髮,而弗雷德和哈利有黑髮。
  3. 朱莉和蘇珊是金髮女郎,瑪麗和安妮是黑髮。
  4. Rich是每個擁有黃金的人 - 弗雷德和朱莉在我們的例子中。
  5. 男性只喜歡女性,反之亦然。此外,約翰和哈利喜歡富有的人,約翰喜歡金髮和弗雷德喜歡黑髮。
  6. 瑪麗和朱莉都喜歡深色頭髮的人,朱莉喜歡富有的人同時。
male(john). 
male(fred). 
male(harry). 

female(mary). 
female(julie). 
female(susan). 
female(anne). 

hasblonde(X):-(male(X),X = john);(female(X),X = susan);(female(X),X = julie). 

hasdarkhair(X):-(male(X),X = harry);(male(X),X = fred). 

hasbrunette(X):-(female(X),X = mary);(female(X),X = anne). 

isrich(X):-(female(julie),X=julie);(male(fred),X=fred). 


likes(male(X),female(Y));likes(female(X),male(Y)):-likes(X,Y).  
likes(X,Y):- 
((X==julie)-> 
    ((hasdarkhair(Y))-> 
     (female(X), male(Y)); 
     male(X)); 
    female(X),male(Y)); 
((X==julie)-> 
    ((isrich(Y))-> 
     (female(X), male(Y)); 
     male(X)); 
    female(X),male(Y)); 
((X=mary)-> 
    ((hasdarkhair(Y))-> 
     (female(X), male(Y)); 
     male(X)); 
    female(X),male(Y)); 
((X=john)-> 
    ((isrich(Y))-> 
     (female(X), male(Y)); 
     female(X)); 
    male(X),female(Y)); 
((X=harry)-> 
    ((isrich(Y))-> 
     (female(X), male(Y)); 
     female(X)); 
    male(X),female(Y));  
((X=fred)-> 
     ((hasbrunette(Y))-> 
      (female(X), male(Y)); 
      female(X)); 
    male(X),female(Y)). 

我想 (報表) - >(如果真跑這一說法);(如果是假來看,這種說法)。在Prolog中, 是正確的方法。爲什麼說不管我寫

likes(MaleName,FemaleName) 
likes(FemaleName,MaleName) 

返回true?

回答

5

建立在CapelliC的答案上,因爲顯然他的答案不夠明確。至於if-else語法和用法,請參閱答案的結尾。

首先,您的問題陳述中包含的信息是您想要以Prolog程序的形式表示的信息。在Prolog中,你有謂詞,它可以描述關係之間的論點或已知的真值關於他們的論點。例如,這裏是一個事實表;它指出我們知道存在七個人:

 
person(john). 
person(fred). 
person(harry). 
person(mary). 
person(julie). 
person(susan). 
person(anne). 

好的。我們現在要說的是,其中一些是男性,一些是女性。

 
% John, Fred and Harry are men, Mary, Julie, Susan and Anne are women. 
male(john). 
male(fred). 
male(harry). 

female(mary). 
female(julie). 
female(susan). 
female(anne). 

這些是另外兩個事實表。現在,您要添加到您的數據庫中關於他們的頭髮顏色的信息:

 
% John has blonde hair while Fred and Harry have dark hair. 
% Julie and Susan are blonde, Mary and Anne are brunette. 
person_hair(john, blond). 
person_hair(fred, dark). 
person_hair(harry, dark). 
person_hair(julie, blond). 
person_hair(susan, blond). 
person_hair(mary, dark). 
person_hair(anne, dark). 

這是兩列的表,如果你會:第一是人,第二個是頭髮顏色的描述。單詞「黑髮」通常用來形容一個黑髮女人,所以我們可以添加一個規則指出:

 
% A brunette is a female with dark hair 
brunette(X) :- 
    female(X), 
    person_hair(X, dark). 

一些,我們有自己的黃金的人,並擁有金我們的節目,使豐富的一個人:

 
person_owns(fred, gold). 
person_owns(julie, gold). 

is_rich(X) :- 
    %person(X), 
    person_owns(X, gold). 

在我們嚴格的異性程序,男人喜歡女人和女人喜歡的男人:

 
person_likes(M, F) :- 
    male(M), 
    female(F). 
person_likes(F, M) :- 
    female(F), 
    male(M). 

正如你可以計算一下,這給我們提供了person_likes(A, B) 3×4 + 4×3 = 24種可能的解決方案,而任何進一步的限制:

 
?- bagof(A-B, person_likes(A, B), R), length(R, Len). 
R = [john-mary, john-julie, john-susan, john-anne, fred-mary, fred-julie, fred-susan, fred-anne, ... - ...|...], 
Len = 24. 

這是一個非常普遍的規則:它描述自由變量之間的關係,這使得它與我們的person_owns/2關係有些不同,例如。它真的有用嗎?爲什麼不:

 
is_heterosexual(H) :- 
    person(H). 

但是,這只是說我們程序中的每個人都是異性戀;它不會讓我們得出異性戀是喜歡異性的人的規則。也許是更好的重新命名,以更好地表達自己的意思(我將使用if-then-else結構,來顯示它是如何正常進行):

 
opposite_sex(X, Y) :- 
    ( male(X) 
    -> female(Y) 
    ; female(X) 
    -> male(Y) 
    ). 

對於我們而言,這可能只是以及寫成上面:

 
opposite_sex(M, F) :- 
    male(M), female(F). 
opposite_sex(F, M) :- 
    male(M), female(F). 

有了這個,我們可以寫一個規則person_likes/2與一般的前置條件,指出對方必須是異性:

 
person_likes(X, Y) :- 
    opposite_sex(X, Y), 
    fits_personal_taste(X, Y). 

我們c現在制定每個人的個人品味規則。朱麗:

 
fits_personal_taste(julie, X) :- 
    is_rich(X), 
    person_hair(X, dark). 

然而,這產生了一個小問題。你需要確保對於程序知道的每個人約這裏有一個規則。我們不知道安妮任何偏好,所以我們必須有一個規則:

 
% Anyone (male) would fit Anne's tastes 
fits_personal_taste(anne, _). 

這將是更好,如果我們能夠代替有一個表格,表格中每個人的條目確實有偏好,例如:

 
person_preferences(julie, [is_rich, person_hair(dark)]). 
person_preferences(harry, [is_rich]). 
% and so on 

這將允許我們寫fits_personal_taste/2是這樣的:

 
fits_personal_taste(X, Y) :- 
    ( person_preferences(X, Ps) 
    -> maplist(fits_preference(Y), Ps) 
    ; true 
    ). 

這是在Prolog專有 OR中的if-else構建的預期用途。

如果一個人的喜好,檢查候選人符合所有的人; 否則成功。

fits_preference/2怎麼樣?這將需要一個人作爲第一個參數,第二個參數是首選項,並且必須以某種方式檢查該人是否符合該首選項。一個有點哈克的解決辦法是使用所謂的大學運營商=..採取的形式person_hair(Color)的一個術語,使窗體person_hair(Person, Color)的期限,並將其命名爲:

fits_preference(Person, Preference) :- 
    Preference =.. [F|Args], 
    Preference1 =.. [F,Person|Args], 
    call(Preference1). 

這也許是更好的那person_preferences直接映射一個人可贖回條款:

 
person_preferences(julie, P, [is_rich(P), person_hair(P, dark)]). 
person_preferences(harry, P, [is_rich(P)]). 
% and so on 

有了這個,fits_personal_taste/2變爲:

 
fits_personal_taste(X, Y) :- 
    ( person_preferences(X, Y, Ps) 
    -> maplist(call, Ps) 
    ; true 
    ). 

當在聲明的條件部分調用person_preferences/3時,首選項列表中的每個首選項都綁定到具體人員;然後我們打電話給每個人檢查它是否可以證明對我們程序中的事實是真實的。

最後一個輔助謂詞possible_pair/2,指出兩國人民需要喜歡對方:

possible_pair(X, Y) :- 
    person_likes(X, Y), 
    person_likes(Y, X), 
    X @< Y. 

最後一行將確保我們不會通過假定得到同樣對兩次的兩個人物應嚴格排列。

有了這個,我得到:

?- bagof(A-B, possible_pair(A, B), R). 
R = [fred-mary, anne-fred]. 

或者,對於單向「喜歡」清單,

?- bagof(A-B, person_likes(A, B), R), write(R). 
[john-julie,fred-mary,fred-anne,harry-julie,susan-john,anne-john,mary-fred,julie-fred,susan-fred,anne-fred,mary-harry,susan-harry,anne-harry] 
R = [john-julie, fred-mary, fred-anne, harry-julie, susan-john, anne-john, mary-fred, julie-fred, ... - ...|...]. 
+1

這太好了。我的程序已經完美運行,但這個組織太好了,無法通過。我會再次重新設計它。感謝您的澄清。 – SuperCell

+3

我沒有15點的聲望可以投票,但是當我這樣做時,我會回到這裏。 – SuperCell

+0

安全檢查的參數如何「充分實例化」? – false

1

你的問題之前,方向盤,我想指出,有幾個問題,在您的代碼:

關於語法:p1 ; p2 :- p3.無效

?- [user]. 
p1;p2:-p3. 
ERROR: user://1:9: 
    No permission to modify static procedure `(;)/2' 
    ... 

Prolog使用邏輯公式的具體的「編碼」,所謂Horn clauses

他們在自動定理的一階分辨率證明很重要,因爲有兩個Horn子句的解決方法本身是一個霍恩條款,以及目標條款和明確條款的解決方案是一個目標條款。

關於對問題進行建模:我認爲最小化「自然語言」公式和計算公式之間的語法差異非常重要。每一個變化必須調試 :-)

那麼,爲什麼不來定義

rich(Person) :- owns(Person, gold). 
owns(fred, gold). 
owns(julie, gold). 

您可以找到有關Zebra拼圖許多問題和答案,我就不在這裏贅述了,所以請期待[zebra-puzzle]在堆棧溢出搜索框。你會看到if/then/else從不需要 - 有很好的理由。在Prolog中有更簡單的方法來表達這些基本問題。

+1

好答案(+1)。順便說一句,這甚至不像「斑馬謎題」那樣的問題,它更多的是尋找正確的方式來模擬數據,就像事實是什麼,規則是什麼一樣。你用'rich/1'和'擁有/ 1'的例子是對的。 – 2015-07-21 07:11:11

+1

您可以在語法中嵌入標籤:'[tag:zebra-puzzle]' – mat

1

所以我修好了,但現在我不得不用你上面說的重做它。這種方式很有效,但它似乎只能得到第一個答案,而不能搜索另一個答案。 例子: 輸出

1 ?- likes(julie,X). 
X = harry ; 
false. 

程序編輯:

likes(male(X),female(Y)):-likes(X,Y). 
likes(female(X),male(Y)):-likes(X,Y). 
likes(X,Y):- 
((X=julie)-> 
    ((hasdarkhair(Y))-> 
     (female(X), male(Y)); 
     male(X)); 

    ((X=julie)-> 
    ((isrich(Y))-> 
     (female(X), male(Y)); 
     male(X)); 

((X=mary)-> 
    ((hasdarkhair(Y))-> 
     (female(X), male(Y)); 
     male(X)); 
    female(X),male(Y)))); 

((X=john)-> 
    ((isrich(Y))-> 
     (male(X), female(Y)); 
     female(X)); 
    ((X=john)-> 
    ((isblonde(Y))-> 
     (male(X), female(Y)); 
     female(X)); 
((X=harry)-> 
    ((isrich(Y))-> 
     (male(X), female(Y)); 
     female(X)); 
((X=fred)-> 
    ((hasbrunette(Y))-> 
     (male(X), female(Y)); 
     female(X)); 
    male(X),female(Y))))). 

當它應該返回

X=Harry 
X=Fred 

因爲

likes(julie,fred) 
true 

//返回

+0

如果/ then/else'operator'已經被引入*爲了避免替代方案出現,Prolog默認會執行。也許,將Prolog看作比原子值更豐富的域上的「可編程」SQL ... – CapelliC

1

更改代碼:

male(john). 
male(fred). 
male(harry). 
female(mary). 
female(julie). 
female(susan). 
female(anne). 

hasblonde(X):-(male(X),X = john);(female(X),X = susan);(female(X),X = julie). 
hasdarkhair(X):-(male(X),X = harry);(male(X),X = fred). 
hasbrunette(X):-(female(X),X = mary);(female(X),X = anne). 

isrich(X):-(female(julie),X=julie);(male(fred),X=fred). 


likes(X,Y):-((X=julie),(hasdarkhair(Y);isrich(Y)),(female(X),male(Y))). 
likes(X,Y):-((X=mary),hasdarkhair(Y),female(X),male(Y)). 
likes(X,Y):-((X=john),(isrich(Y);hasblonde(Y)),male(X),female(Y)). 
likes(X,Y):-((X=harry),isrich(Y),male(X),female(Y)). 
likes(X,Y):-((X=fred),hasbrunette(Y),male(X),female(Y)). 
likes(X,Y):-((X=susan);(X=anne)),((male(X),female(Y));(female(X),male(Y))). 
    ownscar(john). 
love(X,Y):-likes(X,Y),likes(Y,X). 

是不是更好?

+0

但是我使用分號作爲或語句來保存不必重複的代碼。你能舉一個例子,說明哪裏可以做得更好嗎? – SuperCell

0

我想通過定義一組人處理這個問題,所有人都有一套必需的屬性(性別,頭髮顏色和財務狀況)以及一組可選的喜歡(性別,頭髮顏色和財務狀況)。

person(john , is(male , blonde , poor) , likes(female , blonde , rich)) . 
person(fred , is(male , brunette , rich) , likes(female , brunette , _ )) . 
person(harry , is(male , brunette , poor) , likes(female , _  , rich)) . 

person(mary , is(female , brunette , poor) , likes(male , brunette , _ )) . 
person(julie , is(female , blonde , rich) , likes(male , brunette , rich)) . 
person(susan , is(female , blonde , poor) , likes(male , _  , _ )) . 
person(anne , is(female , brunette , poor) , likes(male , _  , _ )) . 

,能讓您確定一個景點是否存在很乾脆:

我們將與一個 不在乎狀態特定喜歡的是由匿名變量 _指示的約定去
likes(P1 , P2) :- 
    person(P1 , _   , likes(G2,H2,S2)) , 
    person(P2 , is(G2,H2,S2) , _    ) 
    . 

如果你想顯示相互吸引,你可以簡單地擴展這個一點:

mutual_attraction(P1 , P2) :- 
    person(P1 , is(G1,H1,S1) , likes(G2,H2,S2)) , 
    person(P2 , is(G2,H2,S2) , likes(G1,H1,S1)) 
    . 

這人所以允許性別靈活的喜歡—只是使用匿名變量爲性別來表示不在乎

這種方法確實有限制,喜歡是單值的—沒有方便的說法,例如,約翰像紅色的頭髮或金色的頭髮,但不是棕色的頭髮。

+0

這也是一個很好的方法來處理它(+1)。不同之處在於,您不會「正常化」數據,但您明確描述了該方法的優點和缺點。 – 2015-07-22 06:04:58