18a sir vs reality

18a sir vs reality

In this video I discuss a number of sir refinements and calibrations to get the model to approximate reality. I also draw some conclusions - see the video and let me know in the comments if you agree!

The fdm simulation is given below. It improves on earlier versions by also discretising the population - the population is divided up into 100m actual units. My plan here was to simulate infections using a poisson binomial but as I also tried to incorporate the spatial interaction I went hardcore and rather programmed it from the ground up. So what you see in the video is somewhat disconnected from fdm.

# Copyright © Ferra Solutions (Pty) Ltd. All rights reserved.

# Lower precision a bit to
# speed up simulations
accuracy( 20 );

# Given a range [ l, h ] and a divisor m
# find the number of integers l, l+1, ..., h
# that are divisible by m
define( "countMultiples", "l", "h", "m",
  {
    m0 = ceil  ( l / m );
    m1 = floor ( h / m );
    m1 - m0 + 1;
  } );

# Weeks per scenario
numT   =   52;

# Starting date
t0     = dateIndex ( 2020, 1, 1 );

# Number of days per interval
td     = 7;

# Assumptions
p0     = 100000000;    # Initial population
i0     = 10;           # Initial infections
inf1   = 50;           # For every inf1 infected
                       # we will have 1 fatality
tIll   = 3;            # Weeks to recover
cRBase = 1;            # Baseline contact rate
numAlt = 100;          # Number of alternative
                       # scenarios

# Parato parameters
pShape = 1.16;         # Arbitrary 80:20
pFast  = 1 / pShape;   # Speed up calculations
                       # Scale based on average
pScale = cRBase * ( pShape - 1 ) / pShape;

# We perform two simulations

# First we do the baseline, then we
# simulate variable contact rate
# scenarios

# So we loop the same code twice
loop = 0;

while( loop < 2, {

  # Variables below

  # tPop - total population
  # tInf - total infected
  # cInf - cumulative infected
  # nInf - newly infected
  # tSuc - total susceptible
  # nRec - newly recovered
  # tRec - total recovered
  # nDec - newly deceased
  # tDec - total deceased

  # Number of scenarios
  numS = if ( loop, numAlt, 1 );

  # Matrices
  # First column is date
  nInfMat  = matrix( numT, 1 + numS );
  tInfMat  = matrix( numT, 1 + numS );
  cInfMat  = matrix( numT, 1 + numS );
  tRecMat  = matrix( numT, 1 + numS );
  tDecMat  = matrix( numT, 1 + numS );
  cRateMat = matrix( numT, 1 + numS );

  # Simulate
  s = 1; # Scenario number

  while ( s <= numS,
  {
    # Initialise for this scenario
    tPop = p0; # Population
    tInf =  0; # Total infected
    cInf =  0; # Cumulative infected
    tRec =  0; # Total recovered
    tDec =  0; # Total deceased
    nRec =  0; # Newly recovered
    nDec =  0; # Newly deceased

    T    = t0; # Date index
    t    =  1; # Time bucket

    while ( t <= numT,
    {
      # Population adjusted
      # for deceased
      tPop = tPop - nDec;

      if( numS > 1,

        # This is not baseline
        # Simulate random contacts
        cR = pScale / ( 1 - randFast () ) ^ pFast,

        # else this is baseline
        cR = cRBase
      );

      # Susceptible population
      tSuc = tPop - tInf - tRec;

      # Newly infected
      if ( t == 1,
        # First time it is our assumption
        nInf = i0,
	# Thereafter it is the rounded number
        nInf = round( cR * tSuc * tInf / tPop ) );

      # Can not exceed susceptible
      if ( nInf > tSuc, nInf = tSuc );

      # Recovered and deceased
      if ( t > tIll,
      # then
      {
        # Newly infected tIll time ago
        nia  = nInfMat[ t - tIll; s + 1 ];

        # Cumulative infected tIll time ago
	cia  = cInfMat[ t - tIll; s + 1 ];

        # Fatality range
	f0   = cia - nia + 1;
	f1   = f0  + nia - 1;

        # Fatalities / newly deceased
	nDec = call( "countMultiples", f0, f1, inf1 );

        # Recovered - infected less fatalities
        nRec = nia - nDec;

      } );

      # Total infected
      tInf = tInf + nInf - nRec - nDec;

      # Cumulative infected
      cInf = cInf + nInf;

      # Total recovered and deceased
      tRec = tRec + nRec;
      tDec = tDec + nDec;

      # Load date column
      if ( s == 1,
      {
        nInfMat [ t; s ] = T;
	tInfMat [ t; s ] = T;
	cInfMat [ t; s ] = T;
        tRecMat [ t; s ] = T;
        tDecMat [ t; s ] = T;
        cRateMat[ t; s ] = T;
      } );

      # Update matrices
      # First column is date
      nInfMat [ t; s + 1 ] = nInf;
      tInfMat [ t; s + 1 ] = tInf;
      cInfMat [ t; s + 1 ] = cInf;
      tRecMat [ t; s + 1 ] = tRec;
      tDecMat [ t; s + 1 ] = tDec;
      cRateMat[ t; s + 1 ] = cR;

      # Move to next time
      T = T + td;
      t = t + 1;
    } ),

    # Move to next scenario
    s = s + 1;

    # Progress
    format( 0 );
    calcStatus( "Scenario " + s + "/" + numS );
  } );

  # Simulation name
  if( numS > 1,
      # then
      name = "Scenarios",
      # else
      name = "Baseline" );

  # Prevent clutter
  scenariosDelete( name );

  # Create scenarios
  scenariosAdd(
    name,
      "New Infections", nInfMat,
      "Total Inf",      tInfMat,
      "Cumulative Inf", cInfMat,
      "Recovered",      tRecMat,
      "Deceased",       tDecMat,
      "Contact Rate",   cRateMat );

  # Print results
  if( loop == 0, {
      format( 2, 30 );
      print( "New infections" );
      print( matrixAsSeries( nInfMat ) );
      print( "Total infections" );
      print( matrixAsSeries( tInfMat ) );
      print( "Cumulative infections" );
      print( matrixAsSeries( cInfMat ) );
      print( "Total recovered" );
      print( matrixAsSeries( tRecMat ) );
      print( "Total deceased" );
      print( matrixAsSeries( tDecMat ) );
  } );

  # Next loop
  loop = loop + 1 } );