def dependency_on_testing_timeliness_homogeneous_model_example():
    """
    Example of several computations of the limit Eff_∞ in homogeneous scenarios
    in which the time interval Δ^{A → T} varies from 0 to 10 days.
    """
    # Severities: gs = [asymptomatic, symptomatic]
    p_gs, b0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model()
    t_0 = 0

    DeltaAT_values_list = [i for i in range(10)]
    Effinfty_values_list = []

    for DeltaAT_in_days in DeltaAT_values_list:

        scenario = HomogeneousScenario(
            p_gs=p_gs,
            b0_gs=b0_gs,
            tauS=tauS,
            t_0=0,
            ss=(lambda t: 0, lambda t: 0.5 if t >= t_0 else 0),
            sc=lambda t: 0.7 if t >= t_0 else 0,
            xi=lambda t: 0.9 if t >= t_0 else 0,
            DeltaAT=delta_distribution(peak_tau_in_days=DeltaAT_in_days),
        )

        (
            t_in_days_list,
            nu,
            nu0,
            R,
            R_by_severity,
            FT_infty,
        ) = compute_time_evolution_homogeneous_case(
            scenario=scenario,
            t_max_in_days=20,
            nu_start=1000,
            b_negative_times=b0_gs,
            verbose=False,
            threshold_to_stop=0.001,
        )

        Rinfty = R[-1]
        Effinfty = effectiveness(Rinfty, R0)
        Effinfty_values_list.append(Effinfty)

    fig = plt.figure(figsize=(10, 15))

    Rinfty_plot = fig.add_subplot(111)
    Rinfty_plot.set_xlabel("Δ^{A → T} (days)")
    Rinfty_plot.set_ylabel("Eff_∞")
    Rinfty_plot.grid(True)
    Rinfty_plot.set_xlim(0, DeltaAT_values_list[-1])
    Rinfty_plot.set_ylim(0, 0.4)
    Rinfty_plot.plot(
        DeltaAT_values_list,
        Effinfty_values_list,
        color="black",
    ),

    plt.show()
コード例 #2
0
def dependency_on_R0_homogeneous_model_example():
    """
    Example of several computations of the limit Eff_∞ in homogeneous scenarios
    in which R0 varies.
    """
    # Severities: gs = [asymptomatic, symptomatic]

    t_0 = 0

    R0_list = [0.5, 1, 2, 3]
    Effinfty_values_list = []

    for R0 in R0_list:
        p_gs, b0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model(
            R0=R0)
        b_negative_times = None  # tuple(b0_g.normalize() for b0_g in b0_gs)

        scenario = HomogeneousScenario(
            p_gs=p_gs,
            b0_gs=b0_gs,
            tauS=tauS,
            t_0=0,
            ss=(lambda t: 0, lambda t: 0.5 if t >= t_0 else 0),
            sc=lambda t: 0.7 if t >= t_0 else 0,
            xi=lambda t: 0.9 if t >= t_0 else 0,
            DeltaAT=delta_distribution(peak_tau_in_days=2),
        )

        (
            t_in_days_list,
            nu,
            nu0,
            R,
            R_by_severity,
            FT_infty,
        ) = compute_time_evolution_homogeneous_case(
            scenario=scenario,
            t_max_in_days=20,
            nu_start=1000,
            b_negative_times=b_negative_times,
            verbose=True,
            threshold_to_stop=0.001,
        )

        Rinfty = R[-1]
        Effinfty = effectiveness(Rinfty, R0)
        Effinfty_values_list.append(Effinfty)

    plt.xlabel("R0")
    plt.ylabel("Eff_∞")
    plt.grid(True)
    plt.xlim(0, R0_list[-1])
    plt.ylim(0, 0.6)
    plt.plot(
        R0_list,
        Effinfty_values_list,
        color="black",
    ),

    plt.show()
