ool_constr_mmin.h

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

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page