--- A Susceptible-Infectious-Recovered (SIR) Model to study epidemics. -- @arg data.susceptible The initial susceptible population. The default value is 9998. -- @arg data.infected The initial indected population. The default value is 2. -- @arg data.recovered The initial recovered population. The default value is 0. -- @arg data.duration The duration of the disease in days. The default value is 2. -- @arg data.contacts The number of contacts each infected has each time step. The default value is 6. -- @arg data.finalTime The final simulation time, in days. The default value is 30. -- @arg data.probability The probability of a susceptible person getting infected after -- a contact with an infected one. The default value is 0.25. -- @arg data.maximum A threshold of infected people that activates a public policy. The -- policy asks people to start leaving their houses, which cuts the contacts -- between people by half. -- @image sir.bmp -- @output maxInfected The maximum number of infected individuals along the simulation. -- @output finalInfected A table with number of infected individuals in each simulation step. SIR = Model{ susceptible = 9998, infected = 2, recovered = 0, duration = 2, finalTime = 30, contacts = 6, maximum = math.huge, probability = 0.25, init = function(model) model.chart = Chart{ target = model, select = {"susceptible", "infected", "recovered"}, color = {"green", "red", "blue"} } model.maxInfected = model.infected model.finalInfected = {model.infected} model.timer = Timer{ Event{action = function() local proportion = model.susceptible / (model.susceptible + model.infected + model.recovered) local newInfected = model.infected * model.contacts * model.probability * proportion local newRecovered = model.infected / model.duration model.susceptible = model.susceptible - newInfected model.recovered = model.recovered + newRecovered model.infected = model.infected + newInfected - newRecovered if model.maxInfected < model.infected then model.maxInfected = model.infected end table.insert(model.finalInfected, model.infected) end}, Event{action = function() if model.infected >= model.maximum then model.contacts = model.contacts / 2 return false end end}, Event{action = model.chart} } end }