Reputation: 1429
I have an assignment to write a Prolog program that lists paths between two Underground (subway) stations, but it should favour the paths with less line changes (it should stay as long as possible in the same line before switching lines).
I've come up with a mock scenario and this code, while it correctly lists some paths (I know I still have to code the cycle detection), does not prioritise same-line segments as it should.
My router is:
route(X,Y,[drive(X,Y,L)],_) :- road(X,Y,L).
%route(From, To, Directions, Lines_Visited).
route(X,Y,[drive(X,Z,L)|R],Ls) :-
take(Ls,L,_), %prioritise same-line paths
road(X,Z,L),
route(Z,Y,R,Ls), !.
route(X,Y,[drive(X,Z,L)|R],Ls) :-
road(X,Z,L), %if no same-line pathes exist, try different line
route(Z,Y,R,[Ls|L]).
Where take/3 is
take([H|T], H, T).
One test scenario would be:
road(a,b,x).
road(b,c,x).
road(c,d,x).
road(d,e,x).
road(e,f,x).
road(b,f,y).
road(f,g,x).
%a - b - c - d - e - f - g
% |_______________|
If I try route(a,f,X). I'd get the path a -> b -> f , which changes lines once, and THEN the one-line path a->b->c->d->e->f.
Apparently my prioritisation is not working and I can't come up with a different way of doing it. Can someone please shed some light and point me to a direction to solve this more efficiently?
Upvotes: 1
Views: 348
Reputation: 60014
Your code need much restructuring. Basically, you're not using at all the info about which line is used in current path (take/3 is useless, since it doesn't bind the third argument). Here is my take on this. Add the loop detection, now that you have the 'seen so far' nodes...
%route(From, To, Directions, Lines_Visited).
route(X,X,RPath,Path) :- reverse(RPath,Path).
route(X,Y,[Last|R],Ls) :-
Last = [drive(X,Z,L)|_], %prioritise same-line paths
road(X,Z,L),
route(Z,Y,R,Ls).
route(X,Y,PathSoFar,Ls) :-
road(X,Z,L), %if no same-line pathes exist, try different line
route(Z,Y,[road(X,Z,L)|PathSoFar],Ls).
test:
?- route(a,f,[],X).
X = [road(a, b, x), road(b, c, x), road(c, d, x), road(d, e, x), road(e, f, x)] ;
X = [road(a, b, x), road(b, f, y)] ;
false.
Upvotes: 1