00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifdef HAVE_CONFIG_H
00036 #include <config.h>
00037 #endif
00038
00045
00047
00048
00049
00050
00051 #include <cpl.h>
00052
00053 #include "xsh_model_kernel.h"
00054 #include "xsh_model_metric.h"
00055
00056
00057
00058
00059
00060 #include <stdio.h>
00061 #include <math.h>
00062 #include <float.h>
00063
00064 #include <stdlib.h>
00065
00066
00067 #include "xsh_model_r250.h"
00068
00069 #include "xsh_model_sa.h"
00070
00071
00072
00073
00074 #ifdef _R250_H_
00075 #define uniform(a,b) ( a + (b - a) * xsh_dr250() )
00076 #endif
00077
00078 #ifndef HUGE
00079 #define HUGE HUGE_VAL
00080 #endif
00081
00082 #ifndef PI
00083 #define PI 3.1415626536
00084 #endif
00085
00086 #ifndef PI2
00087 #define PI2 (PI/2.0)
00088 #endif
00089
00090 typedef struct
00091 {
00092 CostFunction func;
00093 int dimension, maxit, dwell;
00094 double *x, *xnew, *xbest;
00095 float dt, c_jump, K, rho, t0, tscale, range;
00096 double y, ybest;
00097 } SimAnneal;
00098
00099 static SimAnneal s;
00100
00101
00102
00103 #ifdef NO_PROTO
00104 static int equilibrate(t, n)
00105 float t;
00106 int n;
00107 #else
00108 static int equilibrate(float t,int n)
00109 #endif
00110 {
00111 int i, j, equil = 0;
00112 float ynew, c, delta, tmpval;
00113 double *xtmp;
00114
00115 delta = 1.0;
00116 tmpval = s.rho * t;
00117 for (i = 0; i < n; i++)
00118 {
00119 for (j = 0; j < s.dimension; j++)
00120 {
00121 s.xnew[j] = s.x[j] + (tmpval*tan ( uniform( -s.range, s.range ) ));
00122 }
00123
00124 ynew = s.func( s.xnew );
00125 c = ynew - s.y;
00126
00127 if (c < 0.0)
00128 {
00129 xtmp = s.x;
00130 s.x = s.xnew;
00131 s.xnew = xtmp;
00132
00133 s.y = ynew;
00134 if ( s.y < s.ybest )
00135 {
00136 for (j = 0; j < s.dimension; j++)
00137 s.xbest[j] = s.x[j];
00138 s.ybest = s.y;
00139 }
00140
00141 delta = fabs( c );
00142 delta = ( s.y != 0.0 ) ? delta / s.y : ( ynew != 0.0 ) ?
00143 delta / ynew : delta;
00144
00145
00146
00147 if ( delta < 0.10 )
00148 equil++;
00149 else
00150 equil = 0;
00151
00152
00153 }
00154 else
00155 {
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 equil++;
00172 }
00173
00174 if (equil > 9)
00175 break;
00176
00177
00178
00179 }
00180
00181 return i + 1;
00182 }
00183
00184
00185
00186 #ifdef NO_PROTO
00187 int xsh_SAInit(f, d)
00188 CostFunction f;
00189 int d;
00190 #else
00191 int xsh_SAInit(CostFunction f, int d)
00192 #endif
00193 {
00194 int space;
00195
00196 s.func = f;
00197 s.dimension = d;
00198 s.t0 = 0.0;
00199 s.K = 1.0;
00200 s.rho = 0.5;
00201 s.dt = 0.1;
00202 s.tscale = 0.1;
00203 s.maxit = 1;
00204 s.c_jump = 100.0;
00205 s.range = PI2;
00206 s.dwell = 20;
00207
00208 space = s.dimension * sizeof(double);
00209
00210 if ( (s.x = (double *)cpl_malloc( space )) == NULL )
00211 return 0;
00212 if ( (s.xnew = (double *)cpl_malloc( space )) == NULL )
00213 return 0;
00214 if ( (s.xbest = (double *)cpl_malloc( space )) == NULL )
00215 return 0;
00216
00217 s.y = s.ybest = HUGE;
00218
00219 #ifdef _R250_H_
00220 xsh_r250_init( 15256 );
00221 #endif
00222
00223 return 1;
00224
00225 }
00226
00227 void xsh_SAfree(void)
00228 {
00229 cpl_free( s.x );
00230 cpl_free( s.xnew );
00231 cpl_free( s.xbest );
00232 s.dimension = 0;
00233 }
00234
00235 #ifdef NO_PROTO
00236 int xsh_SAiterations(m)
00237 int m;
00238 #else
00239 int xsh_SAiterations(int m)
00240 #endif
00241 {
00242 if ( m > 0 )
00243 s.maxit = m;
00244
00245 return s.maxit;
00246 }
00247
00248 #ifdef NO_PROTO
00249 int xsh_SAdwell(m)
00250 int m;
00251 #else
00252 int xsh_SAdwell(int m)
00253 #endif
00254 {
00255 if ( m > 0 )
00256 s.dwell = m;
00257
00258 return s.dwell;
00259 }
00260
00261
00262
00263 #ifdef NO_PROTO
00264 float xsh_SABoltzmann(k)
00265 float k;
00266 #else
00267 float xsh_SABoltzmann(float k)
00268 #endif
00269 {
00270 if ( k > 0.0 )
00271 s.K = k;
00272
00273 return s.K;
00274 }
00275
00276 #ifdef NO_PROTO
00277 float xsh_SAtemperature(t)
00278 float t;
00279 #else
00280 float xsh_SAtemperature(float t)
00281 #endif
00282 {
00283 if ( t > 0.0 )
00284 s.t0 = t;
00285
00286 return s.t0;
00287 }
00288
00289 #ifdef NO_PROTO
00290 float xsh_SAlearning_rate(r)
00291 float r;
00292 #else
00293 float xsh_SAlearning_rate(float r)
00294 #endif
00295 {
00296 if ( r > 0.0 )
00297 s.rho = r;
00298
00299 return s.rho;
00300 }
00301
00302 #ifdef NO_PROTO
00303 float xsh_SAjump(j)
00304 float j;
00305 #else
00306 float xsh_SAjump(float j)
00307 #endif
00308 {
00309 if ( j > 0.0 )
00310 s.c_jump = j;
00311
00312 return s.c_jump;
00313 }
00314
00315 #ifdef NO_PROTO
00316 float xsh_SArange(r)
00317 float r;
00318 #else
00319 float xsh_SArange(float r)
00320 #endif
00321 {
00322 if ( r > 0.0 )
00323 s.range = r;
00324
00325 return s.range;
00326 }
00327
00328
00329 #ifdef NO_PROTO
00330 void xsh_SAinitial(xi)
00331 float* xi;
00332 #else
00333 void xsh_SAinitial(double* xi)
00334 #endif
00335 {
00336 int k;
00337 for (k = 0; k < s.dimension; k++)
00338 s.x[k] = xi[k];
00339 }
00340
00341 #ifdef NO_PROTO
00342 void xsh_SAcurrent(xc)
00343 float* xc;
00344 #else
00345 void xsh_SAcurrent(double* xc)
00346 #endif
00347 {
00348 int k;
00349
00350 for (k = 0; k < s.dimension; k++)
00351 xc[k] = s.x[k];
00352 }
00353
00354 #ifdef NO_PROTO
00355 void xsh_SAoptimum(xb)
00356 float* xb;
00357 #else
00358 void xsh_SAoptimum(double* xb)
00359 #endif
00360 {
00361 int k;
00362
00363 for (k = 0; k < s.dimension; k++)
00364 xb[k] = s.xbest[k];
00365 }
00366
00367
00368
00369
00370
00371 #ifdef NO_PROTO
00372 float xsh_SAmelt(iters)
00373 int iters;
00374 #else
00375 float xsh_SAmelt(int iters)
00376 #endif
00377 {
00378 int i, j, ok = 0;
00379 float ynew, t, cold = 0.0, c = 0.0, tmpval;
00380
00381 int n = iters;
00382 if ( n < 1 )
00383 n = s.maxit;
00384
00385 t = s.t0;
00386
00387 for (i = 0; i < n; i++)
00388 {
00389 if (i > 0 && c > 0.0)
00390 {
00391 cold = c;
00392 ok = 1;
00393 }
00394
00395 t += s.dt;
00396
00397 tmpval = s.rho*t;
00398 for (j = 0; j < s.dimension; j++)
00399 {
00400 s.x[j] += tmpval * tan ( uniform( -s.range, s.range ) );
00401 }
00402
00403 equilibrate( t, s.dwell);
00404
00405
00406 ynew = s.func( s.x );
00407 c = ynew - s.y;
00408
00409 if ( c < 0.0 && ynew < s.ybest)
00410 {
00411 for (j = 0; j < s.dimension; j++)
00412 s.xbest[j] = s.x[j];
00413 s.ybest = ynew;
00414 }
00415
00416 s.y = ynew;
00417
00418 if ( ok && c > (s.c_jump * cold) )
00419 break;
00420
00421 }
00422
00423 return s.t0 = t;
00424
00425 }
00426
00427
00428 #ifdef NO_PROTO
00429 float xsh_SAanneal(iters)
00430 #else
00431 float xsh_SAanneal(int iters)
00432 #endif
00433 {
00434 int i, j;
00435 float p, ynew, t=0.0, c, dt, told, tmpval;
00436 double *xtmp;
00437
00438
00439 int n = iters;
00440 if ( n < 1 )
00441 n = s.maxit;
00442
00443 equilibrate( s.t0, 10 * s.dwell );
00444
00445 told = s.t0;
00446 for (i = 0; i < n; i++)
00447 {
00448 t = s.t0 /(1.0 + i * s.tscale);
00449 dt = t - told;
00450 told = t;
00451
00452 equilibrate(t, s.dwell);
00453
00454 tmpval = s.rho * t;
00455 for (j = 0; j < s.dimension; j++)
00456 {
00457
00458 s.xnew[j] = tmpval * tan ( uniform( -s.range, s.range ) );
00459 }
00460
00461
00462 ynew = s.func( s.xnew );
00463 c = ynew - s.y;
00464
00465 if (ynew <= s.y)
00466 {
00467 xtmp = s.x;
00468 s.x = s.xnew;
00469 s.xnew = xtmp;
00470 s.y = ynew;
00471
00472 if ( s.y < s.ybest )
00473 {
00474 for (j = 0; j < s.dimension; j++)
00475 s.xbest[j] = s.x[j];
00476 s.ybest = s.y;
00477 }
00478 continue;
00479 }
00480 else
00481 {
00482
00483 p = exp( - (ynew - s.y) / (s.K * t) );
00484
00485 if ( p > uniform(0.0, 1.0) )
00486 {
00487 xtmp = s.x;
00488 s.x = s.xnew;
00489 s.xnew = xtmp;
00490 s.y = ynew;
00491 }
00492 }
00493
00494 }
00495
00496 equilibrate( t, 10 * s.dwell );
00497
00498 return s.t0 = t;
00499 }
00500