[PYTHON] Let's simulate the effect of introducing a contact tracking app as a countermeasure against the new coronavirus

Introduction

Measures to prevent the spread of the new coronavirus infection (COVID-19) include urban blockade, self-restraint of behavior and sales, RT-PCR inspection and cluster measures, contact tracking app, infected person behavior monitoring app, etc. It is being tackled in various countries. Until now, Japan has focused on PCR testing, tracking by cluster countermeasures teams, and self-restraint in actions and sales by declaring an emergency, but as of May 6, 2020, in China, Italy, Iran, the United States, etc. It has not led to the explosive spread of infection seen. However, continuing to refrain from behavior and business as it is has harmful effects on various aspects such as economy, education, and culture, and we are at the stage of searching for an exit strategy. Vaccines are being actively developed, but considering the confirmation of safety and efficacy and the establishment of a production system, it is expected that a period of at least one year will be required at the earliest. More efficient quarantine measures for infected people are needed to prevent the collapse of medical care and gradually lift restrictions on behavior and sales. As an important item, I would like to verify the ** effect of introducing the contact tracking app ** by simulation.

Situation around the world

First, let's take a look at the current medical status of COVID-19 around the world. In the figure below, in countries with 10,000 or more infected people, the horizontal axis is the recovery rate (number of recoverers / number of people requiring treatment), and the vertical axis is the mortality rate (number of deaths / number of people requiring treatment). It is a graph. See this article for the calculation method. CRD_COVID-19_Map_WLD.png

Japan is in a position with a recovery rate of 1.5% and a mortality rate of around 0.25%. In terms of recovery rate, it is equivalent to France, Belgium and Singapore, and in terms of mortality rate, it is equivalent to Germany, Austria, Pakistan and Belarus. Among them, corona tracking apps such as China, Israel, Singapore, and South Korea are said to have been successful, but with the exception of China, which is considered to be the source of infection and the initial response was delayed, Israel, Singapore, and South Korea have certainly died. The rate is low. More than 10 types of corona tracking apps have already been developed around the world. (Reference: Top 10 popular smartphone apps to track Covid-19) It seems that Japan is also developing an application using the API jointly developed by Apple and Google. (Reference: About the development of contact tracing apps). Apple and Google require the approval of national authorities to register the Corona Tracking app in the store, so I don't think there will be multiple apps in a mess. (Reference: How do the corona countermeasure apps in each country implement privacy measures?)

Calculation assumptions

By the way, the corona tracking app that is being introduced in this way has the expected effect.

  1. ** Effect of quickly detecting close contacts and promptly promoting examination, isolation, and treatment (especially asymptomatic infected persons) **
  2. Reduction of cases where "infection route is unknown" during interview survey
  3. Early detection of clusters
  4. As a passport to prevent infected people from entering high-risk areas
  5. In addition, accumulation of epidemiologically useful knowledge, etc.

Various effects are expected, but this time I would like to focus on 1 and evaluate the effects quantitatively.

At that time, the Cluster-based SEIR model shown in the previous article is used as the calculation model. The main reasons for using this model are:

In particular, in the normal SEIR model, when the basic reproduction number is $ R_0 = 2.5 , it is said that the peak out occurs in about 60% of the population ( 1-1 / 2.5 = 0.6 $). (Acquisition of herd immunity) Even if you look at the countries where the number of infected people per million is high, it is 5,000 to 6,000 (/ 1 million) in Qatar and Spain, so the infection rate is at most 0.6% ** Is estimated to be. ** Only 0.01% in Japan. ** Therefore, it seems reasonable at this point to think that the observed peak-out phenomenon of COVID-19 cannot be explained by a simple SEIR model.

Computational model

The calculation formula is shown. First, introduce the variables.

Introduce the following as parameters.

The following is a cluster-based SEIR model that incorporates the isolation effect of the app.

