naive_monte_carlo_example.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright Nick Thompson, 2017
  3. * Use, modification and distribution are subject to the
  4. * Boost Software License, Version 1.0. (See accompanying file
  5. * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. #include <boost/math/quadrature/naive_monte_carlo.hpp>
  8. #include <iostream>
  9. #include <iomanip>
  10. #include <limits>
  11. #include <cmath>
  12. #include <thread>
  13. #include <future>
  14. #include <string>
  15. #include <chrono>
  16. #include <boost/math/special_functions/pow.hpp>
  17. #include <boost/math/constants/constants.hpp>
  18. using std::vector;
  19. using std::pair;
  20. using boost::math::quadrature::naive_monte_carlo;
  21. void display_progress(double progress,
  22. double error_estimate,
  23. double current_estimate,
  24. std::chrono::duration<double> estimated_time_to_completion)
  25. {
  26. int barWidth = 70;
  27. std::cout << "[";
  28. int pos = barWidth * progress;
  29. for (int i = 0; i < barWidth; ++i) {
  30. if (i < pos) std::cout << "=";
  31. else if (i == pos) std::cout << ">";
  32. else std::cout << " ";
  33. }
  34. std::cout << "] "
  35. << int(progress * 100.0)
  36. << "%, E = "
  37. << std::setprecision(3)
  38. << error_estimate
  39. << ", time to completion: "
  40. << estimated_time_to_completion.count()
  41. << " seconds, estimate: "
  42. << std::setprecision(5)
  43. << current_estimate
  44. << " \r";
  45. std::cout.flush();
  46. }
  47. int main()
  48. {
  49. double exact = 1.3932039296856768591842462603255;
  50. double A = 1.0 / boost::math::pow<3>(boost::math::constants::pi<double>());
  51. auto g = [&](std::vector<double> const & x)
  52. {
  53. return A / (1.0 - cos(x[0])*cos(x[1])*cos(x[2]));
  54. };
  55. vector<pair<double, double>> bounds{{0, boost::math::constants::pi<double>() }, {0, boost::math::constants::pi<double>() }, {0, boost::math::constants::pi<double>() }};
  56. naive_monte_carlo<double, decltype(g)> mc(g, bounds, 0.001);
  57. auto task = mc.integrate();
  58. int s = 0;
  59. std::cout << "Hit ctrl-c to cancel.\n";
  60. while (task.wait_for(std::chrono::seconds(1)) != std::future_status::ready)
  61. {
  62. display_progress(mc.progress(),
  63. mc.current_error_estimate(),
  64. mc.current_estimate(),
  65. mc.estimated_time_to_completion());
  66. // TODO: The following shows that cancellation works,
  67. // but it would be nice to show how it works with a ctrl-c signal handler.
  68. if (s++ > 25){
  69. mc.cancel();
  70. std::cout << "\nCancelling because this is too slow!\n";
  71. }
  72. }
  73. double y = task.get();
  74. display_progress(mc.progress(),
  75. mc.current_error_estimate(),
  76. mc.current_estimate(),
  77. mc.estimated_time_to_completion());
  78. std::cout << std::setprecision(std::numeric_limits<double>::digits10) << std::fixed;
  79. std::cout << "\nFinal value: " << y << std::endl;
  80. std::cout << "Exact : " << exact << std::endl;
  81. std::cout << "Final error estimate: " << mc.current_error_estimate() << std::endl;
  82. std::cout << "Actual error : " << abs(y - exact) << std::endl;
  83. std::cout << "Function calls: " << mc.calls() << std::endl;
  84. std::cout << "Is this good enough? [y/N] ";
  85. bool goodenough = true;
  86. std::string line;
  87. std::getline(std::cin, line);
  88. if (line[0] != 'y')
  89. {
  90. goodenough = false;
  91. }
  92. double new_error = -1;
  93. if (!goodenough)
  94. {
  95. std::cout << "What is the new target error? ";
  96. std::getline(std::cin, line);
  97. new_error = atof(line.c_str());
  98. if (new_error >= mc.current_error_estimate())
  99. {
  100. std::cout << "That error bound is already satisfied.\n";
  101. return 0;
  102. }
  103. }
  104. if (new_error > 0)
  105. {
  106. mc.update_target_error(new_error);
  107. auto task = mc.integrate();
  108. std::cout << "Hit ctrl-c to cancel.\n";
  109. while (task.wait_for(std::chrono::seconds(1)) != std::future_status::ready)
  110. {
  111. display_progress(mc.progress(),
  112. mc.current_error_estimate(),
  113. mc.current_estimate(),
  114. mc.estimated_time_to_completion());
  115. }
  116. double y = task.get();
  117. display_progress(mc.progress(),
  118. mc.current_error_estimate(),
  119. mc.current_estimate(),
  120. mc.estimated_time_to_completion());
  121. std::cout << std::setprecision(std::numeric_limits<double>::digits10) << std::fixed;
  122. std::cout << "\nFinal value: " << y << std::endl;
  123. std::cout << "Exact : " << exact << std::endl;
  124. std::cout << "Final error estimate: " << mc.current_error_estimate() << std::endl;
  125. std::cout << "Actual error : " << abs(y - exact) << std::endl;
  126. std::cout << "Function calls: " << mc.calls() << std::endl;
  127. }
  128. }