コード例 #3
0
    def test_only_symptoms_control(self):
        p_gs, b0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model(
        )

        scenario = HomogeneousScenario(
            p_gs=p_gs,
            b0_gs=b0_gs,
            tauS=tauS,
            t_0=0,
            ss=(lambda t: 0, lambda t: 0.5),
            sc=lambda t: 0,
            xi=lambda t: 1,
            DeltaAT=delta_distribution(peak_tau_in_days=2),
        )

        (
            t_in_days_list,
            nu,
            nu0,
            R,
            R_by_severity,
            FT_infty,
        ) = compute_time_evolution_homogeneous_case(
            scenario=scenario,
            t_max_in_days=20,
            nu_start=1000,
            b_negative_times=tuple(d.normalize() for d in b0_gs),
            threshold_to_stop=0.001,
            verbose=False,
        )

        assert R[0] == R[-1] < R0
        assert FT_infty[0] == FT_infty[-1] > 0
def time_evolution_homogeneous_model_example_no_negative_times():
    """
    Example running the full algorithm in the homogeneous scenario (no app usage).
    In this case we assume that there are no infected people at t<0.
    """
    t_max_in_days = 20

    DeltaAT_in_days = 2

    t_0 = 0

    scenario = HomogeneousScenario(
        p_gs=p_gs,
        b0_gs=b0_gs,
        tauS=tauS,
        t_0=0,
        ss=(lambda t: 0, lambda t: 0.5 if t >= t_0 else 0),
        sc=lambda t: 0.7 if t >= t_0 else 0,
        xi=lambda t: 0.9 if t >= t_0 else 0,
        DeltaAT=delta_distribution(peak_tau_in_days=DeltaAT_in_days),
    )

    (
        t_in_days_list,
        nu,
        nu0,
        R,
        R_by_severity,
        FT_infty,
    ) = compute_time_evolution_homogeneous_case(
        scenario=scenario,
        t_max_in_days=t_max_in_days,
        nu_start=1000,
        b_negative_times=None,
        threshold_to_stop=0.001,
    )

    plot_homogeneous_time_evolution(
        t_in_days_sequence=t_in_days_list,
        R_ts=R,
        R0=R0,
        FT_infty_sequence=FT_infty,
        nu_ts=nu,
        nu0_ts=nu0,
    )
def time_evolution_homogeneous_model_example():
    """
    Example running the full algorithm in the homogeneous scenario (no app usage).
    """
    t_max_in_days = 20

    DeltaAT_in_days = 2

    scenario = HomogeneousScenario(
        p_gs=p_gs,
        b0_gs=b0_gs,
        tauS=tauS,
        t_0=0,
        ss=(lambda t: 0, lambda t: 0.5),
        sc=lambda t: 0.7,
        xi=lambda t: 0.9,
        DeltaAT=delta_distribution(peak_tau_in_days=DeltaAT_in_days),
    )

    (
        t_in_days_list,
        nu,
        nu0,
        R,
        R_by_severity,
        FT_infty,
    ) = compute_time_evolution_homogeneous_case(
        scenario=scenario,
        t_max_in_days=t_max_in_days,
        nu_start=1000,
        b_negative_times=tuple(d.normalize() for d in b0_gs),
        threshold_to_stop=0.001,
    )

    plot_homogeneous_time_evolution(
        t_in_days_sequence=t_in_days_list,
        R_ts=R,
        R0=R0,
        FT_infty_sequence=FT_infty,
        nu_ts=nu,
        nu0_ts=nu0,
    )
