00001 #include <cmath>
00002 #include <cstdlib>
00003 #include <cstdio>
00004 #include "minimization.h"
00005
00006 using namespace std;
00007
00008
00009 CMinimization::CMinimization( int dimension)
00010 {
00011 TOL_CG = 1.0e-10;
00012 TOL_Brent = 1.0e-12;
00013 n = dimension;
00014 vec_x = NULL;
00015 vec_dx = NULL;
00016 linear_trial_x = NULL;
00017 linear_dir = NULL;
00018 H = NULL;
00019
00020 AllocVectors();
00021 }
00022
00023 CMinimization::CMinimization()
00024 {
00025
00026
00027 TOL_CG = 1.0e-6;
00028 TOL_Brent = 1.0e-7;
00029 n = 1;
00030 vec_x = NULL;
00031 vec_dx = NULL;
00032 linear_trial_x = NULL;
00033 linear_dir = NULL;
00034 H = NULL;
00035 }
00036
00037 bool CMinimization::AllocVectors()
00038 {
00039
00040 if (NULL != vec_x)
00041 {
00042 delete [] vec_x;
00043 }
00044 if (NULL != vec_dx)
00045 {
00046 delete [] vec_dx;
00047 }
00048 if (NULL != linear_trial_x)
00049 {
00050 delete [] linear_trial_x;
00051 }
00052 if (NULL != linear_dir)
00053 {
00054 delete [] linear_dir;
00055 }
00056 if (NULL != H)
00057 {
00058 for ( int i=0;i<n;i++)
00059 {
00060 delete [] H[i];
00061 }
00062 delete [] H;
00063 }
00064
00065
00066 if (n > 1)
00067 {
00068 TagMultiD = true ;
00069 vec_x = new double [n];
00070 vec_dx = new double [n];
00071 linear_trial_x = new double [n];
00072 linear_dir = new double [n];
00073 H = new double * [n];
00074 for ( int i=0;i<n;i++)
00075 {
00076 H[i] = new double [n];
00077 }
00078
00079 }
00080 else if (1 == n)
00081 {
00082 TagMultiD = false ;
00083 vec_x = NULL;
00084 vec_dx = NULL;
00085 linear_trial_x = NULL;
00086 linear_dir = NULL;
00087 H = NULL;
00088 }
00089 else
00090 {
00091 printf("Error: please input positive integer value of dimension! input n=%d", n);
00092 exit(0);
00093 }
00094
00095 return true ;
00096 }
00097
00098 bool CMinimization::SetDimension( int dimension)
00099 {
00100 n = dimension;
00101 if (AllocVectors() == true )
00102 {
00103 return true ;
00104 }
00105 return false ;
00106 }
00107
00108 CMinimization::~CMinimization()
00109 {
00110 if (NULL != vec_x)
00111 {
00112 delete [] vec_x;
00113 }
00114 if (NULL != vec_dx)
00115 {
00116 delete [] vec_dx;
00117 }
00118 if (NULL != linear_trial_x)
00119 {
00120 delete [] linear_trial_x;
00121 }
00122 if (NULL != linear_dir)
00123 {
00124 delete [] linear_dir;
00125 }
00126 if (NULL != H)
00127 {
00128 for ( int i=0;i<n;i++)
00129 {
00130 delete [] H[i];
00131 }
00132 delete [] H;
00133 }
00134 }
00135
00136 bool CMinimization::bracket( double &ax, double &bx, double &cx, double &fa, double &fb, double &fc)
00137
00138 {
00139 const double GOLD_RATIO = 1.618034;
00140 const double SEARCH_LIMIT = 10.0;
00141
00142 fa = fn1(ax);
00143 fb = fn1(bx);
00144
00145 if (fb > fa)
00146 {
00147 swap2(ax, bx);
00148 swap2(fa, fb);
00149 }
00150
00151 cx = bx + GOLD_RATIO * (bx - ax);
00152 fc = fn1(cx);
00153
00154 double u;
00155 double fu;
00156 double ulim;
00157 while (fb > fc)
00158 {
00159
00160
00161 u = bx - ((bx - cx) * (bx - cx) * (fb - fa) - (bx - ax) * (bx - ax) * (fb - fc)) / (2.0 * ((bx - cx) * (fb - fa) - (bx - ax) * (fb - fc)));
00162 ulim = bx + SEARCH_LIMIT * (cx - bx);
00163
00164 if ((bx - u) * (u - cx) > 0.0)
00165 {
00166 fu = fn1(u);
00167 if (fu < fc)
00168 {
00169 ax = bx;
00170 bx = u;
00171 fa = fb;
00172 fb = fu;
00173 return true ;
00174 }
00175 else
00176 {
00177 if (fu > fb)
00178 {
00179 cx = u;
00180 fc = fu;
00181 return true ;
00182 }
00183 u = cx + GOLD_RATIO * (cx - bx);
00184 fu = fn1(u);
00185 }
00186 }
00187 else if ((cx - u) * (u - ulim) > 0.0)
00188 {
00189 fu = fn1(u);
00190 if (fu < fc)
00191 {
00192 shift3(bx, cx, u, cx + GOLD_RATIO * (cx - bx));
00193 shift3(fb, fc, fu, fn1(u));
00194 }
00195 }
00196 else if ((u - ulim) * (ulim - cx) > 0.0)
00197 {
00198 u = ulim;
00199 fu = fn1(u);
00200 }
00201 else
00202 {
00203 u = cx + GOLD_RATIO * (cx - bx);
00204 fu = fn1(u);
00205 }
00206 shift3(ax, bx, cx, u);
00207 shift3(fa, fb, fc, fu);
00208 }
00209
00210 return true ;
00211 }
00212
00213 double CMinimization::brent( double ax, double bx, double cx, double &xmin)
00214
00215
00216
00217 {
00218 const int MAX_ITERATION = 100;
00219 const double GOLD_RATIO = 2.0 - 1.618034;
00220
00221 double a, b;
00222
00223 a = (ax < cx ? ax : cx);
00224 b = (ax > cx ? ax : cx);
00225
00226 double w, v;
00227 double fw, fv;
00228 double x;
00229 double fx;
00230 x = bx;
00231 w = bx;
00232 v = bx;
00233 fx = fn1(x);
00234 fw = fx;
00235 fv = fx;
00236 double u, fu;
00237
00238 double xm;
00239
00240 double e = 0.0;
00241 double d = 0.0;
00242 double p, q;
00243 double tol1;
00244
00245 for ( int i=0;i<MAX_ITERATION;i++)
00246 {
00247 xm = 0.5 * (a + b);
00248 tol1 = TOL_Brent * fabs(x) + 1.0e-18 ;
00249 if (fabs(x-xm) <= (tol1*2.0-0.5*(b-a)))
00250 {
00251 xmin = x;
00252 return fx;
00253 }
00254 if (fabs(e) > tol1)
00255 {
00256 q = 2.0 * ((x-v)*(fx-fw) - (x-w)*(fx-fv));
00257 p = (x-v)*(x-v)*(fx-fw) - (x-w)*(x-w)*(fx-fv);
00258
00259 if (q > 0.0) p = -p;
00260 q = fabs(q);
00261 if (fabs(p) >= fabs(0.5*q*e)
00262 || p <= q*(a-x)
00263 || p >= q*(b-x))
00264 {
00265 e = (x >= xm ? a-x : b-x);
00266 d = GOLD_RATIO * e;
00267 }
00268 else
00269 {
00270 e = d;
00271 d = p / q;
00272 u = x + d;
00273 if ( u - a < tol1*2.0 || b - u < tol1*2.0)
00274 {
00275 d = tol1 / (x-xm) * fabs(x-xm);
00276 }
00277
00278 }
00279 }
00280 else
00281 {
00282 e = (x >= xm ? a-x : b-x);
00283 d = GOLD_RATIO * e;
00284 }
00285
00286 if (fabs(d) > tol1)
00287 u = x + d;
00288 else
00289 u = x + tol1 / d * fabs(d);
00290 fu = fn1(u);
00291
00292 if (fu <= fx)
00293 {
00294 if (u >= x)
00295 a = x;
00296 else
00297 b = x;
00298 shift3(v, w, x, u);
00299 shift3(fv, fw, fx, fu);
00300 }
00301 else
00302 {
00303 if (u < x)
00304 a = u;
00305 else
00306 b = u;
00307 if (fu <= fw || w == x)
00308 {
00309 v = w;
00310 w = u;
00311 fv = fw;
00312 fw = fu;
00313 }
00314 else if (fu <= fv || v == x || v == w)
00315 {
00316 v = u;
00317 fv = fu;
00318 }
00319 }
00320
00321 }
00322 printf("Warning: cann't find the minimum after maximum iteration in brent!\n");
00323 xmin = x;
00324 return fx;
00325
00326 }
00327
00328 bool CMinimization::linear_Min( double &fmin)
00329 {
00330
00331
00332
00333 double ax = 0.0;
00334 double xx = 1.0e-6;
00335
00336 double max_dir = 0.0;
00337 int j = 0;
00338 for ( int i=0;i<n;i++)
00339 {
00340 if (fabs(linear_dir[i]) > max_dir)
00341 {
00342 max_dir = fabs(linear_dir[i]);
00343 j = i;
00344 }
00345 }
00346 xx = (max_dir > 1.0) ? 1.0/max_dir : 1.0;
00347
00348
00349
00350
00351
00352
00353
00354 double bx;
00355 double fa, fb, fx;
00356 bracket(ax, xx, bx, fa, fx, fb);
00357 printf("bracket done as [%g, %g]\n", ax, bx);
00358 double xmin;
00359 fmin = brent(ax, xx, bx, xmin);
00360 for ( int i=0;i<n;i++)
00361 {
00362 linear_dir[i] *= xmin;
00363 vec_x[i] += linear_dir[i];
00364 }
00365 return true ;
00366 }
00367
00368 bool CMinimization::conjugate_gradient( double * x, int &iteration, double &fmin)
00369 {
00370 for ( int i=0;i<n;i++)
00371 {
00372 vec_x[i] = x[i];
00373 }
00374 const int MAX_ITERATION = 100;
00375 double * g = new double [n];
00376 double * h = new double [n];
00377
00378 double fx = fn(vec_x);
00379 dfn(vec_x);
00380
00381 for ( int i=0;i<n;i++)
00382 {
00383 g[i] = - vec_dx[i];
00384 h[i] = g[i];
00385 vec_dx[i] = h[i];
00386 }
00387 double gg, dgg, gam;
00388 for ( int i=0;i<MAX_ITERATION;i++)
00389 {
00390 iteration = i;
00391 for ( int ii=0;ii<n;ii++)
00392 {
00393 linear_dir[ii] = vec_dx[ii];
00394 }
00395 linear_Min(fmin);
00396
00397 for ( int kk=0;kk<n;kk++)
00398 {
00399 printf("x[%d] : %g ", kk, vec_x[kk]);
00400 }
00401 printf("f(x)=%g after %d iterations\n", fmin, i);
00402
00403 if (2.0 * fabs(fmin-fx) <= TOL_CG * (fabs(fmin)+fabs(fx)+1.0e-15))
00404
00405 {
00406 delete [] g;
00407 delete [] h;
00408 for ( int ii=0;ii<n;ii++)
00409 {
00410 x[ii] = vec_x[ii];
00411 }
00412 return true ;
00413 }
00414 fx = fmin;
00415 dfn(vec_x);
00416 gg = 0.0;
00417 dgg = 0.0;
00418 for ( int j=0;j<n;j++)
00419 {
00420 gg += g[j]*g[j];
00421
00422 dgg += (vec_dx[j]+g[j])*vec_dx[j];
00423 }
00424 if (fabs(gg) <= 1.0e-12)
00425 {
00426 delete [] g;
00427 delete [] h;
00428 for ( int ii=0;ii<n;ii++)
00429 {
00430 x[ii] = vec_x[ii];
00431 }
00432 return true ;
00433 }
00434 gam = dgg / gg;
00435 for ( int j=0;j<n;j++)
00436 {
00437 g[j] = - vec_dx[j];
00438 h[j] = g[j] + gam * h[j];
00439 vec_dx[j] = h[j];
00440 }
00441 }
00442 delete [] g;
00443 delete [] h;
00444 printf("Cannot converge to minimum after %d iterations with f(x) = %g\n", iteration, fx);
00445 return false ;
00446 }
00447
00448 double CMinimization::fn1( double x)
00449 {
00450 if ( false == TagMultiD)
00451 {
00452
00453 return sin(0.1 * x);
00454
00455
00456 }
00457 else
00458 {
00459
00460 for ( int i=0;i<n;i++)
00461 {
00462 linear_trial_x[i] = vec_x[i] + x*linear_dir[i];
00463 }
00464 return fn(linear_trial_x);
00465 }
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 void dummyfunctionname()
00510 {
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569 }
00570