我正在用序言为一个家庭编程,而我侄子的实施遇到了麻烦。当我询问erick是否是Alberto的侄子时,它返回true,当它应该返回false时(因为Alberto是erick的父亲),但是,它在所有其他应该为true的情况下都有效。如果有人可以帮助我,我将不胜感激。
我的代码:
man(beto).
man(fransisco).
man(alberto).
man(jaime).
man(manolo).
man(nolo).
man(lito).
man(manuel).
man(erick).
man(jesu).
man(jesus).
woman(emi).
woman(harumi).
woman(haru).
woman(yuneisi).
woman(yasmeli).
woman(mioara).
woman(elia).
woman(iza).
woman(alice).
woman(ofelia).
woman(arlet).
parent(manuel, alberto).
parent(ofelia, alberto).
parent(manuel, jaime).
parent(ofelia, jaime).
parent(manuel, manolo).
parent(ofelia, manolo).
parent(alberto, erick).
parent(alberto, beto).
parent(alberto, fransisco).
parent(emi, erick).
parent(emi, beto).
parent(manolo, nolo).
parent(manolo, arlet).
parent(nolo, lito).
parent(iza, lito).
parent(mioara, yuneisi).
parent(mioara, yasmeli).
parent(jaime, yuneisi).
parent(jaime, yasmeli).
parent(jesus_padre, jesu)
parent(jesus_padre, alice).
parent(jesus_padre, haru).
parent(harumi, haru).
parent(harumi, jesu).
parent(harumi, alice).
father(X,Y) :- parent(X,Y), man(X).
mother(X,Y) :- parent(X,Y), woman(X).
brother(X,Y) :- man(X), parent(F, X), parent(F, Y).
sister(X,Y) :- woman(X), parent(P, X), parent(P, Y).
grandpa(X,Y) :- father(F,Y), father(X,F), man(X).
grandma(X,Y) :- father(F,Y), mother(X,F), woman(X).
son(X,Y) :- father(Y,X), man(X).
nephew(X,Y) :- father(F,X), brother(F,Y).
最佳答案
除了@LuaiGhunim指出的parent(jesus_padre, jesu)
之后缺少的点外,谓词还存在其他一些问题。您对brother / 2的定义太笼统了。没有人是他自己的兄弟,但是如果您查询谓词,则会发现以下几种实例:
?- brother(X,X).
X = beto ;
X = beto ;
X = fransisco ;
X = alberto ;
X = alberto ;
X = jaime ;
X = jaime ;
X = manolo ;
X = manolo ;
X = nolo ;
X = lito ;
X = lito ;
X = erick ;
X = erick ;
X = jesu ;
X = jesu ;
false.
您可以通过添加目标dif / 2轻松地解决此问题:
brother(X,Y) :-
dif(X,Y),
man(X),
parent(F, X),
parent(F, Y).
现在上面的查询失败了,应该这样:
?- brother(X,X).
false.
您仍然会两次获得很多配对:
?- brother(X,Y).
X = beto, % <- 1st occurrence
Y = erick ; % <- 1st occurrence
X = beto,
Y = fransisco ;
X = beto, % <- 2nd occurrence
Y = erick ; % <- 2nd occurrence
.
.
.
这样做的原因是您可以通过母亲或父亲来获得它。在上面的示例(
beto
和erick
)中,您将通过emi
或alberto
到达那里。这些解决方案可能是多余的,但它们是正确的。谓词姐姐/ 2也是如此:?- sister(X,X).
X = haru ;
X = haru ;
X = yuneisi ;
X = yuneisi ;
X = yasmeli ;
X = yasmeli ;
X = alice ;
X = alice ;
X = arlet.
补救措施与以上相同:
sister(X,Y) :-
dif(X,Y),
woman(X),
parent(P, X),
parent(P, Y).
?- sister(X,X).
false.
?- sister(X,Y).
X = haru,
Y = jesu ;
X = haru,
Y = alice ;
X = haru,
Y = jesu ;
.
.
.
另一方面,您对grandma / 2和grandpa / 2的定义过于具体。为了看到这一点,让我们在代码中添加以下事实:
man(m1).
man(m2).
woman(w1).
woman(w2).
woman(w3).
parent(m1,w1).
parent(w1,w2).
parent(w2,w3).
然后,以下查询应该成功,但失败了:
?- grandpa(m1,w2).
false.
?- grandma(w1,w3).
false.
这样做的原因是,在您的grandpa / 2和grandma / 2定义中,中间父母是父亲/ 2,而父亲应该是父母/ 2。另外,最后一个目标(
man(X)
和woman(X)
)是多余的,因为它们已经分别被父亲/ 2和母亲/ 2覆盖。相反,您可以这样定义两个谓词:grandpa(X,Y) :-
parent(F,Y),
father(X,F).
grandma(X,Y) :-
parent(F,Y),
mother(X,F).
现在,以上查询产生了所需的结果:
?- grandpa(m1,w2).
true.
?- grandma(w1,w3).
true.
最后,根据Cambridge Dictionary的侄子是您姐姐或兄弟的儿子,或者是您丈夫或妻子的姐姐或兄弟的儿子。由于您没有丈夫和妻子的谓词,因此我会坚持您姐姐或兄弟的儿子。如果为丈夫和妻子添加事实,则可以添加其他规则来覆盖定义的其他部分。您可以像下面这样在Prolog中编写定义的第一部分:
nephew(X,Y) :-
man(X),
dif(F,Y),
parent(P,F),
parent(P,Y),
parent(F,X).
如果您查询此谓词,则不再有erick / alberto解决方案:
?- nephew(erick,X).
X = jaime ;
X = manolo ;
X = jaime ;
X = manolo ;
false.