[comp.lang.prolog] London Underground central area map in Prolog

ken@aiai.ed.ac.uk (Ken Johnson) (05/04/90)

THIS IS an interesting data set if you want to give your students a
``real'' programming problem.

FOLLOWUPS are directed to comp.lang.prolog. If you follow up, please
delete or replace the (LONG: 137 lines) in the title, as that will
no longer apply!

% Ken Johnson, 30-4-90
% London Underground system map. Central area only!
% Format is
% station(Name,X_coord,Y_coord,Line_set)

% X_coord and Y_coord are centimetres from the bottom left hand corner
% of the London Underground map and have little geographical
% significance.

% Line_set is a list of London Underground lines that pass through
% the Station. These are atoms, usually those used by LRT but sometimes
% extended to cope with branching (e.g. northern_west).

% Share and Enjoy. You may copy this code freely but if you sell copies
% at a profit I want a share.

station(acton_town,6,11,[piccadilly,district]).
station(aldgate,29.7,12.6,[circle]).
station(aldgate_east,31.8,12.6,[district,metropolitan]).
station(aldwych,23.8,12.6,[piccadilly_aldwych_branch]).
station(angel,26.1,16.4,[northern_west]).
station(baker_street,17.5,16.4,[metropolitan,circle,bakerloo,jubilee,
	metropolitan_amersham_branch]).
station(bank,27.4,14,[central,northern_city,subway_between_bank_and_monument]).
station(barbican,26.1,15.8,[circle,metropolitan]).
station(barons_court,11.3,10,[district,piccadilly]).
station(bayswater,13.6,14.5,[circle]).
station(bethnal_green,31.6,14,[central]).
station(blackfriars,25.2,11.2,[circle,district]).
station(bond_street,17.6,14,[central,jubilee]).
station(borough,25,8,[northern_west]).
station(camden_town,22.0,18.8,[northern_city,northern_west]).
station(cannon_street,26.6,11.2,[circle,district]).
station(chancery_lane,24.4,14,[central]).
station(charing_cross,22.0,11.2,[bakerloo,jubilee,northern_city]).
station(chiswick_park,6,10.2,[district]).
station(covent_garden,23,13.2,[piccadilly]).
station(ealing_broadway,4,14,[central,district]).
station(ealing_common,6,12.5,[piccadilly,district]).
station(earls_court,13,10,[district,district_exhibition_branch,piccadilly]).
station(east_acton,9,14,[central]).
station(edgware_road_bakerloo,14.7,16.3,[bakerloo]).
station(edgware_road_circle,15.6,16.4,[circle,metropolitan]).
station(elephant_and_castle,23.5,6.5,[bakerloo,northern_west]).
station(embankment,22,10,[bakerloo,circle,district,northern_city]).
station(euston,22.0,17.0,[northern_city,northern_west,victoria]).
station(euston_square,22.4,16.4,[circle,metropolitan]).
station(farringdon,25.2,15.8,[circle,metropolitan]).
station(finchley_road,16,18.4,[jubilee,metropolitan_amersham_branch]).
station(finsbury_park,28,20,[piccadilly,victoria]).
station(gloucester_road,14.5,10,[circle,district]).
station(goldhawk_road,10.6,12.4,[metropolitan]).
station(goodge_street,22,15,[northern_city]).
station(great_portland_street,19.7,16.4,[circle,metropolitan]).
station(green_park,19,12.5,[jubilee,piccadilly,victoria]).
station(hammersmith,10.4,10.0,[district,metropolitan,piccadilly]).
station(heathrow_terminal_4,1,6.8,[piccadilly]).
station(heathrow_terminals_1_2_3,1,7.6,[piccadilly]).
station(high_street_kensington,13.6,12.4,[circle]).
station(highbury_and_islington,27.2,17.5,[victoria]).
station(holborn,23.8,14,[central,piccadilly,piccadilly_aldwych_branch]).
station(holland_park,12.6,14,[central]).
station(hyde_park_corner,17.2,11.9,[piccadilly]).
station(kennington,22,5,[northern_city,northern_west]).
station(kensington_olympia,12.4,11.2,[district_exhibition_branch]).
station(kings_cross,24.0,16.4,[piccadilly,metropolitan,circle,
	northern_city,victoria]). 
