-
Notifications
You must be signed in to change notification settings - Fork 9
/
corona_walk
149 lines (106 loc) · 4.12 KB
/
corona_walk
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 11 17:34:35 2020
@author: paul
"""
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
from random import randrange
from pylab import savefig
m,n=100,100
#N=m*n # Lattice size
M=40000 # Number of random walkers
L=20 # Lifetime params
max_iter=10000 # in like discrete time-steps
steps=100 # total number of times
sick, dead, iterate=0,0,0 # counters
neighbors=[] # Store the neighbors here
Lat=nx.grid_2d_graph(m,n) # A 2-D Lattice
nodes=[]
walkers={}
for i in Lat.nodes():
nodes.append(i)
walkers[i]=[]
nx.set_node_attributes(Lat,0,'infected') # Sets the attribute infected, the number of infected peeps at a node at any temporal point
nx.set_node_attributes(Lat,walkers,'walkers') # Sets the attribute walkers, the walkers at a node
x,y=np.zeros(M), np.zeros(M) # walker x,y coord
infect=np.zeros(M) # walker health status
lifespan=L*np.ones(M) # Time left to live
ts_sick=np.zeros(max_iter) # time series of sick walkers
#ts_dead=np.zeros(max_iter)
ts_ctr=np.zeros(max_iter) # counter to record each iter for averaging
iter_high=0 # The max count of iter (it doesn't go on till max_iter)
def place(): # place walkers on lattice
for j in range(M):
( x[j] , y[j] )= nodes[randrange(len(nodes))]
Lat.nodes[ (x[j],y[j]) ]['walkers'].append(j) # add this walker at node
def first_case(): # infect a random walker
while(True):
cx,cy= nodes[randrange(len(nodes))]
temp=Lat.nodes[(cx,cy)]['walkers'] # may be empty if nodes>walkers....! So empty range Error
if (len(temp)!=0):
break
first_case=temp[randrange(len(temp))]
infect[first_case]=1
Lat.nodes[(cx,cy)]['infected']+=1
global sick
sick=1
def walk(j): # walk the walker to a new location
for i in Lat.neighbors( (x[j],y[j]) ):
neighbors.append(i)
# remove a walker from node!
Lat.nodes[(x[j],y[j])]['walkers'].remove(j)
( x[j] , y[j] )=neighbors[randrange(len(neighbors))]
# add him to the new node!
Lat.nodes[(x[j],y[j])]['walkers'].append(j)
def kill(j): # Kill a walker
infect[j]=2
global sick,dead
sick-=1
dead+=1
Lat.nodes[(x[j],y[j])]['walkers'].remove(j)
# 'infected' attribute is not updated as it gives the count of infected people at a hotspot. Going dead doesn't change that
# Maybe a new attribute for people dying in a location would be great!
def actions(j):
if infect[j]<2: #still alive
walk(j)
if infect[j]==1: #sick
lifespan[j]-=1
Lat.nodes[(x[j],y[j])]['infected']+=1 # so this guy is infected!
if lifespan[j]<=0: #go die!
kill(j)
for k in Lat.nodes[(x[j],y[j])]['walkers'] : ##!
if infect[k]==0 and k!=j: # healthy guy
infect[k]=1 # infect him!
global sick
sick+=1
Lat.nodes[(x[j],y[j])]['infected']+=1
def reset():
global sick,dead,iterate
sick,dead,iterate=0,0,0
while(steps>0):
place()
first_case()
while(sick>0) and (iterate < max_iter):
for j in range(0,M):
actions(j)
neighbors.clear()
ts_sick[iterate]+=sick
# ts_dead[iterate]=dead
ts_ctr[iterate]+=1
iterate+=1
if (iterate>iter_high) :
iter_high=iterate
reset()
steps-=1
# Averaging
for i in range(iter_high):
ts_sick[i]/=ts_ctr[i]
plt.plot(range(0,iter_high+10),ts_sick[0:iter_high+10])
#plt.plot(range(0,iterate+10),ts_dead[0:iterate+10])
plt.ylabel('Infected')
plt.xlabel('Discrete Time steps')
savefig("/home/paul/Documents/COVID/Lattice_model.png",dpi=400)
plt.show()