{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Code - Pandemic Flu Spread Using “Green” Simulation Method for Small Sample of Elementary Students " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This paper studies a pandemic flu spread case applying a “green” simulation method, using pseudo-random numbers as presented in the paper by Wilson S., Alabdulkarim A. and Goldsman D. W, [“Green Simulation of Pandemic Disease Propagation”](http://www.math.uwaterloo.ca/~mbfeng/papers/GreenSimWSC.pdf) in a simulation environment build in Python. The scenario is an elementary school with twenty-one kids and the impact of infection when one infected kid enters the system. The findings and answers to the questions are presented at the end of the paper. The paper can be read [here](https://www.carlosaordonez.com/fastpages_3/2020/11/27/Pandemic-Flu-Spread-Using-Green-Simulation-Method-for-Small-Sample-of-Elementary-Students.html)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "#hide\n", "import numpy as np\n", "import pandas as pd\n", "import random\n", "\n", "# probability update function\n", "def pandemic (n, k, p ):\n", "#n number of students, k number of days and p probability\n", "\n", " def p_infected(q, q_t_1):\n", " out= 1 - q **(q_t_1)\n", " #print(out)\n", " return round(out,5)\n", "\n", " # Number of susceptibles \n", " #n = 21\n", " ## Number of days\n", " #k = 30\n", " U = np.random.uniform(0,1,n)\n", " #print(U)\n", " #infected Io =1 \n", " Io=1\n", " #gama rate of infection\n", " gama=1/3\n", " #probability of infection p Bernoulli original at p=0.02 testing with 0.2\n", " #p=0.02\n", " q=1-p\n", " #q=beta/gama\n", " po=1.0-q**Io\n", " po\n", " countPRN=0\n", " # Create a list of days length k\n", " days = np.arange(1,n+1)\n", " probs = np.zeros(n)\n", " probs[0] = p\n", " ## Initial state and PRN\n", " state = np.empty(n, dtype=object)\n", " prn = np.random.uniform(0,1,n)\n", " state[:] = 'S'\n", " # Metadata to count days infected\n", " t_infected = np.zeros(n)\n", " # Generate random Infected'\n", " infected_idx = random.randint(0,n-1)\n", " state[infected_idx] = 'I'\n", " t_infected[infected_idx] = 0\n", " days_sim = list()\n", " days_sim.append(pd.DataFrame(data= {'prn': prn, 'state': state, 't_infected': t_infected}))\n", "\n", " #print(days_sim)\n", "\n", " summary_df = pd.DataFrame(data= {'day':[], 'infected':[], 'susceptible':[],'recovered':[],\n", " 'probability':[], 'count_prn':[] })\n", " last_recovered = pd.DataFrame(data= {'day':[], 'infected':[], 'susceptible':[],'recovered':[],\n", " 'probability':[], 'count_prn':[] })\n", "\n", " for d in range(1,k):\n", " # Get initial data\n", " prn = np.zeros(n)\n", " #prn = np.random.uniform(0,1,m)\n", " prev_df = days_sim[d-1]\n", "\n", " state = prev_df['state'].copy()\n", " t_inf = prev_df['t_infected'].copy()\n", "\n", " # print('================== Day', d, '======================') \n", " # print('p:', p)\n", " # print('Infected:', m)\n", " # print('Susceptible:', s_i)\n", " # print('Removed:', r_i)\n", " # print('m:', m)\n", "\n", " #print(state)\n", " # Simulate current day\n", " for index,rand in enumerate(prn):\n", " # If student is infected, then check how many days he has been infected\n", " # if it's less than 3 then increase the count, else move him to state R\n", " # and leave the count as is (it will no longer be used)\n", "\n", " if state[index] == 'I':\n", " if t_inf[index] < 3:\n", " t_inf[index] = t_inf[index] + 1\n", " else:\n", " state[index] = 'R'\n", "\n", " # Else if the student is still sucseptible \n", " elif state[index] =='S':\n", " countPRN=countPRN+1\n", " prn[index] = random.uniform(0,1)\n", " if prn[index] < p:\n", " state[index] = 'I'\n", " t_inf[index] = 1\n", " \n", " #updating p\n", " #print('prn:', prn)\n", " #print('state:', list(state))\n", " m = len(state[state == 'I'])\n", " p = p_infected(q, m)\n", " s_i = len(state[state == 'S'])\n", " r_i = len(state[state == 'R'])\n", " metrics = {'day': int(d),'infected':int(m), 'susceptible':int(s_i),'recovered':int(r_i), 'probability':p, 'count_prn':countPRN } \n", " # metrics = {'day': [d],'infected':[m], 'susceptible':[s_i],'recovered':[r_i], 'probability':[p], 'prn':[countPRN] } \n", " summary_df = summary_df.append(metrics, ignore_index = True)\n", " #print(summary_df)\n", " if r_i == n:\n", " print (f'All {r_i} removed: in day {d}')\n", " break\n", "\n", " # print('================== Day', d, '======================') \n", " # print('p:', p)\n", " # print('Infected:', m)\n", " # print('Susceptible:', s_i)\n", " # print('Removed:', r_i)\n", " #print(pd.DataFrame(data= {'prn': prn, 'state': state, 't_infected': t_inf}))\n", " days_sim.append(pd.DataFrame(data= {'prn': prn, 'state': state, 't_infected': t_inf})) \n", " #print(summary_df)\n", " last_recovered= last_recovered.append(metrics, ignore_index = True)\n", " return summary_df, last_recovered\n", " #return metrics\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Modeling\n", "This section creates the replications. The input here are: The number of kids, the number of days and the probability of infection" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# This code creates the replications\n", "replications=100\n", "kids=21\n", "days=30\n", "p=0.02\n", "#initializes the data frame of replications\n", "summary_df_replications = pd.DataFrame(data= {'day':[], 'infected':[], 'susceptible':[],'recovered':[],\n", " 'probability':[], 'count_prn':[] })\n", "#initializes the list of last recovered which I will be saving in a data frame for every iteration\n", "summary_last_recovered=summary_df_replications\n", "\n", "mean_per_day =pd.DataFrame(data= {'day':[], 'infected':[], 'susceptible':[],'recovered':[],\n", " 'probability':[], 'count_prn':[] })\n", "\n", "#runs every iteration\n", "for i in range (0, replications):\n", " metrics_result, info_last_recovered = pandemic (kids, days+1, p )\n", " #n number of students, k number of days and p probability\n", " #in this case 21 students with a lenght of 365 days and probability of 0.02\n", " \n", " #creates a single data frame for all replications\n", " summary_df_replications=pd.concat([summary_df_replications, pd.DataFrame(data=metrics_result)])\n", " #creates a single data frame for all replications last recovered\n", " summary_last_recovered=pd.concat([summary_last_recovered, pd.DataFrame(data=info_last_recovered)])\n", " " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "#calcuates the day that there is are no longer infections\n", "def getDayNoInfection(df, infected='infected'):\n", " counter = 0\n", " index = 0\n", " #print(df.head())\n", " for index,d in df.iterrows(): \n", " if d[infected] == 0:\n", " counter = counter + 1\n", " if counter == 0:\n", " index = d['day']\n", " if counter >= 3:\n", " break\n", " return index-1\n", "def getDaysOfNoInfectionsMean(df):\n", " days_change = []\n", " for i in range(replications):\n", " day = getDayNoInfection(df[i*60: i*60 + 60])\n", " days_change.append(day)\n", " out= sum(days_change)/len(days_change)\n", " #print(out)\n", " return (out, days_change)\n", " \n", "last_infected= getDaysOfNoInfectionsMean(summary_df_replications)\n", " #print(counter) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Results" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Table of Replications\n" ] }, { "data": { "text/html": [ "
\n", " | day | \n", "infected | \n", "susceptible | \n", "recovered | \n", "probability | \n", "count_prn | \n", "
---|---|---|---|---|---|---|
0 | \n", "1.0 | \n", "1.0 | \n", "20.0 | \n", "0.0 | \n", "0.02 | \n", "20.0 | \n", "
1 | \n", "2.0 | \n", "1.0 | \n", "20.0 | \n", "0.0 | \n", "0.02 | \n", "40.0 | \n", "
2 | \n", "3.0 | \n", "1.0 | \n", "20.0 | \n", "0.0 | \n", "0.02 | \n", "60.0 | \n", "
3 | \n", "4.0 | \n", "0.0 | \n", "20.0 | \n", "1.0 | \n", "0.00 | \n", "80.0 | \n", "
4 | \n", "5.0 | \n", "0.0 | \n", "20.0 | \n", "1.0 | \n", "0.00 | \n", "100.0 | \n", "
... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
25 | \n", "26.0 | \n", "0.0 | \n", "14.0 | \n", "7.0 | \n", "0.00 | \n", "393.0 | \n", "
26 | \n", "27.0 | \n", "0.0 | \n", "14.0 | \n", "7.0 | \n", "0.00 | \n", "407.0 | \n", "
27 | \n", "28.0 | \n", "0.0 | \n", "14.0 | \n", "7.0 | \n", "0.00 | \n", "421.0 | \n", "
28 | \n", "29.0 | \n", "0.0 | \n", "14.0 | \n", "7.0 | \n", "0.00 | \n", "435.0 | \n", "
29 | \n", "30.0 | \n", "0.0 | \n", "14.0 | \n", "7.0 | \n", "0.00 | \n", "449.0 | \n", "
3000 rows × 6 columns
\n", "\n", " | day | \n", "infected | \n", "susceptible | \n", "recovered | \n", "probability | \n", "count_prn | \n", "
---|---|---|---|---|---|---|
0 | \n", "30.0 | \n", "0.0 | \n", "20.0 | \n", "1.0 | \n", "0.0 | \n", "600.0 | \n", "
0 | \n", "30.0 | \n", "0.0 | \n", "17.0 | \n", "4.0 | \n", "0.0 | \n", "520.0 | \n", "
0 | \n", "30.0 | \n", "0.0 | \n", "6.0 | \n", "15.0 | \n", "0.0 | \n", "318.0 | \n", "
0 | \n", "30.0 | \n", "0.0 | \n", "7.0 | \n", "14.0 | \n", "0.0 | \n", "329.0 | \n", "
0 | \n", "30.0 | \n", "0.0 | \n", "13.0 | \n", "8.0 | \n", "0.0 | \n", "446.0 | \n", "
... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
0 | \n", "30.0 | \n", "0.0 | \n", "20.0 | \n", "1.0 | \n", "0.0 | \n", "600.0 | \n", "
0 | \n", "30.0 | \n", "0.0 | \n", "16.0 | \n", "5.0 | \n", "0.0 | \n", "492.0 | \n", "
0 | \n", "30.0 | \n", "0.0 | \n", "15.0 | \n", "6.0 | \n", "0.0 | \n", "472.0 | \n", "
0 | \n", "30.0 | \n", "0.0 | \n", "6.0 | \n", "15.0 | \n", "0.0 | \n", "303.0 | \n", "
0 | \n", "30.0 | \n", "0.0 | \n", "14.0 | \n", "7.0 | \n", "0.0 | \n", "449.0 | \n", "
100 rows × 6 columns
\n", "