station(knightsbridge,16.5,11.0,[piccadilly]).
station(ladbroke_grove,11.4,15.0,[metropolitan]).
station(lambeth_north,22.8,7.2,[bakerloo]).
station(lancaster_gate,15.8,14,[central]).
station(latimer_road,11.0,14.2,[metropolitan]).
station(leicester_square,22.0,12.5,[northern_city,piccadilly]).
station(liverpool_street,29.6,14.0,[central,circle,metropolitan]).
station(london_bridge,26.1,9,[northern_west]).
station(mansion_house,26,11.2,[circle,district]).
station(marble_arch,16.5,14,[central]).
station(marylebone,16.3,16.6,[bakerloo]).
station(mile_end,33.6,14,[central,district]).
station(monument,26.8,11.2,[circle,district,subway_between_bank_and_monument]).
station(moorgate,27.4,15.8,[circle,metropolitan,northern_west]).
station(mornington_crescent,22.0,18,[northern_city]).
station(neasden,13.4,21.8,[jubilee]).
station(north_acton,8,14,[central]).
station(notting_hill_gate,13.6,14,[central,circle]).
station(old_street,27.2,16.5,[northern_west]).
station(oval,21.5,4.2,[northern_city]).
station(oxford_circus,19.5,14,[bakerloo,central,victoria]).
station(paddington,14.0,16.4,[bakerloo,circle,metropolitan]).
station(piccadilly_circus,21.0,12.5,[bakerloo,piccadilly]).
station(pimlico,19,8.6,[victoria]).
station(queens_park,12,18.4,[bakerloo]).
station(queensway,14.8,14,[central]).
station(ravenscourt_park,9.8,10.2,[district]).
station(regents_park,19.3,16,[bakerloo]).
station(royal_oak,12.1,16.0,[metropolitan]).
station(russell_square,23.8,14.8,[piccadilly]).
station(shepherds_bush_central,11.5,14,[central]).
station(shepherds_bush_met,10.6,13.5,[metropolitan]).
station(sloane_square,15.3,10,[circle,district]).
station(south_kensington,15.6,10,[circle,district,piccadilly]).
station(st_james_park,20,10,[circle,district]).
station(st_pauls,26.1,14,[central]).
station(stamford_brook,8.3,10.2,[district]).
station(stockwell,21,4,[northern_city,victoria]).
station(stratford,33,16.4,[central]).
station(temple,24.1,10.4,[circle,district]).
station(tottenham_court_road,22,14,[central,northern_city]).
station(tower_hill,28.8,11.2,[circle,district]).
station(turnham_green,7,10,[piccadilly,district]).
station(vauxhall,19,7,[victoria]).
station(victoria,19,10,[circle,district,victoria]).
station(warren_street,22.0,16.0,[northern_city,victoria]).
station(waterloo,22,8.3,[bakerloo,northern_city,waterloo_and_city]).
station(west_acton,7,14,[central]).
station(west_kensington,12,10,[district]).
station(westbourne_park,11.8,15.5,[metropolitan]).
station(westminster,21.2,10,[circle,district]).
station(white_city,9.9,14,[central]).
station(whitechapel,32.4,13.0,[district,metropolitan]).
-- 
Ken Johnson, AI Applications Institute, 80 South Bridge, Edinburgh EH1 1HN
E-mail ken@aiai.ed.ac.uk, phone 031-225 4464 extension 212
`I have read your article, Mr Johnson, and I am no wiser now than when I
started'.  -- `Possibly not, sir, but far better informed.'

