Object-oriented Scientific Computing Library: Version 0.910
ool_constr_mmin.h
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 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.