Revision 23215

View differences:

trunk/extensions/extGraph/src/org/gvsig/graph/solvers/TspSolverAnnealing.java
1
package org.gvsig.graph.solvers;
2

  
3
import java.util.Random;
4

  
5
import com.sun.org.apache.xpath.internal.operations.Mod;
6

  
7
public class TspSolverAnnealing {
8
	int n;
9
	int[] iorder;
10
	int[] jorder;
11
	float[] b = new float[4];
12
	double[][] odMatrix;
13
	boolean g_bVolverOrigen;
14
	int origenTSP, destinoTSP;
15
	int[] vTSP;
16

  
17

  
18

  
19
	static int T_INIT = 100;
20
	static double FINAL_T = 0.1;
21
	static double COOLING = 0.9; /* to lower down T (< 1) */
22
	int TRIES_PER_T = 500*n; // TODO: PONER ESTO BIEN.  
23
	int IMPROVED_PATH_PER_T = 60*n;  // TODO: PONER ESTO BIEN.  
24

  
25

  
26
//	static long A[56]= {-1};
27
//	long *rand_fptr = A;
28

  
29
//	#define mod_diff(x,y)   (((x)-(y))&0x7fffffff) 
30
//	private long flipCycle()
31
//	{
32
//		long *ii,*jj;
33
//		for (ii = &A[1], jj = &A[32]; jj <= &A[55]; ii++, jj++)
34
//		*ii= mod_diff (*ii, *jj);
35
//
36
//		for (jj = &A[1]; ii <= &A[55]; ii++, jj++)
37
//		*ii= mod_diff (*ii, *jj);
38
//		rand_fptr = &A[54];
39
//		return A[55];
40
//	}
41

  
42

  
43
//	typedef int Path[3];      /* specify how to change path */
44

  
45
	/*
46
	 * State vars
47
	 */
48
	int     verbose = 0;
49
//	 Point   *cities;
50
//	 int     *dist;
51

  
52
//	#define D(x,y) odMatrix[x][y]    //dist[(x)*n+y]		
53
	/* float calcula_dist_ordenacion(int v[], int bVolverOrigen)
54
	{
55
		float dist, distTot;
56
		int i;
57

  
58
	        distTot = odMatrix[origenTSP][v[0]]; // Origen al primer punto
59
	        for (i = 0; i< numElemTSP-1;i++)
60
			{
61
	            //frmDocMap.Distancia v(i), v(i + 1), dist, tiempo
62
				dist = odMatrix[v[i]][v[i+1]];
63
	            distTot = distTot + dist;
64
			}
65
	        
66
	        //  desde y hasta el almacen (distancia al primero y al ?ltimo
67
	        // frmDocMap.Distancia idNodoOrigen, v(0), dist, tiempo
68
	        if (bVolverOrigen)
69
			{            
70
				dist = odMatrix[v[numElemTSP-1]][origenTSP];
71
	            distTot = distTot + dist;
72
	        }
73
			else
74
			{
75
				dist = odMatrix[v[numElemTSP-1]][destinoTSP];
76
				distTot = distTot + dist;
77
			}
78
			return distTot;
79
	} */
80

  
81

  
82
	double pathLength()
83
	{
84
		int i; 
85
		double len = 0;
86

  
87
		len = odMatrix[origenTSP][iorder[0]];
88
		for (i = 0; i < n-1; i++)
89
		{
90
			len += odMatrix[iorder[i]][iorder[i+1]];
91
		}
92

  
93
		if (g_bVolverOrigen)
94
			len += odMatrix[iorder[n-1]][origenTSP]; /* close path */
95
		else
96
			len += odMatrix[iorder[n-1]][destinoTSP]; /* close path */
97
		return (len);
98
	}
99

  
100

  
101
	/*
102
	 * Prim's approximated TSP tour
103
	 * See also [Cristophides'92]
104
	 */
105
	// TODO: NO LO USO => Borrar esta funci?n.
106
	void findEulerianPath()
107
	{
108
		int[] mst = new int[n];
109
		int[] arc = new int[n];	
110
		int i, j = 0, k = 0, l, a;
111
		double d, maxd;
112

  
113
		double[] dis = new double[n];
114

  
115
		maxd = Math.sqrt(b[1]-b[0])+ Math.sqrt(b[3]-b[2]);
116
		d    = maxd;
117
		dis[0] = -1;
118
		for (i = 1; i < n; i++)
119
		{
120
			dis[i] = odMatrix[i][0]; arc[i] = 0;
121
		        if (d > dis[i])
122
			{
123
				d = dis[i];
124
				j = i;
125
			}
126
		}
127

  
128
		/*
129
		 * O(n^2) Minimum Spanning Trees by Prim and Jarnick 
130
		 * for graphs with adjacency matrix. 
131
		 */
132
		for (a = 0; a < n - 1; a++)
133
		{
134
			mst[a] = j * n + arc[j]; /* join fragment j with MST */
135
			dis[j] = -1; 
136
			d = maxd;
137
			for (i = 0; i < n; i++)
138
			{
139
				if (dis[i] >= 0) /* not connected yet */
140
				{
141
					if (dis[i] > odMatrix[i][j])
142
					{
143
						dis[i] = odMatrix[i][j];
144
						arc[i] = j;
145
					}
146
					if (d > dis[i])
147
					{
148
						d = dis[i];
149
						k = i;
150
					}
151
				}
152
			}
153
			j = k;
154
		}
155

  
156
		/*
157
		 * Preorder Tour of MST
158
		 */
159
//	#define VISITED(x) jorder[x]
160
//	#define NQ(x) arc[l++] = x
161
//	#define DQ()  arc[--l]
162
//	#define EMPTY (l==0)
163
			
164
		for (i = 0; i < n; i++) jorder[i] = 0;
165
		k = 0; l = 0; d = 0; 
166
		arc[l++] = 0;
167
		while (l != 0)
168
		{
169
			i = arc[--l];
170
			if (!(jorder[i] == 0))
171
			{
172
				iorder[k++] = i;
173
				jorder[i]  = 1;			
174
				for (j = 0; j < n - 1; j++) /* push all kids of i */
175
				{
176
					if (i == mst[j]%n)
177
						arc[l++] = mst[j]/n; 
178
				}	
179
			}
180
		}
181
	}
182
	
183
	int mod(int a, int b) {
184
		return (a % b);
185
	}
186
	
187
	double D(int f, int t) {
188
		return odMatrix[f][t];
189
	}
190

  
191

  
192
	/*
193
	 * Local Search Heuristics
194
	 *  b-------a        b       a
195
	 *  .       .   =>   .\     /.
196
	 *  . d...e .        . e...d .  
197
	 *  ./     \.        .       .
198
	 *  c       f        c-------f
199
	 */
200
	double getThreeWayCost (int[] p)
201
	{
202
		int a, b, c, d, e, f;
203
		a = iorder[mod(p[0]-1, n)]; b = iorder[p[0]];
204
		c = iorder[p[1]];   d = iorder[mod(p[1]+1,n)];
205
		e = iorder[p[2]];   f = iorder[mod(p[2]+1,n)];
206
		
207
		// b va a ser el nuevo origen => sumamos su distancia a nuestro origen fijo
208
		double Dant, Dnuevo, Ddiff = 0;
209
		Dant = odMatrix[origenTSP][iorder[0]];
210
		Dnuevo = odMatrix[origenTSP][b];
211
		Ddiff = Dnuevo - Dant;
212

  
213
		// tambi?n hay que mirar la distancia al destino desde el ?ltimo punto
214
		int fin=n-1;
215
		if (g_bVolverOrigen)
216
		{	
217
			// p[2] va a ser el pr?ximo ?ltimo punto 
218
			Dant = D(iorder[fin], origenTSP);
219
			Dnuevo = D(iorder[p[2]], origenTSP);
220
			Ddiff = Ddiff + Dnuevo - Dant;
221
		}
222
		else
223
		{
224
			Dant = D(iorder[fin], destinoTSP);
225
			Dnuevo = D(iorder[p[2]], destinoTSP);
226
			Ddiff = Ddiff + Dnuevo - Dant;
227
		}
228
		
229

  
230
		return (D(a,d) + D(e,b) + D(c,f) - D(a,b) - D(c,d) - D(e,f) + Ddiff); 
231
	        /* add cost between d and e if non symetric TSP */ 
232

  
233
		// A?ADIR DIFERENCIA DE COSTE A LOS NODOS INMOVILES. (ORIGEN Y ?DESTINO?)
234
	}
235

  
236
	void doThreeWay (int[] p)
237
	{
238
		int i, count, m1, m2, m3, a, b, c, d, e, f;
239
		int index;
240
		a = mod(p[0]-1,n); b = p[0];
241
		c = p[1];   d = mod(p[1]+1,n);
242
		e = p[2];   f = mod(p[2]+1,n);	
243
		
244
		m1 = mod(n+c-b,n)+1;  /* num cities from b to c */
245
		m2 = mod(n+a-f,n)+1;  /* num cities from f to a */
246
		m3 = mod(n+e-d,n)+1;  /* num cities from d to e */
247

  
248
		count = 0;
249
		/* [b..c] */
250
		for (i = 0; i < m1; i++)
251
		{
252
			index = mod(i+b,n);
253
			jorder[count++] = iorder[index];
254
		}
255

  
256
		/* [f..a] */
257
		for (i = 0; i < m2; i++)
258
		{
259
			index = mod(i+f,n);
260
			jorder[count++] = iorder[index];
261
		}
262

  
263
		/* [d..e] */
264
		for (i = 0; i < m3; i++)
265
		{
266
			index = mod(i+d,n);
267
			jorder[count++] = iorder[index];
268
		}
269

  
270
		/* copy segment back into iorder */
271
		for (i = 0; i < n; i++) iorder[i] = jorder[i];
272
	}
273

  
274
	/*
275
	 *   c..b       c..b
276
	 *    \/    =>  |  |
277
	 *    /\        |  |
278
	 *   a  d       a  d
279
	 */
280
	double getReverseCost (int[] p)
281
	{
282
		int a, b, c, d;
283
		a = iorder[mod(p[0]-1,n)]; b = iorder[p[0]];
284
		c = iorder[p[1]];   d = iorder[mod(p[1]+1,n)];
285
		
286
		double Dant = 0, Dnuevo = 0, Ddiff = 0;
287

  
288
		if (p[0]==0 || p[1]==0)
289
		{
290
			Dant = D(origenTSP,iorder[0]);
291
			if (p[0]==0)
292
				Dnuevo = D(origenTSP, c);
293
			else
294
				Dnuevo = D(origenTSP, b);
295
			Ddiff = Dnuevo-Dant;
296
		}
297
		int fin = n-1;
298
		if (g_bVolverOrigen) // Miramos la distancia al cero
299
		{		
300
			// iorder[p[1]] o iorder[p[0]] va a acabar en la ?ltima posici?n
301
			if (p[0]==fin || p[1] == fin) // tambi?n hay que mirar la distancia al destino desde el ?ltimo punto
302
			{
303
				Dant = D(iorder[fin], origenTSP);
304
				if (p[0]==fin)
305
					Dnuevo = D(c,origenTSP);
306
				else
307
					Dnuevo = D(b, origenTSP);
308
				Ddiff = Ddiff + Dnuevo - Dant;
309

  
310
			} 
311
		}
312
		else
313
		{
314
			if (p[0]==fin || p[1] == fin) // tambi?n hay que mirar la distancia al destino desde el ?ltimo punto
315
			{
316
				Dant = D(iorder[fin], destinoTSP);
317
				if (p[0]==fin)
318
					Dnuevo = D(c,destinoTSP);
319
				else
320
					Dnuevo = D(b, destinoTSP);
321
				Ddiff = Ddiff + Dnuevo - Dant;
322

  
323
			} 
324
		} 
325

  
326
		return (D(d,b) + D(c,a) - D(a,b) - D(c,d) + Ddiff);
327
	        /* add cost between c and b if non symetric TSP */ 
328
//	 A?ADIR DIFERENCIA DE COSTE A LOS NODOS INMOVILES. (ORIGEN Y ?DESTINO?)
329
	}
330

  
331
	void doReverse(int[] p)
332
	{
333
		int i, nswaps, first, last, tmp;
334

  
335
	        /* reverse path b...c */
336
		nswaps = (mod(p[1]-p[0],n)+1)/2;
337
		for (i = 0; i < nswaps; i++)
338
	        {
339
			first = mod(p[0]+i, n);
340
			last  = mod(p[1]-i, n);
341
			tmp   = iorder[first];
342
			
343
			iorder[first] = iorder[last];
344
			iorder[last]  = tmp;
345
	        }
346
	}
347

  
348
	double annealing()
349
	{
350
		int[] p;
351
		int    i=1, j, pathchg;
352
		int    numOnPath, numNotOnPath;
353
		double    pathlen, bestlen;
354
		double energyChange, T;
355

  
356
		/*
357
		 * Set up first eulerian path iorder to be improved by
358
		 * simulated annealing. 
359
		 */
360
		/* bool conEulerian = true;
361
		if (conEulerian)
362
		 	findEulerianPath();  */
363

  
364

  
365
		pathlen = pathLength(); // (iorder); 
366
		bestlen = pathlen;
367
		Random rnd = new Random();
368

  
369
		for (T = T_INIT; T > FINAL_T; T *= COOLING)  /* annealing schedule */
370
	        {
371
			pathchg = 0;
372
			for (j = 0; j < TRIES_PER_T; j++)
373
			{
374
				do {
375
					p[0] = rnd.nextInt(n);
376
					p[1] = rnd.nextInt(n);
377
					if (p[0] == p[1]) p[1] = mod(p[0]+1,n); /* non-empty path */
378
					numOnPath = mod(p[1]-p[0],n) + 1;
379
					numNotOnPath = n - numOnPath;
380
				} while (numOnPath < 2 || numNotOnPath < 2) ; /* non-empty path */
381
				
382
				
383
				if ((rnd.nextInt() % 2) == 0) /*  threeWay */
384
				{
385
					do {
386
						p[2] = mod(rnd.nextInt(numNotOnPath)+p[1]+1,n);
387
					} while (p[0] == mod(p[2]+1,n)); /* avoids a non-change */
388

  
389
					energyChange = getThreeWayCost (p);
390
					if ((energyChange < 0) || (RREAL < Math.exp(-energyChange/T)))
391
					{
392
						pathchg++;
393
						pathlen += energyChange;
394
						doThreeWay (p); 
395
					}
396
				}
397
				else            /* path Reverse */
398
				{
399
					energyChange = getReverseCost (p);
400
					if ((energyChange < 0) || (RREAL < Math.exp(-energyChange/T)))
401
					{
402
						pathchg++;
403
						pathlen += energyChange;
404
						doReverse(p); 
405
					}
406
				}
407
				if (pathlen < bestlen)
408
				{
409
					pathlen = pathLength(); // Calculamos la distancia de verdad, por si no interesa
410
											// hacer el cambio. pathlen es en realidad una estimaci?n
411
					if (pathlen < bestlen)
412
					{
413
						bestlen = pathlen;
414
						for (i=0; i< n; i++)
415
							vTSP[i+1] = iorder[i];
416
					}
417
				}
418
				if (pathchg > IMPROVED_PATH_PER_T) break; /* finish early */
419
			}   
420
			if (pathchg == 0) break;   /* if no change then quit */
421
	        }
422
		return bestlen;
423
	}
424

  
425
}
0 426

  

Also available in: Unified diff