00001 #include "ga_bistable.h"
00002 #include "opt.h"
00003
00004 static Parameters * _PARAM = 0;
00005 static double * _DU = 0;
00006 static double * _U = 0;
00007 static double * _U0 = 0;
00008 static double MIN_EIG_DEV = 0.1;
00009 static double SS_MIN_ERROR = 1.0e-5;
00010 static double SS_MAX_TIME = 1000.0;
00011 static double SS_MIN_DT = 10.0;
00012 static double * INIT_VALUE = 0;
00013 static double MIN_ERROR = 1.0;
00014 static int PRINT_STEPS = 1;
00015 static int GA_MAX_ITERATIONS = 100;
00016 static int GA_POPULATION_SZ = 1000;
00017
00018 static double * UNSTABLE_PT = 0;
00019 static double * STABLE_PT = 0;
00020
00021 static Parameters ** BAD_PARAMS = 0;
00022
00023 static void (*ODE_FNC)(double,double *,double *,void *);
00024 void deleteGAindividual(void * individual);
00025 void * clone(void * x);
00026
00027 static double distance( double * y1, double * y2, int n )
00028 {
00029 double diff = 0;
00030 int i;
00031 for (i=0; i < n; ++i)
00032 {
00033 diff += (y1[i]-y2[i])*(y1[i]-y2[i]);
00034 }
00035 return diff;
00036 }
00037
00038 static void normalize (double * a , int n)
00039 {
00040 double sum = 0;
00041 int i;
00042 for (i=0; i < n; ++i) sum += (a[i]*a[i]);
00043 if (sum > 0)
00044 {
00045 sum = sqrt(sum);
00046 for (i=0; i < n; ++i) a[i] /= sum;
00047 }
00048 }
00049
00050 static int isBad(Parameters * p)
00051 {
00052 if (BAD_PARAMS)
00053 {
00054 int i=0;
00055 while (BAD_PARAMS[i])
00056 {
00057 if ( (distance( BAD_PARAMS[i]->params, p->params, p->numParams ) < 10.0)
00058 && (distance( BAD_PARAMS[i]->alphas, p->alphas, p->numVars ) < 10.0) )
00059 return 1;
00060 ++i;
00061 }
00062 return 0;
00063 }
00064 return 0;
00065 }
00066
00067 static void setBad(Parameters * p)
00068 {
00069 int i=0, k = 0;
00070 Parameters ** temp;
00071
00072 if (BAD_PARAMS)
00073 {
00074 while (BAD_PARAMS[k]) ++k;
00075 temp = BAD_PARAMS;
00076 BAD_PARAMS = (Parameters**)malloc( (k+1) * sizeof(Parameters*) );
00077 for (i=0; i < k; ++i)
00078 BAD_PARAMS[i] = temp[i];
00079 BAD_PARAMS[k-1] = (Parameters*)clone(p);
00080 BAD_PARAMS[k] = 0;
00081 free(temp);
00082 }
00083 else
00084 {
00085 BAD_PARAMS = (Parameters**)malloc( 2 * sizeof(Parameters) );
00086 BAD_PARAMS[0] = (Parameters*)clone(p);
00087 BAD_PARAMS[1] = 0;
00088 }
00089 }
00090
00091 static void deleteBadParams()
00092 {
00093 if (BAD_PARAMS)
00094 {
00095 int i=0;
00096 while (BAD_PARAMS[i])
00097 {
00098 deleteGAindividual((void*)(BAD_PARAMS[i]));
00099 }
00100 }
00101 }
00102
00103 static double FMIN(int n, double x[])
00104 {
00105 int i;
00106 double sumsq = 0;
00107
00108 if (_U0 && distance(x,_U0,n) < MIN_ERROR) return 1.0;
00109
00110 ODE_FNC(1.0,x,_DU,(void*)_PARAM);
00111
00112 for (i=0; i < n; ++i)
00113 sumsq += (_DU[i]*_DU[i]);
00114 return (sumsq);
00115 }
00116
00117 void deleteGAindividual(void * individual)
00118 {
00119 Parameters * p = (Parameters*)individual;
00120 if (p != NULL)
00121 {
00122 free(p->params);
00123 free(p->alphas);
00124 free(p);
00125 }
00126 }
00127
00128 void * clone(void * x)
00129 {
00130 int i;
00131 Parameters * p = (Parameters*)malloc(sizeof(Parameters));
00132 Parameters * net = (Parameters*)x;
00133
00134 p->numVars = (*net).numVars;
00135 p->numParams = (*net).numParams;
00136 p->params = (double*)malloc( p->numParams * sizeof(double) );
00137 p->alphas = (double*)malloc( p->numVars * sizeof(double) );
00138
00139 for (i = 0; i < p->numVars; ++i)
00140 {
00141 p->alphas[i] = (*net).alphas[i];
00142 }
00143 for (i = 0; i < p->numParams; ++i)
00144 {
00145 p->params[i] = (*net).params[i];
00146 }
00147 return ((void*)p);
00148 }
00149
00150 Parameters * randomNetwork(int numVars, int numParams)
00151 {
00152 int i;
00153
00154 Parameters * p = (Parameters*)malloc(sizeof(Parameters));
00155 p->numParams = numParams;
00156 p->numVars = numVars;
00157 p->params = (double*)malloc( numParams * sizeof(double) );
00158 p->alphas = (double*)malloc( numVars * sizeof(double) );
00159
00160 for (i = 0; i < numParams; ++i) p->params[i] = 10.0*randnum;
00161 for (i = 0; i < numVars; ++i) p->alphas[i] = 2.0*randnum - 1.0;
00162 normalize (p->alphas , p->numVars);
00163 return (p);
00164 }
00165
00166 static double * regularSteadyState(Parameters * p, double * iv)
00167 {
00168 int i;
00169 int N = p->numVars;
00170 double * ss, * alphas = (double*)malloc(N*sizeof(double));
00171
00172 for (i=0; i < N; ++i)
00173 {
00174 alphas[i] = p->alphas[i];
00175 p->alphas[i] = 1.0;
00176 }
00177
00178 ss = steadyState(N,iv,ODE_FNC,(void*)p,SS_MIN_ERROR,SS_MAX_TIME,SS_MIN_DT);
00179
00180 for (i=0; i < N; ++i)
00181 p->alphas[i] = alphas[i];
00182 free(alphas);
00183
00184 return ss;
00185 }
00186
00187 static double * unstableSteadyState(Parameters * p, double * iv)
00188 {
00189 double * ss = steadyState(p->numVars,iv,ODE_FNC,(void*)p,SS_MIN_ERROR,SS_MAX_TIME,SS_MIN_DT);
00190 return ss;
00191 }
00192
00193 static double * findZeros(Parameters * p, double * x, double * fopt)
00194 {
00195 int i;
00196 double * ss = 0;
00197
00198 _PARAM = p;
00199
00200 for (i=0; i < p->numVars; ++i)
00201 {
00202 _U[i] = x[i];
00203 }
00204
00205 if (NelderMeadSimplexMethod(p->numVars, &(FMIN), _U, 10.00, fopt, 1000.0, 1.0e-10) == success)
00206 {
00207 if ((*fopt) <= 1.0e-5)
00208 ss = _U;
00209 }
00210
00211 return ss;
00212 }
00213
00214 double fitness(void * individual)
00215 {
00216 int i, allPos, N;
00217 double * ss0, * ss1, * ss2, fmin, score;
00218 Parameters * p = (Parameters*)individual;
00219
00220 allPos = 1;
00221 N = p->numVars;
00222
00223 for (i=0; i < p->numVars; ++i)
00224 {
00225 if (p->alphas[i] < -MIN_EIG_DEV)
00226 {
00227 allPos = 0;
00228 break;
00229 }
00230 }
00231 if (allPos) return (0.0);
00232
00233 ss0 = regularSteadyState(p,INIT_VALUE);
00234
00235 if (ss0 == 0) { return (0.0); }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 for (i=0; i < p->numVars; ++i)
00246 {
00247 _U0[i] = ss0[i];
00248 }
00249
00250 ss1 = findZeros(p,ss0,&fmin);
00251
00252 if (ss1 != 0)
00253 {
00254 ss2 = unstableSteadyState(p,ss1);
00255 if (ss2 == 0)
00256 {
00257
00258 ss1 = 0;
00259
00260 return 0.0;
00261 }
00262 else
00263 free(ss2);
00264 }
00265
00266 if (ss1 == 0)
00267 {
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 free (ss0);
00332
00333 score = 1.0e-5/(1.0e-5 + fmin);
00334 return score;
00335 }
00336
00337 for (i=0; i < N; ++i)
00338 {
00339 if (ss1[i] < 0.0)
00340 {
00341 free(ss0);
00342
00343 return (0.0);
00344 }
00345 }
00346
00347 if (distance(ss1,ss0,N) < MIN_ERROR)
00348 {
00349 free(ss0);
00350
00351 return (0.0);
00352 }
00353
00354 if (STABLE_PT)
00355 free(ss0);
00356 else
00357 STABLE_PT = ss0;
00358
00359 if (!UNSTABLE_PT)
00360 UNSTABLE_PT = ss1;
00361 return 1.0;
00362 }
00363
00364
00365 void * mutate(void * individual)
00366 {
00367 int i,j,n,m;
00368 Parameters * p = (Parameters*)individual;
00369
00370 n = p->numParams;
00371 m = p->numVars;
00372
00373 if (mtrand() < 0.5)
00374 {
00375 i = (int)(mtrand() * n);
00376 p->params[i] *= randnum;
00377 }
00378 else
00379 {
00380 j = (int)(mtrand() * m);
00381 p->alphas[j] *= 2.0 * randnum - 1.0;
00382 }
00383 normalize (p->alphas , m);
00384 return (p);
00385 }
00386
00387
00388 void * crossover(void * individual1, void * individual2)
00389 {
00390 int i;
00391 Parameters * net1 = (Parameters*)individual1,
00392 * net2 = (Parameters*)individual2,
00393 * net3 = (Parameters*)clone(individual1);
00394
00395 if (mtrand() < 0.5)
00396 {
00397 for (i = 0; i < (*net3).numParams; ++i)
00398 {
00399 (*net3).params[i] = (*net1).params[i];
00400 }
00401 for (i = 0; i < (*net3).numVars; ++i)
00402 {
00403 (*net3).alphas[i] = (*net2).alphas[i];
00404 }
00405 }
00406 else
00407 {
00408 for (i = 0; i < (*net3).numVars; ++i)
00409 {
00410 (*net3).alphas[i] = 0.5 * ((*net1).alphas[i] + (*net2).alphas[i]);
00411 }
00412 for (i = 0; i < (*net3).numParams; ++i)
00413 {
00414 (*net3).params[i] = 0.5 * ((*net1).params[i] + (*net2).params[i]);
00415 }
00416 }
00417 normalize((*net3).alphas , (*net3).numVars);
00418 return ((void*)net3);
00419 }
00420
00421
00422 Parameters ** initGApopulation(int sz, int n, int p)
00423 {
00424 int i;
00425 Parameters ** pop = (Parameters**)malloc(sz * sizeof(Parameters*));
00426
00427 for (i=0; i < sz; ++i)
00428 {
00429 pop[i] = randomNetwork(n,p);
00430 }
00431 return pop;
00432 }
00433
00434
00435 int callbackf(int gen, int popsz, void ** pop, double * fitnessArray, int *** parentsArray)
00436 {
00437 int i,j;
00438 double x;
00439 void * y;
00440 Parameters * p;
00441
00442 y = pop[0];
00443 x = fitness(y);
00444
00445 if (PRINT_STEPS)
00446 {
00447 printf("%i %lf\n", gen, x);
00448 if (x == 1.0) printf("target reached.\n\n");
00449 }
00450 if (x == 1.0)
00451 {
00452 return (1);
00453 }
00454
00455 if (gen > 0 && (gen % 20) == 0)
00456 {
00457 p = 0;
00458 for (i=0; i < popsz/2; ++i)
00459 {
00460 p = (Parameters*)pop[i];
00461 for (j=0; j < p->numVars; ++j) p->alphas[j] *= 2.0 * randnum;
00462 for (j=0; j < p->numParams; ++j) p->params[j] *= 2.0 * randnum;
00463 normalize (p->alphas , p->numVars);
00464 normalize (p->params , p->numParams);
00465 }
00466 }
00467
00468 return (0);
00469 }
00470
00471 static double** findTwoSteadyStates(Parameters * p0)
00472 {
00473 double * iv = unstableSteadyState(p0,INIT_VALUE), * iv2, * y, * y0, fopt, diff, ** ys;
00474 int i,j;
00475 Parameters * p;
00476
00477 if (!iv) return 0;
00478
00479 p = clone((void*)p0);
00480 for (i=0; i < p->numVars; ++i) p->alphas[i] = 1.0;
00481
00482 iv2 = (double*)malloc( p->numVars * sizeof(double) );
00483 for (i=0; i < p->numVars; ++i) iv2[i] = iv[i];
00484
00485 y = y0 = 0;
00486
00487 for (i=0; i < 100; ++i)
00488 {
00489 for (j=0; j < p->numVars; ++j)
00490 iv2[j] = iv[j] + 10.0*randnum - 5.0;
00491
00492
00493 y = 0;
00494 _DU = (double*)malloc( (p->numVars) * sizeof(double));
00495 _PARAM = p;
00496 for (j=0; j < p->numVars; ++j)
00497 {
00498 _U0[j] = _U[j] = INIT_VALUE[j];
00499 }
00500 if (NelderMeadSimplexMethod(p->numVars, &(FMIN), _U, 1.00, &fopt, 1000.0, 1.0e-10) == success)
00501 {
00502 if (fopt < 1.0e-5)
00503 y = _DU;
00504 else
00505 free(_DU);
00506 }
00507 else
00508 free(_DU);
00509
00510 if (y)
00511 {
00512 for (j=0; j < p->numVars; ++j)
00513 if (y[j]==iv2[j])
00514 y[j] = 0.0;
00515 if (y0)
00516 {
00517 diff = 0;
00518 for (j=0; j < p->numVars; ++j)
00519 diff += (y[j] - y0[j])*(y[j] - y0[j]);
00520
00521 if (diff > MIN_ERROR)
00522 {
00523 deleteGAindividual((void*)p);
00524 ys = (double**)malloc(3 * sizeof(double*));
00525 ys[0] = iv;
00526 ys[1] = y0;
00527 ys[2] = y;
00528 free(iv2);
00529 return ys;
00530 }
00531 free(y);
00532 }
00533 else
00534 {
00535 y0 = y;
00536 }
00537 }
00538 }
00539 free(iv);
00540 free(iv2);
00541 deleteGAindividual((void*)p);
00542 free(y);
00543 free(y0);
00544 return 0;
00545 }
00546
00547 BistablePoint makeBistable(int n, int p,double* iv, int maxIter, int popSz, void (*odefnc)(double,double*,double*,void*))
00548 {
00549
00550 int popsz1, i;
00551 BistablePoint ans;
00552 Parameters * param;
00553 GApopulation pop;
00554
00555 _U0 = (double*)malloc( n * sizeof(double));
00556 _U = (double*)malloc( n * sizeof(double));
00557 _DU = (double*)malloc( n * sizeof(double));
00558
00559 ODE_FNC = odefnc;
00560 popsz1 = popSz/5;
00561 INIT_VALUE = iv;
00562
00563 GAinit(&deleteGAindividual,&clone,&fitness,&crossover,&mutate,0,&callbackf);
00564 pop = GArun((void**)initGApopulation(popSz,n,p),popSz,popsz1,maxIter);
00565
00566 param = pop[0];
00567
00568 for (i=1; i < popsz1; ++i) deleteGAindividual(pop[i]);
00569 free(pop);
00570
00571 ans.param = 0;
00572 ans.unstable = ans.stable1 = ans.stable2 = 0;
00573
00574 if (fitness((void*)param) < 1)
00575 {
00576 deleteGAindividual(param);
00577 return ans;
00578 }
00579
00580 ans.param = param;
00581 ans.unstable = ans.stable1 = ans.stable2 = 0;
00582
00583
00584
00585 if (UNSTABLE_PT)
00586 ans.unstable = UNSTABLE_PT;
00587
00588 if (STABLE_PT)
00589 ans.stable1 = STABLE_PT;
00590
00591 free(_U0);
00592 free(_U);
00593 deleteBadParams();
00594 return ans;
00595 }