! Pandemic/Epidemiology model in LINGO. (Pandemic.lng)
! Model the effect that the number of new infections in a population
segment depend upon the infection fraction in other population segments.
The possible states are: susceptible, infected, recovered, deceased;
! Keywords: Bass model, Chain reaction, Contagion, COVID-19, Diffusion,
Epidemic, Multi-period, Pandemic, SIR model;
SETS:
segment: susceptbl0, infected0, recoverd0, decsd0,
recrate, dratei, drate, spnrate;
sxs( segment, segment) : prifct;
period: totalinf, tindex;
pxs( period, segment) : susceptbl, infected, recoverd, decsd;
ENDSETS DATA:
! Note, you get essentially the Bass model if either:
there is only 1 segment, or they are all identical, i.e.,
spnrate( i) = spnrate( j) for all i and j, the spontaneous,
infection rate,
dratei = drate = 0, i.e., no one leaves a population by death,
prifct( i, j) = prifct( i1, j1) for all i, j, i1, j1, and
recrate = 0 for all populations,
i.e, once in infected state you stay there,;
period = 1..500;
! 0-5 6-18 19-30 31-60 a61-above ;
segment = age05 age18 age30 age60 age99;
! Initial population;
susceptbl0= 100 200 200 250 50;
! Initial infections;
infected0= 0 0 1 0 0;
! Initial population of people that have recovered;
recoverd0= 0 0 0 0 0;
! Initial population of number deceased;
decsd0 = 0 0 0 0 0;
! Recovery rate/period for infected;
recrate = 0.04 0.07 0.07 0.07 0.05;
! Death rate for infected. Lower for young;
dratei = 0.0001 0.001 0.001 0.001 0.01;
! Death rate for not infected;
drate = 0.0001 0.0001 0.0001 0.0001 0.0001;
! Spontaneous infection rate;
spnrate = 0 0 0 0 0;
! Infection probability matrix.
prifct( i, j) = Prob( susceptbl person j gets infected in a period by infected person in group i
if every person in i is infected.
Expect that infection rate within a segment > rate between segments;
prifct =
0.05 0.002 0.002 0.002 0.002
0.002 0.05 0.002 0.002 0.002
0.001 0.03 0.04 0.03 0.002
0.002 0.002 0.003 0.05 0.003
0.002 0.002 0.002 0.002 0.03 ;
ENDDATA
CALC:
! Initialization;
@FOR( segment( s):
susceptbl( 1, s) = susceptbl0;
infected( 1, s) = infected0;
recoverd( 1, s) = recoverd0;
decsd( 1, s) = decsd0;
);
! Compute state in t+1 from state in t;
@FOR( period( t) | t #lt# @SIZE( period) :
@FOR( segment( s):
! Compute new infections. It is proportional to
number susceptible and number of infections. Probability of infection
from group i depends upon what fraction of group i is infected.
Prob( infection) = 1 - Prob( not getting infected).
prnot = Prob( not getting infected) =
Pr(not infected by Grp1)*Pr(not infected by Grp2) ...
Prob( infected by i) = prifct(i,s)*(fraction of i infected);
prnot = 1;
@FOR( segment( i):
! Prob( s not infected by any of segment 1, 2, ...).
This is similar to the Bass Marketing diffusion model;
prnot = prnot*( 1 - prifct(i, s)*infected( t, i)/
( susceptbl( t, i) + infected( t, i) + recoverd( t, i) + decsd( t, i));
);
);
! Compute new still susceptible;
susceptbl( t+1, s) = susceptbl( t, s)
- drate( s) * susceptbl( t, s) ! Deaths;
- spnrate( s) * susceptbl( t, s) ! Spontaneous infections;
- ( 1- prnot) * susceptbl( t, s) ;! Infections by infected;
! Compute new infected;
infected( t+1, s) = infected( t, s)
- dratei( s) * infected( t, s) ! Deaths of infected;
- recrate( s) * infected( t, s) ! Recoveries;
+ spnrate( s) * susceptbl( t, s) ! Spontaneous infections;
+ ( 1- prnot) * susceptbl( t, s);! Infections by infected;
! Compute new recovered;
recoverd( t+1, s) = recoverd( t, s)
+ recrate( s) * infected( t, s) ! Recoveries;
- drate( s) * recoverd( t, s); ! Deaths of recovered;
! Compute new deceased;
decsd( t+1, s) = decsd( t, s)
+ drate( s) * susceptbl( t, s) ! Deaths of susceptbl;
+ dratei( s) * infected( t, s) ! Deaths of infected;
+ drate( s) * recoverd( t, s); ! Deaths of recovered;
);
);
! Display a little report;
@FOR( period( t):
total = 0;
@WRITE( @FORMAT( t, '4.0f'),') ');
@FOR( segment( s):
total = total + infected( t, s);
@WRITE( @FORMAT( infected( t, s), '10.1f'));
);
@WRITE(' Total= ', @FORMAT( total, '10.1f'), @NEWLINE( 1));
totalinf( t) = total;
tindex( t) = t; ! Give ourselves a x/time index;
);
! Generate some charts of number infected over time;
@CHARTCURVE( 'Number infected vs. Time, All Segments', 'Time', 'Current Infections', '', tindex, totalinf);
@FOR( segment( s):
@FOR( period( t): totalinf(t) = infected( t, s));
@CHARTCURVE( 'Number infected in segment '+segment(s)+' vs. Time', 'Time', 'Current Infections in Segment ', '', tindex, totalinf);
);
ENDCALC
|