newton-raphson.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /* Boost example/newton-raphson.cpp
  2. * Newton iteration for intervals
  3. *
  4. * Copyright 2003 Guillaume Melquiond
  5. *
  6. * Distributed under the Boost Software License, Version 1.0.
  7. * (See accompanying file LICENSE_1_0.txt or
  8. * copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #include <boost/numeric/interval.hpp>
  11. #include <vector>
  12. #include <algorithm>
  13. #include <utility>
  14. #include <iostream>
  15. #include <iomanip>
  16. template <class I> I f(const I& x)
  17. { return x * (x - 1.) * (x - 2.) * (x - 3.) * (x - 4.); }
  18. template <class I> I f_diff(const I& x)
  19. { return (((5. * x - 40.) * x + 105.) * x - 100.) * x + 24.; }
  20. static const double max_width = 1e-10;
  21. static const double alpha = 0.75;
  22. using namespace boost;
  23. using namespace numeric;
  24. using namespace interval_lib;
  25. // First method: no empty intervals
  26. typedef interval<double> I1_aux;
  27. typedef unprotect<I1_aux>::type I1;
  28. std::vector<I1> newton_raphson(const I1& xs) {
  29. std::vector<I1> l, res;
  30. I1 vf, vd, x, x1, x2;
  31. l.push_back(xs);
  32. while (!l.empty()) {
  33. x = l.back();
  34. l.pop_back();
  35. bool x2_used;
  36. double xx = median(x);
  37. vf = f<I1>(xx);
  38. vd = f_diff<I1>(x);
  39. if (zero_in(vf) && zero_in(vd)) {
  40. x1 = I1::whole();
  41. x2_used = false;
  42. } else {
  43. x1 = xx - division_part1(vf, vd, x2_used);
  44. if (x2_used) x2 = xx - division_part2(vf, vd);
  45. }
  46. if (overlap(x1, x)) x1 = intersect(x, x1);
  47. else if (x2_used) { x1 = x2; x2_used = false; }
  48. else continue;
  49. if (x2_used) {
  50. if (overlap(x2, x)) x2 = intersect(x, x2);
  51. else x2_used = false;
  52. }
  53. if (x2_used && width(x2) > width(x1)) std::swap(x1, x2);
  54. if (!zero_in(f(x1))) {
  55. if (x2_used) { x1 = x2; x2_used = false; }
  56. else continue;
  57. }
  58. if (width(x1) < max_width) res.push_back(x1);
  59. else if (width(x1) > alpha * width(x)) {
  60. std::pair<I1, I1> p = bisect(x);
  61. if (zero_in(f(p.first))) l.push_back(p.first);
  62. x2 = p.second;
  63. x2_used = true;
  64. } else l.push_back(x1);
  65. if (x2_used && zero_in(f(x2))) {
  66. if (width(x2) < max_width) res.push_back(x2);
  67. else l.push_back(x2);
  68. }
  69. }
  70. return res;
  71. }
  72. // Second method: with empty intervals
  73. typedef change_checking<I1_aux, checking_no_nan<double> >::type I2_aux;
  74. typedef unprotect<I2_aux>::type I2;
  75. std::vector<I2> newton_raphson(const I2& xs) {
  76. std::vector<I2> l, res;
  77. I2 vf, vd, x, x1, x2;
  78. l.push_back(xs);
  79. while (!l.empty()) {
  80. x = l.back();
  81. l.pop_back();
  82. double xx = median(x);
  83. vf = f<I2>(xx);
  84. vd = f_diff<I2>(x);
  85. if (zero_in(vf) && zero_in(vd)) {
  86. x1 = x;
  87. x2 = I2::empty();
  88. } else {
  89. bool x2_used;
  90. x1 = intersect(x, xx - division_part1(vf, vd, x2_used));
  91. x2 = intersect(x, xx - division_part2(vf, vd, x2_used));
  92. }
  93. if (width(x2) > width(x1)) std::swap(x1, x2);
  94. if (empty(x1) || !zero_in(f(x1))) {
  95. if (!empty(x2)) { x1 = x2; x2 = I2::empty(); }
  96. else continue;
  97. }
  98. if (width(x1) < max_width) res.push_back(x1);
  99. else if (width(x1) > alpha * width(x)) {
  100. std::pair<I2, I2> p = bisect(x);
  101. if (zero_in(f(p.first))) l.push_back(p.first);
  102. x2 = p.second;
  103. } else l.push_back(x1);
  104. if (!empty(x2) && zero_in(f(x2))) {
  105. if (width(x2) < max_width) res.push_back(x2);
  106. else l.push_back(x2);
  107. }
  108. }
  109. return res;
  110. }
  111. template<class T, class Policies>
  112. std::ostream &operator<<(std::ostream &os,
  113. const boost::numeric::interval<T, Policies> &x) {
  114. os << "[" << x.lower() << ", " << x.upper() << "]";
  115. return os;
  116. }
  117. int main() {
  118. {
  119. I1_aux::traits_type::rounding rnd;
  120. std::vector<I1> res = newton_raphson(I1(-1, 5.1));
  121. std::cout << "Results: " << std::endl << std::setprecision(12);
  122. for(std::vector<I1>::const_iterator i = res.begin(); i != res.end(); ++i)
  123. std::cout << " " << *i << std::endl;
  124. std::cout << std::endl;
  125. }
  126. {
  127. I2_aux::traits_type::rounding rnd;
  128. std::vector<I2> res = newton_raphson(I2(-1, 5.1));
  129. std::cout << "Results: " << std::endl << std::setprecision(12);
  130. for(std::vector<I2>::const_iterator i = res.begin(); i != res.end(); ++i)
  131. std::cout << " " << *i << std::endl;
  132. std::cout << std::endl;
  133. }
  134. }