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