Printing path in Prolog

我的未来我决定 提交于 2019-12-05 20:33:52

While @WouterBeek already pinpointed your problems, Wouter's statement

Without running this code you can already observe that the second clause will always fail, since a list of length 2 cannot be unified with a list of length 1

merits some elaboration. For an experienced Prolog programmer it is easy to spot such problems. But what can beginners do? They can apply the following technique: Generalize your program and if the generalized program is still too specialized, there must be an error in the remaining part.

Generalizing a pure Prolog program

There are several ways to generalize a pure Prolog program: Either remove goals, or remove subterms in arguments of the head or a goal. To remove goals, I will add a * in front of a goal, using:

:- op(950,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).

Now we can ask the most general query of this new predicate:

| ?- path(N1, N2, P).
P = [N1,N2] ? ;
no

Therefore: Although this definition is now an (over-) generalization, it still admits only paths of length 2. The problem is completely independent of the definition of edge/3, only the remaining part is responsible. So look at the remaining part to fix the problem!

In your second clause you have the following two statements:

append([Node1], [SomeNode], X),
append([], [Node2], X).

Notice that variable X occurs in both statements, and this must be instantiated to the same list. This means that [Node1]+[SomeNode] = []+[Node2] or [Node1,SomeNode]=[Node2].

Without running this code you can already observe that the second clause will always fail, since a list of length 2 cannot be unified with as a list of length 1.

Another point: the two clauses do not belong to the same predicate, since the former has arity 3 while the latter has arity 4. Typically, for calculating paths or arbitrary depth, you need a predicate that consists of two clauses that belong together: a base case and a recursive case. For the recursive case it is a common practice to use the head/tail notation to construct the path: [FromNode,ToNode|RestOfPath].

Hope this helps!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!