Skip to content

Commit f830e40

Browse files
committed
Add test based on ex.19.2 from Vose
1 parent 0f68008 commit f830e40

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

tests/test_modeling.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
Min,
1111
Max,
1212
)
13+
from probabilit.distributions import Triangular
1314
import numpy as np
1415

1516

@@ -90,6 +91,44 @@ def test_mutual_fund_problem(self):
9091
np.testing.assert_allclose(samples.mean(), 76583.58738496085)
9192
np.testing.assert_allclose(samples.std(), 33483.2245611436)
9293

94+
def test_total_person_hours(self):
95+
"""Based on Example 19.2 from Risk Analysis: A Quantitative Guide, 3rd Edition by David Vose.
96+
97+
Estimate the number of person-hours requires to rivet 562 plates of a ship's hull.
98+
The quickest anyone has ever riveted a single plate is 3h 45min, while the worst time recorded is 5h 30min.
99+
Most likely value is estimated to be 4h 15min.
100+
What is the total person-hours?
101+
102+
Naively, we could model the problem as:
103+
total_person_hours = 562 * Triangular(3.75, 4.25, 5.5),
104+
but note that the triangular distribution here models the uncertainty of an individual plate,
105+
but we are using it as if it were the distribution of the average time for 562 plates.
106+
107+
A straight forward approach that gives the correct answer is to add 562 triangular distributions.
108+
"""
109+
110+
rng = np.random.default_rng(42)
111+
num_rivets = 562
112+
total_person_hours = 0
113+
114+
for i in range(num_rivets):
115+
total_person_hours += Triangular(low=3.75, mode=4.25, high=5.5, low_perc=0.00001, high_perc=0.99999)
116+
117+
num_samples = 10000
118+
res_total_person_hours = total_person_hours.sample(num_samples, rng)
119+
120+
121+
# The mean and standard deviation of a Triangular(3.75, 4.25, 5.5) are 4.5 and 0.368,
122+
# so by the Central Limit Theoreom we have that
123+
# total_person_hours = Normal(4.5 * 562, 0.368 * sqrt(562)) = Normal(2529, 8.724)
124+
expected_mean = 4.5 * num_rivets
125+
expected_std = 0.368 * np.sqrt(num_rivets)
126+
127+
sample_mean = np.mean(res_total_person_hours)
128+
sample_std = np.std(res_total_person_hours)
129+
130+
assert abs(sample_mean - expected_mean) < 0.3
131+
assert abs(sample_std - expected_std) < 0.1
93132

94133
def test_copying():
95134
# Create a graph

0 commit comments

Comments
 (0)