建立在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, ... - ...|...].
這太好了。我的程序已經完美運行,但這個組織太好了,無法通過。我會再次重新設計它。感謝您的澄清。 – SuperCell
我沒有15點的聲望可以投票,但是當我這樣做時,我會回到這裏。 – SuperCell
安全檢查的參數如何「充分實例化」? – false