我想在有向图中打印节点的路径。 此代码适用于边缘但不适用于整个路径。 它在路径上返回false。 这是我的代码,但它只运行一个边缘,而不是整个路径。 请帮助我。
这是我的代码:
path(Node1, Node2, X) :-
edge(Node1, Node2),
append([Node1], [Node2], X).
path(Node1, Node2, X, N) :-
edge(Node1, SomeNode),
append([Node1], [SomeNode], X),
path(SomeNode, Node2, X, N),
append([], [Node2], X).
X
是一个列表。
答案 0 :(得分:4)
虽然@WouterBeek已经确定了你的问题,Wouter的陈述
如果不运行此代码,您可以观察到第二个子句将始终失败,因为长度为2的列表无法与长度为1的列表统一
值得一些阐述。对于经验丰富的Prolog程序员来说,很容易发现这些问题。但初学者可以做些什么呢?他们可以应用以下技术:概括你的程序,如果通用程序仍然过于专业化,那么其余部分必定存在错误。
有几种方法可以概括纯Prolog程序:删除目标,或删除头部或目标参数中的子项。要删除目标,我会在目标前添加*
,使用:
:- op(920,fy, *). *_. path(Node1, Node2, X) :- *edge(Node1, Node2), append([Node1], [Node2], X). path(Node1, Node2, X) :- *edge(Node1, SomeNode), append([Node1], [SomeNode], X), *path(SomeNode, Node2, X), append([], [Node2], X).
现在我们可以询问这个新谓词的最一般查询:
| ?- path(N1, N2, P).
P = [N1,N2] ? ;
no
因此:虽然这个定义现在是一个(过度)泛化,但它仍然只允许长度为2的路径。问题完全独立于edge/3
的定义,只有剩下的部分负责。所以看看剩下的部分来解决问题!
答案 1 :(得分:3)
在第二个条款中,您有以下两个陈述:
append([Node1], [SomeNode], X),
append([], [Node2], X).
请注意,变量X
出现在两个语句中,并且必须将其实例化到同一个列表中。这意味着[Node1]+[SomeNode] = []+[Node2]
或[Node1,SomeNode]=[Node2]
。
如果不运行此代码,您可以观察到第二个子句将始终失败,因为长度为2的列表无法与长度为1的列表统一。
另一点:这两个子句不属于同一个谓词,因为前者有arity 3而后者有arity 4.通常,为了计算路径或任意深度,你需要一个由属于两个子句组成的谓词在一起:一个基本案例和一个递归案例。对于递归情况,通常使用头/尾表示法来构造路径:[FromNode,ToNode|RestOfPath]
。
希望这有帮助!