00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 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 #ifndef O2SCL_JACOBIAN_H 00024 #define O2SCL_JACOBIAN_H 00025 00026 #include <string> 00027 #include <o2scl/collection.h> 00028 #include <o2scl/omatrix_tlate.h> 00029 #include <o2scl/mm_funct.h> 00030 #include <o2scl/gsl_deriv.h> 00031 #include <o2scl/columnify.h> 00032 00033 #ifndef DOXYGENP 00034 namespace o2scl { 00035 #endif 00036 00037 /** 00038 \brief Base for a square Jacobian where J is 00039 computed at x given y=f(x) [abstract base] 00040 00041 Compute 00042 \f[ 00043 J_{ij} = \frac{\partial f_i}{\partial x_j} 00044 \f] 00045 00046 The \c vec_t objects in operator() could have been written to be 00047 \c const, but they are not \c const so that they can be used as 00048 temporary workspace. They are typically restored to their 00049 original values before operator() exits. 00050 00051 For Jacobian functions with C-style arrays and matrices, use 00052 the corresponding children of \ref jac_vfunct . 00053 00054 */ 00055 template<class param_t, class vec_t=ovector_view, 00056 class mat_t=omatrix_view> class jac_funct { 00057 00058 public: 00059 00060 jac_funct() {} 00061 00062 virtual ~jac_funct() {} 00063 00064 /** \brief The operator() 00065 */ 00066 virtual int operator()(size_t nv, vec_t &x, 00067 vec_t &y, mat_t &j, param_t &pa)=0; 00068 00069 #ifndef DOXYGENP 00070 00071 private: 00072 00073 jac_funct(const jac_funct &); 00074 jac_funct& operator=(const jac_funct&); 00075 00076 #endif 00077 00078 }; 00079 00080 /** \brief Function pointer to jacobian 00081 */ 00082 template<class param_t, class vec_t=ovector_view, 00083 class mat_t=omatrix_view> class jac_funct_fptr : 00084 public jac_funct<param_t,vec_t,mat_t> { 00085 00086 public: 00087 00088 /** \brief Specify the function pointer 00089 */ 00090 jac_funct_fptr(int (*fp)(size_t nv, vec_t &x, vec_t &y, 00091 mat_t &j, param_t &pa)) { 00092 fptr=fp; 00093 } 00094 00095 virtual ~jac_funct_fptr(); 00096 00097 /** \brief The operator() 00098 */ 00099 virtual int operator()(size_t nv, vec_t &x, 00100 vec_t &y, mat_t &j, param_t &pa) { 00101 return fptr(nv,x,y,j,pa); 00102 } 00103 00104 #ifndef DOXYGENP 00105 00106 protected: 00107 00108 jac_funct_fptr() {}; 00109 00110 /// Function pointer 00111 int (*fptr)(size_t nv, vec_t &x, vec_t &y, 00112 mat_t &j, param_t &pa); 00113 00114 private: 00115 00116 jac_funct_fptr(const jac_funct_fptr &); 00117 jac_funct_fptr& operator=(const jac_funct_fptr&); 00118 00119 #endif 00120 00121 }; 00122 00123 /** \brief Member function pointer to a Jacobian 00124 */ 00125 template <class tclass, class param_t, class vec_t=ovector_view, 00126 class mat_t=omatrix_view> class jac_funct_mfptr : 00127 public jac_funct<param_t,vec_t,mat_t> { 00128 00129 public: 00130 00131 /** \brief Specify the member function pointer 00132 */ 00133 jac_funct_mfptr(tclass *tp, int (tclass::*fp) 00134 (size_t nv, vec_t &x, vec_t &y, 00135 mat_t &j, param_t &pa)) { 00136 tptr=tp; 00137 fptr=fp; 00138 } 00139 00140 virtual ~jac_funct_mfptr() {}; 00141 00142 /** \brief The operator() 00143 */ 00144 virtual int operator()(size_t nv, vec_t &x, 00145 vec_t &y, mat_t &j, param_t &pa) { 00146 return (*tptr.*fptr)(nv,x,y,j,pa); 00147 } 00148 00149 #ifndef DOXYGEN_INTERNAL 00150 00151 protected: 00152 00153 /// Member function pointer 00154 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &y, 00155 mat_t &j, param_t &pa); 00156 00157 /// Class pointer 00158 tclass *tptr; 00159 00160 #endif 00161 00162 #ifndef DOXYGENP 00163 00164 private: 00165 00166 jac_funct_mfptr(const jac_funct_mfptr &); 00167 jac_funct_mfptr& operator=(const jac_funct_mfptr&); 00168 00169 #endif 00170 00171 }; 00172 00173 /** 00174 \brief Base for a square Jacobian where J is computed at x given 00175 y=f(x) [abstract base] 00176 00177 Compute 00178 \f[ 00179 J_{ij} = \frac{\partial f_i}{\partial x_j} 00180 \f] 00181 00182 The \c vec_t objects in operator() could have been written to be 00183 \c const, but they are not \c const so that they can be 00184 used as temporary workspace. They are restored to their 00185 original values before operator() exits. 00186 00187 */ 00188 template<class param_t, size_t nv> class jac_vfunct { 00189 00190 public: 00191 00192 jac_vfunct() {} 00193 00194 virtual ~jac_vfunct() {} 00195 00196 /** \brief The operator() 00197 */ 00198 virtual int operator()(size_t nv2, double x[nv], 00199 double y[nv], double j[nv][nv], param_t &pa)=0; 00200 00201 #ifndef DOXYGENP 00202 00203 private: 00204 00205 jac_vfunct(const jac_vfunct &); 00206 jac_vfunct& operator=(const jac_vfunct&); 00207 00208 #endif 00209 00210 }; 00211 00212 /** \brief Function pointer to jacobian 00213 */ 00214 template<class param_t, size_t nv> class jac_vfunct_fptr : 00215 public jac_vfunct<param_t,nv> { 00216 00217 public: 00218 00219 /** \brief Specify the function pointer 00220 */ 00221 jac_vfunct_fptr(int (*fp)(size_t nv, double x[nv], double y[nv], 00222 double j[nv][nv], param_t &pa)) { 00223 fptr=fp; 00224 } 00225 00226 virtual ~jac_vfunct_fptr(); 00227 00228 /** \brief The operator() 00229 */ 00230 virtual int operator()(size_t nv2, double x[nv], 00231 double y[nv], double j[nv][nv], param_t &pa) { 00232 return fptr(nv2,x,y,j,pa); 00233 } 00234 00235 #ifndef DOXYGENP 00236 00237 protected: 00238 00239 jac_vfunct_fptr() {}; 00240 00241 /// Function pointer 00242 int (*fptr)(size_t nv2, double x[nv], double y[nv], 00243 double j[nv][nv], param_t &pa); 00244 00245 private: 00246 00247 jac_vfunct_fptr(const jac_vfunct_fptr &); 00248 jac_vfunct_fptr& operator=(const jac_vfunct_fptr&); 00249 00250 #endif 00251 00252 }; 00253 00254 /** \brief Member function pointer to a Jacobian 00255 */ 00256 template <class tclass, class param_t, size_t nv> class jac_vfunct_mfptr : 00257 public jac_vfunct<param_t,nv> { 00258 00259 public: 00260 00261 /** \brief Specify the member function pointer 00262 */ 00263 jac_vfunct_mfptr(tclass *tp, int (tclass::*fp) 00264 (size_t nv, double x[nv], double y[nv], 00265 double j[nv][nv], param_t &pa)) { 00266 tptr=tp; 00267 fptr=fp; 00268 } 00269 00270 virtual ~jac_vfunct_mfptr() {}; 00271 00272 /** \brief The operator() 00273 */ 00274 virtual int operator()(size_t nv2, double x[nv], 00275 double y[nv], double j[nv][nv], param_t &pa) { 00276 return (*tptr.*fptr)(nv2,x,y,j,pa); 00277 } 00278 00279 #ifndef DOXYGEN_INTERNAL 00280 00281 protected: 00282 00283 /// Member function pointer 00284 int (tclass::*fptr)(size_t nv, double x[nv], double y[nv], 00285 double j[nv][nv], param_t &pa); 00286 00287 /// Class pointer 00288 tclass *tptr; 00289 00290 #endif 00291 00292 #ifndef DOXYGENP 00293 00294 private: 00295 00296 jac_vfunct_mfptr(const jac_vfunct_mfptr &); 00297 jac_vfunct_mfptr& operator=(const jac_vfunct_mfptr&); 00298 00299 #endif 00300 00301 }; 00302 00303 /** 00304 \brief Base for providing a numerical jacobian [abstract base] 00305 00306 This is provides a Jacobian which is numerically determined 00307 by differentiating a user-specified function (typically 00308 of the form of \ref mm_funct). 00309 */ 00310 template<class param_t, class func_t=mm_funct<param_t>, 00311 class vec_t=ovector_view, class mat_t=omatrix_view> 00312 class jacobian : public jac_funct<param_t,vec_t,mat_t> { 00313 public: 00314 00315 jacobian() { 00316 }; 00317 00318 virtual ~jacobian() {}; 00319 00320 /// Set the function to compute the Jacobian of 00321 virtual int set_function(func_t &f) { 00322 func=&f; 00323 return 0; 00324 } 00325 00326 /** \brief Evaluate the Jacobian \c j at point \c y(x) 00327 */ 00328 virtual int operator()(size_t nv, vec_t &x, vec_t &y, 00329 mat_t &j, param_t &pa)=0; 00330 00331 #ifndef DOXYGEN_INTERNAL 00332 00333 protected: 00334 00335 /// A pointer to the user-specified function 00336 func_t *func; 00337 00338 private: 00339 00340 jacobian(const jacobian &); 00341 jacobian& operator=(const jacobian&); 00342 00343 #endif 00344 00345 }; 00346 00347 /** 00348 \brief Simple automatic Jacobian 00349 00350 This class computes a numerical Jacobian by finite differencing. 00351 The stepsize is chosen to be \f$ h_j = \mathrm{epsrel} x_j \f$ or 00352 \f$ h_j = \mathrm{epsmin} \f$ if \f$ \mathrm{epsrel} x_j < 00353 \mathrm{epsmin} \f$. 00354 00355 This is nearly equivalent to the GSL method for computing 00356 Jacobians as in \c multiroots/fdjac.c. To obtain the GSL 00357 behavior, set \ref epsrel to \c GSL_SQRT_DBL_EPSILON and set 00358 \ref epsmin to zero. The \ref gsl_mroot_hybrids class sets \ref 00359 epsrel to \c GSL_SQRT_DBL_EPSILON in its constructor, 00360 but does not set \ref epsmin to zero. 00361 00362 This class does not separately check the vector and matrix sizes 00363 to ensure they are commensurate. 00364 00365 \todo Double check that this class works with arrays 00366 00367 \future GSL-1.10 updated fdjac.c and this update could be 00368 implemented below. 00369 */ 00370 template<class param_t, class func_t=mm_funct<void *>, 00371 class vec_t=ovector_view, class mat_t=omatrix_view, 00372 class alloc_vec_t=ovector, class alloc_t=ovector_alloc> 00373 class simple_jacobian : 00374 public jacobian<param_t,func_t,vec_t,mat_t> { 00375 00376 public: 00377 00378 simple_jacobian() { 00379 epsrel=1.0e-4; 00380 epsmin=1.0e-15; 00381 } 00382 00383 /** \brief The relative stepsize for finite-differencing 00384 (default \f$ 10^{-4} \f$ ) 00385 */ 00386 double epsrel; 00387 00388 /// The minimum stepsize (default \f$ 10^{-15} \f$) 00389 double epsmin; 00390 00391 /// For memory allocation 00392 alloc_t ao; 00393 00394 /** \brief The operator() 00395 */ 00396 virtual int operator()(size_t nv, vec_t &x, vec_t &y, 00397 mat_t &jac, param_t &pa) { 00398 00399 size_t i,j; 00400 double h,temp; 00401 alloc_vec_t f; 00402 bool success=true; 00403 00404 ao.allocate(f,nv); 00405 00406 for (j=0;j<nv;j++) { 00407 00408 h=epsrel*fabs(x[j]); 00409 if (fabs(h)<=epsmin) h=epsrel; 00410 00411 x[j]+=h; 00412 (*this->func)(nv,x,f,pa); 00413 x[j]-=h; 00414 00415 bool nonzero=false; 00416 for (i=0;i<nv;i++) { 00417 temp=(f[i]-y[i])/h; 00418 if (temp!=0.0) nonzero=true; 00419 jac[i][j]=temp; 00420 } 00421 if (nonzero==false) success=false; 00422 } 00423 00424 ao.free(f); 00425 00426 if (success==false) { 00427 set_err2_ret("At least one row of the Jacobian is zero ", 00428 "in simple_jacobian::operator().",gsl_efailed); 00429 } 00430 return 0; 00431 } 00432 }; 00433 00434 /** 00435 \brief A direct calculation of the jacobian using a \ref deriv object 00436 00437 Note that it is sometimes wasteful to use this Jacobian in a 00438 root-finding routine and using more approximate Jacobians is 00439 more efficient. This class is mostly useful for demonstration 00440 purposes. 00441 */ 00442 template<class param_t, class func_t=mm_funct<param_t>, 00443 class vec_t=ovector_view, class mat_t=omatrix_view> class exact_jacobian : 00444 public jacobian<param_t,func_t,vec_t,mat_t> { 00445 00446 public: 00447 00448 exact_jacobian() { 00449 def_deriv.h=1.0e-4; 00450 dptr=&def_deriv; 00451 } 00452 00453 /** 00454 \brief Parameter structure for passing information 00455 00456 This class is primarily useful for specifying derivatives 00457 for using the jacobian::set_deriv() function. 00458 00459 \comment 00460 This type needs to be publicly available so that the 00461 user can properly specify a base 1-dimensional derivative 00462 object. 00463 \endcomment 00464 */ 00465 typedef struct { 00466 /// The number of variables 00467 size_t nv; 00468 /// The current x value 00469 size_t xj; 00470 /// The current y value 00471 size_t yi; 00472 /// The x vector 00473 vec_t *x; 00474 /// The y vector 00475 vec_t *y; 00476 /// The parameters 00477 param_t *pa; 00478 } ej_parms; 00479 00480 /// The default derivative object 00481 gsl_deriv<ej_parms,funct<ej_parms> > def_deriv; 00482 00483 /// Set the derivative object 00484 int set_deriv(deriv<ej_parms,funct<ej_parms> > &de) { 00485 dptr=&de; 00486 return 0; 00487 } 00488 00489 /** \brief The operator() 00490 */ 00491 virtual int operator()(size_t nv, vec_t &x, vec_t &y, 00492 mat_t &jac, param_t &pa) { 00493 size_t i,j; 00494 double h,temp; 00495 00496 ej_parms ejp; 00497 ejp.nv=nv; 00498 ejp.x=&x; 00499 ejp.y=&y; 00500 ejp.pa=&pa; 00501 00502 funct_mfptr<exact_jacobian,ej_parms> dfnp(this,&exact_jacobian::dfn); 00503 00504 for (j=0;j<nv;j++) { 00505 ejp.xj=j; 00506 for (i=0;i<nv;i++) { 00507 ejp.yi=i; 00508 double tmp=(*ejp.x)[j]; 00509 jac[i][j]=dptr->calc(tmp,ejp,dfnp); 00510 (*ejp.x)[j]=tmp; 00511 } 00512 } 00513 00514 return 0; 00515 } 00516 00517 00518 #ifndef DOXYGEN_INTERNAL 00519 00520 protected: 00521 00522 /// Pointer to the derivative object 00523 deriv<ej_parms,funct<ej_parms> > *dptr; 00524 00525 /// Function for the derivative object 00526 int dfn(double x, double &y, ej_parms &ejp) { 00527 (*ejp.x)[ejp.xj]=x; 00528 (*this->func)(ejp.nv,*ejp.x,*ejp.y,*ejp.pa); 00529 y=(*ejp.y)[ejp.yi]; 00530 return 0; 00531 } 00532 00533 #endif 00534 00535 }; 00536 00537 #ifndef DOXYGENP 00538 } 00539 #endif 00540 00541 #endif
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