Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions tests/test_modeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
Min,
Max,
)
from probabilit.distributions import Triangular
import numpy as np


Expand Down Expand Up @@ -90,6 +91,46 @@ def test_mutual_fund_problem(self):
np.testing.assert_allclose(samples.mean(), 76583.58738496085)
np.testing.assert_allclose(samples.std(), 33483.2245611436)

def test_total_person_hours(self):
"""Based on Example 19.2 from Risk Analysis: A Quantitative Guide, 3rd Edition by David Vose.

Estimate the number of person-hours requires to rivet 562 plates of a ship's hull.
The quickest anyone has ever riveted a single plate is 3h 45min, while the worst time recorded is 5h 30min.
Most likely value is estimated to be 4h 15min.
What is the total person-hours?

Naively, we could model the problem as:
total_person_hours = 562 * Triangular(3.75, 4.25, 5.5),
but note that the triangular distribution here models the uncertainty of an individual plate,
but we are using it as if it were the distribution of the average time for 562 plates.

A straight forward approach that gives the correct answer is to add 562 triangular distributions.
"""

rng = np.random.default_rng(42)
num_rivets = 562
total_person_hours = 0

for i in range(num_rivets):
total_person_hours += Triangular(
low=3.75, mode=4.25, high=5.5, low_perc=0.00001, high_perc=0.99999
)

num_samples = 10000
res_total_person_hours = total_person_hours.sample(num_samples, rng)

# The mean and standard deviation of a Triangular(3.75, 4.25, 5.5) are 4.5 and 0.368,
# so by the Central Limit Theoreom we have that
# total_person_hours = Normal(4.5 * 562, 0.368 * sqrt(562)) = Normal(2529, 8.724)
expected_mean = 4.5 * num_rivets
expected_std = 0.368 * np.sqrt(num_rivets)

sample_mean = np.mean(res_total_person_hours)
sample_std = np.std(res_total_person_hours)

assert abs(sample_mean - expected_mean) < 0.3
assert abs(sample_std - expected_std) < 0.1


def test_copying():
# Create a graph
Expand Down