Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

leastsquare.h

00001 // Emacs will be in -*- Mode: c++ -*-
00002 //
00003 // ************ DO NOT REMOVE THIS BANNER ****************
00004 //
00005 //  Nicolas Di Cesare <Nicolas.Dicesare@free.fr>
00006 //  http://acm.emath.fr/~dicesare
00007 //
00008 //********************************************************
00009 //
00010 //  Least Square Method using conjugate gradient method
00011 //
00012 //********************************************************
00013 #ifndef __leastsquare_h__
00014 #define __leastsquare_h__
00015 
00016 #include <cg.h>
00017 
00022 template <class V, class M>
00023 class LeastSquareProblem {
00024 public:
00026   virtual int size()  = 0;
00028   virtual void targetAndValue(const V& x, V& target, V& fct2fit) = 0;
00030   virtual void targetValueAndfirstDerivative(const V& x, M& grad_fct2fit, V& target, V& fct2fit) = 0;
00031 };
00032 
00041 template <class V, class M>
00042 class LeastSquareFunction : public CostFunction<V> {
00043 public:
00045   typedef double value_type;
00046 protected:
00048   LeastSquareProblem<V,M> & lsp_;
00049 public:
00051   LeastSquareFunction(LeastSquareProblem<V,M> & lsp) : lsp_(lsp) {}
00053   virtual ~LeastSquareFunction() {}
00054   
00056   virtual value_type value(const V& x);
00058   virtual void firstDerivative(V& grad_f, const V& x);
00060   virtual value_type valueAndFirstDerivative(V& grad_f, const V& x);
00061   
00063   virtual void Update() {}
00065   virtual void Save(OptimizationMethod<V>&) {}
00066 };
00067 
00068 
00069 template <class V, class M>
00070 typename LeastSquareFunction<V,M>::value_type 
00071 LeastSquareFunction<V,M>::value(const V& x) 
00072 {
00073   // size of target and function to fit vectors
00074   V target(lsp_.size()), fct2fit(lsp_.size()); 
00075   // compute its values
00076   lsp_.targetAndValue(x,target,fct2fit);
00077   // do the difference 
00078   V diff = target - fct2fit;
00079   // and compute the scalar product (square of the norm)
00080   return DotProduct(diff,diff);
00081 }
00082 
00083 template <class V, class M>
00084 void LeastSquareFunction<V,M>::firstDerivative(V& grad_f, const V& x)
00085 {
00086   // size of target and function to fit vectors
00087   V target(lsp_.size()), fct2fit(lsp_.size()); 
00088   // size of gradient matrix
00089   M grad_fct2fit(lsp_.size(),x.size());
00090   // compute its values
00091   lsp_.targetValueAndfirstDerivative(x,grad_fct2fit,target,fct2fit);
00092   // do the difference 
00093   V diff = target - fct2fit;
00094   // compute derivative
00095   grad_f = -2.*(transpose(grad_fct2fit)*diff);
00096 }
00097 
00098 template <class V, class M>
00099 typename LeastSquareFunction<V,M>::value_type 
00100 LeastSquareFunction<V,M>::valueAndFirstDerivative(V& grad_f, const V& x) 
00101 {
00102   // size of target and function to fit vectors
00103   V target(lsp_.size()), fct2fit(lsp_.size()); 
00104   // size of gradient matrix
00105   M grad_fct2fit(lsp_.size(),x.size());
00106   // compute its values
00107   lsp_.targetValueAndfirstDerivative(x,grad_fct2fit,target,fct2fit);
00108   // do the difference 
00109   V diff = target - fct2fit;
00110   // compute derivative
00111   grad_f = -2.*(transpose(grad_fct2fit)*diff);
00112   // and compute the scalar product (square of the norm)
00113   return DotProduct(diff,diff);
00114 }
00115 
00116 
00117 
00137 template <class V>
00138 class NonLinearLeastSquare {
00140   V results_, initialValue_;
00142   double resnorm_;
00144   int exitFlag_;
00146   double accuracy_, bestAccuracy_;
00148   unsigned int maxIterations_, nbIterations_;
00150   QuantLib::Handle< OptimizationMethod<V> > om_;
00151 public:
00153   inline NonLinearLeastSquare(double accuracy = 1e-4,
00154                   int maxiter = 100);
00156   inline NonLinearLeastSquare(double accuracy,
00157                   int maxiter,
00158                   QuantLib::Handle< OptimizationMethod<V> > om);  
00160   inline ~NonLinearLeastSquare() {}
00161 
00163   template <class M> inline 
00164   V& Perform(LeastSquareProblem<V,M> & lsProblem)
00165   {
00166     double eps = accuracy_;
00167 
00168     // set initial value of the optimization method
00169     om_->setInitialValue(initialValue_);
00170     // set end criteria with a given maximum number of iteration and a given error eps
00171     om_->setEndCriteria(OptimizationEndCriteria(maxIterations_, eps));
00172     om_->endCriteria().setPositiveOptimization();
00173 
00174     // wrap the least square problem in an optimization function
00175     LeastSquareFunction<V,M> lsf(lsProblem);
00176 
00177     // define optimization problem
00178     OptimizationProblem<V> P(lsf,*om_);
00179 
00180     // minimize
00181     P.Minimize();
00182 
00183     // summarize results of minimization
00184     exitFlag_ = om_->endCriteria().criteria();
00185     nbIterations_ = om_->iterationNumber();
00186 
00187     results_ = om_->x();
00188     resnorm_ = om_->functionValue();
00189     bestAccuracy_ = om_->functionValue();
00190   
00191     return results_;
00192   }
00193 
00194   inline void setInitialValue(const V& initialValue)
00195   { initialValue_ = initialValue;}
00196 
00198   inline V& results() { return results_;}
00200   inline double residualNorm() { return resnorm_;}
00202   inline double lastValue() { return bestAccuracy_;}
00204   inline int exitFlag() { return exitFlag_;}
00206   inline int iterationsNumber() { return nbIterations_;}
00207 };
00208 
00209 
00210 template <class V> inline 
00211 NonLinearLeastSquare<V>::NonLinearLeastSquare(double accuracy,
00212                           int maxiter)
00213   : exitFlag_(-1), accuracy_(accuracy), maxIterations_(maxiter), 
00214     om_(QuantLib::Handle< OptimizationMethod<V> >(new ConjugateGradient<V>()))
00215 {}
00216 
00217 template <class V> inline 
00218 NonLinearLeastSquare<V>::NonLinearLeastSquare(double accuracy,
00219                           int maxiter,
00220                           QuantLib::Handle< OptimizationMethod<V> > om)
00221   : exitFlag_(-1), accuracy_(accuracy), maxIterations_(maxiter), om_(om)
00222 {}
00223 
00224 
00225 #endif

Generated at Wed Nov 7 16:25:59 2001 for Optimization by doxygen1.2.9 written by Dimitri van Heesch, © 1997-2001