Skip to content

Instantly share code, notes, and snippets.

@ddobbelaere
Last active May 4, 2021 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ddobbelaere/e1b52ab9867c977f3ce30b7c725410ca to your computer and use it in GitHub Desktop.
Save ddobbelaere/e1b52ab9867c977f3ce30b7c725410ca to your computer and use it in GitHub Desktop.
Meest waarschijnlijke mol 2021
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import binom
names = ["Annelotte", "Dami", "Jasmien", "Katrien",
"Kevin", "Lennart", "Noah", "Philip", "Samina", "Sven"]
probs = []
# Aflevering 1.
#
# Op de uiteindelijke (tweede) eliminatie niemand af,
# maar er worden wel groene schermen getoond voor
# Annelotte, Jasmien, Katrien, Philip, Samina en Sven
# (en geen scherm voor de vier andere).
#
# Likelihood van gebeurtenissen is dus
# Als Annelotte, Jasmien, Katrien, Philip, Samina of Sven mol is,
# zijn er 4 mogelijkheden om de afvaller te kiezen.
# Indien niet, dan zijn er slechts 3 mogelijkheden om de afvaller te kiezen.
#
# Dit impliceert dat de kansen resp. 1/9 en 1/12 zijn.
probs.append({"Annelotte": 1/9,
"Dami": 1/12,
"Jasmien": 1/9,
"Katrien": 1/9,
"Kevin": 1/12,
"Lennart": 1/12,
"Noah": 1/12,
"Philip": 1/9,
"Samina": 1/9,
"Sven": 1/9})
# Aflevering 2.
#
# De 10 overblijvers worden opgedeeld in twee groepjes van 5,
# waarbij slechts 1 groepje (bestaande uit Dami, Kevin, Noah, Philip en Sven)
# hoeft deel te nemen aan de eliminatie. Er dienen ook 2 mensen af te vallen,
# en deze zijn Dami en Kevin.
#
# De waarschijnlijkheid dat deze situatie optreedt indien 1 van de mensen
# in het groepje van 3 overblijvers de mol is, is gelijk aan 1/2 x 1/4 x 1/3 x 2 = 1/12.
#
# De kans dat deze situatie optreedt indien een persoon uit het groepje van 5 overblijvers
# (die niet deelnamen aan de eliminatie) de mol is, is gegeven door 1/2 x 1/5 x 1/4 x 2 = 1/20.
probs.append({"Annelotte": 1/20,
"Dami": 0,
"Jasmien": 1/20,
"Katrien": 1/20,
"Kevin": 0,
"Lennart": 1/20,
"Noah": 1/12,
"Philip": 1/12,
"Samina": 1/20,
"Sven": 1/12})
# Aflevering 3.
#
# "Normale" eliminatie waarbij Jasmien en Katrien elk 1 pasvraag hebben en Noah afvalt.
#
# We veronderstellen dat iedereen de 20 vragen willekeurig beantwoordt en dat iedere vraag
# 4 mogelijke antwoorden heeft. Dit leidt tot een binomiale verdeling met p = 1/4 en N = 20.
# We stellen ons eerst de vraag wat de kans is dat iemand met een pasvraag een uiteindelijk
# lagere score heeft (scheidingspunt van tijd bij ex-aequo inbegrepen).
def p_pasvraag(n1=1, n2=0, p_vraag=1/4, aantal_vragen=20):
# Wat is de kans dat speler 1 afvalt in een rechtstreeks duel met speler 2?
# Overloop gewoon de gezamenlijke distributie...
# s1 is de score (zonder pasvraagcorrectie) van speler 1 met n1 pasvragen.
# s2 is de score (zonder pasvraagcorrectie) van speler 2 met n2 pasvragen.
totale_kans = 0
for s1 in range(aantal_vragen+1):
for s2 in range(aantal_vragen+1):
gezamenlijke_kans = binom.pmf(
s1, aantal_vragen, p_vraag)*binom.pmf(s2, aantal_vragen, p_vraag)
# Pasvraagcorrectie.
s1_p = min(aantal_vragen, s1+n1)
s2_p = min(aantal_vragen, s2+n2)
if s1_p < s2_p:
totale_kans += gezamenlijke_kans
elif s1_p == s2_p:
# Tijd is scheidingspunt.
# Kans is 1/2 dat speler 1 wint.
totale_kans += gezamenlijke_kans/2
return totale_kans
probs.append({"Annelotte": p_pasvraag(0, 1),
"Dami": 0,
"Jasmien": 1/2,
"Katrien": 1/2,
"Kevin": 0,
"Lennart": p_pasvraag(0, 1),
"Noah": 0,
"Philip": p_pasvraag(0, 1),
"Samina": p_pasvraag(0, 1),
"Sven": p_pasvraag(0, 1)})
# Aflevering 4.
# Annelotte krijgt 5 pasvragen, Sven krijgt 1 pasvraag.
# Katrien valt af.
probs.append({"Annelotte": p_pasvraag(0, 1) * 1/2,
"Dami": 0,
"Jasmien": p_pasvraag(0, 1) * p_pasvraag(0, 5),
"Katrien": 0,
"Kevin": 0,
"Lennart": p_pasvraag(0, 1) * p_pasvraag(0, 5),
"Noah": 0,
"Philip": p_pasvraag(0, 1) * p_pasvraag(0, 5),
"Samina": p_pasvraag(0, 1) * p_pasvraag(0, 5),
"Sven": 1/2 * p_pasvraag(0, 5)})
# Aflevering 5.
# Samina valt af.
probs.append({"Annelotte": 1,
"Dami": 0,
"Jasmien": 1,
"Katrien": 0,
"Kevin": 0,
"Lennart": 1,
"Noah": 0,
"Philip": 1,
"Samina": 0,
"Sven": 1})
# Aflevering 6.
# Lennart heeft vrijstelling.
# Jasmien valt af.
probs.append({"Annelotte": 1,
"Dami": 0,
"Jasmien": 0,
"Katrien": 0,
"Kevin": 0,
"Lennart": 1/2,
"Noah": 0,
"Philip": 1,
"Samina": 0,
"Sven": 1})
# Aflevering 7.
# Iedereen heeft een pasvraag, behalve Philip die afvalt.
probs.append({"Annelotte": 1,
"Dami": 0,
"Jasmien": 0,
"Katrien": 0,
"Kevin": 0,
"Lennart": 1,
"Noah": 0,
"Philip": 0,
"Samina": 0,
"Sven": 1})
# Bereken a posteriori kansen.
post_probs = [[1/len(names)] for name in names]
for k, prior_probs in enumerate(probs):
total_p = 0
for i, name in enumerate(names):
# Als kandidaat er al uit ligt, moet likelihood nul zijn.
assert post_probs[i][k] != 0 or prior_probs[name] == 0
# Bereken likelihood maal a priori kans.
new_prob = post_probs[i][k] * prior_probs[name]
post_probs[i].append(new_prob)
total_p += new_prob
# Normaliseer.
for i, name in enumerate(names):
post_probs[i][-1] /= total_p
N = len(post_probs[0])-1
for k in range(1, N+1):
print("Aflevering {}".format(k))
print("-------------")
for i, name in enumerate(names):
if post_probs[i][k] != 0:
print("{:<10s}: {:.1f}%".format(name, 100*post_probs[i][k]))
print()
# Plot.
bottom = np.ones(N)
plt.style.use('ggplot')
plt.figure(figsize=(8, 5))
col = sns.color_palette("Paired", 10)
for i, name in enumerate(names):
bottom -= post_probs[i][1:]
plt.bar(list(map(str, range(1, N+1))),
100*np.array(post_probs[i][1:]), bottom=100*bottom,
color=col[i], label=name)
plt.xlabel("Aflevering")
plt.ylabel("Kans (%)")
plt.title("Kans dat iemand de mol is")
plt.legend(loc='center left', framealpha=1)
plt.tight_layout()
plt.savefig("kans_na_{}_afleveringen.png".format(N))
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment