Prolog中的打印路径

时间:2014-04-19 20:15:42

标签: prolog program-slicing

我想在有向图中打印节点的路径。 此代码适用于边缘但不适用于整个路径。 它在路径上返回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是一个列表。

2 个答案:

答案 0 :(得分:4)

虽然@WouterBeek已经确定了你的问题,Wouter的陈述

  

如果不运行此代码,您可以观察到第二个子句将始终失败,因为长度为2的列表无法与长度为1的列表统一

值得一些阐述。对于经验丰富的Prolog程序员来说,很容易发现这些问题。但初学者可以做些什么呢?他们可以应用以下技术:概括你的程序,如果通用程序仍然过于专业化,那么其余部分必定存在错误。

推广纯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]

希望这有帮助!