![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006-2012, 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/ovector_tlate.h> 00050 #include <o2scl/multi_funct.h> 00051 #include <o2scl/multi_min.h> 00052 #include <o2scl/vec_arith.h> 00053 00054 #ifndef DOXYGENP 00055 namespace o2scl { 00056 #endif 00057 00058 /** \brief Hessian product function for ool_constr_mmin [abstract base] 00059 */ 00060 template<class vec_t=ovector_base> class ool_hfunct { 00061 00062 public: 00063 00064 ool_hfunct() {} 00065 00066 virtual ~ool_hfunct() {} 00067 00068 /** \brief Evaluate \f$ H(x) \cdot v \f$ 00069 */ 00070 virtual int operator()(size_t nv, const vec_t &x, const vec_t &v, 00071 vec_t &hv)=0; 00072 00073 #ifndef DOXYGENP 00074 00075 private: 00076 00077 ool_hfunct(const ool_hfunct &); 00078 ool_hfunct& operator=(const ool_hfunct&); 00079 00080 #endif 00081 00082 }; 00083 00084 /** \brief A hessian product supplied by a function pointer 00085 */ 00086 template<class vec_t=ovector_base> 00087 class ool_hfunct_fptr : public ool_hfunct<vec_t> { 00088 00089 public: 00090 00091 /** \brief Specify the function pointer 00092 */ 00093 ool_hfunct_fptr(int (*fp)(size_t nv, const vec_t &x, const vec_t &v, 00094 vec_t &hv)) { 00095 fptr=fp; 00096 } 00097 00098 00099 virtual ~ool_hfunct_fptr() {}; 00100 00101 /** \brief Evaluate \f$ H(x) \cdot v \f$ 00102 */ 00103 virtual int operator()(size_t nv, const vec_t &x, const vec_t &v, 00104 vec_t &hv) { 00105 return fptr(nv,x,v,hv); 00106 } 00107 00108 #ifndef DOXYGEN_INTERNAL 00109 00110 protected: 00111 00112 /// Store the function pointer 00113 int (*fptr)(size_t nv, const vec_t &x, const vec_t &v, vec_t &hv); 00114 00115 ool_hfunct_fptr() {} 00116 00117 #ifndef DOXYGENP 00118 #endif 00119 00120 private: 00121 00122 ool_hfunct_fptr(const ool_hfunct_fptr &); 00123 ool_hfunct_fptr& operator=(const ool_hfunct_fptr&); 00124 00125 #endif 00126 00127 }; 00128 00129 /** \brief A hessian product supplied by a member function pointer 00130 */ 00131 template<class tclass, class vec_t=ovector_base> 00132 class ool_hfunct_mfptr : public ool_hfunct<vec_t> { 00133 public: 00134 00135 /** \brief Specify the class instance and member function pointer 00136 */ 00137 ool_hfunct_mfptr(tclass *tp, int (tclass::*fp) 00138 (size_t nv, const vec_t &x, const vec_t &v, 00139 vec_t &hv)) { 00140 tptr=tp; 00141 fptr=fp; 00142 } 00143 00144 virtual ~ool_hfunct_mfptr() {} 00145 00146 /** \brief Evaluate \f$ H(x) \cdot v \f$ 00147 */ 00148 virtual int operator()(size_t nv, const vec_t &x, const vec_t &v, 00149 vec_t &hv) { 00150 return (*tptr.*fptr)(nv,x,v,hv); 00151 } 00152 00153 #ifndef DOXYGEN_INTERNAL 00154 00155 protected: 00156 00157 /// Store the function pointer 00158 int (tclass::*fptr)(size_t nv, const vec_t &x, const vec_t &v, 00159 vec_t &hv); 00160 00161 /// Store a pointer to the class instance 00162 tclass *tptr; 00163 00164 #ifndef DOXYGENP 00165 #endif 00166 00167 private: 00168 00169 ool_hfunct_mfptr(const ool_hfunct_mfptr &); 00170 ool_hfunct_mfptr& operator=(const ool_hfunct_mfptr&); 00171 00172 #endif 00173 00174 }; 00175 00176 /** \brief Constrained multidimensional minimization (OOL) [abstract base] 00177 00178 \future Implement automatic computations of \gradient and Hessian 00179 \future Construct a more difficult example for the "examples" directory 00180 \future Finish mmin() interface 00181 \future Implement a direct computation of the hessian as the 00182 jacobian of the gradient 00183 */ 00184 template<class func_t, class dfunc_t=func_t, 00185 class hfunc_t=func_t, class vec_t=ovector_base, 00186 class alloc_vec_t=ovector, class alloc_t=ovector_alloc> 00187 class ool_constr_mmin : public multi_min<func_t,dfunc_t,vec_t> { 00188 00189 public: 00190 00191 #ifndef DOXYGEN_INTERNAL 00192 00193 protected: 00194 00195 /// The current function value 00196 double f; 00197 /// Desc 00198 double size; 00199 00200 /// Memory allocation object 00201 alloc_t ao; 00202 00203 /// The current minimum vector 00204 alloc_vec_t x; 00205 /// The current gradient vector 00206 alloc_vec_t gradient; 00207 /// Desc 00208 alloc_vec_t dx; 00209 00210 /// Number of function evaluations 00211 size_t fcount; 00212 /// Number of gradient evaluations 00213 size_t gcount; 00214 /// Number of Hessian evaluations 00215 size_t hcount; 00216 00217 /// Number of parameters 00218 size_t dim; 00219 /// Number of constraints 00220 size_t nconstr; 00221 /// User-supplied function 00222 func_t *func; 00223 /// Gradient function 00224 dfunc_t *dfunc; 00225 /// Hessian function 00226 hfunc_t *hfunc; 00227 00228 /// Lower bound constraints 00229 alloc_vec_t L; 00230 /// Upper bound constraints 00231 alloc_vec_t U; 00232 00233 /// If true, the algorithm requires the hessian vector product 00234 bool requires_hess; 00235 00236 /// Shrink vector \c V from the full to the reduced space 00237 void shrink(const size_t nind, gsl_vector_uint *Ind, 00238 const vec_t &V) { 00239 size_t ii, indii; 00240 00241 for( ii = 0; ii < nind; ii++ ) { 00242 indii = gsl_vector_uint_get(Ind,ii); 00243 00244 double tmp=V[ii]; 00245 V[ii]=V[indii]; 00246 V[indii]=tmp; 00247 } 00248 } 00249 00250 /// Expand vector \c V from the reduced to the full space 00251 void expand(const size_t nind, gsl_vector_uint *Ind, 00252 const vec_t &V) { 00253 00254 size_t jj, ii, indii; 00255 00256 ii = nind; 00257 for( jj = 0; jj < nind; jj++ ) { 00258 ii--; 00259 indii = gsl_vector_uint_get( Ind, ii ); 00260 00261 double tmp=V[ii]; 00262 V[ii]=V[indii]; 00263 V[indii]=tmp; 00264 } 00265 } 00266 00267 /// Evaluate the objective function from the reduced space 00268 double calc_f(const size_t nind, gsl_vector_uint *Ind, 00269 vec_t &X, vec_t &Xc) { 00270 00271 const size_t missing=this->dim-nind; 00272 double ftmp; 00273 00274 if (missing>0) { 00275 00276 // Complete X with values from Xc 00277 for(size_t i=nind;i<nind+missing;i++) { 00278 X[i]=Xc[i]; 00279 } 00280 00281 // Expand to full space 00282 expand(nind,Ind,X); 00283 } 00284 00285 // Compute f 00286 func(dim,X,ftmp); 00287 00288 if(missing>0) { 00289 // Shrink to reduced space 00290 shrink(nind,Ind,X); 00291 } 00292 00293 return f; 00294 } 00295 00296 /// Compute gradient in the reduced space 00297 int calc_g(const size_t nind, gsl_vector_uint *Ind, vec_t &X, 00298 vec_t &Xc, vec_t &G) { 00299 00300 const size_t missing=this->dim-nind; 00301 00302 if( missing > 0 ) { 00303 00304 // Complete X with values from Xc 00305 for(size_t i=nind;i<nind+missing;i++) { 00306 X[i]=Xc[i]; 00307 } 00308 00309 // Expand to full space 00310 expand(nind,Ind,X); 00311 } 00312 00313 // Compute gradient 00314 dfunc_t(dim,X,G); 00315 00316 if (missing>0) { 00317 // Shrink to reduced space 00318 shrink(nind,Ind,X); 00319 shrink(nind,Ind,G); 00320 } 00321 00322 return 0; 00323 } 00324 00325 /// Evaluate a hessian times a vector from the reduced space 00326 int calc_Hv(const size_t nind, gsl_vector_uint *Ind, 00327 vec_t &X, vec_t &Xc, vec_t &V, vec_t &Hv) { 00328 00329 const size_t missing=this->ndim-nind; 00330 00331 if (missing>0) { 00332 // Complete X with values from Xc and set V to zero 00333 for(size_t i=nind;i<nind+missing;i++) { 00334 X[i]=Xc[i]; 00335 V[i]=0.0; 00336 } 00337 /// Expand to full space 00338 expand(nind,Ind,X); 00339 expand(nind,Ind,V); 00340 } 00341 00342 // Compute gradient 00343 hfunc(this->dim,X,V,Hv); 00344 00345 if (missing>0) { 00346 // Shrink to reduced space 00347 shrink(nind,Ind,X); 00348 shrink(nind,Ind,V); 00349 shrink(nind,Ind,Hv); 00350 } 00351 00352 return 0; 00353 } 00354 00355 #endif 00356 00357 public: 00358 00359 ool_constr_mmin() { 00360 dim=0; 00361 nconstr=0; 00362 requires_hess=false; 00363 } 00364 00365 virtual ~ool_constr_mmin() { 00366 if (dim>0) free(); 00367 if (nconstr>0) { 00368 ao.free(L); 00369 ao.free(U); 00370 } 00371 } 00372 00373 /// Allocate memory 00374 virtual int allocate(const size_t n) { 00375 int status; 00376 00377 ao.allocate(x,n); 00378 ao.allocate(gradient,n); 00379 ao.allocate(dx,n); 00380 dim=n; 00381 00382 for(size_t i=0;i<n;i++) { 00383 x[i]=0.0; 00384 gradient[i]=0.0; 00385 dx[i]=0.0; 00386 } 00387 00388 return 0; 00389 } 00390 00391 /// Free previously allocated memory 00392 virtual int free() { 00393 ao.free(dx); 00394 ao.free(gradient); 00395 ao.free(x); 00396 return 0; 00397 } 00398 00399 /// Restart the minimizer 00400 virtual int restart() { 00401 00402 // Reset dx vector 00403 for(size_t i=0;i<dim;i++) dx[i]=0.0; 00404 00405 // Restart evaluation counters 00406 fcount = 0; 00407 gcount = 0; 00408 hcount = 0; 00409 00410 return 0; 00411 } 00412 00413 /// Set the function, the gradient, and the initial guess 00414 virtual int set(func_t &fn, dfunc_t &dfn, vec_t &init) { 00415 00416 o2scl::vector_copy(dim,init,x); 00417 for(size_t i=0;i<dim;i++) dx[i]=0.0; 00418 00419 func=&fn; 00420 dfunc=&dfn; 00421 00422 // Start evaluation conunters 00423 fcount = 0; 00424 gcount = 0; 00425 hcount = 0; 00426 00427 return 0; 00428 } 00429 00430 /** \brief Set the function, the gradient, the Hessian product, 00431 and the initial guess 00432 */ 00433 virtual int set_hess(func_t &fn, dfunc_t &dfn, hfunc_t &hfn, 00434 vec_t &init) { 00435 00436 o2scl::vector_copy(dim,init,x); 00437 for(size_t i=0;i<dim;i++) dx[i]=0.0; 00438 00439 func=&fn; 00440 dfunc=&dfn; 00441 hfunc=&hfn; 00442 00443 // Start evaluation conunters 00444 fcount = 0; 00445 gcount = 0; 00446 hcount = 0; 00447 00448 return 0; 00449 } 00450 00451 /// Set the constraints 00452 virtual int set_constraints(size_t nc, vec_t &lower, vec_t &upper) { 00453 if (nconstr>0) { 00454 ao.free(L); 00455 ao.free(U); 00456 } 00457 ao.allocate(L,nc); 00458 ao.allocate(U,nc); 00459 nconstr=nc; 00460 o2scl::vector_copy(nc,lower,L); 00461 o2scl::vector_copy(nc,upper,U); 00462 return 0; 00463 } 00464 00465 /// Perform an iteration 00466 virtual int iterate()=0; 00467 00468 /// See if we're finished 00469 virtual int is_optimal()=0; 00470 00471 /** \brief Calculate the minimum \c min of \c func w.r.t. the 00472 array \c x of size \c nvar. 00473 00474 \note This is unimplemented. 00475 */ 00476 virtual int mmin(size_t nvar, vec_t &xx, double &fmin, 00477 func_t &ff) 00478 { 00479 O2SCL_ERR_RET("Not yet implemented ool_constr_mmin::mmin().", 00480 gsl_eunimpl); 00481 } 00482 00483 /** \brief Calculate the minimum \c min of \c ff 00484 w.r.t. the array \c x of size \c nvar with gradient 00485 \c df and hessian vector product \c hf 00486 */ 00487 virtual int mmin_hess(size_t nvar, vec_t &xx, double &fmin, 00488 func_t &ff, dfunc_t &df, hfunc_t &hf) 00489 { 00490 00491 int status; 00492 allocate(nvar); 00493 if (requires_hess) set_hess(ff,df,hf,xx); 00494 else set(ff,df,xx); 00495 int it=0; 00496 do { 00497 status=iterate(); 00498 status=is_optimal(); 00499 it++; 00500 } while (it<this->ntrial && status==gsl_continue); 00501 00502 for(size_t i=0;i<nvar;i++) xx[i]=this->x[i]; 00503 fmin=this->f; 00504 this->last_ntrial=it; 00505 00506 free(); 00507 return 0; 00508 } 00509 00510 /** \brief Calculate the minimum \c min of \c func 00511 w.r.t. the array \c x of size \c nvar with gradient 00512 \c dfunc 00513 */ 00514 virtual int mmin_de(size_t nvar, vec_t &xx, double &fmin, 00515 func_t &ff, dfunc_t &df) { 00516 00517 int status; 00518 allocate(nvar); 00519 set(ff,df,xx); 00520 int it=0; 00521 do { 00522 status=iterate(); 00523 status=is_optimal(); 00524 it++; 00525 } while (it<this->ntrial && status==gsl_continue); 00526 00527 for(size_t i=0;i<nvar;i++) xx[i]=this->x[i]; 00528 fmin=this->f; 00529 this->last_ntrial=it; 00530 00531 free(); 00532 return 0; 00533 } 00534 00535 /// Return string denoting type ("ool_constr_mmin") 00536 const char *type() { return "ool_constr_mmin"; } 00537 00538 }; 00539 00540 #ifndef DOXYGENP 00541 } 00542 #endif 00543 00544 #endif 00545
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).