00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef NewtonRaphson_hpp
00026 #define NewtonRaphson_hpp
00027
00028 #include <iostream>
00029 #include <vector>
00030
00031 using namespace std;
00032
00040 template<class functor, class real>
00041 class NewtonRaphsonSolve0 {
00042 protected:
00043
00044
00047 int _max_iter;
00048
00051 real _x0;
00052
00054 real _epsilon;
00055
00057 real _fsolve;
00058
00060 bool _twice_df;
00061
00063 real (functor::*_f)(real);
00064
00066 real (functor::*_df)(real);
00067
00069 real (functor::*_d2f)(real);
00070
00072 functor& _F;
00073
00074
00076 bool _check_boundary;
00077
00079 real _min_x;
00080
00082 real _max_x;
00083
00084
00085
00087 mutable real _x_converge;
00089 mutable real _f_converge;
00091 mutable vector<real> _x;
00093 mutable vector<real> _F_x;
00095 mutable vector<real> _abs_F_x;
00097 mutable vector<real> _dF_x;
00099 mutable bool _converged;
00101 mutable bool _diverged;
00103 mutable bool _boundary_solution;
00105 mutable int _number_boundary_hits;
00107 mutable bool _lower_boundary_hit;
00109 mutable bool _upper_boundary_hit;
00111 mutable bool _boundary_hit;
00112
00114 int check_boundary( real & x, real df_dx) {
00115
00116 if (_check_boundary) {
00117 _lower_boundary_hit = _upper_boundary_hit = false;
00118 if (x < _min_x) {
00119 x = _min_x + 2 * _epsilon / df_dx;
00120 _lower_boundary_hit = true;
00121 _number_boundary_hits++;
00122 } else if (x > _max_x) {
00123 x = _max_x - 2 * _epsilon / df_dx;
00124 _upper_boundary_hit = true;
00125 _number_boundary_hits++;
00126 }
00127 _boundary_hit = _lower_boundary_hit || _upper_boundary_hit;
00128 }
00129
00130 return _number_boundary_hits;
00131 }
00132
00133 public:
00134
00136 bool get_boundary_solution() const {
00137 return _boundary_solution;
00138 }
00139
00141 void set_d2f( real (functor::*d2f)(real)) {
00142 _d2f = d2f;
00143 }
00144
00146 void set_check_boundary( bool check_boundary) {
00147 _check_boundary = check_boundary;
00148 }
00149
00151 void set_min_x( real min_x) {
00152 _min_x = min_x;
00153 }
00154
00156 void set_max_x( real max_x) {
00157 _max_x = max_x;
00158 }
00159
00161 real get_x_converge() const {
00162 return _x_converge;
00163 }
00164
00166 real get_f_converge() const {
00167 return _f_converge;
00168 }
00169
00171 functor& get_functor() { return _F;}
00172
00173
00185 NewtonRaphsonSolve0(
00186 real X0,
00187 real Epsilon,
00188 bool Twice_df,
00189 unsigned int max_iter,
00190 functor& F,
00191 real (functor::*f)(real),
00192 real (functor::*df)(real),
00193 real (functor::*d2f)(real) = NULL,
00194 real fsolve = 0,
00195 bool check_boundary = false,
00196 real min_x = 0,
00197 real max_x = 0)
00198 : _x0( X0), _epsilon( Epsilon), _twice_df( Twice_df), _max_iter(max_iter), _F(F), _f(f), _df(df), _d2f(d2f), _fsolve(fsolve), _check_boundary(check_boundary), _min_x(min_x), _max_x(max_x),
00199 _x_converge(0), _f_converge(0),
00200 _x(max_iter), _F_x(max_iter), _abs_F_x(max_iter), _dF_x(max_iter), _converged(false), _diverged(false),
00201 _lower_boundary_hit(false), _upper_boundary_hit(false), _boundary_hit(false)
00202 {
00203
00204 }
00205
00207 void do_iteration( ostream* output) {
00208 int i;
00209
00210 _converged = _diverged = _boundary_solution = false;
00211
00212 _x[0] = _x0;
00213
00214 for (i=_number_boundary_hits=0; ;) {
00215 _F_x[i] = (_F.*_f)( _x[i]) - _fsolve;
00216
00217 _abs_F_x[i] = (_F_x[i] > 0)? _F_x[i] : -_F_x[i];
00218
00219 if (_abs_F_x[i] < _epsilon) {
00220 _x_converge = _x[i];
00221 _f_converge = _F_x[i];
00222 _converged = true;
00223 break;
00224 }
00225
00226 if (i>0 && _abs_F_x[i] > _abs_F_x[i-1]) {
00227 _diverged = true;
00228 break;
00229 }
00230
00231 if (output) {
00232 *output << i << " " << _x[i] << " " << _F_x[i] << " " << _dF_x[i] << endl;
00233 }
00234
00235 _dF_x[i] = (_F.*_df)( _x[i]);
00236
00237 ++i;
00238 if (i >= _max_iter) break;
00239
00240 if (_d2f != 0) {
00241 real dx = (_F_x[i-1]) / _dF_x[i-1];
00242 real df2_dx2 = (_F.*_d2f) ( _x[i-1]);
00243 _dF_x[i-1] -= .5 * dx * df2_dx2;
00244 } else if (_twice_df) {
00245 _x[i] = _x[i-1] - (_F_x[i-1]) / _dF_x[i-1];
00246 if (check_boundary( _x[i], _dF_x[i-1])>2) {
00247 goto boundary;
00248 }
00249
00250 if (_boundary_hit) {
00251 _dF_x[i-1] = (_F.*_df)( _x[i]);
00252 } else {
00253 real df_dx = (_F.*_df)( _x[i]);
00254 _dF_x[i-1] = .5 * (_dF_x[i-1] + df_dx);
00255 }
00256 }
00257
00258 _x[i] = _x[i-1] - (_F_x[i-1]) / _dF_x[i-1];
00259
00260 if (check_boundary( _x[i], _dF_x[i-1])>2) {
00261 goto boundary;
00262 }
00263
00264 continue;
00265
00266 boundary:
00267 if (_lower_boundary_hit) {
00268 _boundary_solution = true;
00269 _x_converge = _min_x;
00270 _f_converge = (_F.*_f)( _min_x);
00271 break;
00272 }
00273
00274 if (_upper_boundary_hit) {
00275 _boundary_solution = true;
00276 _x_converge = _max_x;
00277 _f_converge = (_F.*_f)( _max_x);
00278 break;
00279 }
00280 }
00281
00282 if (_diverged && output) {
00283 *output << "answer diverged" << endl;
00284 }
00285
00286 if (_boundary_solution && output) {
00287 *output << i << " " << _x_converge << " " << _f_converge << " boundary_solution" << endl;
00288 } else if (_converged && output) {
00289 *output << i << " " << _x[i] << " " << _F_x[i] << " answer converged" << endl;
00290 }
00291 }
00292 };
00293
00294
00295 #endif