00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _conjugate_gradient_h
00014 #define _conjugate_gradient_h
00015
00016 #include <iostream>
00017 #include <iomanip>
00018 #include <cmath>
00019
00020 #include <optimizer.h>
00021 #include <linesearch.h>
00022 #include <criteria.h>
00023 #include <armijo.h>
00024
00025 #include <ql/handle.hpp>
00026
00027
00028
00039 template <class V>
00040 class ConjugateGradient : public OptimizationMethod<V> {
00042 QuantLib::Handle< LineSearch<V> > lineSearch_;
00043 public:
00045 ConjugateGradient()
00046 : OptimizationMethod<V>(), lineSearch_(QuantLib::Handle< LineSearch<V> >(new ArmijoLineSearch<V>()))
00047 {}
00049 ConjugateGradient(QuantLib::Handle< LineSearch<V> >& lineSearch)
00050 : OptimizationMethod<V>(), lineSearch_(lineSearch)
00051 {}
00052
00053
00055 virtual ~ConjugateGradient() {}
00056
00058 virtual void Minimize(OptimizationProblem<V> & P);
00059 };
00060
00061 template <class V> void
00062 ConjugateGradient<V>::Minimize(OptimizationProblem<V> & P)
00063 {
00064 bool EndCriteria = false;
00065
00066
00067 double f, fold, sd2, sdold2, g2, gold2, c = 0.,normdiff = 0;
00068
00069 double t = 1.;
00070
00071
00072 V & X = x();
00073 V & SearchDirection = searchDirection();
00074
00075 int sz = searchDirection().size();
00076 V g(sz), d(sz), sddiff(sz);
00077
00078 f = P.valueAndFirstDerivative(g,X);
00079 SearchDirection = - g;
00080 g2 = DotProduct(g,g);
00081 sd2 = g2;
00082 normdiff = sqrt(sd2);
00083
00084
00085 do {
00086
00087 P.Save(iterationNumber(), f, sqrt(g2), t, *this);
00088
00089 #ifdef DEBUG_CG
00090 std::cout << "searchDirection() = " << searchDirection()
00091 << "gradient = " << g
00092 << "norm of gradient = " << sqrt(g2) << std::endl
00093 << "search direction = " << SearchDirection
00094 << "norm = " << sqrt(sd2) << std::endl
00095 << "t = " << t << std::endl
00096 << "c = " << c << std::endl
00097 << "d = " << d
00098 << "x = " << X << std::endl;
00099 #endif
00100
00101 t = (*lineSearch_)(P,t,f,g2);
00102
00103 if ( lineSearch_->succeed()) {
00104
00105 d = SearchDirection;
00106
00107 X = lineSearch_->lastX();
00108
00109 fold = f;
00110 f = lineSearch_->lastFunctionValue();
00111
00112 g = lineSearch_->lastGradient();
00113
00114 gold2 = g2;
00115 g2 = lineSearch_->lastGradientNorm2();
00116 c = g2 / gold2;
00117
00118 sddiff = (-g+c*d) - SearchDirection;
00119 normdiff = sqrt(DotProduct(sddiff,sddiff));
00120 SearchDirection = -g+c*d;
00121
00122 sdold2 = sd2;
00123 sd2 = DotProduct(SearchDirection,SearchDirection);
00124
00125
00126 EndCriteria = endCriteria()(iterationNumber_, fold, sqrt(gold2),
00127 f, sqrt(g2), normdiff
00128 );
00129
00130
00131 iterationNumber()++;
00132 }
00133 }
00134 while ( (EndCriteria == false)&&(lineSearch_->succeed()) );
00135
00136 P.Save(iterationNumber(), f, sqrt(g2), t, *this);
00137
00138 if ( !lineSearch_->succeed() ) throw Error("ConjugateGradient<V>::Minimize(...), line-search failed!");
00139 }
00140
00141
00142 #endif