建立在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