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
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
00038 bool _check_boundary;
00040 real _min_x;
00042 real _max_x;
00043
00044
00045
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