Reputation: 195
I am writing the following code and is giving perfect results.
edge(s,a,300).
edge(s,d,20).
edge(a,d,400).
edge(a,b,1500).
edge(b,c,9).
edge(b,e,200).
edge(c,d,2000).
edge(c,g,12).
edge(d,e,3).
edge(e,f,400).
edge(f,g,800).
connected(X,Y,D) :- edge(X,Y,D) ; edge(Y,X,D).
path(A,B,D,Path) :-
travel(A,B,D,[A],Q),
reverse(Q,Path).
travel(A,B,D,P,[B|P]) :-
connected(A,B,D).
travel(A,B,D,Visited,Path) :-
connected(A,X,D1),
X \== B,
\+member(X,Visited),
D2 is D - D1,
travel(X,B,D2,[X|Visited],Path).
Here if I query like
| ?- path(s,e,23,P).
P = [s,d,e] ? ;
no
| ?-
I do get the correct response. But no I wish to get the results for a D<50, say. How to do?
Upvotes: 2
Views: 801
Reputation: 60014
You should let Prolog compute the distance D as well as the Path:
travel(A,B,D,Visited,Path) :-
connected(A,X,D1),
X \== B,
\+member(X,Visited),
travel(X,B,D2,[X|Visited],Path),
D is D2 + D1.
Then you can query it
?- path(Start, Stop, D, P), D < 50.
and will get (on backtracking) all paths with D < 50.
?- path(s,e,X,P),X<50.
X = 23,
P = [s, d, e] ;
false.
Upvotes: 2
Reputation: 22585
Although I think finite domain constraints are the best to use here, you can achieve what you want with a minor modification to your code.
In the first clause of travel/5
instead of unifying input argument D
with the third argument of connected/3
, you can use a fresh variable and then check to see whether your current distance (D
) is larger or equal to this new variable.
travel(A,B,D,P,[B|P]) :-
connected(A,B,TD),
D >= TD.
Upvotes: 1
Reputation: 7402
Arithmetic expressions are kind of a special case in Prolog, and not expected to work with unbound arguments, so you cannot simply ask for path(s,e,D,P), D < 50
, because the is
-clause needs all its right-hand side arguments instantiated.
You can use the finite domain (FD) constraint extensions for Prolog (e.g. in GNU Prolog): just change your is
to the FD-equivalent #=
, and ask:
/Users/stolz/test.pl compiled, 27 lines read - 3180 bytes written, 8 ms
| ?- fd_domain(D,0,50), path(s,e,D,P).
D = 23
P = [s,d,e] ? ;
no
Upvotes: 4