00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00074 V target(lsp_.size()), fct2fit(lsp_.size());
00075
00076 lsp_.targetAndValue(x,target,fct2fit);
00077
00078 V diff = target - fct2fit;
00079
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
00087 V target(lsp_.size()), fct2fit(lsp_.size());
00088
00089 M grad_fct2fit(lsp_.size(),x.size());
00090
00091 lsp_.targetValueAndfirstDerivative(x,grad_fct2fit,target,fct2fit);
00092
00093 V diff = target - fct2fit;
00094
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
00103 V target(lsp_.size()), fct2fit(lsp_.size());
00104
00105 M grad_fct2fit(lsp_.size(),x.size());
00106
00107 lsp_.targetValueAndfirstDerivative(x,grad_fct2fit,target,fct2fit);
00108
00109 V diff = target - fct2fit;
00110
00111 grad_f = -2.*(transpose(grad_fct2fit)*diff);
00112
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
00169 om_->setInitialValue(initialValue_);
00170
00171 om_->setEndCriteria(OptimizationEndCriteria(maxIterations_, eps));
00172 om_->endCriteria().setPositiveOptimization();
00173
00174
00175 LeastSquareFunction<V,M> lsf(lsProblem);
00176
00177
00178 OptimizationProblem<V> P(lsf,*om_);
00179
00180
00181 P.Minimize();
00182
00183
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