This is a Jupyter Notebook. It is an interactive document that contains both rich text elements such as figures, links, equations, etc. and executable code (in this case Python code) contained in cells. Instructions:* You can execute the blocks of code one at the time by placing the mouse in the grey box and pressing shift + enter. An asterisk will appear in the brackets at the top left of the box while the code is being exectued (this may take few seconds) and turns into a number when the execution is over. Alternatively,you can run the whole notebook in a single step by clicking on the menu Cell -> Run All.*
Mathematical models are often used to inform decision-makers dealing with complex management problems. The model is used to predict the consequences of alternative actions, hence providing a quantitative assessment of their benefits and costs, possibly under different uncertain scenarios. In this context, Global Sensitivity Analysis (GSA) can be used to investigate the space of possible actions in a more comprehensive and structured way, including a range of actions possibly larger than the few ones that decision-makers would test in a traditional 'what-if?' analysis. GSA can also help quantifying the importance of these actions relative to other factors that influence the system response, but that are not controllable and potentially highly uncertain (Ref. 1).
In this Notebook we will use a flu model, which provides a simple mathematical description of the spread of an infectious deasease, such as flu, within a population. The model divides the population into three "compartments":
Vulnerable: individuals who are vulnerable but not yet infected with the flu;
Sick: individuals who are infected with the flu;
Immune: individuals have immunity to the flu. This includes individuals who either have recovered from the flu or have been vaccinated.
The model describes the change in the number of individuals in each compartment over time, using five parameters:
Let's imagine the following problem. In a city with a population of 100,000 people, we would like to simulate and compare three possible actions to be taken during the flu season:
We don't know how many people are already vaccinated at the start of the flu season, but we have estimated that this number should range between 0 and 50,000 people (half of the population). The recovery time is also uncertain, but it is estimated to vary between 7 and 21 days.
The objective is to keep the sick population below 40% (40,000 people) at any time, because above this number the healthcare system is overwhelmed. The total available budget to achieve this goal is £300,000.
Now use the model to determine a robust combination of actions that maintain the sick population below 40,000 at all time for a total cost within the available budget of £300,000. Here, robust means that the combination should maintain the sick population below 40,000 under as many scenarios of Initial number of vaccinated individuals and Recovery time as possible.
from ipywidgets import widgets
from util.flu.flu_interactive import flu_interactive
immune_ini,contact_rate,contagion_rate,recovery_time,vaccination_rate,fig1 = flu_interactive()
widgets.VBox([widgets.VBox([immune_ini,recovery_time],
layout=dict(border='solid 1px',width = '750px',height = '80px')),
widgets.VBox([contact_rate,contagion_rate,vaccination_rate],
layout=dict(border='solid 1px', width = '750px',height = '110px')),
fig1])
VBox(children=(VBox(children=(IntSlider(value=0, description='Initial number of vaccinated individuals: ', lay…
We can see that it is difficult to find a combination of parameters that achieve the set objectives by varying the parameter values one at the time. In order to facilitate this search we can apply Global Sensitivity Analysis (GSA).
Here we use one particular GSA method, PAWN (Ref. 2). It provides a sensitivity index for each model parameter and each output of interest - in our case: the maximum number of individuals who are sick at the same time during the flu season, called outbreak peak; and the total cost of actions. The sensitivity index measures the relative importance of that parameter on that output: the lower the index, the smaller the influence. The method also provides a threshold value (Ref. 3): if the index of a parameter is above the threshold, then the parameter definitely has an effect on that output, whereas if the index is below the threshold the effect could be negligible.
First, run the cell below to obtain the sensitivity indices of the outbreak peak. They tell us which parameters have the most influence in attenuating the peak of the sick individuals curve, and hence which actions are more effective (regardless of their cost).
We observe that, among the 3 parameters connected to our possible actions, the Contact rate per day has the highest sensitivity index. Hence, reducing the contact rate by social distancing measure is potentially the most effective action. Among all parameters, we observe that the Recovery time has quite low sensitivity. This means that the uncertainty around the recovery time should have limited influence on the population dynamics and the efficacy of the possible actions, and hence we may neglect the uncertainty in this variable when assessing the robustness of our solutions.
Now run the cell below to obtain the sensitivity indices of the total cost.
We observe that Contact rate per day has a disproportionally high sensitivity index, which means that acting on it is likely to be very costly. In this sense, acting on the Vaccination rate and Contagion ratio may be more interesting given that their effects on the total costs are much lower.
Now taking into account what learnt so far through the GSA, can you find a combination of two actions only that flattens the Sick curve so that the peak stays below 40,000 individuals (blue dashed line) with a cost lower than £300,000?
immune_ini,contact_rate,contagion_rate,recovery_time,vaccination_rate,fig4 = flu_interactive()
widgets.VBox([widgets.VBox([immune_ini,recovery_time],
layout=dict(border='solid 1px',width = '750px',height = '80px')),
widgets.VBox([contact_rate,contagion_rate,vaccination_rate],
layout=dict(border='solid 1px', width = '750px',height = '110px')),
fig4])
VBox(children=(VBox(children=(IntSlider(value=0, description='Initial number of vaccinated individuals: ', lay…