3 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Mark Galassi
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include <gsl/gsl_math.h>
25 #include <gsl/gsl_rng.h>
26 #include <gsl/gsl_siman.h>
27 #include <gsl/gsl_ieee_utils.h>
29 /* set up parameters for this simulated annealing run */
31 #define N_TRIES 200 /* how many points do we try before stepping */
32 #define ITERS_FIXED_T 2000 /* how many iterations for each T? */
33 #define STEP_SIZE 1.0 /* max step size in random walk */
34 #define K 1.0 /* Boltzmann constant */
35 #define T_INITIAL 5000.0 /* initial temperature */
36 #define MU_T 1.002 /* damping factor for temperature */
39 gsl_siman_params_t params = {N_TRIES, ITERS_FIXED_T, STEP_SIZE,
40 K, T_INITIAL, MU_T, T_MIN};
44 double lat, longitude; /* coordinates */
46 typedef struct s_tsp_city Stsp_city;
48 void prepare_distance_matrix(void);
49 void exhaustive_search(void);
50 void print_distance_matrix(void);
51 double city_distance(Stsp_city c1, Stsp_city c2);
52 double Etsp(void *xp);
53 double Mtsp(void *xp, void *yp);
54 void Stsp(const gsl_rng * r, void *xp, double step_size);
57 /* in this table, latitude and longitude are obtained from the US
58 Census Bureau, at http://www.census.gov/cgi-bin/gazetteer */
60 Stsp_city cities[] = {{"Santa Fe", 35.68, 105.95},
61 {"Phoenix", 33.54, 112.07},
62 {"Albuquerque", 35.12, 106.62},
63 {"Clovis", 34.41, 103.20},
64 {"Durango", 37.29, 107.87},
65 {"Dallas", 32.79, 96.77},
66 {"Tesuque", 35.77, 105.92},
67 {"Grants", 35.15, 107.84},
68 {"Los Alamos", 35.89, 106.28},
69 {"Las Cruces", 32.34, 106.76},
70 {"Cortez", 37.35, 108.58},
71 {"Gallup", 35.52, 108.74}};
73 #define N_CITIES (sizeof(cities)/sizeof(Stsp_city))
75 double distance_matrix[N_CITIES][N_CITIES];
77 /* distance between two cities */
78 double city_distance(Stsp_city c1, Stsp_city c2)
80 const double earth_radius = 6375.000; /* 6000KM approximately */
81 /* sin and cos of lat and long; must convert to radians */
82 double sla1 = sin(c1.lat*M_PI/180), cla1 = cos(c1.lat*M_PI/180),
83 slo1 = sin(c1.longitude*M_PI/180), clo1 = cos(c1.longitude*M_PI/180);
84 double sla2 = sin(c2.lat*M_PI/180), cla2 = cos(c2.lat*M_PI/180),
85 slo2 = sin(c2.longitude*M_PI/180), clo2 = cos(c2.longitude*M_PI/180);
87 double x1 = cla1*clo1;
88 double x2 = cla2*clo2;
90 double y1 = cla1*slo1;
91 double y2 = cla2*slo2;
96 double dot_product = x1*x2 + y1*y2 + z1*z2;
98 double angle = acos(dot_product);
100 /* distance is the angle (in radians) times the earth radius */
101 return angle*earth_radius;
104 /* energy for the travelling salesman problem */
105 double Etsp(void *xp)
107 /* an array of N_CITIES integers describing the order */
108 int *route = (int *) xp;
112 for (i = 0; i < N_CITIES; ++i) {
113 /* use the distance_matrix to optimize this calculation; it had
114 better be allocated!! */
115 E += distance_matrix[route[i]][route[(i + 1) % N_CITIES]];
121 double Mtsp(void *xp, void *yp)
123 int *route1 = (int *) xp, *route2 = (int *) yp;
127 for (i = 0; i < N_CITIES; ++i) {
128 distance += ((route1[i] == route2[i]) ? 0 : 1);
134 /* take a step through the TSP space */
135 void Stsp(const gsl_rng * r, void *xp, double step_size)
138 int *route = (int *) xp;
140 step_size = 0 ; /* prevent warnings about unused parameter */
142 /* pick the two cities to swap in the matrix; we leave the first
144 x1 = (gsl_rng_get (r) % (N_CITIES-1)) + 1;
146 x2 = (gsl_rng_get (r) % (N_CITIES-1)) + 1;
150 route[x1] = route[x2];
157 int *route = (int *) xp;
159 for (i = 0; i < N_CITIES; ++i) {
160 printf(" %d ", route[i]);
167 int x_initial[N_CITIES];
170 const gsl_rng * r = gsl_rng_alloc (gsl_rng_env_setup()) ;
172 gsl_ieee_env_setup ();
174 prepare_distance_matrix();
176 /* set up a trivial initial route */
177 printf("# initial order of cities:\n");
178 for (i = 0; i < N_CITIES; ++i) {
179 printf("# \"%s\"\n", cities[i].name);
183 printf("# distance matrix is:\n");
184 print_distance_matrix();
186 printf("# initial coordinates of cities (longitude and latitude)\n");
187 /* this can be plotted with */
188 /* ./siman_tsp > hhh ; grep city_coord hhh | awk '{print $2 " " $3}' | xyplot -ps -d "xy" > c.eps */
189 for (i = 0; i < N_CITIES+1; ++i) {
190 printf("###initial_city_coord: %g %g \"%s\"\n",
191 -cities[x_initial[i % N_CITIES]].longitude,
192 cities[x_initial[i % N_CITIES]].lat,
193 cities[x_initial[i % N_CITIES]].name);
196 /* exhaustive_search(); */
198 gsl_siman_solve(r, x_initial, Etsp, Stsp, Mtsp, Ptsp, NULL, NULL, NULL,
199 N_CITIES*sizeof(int), params);
201 printf("# final order of cities:\n");
202 for (i = 0; i < N_CITIES; ++i) {
203 printf("# \"%s\"\n", cities[x_initial[i]].name);
206 printf("# final coordinates of cities (longitude and latitude)\n");
207 /* this can be plotted with */
208 /* ./siman_tsp > hhh ; grep city_coord hhh | awk '{print $2 " " $3}' | xyplot -ps -d "xy" > c.eps */
209 for (i = 0; i < N_CITIES+1; ++i) {
210 printf("###final_city_coord: %g %g %s\n",
211 -cities[x_initial[i % N_CITIES]].longitude,
212 cities[x_initial[i % N_CITIES]].lat,
213 cities[x_initial[i % N_CITIES]].name);
226 void prepare_distance_matrix()
231 for (i = 0; i < N_CITIES; ++i) {
232 for (j = 0; j < N_CITIES; ++j) {
236 dist = city_distance(cities[i], cities[j]);
238 distance_matrix[i][j] = dist;
243 void print_distance_matrix()
247 for (i = 0; i < N_CITIES; ++i) {
249 for (j = 0; j < N_CITIES; ++j) {
250 printf("%15.8f ", distance_matrix[i][j]);
256 /* [only works for 12] search the entire space for solutions */
257 static double best_E = 1.0e100, second_E = 1.0e100, third_E = 1.0e100;
258 static int best_route[N_CITIES];
259 static int second_route[N_CITIES];
260 static int third_route[N_CITIES];
261 static void do_all_perms(int *route, int n);
263 void exhaustive_search()
265 static int initial_route[N_CITIES] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
272 do_all_perms(initial_route, 1);
280 printf("# exhaustive best route: ");
282 printf("\n# its energy is: %g\n", best_E);
284 printf("# exhaustive second_best route: ");
286 printf("\n# its energy is: %g\n", second_E);
288 printf("# exhaustive third_best route: ");
290 printf("\n# its energy is: %g\n", third_E);
293 /* James Theiler's recursive algorithm for generating all routes */
294 static void do_all_perms(int *route, int n)
296 if (n == (N_CITIES-1)) {
297 /* do it! calculate the energy/cost for that route */
299 E = Etsp(route); /* TSP energy function */
300 /* now save the best 3 energies and routes */
303 memcpy(third_route, second_route, N_CITIES*sizeof(*route));
305 memcpy(second_route, best_route, N_CITIES*sizeof(*route));
307 memcpy(best_route, route, N_CITIES*sizeof(*route));
308 } else if (E < second_E) {
310 memcpy(third_route, second_route, N_CITIES*sizeof(*route));
312 memcpy(second_route, route, N_CITIES*sizeof(*route));
313 } else if (E < third_E) {
315 memcpy(route, third_route, N_CITIES*sizeof(*route));
318 int new_route[N_CITIES];
321 memcpy(new_route, route, N_CITIES*sizeof(*route));
322 for (j = n; j < N_CITIES; ++j) {
323 swap_tmp = new_route[j];
324 new_route[j] = new_route[n];
325 new_route[n] = swap_tmp;
326 do_all_perms(new_route, n+1);