Modified SIR model

陌路散爱 提交于 2021-01-29 11:17:22

问题


I am making a modified SIR model with an added vaccination parameter V. InitIALLY all the nodes in the graph are susceptible and there are a few initially infected people. The initial infected people neighbours are first vaccinated with prob w (which means they cant be infected) and then they are infected with prob b. The total number of vaccinated people is controlled by Vl which is a fraction of the total population.

Here is my code-

import networkx as nx
import random
import scipy
from collections import defaultdict
from collections import Counter
import matplotlib.pyplot as plt
import numpy as np
from statistics import mean
from random import choice
from random import sample

def test_transmission(u, v, p):

    return random.random()<p


def discrete_SIR(G,
                initial_infecteds=None, initial_recovereds = None,beta=0.8,
                rho = None, w=0.5,Vl=1,tmin = 0, tmax = 100000,
                return_full_data = False):


    if G.has_node(initial_infecteds):
        initial_infecteds=[initial_infecteds]           

    N=  G.order()
    t = [tmin]
    S = [N-len(initial_infecteds)]
    I = [len(initial_infecteds)]
    R = [0]
    V = [0]

    susceptible = defaultdict(lambda: True)  
    #above line is equivalent to u.susceptible=True for all nodes.

    for u in initial_infecteds:
        susceptible[u] = False
    if initial_recovereds is not None:
        for u in initial_recovereds:
            susceptible[u] = False

    infecteds = set(initial_infecteds)
    print('len of infected initially',len(infecteds))

    while infecteds and t[-1]<tmax :
        print('len of infected on each iter',len(infecteds))
        new_infecteds = set()
        vaccinated = set()
        #infector = {}  #used for returning full data.  a waste of time otherwise
        for u in infecteds:
            print('u-->' +str(u))
            for v in G.neighbors(u):
                print('v --> '+ str(v))
            ##vaccination
                if len(vaccinated)+V[-1]< (Vl*N)  : #check if vaccination over or not
                #V.append(V[-1]+len(vaccinated))< (Vl*N)
                    #print(len(vaccinated),Vl*N)
                    print("HI")
                    print(V[-1])

                    if susceptible[v] and test_transmission(u, v, w):

                        vaccinated.add(v)
                        susceptible[v] = False
                        print('transmitting vaccination')

                    elif susceptible[v] and test_transmission(u,v,beta):
                        new_infecteds.add(v)
                        susceptible[v]=False
                        print('transmitting infection')
                else:

                    print("BYE")
                    if susceptible[v] and test_transmission(u, v,beta): 
                        new_infecteds.add(v)
                        susceptible[v] = False
                        #infector[v] = [u]



        infecteds = new_infecteds

        R.append(R[-1]+I[-1])
        V.append(len(vaccinated)+V[-1])
        I.append(len(infecteds))
        S.append(N-V[-1]-I[-1]-R[-1])
        #S.append(S[-1]-V[-1]-I[-1])
        t.append(t[-1]+1)

        print('\n')
        print('time is',str(t) +' --> ')
        print('infected is',I)
        print('sum is',R[-1]+V[-1]+I[-1]+S[-1])
        print('R V I S',str(R[-1])+','+str(V[-1])+','+str(I[-1])+','+str(S[-1]))
        print('time t[-1]',t[-1])


    if not return_full_data:
        return scipy.array(t), scipy.array(S),scipy.array(V), scipy.array(I), \
               scipy.array(R)





m=100
G=nx.grid_2d_graph(m,m,periodic=True)

def avg_deg(self,num_nodes):
        return self.number_of_edges() * 2 / num_nodes


def avg_degree(num_nodes,target_deg):

    G=nx.Graph()

    G.add_nodes_from(range(num_nodes))
    while avg_deg(G,num_nodes) < target_deg:
        n1, n2 = sample(G.nodes(), 2)
        G.add_edge(n1, n2, weight=1)

    nx.draw(G)
    plt.show()
    return G    


initial_infections = [(u,v) for (u,v) in G if u==int(m/2) and v==int(m/2)]  

t, S, V, I, R = discrete_SIR(G,initial_infecteds= initial_infections,beta=0.8,w=0.05,Vl=0.1)  

plt.figure()
plt.plot(t,I,ls='-',color='red')
plt.plot(t,R,ls='--',color='orange')
plt.plot(t,S,ls='--',color='green')
plt.plot(t,V,ls='-',color='black')
plt.show()

The problem with my code is the total number of S + V+ I+R should be equal to N and the number of vaccinated people is also at max coming to be 5. It should be higher than that.


回答1:


Your problem is that V is only measuring the total number of individuals becoming vaccinated in that time step, rather than the cumulative number of vaccinations.

So S+I+V+R is not constant. If you want V to be the cumulative number of vaccinations, then do V.append(V[-1]+len(vaccinated))

I'm not sure that this test if len(vaccinated)< (Vl*N) is doing what you think as well. It is checking whether the number of people vaccinated in a given time step is less than some fraction of the entire population. I suspect you want to use the cumulative number of vaccinations.



来源:https://stackoverflow.com/questions/56927079/modified-sir-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!