00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef O2SCL_GSL_MMIN_SIMP_H
00024 #define O2SCL_GSL_MMIN_SIMP_H
00025
00026 #include <o2scl/multi_min.h>
00027 #include <o2scl/gsl_mmin_simp_b.h>
00028
00029 #ifndef DOXYGENP
00030 namespace o2scl {
00031 #endif
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 template<class param_t,class func_t=multi_funct<param_t>,
00049 class vec_t=ovector_view> class gsl_mmin_simp :
00050 public multi_min<param_t,func_t,func_t,vec_t>, public gsl_mmin_simp_b
00051 {
00052
00053 #ifndef DOXYGEN_INTERNAL
00054
00055 protected:
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 virtual double move_corner(const double coeff, const simp_state_t *state,
00066 size_t corner, gsl_vector *xc, func_t &f,
00067 size_t nvar, param_t &pa) {
00068
00069 gsl_matrix *x1=state->x1;
00070
00071 size_t i,j;
00072 double newval,mp;
00073
00074 if(x1->size1<2) {
00075 set_err("Simplex too small in gsl_mmin_simp::move_corner().",
00076 gsl_efailed);
00077 return 0.0;
00078 }
00079
00080 for (j=0;j<x1->size2;j++) {
00081 mp=0.0;
00082 for (i=0;i<x1->size1;i++) {
00083 if (i!=corner) {
00084 mp+=(gsl_matrix_get(x1,i,j));
00085 }
00086 }
00087 mp/=(double)(x1->size1-1);
00088 newval=mp-coeff*(mp-gsl_matrix_get(x1,corner,j));
00089 gsl_vector_set(xc,j,newval);
00090 }
00091
00092 f(nvar,*((ovector *)xc),newval,pa);
00093
00094 return newval;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 virtual int contract_by_best(simp_state_t *state, size_t best,
00106 gsl_vector *xc, func_t &f,
00107 size_t nvar, param_t &pa) {
00108
00109 gsl_matrix *x1=state->x1;
00110 gsl_vector *y1=state->y1;
00111
00112 size_t i,j;
00113 double newval;
00114
00115 for (i=0;i<x1->size1;i++) {
00116 if (i!=best) {
00117 for (j=0;j<x1->size2;j++) {
00118 newval=0.5*(gsl_matrix_get(x1,i,j)
00119 +gsl_matrix_get(x1,best,j));
00120 gsl_matrix_set(x1,i,j,newval);
00121 }
00122
00123
00124 gsl_matrix_get_row(xc,x1,i);
00125 f(nvar,*((ovector *)xc),newval,pa);
00126 gsl_vector_set(y1,i,newval);
00127 }
00128 }
00129
00130 return gsl_success;
00131 }
00132
00133
00134 size_t dim;
00135
00136
00137 gsl_vector *x;
00138
00139
00140 double fval;
00141
00142
00143 func_t *func;
00144
00145
00146 param_t *params;
00147
00148
00149 bool set_called;
00150
00151
00152 double size;
00153
00154
00155 simp_state_t lstate;
00156
00157 #endif
00158
00159 public:
00160
00161 gsl_mmin_simp() {
00162 dim=0;
00163 initial_step=1.0;
00164 print_simplex=0;
00165 }
00166
00167 virtual ~gsl_mmin_simp() {}
00168
00169
00170 double initial_step;
00171
00172
00173
00174
00175
00176
00177
00178
00179 int print_simplex;
00180
00181
00182
00183
00184 virtual int mmin(size_t nn, vec_t &xx, double &fmin, param_t &pa,
00185 func_t &ufunc) {
00186
00187 int ret=0,status,iter=0;
00188
00189 allocate(nn);
00190
00191 ovector ss(nn);
00192 for (size_t is=0;is<nn;is++) ss[is]=initial_step;
00193 ret=set(ufunc,pa,xx,ss);
00194 if(ret!=0) {
00195 free();
00196 return ret;
00197 }
00198
00199 do {
00200 iter++;
00201
00202 status=iterate();
00203 if(status) break;
00204
00205 if(this->verbose>0) {
00206 ovector *tx=(ovector *)(x);
00207 print_iter(nn,*tx,fval,iter,size,this->tolx,
00208 "gsl_mmin_nmsimplex");
00209 }
00210
00211 status=gsl_multimin_test_size(size,this->tolx);
00212
00213 } while(status == GSL_CONTINUE && iter<this->ntrial);
00214
00215 for (size_t i=0;i<nn;i++) xx[i]=gsl_vector_get(x,i);
00216 fmin=fval;
00217
00218 if(iter>=this->ntrial) {
00219 set_err_ret("Exceeded max # of iterations in gsl_mmin_simp::mmin().",
00220 gsl_emaxiter);
00221 }
00222
00223 free();
00224 this->last_ntrial=iter;
00225
00226 return status;
00227 }
00228
00229
00230
00231
00232
00233 virtual int mmin_twovec(size_t nn, vec_t &xx, vec_t &xx2, double &fmin,
00234 param_t &pa, func_t &ufunc) {
00235
00236 int ret=0,i,status,iter=0;
00237
00238 allocate(nn);
00239
00240 ovector ss(nn);
00241 for (size_t is=0;is<nn;is++) ss[is]=xx2[is]-xx[is];
00242 ret=set(ufunc,pa,xx,ss);
00243 if(ret!=0) {
00244 free();
00245 return ret;
00246 }
00247
00248 do {
00249 iter++;
00250
00251 status=iterate();
00252 if(status) break;
00253
00254 if(this->verbose>0) {
00255 ovector *tx=(ovector *)(x);
00256 print_iter(nn,*tx,fval,iter,size,this->tolx,
00257 "gsl_mmin_nmsimplex");
00258 }
00259
00260 status=gsl_multimin_test_size(size,this->tolx);
00261
00262 } while(status == GSL_CONTINUE && iter<this->ntrial);
00263
00264 for (i=0;i<((int)nn);i++) xx[i]=gsl_vector_get(x,i);
00265 fmin=fval;
00266
00267 if(iter>=this->ntrial) {
00268 set_err_ret
00269 ("Exceeded max # of iterations in gsl_mmin_simp::mmin_twovec().",
00270 gsl_emaxiter);
00271 }
00272
00273 free();
00274 this->last_ntrial=iter;
00275
00276 return status;
00277 }
00278
00279
00280 virtual int allocate(size_t n) {
00281 int status;
00282 if(dim!=0) free();
00283 set_called=false;
00284 dim=n;
00285
00286 x=gsl_vector_calloc(n);
00287 if(x == 0) {
00288 GSL_ERROR_VAL("failed to allocate space for x",GSL_ENOMEM,0);
00289 }
00290
00291 lstate.x1=gsl_matrix_alloc(n+1,n);
00292 if(lstate.x1 == NULL) {
00293 set_err("Failed to allocate x1 in gsl_mmin_nmsimplex::allocate().",
00294 gsl_enomem);
00295 }
00296
00297 lstate.y1=gsl_vector_alloc(n+1);
00298 if(lstate.y1 == NULL) {
00299 set_err("Failed to allocate y1 in gsl_mmin_nmsimplex::allocate().",
00300 gsl_enomem);
00301 }
00302
00303 lstate.ws1=gsl_vector_alloc(n);
00304 if(lstate.ws1 == NULL) {
00305 set_err("Failed to allocate ws1 in gsl_mmin_nmsimplex::allocate().",
00306 gsl_enomem);
00307 }
00308
00309 lstate.ws2=gsl_vector_alloc(n);
00310 if(lstate.ws2 == NULL) {
00311 set_err("Failed to allocate ws2 in gsl_mmin_nmsimplex::allocate().",
00312 gsl_enomem);
00313 }
00314
00315 return gsl_success;
00316 }
00317
00318
00319 virtual int free() {
00320
00321 gsl_matrix_free(lstate.x1);
00322 gsl_vector_free(lstate.y1);
00323 gsl_vector_free(lstate.ws1);
00324 gsl_vector_free(lstate.ws2);
00325 gsl_vector_free(x);
00326
00327 dim=0;
00328
00329 return 0;
00330 }
00331
00332
00333 virtual int set(func_t &ufunc, param_t &pa, vec_t &ax,
00334 vec_t &step_size) {
00335 size_t i;
00336
00337 if(dim==0) {
00338 set_err_ret("Memory not allocated in gsl_mmin_nmsimplex::set().",
00339 gsl_ebadlen);
00340 }
00341
00342 if(dim>ax.size()) {
00343 set_err_ret("Initial guess<solver size in gsl_mmin_nmsimplex::set().",
00344 gsl_ebadlen);
00345 }
00346
00347 params=&pa;
00348
00349
00350
00351 for (i=0;i<dim;i++) gsl_vector_set(x,i,ax[i]);
00352
00353 func=&ufunc;
00354
00355 double val;
00356 int status;
00357
00358 gsl_vector *xtemp=lstate.ws1;
00359
00360
00361
00362 ufunc(dim,ax,val,pa);
00363 gsl_matrix_set_row(lstate.x1,0,x);
00364 gsl_vector_set(lstate.y1,0,val);
00365
00366
00367
00368 for (i=0;i<x->size;i++) {
00369 status=gsl_vector_memcpy(xtemp,x);
00370
00371 if(status != 0) {
00372 GSL_ERROR("vector memcopy failed",GSL_EFAILED);
00373 }
00374
00375 val=gsl_vector_get(xtemp,i)+
00376 gsl_vector_get((gsl_vector *)(&step_size),i);
00377 gsl_vector_set(xtemp,i,val);
00378 ufunc(dim,*((ovector *)xtemp),val,pa);
00379 gsl_matrix_set_row(lstate.x1,i+1,xtemp);
00380 gsl_vector_set(lstate.y1,i+1,val);
00381 }
00382
00383
00384
00385 size=nmsimplex_size(&lstate);
00386
00387 set_called=true;
00388
00389 return gsl_success;
00390 }
00391
00392
00393 virtual int iterate() {
00394
00395 simp_state_t *nstate=&lstate;
00396
00397
00398
00399 gsl_vector *xc=nstate->ws1;
00400 gsl_vector *xc2=nstate->ws2;
00401 gsl_vector *y1=nstate->y1;
00402 gsl_matrix *x1=nstate->x1;
00403
00404 size_t n=y1->size;
00405 size_t i;
00406 size_t hi=0,s_hi=0,lo=0;
00407 double dhi,ds_hi,dlo;
00408 int status;
00409 double val,val2;
00410
00411
00412
00413 dhi=ds_hi=dlo=gsl_vector_get(y1,0);
00414
00415 for (i=1;i<n;i++) {
00416 val =(gsl_vector_get(y1,i));
00417 if(val<dlo) {
00418 dlo=val;
00419 lo=i;
00420 } else if (val > dhi) {
00421 ds_hi=dhi;
00422 s_hi=hi;
00423 dhi=val;
00424 hi=i;
00425 } else if(val > ds_hi) {
00426 ds_hi=val;
00427 s_hi=i;
00428 }
00429 }
00430
00431
00432
00433 val=move_corner(-1.0,nstate,hi,xc,*func,dim,*params);
00434
00435 if (val<gsl_vector_get(y1,lo)) {
00436
00437
00438
00439 val2=move_corner(-2.0,nstate,hi,xc2,*func,dim,*params);
00440 if (val2<gsl_vector_get(y1,lo)) {
00441 gsl_matrix_set_row(x1,hi,xc2);
00442 gsl_vector_set(y1,hi,val2);
00443 } else {
00444 gsl_matrix_set_row(x1,hi,xc);
00445 gsl_vector_set(y1,hi,val);
00446 }
00447
00448 } else if (val > gsl_vector_get(y1,s_hi)) {
00449
00450
00451
00452 if(val <= gsl_vector_get(y1,hi)) {
00453
00454
00455
00456
00457 gsl_matrix_set_row(x1,hi,xc);
00458 gsl_vector_set(y1,hi,val);
00459 }
00460
00461
00462
00463 val2=move_corner(0.5,nstate,hi,xc2,*func,dim,*params);
00464
00465 if(val2 <= gsl_vector_get(y1,hi)) {
00466
00467 gsl_matrix_set_row(nstate->x1,hi,xc2);
00468 gsl_vector_set(y1,hi,val2);
00469
00470 } else {
00471
00472
00473
00474 status=contract_by_best(nstate,lo,xc,*func,dim,*params);
00475 if(status != 0) {
00476 set_err("Function contract_by_best() failed in iterate().",
00477 gsl_efailed);
00478 }
00479 }
00480
00481 } else {
00482
00483
00484
00485
00486 gsl_matrix_set_row(x1,hi,xc);
00487 gsl_vector_set(y1,hi,val);
00488 }
00489
00490
00491
00492 lo=gsl_vector_min_index(y1);
00493 gsl_matrix_get_row(x,x1,lo);
00494 fval=gsl_vector_get(y1,lo);
00495
00496
00497
00498 size=nmsimplex_size(nstate);
00499
00500 return gsl_success;
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 virtual int print_iter(size_t nv, vec_t &xx, double y, int iter,
00514 double value, double limit,
00515 std::string comment) {
00516 if (this->verbose<=0) return 0;
00517
00518 int i;
00519 char ch;
00520
00521 std::cout << comment << " Iteration: " << iter << std::endl;
00522 text_out_file outs(&std::cout,79);
00523 outs.word_out("x:");
00524 for(i=0;i<((int)nv);i++) outs.double_out(xx[i]);
00525 outs.end_line();
00526 if (print_simplex==1) {
00527 ovector_view *ov=(ovector_view *)(lstate.y1);
00528 outs.word_out("simp vals:");
00529 for(i=0;i<((int)nv+1);i++) {
00530 outs.double_out((*ov)[i]);
00531 }
00532 outs.end_line();
00533 }
00534 std::cout << "y: " << y << " Val: " << value << " Lim: "
00535 << limit << std::endl;
00536 if (this->verbose>1) {
00537 std::cout << "Press a key and type enter to continue. ";
00538 std::cin >> ch;
00539 }
00540
00541 return 0;
00542 }
00543
00544
00545 virtual const char *type() { return "gsl_mmin_simp";}
00546
00547 };
00548
00549 #ifndef DOXYGENP
00550 }
00551 #endif
00552
00553 #endif