Created
October 23, 2020 20:10
-
-
Save kristovatlas/e9945d8e9360f4dac26cc07be44b12fd to your computer and use it in GitHub Desktop.
evidence.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
https://twitter.com/elliot_olds/status/1319364546880942080 | |
To keep calculations simple, let's fix population size to 100 | |
""" | |
POPULATION = 100 | |
FRED_PROB_FIRST = 1/(0.6 * POPULATION) | |
NOT_FRED_PROB_FIRST = 1-FRED_PROB_FIRST | |
def prob_no_blood_type(population, num_crime_scene): | |
""" | |
Suppose there are p people in the population and n people at the scene of | |
the crime. If we have no idea how many people are at the scene of the crime | |
(n is between 1 and p, inclusive), then the probability that Fred was one of | |
the people at the scene of the crime is n/p. | |
""" | |
return num_crime_scene * 1.0 / population | |
def prob_blood_type(population, num_crime_scene): | |
""" | |
If we know that there were at least two people at the scene of the crime | |
with blood types O (60%) and AB (1%) respectively, and that Fred has blood | |
type O, then the probability is changed. Since order does not matter, let's | |
fix the first person at the scene as blood type O, the second as blood type | |
AB, and the remainder (if any) as being any remaining member of the | |
population. | |
The probability that Fred is the O type (first) is 1/(0.6p) | |
The probability that Fred isn't the O type (first) is 1-(1/(0.6p)) | |
The probability that Fred is the AB type (second) is 0 | |
The probability that is third or later is based on the probability that | |
Fred was in none of the previous places multiplied by probability that | |
he was at a specific place. He cannot appear in multiple places, of | |
course. | |
We will calculate the total probability that one of the suspects is Fred. | |
""" | |
fred_prob_first = 1/(0.6 * population) | |
not_fred_prob_first = 1-fred_prob_first | |
fred_total_prob = fred_prob_first | |
# The probability that all previous suspects were not Fred. We will add to | |
# this list as we continue to calculate from N=3 to N=num_crime_scene | |
not_fred_lookup_table = [not_fred_prob_first, not_fred_prob_first] | |
# nth_person_at_scene is 0-based; starting at 2 since Fred can't be the | |
# second person given his blood type of O | |
for nth_person_at_scene in range(2, num_crime_scene): | |
not_fred_prev = not_fred_lookup_table[nth_person_at_scene - 1] | |
new_prob_fred = 1.0 / (population - nth_person_at_scene) | |
new_prob_not_fred = 1 - new_prob_fred | |
not_fred_lookup_table.append(not_fred_prev * new_prob_not_fred) | |
current_prob = not_fred_prev * new_prob_fred | |
fred_total_prob += current_prob | |
return fred_total_prob | |
def main(): | |
""" | |
Let's compare likelihoods for Fred given fixed P = 100 and various N's | |
We can skip N=1 since there's no comparison for the blood type scenario | |
""" | |
print("p,n,prob_no_blood,prob_blood") | |
#num_crime_scene is 1-based | |
for num_crime_scene in range(2, POPULATION + 1): | |
prob_no_blood = prob_no_blood_type(POPULATION, num_crime_scene) | |
prob_blood = prob_blood_type(POPULATION, num_crime_scene) | |
if prob_blood > 1: | |
prob_blood = 1 #correct rounding error | |
print("{p},{n},{prob_no_blood},{prob_blood}".format( | |
p=POPULATION, n=num_crime_scene, prob_no_blood=prob_no_blood, | |
prob_blood=prob_blood)) | |
if __name__ == '__main__': | |
main() |
Author
kristovatlas
commented
Oct 23, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment