How to specify policies

In SID we can implement nearly any type of policy as a modification of the contact models. However, to keep things separable and modular, policies can also specified outside the contact models in a seperate, specialized contact_policies dictionary.

Here we showcase some abilities of contact_policies, building from easier to more involved policies.

Let’s assume that we have three contact models, school, work and other and want to implement a lockdown from the 22nd of March to the 20th of April.

Let’s start with defining our contact_model functions and then define our contact_models.

[1]:
import functools

import numpy as np
import pandas as pd

import sid
[2]:
def attends_school(states, params, seed):
    """All children with a school class go to school"""
    date = sid.get_date(states)
    day = date.day_name()
    if day in ["Saturday", "Sunday"]:
        return pd.Series(data=0, index=states.index)
    else:
        return states["school_class_id"] > 0


def work_contacts(states, params, seed):
    """On weekdays every worker meets between 0 and 10 people."""
    contacts = pd.Series(data=0, index=states.index)
    date = sid.get_date(states)
    day = date.day_name()
    if day in ["Saturday", "Sunday"]:
        return contacts
    else:
        workers = states[states["occupation"] == "working"].index
        contacts[workers] = np.random.randint(low=0, high=10, size=len(workers))
        return contacts


def n_strangers_to_meet(states, params, seed):
    """Every day everyone meets two strangers."""
    return pd.Series(2, index=states.index)
[3]:
contact_models = {
    "school": {
        "is_recurrent": True,
        "model": attends_school,
        "assort_by": ["school_class_id"],
    },
    "work": {
        "is_recurrent": False,
        "model": work_contacts,
    },
    "other": {
        "is_recurrent": False,
        "model": n_strangers_to_meet,
    },
}

To implement the most basic lockdown, let’s close schools and businesses.

[4]:
def shut_down_model(states, contacts, seed):
    """Set all contacts to zero independent of incoming contacts."""
    return pd.Series(0, index=states.index)


basic_lockdown = {
    "basic_lockdown_school": {
        "affected_contact_model": "school",
        "policy": shut_down_model,
        "start": "2020-03-22",
        "end": "2020-04-20",
    },
    "basic_lockdown_work": {
        "affected_contact_model": "work",
        "policy": shut_down_model,
        "start": "2020-03-22",
        "end": "2020-04-20",
    },
}

Let’s say our states identify people working in systemically relevant occupations (grocery stores, hospitals …) and we want to implement that they continue to work. We can do this by providing a policy function as the following:

[5]:
def only_systemically_relevant_workers_work(states, contacts, seed):
    essential = states["systemically_relevant"]
    return contacts.where(essential, 0)


lockdown_for_non_essential_workers = {
    "basic_lockdown_school": {
        "affected_contact_model": "school",
        "policy": shut_down_model,
        "start": "2020-03-22",
        "end": "2020-04-20",
    },
    "only_essentials_work": {
        "affected_contact_model": "work",
        "policy": only_systemically_relevant_workers_work,
        "start": "2020-03-22",
        "end": "2020-04-20",
    },
}

In addition, we might place a state wide shelter in place order if the incidence surpasses 100 cases per 100 000 inhabitants. In that case we want to reduce the other contact model to have no one meet anyone.

One way to specify this:

[6]:
def shutdown_if_incidence_above_threshold(states, params, seed, threshold):
    is_incidence_above_threshold = states["knows_infectious"].mean() > threshold
    return pd.Series(int(not is_incidence_above_threshold), index=states.index)


lockdown_with_shelter_in_place = {
    "basic_lockdown_school": {
        "affected_contact_model": "school",
        "policy": shut_down_model,
        "start": "2020-03-22",
        "end": "2020-04-20",
    },
    "only_essentials_work": {
        "affected_contact_model": "work",
        "policy": only_systemically_relevant_workers_work,
        "start": "2020-03-22",
        "end": "2020-04-20",
    },
    "shelter_in_place": {
        "affected_contact_model": "other",
        "policy": functools.partial(
            shutdown_if_incidence_above_threshold,
            threshold=100 / 100000,
        ),
        "start": "2020-03-22",
        "end": "2020-04-20",
    },
}