List 在Prolog中递归创建子体列表

List 在Prolog中递归创建子体列表,list,recursion,prolog,append,List,Recursion,Prolog,Append,我对Prolog真的是个新手,正在努力递归地附加到列表中。我试图创建一个程序,告诉你一个人是否是另一个人的后代,以及他们之间的后代列表。例如,示例数据和所需输出: parent(greatgrandma, grandma). parent(grandma, mom). parent(mom, daughter). ?- relatives(greatgrandma, daughter, Lineage). Lineage = [greatgrandma, grandma, mom, daugh

我对Prolog真的是个新手,正在努力递归地附加到列表中。我试图创建一个程序,告诉你一个人是否是另一个人的后代,以及他们之间的后代列表。例如,示例数据和所需输出:

parent(greatgrandma, grandma).
parent(grandma, mom).
parent(mom, daughter).

?- relatives(greatgrandma, daughter, Lineage).
Lineage = [greatgrandma, grandma, mom, daughter]

?- relatives(mom, son, Lineage).
False.
我能够递归搜索以检查两个人是否与以下代码相关,并将其作为测试用例使用

relatives(X, Y, Lineage):- isChild(X,Y, Lineage).
isChild(X,Y, Lineage):- parent(X,Y), append([X], [Y], Lineage).
isChild(X,Y, Lineage):- parent(X,Z), isChild(Z,Y, Lineage).
但是,到目前为止,我试图从这个子代搜索构建一个列表的所有方法都没有奏效。这是我得到的最接近的结果:

relatives(X, Y, Lineage):- append([X], Lineage, NewLineage), isChild(X,Y, NewLineage).
isChild(X,Y, Lineage):- parent(X,Z), append(Lineage, [Z], NewLineage), isChild(Z,Y, NewLineage).
isChild(X,Y, Lineage):- parent(X,Y), append(Lineage, [Y], NewLineage).
因此,我得到的列表的顺序是正确的[奶奶,妈妈,女儿],但我不知道如何将其返回为p值,而不是空列表。此外,使用“son”的测试会导致使用此代码的无休止的递归循环,但与前面的基本情况不同


任何帮助或建议都将不胜感激。

很接近!如果您想使用这种方法,那么缺少的主要内容是以下观察:如果
isChild
都接受“当前沿袭”,并且预期将产生“新沿袭”,那么它需要两个沿袭参数。一个是“旧”州,一个是“新”州

像这样:

isChild(X,Y, Lineage, NewLineage) :-
    parent(X,Z),
    append(Lineage, [Z], Lineage2),
    isChild(Z,Y, Lineage2, NewLineage).
isChild(X,Y, Lineage, NewLineage) :-
    parent(X,Y),
    append(Lineage, [Y], NewLineage).
调用此函数时,您需要传入正确的初始沿袭来开始:

relatives(X, Y, Lineage) :-
    isChild(X,Y, [X], Lineage).
现在,它的行为符合您的要求:

?- relatives(grandma, daughter, Lineage).
Lineage = [grandma, mom, daughter] ;
false.

?- relatives(mom, son, Lineage).
false.
然而,真正的答案是,在Prolog中进行此类搜索时,通常不会将内容附加到列表中。相反,您需要预先添加数据。这样做效率更高,而且更短,可读性更强,中间状态更少:

ancestor_successor_lineage(Ancestor, Successor, [Ancestor, Successor]) :-
    parent(Ancestor, Successor).
ancestor_successor_lineage(Ancestor, Successor, [Ancestor | Lineage]) :-
    parent(Ancestor, Intermediate),
    ancestor_successor_lineage(Intermediate, Successor, Lineage).
请注意,这与您在对血统不感兴趣的情况下编写的内容基本相同。添加中间状态的记录只需添加一个(而不是像以前那样添加两个!)额外参数,并使用列表构造函数
[\u124;|]
将父级
的“单步”与递归步骤中的列表相结合。这确实是在Prolog中编写这篇文章的首选方法

其行为与其他解决方案相同:

?- ancestor_successor_lineage(grandma, daughter, Lineage).
Lineage = [grandma, mom, daughter] ;
false.

?- ancestor_successor_lineage(mom, son, Lineage).
false.
?- ancestor_successor_lineage(grandma, daughter, Lineage).
Lineage = [grandma, mom, daughter] ;
false.

?- ancestor_successor_lineage(mom, son, Lineage).
false.