-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathEstimate_pi.py
executable file
·92 lines (80 loc) · 3.86 KB
/
Estimate_pi.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/env python
from __future__ import division
from random import random
from math import pi
import matplotlib.pyplot as plt
"""
Script to simulate rain in a square field. Counting the number of rain drops in the inscribed circle of radius equal to the length of the field. The ratio of the number of drops in the circle to the total number of drops gives $\pi$.
"""
def rain_drop(length_of_field=1):
"""
Simulate a random rain drop
"""
return [(.5 - random()) * length_of_field, (.5 - random()) * length_of_field]
def is_point_in_circle(point, length_of_field=1):
"""
Return True if point is in inscribed circle
"""
return (point[0]) ** 2 + (point[1]) ** 2 <= (length_of_field / 2) ** 2
def plot_rain_drops(drops_in_circle, drops_out_of_circle, length_of_field=1, format='pdf'):
""" Function to draw rain drops """
number_of_drops_in_circle = len(drops_in_circle)
number_of_drops_out_of_circle = len(drops_out_of_circle)
number_of_drops = number_of_drops_in_circle + number_of_drops_out_of_circle
plt.figure()
plt.xlim(-length_of_field / 2, length_of_field / 2)
plt.ylim(-length_of_field / 2, length_of_field / 2)
plt.scatter([e[0] for e in drops_in_circle], [e[1] for e in drops_in_circle], color='blue', label="Drops in circle")
plt.scatter([e[0] for e in drops_out_of_circle], [e[1] for e in drops_out_of_circle], color='black', label="Drops out of circle")
plt.legend(loc="center")
plt.title("%s drops: %s landed in circle, estimating $\pi$ as %.4f." % (number_of_drops, number_of_drops_in_circle, 4 * number_of_drops_in_circle / number_of_drops))
plt.savefig("%s_drops.%s" % (number_of_drops, format))
def rain(number_of_drops=1000, length_of_field=1, plot=True, format='pdf', dynamic=False):
"""
Function to make rain drops.
"""
number_of_drops_in_circle = 0
drops_in_circle = []
drops_out_of_circle = []
pi_estimate = []
for k in range(number_of_drops):
d = (rain_drop(length_of_field))
if is_point_in_circle(d, length_of_field):
drops_in_circle.append(d)
number_of_drops_in_circle += 1
else:
drops_out_of_circle.append(d)
if dynamic: # The dynamic option if set to True will plot every new drop (this can be used to create animations of the simulation)
print "Plotting drop number: %s" % (k + 1)
plot_rain_drops(drops_in_circle, drops_out_of_circle, length_of_field, format)
pi_estimate.append(4 * number_of_drops_in_circle / (k + 1)) # This updates the list with the newest estimate for pi.
# Plot the pi estimates
plt.figure()
plt.scatter(range(1, number_of_drops + 1), pi_estimate)
max_x = plt.xlim()[1]
plt.hlines(pi, 0, max_x, color='black')
plt.xlim(0, max_x)
plt.title("$\pi$ estimate against number of rain drops")
plt.xlabel("Number of rain drops")
plt.ylabel("$\pi$")
plt.savefig("Pi_estimate_for_%s_drops_thrown.pdf" % number_of_drops)
if plot and not dynamic:
# If the plot option is passed and matplotlib is installed this plots
# the final set of drops
plot_rain_drops(drops_in_circle, drops_out_of_circle, length_of_field, format)
return [number_of_drops_in_circle, number_of_drops]
if __name__ == "__main__":
# Run the script from cli
from sys import argv
number_of_drops = 100
if len(argv) > 1: # If an argument is passed then change number of drops to be simulated.
number_of_drops = eval(argv[1])
# Two sets of simulations (comment out the unwanted one).
#r = rain(number_of_drops, plot=True, format='png', dynamic=True)
r = rain(number_of_drops, plot=True, format='png', dynamic=False)
# Print to screen:
print "----------------------"
print "%s drops" % number_of_drops
print "pi estimated as:"
print "\t%s" % (4 * r[0] / r[1])
print "----------------------"