\begin{eqnarray}
\frac{dRp}{dt} &=& - \frac{ln2}{T_h}Rp \\
\frac{dS}{dt} &=& -\frac{1}{ip} Rp \cdot I \\
\frac{dE}{dt} &=& -\frac{dS}{dt} - \frac{1}{lp} E - \alpha E\\
\frac{dI}{dt} &=& \frac{1}{lp} E - \frac{1}{ip} I - \alpha I\\
\frac{dR_1}{dt} &=& \frac{1}{ip} I \\
\frac{dR_2}{dt} &=& \alpha E + \alpha I \\
\frac{dR}{dt} &=& \frac{dR_1}{dt} +\frac{dR_2}{dt} 
\end{eqnarray}

By the way, the following equation holds.

\frac{d}{dt}(S+E+I+R_1+R_2)=\frac{d}{dt}(S+E+I+R)=0

The point is that the app effect isolates you from E and I at a constant rate.

Calculation result

This time, I would like to show the results first. The initial value of the effective reproduction number is $ R_p (0) = 10 $. Also, let the initial state be $ (E, I, R) = (0,1,0) $.

When the application isolation rate α = 0

There is no quarantine by the app. Eventually 113 people will be infected. m8_1_Rp0_10_Al_0.0.jpg

When the application isolation rate α = 0.1

When the quarantine rate by the app is 10 [% / day]. In other words, assume that 10% of infected people are quarantined per day. Eventually 26 people will be infected (R1 + R2). The number of infected people has decreased by 77%. m8_1_Rp0_10_Al_0.1.jpg

When the app quarantine rate α = 0.2

When the quarantine rate by the app is 20 [% / day]. Eventually 11 people will be infected (R1 + R2). ** The number of infected people has decreased by 90%. ** ** m8_1_Rp0_10_Al_0.2.jpg

Relationship between app quarantine rate α and final number of infected people

Let's graph the relationship between the quarantine rate by the app $ \ alpha $ and the final number of infected people $ R (T_ {max}), R_1 (T_ {max}), R_2 (T_ {max}) $. At around ** $ \ alpha = 0.07 $ or more, app quarantines outnumber non-app quarantines **. m8_2_Rp0_10.jpg

Consideration

From the above, the following trends can be derived from the simulation regarding the effect of early isolation by the corona tracking app based on the cluster-based SEIR model.

Furthermore ...

Reference link

I referred to the following page.

  1. Top 10 popular smartphone apps to track Covid-19
  2. Development of contact tracing app
  3. How are the corona countermeasure apps in each country implementing privacy measures?
  4. Let's test the medical collapse hypothesis of the new coronavirus
  5. Explanation of the difference in the spread of the new coronavirus between Japan and other countries using a cluster countermeasure model

Python code

Finally, I'll paste the Python code used in this article.

import numpy as np
import matplotlib.pyplot as plt

# ODE solver
def my_odeint(deq, ini_state, tseq, keys):
    sim = None
    v = np.array(ini_state).astype(np.float64)
    dt = (tseq[1] - tseq[0])*1.0
    for t in tseq:
        dv = deq(v,t, keys)
        v = v + np.array(dv) * dt
        if sim is None:
            sim = v
        else:
            sim = np.vstack((sim, v))
    return sim

#define differencial equation of seir model
def seir_eq8(v, t, keys):
    Th = keys['Th']
    lp = keys['lp']
    ip = keys['ip']
    al = keys['al']
    #
    Rp  = v[0];
    s   = v[1];
    e   = v[2];
    i   = v[3];
    r1  = v[4];
    r2  = v[5];
    r   = v[6];
    #
    dRp  = - np.log(2)/Th * Rp
    ds   = - Rp/ip * i
    de   = - ds     - (1/lp) * e - al * e
    di   = (1/lp)*e - (1/ip) * i - al * i
    dr1  = (1/ip)*i
    dr2  = al * e + al * i
    dr   = dr1 + dr2
    return [dRp, ds, de, di, dr1, dr2, dr]

