我正在尝试查找给定家庭的kth
代的所有家庭成员的列表。我们也得到了家庭的第一批成员和家谱。下面是我的KB相同和实现。我无法弄清楚如何获得这个家谱的kth
代?让我们说k = 4
。一种方法是我可以找到这样的关系的4倍:
4thGen(X,Y) :- parent(X,A),parent(A,B),parent(B,C),parent(C,Y)
但这不是我认为的正确方法。
male(alex).
male(romeo).
male(oscar).
male(peter).
male(bruno).
male(georg).
male(otto).
male(pascal).
male(jean).
female(lina).
female(julia).
female(rosa).
female(eva).
female(ruth).
female(silvia).
female(ida).
female(irma).
female(olga).
female(marie).
female(tina).
parent(alex,julia).
parent(alex,rosa).
parent(lina,julia).
parent(lina,rosa).
parent(romeo,peter).
parent(julia,peter).
parent(rosa,silvia).
parent(oscar,ida).
parent(eva,ida).
parent(eva,bruno).
parent(peter,bruno).
parent(peter,georg).
parent(peter,irma).
parent(ruth,georg).
parent(ruth,irma).
parent(silvia,otto).
parent(silvia,pascal).
parent(irma,olga).
parent(irma,jean).
parent(otto,olga).
parent(otto,jean).
parent(jean,tina).
parent(marie,tina).
father(X,Y):-parent(X,Y),male(X).
grandfather(X,Y):-father(X,Z),parent(Z,Y).
答案 0 :(得分:2)
为了制作更一般的谓词,你可以使用递归:
kthGen(X,Y,1):-parent(X,Y).
kthGen(X,Y,K) :- parent(X,A),K1 is K-1,kthGen(A,Y,K1).
以下是一些问题:
?- kthGen(alex,julia,1).
true ;
false.
?- kthGen(alex,peter,2).
true ;
false.
?- kthGen(alex,bruno,2).
false.
?- kthGen(alex,bruno,3).
true ;
false.
这里需要注意的两件重要事情:
parent(A,B)
如果您不能parent(B,A)
),这很重要,因为如果无向您可能会陷入周期(例如kthGen(alex,julia,4).
会因路径alex->julia->alex->julia
而成功,您可以通过添加另一个跟踪您访问过的人的列表来解决这个问题。其次,如果你尝试:
?- kthGen(alex,bruno,K).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [8] kthGen(alex,bruno,_7630)
ERROR: [7] <user>
因此谓词kthGen/3
没有关系行为。您可以使用库CLPFD:
:- use_module(library(clpfd)).
kthGen(X,Y,1):-parent(X,Y).
kthGen(X,Y,K) :- parent(X,A),K1 #= K-1,kthGen(A,Y,K1).
现在,如果你尝试:
?- kthGen(alex,bruno,K).
K = 3 ;
false
好多了!!。
<强>更新强>
为了从X人中找到第k代人,你可以相应地修改:
:- use_module(library(clpfd)).
kthGen(Y,1,[Y]).
kthGen(X,K,[X|T]) :- parent(X,A),K1 #= K-1,kthGen(A,K1,T).
示例:
?- kthGen(alex,4,L).
L = [alex, julia, peter, bruno] ;
L = [alex, julia, peter, georg] ;
L = [alex, julia, peter, irma] ;
L = [alex, rosa, silvia, otto] ;
L = [alex, rosa, silvia, pascal] ;
false.
这给了亚历克斯所有可能的第四代。如果你想找到更复杂的例如来自alex或lina的第4代,你可以单独找到它,写一个连接结果的另一个谓词......
更新2
在上次更新中,我会跟踪所有人,直到第4代。如果你想要第4代只需修改如下:
kthGen(Y,1,[Y]).
kthGen(X,K,L) :- parent(X,A),K1 #= K-1,kthGen(A,K1,L).
Examlpe:
?- kthGen(alex,4,L).
L = [bruno] ;
L = [georg] ;
L = [irma] ;
L = [otto] ;
L = [pascal] ;
false.
现在,如果您想将所有结果放在一个列表中:
?- findall(X,kthGen(alex,4,[X]),L).
L = [bruno, georg, irma, otto, pascal].