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) {
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 {
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
00260
00261
00262
00263
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