Tree 序言:查找从根树节点到指定节点的路径

Tree 序言:查找从根树节点到指定节点的路径,tree,prolog,Tree,Prolog,我有一棵树,例如: root(atom). node(atom, [cactus, butter]). node(butter, []). node(cactus, [home, tree, focus]). node(home, []). node(tree, []). node(focus, []). path(Start, Start, _, [Start]). path(Start, Destination, Visited, [Start|Nodes]) :- \+ mem

我有一棵树,例如:

root(atom).
node(atom, [cactus, butter]).
node(butter, []).
node(cactus, [home, tree, focus]).
node(home, []).
node(tree, []).
node(focus, []).
path(Start, Start, _, [Start]). 
path(Start, Destination, Visited, [Start|Nodes]) :-
    \+ member(Start, Visited),
    dif(Start, Destination),
    node(Start, [Node| _]), 
    path(Node, Destination, [Start|Visited], Nodes).
是否要为特定节点查找路径? 我怎样才能做到这一点

我有这样一个代码:

root(atom).
node(atom, [cactus, butter]).
node(butter, []).
node(cactus, [home, tree, focus]).
node(home, []).
node(tree, []).
node(focus, []).
path(Start, Start, _, [Start]). 
path(Start, Destination, Visited, [Start|Nodes]) :-
    \+ member(Start, Visited),
    dif(Start, Destination),
    node(Start, [Node| _]), 
    path(Node, Destination, [Start|Visited], Nodes).
但是如果只使用第一个子节点,则if仅对请求有效。 我的意思是: 为了

我明白了,这是绝对正确的

Path = [atom, cactus, home]
但如果我真的这样要求

?-path(atom, butter, Path).
我明白了

这显然是错误的。
我可以看到问题在哪里-它在这里
节点(开始,[node |)]
,但是没有一条线索来解决它以考虑所有子节点。

我的答案是:首先我需要path/3来运行查询,因为您定义了path/4:

path(Start, End, Path) :-
    path(Start, End, [], Path).
path/4中的参数3表示没有当前访问的节点

path(Start, Start, _, [Start]). 
path(Start, Destination, Visited, [Start|Nodes]) :-
    \+ member(Start, Visited),
    dif(Start, Destination),
    node(Start, Etc),
    member(Node, Etc),
    path(Node, Destination, [Start|Visited], Nodes).
为了允许path/4转到连接到起始节点的任何节点,我使用member/2。它声明Node是列表中的任何节点成员,等等

?- path(atom, butter, P).
P = [atom,butter]

以下是我的答案:首先我需要path/3来运行查询,因为您定义了path/4:

path(Start, End, Path) :-
    path(Start, End, [], Path).
path/4中的参数3表示没有当前访问的节点

path(Start, Start, _, [Start]). 
path(Start, Destination, Visited, [Start|Nodes]) :-
    \+ member(Start, Visited),
    dif(Start, Destination),
    node(Start, Etc),
    member(Node, Etc),
    path(Node, Destination, [Start|Visited], Nodes).
为了允许path/4转到连接到起始节点的任何节点,我使用member/2。它声明Node是列表中的任何节点成员,等等

?- path(atom, butter, P).
P = [atom,butter]

请参阅:memberchk性能更高,但存在问题memberchk/2不执行完整列表类型检查。我以后会进行优化。具体来说,
memberchk/2
的第一个参数始终是一个自由变量。在这种情况下,
memberchk/2
将与列表的第一个元素一起决定性地成功。如果从
Start
Destination
的唯一路径经过第一个元素以外的其他元素,则该版本将找不到它@我相信GuyCoder在这种情况下是错的。请看:memberchk性能更好,但也有问题memberchk/2不执行完整的列表类型检查。我以后会进行优化。具体来说,
memberchk/2
的第一个参数始终是一个自由变量。在这种情况下,
memberchk/2
将与列表的第一个元素一起决定性地成功。如果从
Start
Destination
的唯一路径经过第一个元素以外的其他元素,则该版本将找不到它@我相信GuyCoder在这件事上是错的。