Machine Problem 8
Due Mar 29, on line
the homework for CS:2820, Spring 2021
To model contageon for our disease, we need to keep track of where people are. Eventually, people will move from place to place following their schedules. Initially, though, people will stay put in one place. Our model, as of MP7, doesn't put a person in any place.
For people to infect each other, we need a record of which people are in the same place. The probability of a person being infected in any particular place depends on how many people there are infectous (any infection state between asymptomatic and bedridden, inclusive) how long the person spends, and a property of the place we'll call transmissivity. That's a made-up word, but the idea is that a poorly ventilated place where people are packed in will have a high transmissivity, while a well ventilated place where people are spaced out will have a low transmissivity. A supermarket, for example, has a lower transmissivity than a nightclub.
Transmissivity is an attribute of the kind of place. Given
The probabilty of that one person becoming infected from their stay in that place will be:
This holds only for infinitesimal probabilities, because the probability can never be greater than one. So long as all the numbers are small, though, doubling the number of infected people in the place, or doubling the transmissivity, or doubling the duration of stay should each approximately double the likelihood of catching the disease.
How do we make the curve asymptotically approach one instead of being linear in n, t and d? A quick tour through pre-calculus shows that ex is one when x is zero, and the slope is -1 at that point. This with a little work, then, this gives:
For small n, t and d, this behaves just like our original approximation, and it never exceeds 1.
A quick unit analysis shows that transmissivities are measured in units of disease transmissions per infected person present per unit of contact time. This then gives the conversion rules for converting transmissivities per hour into transmissivity per second, for example, just divide by 602.
We can also work the math to determine the expected time until the person gets infected. The expected delay until an infection is simply 1/n t time units, and if the person steps out the door, gets tested to show that they are not yet infected, and then steps right back in, the expected delay is the same. This fact suggests that the delay until infection is characterized by a negative exponential distribution.
Therefore, the time until a person is infected in some place with population n and transmissivity t will be an exponential distribution with mean 1/n t.
If the person leaves before that time, they don't get infected. If people don't move around, we can ignore leaving, but later, note that our scheduling mechanism allows every person's every departure from a place to be scheduled when they arrive, so we always know when they will leave and we can compute whether and when they get infected from this.
This lead us to add transmissivity (in infections per person per hour) as an additional attribute for each kind of place:
place home 3.5 2.5 0.75; place classroom 25 10 1.15;
The next thing we need is a place for each person. What we'll do for this is use the list of places for that person. We had the rule that, for each role, there were a number of places, each with an optional schedule.
Now, we'll break that up a bit. The place with no schedule will be the person's home place, that is, the place where the person starts out and where that person returns to when their schedule allows. For this problem, that place will be the person's only place. Exactly one kind of place per role will be required to have no schedule.
The output should be exactly as it was in machine problem 7, except that now, people who were initially uninfected will begin to get sick if one of the others in their place becomes infectious.
Extend any solution to MP7 so that:
Also in writing your code, think ahead. In future versions:
The usual rules and coding standards apply. Your code should conform reasonably to the Sun/Oracle rules for Java formatting: 4-space indents, appropriate use of comments, 80-character lines, etc. You should check your code for annoying problems with ~dwjones/format. This will identify overlength lines and flag other undesirable problems with your text file such as residual DOS artifacts that come from transferring files between Windows and Linux systems.
As usual, submit using the ~dwjones/submit utility. Your program should be in a single source file called epidemic.java.
A student asked: Is the exponential distribution related to the logistic distribution?
Yes, they are both related and somewhat similar looking, but they are not the same. There is a property of the exponential distribution that is crucial here: If you start at any time and then draw from an exponential distribution to determine the time of any later event e, then, at some later time before e, you cancel e and then redo the drawing of from the same distribution to schedule e', the distributions of expected values of e and e' will be identical!
The exponential distribution is the only probability distribution with this somewhat magical property. This property means that we can stop the simulation at any moment and re-throw the dice from the perspective of that moment to determine when in the future each currently uninfected person will be infected. Doing this has no impact at all on any collective statistical properties of the spread of the disease, although it might change who gets infected when.
A student asked: What are the time units on infections?
Note that we already have multiple time units. Disease stages are input to the simulation in days, while transmissivities are given in units of infections per person per hour. Since the internal time units of the simulator are unlikely to be hours, you need to convert the input transmissivity to use your internal time units. If the internal time unit is one second, multiply by hours per second, which is the same as dividing by seconds per hour. If the internal time unit is one day, multiply by hours per day, which is the same as dividing by days per hour.
A student asked: Consider a home with 3 people with 1 initially infected and latent. When that person becomes asymptomatic, others in the home are exposed. When one of the others is infected and transitions from laten to asymptomatic, does that speed up the time frame for the third person getting infected?
Yes! This is why I have emphasized that you may have to think about cancelling or at least nullifying events.
The expected time until infection is 1/(n t). Note that the transmissivity t is in units of (infections/person)/time which is (infections/person × time). If we want something measured in units of time, we need to invert this.
When nobody in the place is infectious, 1/(n t) is infinite beause n is zero.
When one person in the place is infectious, the expected delay until each other person in the place is infected is 1/t.
If two people in the place is infected, the expected delay until each other person in the place is infected changes to 1/(3 t).
If one person recovers or dies, the expected delay until infection for other people changes back to 1/t.
The special property of the exponential distribution outlined above means that, at the moment that the number of infected people in a place changes, it is entirely proper to ignore any previously scheduled infection invents for the people in the room and re-throw the dice to schedule the times they get infected. If the last infected person in the room just recovered, this re-throw will set the time of infection to infinity for all the people in the room who are not yet infected.
This is an obvious example of simplification of a process that is more complex in the real world. In the real world, people don't recover as an event, recovery is gradual, and during recovery, the rate at which a person sheds virus particles falls gradually. When an infected person leaves the room, some of the virus particles they shed hang around for while, potentially infecting those who enter the room shortly after. Simulations always involve simplification.
A student asked: Do we really have to have events for each change of disease state? Since people are not moving around, is it sufficient to just check at midnight every day to see who got infected during the last day?
You really have to have events for each change of disease state! In the first place, the whole point of all of these assignments is not to merely produce the "right" output, the purpose is to build a foundation on which later more sophisticated simulation models work. Later, people will follow their schedules and move around. Therefore, shortcuts that simplify the problem by producing a solution that cannot work when people move won't be very useful.
Second, suppose we wanted to model some kind of moderately fast disease, where things like latency, asymptomatic, symptomatic and bedridden times were measured in hours, so the disease could go through severeal stages in the period between reports. Can you figure out how to make this work without thinking about each transition between disease stages as a separate event for each person?
A student asked: When people recover, can they be reinfected?
No. We assume that, in the time scale of our model, recovery confers immunity. So, only uninfected people can be infected. This is why recovered is a distinct disease state.
A student asked: If a person in a room becomes contageous, how many times do you have to draw new random numbers?
For each person in the room, you have to decide when they become infected. You can ignore those in the room who are already infected.
You also have to do the same thing when a contageous person in the room dies or recovers.
The history-free property of the negative exponential distribution is critical here. If, for some person, you had previously decided that they'll be infected at 10:03 AM, because there was one other contageous person in the room, it is perfectly OK to throw that out when a second contageous person shows up, and simply throw the dice again based on two sick people being there. The statistics work out OK even if the result is that your person now becomes infected at 11:34 AM. On the average, your person will be infected sooner because to the new throw of the dice, but each throw is an independent experiment, and in some run of the simulation, the new person arriving can delay the time of infection.
You can imagine that the new person sneezing caused the air currents to swirl differently, and your person who would have inhaled an infectious droplet at 10:03 AM doesn't. Yes, there are now more infectous droplets in the air, but by random chance, your person now inhales his first infectious droplet at 11:34 AM, at least on this run of the simulation. On the average, over many runs, your person will get sick sooner, but on this run, your person got lucky.
A student asked: How do we go about cancelling or nullifyig events in favor of new events.
There are many ways of doing this.
One approach is to modify the simulation framework so that schedule returns a handle for the event just scheduled, and then add a new method to the framework called cancel where you pass the handle back and ask for that event to be de-scheduled, or perhaps a reschedule method. This involves modifying the simulation framework, something I'm a bit nervous about because it's already rather tricky code.
The alternative is to have the event-service code check to see if this event should occur. For example, for each person, you could have a variable for "time at which I become infected;" if an "infect me" event comes through at that time, it works, but if the "infect me" event comes through at a different time, it must be an obsolete event. When you schedule a person to become infected at some time, you also set that new variable to that time.
There are an infinite number of alternative solutions, so don't feel limited by the above suggestions.
A student asked: in future MPs we will have people moving around, but now people stay in one place. This means that the number of people in a place will never change. What does change and how does this relate to future problems?
The number of infectious people in each place changes. For this problem, it goes up when a person becomes asymptomatic and contageous, and it goes down when someone recovers or dies. In the future, it will also go up when an infectous person arrives in a place and it will go down when an infectous person leaves a place. What you do when the number changes, however, will remain the same. This problem centers on working out the details of that.
A student asked: Am I right that the only thing that we care about is the time until a person gets infected, which is 1/(n t)?
1/(n t) gives you the expected delay until a person gets infected, but in each case, the actual delay is random. That is, you need to draw a random number from a distribution with this as its mean. The distribution should be a negative exponential distribution!
A student asked: Can you show us some input and the corresponding output?
Here's a test file I've been fooling with, just one infected person out of 100, but it's not very contageous and a latency of 2 days slows the spread. Of course, as soon as multiple people are infected, the remaindere have a higher and higher chance of catching it.
population 100; infected 1; place earth 100 0 .01; place moon 100 0 100; role human 1 earth moon (10-12); end 30; latent 2.0 0; asymptomatic 3 0; symptomatic 5 1 0.9; bedridden 8 2 0.9;
Here's the result of just one run of the model. The epidemic ran its course in 26 days for this run, but in some runs, it finishes in as little as 22 days.
0.0,99,1,0,0,0,0,0 1.0,99,1,0,0,0,0,0 2.0,99,0,1,0,0,0,0 3.0,74,25,1,0,0,0,0 4.0,62,37,1,0,0,0,0 5.0,2,72,25,1,0,0,0 6.0,0,62,37,1,0,0,0 7.0,0,2,97,1,0,0,0 8.0,0,0,74,26,0,0,0 9.0,0,0,62,38,0,0,0 10.0,0,0,2,98,0,0,0 11.0,0,0,0,99,0,1,0 12.0,0,0,0,92,1,7,0 13.0,0,0,0,80,1,19,0 14.0,0,0,0,44,2,54,0 15.0,0,0,0,14,5,81,0 16.0,0,0,0,3,7,90,0 17.0,0,0,0,0,8,92,0 18.0,0,0,0,0,8,92,0 19.0,0,0,0,0,8,92,0 20.0,0,0,0,0,7,93,0 21.0,0,0,0,0,6,94,0 22.0,0,0,0,0,6,94,0 23.0,0,0,0,0,5,95,0 24.0,0,0,0,0,3,96,1 25.0,0,0,0,0,2,97,1 26.0,0,0,0,0,1,98,1 27.0,0,0,0,0,0,99,1 28.0,0,0,0,0,0,99,1 29.0,0,0,0,0,0,99,1