Issue
I am doing a project to which I predict the behaviour of COVID using a SEIRDV model. I have created the differential equations and have set initial parameters. I am solving these ODE's using the forward Euler method. When I create a program to find the S, E, I, R, D, V at each day for 180 days and display it using matplotlib. I get an error which can be seen below. I believe this is due to the following operation.
I[i]/N[i]
I am sort of new to NumPy and therefore not familiar with the errors that come up. Can anyone please inform me on how to fix this issue? In addition, I have tried plotting the data using matplotlib but the data points are all-over the place and not in the way a SEIRDV model representation should look like. Any insights on how to solve this would be greatly appreciated.
import matplotlib.pyplot as plt
import numpy as np
ndays = 180 # time length for prediction
dt = 1 # time step in days
S = np.zeros(ndays) # susceptibles
E = np.zeros(ndays) # exposed
I = np.zeros(ndays) # infective
R = np.zeros(ndays) # recovered / removed
D = np.zeros(ndays) # fatalities
V = np.zeros(ndays) # vaccinated but have had the vaccine for less than 21 days
N = np.zeros(ndays) # total population
t = np.arange(ndays)*dt
S[0] = 45167146 # initial S
E[0] = 20000 # initial E
I[0] = 3085 # initial I
R[0] = 19744004 # initial R
V[0] = 65000 # initial V
D[0] = 0 # initial D
N[0] = 60500000 # initial N
beta = (0.75) # infection rate
gam = (0.1) # recovery rate
Clamb = (0.00005) # birth rate
mu = (0.00003) # natural death rate
epsi = (0.07) # rate at which someone goes from E to I
alpha = (0.1) # rate at which Infectives die from the virus
Ldelta = (0.0006) # rate at which people get vaccinated
zeta = (0.07) # rate at which someone goes from V to R
for i in range(ndays-1):
S[i+1] = S[i] + (Clamb - mu*S[i] - beta*S[i]*(I[i]/N[i]) - Ldelta*S[i])*dt
E[i+1] = E[i] + (beta*S[i]*(I[i]/N[i]) + beta*V[i]*(I[i]/N[i]) - mu*E[i] - epsi*E[i])*dt
I[i+1] = I[i] + (epsi*E[i] - gam*I[i] - mu*I[i] - alpha*I[i])*dt
R[i+1] = R[i] + (gam*I[i] + zeta*V[i] - mu*R[i])*dt
D[i+1] = D[i] + (alpha*I[i])*dt
V[i+1] = V[i] + (Ldelta*S[i] - beta*V[i]*(I[i]/N[i]) - zeta*V[i])*dt
display (S)
fig = plt.figure(1)
plt.plot(t, S, "r", lw=2, label="Susceptible")
plt.plot(t, E, "y", lw=2, label="Exposed")
plt.plot(t, I, "g", lw=2, label="Infective")
plt.plot(t, R, "p", lw=2, label="Removed")
plt.plot(t, D, "b", lw=2, label="Fatalities")
plt.plot(t, V, "o", lw=2, label="Vaccinated before immunity")
fig.legend(); plt.xlabel("Days"); plt.ylabel("Amount of people")
This is the error I get
C:\Users\jared\AppData\Local\Temp/ipykernel_18008/1585353571.py:34: RuntimeWarning: divide by zero encountered in double_scalars
S[i+1] = S[i] + (Clamb - mu*S[i] - beta*S[i]*(I[i]/N[i]) - Ldelta*S[i])*dt
C:\Users\jared\AppData\Local\Temp/ipykernel_18008/1585353571.py:35: RuntimeWarning: divide by zero encountered in double_scalars
E[i+1] = E[i] + (beta*S[i]*(I[i]/N[i]) + beta*V[i]*(I[i]/N[i]) - mu*E[i] - epsi*E[i])*dt
C:\Users\jared\AppData\Local\Temp/ipykernel_18008/1585353571.py:39: RuntimeWarning: divide by zero encountered in double_scalars
V[i+1] = V[i] + (Ldelta*S[i] - beta*V[i]*(I[i]/N[i]) - zeta*V[i])*dt
C:\Users\jared\AppData\Local\Temp/ipykernel_18008/1585353571.py:34: RuntimeWarning: invalid value encountered in double_scalars
S[i+1] = S[i] + (Clamb - mu*S[i] - beta*S[i]*(I[i]/N[i]) - Ldelta*S[i])*dt
C:\Users\jared\AppData\Local\Temp/ipykernel_18008/1585353571.py:35: RuntimeWarning: invalid value encountered in double_scalars
E[i+1] = E[i] + (beta*S[i]*(I[i]/N[i]) + beta*V[i]*(I[i]/N[i]) - mu*E[i] - epsi*E[i])*dt
C:\Users\jared\AppData\Local\Temp/ipykernel_18008/1585353571.py:39: RuntimeWarning: invalid value encountered in double_scalars
V[i+1] = V[i] + (Ldelta*S[i] - beta*V[i]*(I[i]/N[i]) - zeta*V[i])*dt
Solution
You never update N[i]
, so it's 0
after the first step .. it should probably be set at each iteration and perhaps filled to begin with
EDIT: As @Lutz Lehmann notes in a comment, directly setting N[i]
isn't a trivial "add this line" and requires doing more work
- to get the previous
D[i-1]
(perhaps starting at index 1) - switching
N
to be cumulative living - switching
D
to immediate fatalities
i=0 S[i]=45167146.0 I[i]=3085.0 N[i]=60500000.0 dt=1
i=1 S[i]=45136963.33469715 I[i]=3867.90745 N[i]=0.0 dt=1
You can embed a print()
or use PDB to debug small programs very easily
% python3 -m pdb test_70976944.py
> test_70976944.py(1)<module>()
-> import matplotlib.pyplot as plt
(Pdb) b 34
Breakpoint 1 at test_70976944.py:34
(Pdb) c
> test_70976944.py(34)<module>()
-> S[i+1] = S[i] + (Clamb - mu*S[i] - beta*S[i]*(I[i]/N[i]) - Ldelta*S[i])*dt
(Pdb) print(f"i={i} S[i]={S[i]} I[i]={I[i]} N[i]={N[i]} dt={dt}")
i=0 S[i]=45167146.0 I[i]=3085.0 N[i]=60500000.0 dt=1
(Pdb) c
> test_70976944.py(34)<module>()
-> S[i+1] = S[i] + (Clamb - mu*S[i] - beta*S[i]*(I[i]/N[i]) - Ldelta*S[i])*dt
(Pdb) print(f"i={i} S[i]={S[i]} I[i]={I[i]} N[i]={N[i]} dt={dt}")
i=1 S[i]=45136963.33469715 I[i]=3867.90745 N[i]=0.0 dt=1
Answered By - ti7
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.