Bisection.h

Go to the documentation of this file.
00001 
00002 
00003 #ifndef Bisection_hpp
00004 #define Bisection_hpp
00005 
00006 #include <iostream>
00007 #include <vector>
00008 
00009 #include <stdexcept>
00010 
00011 #include "Secant.h"
00012 
00013 using namespace std;
00014 
00027 template< class functor, class real>
00028 void stradle_value( 
00029                    real& X0,
00030                    real& X1,
00031                    real& FX0,
00032                    real& FX1,
00033                    real Fsolve,
00034                    functor& obj, 
00035                    real (functor::*f)(real),
00036                    bool initialize_fx0 = true,
00037                    bool initialize_fx1 = true,
00038                    int direction = 0,
00039                    real MinX = 0,
00040                    real MaxX = 0)
00041 {
00042   bool is_increasing, check_bounds;
00043 
00044   if (initialize_fx0) FX0 =(obj.*f)( X0);
00045   if (initialize_fx1) FX1 =(obj.*f)( X1);
00046 
00047   check_bounds = MinX!=0 || MaxX!=0;
00048 
00049   if (X0==X1) throw domain_error( "X0==X1 in stradle function");
00050 
00051   if (X0 > X1) {
00052     real tmp;
00053     tmp = X0;    X0 = X1;  X1 = tmp;
00054     tmp = FX0; FX0 = FX1; FX1 = tmp;
00055   }
00056 
00057   if (FX0 < Fsolve && Fsolve < FX1) return;
00058 
00059   if (direction == 0) {
00060     is_increasing = FX1 > FX0;
00061   } else {
00062     is_increasing = direction > 0;
00063   }
00064 
00065   if (check_bounds && (X1 > MaxX || X0 < MinX)) {
00066     throw domain_error( "X1 > MaxX || X0 < MinX in stradle_value");
00067   }
00068 
00069   if (is_increasing) {    // solve fx0 < fsolve < fx1
00070     while (FX0 > Fsolve) {
00071       if (FX1 < FX0) throw range_error( "FX1 < FX0 for monotonic increasing function  at label A in stradle_value");
00072       FX1 = FX0;
00073       X0 *= .5;
00074       if (check_bounds && X0 < MinX) {
00075         throw domain_error( "X0 < MinX in stradle_value");
00076       }
00077       FX0 = (obj.*f)( X0);
00078     }
00079     while (Fsolve > FX1) {
00080       if (FX1 < FX0) throw range_error( "FX1 < FX0 for monotonic increasing function  at label B in stradle_value");
00081       FX0 = FX1;
00082       X1 *= 2;
00083       if (check_bounds && X1 > MaxX) {
00084         throw domain_error( "X1 > MaxX in stradle_value");
00085       }
00086       FX1 = (obj.*f)( X1);
00087     }
00088   } else {  // solve fx0 > fsolve > fx1
00089     while (FX0 < Fsolve) {
00090       if (FX1 > FX0) throw range_error( "FX1 > FX0 for monotonic decreasing function at label C in stradle_value");
00091       FX1 = FX0;
00092       X0 *= .5;
00093       if (check_bounds && X0 < MinX) {
00094         throw domain_error( "X0 < MinX in stradle_value");
00095       }
00096       FX0 = (obj.*f)( X0);
00097     }
00098     while (Fsolve < FX1) {
00099       if (FX1 > FX0) throw range_error( "FX1 > FX0 for monotonic decreasing function at label D in stradle_value");
00100       FX0 = FX1;
00101       X1 *= 2;
00102       if (check_bounds && X1 > MaxX) {
00103         throw domain_error( "X1 > MaxX in stradle_value");
00104       }
00105       FX1 = (obj.*f)( X1);
00106     }
00107   }
00108 }
00109 
00114 template<class functor, class real>
00115 class Bisection {
00116  protected:
00117 
00119   real _x0;
00120 
00122   real _x1;
00123 
00125   real _fsolve;
00126 
00128   real _delta;
00129 
00131   real _epsilon;
00132 
00134   real _x_lower;
00135 
00137   real _x_upper;
00138 
00140   real _F_x_lower;
00141 
00143   bool _calc_F_x_lower;
00144 
00146   real _F_x_upper;
00147 
00149   bool _calc_F_x_upper;
00150 
00152   real _x_mid;
00153 
00155   real _dx;
00156 
00158   real _F_x_mid;
00159 
00161   real _abs_error;
00162 
00164   bool _is_increasing;
00165 
00167   int _max_iter;
00168 
00170   int i;
00171 
00173   bool _converged;
00174 
00176   functor& _obj;
00177 
00179   real (functor::*_f)(real);
00180 
00181  public:
00182 
00183   Bisection( 
00184     real X0, 
00185     real X1,
00186     real Fsolve,
00187     real Delta,
00188     real Epsilon, 
00189     unsigned int max_iter, 
00190     functor& obj, 
00191     real (functor::*f)(real)) :
00192     _x0(X0), _x1(X1), _fsolve(Fsolve), _delta(Delta), _epsilon(Epsilon), _max_iter(max_iter), _obj(obj), _f(f), _calc_F_x_lower(false), _calc_F_x_upper(false)
00193   {
00194 
00195   }
00196 
00197   Bisection( 
00198     real X0, 
00199     real X1,
00200     real FX0,
00201     real FX1,
00202     real Fsolve,
00203     real Delta,
00204     real Epsilon, 
00205     unsigned int max_iter, 
00206     functor& obj, 
00207     real (functor::*f)(real)) :
00208     _x0(X0), _x1(X1), _F_x_lower(FX0), _calc_F_x_lower(true), 
00209     _F_x_upper(FX1), _calc_F_x_upper(true), _fsolve(Fsolve), 
00210     _delta(Delta), _epsilon(Epsilon), _max_iter(max_iter), _obj(obj), _f(f)
00211   {
00212 
00213   }
00214 
00215   
00217   void do_iteration(  bool print_results)
00218     {
00219 
00220       _converged = false;
00221 
00222       _x_lower = _x0;
00223       _x_upper = _x1;
00224       if (_calc_F_x_lower) _F_x_lower =  (_obj.*_f)( _x_lower); 
00225       if (_calc_F_x_upper) _F_x_upper =  (_obj.*_f)( _x_upper); 
00226 
00227       _is_increasing = (_F_x_upper > _F_x_lower);
00228 
00229       if (print_results) {
00230         cout << "x_lower = " << _x_lower << endl;
00231         cout << "x_upper = " << _x_upper << endl;
00232 
00233         cout << "F_x_lower = " << _F_x_lower << endl;
00234         cout << "F_x_upper = " << _F_x_upper << endl;
00235 
00236         if (_is_increasing) {
00237           cout << "F is increasing" << endl;
00238         } else {
00239           cout << "F is decreasing" << endl;
00240         }
00241       }
00242 
00243       _converged = false;
00244     
00245       for (i=0; i<_max_iter; i++) {
00246         _x_mid = .5 * (_x_lower + _x_upper);
00247         _dx = _x_upper - _x_mid;
00248         _F_x_mid = (_obj.*_f)( _x_mid);
00249         _abs_error = _F_x_mid - _fsolve;
00250         if (_abs_error < 0) _abs_error = -_abs_error;
00251 
00252         if (print_results) {
00253           cerr << "i = " << i 
00254                << " x_lower = " << _x_lower 
00255                << " x_upper = " << _x_upper 
00256                << " x_mid = " << _x_mid 
00257                << " _F_x_mid = " << _F_x_mid << endl;
00258 
00259         /*cout << "x_lower = " << _x_lower << endl;
00260           cout << "x_upper = " << _x_upper << endl;
00261           cout << "F_x_lower = " << _F_x_lower << endl;
00262           cout << "F_x_mid   = " << _F_x_mid << endl;
00263           cout << "F_x_upper = " << _F_x_upper << endl; */
00264 
00265         }
00266 
00267         if (_abs_error < _epsilon || _dx < _delta) {
00268           _converged = true;
00269           break;
00270         }
00271 
00272         if (_F_x_mid > _fsolve) { 
00273           if (_is_increasing) {
00274             _x_upper = _x_mid;
00275             _F_x_upper = _F_x_mid;
00276           } else {
00277             _x_lower = _x_mid;
00278             _F_x_lower = _F_x_mid;
00279           }
00280         }
00281 
00282         if (_F_x_mid < _fsolve) {
00283           if (_is_increasing) {
00284             _x_lower = _x_mid;
00285             _F_x_lower = _F_x_mid;
00286           } else {
00287             _x_upper = _x_mid;
00288             _F_x_upper = _F_x_mid;
00289           }
00290         }
00291       }
00292     }
00293                                  
00294 
00296   real get_x_mid() const {
00297     return _x_mid;
00298   }
00299 
00301   bool get_converged() const {
00302     return _converged;
00303   }
00304 
00305   real get_df_dx() const {
00306     return (_F_x_upper - _F_x_mid) / (_x_upper - _x_mid);
00307   }
00308 };
00309 
00311 template<class functor, class real>
00312 class Bisection_Secant : public Bisection< functor, real >  {
00313  public:
00314 
00315   Bisection_Secant( 
00316     real X0, 
00317     real X1,
00318     real Fsolve,
00319     real Delta,
00320     real Epsilon, 
00321     unsigned int max_iter, 
00322     functor& obj, 
00323     real (functor::*f)(real)) :
00324     Bisection< functor, real > ( X0, X1, Fsolve, Delta, Epsilon, max_iter, obj, f )
00325   {
00326   }
00327 
00328   Bisection_Secant( 
00329     real X0, 
00330     real X1,
00331     real FX0,
00332     real FX1,
00333     real Fsolve,
00334     real Delta,
00335     real Epsilon, 
00336     unsigned int max_iter, 
00337     functor& obj, 
00338     real (functor::*f)(real)) :
00339     Bisection< functor, real > ( X0, X1, FX0, FX1, Fsolve, Delta, Epsilon, max_iter, obj, f )
00340   {
00341   }
00342 
00344   void do_iteration( bool print_results) {
00345     unsigned int i;
00346     real df_dx;
00347 
00348     this->_converged = false;
00349 
00350     this->_x_lower = this->_x0;
00351     this->_x_upper = this->_x1;
00352     if (this->_calc_F_x_lower) this->_F_x_lower =  (this->_obj.*this->_f)( this->_x_lower); 
00353     if (this->_calc_F_x_upper) this->_F_x_upper =  (this->_obj.*this->_f)( this->_x_upper); 
00354     
00355     if (print_results) {
00356       cout << "x_lower = " << this->_x_lower << endl;
00357       cout << "x_upper = " << this->_x_upper << endl;
00358 
00359       cout << "F_x_lower = " << this->_F_x_lower << endl;
00360       cout << "F_x_upper = " << this->_F_x_upper << endl;
00361     }
00362 
00363     this->_is_increasing = this->_F_x_upper > this->_F_x_lower;
00364     
00365     for (i=0; i<this->_max_iter; i++) {
00366       if (i % 2 == 1) {
00367         df_dx = (this->_F_x_upper - this->_F_x_lower) / (this->_x_upper - this->_x_lower);
00368         this->_x_mid = this->_x_upper - (this->_F_x_upper - this->_fsolve) / df_dx;
00369         if (this->_x_mid < this->_x_lower || this->_x_mid > this->_x_upper) {
00370           this->_x_mid = .5 * (this->_x_lower + this->_x_upper);
00371         }
00372       } else {
00373         this->_x_mid = .5 * (this->_x_lower + this->_x_upper);
00374       }
00375 
00376       this->_dx = this->_x_upper - this->_x_mid;
00377       this->_F_x_mid = (this->_obj.*this->_f)( this->_x_mid);
00378       this->_abs_error = this->_F_x_mid - this->_fsolve;
00379       if (this->_abs_error < 0) this->_abs_error = -this->_abs_error;
00380 
00381       if (print_results) {
00382         cerr << "i = " << i 
00383              << " x_lower = " << this->_x_lower 
00384              << " x_upper = " << this->_x_upper 
00385              << " x_mid = " << this->_x_mid 
00386              << " this->_F_x_mid = " << this->_F_x_mid << endl;
00387       }
00388 
00389       if (this->_abs_error < this->_epsilon || this->_dx < this->_delta) {
00390         this->_converged = true;
00391         break;
00392       }
00393 
00394       if (this->_F_x_mid > this->_fsolve) { 
00395         if (this->_is_increasing) {
00396           this->_x_upper = this->_x_mid;
00397           this->_F_x_upper = this->_F_x_mid;
00398         } else {
00399           this->_x_lower = this->_x_mid;
00400           this->_F_x_lower = this->_F_x_mid;
00401         }
00402       }
00403 
00404       if (this->_F_x_mid < this->_fsolve) {
00405         if (this->_is_increasing) {
00406           this->_x_lower = this->_x_mid;
00407           this->_F_x_lower = this->_F_x_mid;
00408         } else {
00409           this->_x_upper = this->_x_mid;
00410           this->_F_x_upper = this->_F_x_mid;
00411         }
00412       }
00413     }
00414   }
00415 };
00416 
00417 #endif

Generated on Fri Jan 7 12:36:18 2011 for public_options by  doxygen 1.5.1