pgRouting

root/tags/release-1.0-beta/tsp_solver.cpp

Revision 39, 8.5 kB (checked in by anton, 1 year ago)

1.0.0b tag added

Line 
1 /*
2  * Traveling Salesman Problem solution algorithm for PostgreSQL
3  *
4  * Copyright (c) 2006 Anton A. Patrushev, Orkney, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  */
21                    
22 extern "C"
23 {
24 #include <gaul.h>
25 #include <postgres.h>
26 }
27
28 #include "tsp.h"
29
30 using namespace std;
31
32
33 // Maximal number of nodes in the path (to avoid infinite loops)
34 //#define MAX_TOWNS 40
35
36 float DISTANCE[MAX_TOWNS][MAX_TOWNS];
37 int ids[MAX_TOWNS];
38 int source_id;
39 int cnum;
40
41 boolean tsp_score(population *pop, entity *entity)
42 {
43   int           k;
44   float         dist;
45   int           cur_allele, prev_allele;
46      
47   entity->fitness = 0.0;
48   dist = 0.0;
49
50   // Loop over alleles in chromosome.
51   for (k = 1; k < pop->len_chromosomes; k++)
52     {
53       cur_allele = ((int *)entity->chromosome[0])[k];
54       prev_allele = ((int *)entity->chromosome[0])[k-1];
55       dist += DISTANCE[cur_allele][prev_allele];
56     }
57                                  
58   entity->fitness = 1/dist*100;
59   if(ids[((int *)entity->chromosome[0])[0]] != source_id)
60     entity->fitness /= 10;
61      
62   return TRUE;
63 }
64                                            
65 boolean tsp_seed(population *pop, entity *adam)
66 {
67   int           i,s,tmp;
68   int           *data;
69    
70   data = (int *)adam->chromosome[0];
71      
72   for (i=0; i<pop->len_chromosomes; i++)
73   {
74     data[i] = i;
75   }
76                      
77   for (i=0; i<pop->len_chromosomes; i++)
78   {
79     if(ids[data[i]] == source_id)
80       s = i;
81   }
82                                              
83   tmp = data[0];
84   data[0] = data[s];
85   data[s] = tmp;
86                                                    
87   return TRUE;
88 }
89                                                      
90 void tsp_mutate_swap(population *pop, entity *mother, entity *son)
91 {
92   int           i, j;
93   int           tmp; 
94          
95   // Copy chromosomes from parent to offspring.
96   memcpy( son->chromosome[0],
97           mother->chromosome[0],
98           pop->len_chromosomes*sizeof(int) );
99                        
100   do
101     {
102       i = random_int(pop->len_chromosomes-1);
103     }
104   while(i==0);
105
106   do
107     {
108       j = random_int(pop->len_chromosomes-1);
109     }
110   while(j==0);
111                                    
112   if (i==j)
113     {
114       if (j==9)
115         j=1;
116       else
117         j++;
118     }
119                                                                          
120   tmp = ((int *)son->chromosome[0])[i];
121   ((int *)son->chromosome[0])[i] = ((int *)son->chromosome[0])[j];
122   ((int *)son->chromosome[0])[j] = tmp;
123                                                    
124   return;
125 }
126
127 void tsp_mutate_shift(population *pop, entity *mother, entity *son)
128 {
129   int i, j, k;        // Team members.
130   int tmp;            // For swapping i and j.
131          
132   // Copy chromosomes from parent to offspring.
133   memcpy( son->chromosome[0],
134           mother->chromosome[0],
135           pop->len_chromosomes*sizeof(int) );
136                                
137                  
138   i = random_int(pop->len_chromosomes-1);
139
140   do
141     {
142       j = random_int(pop->len_chromosomes-1);
143     }
144   while(i==j);
145                                                    
146   if (i>j)
147     {
148       tmp = ((int *)son->chromosome[0])[j];
149       for (k=j; k<i; k++)
150         {
151           ((int *)son->chromosome[0])[k] = ((int *)son->chromosome[0])[k+1];
152         }
153       ((int *)son->chromosome[0])[i] = tmp;
154     }
155   else
156     {
157       tmp = ((int *)son->chromosome[0])[j];
158       for (k=j; k>i; k--)
159         {
160           ((int *)son->chromosome[0])[k] = ((int *)son->chromosome[0])[k-1];
161         }
162       ((int *)son->chromosome[0])[i] = tmp;
163     }
164
165   return;
166 }                                                     
167
168 void tsp_mutate(population *pop, entity *mother, entity *son)
169 {
170  
171   if (!mother || !son) die("Null pointer to entity structure passed");
172          
173   if (random_boolean_prob(0.2))
174     tsp_mutate_swap(pop, mother, son);
175   else
176     tsp_mutate_shift(pop, mother, son);
177                          
178   return;
179 }
180
181
182 void tsp_crossover(population *pop, entity *mother,
183                    entity *father, entity *daughter, entity *son)
184 {
185   int i, j;
186      
187   for (i=0; i<pop->len_chromosomes; i++)
188     {
189       if (random_boolean())
190         {
191           ((int *)son->chromosome[0])[i] =
192             ((int *)father->chromosome[0])[i];
193           ((int *)daughter->chromosome[0])[i] =
194             ((int *)mother->chromosome[0])[i];
195         }
196       else
197         {
198           ((int *)son->chromosome[0])[i] =
199             ((int *)father->chromosome[0])[i];
200
201           ((int *)daughter->chromosome[0])[i] =
202             ((int *)mother->chromosome[0])[i];
203         }
204     }
205
206   for (i=1; i<pop->len_chromosomes; i++)
207     {
208       for (j=0; j<i; j++)
209         {
210           if (((int *)son->chromosome[0])[j] ==
211                 ((int *)son->chromosome[0])[i])
212             {
213               if (((int *)son->chromosome[0])[i]==9)
214                 ((int *)son->chromosome[0])[i]=0;
215               else
216                 ((int *)son->chromosome[0])[i]++;
217               j=0;
218             }
219         }
220       for (j=0; j<i; j++)
221         {
222           if (((int *)daughter->chromosome[0])[j] ==
223                 ((int *)daughter->chromosome[0])[i])
224             {
225               if (((int *)daughter->chromosome[0])[i]==9)
226                 ((int *)daughter->chromosome[0])[i]=0;
227               else
228                 ((int *)daughter->chromosome[0])[i]++;
229               j=0;
230             }
231         }
232     }
233   return;
234 }
235
236
237 int
238 find_tsp_solution(int num, float dist[MAX_TOWNS][MAX_TOWNS],
239                   int p_ids[MAX_TOWNS], int source,
240                   float *fit, char* err_msg)
241 {
242   int i,j;
243   population    *pop=NULL;              /* Population of solutions. */
244   float         score = 0.0;            /* Best score */
245
246   source_id = source;
247   cnum=num;
248  
249   for(i=0;i<cnum;i++)
250     {
251       ids[i] = p_ids[i];
252
253       for(j=0;j<cnum;j++)
254         {
255           DISTANCE[i][j]=dist[i][j];
256         }
257     }
258  
259   random_init();
260
261   for (int ss=0; ss<15; ss++) //use seed 15 times
262     {
263       if (pop) ga_extinction(pop);
264       random_seed(ss);
265       pop = ga_genesis_integer(
266                 num*4,  /* const int              population_size */
267                 1,      /* const int              num_chromo */
268                 cnum,   /* const int              len_chromo */
269                 NULL,   /* GAgeneration_hook      generation_hook */
270                 NULL,   /* GAiteration_hook       iteration_hook */
271                 NULL,   /* GAdata_destructor      data_destructor */
272                 NULL,   /* GAdata_ref_incrementor data_ref_incrementor */
273                 tsp_score,/* GAevaluate           evaluate */
274                 tsp_seed, /* GAseed               seed */
275                 NULL,     /* GAadapt              adapt */
276                 ga_select_one_randomrank,/* GAselect_one     select_one */
277                 ga_select_two_randomrank,/* GAselect_two     select_two */
278                 tsp_mutate,    /* GAmutate        mutate */
279                 tsp_crossover, /* GAcrossover     crossover */
280                 NULL,          /* GAreplace       replace */
281                 NULL           /* vpointer        User data */
282                 );
283
284       ga_population_set_parameters(
285                pop,                     /* population      *pop */
286                GA_SCHEME_DARWIN,        /* const ga_scheme_type     scheme */
287                GA_ELITISM_PARENTS_DIE,  /* const ga_elitism_type   elitism */
288                0.5,                     /* optimal double  crossover */
289                0.4,                     /* optimal double  mutation */
290                0.0                      /* unused  double  migration */
291                );
292
293       ga_evolution(
294               pop,              /* population  *pop */
295               num*4             /* const int   max_generations */
296               );
297
298
299       if(score < ga_get_entity_from_rank(pop,0)->fitness)
300         {
301           score = ga_get_entity_from_rank(pop,0)->fitness;
302           *fit = score;
303      
304           for(int l=0; l<cnum; l++)
305             {
306               p_ids[l] = ids[
307                              ((int *)ga_get_entity_from_rank(pop,0)->
308                               chromosome[0])[l]];
309             }
310         }
311      
312     } 
313  
314   return EXIT_SUCCESS;
315 }
Note: See TracBrowser for help on using the browser.