2001-06-06 21:07:01 +01:00
|
|
|
|
|
|
|
:- object(salesman).
|
|
|
|
|
2005-12-24 18:00:21 +00:00
|
|
|
:- info([
|
|
|
|
author is 'Paulo Moura',
|
|
|
|
version is 1.0,
|
|
|
|
date is 2000/4/22,
|
|
|
|
comment is '.',
|
|
|
|
source is 'Example adopted from the Francis G. McCabe L&O documentation.']).
|
|
|
|
|
|
|
|
:- public(route/2).
|
|
|
|
:- mode(route(+list, -nonvar), zero_or_more).
|
|
|
|
|
|
|
|
:- end_object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:- object(circular,
|
|
|
|
extends(salesman)).
|
2001-06-06 21:07:01 +01:00
|
|
|
|
|
|
|
:- info([
|
2003-02-05 00:15:28 +00:00
|
|
|
author is 'Paulo Moura',
|
2001-06-06 21:07:01 +01:00
|
|
|
version is 1.0,
|
|
|
|
date is 2000/4/22,
|
|
|
|
comment is '.',
|
|
|
|
source is 'Example adopted from the Francis G. McCabe L&O documentation.']).
|
|
|
|
|
2005-12-24 18:00:21 +00:00
|
|
|
route([Town| Towns], Route) :-
|
|
|
|
route(Towns, Town-Town, Route).
|
2001-06-06 21:07:01 +01:00
|
|
|
|
2005-12-24 18:00:21 +00:00
|
|
|
route([], Route, Route).
|
|
|
|
route([Town| Towns], Route, Route2) :-
|
|
|
|
best_place(Route, Town, Best),
|
|
|
|
split(Best, Route, Town, Split),
|
|
|
|
route(Towns, Split, Route2).
|
2001-06-06 21:07:01 +01:00
|
|
|
|
2005-12-24 18:00:21 +00:00
|
|
|
best_place(Route, Town, Best) :-
|
|
|
|
best_place(Route, Town, 10000000, 0, 0, Best).
|
2001-06-06 21:07:01 +01:00
|
|
|
|
2005-12-24 18:00:21 +00:00
|
|
|
best_place(R-T1-T2, Town, XD, _, I, Best) :-
|
|
|
|
atom(T1),
|
|
|
|
atom(T2),
|
|
|
|
extra(T1, Town, T2, XT),
|
|
|
|
XT < XD,
|
|
|
|
I2 is I + 1,
|
|
|
|
best_place(R-T1, Town, XT, I2, I2, Best).
|
|
|
|
best_place(R-T1-T2, Town, XD, XI, I, Best) :-
|
|
|
|
atom(T1),
|
|
|
|
atom(T2),
|
|
|
|
I2 is I + 1,
|
|
|
|
best_place(R-T1, Town, XD, XI, I2, Best).
|
|
|
|
best_place(T1-T2, Town, XD, _, I, Best) :-
|
|
|
|
atom(T1),
|
|
|
|
atom(T2),
|
|
|
|
extra(T1, Town, T2, XT),
|
|
|
|
XT < XD,
|
|
|
|
Best is I + 1.
|
|
|
|
best_place(_-_, _, _, XI, _, XI).
|
|
|
|
|
|
|
|
split(0, Route, Town, Route-Town).
|
|
|
|
split(IX, Route-Town1, Town, Split-Town1) :-
|
|
|
|
IX2 is IX - 1,
|
|
|
|
split(IX2, Route, Town, Split).
|
|
|
|
split(1, Route, Town, Town-Route).
|
|
|
|
|
|
|
|
extra(T1, T, T2, E) :-
|
|
|
|
T1::crow_flies(T, E1),
|
|
|
|
T::crow_flies(T2, E2),
|
|
|
|
T1::crow_flies(T2, E3),
|
|
|
|
E is E1 + E2 - E3.
|
|
|
|
|
|
|
|
:- end_object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:- object(incremental,
|
|
|
|
extends(salesman)).
|
|
|
|
|
|
|
|
:- info([
|
|
|
|
author is 'Paulo Moura',
|
|
|
|
version is 1.0,
|
|
|
|
date is 2000/4/22,
|
|
|
|
comment is '.',
|
|
|
|
source is 'Example adopted from the Francis G. McCabe L&O documentation.']).
|
|
|
|
|
|
|
|
route([Town| Towns], Route) :-
|
|
|
|
route(Towns, Town, Route).
|
|
|
|
|
|
|
|
route([], Route, Route).
|
|
|
|
route([Town| Towns], Route, Route2) :-
|
|
|
|
best_place(Route, Town, Best),
|
|
|
|
split(Best, Route, Town, NewR),
|
|
|
|
route(Towns, NewR, Route2).
|
|
|
|
|
|
|
|
best_place(Route-Town1, Town, Best) :- % try the back first ...
|
|
|
|
atom(Town1),
|
|
|
|
Town::crow_flies(Town1, Distance),
|
|
|
|
best_place(Route-Town1, Town, Distance, 0, 0, Best).
|
|
|
|
best_place(Town, _, 0) :-
|
|
|
|
atom(Town).
|
|
|
|
|
|
|
|
best_place(R-T1-T2, T, XD, _, I, Best) :-
|
|
|
|
atom(T1),
|
|
|
|
atom(T2),
|
|
|
|
extra(T1, T, T2, XT),
|
|
|
|
XT < XD,
|
|
|
|
I2 is I + 1,
|
|
|
|
best_place(R-T1, T, XT, I2, I2, Best).
|
|
|
|
best_place(R-T1-T2, T, XD, XI, I, Best) :-
|
|
|
|
atom(T1),
|
|
|
|
atom(T2),
|
|
|
|
I2 is I + 1,
|
|
|
|
best_place(R-T1, T, XD, XI, I2, Best).
|
|
|
|
best_place(T1-T2, T, XD, _, I, Best) :-
|
|
|
|
atom(T1),
|
|
|
|
atom(T2),
|
|
|
|
extra(T1, T, T2, XT),
|
|
|
|
XT < XD,
|
|
|
|
I2 is I + 1,
|
|
|
|
best_place(T1, T, XT, I2, I2, Best).
|
|
|
|
best_place(T1-T2, T, XD, XI, I, Best) :-
|
|
|
|
atom(T1),
|
|
|
|
atom(T2),
|
|
|
|
I2 is I + 1,
|
|
|
|
best_place(T1, T, XD, XI, I2, Best).
|
|
|
|
best_place(T1, T, XD, _, I, Best) :-
|
|
|
|
atom(T1),
|
|
|
|
T1::crow_flies(T, Distance),
|
|
|
|
Distance < XD,
|
|
|
|
Best is I + 1.
|
|
|
|
best_place(_, _, _, XI, _, XI).
|
|
|
|
|
|
|
|
split(0, Route, Town, Route-Town).
|
|
|
|
split(IX, Route-Town1, Town, S-Town1) :-
|
|
|
|
IX2 is IX -1,
|
|
|
|
split(IX2, Route, Town, S).
|
|
|
|
split(1, Route, Town, Town-Route).
|
|
|
|
|
|
|
|
extra(T1, T, T2, XT) :-
|
|
|
|
T1::crow_flies(T, Distance1),
|
|
|
|
T::crow_flies(T2, Distance2),
|
|
|
|
T1::crow_flies(T2, Distance3),
|
|
|
|
XT is Distance1 + Distance2 - Distance3.
|
|
|
|
|
|
|
|
:- end_object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:- object(presort,
|
|
|
|
extends(incremental)).
|
|
|
|
|
|
|
|
:- info([
|
|
|
|
author is 'Paulo Moura',
|
|
|
|
version is 1.0,
|
|
|
|
date is 2000/4/22,
|
|
|
|
comment is '.',
|
|
|
|
source is 'Example adopted from the Francis G. McCabe L&O documentation.']).
|
|
|
|
|
|
|
|
:- uses(quick(_)).
|
|
|
|
|
|
|
|
route(Towns, Route) :-
|
|
|
|
arrange(Towns, Towns2),
|
|
|
|
^^route(Towns2, Route).
|
|
|
|
|
|
|
|
arrange(Towns, Sorted) :-
|
|
|
|
centre(Towns, X, Y),
|
|
|
|
quick(geographic(X, Y))::sort(Towns, Sorted).
|
|
|
|
|
|
|
|
centre(Towns, X, Y) :-
|
|
|
|
average(Towns, 0, 0, U, V, 0, L),
|
|
|
|
X is U/L,
|
|
|
|
Y is V/L.
|
|
|
|
|
|
|
|
average([], U, V, U, V, L, L).
|
|
|
|
average([Town| Towns], UX, VX, U, V, I, L):-
|
|
|
|
Town::at(UT, VT),
|
|
|
|
UX2 is UX+UT,
|
|
|
|
VX2 is VX+VT,
|
|
|
|
I2 is I + 1,
|
|
|
|
average(Towns, UX2, VX2, U, V, I2, L).
|
|
|
|
|
|
|
|
:- end_object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:- object(driving,
|
|
|
|
extends(salesman)).
|
|
|
|
|
|
|
|
:- info([
|
|
|
|
author is 'Paulo Moura',
|
|
|
|
version is 1.0,
|
|
|
|
date is 2000/4/22,
|
|
|
|
comment is '.',
|
|
|
|
source is 'Example adopted from the Francis G. McCabe L&O documentation.']).
|
|
|
|
|
|
|
|
route(Towns, Route) :-
|
|
|
|
presort::route(Towns, Presort),
|
|
|
|
drive_around(Presort, Route).
|
|
|
|
|
|
|
|
drive_around(Route-Town1-Town2, Route1-Route2) :-
|
|
|
|
!,
|
|
|
|
drive_around(Route-Town1, Route1),
|
|
|
|
Town1::drive(Town2, Route2).
|
|
|
|
drive_around(Town1-Town2, Route) :-
|
|
|
|
!,
|
|
|
|
Town1::drive(Town2, Route).
|
|
|
|
drive_around(Town, Town).
|
|
|
|
|
|
|
|
drive_length(Route, Length) :-
|
|
|
|
drive_length(Route, 0, Length).
|
|
|
|
|
|
|
|
drive_length(Route-Town1-Town2, Acc, Length) :-
|
|
|
|
!,
|
|
|
|
Town1::road_distance(Town2, Length2),
|
|
|
|
Acc2 is Acc + Length2,
|
|
|
|
drive_length(Route-Town1, Acc2, Length).
|
|
|
|
drive_length(Town1-Town2, Acc, Length) :-
|
|
|
|
!,
|
|
|
|
Town1::road_distance(Town2, Length2),
|
|
|
|
Length is Acc + Length2.
|
|
|
|
drive_length(_, Length, Length).
|
|
|
|
|
|
|
|
:- end_object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:- object(permute,
|
|
|
|
extends(salesman)).
|
|
|
|
|
|
|
|
:- info([
|
|
|
|
author is 'Paulo Moura',
|
|
|
|
version is 1.0,
|
|
|
|
date is 2000/4/22,
|
|
|
|
comment is '.',
|
|
|
|
source is 'Example adopted from the Francis G. McCabe L&O documentation.']).
|
|
|
|
|
|
|
|
route(Towns, Route) :-
|
|
|
|
findall(
|
|
|
|
(Towns2, Length),
|
|
|
|
(permute(Towns, Towns2), route_length(Towns2, Length)),
|
|
|
|
List),
|
|
|
|
shortest(List, Route).
|
|
|
|
|
|
|
|
permute([Town], Town).
|
|
|
|
permute(Towns, Towns2-Town) :-
|
|
|
|
delete(Towns, Town, Towns3),
|
|
|
|
permute(Towns3, Towns2).
|
|
|
|
|
|
|
|
delete([Head| Tail], Head, Tail).
|
|
|
|
delete([Head| Tail], Element, [Head| Tail2]):-
|
|
|
|
delete(Tail, Element, Tail2).
|
|
|
|
|
|
|
|
route_length(Town, 0) :-
|
|
|
|
atom(Town), !.
|
|
|
|
route_length(Towns-Town1-Town2, Length) :-
|
|
|
|
!,
|
|
|
|
route_length(Towns-Town1, Length1),
|
|
|
|
Town1::crow_flies(Town2, Length2),
|
|
|
|
Length is Length1 + Length2.
|
|
|
|
route_length(Town1-Town2, Length) :-
|
|
|
|
Town1::crow_flies(Town2, Length).
|
|
|
|
|
|
|
|
shortest(List, Shortest) :-
|
|
|
|
shortest(List, null, 1000000, Shortest).
|
2001-06-06 21:07:01 +01:00
|
|
|
|
2005-12-24 18:00:21 +00:00
|
|
|
shortest([], Route, Length, (Route, Length)).
|
|
|
|
shortest([(Route, Length)| Routes], _, LX, Shortest) :-
|
|
|
|
Length < LX, !,
|
|
|
|
shortest(Routes, Route, Length, Shortest).
|
|
|
|
shortest([_| Routes], RX, LX, Shortest) :-
|
|
|
|
shortest(Routes, RX, LX, Shortest).
|
2001-06-06 21:07:01 +01:00
|
|
|
|
|
|
|
:- end_object.
|