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