コード例 #6
0
def dependency_on_share_of_symptomatics_homogeneous_model_example():
    """
    Example of several computations of the limit Eff_∞ in homogeneous scenarios
    in which the fraction p_sym of symptomatic individuals  and their contribution to R^0 vary.
    """

    p_sym_list = [0.3, 0.4, 0.5, 0.6, 0.7]
    x_axis_list = []
    Effinfty_values_list = []

    for p_sym in p_sym_list:

        contribution_of_symptomatics_to_R0 = 1 - math.exp(
            -4.993 * p_sym)  # Random choice, gives 0.95 when p_sym = 0.6
        R0_sym = contribution_of_symptomatics_to_R0 / p_sym * R0
        R0_asy = (1 - contribution_of_symptomatics_to_R0) / (1 - p_sym) * R0

        # Severities: gs = (asymptomatic, symptomatic)
        p_gs, b0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model(
            p_sym=p_sym,
            contribution_of_symptomatics_to_R0=
            contribution_of_symptomatics_to_R0,
        )

        scenario = HomogeneousScenario(
            p_gs=p_gs,
            b0_gs=b0_gs,
            tauS=tauS,
            t_0=0,
            ss=(lambda t: 0, lambda t: 0.5),
            sc=lambda t: 0.7,
            xi=lambda t: 0.9,
            DeltaAT=delta_distribution(peak_tau_in_days=2),
        )

        (
            t_in_days_list,
            nu,
            nu0,
            R,
            R_by_severity,
            FT_infty,
        ) = compute_time_evolution_homogeneous_case(
            scenario=scenario,
            t_max_in_days=20,
            nu_start=1000,
            b_negative_times=b0_gs,
            verbose=False,
            threshold_to_stop=0.001,
        )

        Rinfty = R[-1]
        Effinfty = effectiveness(Rinfty, R0)
        Effinfty_values_list.append(Effinfty)

        x_axis_list.append(
            f"p_sym = {p_sym},\nκ={round(contribution_of_symptomatics_to_R0, 2)},\nR^0_sym={round(R0_sym, 2)},\nR^0_asy={round(R0_asy, 2)}"
        )

    plt.xticks(p_sym_list, x_axis_list, rotation=0)
    plt.xlim(0, p_sym_list[-1])
    plt.ylim(0.13, 0.3)
    plt.ylabel("Eff_∞")
    plt.grid(True)
    plt.plot(
        p_sym_list,
        Effinfty_values_list,
        color="black",
    ),

    plt.show()
コード例 #7
0
def dependency_on_generation_time_homogeneous_model_example():
    """
    Example of several computations of the limit Eff_∞ in homogeneous scenarios
    in which the default distribution ρ^0 of the generation time is rescaled by different factors.
    """

    rescale_factors = [0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8]

    expected_default_generation_times_list = []
    Effinfty_values_list = []

    for f in rescale_factors:

        def rescaled_rho0_function(tau):
            return (1 / f) * rho0(tau / f)

        rescaled_rho0 = generate_discrete_distribution_from_pdf_function(
            pdf=lambda tau: rescaled_rho0_function(tau * TAU_UNIT_IN_DAYS) *
            TAU_UNIT_IN_DAYS,
            tau_min=1,
            tau_max=TAU_MAX_IN_UNITS,
            normalize=True,
        )
        EtauC0 = rescaled_rho0.mean()  # Expected default generation time
        expected_default_generation_times_list.append(EtauC0)

        # Severities: gs = (asymptomatic, symptomatic)
        p_gs, b0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model(
            rho0_discrete=rescaled_rho0)

        scenario = HomogeneousScenario(
            p_gs=p_gs,
            b0_gs=b0_gs,
            tauS=tauS,
            t_0=0,
            ss=(lambda t: 0, lambda t: 0.5),
            sc=lambda t: 0.7,
            xi=lambda t: 0.9,
            DeltaAT=delta_distribution(peak_tau_in_days=2),
        )

        (
            t_in_days_list,
            nu,
            nu0,
            R,
            R_by_severity,
            FT_infty,
        ) = compute_time_evolution_homogeneous_case(
            scenario=scenario,
            t_max_in_days=20,
            nu_start=1000,
            b_negative_times=b0_gs,
            verbose=False,
            threshold_to_stop=0.001,
        )

        Rinfty = R[-1]
        Effinfty = effectiveness(Rinfty, R0)
        Effinfty_values_list.append(Effinfty)

    plt.ylim(0, 0.8)
    plt.grid(True)
    plt.plot(
        expected_default_generation_times_list,
        Effinfty_values_list,
        color="black",
    ),
    plt.xlabel("E(τ^{0,C})")
    plt.ylabel("Eff_∞")
    plt.title(
        "Effectiveness under rescaling of the default generation time distribution"
    )

    plt.show()
