University of Kentucky
3-30-2020
My friends, I have been sitting in front of my computer 7-8 hours per day for more than ten days AT HOME. After strictly practicing social distancing for this long, I can't help wondering whether it will work or not. Can it flatten the curve? How soon can I go back to the campus? How soon will our lives go back normal? I decided to build a model to find it out. Want to do it with me?
I started with a very simple model (Fig.1). You can either download it or make it. This model, made in NetLogo, shows a butterfly wandering on a green lawn (Fig. 1). It is pretty, but has nothing to do with infections, diseases, or outbreaks! So what do I need to change?
* A set of slides are available here in case the figures below are too small for you to follow.
The first thing that popped up in my mind is that I need a lot of people. Not very hard. I can simply ask NetLogo to create a lot of people for me. I went to the “code” tab, create a variable “number-of-person” after the create-turtles command. I also changed the agent shape from “butterfly” to “person”. Then I added a slide in the “interface” tab for the “number-of-person” variable (Fig. 2). For now, I set the min and max bounds of the slider to 50 and 800. Why these numbers? To be honest, I just tried them out and will adjust them as needed. We have to try many things out when building a model, no worries!
Run it. Only one person, seriously?! Of course, I did not set their positions. By default, all agents are placed at the center, silly me! Add the code to randomize people’s positions (Fig. 3). Ha, there we go!
Now I have a group of people, here comes the disease! Hold on, I need to decide what to simulate? The disease? The pathogen causing the disease? Or the infected person? In this case, I want to see how the disease spreads among people and I will mostly be checking on people, so I decided to make an infected person.
To be able to control the presence of the infected person, I added a new procedure in the “Code” tab, named “add-an-infected-person”. Yes, my friends, this is a very long name, but it does not matter. What is important is that two months later I can still recognize what this procedure does. You need to ensure to connect all the words with dashes so that NetLogo thinks of it as one word. Then I added a button in the “Interface” tab to execute the procedure. Now, every time when I pressed the button, an infected person is introduced to the population (Fig. 4). Oh, I forget to tell you, I made the infected person orange color so we can distinguish him/her from the healthy people who are green.
Now run the model again. The orange sick person moves among other people. Will something happen? NO! Nothing will happen! We have not made the disease infectious. Let’s do that. I added another new procedure in the “Code” tab, named “transmission”. In English, the code in the procedure says,
Hi, infected person, are there any healthy people nearby? Within a radius of 1.5. If there is at least one, choose one of them. This person will be infected at the transmission rate.
You can see how healthy people are defined by their color (68). Every time, the infected person passes the disease to only one of the close healthy but unimmunized people at a certain rate. In reality, one infected person may pass the disease to more than one person every time. Let's keep the smallest number for now. You will see it is already bad enough.
Oh, I must add this transmission procedure into the “go” procedure so that it gets run over time (Fig. 5). Run it. Oh, my gosh!
The disease is passing through the population so quickly. I wanted to be able to track the spreading more closely. How long does it take to infect all the people? Does the number of people matter? Does it take longer to infect a larger population? I needed something more accurate to compare. I decided to track the number of infected people using monitors and a plot. This is easy. In the “Interface” tab, I added two monitors to track the number of healthy people and the number of infected people each round. I then added a plot to track these two numbers over time. Oh, just so you know, I must add a command “tick” in the “go” procedure to keep the plot updated (Fig. 6).
After running the model many times, it was clear that the disease spreads faster in a population with more people. It did not seem to take a longer time to infect more people. Why? Was it because it was crowded there? To test it, I set the number of persons as 800 and increased the simulation area four times larger so the population density equals that of a population with 200 persons in the original simulation (Fig.7). Yes, the model showed that it took about the same time to infect all 800 people in the enlarged simulation as to 200 persons in the original simulation. So, it was not just the number of people but the population density that mattered.
If population density matters, social distancing makes sense. Let's limit the movement of people and see what happens. I set the window size back to 16X16. Then went to the “move” procedure, changed the number “1” after the forward command to a variable “mobility”. Then added a slider of "mobility" in the interface tab (Fig. 8). I defined the mobility range from 0.1 to 1. Something interesting happened. Within a really crowed population, limiting mobility does not seem to work because they remain crowded even with low mobility, meaning the people are unable to perform social distancing. It made me think of the people living in highly crowded places-- you can surely name some of them. In the population where people have had some spaces to maintain distancing, the low mobility evidently helps to slow down the spreading in the model.
It all seems to make sense so far, but I still had questions. What will happen after the entire population is infected? Of course, two more things can be added to the model: recovery and mortality. Since they are the two sides of the same coin, I added a new procedure to define both. First, I needed to decide when the infected person recovers or dies. Take the COVID-19, I used the 15 days as the cutoff. I gave a variable "days" to all people. It remains at 0 for healthy people but starts to accumulate for the infected people. To set the variable, I need to go to the very top of the code top, put a code line: turtle-own [days]. Yes, it must be on the very top. I then added a new procedure call "sickness"--it can be placed below other procedures.
The "sickness" procedure says,
Hi, infected person, if you have not been sick for 15 days, stay sick. If you have been sick for 15 days, at a certain rate, you either die or recover to become immunized, indicated by a blue color.
I added this sickness procedure to the “go” procedure, added the mortality rate slider in the interface, and updated the plot to track recovered persons. We are ready to go (Fig. 9).
Ah ha, in a crowded but not super crowded population, I thought I saw a flattened infection curve when people became less mobile (Fig. 10). What do you think? Of course, it cannot happen if only one person practices social distancing and remains less mobile, we all need to do it because the curve emerges from all of us, the agents.
At this point, my friends, I see hope and want to take a coffee break. The completed model can be found here**.Note even quite a few things have been included, this outbreak model is still very simple and basic. It provides a simple representation of the disease spreading dynamics but is quite useful to reveal many general patterns. It can help us think about what social distancing really means. I.e., simply staying stationary does not mean you maintain a proper social distance, keeping 6 feet away is.
"All models are wrong but some are useful (Box, 1987)."
**: Several functions were added to the model to make it more user-friendly, such as a "run a day" button, an adjustable time input, change the background to black color, and the legend notes. The simulation world was also resized to improve the visualization. (3-30-2020)
Related link: A more complicated Infectious Disease Outbreak model