00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 Some of the source code in this file has been adapted from OOL 00009 library written by Sergio Drumond Ventura, Luis Alberto D'Afonseca, 00010 and Ricardo Biloti available from http://ool.sourceforge.net. 00011 00012 O2scl is free software; you can redistribute it and/or modify 00013 it under the terms of the GNU General Public License as published by 00014 the Free Software Foundation; either version 3 of the License, or 00015 (at your option) any later version. 00016 00017 O2scl is distributed in the hope that it will be useful, 00018 but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 GNU General Public License for more details. 00021 00022 You should have received a copy of the GNU General Public License 00023 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00024 00025 ------------------------------------------------------------------- 00026 */ 00027 #ifndef O2SCL_OOL_CONSTR_MMIN_H 00028 #define O2SCL_OOL_CONSTR_MMIN_H 00029 00030 #include <o2scl/text_file.h> 00031 #include <o2scl/ovector_tlate.h> 00032 #include <o2scl/multi_funct.h> 00033 #include <o2scl/multi_min.h> 00034 #include <o2scl/vec_arith.h> 00035 00036 #ifndef DOXYGENP 00037 namespace o2scl { 00038 #endif 00039 00040 /** 00041 \brief Hessian product function for ool_constr_mmin [abstract base] 00042 */ 00043 template<class param_t, class vec_t=ovector_view> class ool_hfunct { 00044 00045 public: 00046 00047 ool_hfunct() {} 00048 00049 virtual ~ool_hfunct() {} 00050 00051 /** \brief Evaluate \f$ H(x) \cdot v \f$ 00052 */ 00053 virtual int operator()(size_t nv, const vec_t &x, const vec_t &v, 00054 vec_t &hv, param_t &pa)=0; 00055 00056 #ifndef DOXYGENP 00057 00058 private: 00059 00060 ool_hfunct(const ool_hfunct &); 00061 ool_hfunct& operator=(const ool_hfunct&); 00062 00063 #endif 00064 00065 }; 00066 00067 /** \brief A hessian product supplied by a function pointer 00068 */ 00069 template<class param_t, class vec_t=ovector_view> 00070 class ool_hfunct_fptr : public ool_hfunct<param_t,vec_t> { 00071 00072 public: 00073 00074 /** \brief Specify the function pointer 00075 */ 00076 ool_hfunct_fptr(int (*fp)(size_t nv, const vec_t &x, const vec_t &v, 00077 vec_t &hv, param_t &pa)) { 00078 fptr=fp; 00079 } 00080 00081 00082 virtual ~ool_hfunct_fptr() {}; 00083 00084 /** \brief Evaluate \f$ H(x) \cdot v \f$ 00085 */ 00086 virtual int operator()(size_t nv, const vec_t &x, const vec_t &v, 00087 vec_t &hv, param_t &pa) { 00088 return fptr(nv,x,v,hv,pa); 00089 } 00090 00091 #ifndef DOXYGEN_INTERNAL 00092 00093 protected: 00094 00095 friend class io_tlate<ool_hfunct_fptr>; 00096 00097 /// Store the function pointer 00098 int (*fptr)(size_t nv, const vec_t &x, const vec_t &v, vec_t &hv, 00099 param_t &pa); 00100 00101 ool_hfunct_fptr() {} 00102 00103 #ifndef DOXYGENP 00104 #endif 00105 00106 private: 00107 00108 ool_hfunct_fptr(const ool_hfunct_fptr &); 00109 ool_hfunct_fptr& operator=(const ool_hfunct_fptr&); 00110 00111 #endif 00112 00113 }; 00114 00115 /** \brief A hessian product supplied by a member function pointer 00116 */ 00117 template<class tclass, class param_t, class vec_t=ovector_view> 00118 class ool_hfunct_mfptr : public ool_hfunct<param_t,vec_t> { 00119 public: 00120 00121 /** \brief Specify the class instance and member function pointer 00122 */ 00123 ool_hfunct_mfptr(tclass *tp, int (tclass::*fp) 00124 (size_t nv, const vec_t &x, const vec_t &v, 00125 vec_t &hv, param_t &pa)) { 00126 tptr=tp; 00127 fptr=fp; 00128 } 00129 00130 virtual ~ool_hfunct_mfptr() {} 00131 00132 /** \brief Evaluate \f$ H(x) \cdot v \f$ 00133 */ 00134 virtual int operator()(size_t nv, const vec_t &x, const vec_t &v, 00135 vec_t &hv, param_t &pa) { 00136 return (*tptr.*fptr)(nv,x,v,hv,pa); 00137 } 00138 00139 #ifndef DOXYGEN_INTERNAL 00140 00141 protected: 00142 00143 /// Store the function pointer 00144 int (tclass::*fptr)(size_t nv, const vec_t &x, const vec_t &v, 00145 vec_t &hv, param_t &pa); 00146 /// Store a pointer to the class instance 00147 tclass *tptr; 00148 00149 #ifndef DOXYGENP 00150 #endif 00151 00152 private: 00153 00154 ool_hfunct_mfptr(const ool_hfunct_mfptr &); 00155 ool_hfunct_mfptr& operator=(const ool_hfunct_mfptr&); 00156 00157 #endif 00158 00159 }; 00160 00161 // --------------------------------------------------------------------- 00162 // Array-type hessian function classes 00163 // --------------------------------------------------------------------- 00164 00165 /** 00166 \brief Hessian product function base for ool_constr_mmin using arrays 00167 */ 00168 template<class param_t, size_t nvar> class ool_hvfunct { 00169 00170 public: 00171 00172 ool_hvfunct() {} 00173 00174 virtual ~ool_hvfunct() {} 00175 00176 /** \brief Evaluate \f$ H(x) \cdot v \f$ 00177 */ 00178 virtual int operator()(size_t nv, const double x[nvar], 00179 const double v[nvar], double hv[nvar], 00180 param_t &pa)=0; 00181 00182 #ifndef DOXYGENP 00183 00184 private: 00185 00186 ool_hvfunct(const ool_hvfunct &); 00187 ool_hvfunct& operator=(const ool_hvfunct&); 00188 00189 #endif 00190 00191 }; 00192 00193 /** \brief A hessian product supplied by a function pointer using arrays 00194 */ 00195 template<class param_t, size_t nvar> 00196 class ool_hvfunct_fptr : public ool_hvfunct<param_t,nvar> { 00197 00198 public: 00199 00200 /** \brief Specify the function pointer 00201 */ 00202 ool_hvfunct_fptr(int (*fp)(size_t nv, const double x[nvar], 00203 const double v[nvar], double hv[nvar], 00204 param_t &pa)) { 00205 fptr=fp; 00206 } 00207 00208 00209 virtual ~ool_hvfunct_fptr() {} 00210 00211 /** \brief Evaluate \f$ H(x) \cdot v \f$ 00212 */ 00213 virtual int operator()(size_t nv, const double x[nvar], 00214 const double v[nvar], double hv[nvar], 00215 param_t &pa) { 00216 return fptr(nv,x,v,hv,pa); 00217 } 00218 00219 #ifndef DOXYGEN_INTERNAL 00220 00221 protected: 00222 00223 friend class io_tlate<ool_hvfunct_fptr>; 00224 00225 /// Store the function pointer 00226 int (*fptr)(size_t nv, const double x[nvar], const double v[nvar], 00227 double hv[nvar], param_t &pa); 00228 00229 ool_hvfunct_fptr() {} 00230 00231 #ifndef DOXYGENP 00232 #endif 00233 00234 private: 00235 00236 ool_hvfunct_fptr(const ool_hvfunct_fptr &); 00237 ool_hvfunct_fptr& operator=(const ool_hvfunct_fptr&); 00238 00239 #endif 00240 00241 }; 00242 00243 /** \brief A hessian product supplied by a member function pointer 00244 using arrays 00245 */ 00246 template<class tclass, class param_t, size_t nvar> 00247 class ool_hvfunct_mfptr : public ool_hvfunct<param_t,nvar> { 00248 public: 00249 00250 /** \brief Specify the member function pointer 00251 */ 00252 ool_hvfunct_mfptr(tclass *tp, int (tclass::*fp) 00253 (size_t nv, const double x[nvar], 00254 const double v[nvar], double hv[nvar], 00255 param_t &pa)) { 00256 tptr=tp; 00257 fptr=fp; 00258 } 00259 00260 virtual ~ool_hvfunct_mfptr() {} 00261 00262 /** \brief Evaluate \f$ H(x) \cdot v \f$ 00263 */ 00264 virtual int operator()(size_t nv, const double x[nvar], 00265 const double v[nvar], double hv[nvar], 00266 param_t &pa) { 00267 return (*tptr.*fptr)(nv,x,v,hv,pa); 00268 } 00269 00270 #ifndef DOXYGEN_INTERNAL 00271 00272 protected: 00273 00274 /// Store the function pointer 00275 int (tclass::*fptr)(size_t nv, const double x[nvar], 00276 const double v[nvar], double hv[nvar], 00277 param_t &pa); 00278 00279 /// Store a pointer to the class instance 00280 tclass *tptr; 00281 00282 #ifndef DOXYGENP 00283 #endif 00284 00285 private: 00286 00287 ool_hvfunct_mfptr(const ool_hvfunct_mfptr &); 00288 ool_hvfunct_mfptr& operator=(const ool_hvfunct_mfptr&); 00289 00290 #endif 00291 00292 }; 00293 00294 /** 00295 \brief Constrained multidimensional minimization base (OOL) 00296 00297 \todo Implement automatic computations of gradient and Hessian 00298 \todo Construct a non-trivial example for the "examples" directory 00299 \todo Finish mmin() interface 00300 */ 00301 template<class param_t, class func_t, class dfunc_t=func_t, 00302 class hfunc_t=func_t, class vec_t=ovector_view, 00303 class alloc_vec_t=ovector, class alloc_t=ovector_alloc> 00304 class ool_constr_mmin : public multi_min<param_t,func_t,dfunc_t,vec_t> { 00305 00306 public: 00307 00308 /// \name OOL-specific error codes 00309 //@{ 00310 /// Lower unbounded function 00311 static const int OOL_UNBOUNDEDF = 1101; 00312 /// Infeasible point 00313 static const int OOL_INFEASIBLE = 1102; 00314 /// Too many inner iterations 00315 static const int OOL_FINNERIT = 1103; 00316 /// Line search failed 00317 static const int OOL_FLSEARCH = 1104; 00318 /// Unable to find a descent direction 00319 static const int OOL_FDDIR = 1105; 00320 //@} 00321 00322 #ifndef DOXYGEN_INTERNAL 00323 00324 protected: 00325 00326 /// The current function value 00327 double f; 00328 /// Desc 00329 double size; 00330 00331 /// Memory allocation object 00332 alloc_t ao; 00333 00334 /// The current minimum vector 00335 alloc_vec_t x; 00336 /// The current gradient vector 00337 alloc_vec_t gradient; 00338 /// Desc 00339 alloc_vec_t dx; 00340 00341 /// Number of function evaluations 00342 size_t fcount; 00343 /// Number of gradient evaluations 00344 size_t gcount; 00345 /// Number of Hessian evaluations 00346 size_t hcount; 00347 00348 /// Number of parameters 00349 size_t dim; 00350 /// Number of constraints 00351 size_t nconstr; 00352 /// User-supplied function 00353 func_t *func; 00354 /// Gradient function 00355 dfunc_t *dfunc; 00356 /// Hessian function 00357 hfunc_t *hfunc; 00358 /// User-specified parameters 00359 param_t *param; 00360 00361 /// Lower bound constraints 00362 alloc_vec_t L; 00363 /// Upper bound constraints 00364 alloc_vec_t U; 00365 00366 /// If true, the algorithm requires the hessian vector product 00367 bool requires_hess; 00368 00369 /// Shrink vector \c V from the full to the reduced space 00370 void shrink(const size_t nind, gsl_vector_uint *Ind, 00371 const vec_t &V) { 00372 size_t ii, indii; 00373 00374 for( ii = 0; ii < nind; ii++ ) { 00375 indii = gsl_vector_uint_get(Ind,ii); 00376 00377 double tmp=V[ii]; 00378 V[ii]=V[indii]; 00379 V[indii]=tmp; 00380 } 00381 } 00382 00383 /// Expand vector \c V from the reduced to the full space 00384 void expand(const size_t nind, gsl_vector_uint *Ind, 00385 const vec_t &V) { 00386 00387 size_t jj, ii, indii; 00388 00389 ii = nind; 00390 for( jj = 0; jj < nind; jj++ ) { 00391 ii--; 00392 indii = gsl_vector_uint_get( Ind, ii ); 00393 00394 double tmp=V[ii]; 00395 V[ii]=V[indii]; 00396 V[indii]=tmp; 00397 } 00398 } 00399 00400 /// Evaluate the objective function from the reduced space 00401 double calc_f(const size_t nind, gsl_vector_uint *Ind, 00402 vec_t &X, vec_t &Xc) { 00403 00404 const size_t missing=this->dim-nind; 00405 double ftmp; 00406 00407 if (missing>0) { 00408 00409 // Complete X with values from Xc 00410 for(size_t i=nind;i<nind+missing;i++) { 00411 X[i]=Xc[i]; 00412 } 00413 00414 // Expand to full space 00415 expand(nind,Ind,X); 00416 } 00417 00418 // Compute f 00419 func(dim,X,ftmp,param); 00420 00421 if(missing>0) { 00422 // Shrink to reduced space 00423 shrink(nind,Ind,X); 00424 } 00425 00426 return f; 00427 } 00428 00429 /// Compute gradient in the reduced space 00430 int calc_g(const size_t nind, gsl_vector_uint *Ind, vec_t &X, 00431 vec_t &Xc, vec_t &G) { 00432 00433 const size_t missing=this->dim-nind; 00434 00435 if( missing > 0 ) { 00436 00437 // Complete X with values from Xc 00438 for(size_t i=nind;i<nind+missing;i++) { 00439 X[i]=Xc[i]; 00440 } 00441 00442 // Expand to full space 00443 expand(nind,Ind,X); 00444 } 00445 00446 // Compute gradient 00447 dfunc_t(dim,X,G,param); 00448 00449 if (missing>0) { 00450 // Shrink to reduced space 00451 shrink(nind,Ind,X); 00452 shrink(nind,Ind,G); 00453 } 00454 00455 return 0; 00456 } 00457 00458 /// Evaluate a hessian times a vector from the reduced space 00459 int calc_Hv(const size_t nind, gsl_vector_uint *Ind, 00460 vec_t &X, vec_t &Xc, vec_t &V, vec_t &Hv) { 00461 00462 const size_t missing=this->ndim-nind; 00463 00464 if (missing>0) { 00465 // Complete X with values from Xc and set V to zero 00466 for(size_t i=nind;i<nind+missing;i++) { 00467 X[i]=Xc[i]; 00468 V[i]=0.0; 00469 } 00470 /// Expand to full space 00471 expand(nind,Ind,X); 00472 expand(nind,Ind,V); 00473 } 00474 00475 // Compute gradient 00476 hfunc(this->dim,X,V,Hv); 00477 00478 if (missing>0) { 00479 // Shrink to reduced space 00480 shrink(nind,Ind,X); 00481 shrink(nind,Ind,V); 00482 shrink(nind,Ind,Hv); 00483 } 00484 00485 return 0; 00486 } 00487 00488 #endif 00489 00490 public: 00491 00492 ool_constr_mmin() { 00493 dim=0; 00494 nconstr=0; 00495 requires_hess=false; 00496 } 00497 00498 virtual ~ool_constr_mmin() { 00499 if (dim>0) free(); 00500 if (nconstr>0) { 00501 ao.free(L); 00502 ao.free(U); 00503 } 00504 } 00505 00506 /// Allocate memory 00507 virtual int allocate(const size_t n) { 00508 int status; 00509 00510 ao.allocate(x,n); 00511 ao.allocate(gradient,n); 00512 ao.allocate(dx,n); 00513 dim=n; 00514 00515 for(size_t i=0;i<n;i++) { 00516 x[i]=0.0; 00517 gradient[i]=0.0; 00518 dx[i]=0.0; 00519 } 00520 00521 return 0; 00522 } 00523 00524 /// Free previously allocated memory 00525 virtual int free() { 00526 ao.free(dx); 00527 ao.free(gradient); 00528 ao.free(x); 00529 return 0; 00530 } 00531 00532 /// Restart the minimizer 00533 virtual int restart() { 00534 00535 // Reset dx vector 00536 for(size_t i=0;i<dim;i++) dx[i]=0.0; 00537 00538 // Restart evaluation counters 00539 fcount = 0; 00540 gcount = 0; 00541 hcount = 0; 00542 00543 return 0; 00544 } 00545 00546 /// Set the function, the initial guess, and the parameters 00547 virtual int set(func_t &fn, dfunc_t &dfn, vec_t &init, param_t &par) { 00548 00549 o2scl::vector_copy(dim,init,x); 00550 for(size_t i=0;i<dim;i++) dx[i]=0.0; 00551 00552 func=&fn; 00553 dfunc=&dfn; 00554 param=∥ 00555 00556 // Start evaluation conunters 00557 fcount = 0; 00558 gcount = 0; 00559 hcount = 0; 00560 00561 return 0; 00562 } 00563 00564 /// Set the function, the initial guess, and the parameters 00565 virtual int set_hess(func_t &fn, dfunc_t &dfn, hfunc_t &hfn, 00566 vec_t &init, param_t &par) { 00567 00568 o2scl::vector_copy(dim,init,x); 00569 for(size_t i=0;i<dim;i++) dx[i]=0.0; 00570 00571 func=&fn; 00572 dfunc=&dfn; 00573 hfunc=&hfn; 00574 param=∥ 00575 00576 // Start evaluation conunters 00577 fcount = 0; 00578 gcount = 0; 00579 hcount = 0; 00580 00581 return 0; 00582 } 00583 00584 /// Set the constraints 00585 virtual int set_constraints(size_t nc, vec_t &lower, vec_t &upper) { 00586 if (nconstr>0) { 00587 ao.free(L); 00588 ao.free(U); 00589 } 00590 ao.allocate(L,nc); 00591 ao.allocate(U,nc); 00592 nconstr=nc; 00593 o2scl::vector_copy(nc,lower,L); 00594 o2scl::vector_copy(nc,upper,U); 00595 return 0; 00596 } 00597 00598 /// Perform an iteration 00599 virtual int iterate() { 00600 return 0; 00601 } 00602 00603 /// See if we're finished 00604 virtual int is_optimal() { 00605 return 0; 00606 } 00607 00608 /** \brief Calculate the minimum \c min of \c func w.r.t. the 00609 array \c x of size \c nvar. 00610 00611 \todo Need to finish this function somehow since it's 00612 pure virtual in multi_min. 00613 */ 00614 virtual int mmin(size_t nvar, vec_t &xx, double &fmin, param_t &pa, 00615 func_t &ff) 00616 { 00617 return 0; 00618 } 00619 00620 /** \brief Calculate the minimum \c min of \c ff 00621 w.r.t. the array \c x of size \c nvar with gradient 00622 \c df and hessian vector product \c hf 00623 */ 00624 virtual int mmin_hess(size_t nvar, vec_t &xx, double &fmin, param_t &pa, 00625 func_t &ff, dfunc_t &df, hfunc_t &hf) 00626 { 00627 00628 int status; 00629 allocate(nvar); 00630 if (requires_hess) set_hess(ff,df,hf,xx,pa); 00631 else set(ff,df,xx,pa); 00632 int it=0; 00633 do { 00634 status=iterate(); 00635 status=is_optimal(); 00636 it++; 00637 } while (it<this->ntrial && status==gsl_continue); 00638 00639 for(size_t i=0;i<nvar;i++) xx[i]=this->x[i]; 00640 fmin=this->f; 00641 this->last_ntrial=it; 00642 00643 free(); 00644 return 0; 00645 } 00646 00647 /** \brief Calculate the minimum \c min of \c func 00648 w.r.t. the array \c x of size \c nvar with gradient 00649 \c dfunc 00650 */ 00651 virtual int mmin_de(size_t nvar, vec_t &xx, double &fmin, param_t &pa, 00652 func_t &ff, dfunc_t &df) 00653 { 00654 00655 int status; 00656 allocate(nvar); 00657 set(ff,df,xx,pa); 00658 int it=0; 00659 do { 00660 status=iterate(); 00661 status=is_optimal(); 00662 it++; 00663 } while (it<this->ntrial && status==gsl_continue); 00664 00665 for(size_t i=0;i<nvar;i++) xx[i]=this->x[i]; 00666 fmin=this->f; 00667 this->last_ntrial=it; 00668 00669 free(); 00670 return 0; 00671 } 00672 00673 /// Return string denoting type ("ool_constr_mmin") 00674 const char *type() { return "ool_constr_mmin"; } 00675 00676 }; 00677 00678 #ifndef DOXYGENP 00679 } 00680 #endif 00681 00682 #endif 00683
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page