Advertisement
MaxObznyi

MonteCarlo

Apr 11th, 2021
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.49 KB | None | 0 0
  1. #include <iostream>
  2. #include <cmath>
  3. #include <vector>
  4. #include <random>
  5. #include <chrono>
  6. #define pb push_bac
  7. #define MONTECARLOITERATIONS 1000000
  8. using namespace std;
  9.  
  10. namespace OboznyiMaksymArea {
  11.  
  12. const double PI = acos(-1);
  13.  
  14. struct Point {
  15. int x, y;
  16. };
  17.  
  18. int R, n;
  19. vector<Point> polygon;
  20.  
  21. double s(Point a, Point b, Point c) {
  22. return (a.x - b.x) * (a.y + b.y) + (b.x - c.x) * (b.y + c.y) + (c.x - a.x) * (c.y + a.y);
  23. }
  24.  
  25. bool is_inside(Point p) {
  26. for (int i = 0; i + 1 < polygon.size(); i++)
  27. if (s(polygon[i], p, polygon[i + 1]) < 0)
  28. return 0;
  29. return 1;
  30. }
  31.  
  32. int f0 = 1, f1 = 1;
  33.  
  34. double MonteCarloOurArea() {
  35.  
  36. if (MONTECARLOITERATIONS * n > 100'000'000) {
  37. cout << "The polygon is too big for Monte-Carlo method\n";
  38. return 0;
  39. }
  40. int good = 0;
  41. for (int k = 0; k < MONTECARLOITERATIONS; k++) {
  42. Point cur;
  43. cur.x = f0;
  44. f1 = f1 + f0;
  45. f0 = f1 - f0;
  46. f1 %= (2 * R + 1);
  47. f0 %= (2 * R + 1);
  48.  
  49. cur.y = f0;
  50. f1 = f1 + f0;
  51. f0 = f1 - f0;
  52. f1 %= (2 * R + 1);
  53. f0 %= (2 * R + 1);
  54.  
  55.  
  56. if (is_inside(cur))
  57. good++;
  58. }
  59. return good * 1.0 / MONTECARLOITERATIONS * (4 * R * R);
  60.  
  61. }
  62.  
  63. double MonteCarloStdArea() {
  64. if (MONTECARLOITERATIONS * n > 100'000'000) {
  65. cout << "The polygon is too big for Monte-Carlo method\n";
  66. return 0;
  67. }
  68. mt19937 gen;
  69. gen.seed(time(0));
  70. int good = 0;
  71. for (int k = 0; k < MONTECARLOITERATIONS; k++) {
  72. Point cur;
  73. cur.x = gen() % (2 * R + 1) - R;
  74. cur.y = gen() % (2 * R + 1) - R;
  75. if (is_inside(cur))
  76. good++;
  77. }
  78. return good * 1.0 / MONTECARLOITERATIONS * (4 * R * R);
  79.  
  80. }
  81.  
  82. double GeometryArea() {
  83. return n * 0.5 * R * R * sin(2 * PI / n);
  84. }
  85.  
  86. double CellMethodArea() {
  87. if (R * R * n > 20'000'000) {
  88. cout << "The polygon is too big for cell method\n";
  89. return 0;
  90. }
  91. int full = 0, part = 0;
  92. for (int i = -R; i < R; i++)
  93. for (int j = -R; j < R; j++) {
  94. if (is_inside({i, j}) && is_inside({i, j + 1}) && is_inside({i + 1, j}) && is_inside({i + 1, j + 1}))
  95. full++;
  96. else if (is_inside({i, j}) || is_inside({i, j + 1}) || is_inside({i + 1, j}) || is_inside({i + 1, j + 1}))
  97. part++;
  98. }
  99. return full + part * 0.5;
  100. }
  101. void run() {
  102. cout << "Enter the number of points(from 3 to 100): ";
  103. while (1) {
  104. cin >> n;
  105. if (n < 3 || n > 100)
  106. cout << "Incorrect value\n";
  107. else
  108. break;
  109. }
  110.  
  111. cout << "Enter the radius(from 1 to 1000): ";
  112. while (1) {
  113. cin >> R;
  114. if (R < 1 || R > 1000)
  115. cout << "Incorrect value\n";
  116. else
  117. break;
  118. }
  119.  
  120. double alpha = 2 * PI / n;
  121. for (int i = 0; i < n; i++)
  122. polygon.push_back({R * sin(i * alpha), R * cos(i * alpha)});
  123. polygon.push_back(polygon[0]);
  124.  
  125. double ideal = GeometryArea();
  126. cout << "Geometry: " << ideal << endl;
  127. double area = MonteCarloOurArea();
  128. cout << "Our generator: " << area << ' ' << (area - ideal) / ideal << endl;
  129. area = MonteCarloStdArea();
  130. cout << "Mt19937 generator: " << area << ' ' << (area - ideal) / ideal << endl;
  131. area = CellMethodArea();
  132. cout << "Cell: " << area << ' ' << (area - ideal) / ideal << endl;
  133.  
  134. }
  135. }
  136.  
  137. int main()
  138. {
  139.  
  140. OboznyiMaksymArea::run();
  141. return 0;
  142. }
  143.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement