root/trunk/extra/tsp/src/tsp_solver.cpp

Revision 101, 8.6 KB (checked in by anton, 3 years ago)

GAUL utils library location fixed

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                   
22extern "C"
23{
24#include <gaul.h>
25#include <postgres.h>
26}
27
28#include "tsp.h"
29
30using namespace std;
31
32
33// Maximal number of nodes in the path (to avoid infinite loops)
34//#define MAX_TOWNS 40
35
36float DISTANCE[MAX_TOWNS][MAX_TOWNS];
37int ids[MAX_TOWNS];
38int source_id;
39int cnum;
40
41boolean 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                                           
65boolean 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                                                     
90void 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
127void 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
168void 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
182void 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
237int
238find_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.