コード例 #8
0
def dependency_on_contribution_of_symptomatics_homogeneous_model_example():
    """
    Example of several computations of the limit Eff_∞ in homogeneous scenarios
    in which the fraction contribution of symptomatic infections to R^0 vary.
    """

    contribution_of_symptomatics_to_R0_list = [0.7, 0.8, 0.9, 1]
    x_axis_list = []
    Effinfty_values_list = []

    p_sym = 0.6

    for kappa in contribution_of_symptomatics_to_R0_list:

        R0_sym = kappa / p_sym * R0
        R0_asy = (1 - kappa) / (1 - p_sym) * R0

        # Severities: gs = (asymptomatic, symptomatic)
        p_gs, b0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model(
            p_sym=p_sym,
            contribution_of_symptomatics_to_R0=kappa,
        )

        scenario = HomogeneousScenario(
            p_gs=p_gs,
            b0_gs=b0_gs,
            tauS=tauS,
            t_0=0,
            ss=(lambda t: 0, lambda t: 0.5),
            sc=lambda t: 0.7,
            xi=lambda t: 0.9,
            DeltaAT=delta_distribution(peak_tau_in_days=2),
        )

        (
            t_in_days_list,
            nu,
            nu0,
            R,
            R_by_severity,
            FT_infty,
        ) = compute_time_evolution_homogeneous_case(
            scenario=scenario,
            t_max_in_days=20,
            nu_start=1000,
            b_negative_times=b0_gs,
            verbose=False,
            threshold_to_stop=0.001,
        )

        Rinfty = R[-1]
        Effinfty = effectiveness(Rinfty, R0)
        Effinfty_values_list.append(Effinfty)

        x_axis_list.append(
            f"p_sym = {p_sym},\nκ={round(kappa, 2)},\nR^0_sym={round(R0_sym, 2)},\nR^0_asy={round(R0_asy, 2)}"
        )

    plt.xticks(contribution_of_symptomatics_to_R0_list,
               x_axis_list,
               rotation=0)
    plt.xlim(0.5, 1)
    plt.ylim(0.13, 0.3)
    plt.ylabel("Eff_∞")
    plt.grid(True)
    plt.plot(
        contribution_of_symptomatics_to_R0_list,
        Effinfty_values_list,
        color="black",
    ),

    plt.show()
コード例 #9
0
    def test_no_differences_app_no_app_scenario(self):
        p_gs, b0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model(
        )

        ss = 0.5
        sc = 0.6
        DeltaAT = delta_distribution(peak_tau_in_days=2)
        xi = 0.9

        t_max_in_days = 20
        nu_start = 1000

        # Homogeneous case

        scenario = HomogeneousScenario(
            p_gs=p_gs,
            b0_gs=b0_gs,
            tauS=tauS,
            t_0=0,
            ss=(lambda t: 0, lambda t: ss),
            sc=lambda t: sc,
            xi=lambda t: xi,
            DeltaAT=DeltaAT,
        )

        (
            t_in_days_list,
            nu,
            nu0,
            R_homog,
            R_by_severity,
            FT_infty_homog,
        ) = compute_time_evolution_homogeneous_case(
            scenario=scenario,
            t_max_in_days=t_max_in_days,
            nu_start=nu_start,
            b_negative_times=tuple(d.normalize() for d in b0_gs),
            threshold_to_stop=0.001,
            verbose=False,
        )

        # With app case

        scenario = ScenarioWithApp(
            p_gs=p_gs,
            b0_gs=b0_gs,
            tauS=tauS,
            t_0=0,
            ssapp=(lambda t: 0, lambda t: ss),
            ssnoapp=(lambda t: 0, lambda t: ss),
            scapp=lambda t: sc,
            scnoapp=lambda t: sc,
            xi=lambda t: xi,
            DeltaATapp=DeltaAT,
            DeltaATnoapp=DeltaAT,
            epsilon_app=lambda t: 0.6,
        )

        (
            t_in_days_list,
            nu,
            nu0,
            Fsigmaapp_infty,
            R,
            R_app,
            R_noapp,
            FT_infty,
            FT_app_infty,
            FT_noapp_infty,
        ) = compute_time_evolution_with_app(
            scenario=scenario,
            t_max_in_days=t_max_in_days,
            nu_start=1000,
            b_negative_times=tuple(d.normalize() for d in b0_gs),
            verbose=False,
        )

        assert abs(R[-1] - R_homog[-1]) < 0.001
        assert abs(R_app[-1] - R_homog[-1]) < 0.001
        assert abs(R_noapp[-1] - R_homog[-1]) < 0.001
        assert abs(FT_infty[-1] - FT_infty_homog[-1]) < 0.001
        assert abs(FT_app_infty[-1] - FT_infty_homog[-1]) < 0.001
        assert abs(FT_noapp_infty[-1] - FT_infty_homog[-1]) < 0.001
