Skip to content

Commit 5543d14

Browse files
singlavcclauss
andauthored
estimate area under a curve defined by non-negative real-valued continuous function within a continuous interval using monte-carlo (TheAlgorithms#1785)
* estimate area under a curve defined by non-negative real-valued continuous function within a continuous interval using monte-carlo * run black; update comments * Use f”strings” and drop unnecessary returns Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent 652b891 commit 5543d14

File tree

1 file changed

+79
-29
lines changed

1 file changed

+79
-29
lines changed

maths/monte_carlo.py

+79-29
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
"""
22
@author: MatteoRaso
33
"""
4-
from numpy import pi, sqrt
4+
from math import pi, sqrt
55
from random import uniform
66
from statistics import mean
7+
from typing import Callable
78

89

910
def pi_estimator(iterations: int):
@@ -18,58 +19,107 @@ def pi_estimator(iterations: int):
1819
6. Print the estimated and numpy value of pi
1920
"""
2021
# A local function to see if a dot lands in the circle.
21-
def in_circle(x: float, y: float) -> bool:
22+
def is_in_circle(x: float, y: float) -> bool:
2223
distance_from_centre = sqrt((x ** 2) + (y ** 2))
2324
# Our circle has a radius of 1, so a distance
2425
# greater than 1 would land outside the circle.
2526
return distance_from_centre <= 1
2627

2728
# The proportion of guesses that landed in the circle
2829
proportion = mean(
29-
int(in_circle(uniform(-1.0, 1.0), uniform(-1.0, 1.0))) for _ in range(iterations)
30+
int(is_in_circle(uniform(-1.0, 1.0), uniform(-1.0, 1.0)))
31+
for _ in range(iterations)
3032
)
3133
# The ratio of the area for circle to square is pi/4.
3234
pi_estimate = proportion * 4
33-
print("The estimated value of pi is ", pi_estimate)
34-
print("The numpy value of pi is ", pi)
35-
print("The total error is ", abs(pi - pi_estimate))
35+
print(f"The estimated value of pi is {pi_estimate}")
36+
print(f"The numpy value of pi is {pi}")
37+
print(f"The total error is {abs(pi - pi_estimate)}")
3638

3739

38-
def area_under_line_estimator(iterations: int,
39-
min_value: float=0.0,
40-
max_value: float=1.0) -> float:
40+
def area_under_curve_estimator(
41+
iterations: int,
42+
function_to_integrate: Callable[[float], float],
43+
min_value: float = 0.0,
44+
max_value: float = 1.0,
45+
) -> float:
4146
"""
4247
An implementation of the Monte Carlo method to find area under
43-
y = x where x lies between min_value to max_value
44-
1. Let x be a uniformly distributed random variable between min_value to max_value
45-
2. Expected value of x = (integration of x from min_value to max_value) / (max_value - min_value)
46-
3. Finding expected value of x:
48+
a single variable non-negative real-valued continuous function,
49+
say f(x), where x lies within a continuous bounded interval,
50+
say [min_value, max_value], where min_value and max_value are
51+
finite numbers
52+
1. Let x be a uniformly distributed random variable between min_value to
53+
max_value
54+
2. Expected value of f(x) =
55+
(integrate f(x) from min_value to max_value)/(max_value - min_value)
56+
3. Finding expected value of f(x):
4757
a. Repeatedly draw x from uniform distribution
48-
b. Expected value = average of those values
49-
4. Actual value = (max_value^2 - min_value^2) / 2
58+
b. Evaluate f(x) at each of the drawn x values
59+
c. Expected value = average of the function evaluations
60+
4. Estimated value of integral = Expected value * (max_value - min_value)
5061
5. Returns estimated value
5162
"""
52-
return mean(uniform(min_value, max_value) for _ in range(iterations)) * (max_value - min_value)
5363

64+
return mean(
65+
function_to_integrate(uniform(min_value, max_value)) for _ in range(iterations)
66+
) * (max_value - min_value)
5467

55-
def area_under_line_estimator_check(iterations: int,
56-
min_value: float=0.0,
57-
max_value: float=1.0) -> None:
68+
69+
def area_under_line_estimator_check(
70+
iterations: int, min_value: float = 0.0, max_value: float = 1.0
71+
) -> None:
5872
"""
59-
Checks estimation error for area_under_line_estimator func
60-
1. Calls "area_under_line_estimator" function
73+
Checks estimation error for area_under_curve_estimator function
74+
for f(x) = x where x lies within min_value to max_value
75+
1. Calls "area_under_curve_estimator" function
6176
2. Compares with the expected value
6277
3. Prints estimated, expected and error value
6378
"""
64-
65-
estimated_value = area_under_line_estimator(iterations, min_value, max_value)
66-
expected_value = (max_value*max_value - min_value*min_value) / 2
67-
79+
80+
def identity_function(x: float) -> float:
81+
"""
82+
Represents identity function
83+
>>> [function_to_integrate(x) for x in [-2.0, -1.0, 0.0, 1.0, 2.0]]
84+
[-2.0, -1.0, 0.0, 1.0, 2.0]
85+
"""
86+
return x
87+
88+
estimated_value = area_under_curve_estimator(
89+
iterations, identity_function, min_value, max_value
90+
)
91+
expected_value = (max_value * max_value - min_value * min_value) / 2
92+
93+
print("******************")
94+
print(f"Estimating area under y=x where x varies from {min_value} to {max_value}")
95+
print(f"Estimated value is {estimated_value}")
96+
print(f"Expected value is {expected_value}")
97+
print(f"Total error is {abs(estimated_value - expected_value)}")
98+
print("******************")
99+
100+
101+
def pi_estimator_using_area_under_curve(iterations: int) -> None:
102+
"""
103+
Area under curve y = sqrt(4 - x^2) where x lies in 0 to 2 is equal to pi
104+
"""
105+
106+
def function_to_integrate(x: float) -> float:
107+
"""
108+
Represents semi-circle with radius 2
109+
>>> [function_to_integrate(x) for x in [-2.0, 0.0, 2.0]]
110+
[0.0, 2.0, 0.0]
111+
"""
112+
return sqrt(4.0 - x * x)
113+
114+
estimated_value = area_under_curve_estimator(
115+
iterations, function_to_integrate, 0.0, 2.0
116+
)
117+
68118
print("******************")
69-
print("Estimating area under y=x where x varies from ",min_value, " to ",max_value)
70-
print("Estimated value is ", estimated_value)
71-
print("Expected value is ", expected_value)
72-
print("Total error is ", abs(estimated_value - expected_value))
119+
print("Estimating pi using area_under_curve_estimator")
120+
print(f"Estimated value is {estimated_value}")
121+
print(f"Expected value is {pi}")
122+
print(f"Total error is {abs(estimated_value - pi)}")
73123
print("******************")
74124

75125

0 commit comments

Comments
 (0)