以下故事来自N. Wirth(1976) Algorithms + Datastructures = Programs。
我娶了一个寡妇(让她叫她W) 谁有一个成年女儿(打电话给她 d)。我的父亲(F)访问了我们 经常,爱上我的 继女和她结婚了。因此, 我父亲成了我的女婿和我的女儿 继女成了我的母亲。一些 几个月后,我的妻子生了一个 儿子(S1),谁成为 我父亲的姐夫也是 作为我的叔叔。这位父亲的妻子, 也就是说,我的继女,也有一个 儿子(S2)。
我正试图在prolog中建模这些关系,所以最终我将能够输入:
| ?- grandfather(i,i).
对于我是否是自己的爷爷,我会得到“是”或“否”。
这是我到目前为止编写的代码(grandpa.pl):
aunt(X,Y):-
sibling(X,Z),
parent(Z,Y),
female(X).
brother(X,Y):-
sibling(X,Y),
male(X).
brother_in_law(X,Y):-
child(X,Z),
married(Z,W),
parent(W,Y),
not(sibling(X,Y)),
male(X).
brother_in_law(s1,f).
child(X,Y):-
parent(Y,X).
daughter(X,Y):-
parent(Y,X),
child(X,Y),
female(X).
daughter(d,w).
father(X,Y):-
parent(X,Y),
male(X).
father(f,i).
father_in_law(X,Y):-
child(X,Z),
married(Y,Z),
not(child(X,Y)),
male(X).
grandparent(X,Y):-
parent(X,Z),
parent(Z,Y).
grandmother(X,Y):-
grandparent(X,Y),
female(X).
grandfather(X,Y):-
grandparent(X,Y),
male(X).
grandchild(X,Y):-
child(X,Z),
child(Z,Y).
married(X,Y):-
wife(X,Y),
female(X).
married(X,Y):-
husband(X,Y),
male(X).
married(i,w).
married(f,d).
mother(X,Y):-
parent(X,Y),
female(X).
parent(X,Y):-
child(Y,X).
sibling(X,Y):-
parent(Z,X),
parent(Z,Y).
sister(X,Y):-
sibling(X,Y),
female(X).
son(X,Y):-
parent(Y,X),
male(X).
son(s1,w).
son(s2,d).
son_in_law(X,Y):-
child(X,Z),
not(child(X,Y)),
married(Z,Y),
male(X).
son_in_law(f,i).
step_daughter(X,Y):-
child(X,Z),
married(Z,Y),
not(child(X,Y)),
female(X).
step_daughter(d,i).
step_parent(X,Y):-
married(X,Z),
parent(Z,Y),
not(parent(X,Y)).
step_father(X,Y):-
step_parent(X,Y),
male(X).
step_mother(X,Y):-
step_parent(X,Y),
female(X).
step_mother(d,i).
uncle(X,Y):-
sibling(X,Z),
parent(Z,Y),
male(X).
uncle(s1,i).
现在我在循环定义方面遇到了很多麻烦,以便在运行查询时进入无限循环:祖父(i,i)。
例如,我有:
(1 ms)yes {trace} | ? - 祖父(I,i)中。 1 1电话:祖父(i,i)?
2 2电话:祖父母(i,i)?
3 3呼叫:父母(i,_103)?
4 4电话:孩子(_127,i)?
5 5呼叫:父母(i,_151)?
6 6电话:孩子(_175,i)?
7 7呼叫:父母(i,_199)?
8 8电话:孩子(_223,i)?
9 9呼叫:父母(i,_247)?
10 10电话:孩子(_271,i)?
11 11致电:父母(i,_295)?
12 12电话:孩子(_319,i)?
13 13致电:家长(i,_343)? 14 14电话:孩子(_367,i)?
15 15致电:家长(i,_391)?
...
这是因为child将自己定义为拥有父级,而父级定义自己有一个孩子(正如您在上面发布的谓词中所看到的那样)。
任何人都可以帮助我重新定义这些关系的谓词,以便我可以确定我是不是自己的爷爷吗?
答案 0 :(得分:6)
我删除了代码中不必要的所有内容并更改了一些内容,这就是我最终的结果:
% married(Husband, Wife)
married(i,w).
married(f,d).
人们会认为married(X,Y) :- married(Y,X)
,但它会导致令人讨厌的循环证据,因此我们将按照惯例将丈夫放在第一位。
关于父母身份,出现了类似的问题。我们需要将父母一步视为真正的父母,因为谜语取决于它。我们知道你永远不可能成为自己的生物祖先!
然而,parent(X,Y) :- parent(Z,Y), married(X,Z)
遇到了同样的问题,所以我只是让bio_parent
表示亲生父母。
bio_parent(f,i).
bio_parent(w,d).
bio_parent(w,s1).
bio_parent(i,s1).
bio_parent(d,s2).
bio_parent(f,s2).
请注意,我们必须明确父母双方,因为没有办法从婚姻中结束亲生父母!此外,您的规范方式存在问题。你有类似的东西:
son(X,Y) :- child(X,Y), male(X).
son(a,b).
但是,根据这些规则,Prolog无法推断child(a,b)
,所以你最终得到了不是孩子的儿子!这在代码中出现了几次。如果您从b
派生a
,请始终将a
作为事实说明!
乍一看,这似乎是Prolog的缺点,但事实并非如此。请记住,每个子句只是证明某个谓词的一种方式。在上面的例子中,你说过每个男孩都是儿子,a
恰好是b
的儿子。没有人说,作为一个男孩,是一个人可以成为儿子的唯一方式,a
可能只是例外。
下一个有点罗嗦,因为我们对married
的定义迫使我们这样做
分步父亲与分步母亲分开对待。我们将它们统一为父母
但是,不过。
step_father(X,Y) :- married(X,Z),bio_parent(Z,Y),\+bio_parent(X,Y).
step_mother(X,Y) :- married(Z,X),bio_parent(Z,Y),\+bio_parent(X,Y).
step_parent(X,Y) :- step_father(X,Y).
step_parent(X,Y) :- step_mother(X,Y).
正如我上面所说,我们需要将继父母视为父母!
parent(X,Y) :- step_parent(X,Y).
parent(X,Y) :- bio_parent(X,Y).
grandparent(X,Y):-
parent(X,Z),
parent(Z,Y).
我的代码中还有一些其他错误,我只是向您展示一些示例,以便您可以从中学习。
首先,在这里你说女性妻子已婚,男性丈夫已婚。所以,男性妻子未婚。应该是相反的方式,女性已婚人士被称为妻子!
% wrong:
%
% married(X,Y):-
% wife(X,Y),
% female(X).
%
% married(X,Y):-
% husband(X,Y),
% male(X).
%
% right:
% wife(X,Y) :- married(Y,X). % according to our new definition of 'married'
% husband(X,Y) :- married(X,Y).
这里我添加了最后一行,因为您通常不认为自己是自己的兄弟姐妹:
% sibling(X,Y):-
% parent(Z,X),
% parent(Z,Y),
% X \= Y. % added this
最后两个是关于错误谓词的事实。你基本上覆盖了Prolog的 与他们一起演绎。它们应该被扣除,而不是作为事实说明!
% son_in_law(f,i).
% step_mother(d,i).
现在,尝试这样的程序。不要惊讶:你不会是唯一一个成为自己祖父母的人! ; - )
答案 1 :(得分:4)
我的prolog课程已经很久很久了,但是如何移除
parent(X,Y):-
child(Y,X).
只是将parent(A,B)
的任何用法替换为child(B,A)
?您仍然可以添加有关父母的事实,因为反向规则仍然可用 - 您也可以删除该规则,但在这种情况下,您不能再使用任何有关父母的事实,您必须将所有事实都写为子(a,b)同样。
它是一样的不是吗?
答案 2 :(得分:2)
请注意,我对Prolog的了解很久(而且从未如此深入)......
我认为你需要让父(或孩子)成为主要(不依赖于其他关系)。
child(X,Y):-
parent(Y,X).
parent(X,Y):-
child(Y,X).
可能导致循环。
答案 3 :(得分:0)
以下是事实和规则
couples(i,w).
mother_of(w,d).
father_of(f,i).
couples(f,d).
son_in_law(f,i).
mother_of(d,i).
mother_of(w,s1).
mother_of(d,s2).
grand(F,C):- son_in_law(F,C),couples(H,D),mother_of(D,C).
grand(F,C):- father_of(F,D),father_of(D,C).
查询
?-grand(i,i).