问题
I want to print the path of nodes in a directed graph. This code works properly for an edge but didn't work for the whole path. It returns false when it comes to path. Here is my code but it is only running for just an edge and not for the whole path. Kindly help me out.
Here is my code:
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
is a list.
回答1:
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!
回答2:
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!
来源:https://stackoverflow.com/questions/23174999/printing-path-in-prolog