Last active
May 7, 2020 16:42
-
-
Save gngdb/8ddc6ca142178d280695ee7e3de62927 to your computer and use it in GitHub Desktop.
Brute Force Ancestral Monte Carlo I used for project planning when writing my PhD thesis
This file contains 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
# renders a MAP estimate of the PhD thesis timeline along with estimate of the | |
# 50%, 90% and 99% chance of thesis being complete | |
import numpy as np | |
import time | |
import datetime | |
from datetime import timedelta | |
def main(): | |
# model the PhD as a sequence of events of random length. | |
# would like to be recursively evaluated | |
# (name, n, p) | |
# (str, days to complete, probability of succesful workday) | |
to_complete = [#("Resouce-Efficient", 1, 2), DONE | |
#("Moonshine", 5, 0.8), DONE | |
#("Lit Review", 2, 0.9), DONE | |
("Low-Rank", 1, 0.8), | |
("Intro & Conclusion", 2, 0.8), | |
("Editing", 2, 0.8)] | |
# sample a lot | |
rng = np.random.RandomState(42) | |
n_samples = 100000 | |
samples = [(n,rng.geometric(p, size=(n_samples,d)).sum(1)) for n, d, p in to_complete] | |
# would be nice to take into account weekends, but probably not going to happen | |
# combine the samples to get no. of days to completion | |
sum_events = np.concatenate([s.reshape(1,-1) for n, s in samples],0) | |
sum_events = sum_events.sum(0) | |
today = datetime.date.fromtimestamp(time.time()) | |
if False: | |
###################### | |
# The NIPS condition # | |
###################### | |
# if any of these exceed the 2nd of December, add a week for NIPS | |
December2 = datetime.date(2018, 12, 2) | |
days_until = (December2 - today).days | |
exceeding = (sum_events > days_until).astype(int) | |
sum_events = sum_events + exceeding*7 # add a week where we hit NIPS | |
# sort scenarios | |
sum_events.sort() | |
p = lambda x: int(round(sum_events[x*n_samples//100])) | |
print("50 percent chance to be done by: " + str(today + timedelta(days=p(50)))) | |
print("90 percent chance to be done by: " + str(today + timedelta(days=p(90)))) | |
print("99 percent chance to be done by: " + str(today + timedelta(days=p(99)))) | |
return None | |
# draw timeline | |
days = 0 | |
current_month = today.month | |
to_complete = [] | |
for i, (n,m,s) in enumerate(to_complete): | |
sum_events = np.concatenate([s.reshape(1,-1) for n, s in samples[:i+1]],0) | |
sum_events = sum_events.sum(0) | |
sum_events.sort() | |
p = lambda x: int(round(sum_events[x*n_samples//100])) | |
to_complete.append((n[0], p(90))) | |
timeline = "" | |
total_days = p(90) | |
while days < total_days: | |
if days > days_until and days < days_until + 7: | |
timeline += "N" | |
to_complete = [(n,m+1) for n,m in to_complete] | |
total_days += 1 | |
else: | |
timeline += "-" | |
days += 1 | |
# see if we've changed month | |
now = today + timedelta(days) | |
if now.month > current_month: | |
current_month = now.month | |
timeline += "|%i|"%current_month | |
# to add in when stuff should be completed | |
past = [n for n,m in to_complete if days-m == 0] | |
if len(past) > 0: | |
to_complete.pop(0) | |
timeline += "|%s|"%past[0] | |
print(timeline) | |
if __name__ == '__main__': | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment