bpp-core  2.1.0
AbstractNumericalDerivative.h
Go to the documentation of this file.
00001 //
00002 // File: AbstractNumericalDerivative.h
00003 // Created by: Julien Dutheil
00004 // Created on: Thu Aug 17 15:00 2006
00005 //
00006 
00007 /*
00008 Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
00009 
00010 This software is a computer program whose purpose is to provide classes
00011 for numerical calculus.
00012 
00013 This software is governed by the CeCILL  license under French law and
00014 abiding by the rules of distribution of free software.  You can  use, 
00015 modify and/ or redistribute the software under the terms of the CeCILL
00016 license as circulated by CEA, CNRS and INRIA at the following URL
00017 "http://www.cecill.info". 
00018 
00019 As a counterpart to the access to the source code and  rights to copy,
00020 modify and redistribute granted by the license, users are provided only
00021 with a limited warranty  and the software's author,  the holder of the
00022 economic rights,  and the successive licensors  have only  limited
00023 liability. 
00024 
00025 In this respect, the user's attention is drawn to the risks associated
00026 with loading,  using,  modifying and/or developing or reproducing the
00027 software by the user in light of its specific status of free software,
00028 that may mean  that it is complicated to manipulate,  and  that  also
00029 therefore means  that it is reserved for developers  and  experienced
00030 professionals having in-depth computer knowledge. Users are therefore
00031 encouraged to load and test the software's suitability as regards their
00032 requirements in conditions enabling the security of their systems and/or 
00033 data to be ensured and,  more generally, to use and operate it in the 
00034 same conditions as regards security. 
00035 
00036 The fact that you are presently reading this means that you have had
00037 knowledge of the CeCILL license and that you accept its terms.
00038 */
00039 
00040 #ifndef _ABSTRACTNUMERICALDERIVATIVE_H_
00041 #define _ABSTRACTNUMERICALDERIVATIVE_H_
00042 
00043 #include "Functions.h"
00044 #include "../Matrix/Matrix.h"
00045 
00046 //From the STL:
00047 #include <map>
00048 #include <vector>
00049 #include <string>
00050 
00051 namespace bpp
00052 {
00053 
00066 class AbstractNumericalDerivative:
00067   public DerivableSecondOrder,
00068   public FunctionWrapper
00069 {
00070   protected:
00071     DerivableFirstOrder *function1_;
00072     DerivableSecondOrder *function2_;
00073     double h_;
00074     std::vector<std::string> variables_;
00075     mutable std::map<std::string, size_t> index_; //Store positions in array corresponding to variable names.
00076     std::vector<double> der1_;
00077     std::vector<double> der2_;
00078     RowMatrix<double> crossDer2_;
00079     bool computeD1_, computeD2_, computeCrossD2_;
00080     
00081   public:
00082     AbstractNumericalDerivative(Function* function):
00083       FunctionWrapper(function), function1_(0), function2_(0),
00084       h_(0.0001), variables_(), index_(), der1_(), der2_(), crossDer2_(),
00085       computeD1_(true), computeD2_(true), computeCrossD2_(false) {}
00086 
00087     AbstractNumericalDerivative(DerivableFirstOrder* function):
00088       FunctionWrapper(function), function1_(function), function2_(0),
00089       h_(0.0001), variables_(), index_(), der1_(), der2_(), crossDer2_(),
00090       computeD1_(true), computeD2_(true), computeCrossD2_(false) {}
00091 
00092     AbstractNumericalDerivative(DerivableSecondOrder* function):
00093       FunctionWrapper(function), function1_(function), function2_(function),
00094       h_(0.0001), variables_(), index_(), der1_(), der2_(), crossDer2_(),
00095       computeD1_(true), computeD2_(true), computeCrossD2_(false) {}
00096 
00097     AbstractNumericalDerivative(const AbstractNumericalDerivative& ad):
00098       FunctionWrapper(ad), function1_(ad.function1_), function2_(ad.function2_),
00099       h_(ad.h_), variables_(ad.variables_), index_(ad.index_), der1_(ad.der1_), der2_(ad.der2_), crossDer2_(ad.crossDer2_),
00100       computeD1_(ad.computeD1_), computeD2_(ad.computeD2_), computeCrossD2_(ad.computeCrossD2_) {}
00101 
00102     AbstractNumericalDerivative& operator=(const AbstractNumericalDerivative& ad)
00103     {
00104       FunctionWrapper::operator=(ad);
00105       function1_ = ad.function1_;
00106       function2_ = ad.function2_;
00107       h_ = ad.h_;
00108       variables_ = ad.variables_;
00109       index_ = ad.index_;
00110       der1_ = ad.der1_;
00111       der2_ = ad.der2_;
00112       crossDer2_ = ad.crossDer2_;
00113       computeD1_ = ad.computeD1_;
00114       computeD2_ = ad.computeD2_;
00115       computeCrossD2_ = ad.computeCrossD2_;
00116       return *this;
00117     }
00118 
00119     virtual ~AbstractNumericalDerivative() {}
00120 
00121     AbstractNumericalDerivative* clone() const = 0;
00122 
00123   public:
00131     void setInterval(double h) { h_ = h; }
00132     
00136     double getInterval() const { return h_; }
00137     
00143     void setParametersToDerivate(const std::vector<std::string>& variables)
00144     {
00145       variables_ = variables;
00146       index_.clear();
00147       for(size_t i = 0; i < variables_.size(); i++)
00148         index_[variables_[i]] = i;
00149       der1_.resize(variables_.size());
00150       der2_.resize(variables_.size());
00151       crossDer2_.resize(variables_.size(), variables_.size());
00152     }
00153     
00159     void enableFirstOrderDerivatives(bool yn) { computeD1_ = yn; }
00160     bool enableFirstOrderDerivatives() const { return computeD1_; }
00161     
00162     double getFirstOrderDerivative(const std::string& variable) const
00163       throw (Exception)
00164     {
00165       if (function1_)
00166       {
00167         try
00168         {
00169           return function1_->getFirstOrderDerivative(variable);
00170         }
00171         catch (Exception& e) {}
00172       }    
00173       std::map<std::string, size_t>::iterator it = index_.find(variable);
00174       if (computeD1_ && it != index_.end()) return der1_[it->second];
00175       else throw Exception("First order derivative not computed for variable " + variable + "."); 
00176     }
00185     void enableSecondOrderDerivatives(bool yn) { computeD2_ = yn; }
00186     bool enableSecondOrderDerivatives() const { return computeD2_; }
00187 
00188     double getSecondOrderDerivative(const std::string& variable) const
00189       throw (Exception)
00190     {
00191       if (function2_)
00192       {
00193         try
00194         {
00195           return function2_->getSecondOrderDerivative(variable);
00196         }
00197         catch(Exception & e) {}
00198       }    
00199       std::map<std::string, size_t>::iterator it = index_.find(variable);
00200       if(computeD2_ && it != index_.end()) return der2_[it->second];
00201       else throw Exception("Second order derivative not computed for variable " + variable + "."); 
00202     }
00203 
00204     double getSecondOrderDerivative(const std::string& variable1, const std::string& variable2) const
00205       throw (Exception)
00206     {
00207       if (function2_)
00208       {
00209         try
00210         {
00211           return function2_->getSecondOrderDerivative(variable1, variable2);
00212         }
00213         catch(Exception & e) {}
00214       }    
00215       std::map<std::string, size_t>::iterator it1 = index_.find(variable1);
00216       std::map<std::string, size_t>::iterator it2 = index_.find(variable2);
00217       if(computeCrossD2_ && it1 != index_.end() && it2 != index_.end()) return crossDer2_(it1->second, it2->second);
00218       else throw Exception("Cross second order derivative not computed for variables " + variable1 + " and " + variable2 + "."); 
00219     }
00227     double f(const ParameterList& parameters) throw (Exception)
00228     {
00229       setParameters(parameters);
00230       return getValue();
00231     }
00232     void setParameters(const ParameterList& parameters)
00233       throw (ParameterNotFoundException, ConstraintException)
00234     {
00235       function_->setParameters(parameters);
00236       updateDerivatives(parameters);
00237     }
00238     void setAllParametersValues(const ParameterList& parameters)
00239       throw (ParameterNotFoundException, ConstraintException)
00240     {
00241       function_->setAllParametersValues(parameters);
00242       updateDerivatives(parameters);
00243     }
00244     
00245     void setParameterValue(const std::string& name, double value)
00246       throw (ParameterNotFoundException, ConstraintException)
00247     {
00248       function_->setParameterValue(name, value);
00249       updateDerivatives(function_->getParameters().subList(name));
00250     }
00251     
00252     void setParametersValues(const ParameterList& parameters)
00253       throw (ParameterNotFoundException, ConstraintException)
00254     {
00255       function_->setParametersValues(parameters);
00256       updateDerivatives(parameters);
00257     }
00258     
00259     bool matchParametersValues(const ParameterList& parameters)
00260       throw (ConstraintException)
00261     {
00262       bool test = function_->matchParametersValues(parameters);
00263       updateDerivatives(parameters);
00264       return test;
00265     }
00268     void enableSecondOrderCrossDerivatives(bool yn) { computeCrossD2_ = yn; }
00269     bool enableSecondOrderCrossDerivatives() const { return computeCrossD2_; }
00270 
00271   protected:
00278     virtual void updateDerivatives(const ParameterList parameters) = 0;
00279     
00280 };
00281 
00282 } //end of namespace bpp.
00283 
00284 #endif //_ABSTRACTNUMERICALDERIVATIVE_H_
00285 
 All Classes Namespaces Files Functions Variables Typedefs Friends