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