Reputation: 576
I am stuck with the following Prolog question: Given the edges of a graph with no cycles as facts. e.g:
edge(a, b).
edge(b, c).
edge(c, d).
edge(c, e).
...
I have to write a predicate that tests whether there are two different paths between vertices X and Y. e.g the call two_paths(a, c).
should return true if there are two different paths from node a to node c. I know how to check whether there is a path between two vertices:
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
But how should I do this to check for two distinct paths? Thank you very much for your help.
Upvotes: 2
Views: 555
Reputation: 476503
An idea might be to create a predicate path/3
that returns the constructed path, and then query for two paths that are different. Something like:
path(X,Y,[X,Y]) :- edge(X,Y).
path(X,Y,[X|T]) :- edge(X,Z), path(Z,Y,T).
Now path(a,c,T)
will show you the path:
?- path(a,c,L).
L = [a, b, c] ;
false.
Now you could construct a predicate:
two_paths(X,Y) :-
path(X,Y,La),
path(X,Y,Lb),
dif(La,Lb).
In other words, you ask Prolog to construct for you a path La
, next construct for you a path Lb
and then check if they are not equal (dif(La,Lb)
). The first constructed Lb
will be equivalent to La
, but due to Prologs backtracking mechanism, it will try to construct you another path for which the condition might succeed. This is a rather pure Prolog implementation (with no cut (!
), once/1
, etc.). More efficient approaches exists since here you will "redo" the work in your second call.
A more efficient approach could be to construct a predicate path_avoid/3
(or path_avoid/4
) where you feed the first constructed path to the predicate and thus force your program to at least at some point perform a different step from the one presented. I leave this open as a potential exercise.
Upvotes: 5