0

Sorry, I know this question comes up a lot but I've done so much research and I just can't figure out how to solve this problem. I have represented a tube map in PROLOG and need to write a predicate that returns all routes between two stations. I know I need to use recursion and have tried a bunch of different solutions but none are working. The facts I have are:

station('AL',[metropolitan]).%Aldgate on the Metropolitan Line
station('BG',[central]).%Bethnal Green on the Central Line
station('BR',[victoria]).%Brixton on the Victoria Line
station('BS',[metropolitan]).%Baker Street on the Metropolitan Line
station('CL',[central]).%Chancery Lane on the Central Line
station('EC',[bakerloo]).%Elephant & Castle on the Bakerloo Line
station('EM',[bakerloo,northern]).%Embankment on the Bakerloo and Northern Lines
station('EU',[northern]).%Euston on the Northern Line
station('FP',[victoria]).%Finsbury Park on the Victoria Line
station('FR',[metropolitan]).%Finchley Road on the Metropolitan Line
station('KE',[northern]).%Kennington on the Northern Line
station('KX',[metropolitan,victoria]).%Kings Cross on the Metropolitan and Victoria Lines
station('LG',[central]).%Lancaster Gate on the Central Line
station('LS',[central,metropolitan]).%Liverpool Street on the Central and Metropolitan Lines
station('NH',[central]).%Notting Hill Gate on the Central Line
station('OC',[bakerloo,central,victoria]).%Oxford Circus on the Bakerloo, Central and Victoria Lines
station('PA',[bakerloo]).%Paddington on the Bakerloo Line
station('TC',[central,northern]).%Tottenham Court Road on the Central and Northern Lines
station('VI',[victoria]).%Victoria on the Victoria Line
station('WA',[bakerloo]).%Warwick Avenue on the Bakerloo Line
station('WS',[northern,victoria]).%Warren Street on the Northern and Victoria Lines
adjacent('WA','PA').%Warwick Avenue is adjacent to Paddington
adjacent('PA','OC').%Paddington is adjacent to Oxford Circus
adjacent('OC','EM').%Oxford Circus is adjacent to Embankment
adjacent('EM','EC').%Embankment is adjacent to Elephant & Castle
adjacent('NH','LG').%Notting Hill Gate is adjacent to Lancaster Gate
adjacent('LG','OC').%Lancaster Gate is adjacent to Oxford Circus
adjacent('OC','TC').%Oxford Circus is adjacent to Tottenham Court Road
adjacent('TC','CL').%Tottenham Court Road is adjacent to Chancery Lane
adjacent('CL','LS').%Chancery Lane is adjacent to Lviverpool Street
adjacent('LS','BG').%Liverpool Street is adjacent to Bethnal Green
adjacent('FR','BS').%Finchley Road is adjacent to Baker Street
adjacent('BS','KX').%Baker Street is adjacent to Kings Cross
adjacent('KX','LS').%Kings Cross is adjacent to Liverpool Street
adjacent('LS','AL').%Liverpool Street is adjacent to Algate
adjacent('EU','WS').%Euston is adjacent Warren Street
adjacent('WS','TC').%Warren Street is adjacent to Tottenham Court Road
adjacent('TC','EM').%Tottenham Court Road is adjacent to Embankment
adjacent('EM','KE').%Embankment is adjacent to Kennington
adjacent('BR','VI').%Brixton is adjacent to Victoria
adjacent('VI','OC').%Victoria is adjacent to Oxford Circus
adjacent('OC','WS').%Oxford Circus is adjacent to Warren Street
adjacent('WS','KX').%Warrent Street is adjacent to Kings Cross
adjacent('KX','FP').%Kings Cross is adjacent to Finsbury Park

And the solution I have tried is:

route(From,To,Route) :-
   routeattempt(From,To,[From],Route),
   reverse(Route,route).

routeattempt(From,To,Inbetween,Route) :-
   adjacent(From,To),
   \+member(From,Inbetween),
   Route = [From|Inbetween].
routeattempt(From,To,Visited,Route) :-
   adjacent(From,Inbetween),
   Inbetween \== To,
   \+member(Inbetween,Visited),
   routeattempt(Inbetween,To,Inbetween|Visited],Route).

But it just returns false to any input. If anyone could help that would be great.

false
  • 10,264
  • 13
  • 101
  • 209
  • The third line of the route/2 predicate says `reverse(Route,route).` That can't be right, the second `route` is a constant. You want to reverse `Route` into the output, so you need a `RouteOut` that appears in the output here. – David Tonhofer Mar 16 '20 at 03:27
  • There is also a syntax error in the last line: `routeattempt(Inbetween,To,Inbetween|Visited],Route).` has an unclosed list ternm – David Tonhofer Mar 16 '20 at 03:47
  • Also, put the comments "%Aldgate on the Metropolitan Line" as values into the facts: `station('FR',[metropolitan], "Finchley Road on the Metropolitan Line")`. then you can use them when printing later. At this point, nothing of `station/2` is used at all of course. – David Tonhofer Mar 16 '20 at 03:56

1 Answers1

0

This is confused.

In

route(From,To,Route) :-
   routeattempt(From,To,[From],Route),
   reverse(Route,route).

the idea is clearly for routeattempt/4 to "find a route from From to To to be stored as a list of stations in Route. But what does argument 3, here [From] do exactly? It seems to be the list of visited stations, but do your really need it? You have Route already.

Now you have to subcases: either From or To are adjacent:

routeattempt(From,To,Inbetween,Route) :-
   adjacent(From,To),
   \+member(From,Inbetween),
   Route = [From|Inbetween].

or they are are not:

routeattempt(From,To,Visited,Route) :-
   adjacent(From,Inbetween),
   Inbetween \== To,
   \+member(Inbetween,Visited),
   routeattempt(Inbetween,To,Inbetween|Visited],Route).

In the first case (the base case), it is unclear why to check whether From is a member of Inbetween. Indeed, this will preclude finding any route between between two adjacent stations, because route/3 will already have deposited From into the list Inbetween. And shouldn't the route between two adjacent stations not just be [From,To] instead of [From|Inbetween]?

In the second case, you go from From to To by waystation Inbetween, which is also not equal to To, and has not been visited yet. Okay. But you need to complete Route after the recursive call.

Try add a format("Current route from ~w to ~w: ~w\n", [From, To, Route]) before adjacent/2 and see what happens.

David Tonhofer
  • 14,559
  • 5
  • 55
  • 51