# simulation 1
def calcsim(Rp0, keys):
    # solve seir model
    #          Rp  S  E  I  R1 R2  R
    ini_state=[Rp0, 0, 0, 1, 0, 0, 0]
    t_max=180
    dt=0.01
    t=np.arange(0,t_max,dt)
    #
    sim = my_odeint(seir_eq8, ini_state, t, keys)
    #
    plt.rcParams["font.size"] = 12
    fig, ax = plt.subplots(figsize=(10,5))
    ax.plot(t,sim[:,[2,3,4,5]]) # extract E I R1 R2
    ax.set_xticks(np.linspace(0,t_max,19))
    yw = 10; yn = int(120/yw)+1
    ax.set_yticks(np.linspace(0,yw*(yn-1), yn))
    ax.grid(which='both')
    ax.legend([ 'Exposed', 'Infected','Recoverd1(normal)', 'Recoverd2(App-based)'])
    ax.set_xlabel('date')
    ax.set_ylim(0,)
    plt.show()
    print("R(tmax):{}".format(sim[-1,6]))

# do simulation 1
keys = {'lp':5, 'ip':8, 'Th':7.5, 'al':0.0 }
calcsim(10, keys)
keys = {'lp':5, 'ip':8, 'Th':7.5, 'al':0.1 }
calcsim(10, keys)
keys = {'lp':5, 'ip':8, 'Th':7.5, 'al':0.2 }
calcsim(10, keys)


# simulation 2
def calcAltoRfin(Rp0):
    #          Rp  S  E  I  R1 R2  R
    ini_state=[Rp0, 0, 0, 1, 0, 0, 0]
    t_max=180
    dt=0.01
    t=np.arange(0,t_max,dt)
    #
    lp = 5
    ip = 8
    keys = {'lp':lp, 'ip':ip, 'Th':7.5, 'al':(0.) }
    #
    mklist = lambda e, l : np.append(np.array(e),l)
    #
    rslt = []
    for i in np.linspace(0,0.4,20):
        keys['al'] = i
        sim = my_odeint(seir_eq8, ini_state, t, keys)
        r = mklist(keys['al'], sim[-1][4:])  # (i, R(tmax), R1(tmax), R2(tmax))
        rslt.append(r)
    #
    rslt = np.array(rslt)
    ymax = max(rslt[:,2])
    plt.rcParams["font.size"] = 12
    fig, ax = plt.subplots(figsize=(10,5))
    #
    ax.plot( rslt[:,0], rslt[:,3], 'b')
    ax.plot( rslt[:,0], rslt[:,1], 'g')
    ax.plot( rslt[:,0], rslt[:,2], 'r')
    ax.legend([ 'R(Total infected)', 'R1(normal purge)', 'R2(App-based purge)'], loc='upper right')
    ax.grid(which='both')
    ax.set_xlabel('application-based purge rate [/day]')
    ax.set_ylabel('total infected cases at tmax')
    yw = 10; yn = int(120/yw)+1
    ax.set_yticks(np.linspace(0,yw*(yn-1), yn))
    #
    for tat in [0,0.1,0.2,0.3,0.4]:
        idx = [i for i in range(len(rslt[:,0])) if rslt[i,0] >= tat][0]
        print("R_fin with Al:{} is {}".format(rslt[idx,0], rslt[idx,3]))
    #
    ax.set_xlim(0,)
    ax.set_ylim(0,)
    plt.show()

# do simulation 2
calcAltoRfin(10)

Recommended Posts

Let's simulate the effect of introducing a contact tracking app as a countermeasure against the new coronavirus
Verify the effect of leave as a countermeasure against the new coronavirus with the SEIR model
Scraping the number of downloads and positive registrations of the new coronavirus contact confirmation app
Let's test the medical collapse hypothesis of the new coronavirus
Let's put out a ranking of the number of effective reproductions of the new coronavirus by prefecture
Plot the spread of the new coronavirus
The story of the student who developed the new coronavirus countermeasure site (Ishikawa version)
Let's calculate the transition of the basic reproduction number of the new coronavirus by prefecture
Estimate the peak infectivity of the new coronavirus
Let's explain the difference in how the new coronavirus spreads between Japan and other countries with a cluster countermeasure model
Factfulness of the new coronavirus seen in Splunk
GUI simulation of the new coronavirus (SEIR model)
Let's examine the convergence time from the global trend of the effective reproduction number of the new coronavirus