def time_evolution_optimistic_scenario_example(): """ Example in which the sensitivities s^S and s^C are high for who uses the app, and the app is used by 60% of the population. """ # gs = [asymptomatic, symptomatic] n_iterations = 8 p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model( ) scenario = Scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ssapp=[0, 0.8], ssnoapp=[0, 0.2], scapp=0.8, scnoapp=0.2, xi=0.9, papp=lambda t: 0.6, p_DeltaATapp=DeltaMeasure(position=2), p_DeltaATnoapp=DeltaMeasure(position=4), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=n_iterations, verbose=True, ) plot_time_evolution(step_data_list=step_data_list)
def dependency_on_share_of_symptomatics_homogeneous_model_example(): """ Example of several computations of the limit Eff_∞ in homogeneous scenarios (i.e. with no app usage) 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 # gs = [asymptomatic, symptomatic] p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model( p_sym=p_sym, contribution_of_symptomatics_to_R0=contribution_of_symptomatics_to_R0, ) n_iterations = 6 scenario = make_homogeneous_scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ss=[0, 0.5], sc=0.7, xi=0.9, p_DeltaAT=DeltaMeasure(position=2), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=n_iterations, verbose=False, ) Rinfty = step_data_list[-1].R Effinfty = effectiveness_from_R(Rinfty) 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)}" ) Effinfty_values_list.append(Effinfty) plt.xticks(p_sym_list, x_axis_list, rotation=0) plt.xlim(0, p_sym_list[-1]) plt.ylim(0, 0.8) plt.ylabel("Eff_∞") plt.grid(True) plt.plot(p_sym_list, Effinfty_values_list, color="black",), plt.show()
def time_evolution_with_varying_parameters(): """ Run the algorithm several times, each with a different choice of the parameters s^S, s^C, xi, and p^app. """ tau_max = 30 integration_step = 0.1 n_iterations = 8 # gs = [asymptomatic, symptomatic] p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model( ) ssnoapp = 0.2 scnoapp = 0.2 DeltaATapp = 2 DeltaATnoapp = 4 # Varying parameters ssapp_list = [0.2, 0.5, 0.8] scapp_list = [0.5, 0.8] xi_list = [0.7, 0.9] papp_list = [0.2, 0.5, 0.7, 0.9] for ssapp in ssapp_list: for scapp in scapp_list: for xi in xi_list: for papp in papp_list: scenario = Scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ssapp=[0, ssapp], ssnoapp=[0, ssnoapp], scapp=scapp, scnoapp=scnoapp, xi=xi, papp=lambda tau: papp, p_DeltaATapp=DeltaMeasure(position=DeltaATapp), p_DeltaATnoapp=DeltaMeasure(position=DeltaATnoapp), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=n_iterations, verbose=False, ) Rinfty = step_data_list[-1].R Effinfty = effectiveness_from_R(Rinfty) print( f" {ssapp} & {scapp} & {xi} & {papp} & {round2(Rinfty)} & {round2(Effinfty)} \\\ " )
def plot_symptoms_onset_distribution(): tau_max = 30 step = 0.05 EtauS = integrate( lambda tau: (1 - FS(tau)), 0, tau_max ) # Expected time of symptoms onset for symptomatics print("E(τ^S) =", EtauS) plot_functions( fs=[FS], real_range=RealRange(x_min=0, x_max=tau_max, step=step), title="The CDF F^S of the symptoms onset time τ^S", )
def plot_and_integrate_infectiousness(): tau_max = 30 step = 0.05 integral_beta0 = integrate(beta0, 0, tau_max) print("The integral of β^0_0 is", integral_beta0) # This should (approximately) give back R0: assert round(integral_beta0 - R0, 5) == 0 plot_functions( fs=[beta0], real_range=RealRange(x_min=0, x_max=tau_max, step=step), title="The default infectiousness β^0_0", )
def plot_generation_time(): tau_max = 30 step = 0.05 print( "Expected default generation time: E(τ^C) =", integrate(lambda tau: tau * rho0(tau), 0, tau_max), ) plot_functions( fs=[rho0], real_range=RealRange(x_min=0, x_max=tau_max, step=step), title="The default generation time distribution ρ^0", )
def dependency_on_app_adoption_example(): """ Example of several computations of the limit Eff_∞ with app usage, where the fraction p^app of app adopters varies. """ n_iterations = 8 # gs = [asymptomatic, symptomatic] p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model() papp_list = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] Effinfty_values_list = [] for papp in papp_list: scenario = Scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ssapp=[0, 0.5], ssnoapp=[0, 0.2], scapp=0.7, scnoapp=0.2, xi=0.9, papp=lambda t: papp, p_DeltaATapp=DeltaMeasure(position=2), p_DeltaATnoapp=DeltaMeasure(position=4), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=n_iterations, verbose=False, ) Rinfty = step_data_list[-1].R Effinfty = effectiveness_from_R(Rinfty) Effinfty_values_list.append(Effinfty) fig = plt.figure(figsize=(10, 15)) Rinfty_plot = fig.add_subplot(111) Rinfty_plot.set_xlabel("p^app") Rinfty_plot.set_ylabel("Eff_∞") Rinfty_plot.grid(True) Rinfty_plot.set_xlim(0, 1) Rinfty_plot.set_ylim(0, 1) Rinfty_plot.plot(papp_list, Effinfty_values_list, color="black",), plt.show()
def test_compute_FT(self): FAapp_ti_gs = [ lambda tau: 0.4, lambda tau: 1 if tau >= 10 else 0.5, ] FAnoapp_ti_gs = [ lambda tau: 0.5 if tau >= 20 else 0, lambda tau: 1 if tau >= 20 else 0.3, ] position_app = 1 position_noapp = 5 p_DeltaATapp = DeltaMeasure(position=position_app) p_DeltaATnoapp = DeltaMeasure(position=position_noapp) real_range = RealRange(x_min=0, x_max=30, step=0.1) FTapp_ti_gs, FTnoapp_ti_gs = compute_FT_from_FA_and_DeltaAT( FAapp_ti_gs=FAapp_ti_gs, FAnoapp_ti_gs=FAnoapp_ti_gs, p_DeltaATapp=p_DeltaATapp, p_DeltaATnoapp=p_DeltaATnoapp, ) # Check that each FT component is the translation of the respective FA component assert all( FAapp_ti_gs[0](tau - position_app) == FTapp_ti_gs[0](tau) for tau in (-10, -2, 0, 2, 5, 10, 20, 30) ) assert all( FAapp_ti_gs[1](tau - position_app) == FTapp_ti_gs[1](tau) for tau in (-10, -2, 0, 2, 5, 10, 20, 30) ) assert not all( FAapp_ti_gs[1](tau) == FTapp_ti_gs[1](tau) for tau in (8, 10, 12) ) assert all( FAnoapp_ti_gs[0](tau - position_noapp) == FTnoapp_ti_gs[0](tau) for tau in (-10, 10, 20, 22, 27, 30) ) assert all( FAnoapp_ti_gs[1](tau - position_noapp) == FTnoapp_ti_gs[1](tau) for tau in (-10, 10, 20, 22, 27, 30) ) assert not all( FAnoapp_ti_gs[1](tau) == FTnoapp_ti_gs[1](tau) for tau in (18, 20, 22) )
def R_suppression_with_fixed_testing_time(): """ Example computing the suppressed beta and R, given that the testing time CDF F^T is a step function. """ tau_s = 10 FT = lambda tau: heaviside(tau - tau_s, 1) # CDF of testing time xi = 1.0 # Probability of (immediate) isolation given positive test suppressed_beta_0 = suppressed_beta_from_test_cdf(beta0, FT, xi) suppressed_R_0 = integrate.quad(lambda tau: suppressed_beta_0(tau), 0, tau_max)[0] print("suppressed R_0 =", suppressed_R_0) plot_functions([beta0, suppressed_beta_0], RealRange(x_min=0, x_max=tau_max, step=step))
def dependency_on_testing_timeliness_homogeneous_model_example(): """ Example of several computations of the limit Eff_∞ in homogeneous scenarios (i.e. with no app usage) in which the time interval Δ^{A → T} varies from 0 to 10 days. """ n_iterations = 8 # gs = [asymptomatic, symptomatic] p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model() DeltaAT_values_list = list(range(0, 10)) Effinfty_values_list = [] for DeltaAT in DeltaAT_values_list: scenario = make_homogeneous_scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ss=[0, 0.5], sc=0.7, xi=0.9, p_DeltaAT=DeltaMeasure(position=DeltaAT), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=n_iterations, verbose=False, ) Rinfty = step_data_list[-1].R Effinfty = effectiveness_from_R(Rinfty) 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.6) Rinfty_plot.plot(DeltaAT_values_list, Effinfty_values_list, color="black",), plt.show()
def test_functions_to_lists(): def f(x): return x * x real_range = RealRange(0, 2, 0.5) lf = list_from_f(f, real_range) assert len(lf) == 5 assert all([lf[i] == real_range.x_values[i]**2 for i in range(len(lf))]) fl = f_from_list(lf, real_range) assert all([ fl(real_range.x_values[i]) == real_range.x_values[i]**2 for i in range(len(lf)) ])
def R_suppression_due_to_symptoms_only(): """ Example computing the suppressed beta and R, given that the testing time CDF F^T is just a traslation and rescaling of the symptoms onset CDF F^S. """ Deltat_test = 4 ss = 0.2 FT = lambda tau: ss * FS(tau - Deltat_test) # CDF of testing time xi = 1.0 # Probability of (immediate) isolation given positive test suppressed_beta_0 = suppressed_beta_from_test_cdf(beta0, FT, xi) suppressed_R_0 = integrate.quad(lambda tau: suppressed_beta_0(tau), 0, tau_max)[0] print("suppressed R_0 =", suppressed_R_0) plot_functions([beta0, suppressed_beta_0], RealRange(x_min=0, x_max=tau_max, step=step))
def time_evolution_gradual_app_adoption_example(): """ Example in which the share of people using the app linearly increases, until reaching 60% in 30 days. """ # gs = [asymptomatic, symptomatic] n_iterations = 16 p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model( ) def papp(t: float) -> float: papp_infty = 0.6 t_saturation = 30 if 0 <= t < t_saturation: return papp_infty * t / t_saturation elif t >= t_saturation: return papp_infty scenario = Scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ssapp=[0, 0.8], ssnoapp=[0, 0.2], scapp=0.8, scnoapp=0.2, xi=0.9, papp=papp, p_DeltaATapp=DeltaMeasure(position=2), p_DeltaATnoapp=DeltaMeasure(position=4), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=n_iterations, verbose=True, ) plot_time_evolution(step_data_list=step_data_list)
def time_evolution_homogeneous_model_optimistic_scenario_example(): """ Example in which there is no app usage, and the sensitivities s^S and s^C are quite high """ # gs = [asymptomatic, symptomatic] n_iterations = 8 p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model( ) ss = [0, 0.5] sc = 0.7 xi = 0.9 DeltaAT = 2 scenario = Scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ssapp=[0, 0], ssnoapp=ss, scapp=0, scnoapp=sc, xi=xi, papp=lambda tau: 0, p_DeltaATapp=DeltaMeasure(position=0), p_DeltaATnoapp=DeltaMeasure(position=DeltaAT), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=n_iterations, verbose=True, ) plot_time_evolution(step_data_list=step_data_list, plot_components=False)
def test_no_epidemic_control_scenario(self): tau_max = 30 integration_step = 0.1 scenario = Scenario( p_gs=[1], beta0_gs=[lambda t, tau: beta0(tau)], t_0=0, ssapp=[0], ssnoapp=[0], scapp=0, scnoapp=0, xi=1, papp=lambda tau: 0.6, p_DeltaATapp=DeltaMeasure(position=1), p_DeltaATnoapp=DeltaMeasure(position=2), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=4, verbose=False, ) last_step_data = step_data_list[-1] precision = 3 assert check_equality_with_precision(x=last_step_data.R, y=R0, decimal=precision) assert check_equality_with_precision(x=last_step_data.FT_infty, y=0, decimal=precision) assert check_equality_with_precision(x=last_step_data.papp, y=last_step_data.tildepapp, decimal=precision)
def test_only_symptoms_control(self): tau_max = 30 integration_step = 0.1 # gs = [asymptomatic, symptomatic]: p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model( ) scenario = Scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ssapp=[0, 0.7], ssnoapp=[0, 0.5], scapp=0, scnoapp=0, xi=1, papp=lambda tau: 0, p_DeltaATapp=DeltaMeasure(position=1), p_DeltaATnoapp=DeltaMeasure(position=2), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=4, verbose=False, ) precision = 3 first_step_data = step_data_list[0] last_step_data = step_data_list[-1] assert check_equality_with_precision(x=first_step_data.R, y=last_step_data.R, decimal=precision)
def dependency_on_infectiousness_width_homogeneous_model_example(): """ Example of several computations of the limit Eff_∞ in homogeneous scenarios (i.e. with no app usage) in which the default distribution ρ^0 of the generation time is rescaled by different factors. """ infectiousness_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 infectiousness_rescale_factors: def rescaled_rho0(tau): return (1 / f) * rho0(tau / f) assert round(integrate(rescaled_rho0, 0, tau_max), 5) == 1 EtauC0 = integrate( lambda tau: tau * rescaled_rho0(tau), 0, tau_max ) # Expected default generation time expected_default_generation_times_list.append(EtauC0) # gs = [asymptomatic, symptomatic] p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model( rho0=rescaled_rho0 ) n_iterations = 6 scenario = make_homogeneous_scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ss=[0, 0.5], sc=0.7, xi=0.9, p_DeltaAT=DeltaMeasure(position=2), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=n_iterations, verbose=False, ) Rinfty = step_data_list[-1].R Effinfty = effectiveness_from_R(Rinfty) 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()
def dependency_on_efficiencies_example(): """ Example of several computations of the limit Eff_∞ with app usage, where the parameters s^{s,app} and s^{c,app} vary. """ n_iterations = 8 # gs = [asymptomatic, symptomatic] p_gs, beta0_gs = make_scenario_parameters_for_asymptomatic_symptomatic_model() ssapp_list = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] scapp_list = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] Effinfty_values_list = [] for scapp in scapp_list: Effinfty_values_list_for_scapp = [] for ssapp in ssapp_list: scenario = Scenario( p_gs=p_gs, beta0_gs=beta0_gs, t_0=0, ssapp=[0, ssapp], ssnoapp=[0, 0.2], scapp=scapp, scnoapp=0.2, xi=0.9, papp=lambda t: 0.6, p_DeltaATapp=DeltaMeasure(position=2), p_DeltaATnoapp=DeltaMeasure(position=4), ) step_data_list = compute_time_evolution( scenario=scenario, real_range=RealRange(0, tau_max, integration_step), n_iterations=n_iterations, verbose=False, ) Rinfty = step_data_list[-1].R Effinfty = effectiveness_from_R(Rinfty) print( f"s^{{s,app}} = {ssapp}, s^{{c,app}} = {scapp}, Eff_∞ = {round(Effinfty, 2)}" ) Effinfty_values_list_for_scapp.append(Effinfty) Effinfty_values_list.append(Effinfty_values_list_for_scapp) ssapp_values_array, scapp_values_array = np.meshgrid(ssapp_list, scapp_list) fig = plt.figure(figsize=(10, 15)) ax = fig.gca(projection="3d") ax.plot_surface( ssapp_values_array, scapp_values_array, np.array(Effinfty_values_list), ) ax.set_xlabel("s^{s,app}") ax.set_ylabel("s^{c,app}") ax.set_zlabel("Eff_∞") plt.show()