Example #1
0
 def test_interface(
     self,
     gdp_model_cls,
     personal_bankruptcy_model_cls,
     corporate_bankruptcy_model_cls,
     utilisation,
 ):
     reader = Reader(DATA_PATH)
     state = state_from_utilisation(UTILISATION_NO_COVID_NO_LOCKDOWN)
     econ_model = Economics(
         gdp_model_cls(),
         corporate_bankruptcy_model_cls(),
         personal_bankruptcy_model_cls(),
     )
     econ_model.load(reader)
     econ_model.simulate(state)
     new_state = advance_state(state, utilisation)
     econ_model.simulate(new_state)
     # Factor of 1.1 is because of the GDP backbone model
     assert (0 <= sum(new_state.gdp_state.gdp.values()) <=
             new_state.gdp_state.max_gdp * 1.1)
     for (
             _business_size,
             mapping,
     ) in new_state.corporate_state.proportion_solvent.items():
         for sector, solvent in mapping.items():
             assert 0 <= solvent <= 1
     for region in Region:
         assert 0 <= new_state.personal_state.personal_bankruptcy[
             region] <= 1
 def test_interface(
     self,
     gdp_model_cls,
     personal_bankruptcy_model_cls,
     corporate_bankruptcy_model_cls,
     lockdown,
     utilisations,
 ):
     reader = Reader(DATA_PATH)
     econ_model = Economics(
         gdp_model_cls(),
         corporate_bankruptcy_model_cls(),
         personal_bankruptcy_model_cls(),
     )
     econ_model.load(reader)
     try:
         # Simulation should fail unless we start outside of lockdown
         econ_model.simulate(time=0,
                             lockdown=lockdown,
                             utilisations=utilisations)
     except ValueError:
         if not lockdown:
             raise
     else:
         if lockdown:
             raise ValueError()
         assert 0 <= sum(
             econ_model.results.fraction_gdp_by_sector(0).values()) <= 1
Example #3
0
def _econ_worker(
    queues: Mapping[Region, multiprocessing.Queue],
    model: Economics,
    total_individuals: int,
    end_time: int,
    output_dir: str,
) -> Economics:
    utilisations = {}
    for step in range(end_time):
        lockdowns = {}
        for region, queue in queues.items():
            step_, results = queue.get()
            if step != step_:
                raise ValueError(
                    f"Simulation offset: expected {step}, found {step_}, state: {results}"
                )
            lockdowns[region] = results["lockdown"]
            # total individuals is measured per region
            out_of_action = (
                results["n_quarantine"]
                + results["n_hospital"]
                + results["n_critical"]
                + results["n_death"]
            )
            utilisations[region] = 1 - out_of_action / total_individuals

        if len(set(lockdowns.values())) != 1:
            raise NotImplementedError(
                f"Model cannot handle selective lockdown by region yet: step={step} lockdowns={lockdowns}"
            )
        lockdown = next(iter(lockdowns.values()))
        utilisations = {
            (r, s, a): utilisations[r]
            for r, s, a in itertools.product(Region, Sector, Age)
        }
        model.simulate(step, lockdown, utilisations)

    _output_econ_data(model, end_time, output_dir)
    return model
Example #4
0
    def simulate(
        self,
        scenario: Scenario,
        show_plots: bool = True,
        figsize: Tuple = (20, 60),
        scenario_name: str = "",
    ) -> Tuple[Economics, List[SimulateState]]:
        """
        Run simulation for a given scenario

        :param scenario: Scenario to run the simulation
        :type scenario: Scenario
        :param show_plots: Show the plots using matplotlib if set to be True
        :type show_plots: bool
        :param figsize: Size of the figure to be plotted. This parameter is only used when show_plots is set to be True
        :type figsize: Tuple
        :param scenario_name: Name of the scenario. Used in plotting
        :type scenario_name: str
        :return: Tuple[Economics, List[SimulateState]]
        """
        # Load data for the scenario object if not done yet
        if not scenario.is_loaded:
            scenario.load(self.reader)

        # Initialize various models given the model parameters specified in the Scenario
        model_params = scenario.model_params
        gdp_model = PiecewiseLinearCobbDouglasGdpModel(
            **model_params.gdp_params)
        cb_model = CorporateBankruptcyModel(**model_params.corporate_params)
        pb_model = PersonalBankruptcyModel(**model_params.personal_params)
        econ = Economics(gdp_model, cb_model, pb_model,
                         **model_params.economics_params)

        # Load data for Economy
        econ.load(self.reader)

        states = []
        for i in tqdm(range(scenario.simulation_end_time)):
            # Load ill and dead ratio from scenario
            ill = scenario.get_ill_ratio_dict(i)
            dead = scenario.get_dead_ratio_dict(i)

            # Load quarantine information
            quarantine = scenario.get_quarantine_ratio_dict(i)

            # Initialize  a SimulateState object
            simulate_state = scenario.generate(
                time=i,
                dead=dead,
                ill=ill,
                quarantine=quarantine,
                lockdown=scenario.lockdown_start_time <= i <
                scenario.lockdown_end_time,
                furlough=scenario.furlough_start_time <= i <
                scenario.furlough_end_time,
                reader=self.reader,
            )

            # Pass SimulateState to Economy
            econ.simulate(simulate_state)

            # Keep a record of the current SimulateState
            states.append(simulate_state)

        # Plots
        if show_plots:
            fig, axes = plt.subplots(7,
                                     1,
                                     sharex="col",
                                     sharey="row",
                                     figsize=figsize)
            plot_one_scenario(states,
                              scenario.simulation_end_time,
                              axes,
                              title_prefix=scenario_name)

        return econ, states
