Skip to content

Commit

Permalink
⬆️ UTLDR model
Browse files Browse the repository at this point in the history
  • Loading branch information
GiulioRossetti committed Apr 8, 2020
1 parent 335b78b commit dc8bb13
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 53 deletions.
106 changes: 54 additions & 52 deletions ndlib/models/epidemics/UTLDRModel.py
Expand Up @@ -27,13 +27,13 @@ def __init__(self, graph, seed=None):
"Exposed": 2,
"Infected": 1,
"Recovered": 3,
"Tested_E": 4,
"Tested_I": 5,
"Tested_H": 6,
"Tested_F": 7,
"Lockdown_S": 8,
"Lockdown_E": 9,
"Lockdown_I": 10,
"Identified_Exposed": 4,
"Hospitalized_mild": 5,
"Hospitalized_severe_ICU": 6,
"Hospitalized_severe": 7,
"Lockdown_Susceptible": 8,
"Lockdown_Exposed": 9,
"Lockdown_Infected": 10,
"Dead": 11,
"Vaccinated": 12,
}
Expand Down Expand Up @@ -85,25 +85,25 @@ def __init__(self, graph, seed=None):
"default": 0
},
"phi_e": {
"descr": "Testing probability if exposed",
"descr": "Testing probability if Exposed",
"range": [0, 1],
"optional": True,
"default": 0
},
"phi_i": {
"descr": "Testing probability if infected",
"descr": "Testing probability if Infected",
"range": [0, 1],
"optional": True,
"default": 0
},
"kappa_e": {
"descr": "Test False Negative probability if exposed",
"descr": "Test False Negative probability if Exposed",
"range": [0, 1],
"optional": True,
"default": 0.7
},
"kappa_i": {
"descr": "Test False Negative probability if infected",
"descr": "Test False Negative probability if Infected",
"range": [0, 1],
"optional": True,
"default": 0.9
Expand All @@ -115,10 +115,10 @@ def __init__(self, graph, seed=None):
"default": 1
},
"epsilon_l": {
"descr": "Social restriction due to lockdown (percentage of pruned edges)",
"descr": "Social restriction due to lockdown (maximum household size)",
"range": [0, 1],
"optional": True,
"default": 0.25
"default": 1
},
"lambda": {
"descr": "Lockdown effectiveness (percentage of compliant individuals)",
Expand All @@ -127,7 +127,7 @@ def __init__(self, graph, seed=None):
"default": 1
},
"mu": {
"descr": "Lockdown length (1/expected iterations)",
"descr": "Lockdown duration (1/expected iterations)",
"range": [0, 1],
"optional": True,
"default": 1
Expand All @@ -139,7 +139,7 @@ def __init__(self, graph, seed=None):
"default": 0
},
"p_l": {
"descr": "Probability of long-range interactions if in lockdown",
"descr": "Probability of long-range interactions if in Lockdown",
"range": [0, 1],
"optional": True,
"default": 0
Expand All @@ -151,13 +151,13 @@ def __init__(self, graph, seed=None):
"default": 0.25
},
"icu_b": {
"descr": "Beds availability in ICU (as percentage of the population)",
"descr": "Beds availability in ICU (absolute value)",
"range": [0, np.infty],
"optional": True,
"default": self.graph.number_of_nodes()
},
"iota": {
"descr": "ICU case probability",
"descr": "Severe case probability (needing ICU treatments)",
"range": [0, 1],
"optional": True,
"default": 1
Expand Down Expand Up @@ -246,7 +246,7 @@ def iteration(self, node_status=True):
res = np.random.random_sample() # probability of false negative result
if res > self.params['model']['kappa_e']:
self.__limit_social_contacts(u, neighbors, 'Tested')
actual_status[u] = self.available_statuses['Tested_E']
actual_status[u] = self.available_statuses['Identified_Exposed']
self.params['nodes']['tested'][u] = True
else:
at = np.random.random_sample()
Expand All @@ -265,12 +265,12 @@ def iteration(self, node_status=True):

if icup < self.params['model']['iota']:
if self.icu_b > 0 and not self.params['nodes']['ICU'][u]:
actual_status[u] = self.available_statuses['Tested_H']
actual_status[u] = self.available_statuses['Hospitalized_severe_ICU']
self.icu_b -= 1
else:
actual_status[u] = self.available_statuses['Tested_F']
actual_status[u] = self.available_statuses['Hospitalized_severe']
else:
actual_status[u] = self.available_statuses['Tested_I']
actual_status[u] = self.available_statuses['Hospitalized_mild']
self.params['nodes']['tested'][u] = True

else:
Expand All @@ -284,22 +284,22 @@ def iteration(self, node_status=True):

####################### Quarantined Compartment ###########################

elif u_status == self.available_statuses['Tested_E']:
elif u_status == self.available_statuses['Identified_Exposed']:
at = np.random.random_sample()
if at < self.params['model']['sigma']:
icup = np.random.random_sample()
# icu_avalaibility = np.random.random_sample()
if icup < self.params['model']['iota']:
if self.icu_b > 0 and not self.params['nodes']['ICU'][u]:
actual_status[u] = self.available_statuses['Tested_H']
actual_status[u] = self.available_statuses['Hospitalized_severe_ICU']
self.icu_b -= 1
else:
actual_status[u] = self.available_statuses['Tested_F']
actual_status[u] = self.available_statuses['Hospitalized_severe']
else:
actual_status[u] = self.available_statuses['Tested_I']
actual_status[u] = self.available_statuses['Hospitalized_mild']
self.params['nodes']['ICU'][u] = True

elif u_status == self.available_statuses['Tested_I']:
elif u_status == self.available_statuses['Hospitalized_mild']:
recovered = np.random.random_sample()
if recovered < self.params['model']['gamma']:
actual_status[u] = self.available_statuses['Recovered']
Expand All @@ -308,7 +308,7 @@ def iteration(self, node_status=True):
if dead < self.params['model']['omega']:
actual_status[u] = self.available_statuses['Dead']

elif u_status == self.available_statuses['Tested_F']:
elif u_status == self.available_statuses['Hospitalized_severe']:
recovered = np.random.random_sample()
if recovered < self.params['model']['gamma_f']:
actual_status[u] = self.available_statuses['Recovered']
Expand All @@ -317,7 +317,7 @@ def iteration(self, node_status=True):
if dead < self.params['model']['omega_f']:
actual_status[u] = self.available_statuses['Dead']

elif u_status == self.available_statuses['Tested_H']:
elif u_status == self.available_statuses['Hospitalized_severe_ICU']:
recovered = np.random.random_sample()
if recovered < self.params['model']['gamma_t']:
actual_status[u] = self.available_statuses['Recovered']
Expand All @@ -330,7 +330,7 @@ def iteration(self, node_status=True):

####################### Lockdown Compartment ###########################

elif u_status == self.available_statuses['Lockdown_S']:
elif u_status == self.available_statuses['Lockdown_Susceptible']:
# test lockdown exit
exit = np.random.random_sample() # loockdown acceptance
if exit < self.params['model']['mu']:
Expand All @@ -340,7 +340,7 @@ def iteration(self, node_status=True):
else:
actual_status[u] = self.__Susceptible_to_Exposed(u, neighbors, lockdown=True)

elif u_status == self.available_statuses['Lockdown_E']:
elif u_status == self.available_statuses['Lockdown_Exposed']:
# test lockdown exit
exit = np.random.random_sample() # loockdown exit
if exit < self.params['model']['mu']:
Expand All @@ -350,9 +350,9 @@ def iteration(self, node_status=True):
else:
at = np.random.random_sample()
if at < self.params['model']['sigma']:
actual_status[u] = self.available_statuses['Lockdown_I']
actual_status[u] = self.available_statuses['Lockdown_Infected']

elif u_status == self.available_statuses['Lockdown_I']:
elif u_status == self.available_statuses['Lockdown_Infected']:
# test lockdown exit
exit = np.random.random_sample() # loockdown exit

Expand Down Expand Up @@ -416,15 +416,15 @@ def set_lockdown(self):
if la < self.params['model']['lambda']:

if actual_status[u] == self.available_statuses['Susceptible']:
actual_status[u] = self.available_statuses['Lockdown_S']
actual_status[u] = self.available_statuses['Lockdown_Susceptible']
self.__limit_social_contacts(u, event="Lockdown")

elif actual_status[u] == self.available_statuses['Exposed']:
actual_status[u] = self.available_statuses["Lockdown_E"]
actual_status[u] = self.available_statuses["Lockdown_Exposed"]
self.__limit_social_contacts(u, event="Lockdown")

elif actual_status[u] == self.available_statuses['Infected']:
actual_status[u] = self.available_statuses['Lockdown_I']
actual_status[u] = self.available_statuses['Lockdown_Infected']
self.__limit_social_contacts(u, event="Lockdown")

delta, node_count, status_delta = self.status_delta(actual_status)
Expand All @@ -439,11 +439,11 @@ def unset_lockdown(self):

for u in self.graph.nodes:
self.__ripristinate_social_contacts(u)
if actual_status[u] == self.available_statuses['Lockdown_S']:
if actual_status[u] == self.available_statuses['Lockdown_Susceptible']:
actual_status[u] = self.available_statuses['Susceptible']
elif actual_status[u] == self.available_statuses['Lockdown_E']:
elif actual_status[u] == self.available_statuses['Lockdown_Exposed']:
actual_status[u] = self.available_statuses["Exposed"]
elif actual_status[u] == self.available_statuses['Lockdown_I']:
elif actual_status[u] == self.available_statuses['Lockdown_Infected']:
actual_status[u] = self.available_statuses['Infected']

delta, node_count, status_delta = self.status_delta(actual_status)
Expand All @@ -464,11 +464,11 @@ def __limit_social_contacts(self, u, neighbors=None, event='Tested'):

if event == 'Tested':
filtering_prob = self.params['model']['epsilon_e']
remaining_candidates = [n for n in neighbors if len(self.params['nodes']['filtered'][n]) == 0]
size = min(int(len(neighbors) * (1 - filtering_prob)), len(remaining_candidates))
else:
filtering_prob = self.params['model']['epsilon_l']

remaining_candidates = [n for n in neighbors if len(self.params['nodes']['filtered'][n]) == 0]
size = min(int(len(neighbors)*(1-filtering_prob)), len(remaining_candidates))
houseold_max_size = self.params['model']['epsilon_l']
size = list(np.random.choice(a=range(houseold_max_size), size=1))[0]

to_keep = list(np.random.choice(a=neighbors, size=size, replace=False))
self.params['nodes']['filtered'][u] = to_keep
Expand Down Expand Up @@ -513,12 +513,14 @@ def __Susceptible_to_Exposed(self, u, neighbors, lockdown=False):
if l_range < l_range_proba:
# filtering out quarantined and dead nodes
if self.params['model']['z'] == 0:
candidates = [n for n in self.graph.nodes if self.status[n] not in [self.available_statuses['Tested_E'],
self.available_statuses['Tested_I'],
self.available_statuses['Dead']]]
candidates = [n for n in self.graph.nodes if self.status[n] not in
[self.available_statuses['Identified_Exposed'],
self.available_statuses['Hospitalized_mild'],
self.available_statuses['Dead']]]
else:
candidates = [n for n in self.graph.nodes if self.status[n] not in [self.available_statuses['Tested_E'],
self.available_statuses['Tested_I']]
candidates = [n for n in self.graph.nodes if self.status[n] not in
[self.available_statuses['Identified_Exposed'],
self.available_statuses['Hospitalized_mild']]
]

interactions.extend(list(np.random.choice(a=candidates,
Expand All @@ -527,22 +529,22 @@ def __Susceptible_to_Exposed(self, u, neighbors, lockdown=False):

for v in interactions:
if self.status[v] == self.available_statuses['Infected'] or \
self.status[v] == self.available_statuses['Lockdown_I'] or \
self.status[v] == self.available_statuses['Tested_I']:
self.status[v] == self.available_statuses['Lockdown_Infected'] or \
self.status[v] == self.available_statuses['Hospitalized_mild']:
bt = np.random.random_sample()

if bt < self.params['model']['beta']:
if lockdown:
return self.available_statuses['Lockdown_E']
return self.available_statuses['Lockdown_Exposed']
return self.available_statuses['Exposed']

elif self.status[v] == self.available_statuses['Dead']:
zp = np.random.random_sample()
if zp < self.params['model']['z']: # infection risk due to partial corpse disposal
if lockdown:
return self.available_statuses['Lockdown_E']
return self.available_statuses['Lockdown_Exposed']
return self.available_statuses['Exposed']

if lockdown:
return self.available_statuses['Lockdown_S']
return self.available_statuses['Lockdown_Susceptible']
return self.available_statuses['Susceptible']
2 changes: 1 addition & 1 deletion ndlib/test/test_ndlib.py
Expand Up @@ -73,7 +73,7 @@ def test_utldr(self):

# Lockdown
config.add_model_parameter("lambda", 0.8)
config.add_model_parameter("epsilon_l", 0.75)
config.add_model_parameter("epsilon_l", 5)
config.add_model_parameter("mu", 0.05)
config.add_model_parameter("p_l", 0.04)

Expand Down

0 comments on commit dc8bb13

Please sign in to comment.