def compute_time_evolution_homogeneous_case(
    scenario: HomogeneousScenario,
    t_max_in_days: int,
    nu_start: int,
    b_negative_times: Optional[Tuple[DiscreteDistributionOnNonNegatives,
                                     ...]] = None,
    verbose: bool = True,
    threshold_to_stop: Optional[float] = None,
) -> Tuple[List[int], List[float], List[float], List[float], List[Tuple[
        float, ...]], List[float], ]:
    """
    The main function that implements the algorithm, computing the time evolution in the
    "homogeneous" scenario, in which the same tracing and isolation measures apply to the whole
    population.
    Note that the time step Δ𝜏 is determined by the constant
        math_utilities.config.UNITS_IN_ONE_DAY.
    :param scenario: the object gathering the input parameters (epidemic data and
      suppression measures).
    :param t_max_in_days: the maximum number of days for which the algorithm runs
    :param nu_start: the initial number of infected people per time step.
    :param b_negative_times: the optional infectiousness (by degree of severity) at times t<0.
      These improper distribution must be jointly normalized to have total mass 1,
      to ensure that the number of infections per time step is constantly equal to nu_start at t<0.
      If None, the epidemic is assumed to start at t=0.
    :param verbose: if True, the main KPIs are printed for each day.
    :param threshold_to_stop: an optional float that makes the algorithm stop if the reproduction
      number R_t and total testing probability FT_infty_t have had relative variations below
      threshold_to_stop in the previous iteration.
    :return: Several lists of floats, one per time step:
    - t_in_days_list: the absolute times 0, Δ𝜏, 2Δ𝜏,...
    - nu: the number of infections at each time step.
    - nu0: the number of infections at each time step, if there were no isolation measures.
    - R: the effective reproduction numbers.
    - R_by_severity: the tuples of effective reproduction numbers by degree of severity,
    - FT_infty: the probabilities to be eventually tested positive.
    """
    #
    t_in_days_list = []
    nu = []
    nu0 = []
    b: List[Tuple[DiscreteDistributionOnNonNegatives, ...]] = []
    R_by_severity: List[Tuple[float, ...]] = []
    R: List[float] = []
    tausigma: List[Tuple[DiscreteDistributionOnNonNegatives, ...]] = []
    tauT: List[Tuple[DiscreteDistributionOnNonNegatives, ...]] = []
    FT_infty: List[float, ...] = []

    gs = range(scenario.n_severities)  # Values of severity G

    t_max = t_max_in_days * UNITS_IN_ONE_DAY
    for t in range(0, t_max + 1):
        t_in_days = t / UNITS_IN_ONE_DAY

        # Compute tausigma_t and nu_t from nu_t' and b_t' for t' = 0,...,t-1
        if t == 0 and b_negative_times is None:
            nu_t = nu_start
            nugs_t = tuple(nu_t * p_g for p_g in scenario.p_gs)
            nu0_t = nu_start
            tausigmags_t = tuple(
                DiscreteDistributionOnNonNegatives(
                    pmf_values=[], tau_min=0, improper=True) for _ in gs)
        else:
            nugs_t, tausigmags_t = compute_tausigma_and_nu_components_at_time_t(
                t=t,
                b=b,
                nu=nu,
                p_gs=scenario.p_gs,
                b_negative_times=b_negative_times,
                nu_negative_times=nu_start,
            )
            nugs0_t, _ = compute_tausigma_and_nu_components_at_time_t(
                t=t,
                b=[scenario.b0_gs] * t,
                nu=nu0,
                p_gs=scenario.p_gs,
                b_negative_times=b_negative_times,
                nu_negative_times=nu_start,
            )

            nu_t = sum(nugs_t)  # People infected at t
            nu0_t = sum(
                nugs0_t)  # People infected at t without isolation measures

            if nu_t < 0.5:  # Breaks the loop when nu_t = 0
                break

        # Compute tauAs_t components from tauS
        tauAs_t_gs = tuple(
            scenario.tauS.rescale_by_factor(scenario.ss[g](t)) for g in gs)

        # Time evolution step:
        # Compute tauAc_t from tausigma_t and tauT_t' (for t' = 0,...,t-1) components
        tauAc_t = compute_tauAc_t(
            t=t,
            tauT=tauT,
            tausigmags_t=tausigmags_t,
            xi=scenario.xi,
            sc_t=scenario.sc(t),
        )

        # Compute tauA_t and tauT_t components from tauAs_t, tauAc_t, and DeltaAT
        tauT_t_gs = compute_tauT_t(tauAs_t_gs=tauAs_t_gs,
                                   tauAc_t=tauAc_t,
                                   DeltaAT=scenario.DeltaAT)

        # Compute b and R
        b_t_gs = compute_suppressed_b_t(b0_t_gs=scenario.b0_gs,
                                        tauT_t_gs=tauT_t_gs,
                                        xi_t=scenario.xi(t))
        R_t_gs = tuple(b_t_g.total_mass for b_t_g in b_t_gs)
        R_t = sum(p_g * R_t_g for (p_g, R_t_g) in zip(scenario.p_gs, R_t_gs))
        FT_t_infty = sum(p_g * tauT_t_g.total_mass
                         for (p_g, tauT_t_g) in zip(scenario.p_gs, tauT_t_gs))

        t_in_days_list.append(t_in_days)
        tausigma.append(tausigmags_t)
        nu.append(nu_t)
        nu0.append(nu0_t)
        b.append(b_t_gs)
        R.append(R_t)
        R_by_severity.append(R_t_gs)
        tauT.append(tauT_t_gs)
        FT_infty.append(FT_t_infty)

        if verbose and t % UNITS_IN_ONE_DAY == 0:
            EtauC_t_gs_in_days = [
                b_t_g.normalize().mean() * UNITS_IN_ONE_DAY for b_t_g in b_t_gs
            ]

            print(f"""t = {t_in_days} days
                    nugs_t = {tuple(nugs_t)},   nu_t = {int(round(nu_t, 0))}
                    nu0_t = {int(round(nu0_t, 0))}
                    R_t_gs = {R_t_gs},    R_t = {round(R_t, 2)}
                    EtauC_t_gs = {tuple(EtauC_t_gs_in_days)} days
                    Fsigmags_t(∞) = {tuple(tausigmag_t.total_mass for tausigmag_t in tausigmags_t)}
                    FAs_t_gs(∞) = {tuple(tauAs_t_g.total_mass for tauAs_t_g in tauAs_t_gs)}
                    FAc_t(∞) = {tauAc_t.total_mass}
                    FT_t_gs(∞) = {tuple(tauT_t_g.total_mass for tauT_t_g in tauT_t_gs)},   FT_t(∞) = {round(FT_t_infty, 2)}
                    tauT_t_gs_mean = {tuple(tauT_t_g.normalize().mean() if tauT_t_g.total_mass > 0 else None for tauT_t_g in tauT_t_gs)},
                    """)

        if (threshold_to_stop is not None and t > 10
                and (abs((R[-2] - R[-1]) / R[-2]) < threshold_to_stop
                     and FT_infty[-2] != 0 and abs(
                         (FT_infty[-2] - FT_infty[-1]) / FT_infty[-2]) <
                     threshold_to_stop)):
            break

    return t_in_days_list, nu, nu0, R, R_by_severity, FT_infty