Secant.h

Go to the documentation of this file.
00001 
00002 
00003 #ifndef Secant_hpp
00004 #define Secant_hpp
00005 
00006 #include <iostream>
00007 #include <vector>
00008 
00009 using namespace std;
00010 
00012 template<class functor, class real>
00013 class SecantSolve0 {
00014  protected:
00015   // key attributes
00017   int _max_iter;
00018 
00020   real _x0;
00022   real _x1;
00023 
00025   real _Fsolve;
00026   
00028   real _epsilon;
00029 
00031   real (functor::*_f)(real);
00032 
00034   functor& _obj;
00035 
00036   // functional attributes
00038   bool _check_boundary;
00040   real _min_x;
00042   real _max_x;
00043 
00044 
00045   // derived attributes
00047   mutable real _x_converge;
00049   mutable real _f_converge;
00051   mutable vector<real> _x;
00053   mutable vector<real> _F_x;
00055   mutable vector<real> _abs_Err_F_x;
00057   mutable vector<real> _dF_x;
00059   mutable bool _converged;
00061   mutable bool _diverged;
00063   mutable bool _boundary_solution;
00065   mutable int _number_boundary_hits;
00067   mutable bool _lower_boundary_hit;
00069   mutable bool _upper_boundary_hit;
00071   mutable bool _boundary_hit;
00072 
00074   int check_boundary( real & x, real df_dx) {
00075 
00076     if (_check_boundary) {
00077       _lower_boundary_hit = _upper_boundary_hit = false;
00078       if (x < _min_x) {
00079         x = _min_x + 2 * _epsilon / df_dx;
00080         _lower_boundary_hit = true;
00081         _number_boundary_hits++;      
00082       } else if (x > _max_x) {
00083         x = _max_x - 2 * _epsilon / df_dx;
00084         _upper_boundary_hit = true;
00085         _number_boundary_hits++;
00086       }
00087       _boundary_hit = _lower_boundary_hit || _upper_boundary_hit;
00088     }
00089     
00090     return _number_boundary_hits;
00091   }
00092 
00093  public:  
00094 
00096   bool get_boundary_solution() const {
00097     return _boundary_solution;
00098   }
00099 
00100 
00102   void set_check_boundary( bool check_boundary) {
00103     _check_boundary = check_boundary;
00104   }
00105 
00107   void set_min_x( real min_x) {
00108     _min_x = min_x;
00109   }
00110 
00112   void set_max_x( real max_x) {
00113     _max_x = max_x;
00114   }
00115 
00117   real get_x_converge() const {
00118     return _x_converge;
00119   }
00120 
00122   real get_f_converge() const {
00123     return _f_converge;
00124   }
00125 
00127   functor& get_functor() { return _obj;}
00128 
00130   bool get_converged() const { return _converged;}
00131 
00133   SecantSolve0( 
00134     real X0, 
00135     real X1,
00136     real Fsolve,
00137     real Epsilon, 
00138     unsigned int max_iter, 
00139     functor& obj, 
00140     real (functor::*f)(real), 
00141     bool check_boundary = false,
00142     real min_x = 0,
00143     real max_x = 0)
00144     :  _x0( X0), _x1( X1), _Fsolve( Fsolve), _epsilon( Epsilon),  _max_iter(max_iter), _obj(obj), _f(f),  _check_boundary(check_boundary), _min_x(min_x), _max_x(max_x), 
00145     _x_converge(0), _f_converge(0), 
00146     _x(max_iter), _F_x(max_iter), _abs_Err_F_x(max_iter), _dF_x(max_iter), _converged(false), _diverged(false), 
00147     _lower_boundary_hit(false), _upper_boundary_hit(false), _boundary_hit(false)
00148   {
00149 
00150   }
00151 
00153   void do_iteration( bool print_results) {
00154     int i;
00155     real dx, abs_dx, err;
00156 
00157     _converged = _diverged = _boundary_solution = false;
00158 
00159     _x[0] = _x0;
00160     _x[1] = _x1;
00161     _F_x[0] = (_obj.*_f)( _x[0]);
00162     _F_x[1] = (_obj.*_f)( _x[1]);
00163     _abs_Err_F_x[1] = (_F_x[1] > 0)? _F_x[1] : -_F_x[1];
00164     _dF_x[0] = 0;
00165     _dF_x[1] = (_F_x[1] - _F_x[0]) / (_x[1] - _x[0]);
00166 
00167     if (print_results) {
00168       cout << 0 << " " << _x[0] << " " << _F_x[0] << " not calculated" << endl;
00169       cout << 1 << " " << _x[1] << " " << _F_x[1] << " " << _dF_x[1] << endl;
00170     } 
00171 
00172     _number_boundary_hits=0;
00173     for (i=2; i<_max_iter; i++) {
00174 
00175       _x[i] = _x[i-1] - (_F_x[i-1] - _Fsolve) / _dF_x[i-1];
00176 
00177       if (check_boundary( _x[i], _dF_x[i-1])>1) {
00178         if (_lower_boundary_hit) {
00179           _boundary_solution = true;
00180           _x_converge = _min_x;
00181           _f_converge = (_obj.*_f)( _min_x);
00182           break;
00183         }
00184         if (_upper_boundary_hit) {
00185           _boundary_solution = true;
00186           _x_converge = _max_x;
00187           _f_converge = (_obj.*_f)( _max_x);
00188           break;
00189         }
00190       } else {
00191         if (_lower_boundary_hit) {
00192           _x[i] = _min_x + _epsilon;
00193         }
00194         if (_upper_boundary_hit) {
00195           _x[i] = _max_x - _epsilon;
00196         }
00197       }
00198 
00199       _F_x[i] = (_obj.*_f)( _x[i]);
00200       err = _F_x[i] - _Fsolve;
00201       _abs_Err_F_x[i] = (err > 0)? err : -err;
00202       dx = (_x[i] - _x[i-1]);
00203       abs_dx = (dx > 0)? dx : -dx;
00204         
00205       if (_abs_Err_F_x[i] < _epsilon || abs_dx < _epsilon) {
00206         _x_converge = _x[i];
00207         _f_converge = _F_x[i];
00208         _converged = true;
00209         break;
00210       }
00211       if (_abs_Err_F_x[i] > _abs_Err_F_x[i-1]) {
00212         _diverged = true;
00213       }
00214 
00215       _dF_x[i] = (_F_x[i] - _F_x[i-1]) / (_x[i] - _x[i-1]);
00216 
00217       if (print_results) {
00218         cout << i << " " << _x[i] << " " << _F_x[i] << " " << _dF_x[i] << endl;
00219       } 
00220     }
00221 
00222     if (_boundary_solution && print_results) {
00223       cout << i << " " << _x_converge << " " << _f_converge << " boundary_solution" << endl;
00224     } else if (_converged && print_results) {
00225       cout << i << " " << _x[i] << " " << _F_x[i] << " answer converged" << endl;
00226     } else if (_diverged && print_results) {
00227       cout << "answer diverged" << endl;
00228     }
00229   }
00230 };
00231 
00232 
00233 #endif

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