-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathComplex_contagions2.py
76 lines (58 loc) · 2.62 KB
/
Complex_contagions2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import networkx as nx
import EoN
import numpy as np
import matplotlib.pyplot as plt
from collections import defaultdict
def transition_rate(G, node, status, parameters):
#Esta función debe devolver la tasa a la que \texttt{node} cambia de estado.
#Para el modelo que estamos asumiendo, debería devolver 1 si \texttt{node} tiene al menos
#socios infectados y 0 en caso contrario. La información sobre el umbral
#se proporciona en la tupla \texttt{parameters}.
r = parameters[0] #El umbral
#Si hay parejas susceptibles y al menos \texttt{r} infectadas, entonces la tasa es 1
if status[node] == "S" and len([nbr for nbr in G.neighbors(node) if
status[nbr] == "I"])>=r:
return 1
else:
return 0
def transition_choice(G, node, status, parameters):
#Esta función debe devolver el nuevo estado del nodo. Suponemos que al entrar
#ya hemos calculado que está cambiando de estado.
#Esta función podría ser más elaborada si hubiera diferentes
#transiciones posibles que pudieran ocurrir. Sin embargo, para este modelo,
#los nodos 'I' no están cambiando de estado, y los 'S' están cambiando a
#'I'. Entonces, si estamos en esta función, el nodo debe ser 'S' y convertirse en 'I'
return "I"
def get_influence_set(G, node, status, parameters):
#Esta función debe devolver un conjunto que contenga todos los nodos cuyas tasas
#podrían cambiar debido a que \texttt{node} acaba de cambiar de estado. Es decir, ¿qué nodos
#podrían verse afectados por \texttt{node}?
#Para nuestros modelos, los únicos nodos a los que un nodo podría afectar son los vecinos susceptibles.
return {nbr for nbr in G.neighbors(node) if status[nbr] == "S"}
parameters = (2,)
#este es el umbral. Tenga en cuenta la coma. Es necesaria
#para que Python se dé cuenta de que se trata de una tupla de 1, no solo un
#número.\texttt{parámetros} se envía como una tupla, por lo que necesitamos
#la coma.
N = 600000
deg_dist = [(0,1), (0,2), (0,3)]*int(N/3)
print("generando gráfico G con {} nodos".format(N))
G = nx.random_clustered_graph(deg_dist)
for rho in np.linspace(1./80, 5./80, 8):
#8 values from 3/80 to 7/80.
print(rho)
IC = defaultdict(lambda: "S")
for node in G.nodes():
if np.random.random()<rho: #there are faster ways to do this random
#selection
IC[node] = "I"
print("Simulación de Gillespie")
t, S, I = EoN.Gillespie_complex_contagion(G, transition_rate,
transition_choice, get_influence_set, IC,
return_statuses = ("S", "I"),
parameters = parameters)
print("Terminé con la simulación, ahora estoy trazando")
plt.plot(t, I)
plt.xlabel("$t$")
plt.ylabel("Numero de infectados")
plt.show()