Example #5
0
def main(
    parameters,
    household_demographics,
    outdir,
    total_individuals,
    lockdown_start,
    lockdown_end,
    end_time,
    econ_data_dir,
    gdp_model,
) -> None:
    """
    Run simulations by region
    """

    # set up output directory and paths
    output_dir = click.format_filename(outdir)
    os.makedirs(output_dir, exist_ok=True)
    parameters_path = click.format_filename(parameters)
    household_demographics_path = click.format_filename(household_demographics)
    econ_data_dir = click.format_filename(econ_data_dir)
    with open(os.path.join(econ_data_dir, "parameters.json"), "r") as f:
        econ_parameters = json.load(f)

    # Read regional population distributions in age
    populations_df = pd.read_csv(os.path.join(econ_data_dir, "populations.csv"))
    populations_by_region = {
        Region[k]: {Age10Y[kk]: vv for kk, vv in v.items()}
        for k, v in populations_df.set_index("region").T.to_dict().items()
    }
    queues = {r: multiprocessing.Queue() for r in Region}

    # Setup economics model
    reader = Reader(econ_data_dir)
    gdp_model = ECON_MODELS[gdp_model](**econ_parameters["gdp"])
    cb_model = CorporateBankruptcyModel(**econ_parameters["corporate_bankruptcy"])
    pb_model = PersonalBankruptcyModel(**econ_parameters["personal_insolvency"])
    econ_model = Economics(gdp_model, cb_model, pb_model)
    econ_model.load(reader)

    worker = functools.partial(
        _worker,
        output_dir=output_dir,
        parameters_path=parameters_path,
        household_demographics_path=household_demographics_path,
        total_individuals=total_individuals,
        lockdown_start=lockdown_start,
        lockdown_end=lockdown_end,
        end_time=end_time,
    )

    econ_worker = functools.partial(
        _econ_worker,
        model=econ_model,
        total_individuals=total_individuals,
        end_time=end_time,
        output_dir=output_dir,
    )

    spread_processes = [
        multiprocessing.Process(
            target=worker, args=((r, populations_by_region[r], queues[r]),)
        )
        for r in Region
    ]
    for p in spread_processes:
        p.start()
    econ_model = econ_worker(queues)
    for p in spread_processes:
        p.join()

    plot_econ_data(econ_model, total_individuals, end_time, econ_data_dir, output_dir)
    # Read regional population distributions in age
    populations_df = pd.read_csv(os.path.join(econ_data_dir, "populations.csv"))
    populations_by_region = {
        Region[k]: {Age10Y[kk]: vv for kk, vv in v.items()}
        for k, v in populations_df.set_index("region").T.to_dict().items()
    }
    manager = multiprocessing.Manager()
    queues = {r: manager.Queue() for r in Region}

    # Setup economics model
    reader = Reader(econ_data_dir)
    gdp_model = ECON_MODELS[gdp_model](**example_parameters["gdp"])
    cb_model = CorporateBankruptcyModel(**example_parameters["corporate_bankruptcy"])
    pb_model = PersonalBankruptcyModel(**example_parameters["personal_insolvency"])
    econ_model = Economics(gdp_model, cb_model, pb_model)
    econ_model.load(reader)

    spread_worker = functools.partial(
        _spread_worker,
        output_dir=output_dir,
        parameters_path=parameters_path,
        household_demographics_path=household_demographics_path,
        total_individuals=total_individuals,
        lockdown_start=lockdown_start,
        lockdown_end=lockdown_end,
        end_time=end_time,
    )

    econ_worker = functools.partial(
        _econ_worker,
Example #7
0
def lockdown_then_unlock_no_corona(data_path: str = "data"):
    """
    Lockdown at t=5 days, then release lockdown at t=50 days.

    :param data_path:
    :return:
    """
    reader = Reader(data_path)
    econ = Economics(
        SupplyDemandGdpModel(), CorporateBankruptcyModel(), PersonalBankruptcyModel()
    )
    econ.load(reader)
    max_utilisations = {key: 1.0 for key in itertools.product(Region, Sector, Age)}
    min_utilisations = {key: 0.0 for key in itertools.product(Region, Sector, Age)}
    length = 100
    for i in range(length):
        if 5 <= i < 50:
            econ.simulate(i, True, min_utilisations)
        else:
            econ.simulate(i, False, max_utilisations)
    df = (
        pd.DataFrame(
            [econ.results.fraction_gdp_by_sector(i) for i in range(1, length)],
            index=range(1, length),
        )
        .T.sort_index()
        .T.cumsum(axis=1)
    )

    # Plot 1
    fig, ax = plt.subplots(figsize=(20, 10))
    ax.fill_between(df.index, df.iloc[:, 0] * 0, df.iloc[:, 0], label=df.columns[0])
    for i in range(1, df.shape[1]):
        ax.fill_between(df.index, df.iloc[:, i - 1], df.iloc[:, i], label=df.columns[i])
    ax.legend(ncol=2)

    # Plot 2
    df = pd.DataFrame(
        [
            econ.results.corporate_solvencies[i]
            for i in econ.results.corporate_solvencies
        ]
    )
    df.plot(figsize=(20, 10))

    # Plot 3
    pd.DataFrame(
        [
            {
                r: econ.results.personal_bankruptcy[i][r].personal_bankruptcy
                for r in Region
            }
            for i in econ.results.personal_bankruptcy
        ]
    ).plot(figsize=(20, 10))

    # Plot 4
    pd.DataFrame(
        [
            {
                r: econ.results.personal_bankruptcy[i][r].corporate_bankruptcy
                for r in Region
            }
            for i in econ.results.personal_bankruptcy
        ]
    ).plot(figsize=(20, 10))