ok@goanna.cs.rmit.OZ.AU (Richard A. O'Keefe) (05/05/90)

In article <2371@skye.ed.ac.uk>, ken@aiai.ed.ac.uk (Ken Johnson) writes:
> THIS IS an interesting data set if you want to give your students a
> ``real'' programming problem.

Ken Johnson is one of my favourite people, and it's nice to have good
examples to play with, _BUT_

The tuples in his data base have the form
	> % station(Name, X_coord, Y_coord, Lines)
 
	> % X_coord and Y_coord are centimetres from the bottom left hand
	> % corner of the London Underground map and have little
	> % geographical significance.

	> % Lines is a list of London Underground lines that pass through
	> % the Station.

The first thing that hits a Codd fan in the eye is that this relation is
not in 1st Normal Form:  the Lines attribute is not atomic with respect to
likely applications (e.g. if one wants to know whether two stations are on
the same line, and if so which).

But that was actually the second thing that hit me.  The first thing that
_really_ hit was "I can't use this".  I have often travelled on the London
underground, and the two questions I have been vitally concerned with are
    (1) how many stops before I get off?
    (2) where should I change?
Basically, the kind of information you need for this is "how are the
stations connected".

It seems to me that a better structure for this data base would be

	station(StationName, X, Y).
	-- StationName is the name of a station at (X,Y) on the map.

	line(FromStation, ToStation, LineName)
	-- you can get from FromStation to ToStation in one step
	-- by travelling along the line called LineName

Then one could define

	station_line(Station, Line) :-
		line(Station, _, Line).
	station_line(Station, Line) :-
		line(_, Station, Line).

	kj_station(Station, X, Y, Lines) :-
		station(Station, X, Y),
		setof(Line, station_line(Station,Line), Lines).

A richer data base for the London underground would also include
the fares, or rather the zoning structure underlying the fares.
I've forgotten how that would go for London.  In Melbourne the
fare structure for the Met would go something like

	station_zone(Station, /* -> */ Zone /* 1, 2, or 3 */).

	zone_card(FromZone, ToZone, CardType).
	-- you can travel from FromZone to ToZone if you hold a
	-- current card of type CardType (e.g. '2/1 weekly')
	-- This is symmetric in FromZone, ToZone

	card_price(CardType, /* -> */ Price).

aipdc@castle.ed.ac.uk (Paul D. Crowley) (05/06/90)

ok@goanna.cs.rmit.OZ.AU (Richard A. O'Keefe) sez in <3155@goanna.cs.rmit.OZ.AU>
>In article <2371@skye.ed.ac.uk>, ken@aiai.ed.ac.uk (Ken Johnson) writes:
[Ken writes about a Prolog database detailing the structure of the
London Underground]
[Richard points out faults]
>It seems to me that a better structure for this data base would be
[map info]
>	line(FromStation, ToStation, LineName)
>	-- you can get from FromStation to ToStation in one step
>	-- by travelling along the line called LineName

Probs: one part of the Central Line looks like this:

                                South Woodford
                       ----- *-----*--...
        Leytonstone   / Snaresbrook
...--*-----*---------<
   Leyton             \ Wanstead
                       ----*-----*--...
                              Redbridge

In the database this looks like:

line(leyton,leytonstone,central).
line(leytonstone,snaresbrook,central).
line(leytonstone,wanstead,central).
line(snaresbrook,south_woodford,central).
line(wanstead,redbridge,central).

However if you want to get from Wanstead to Snaresbrook you have to
change at Leytonstone.

Or look at Epping, where there's a capacitor-like symbol.   Or Monument
and Bank, which are connected by escalator.

The Underground has quite a few special cases waiting to foul up such a
program.

Such a program will need a concept of "Epping trains" and "Hainault via
Newbury Park trains" and "Peak Hours only" and "Westbound" in order to
be really useful. 

(A few thoughts from a Londoner who lives in South Woodford and so has
to think about these things.)
-- 
\/ o\ Paul Crowley aipdc@uk.ac.ed.castle                       :-| Have a day
/\__/ "The whole is the sum of its parts, plus one or more bugs" aimsm@castle