-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #65 from mikhailsirenko/develop
Develop
- Loading branch information
Showing
35 changed files
with
29,094 additions
and
542 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import yaml | ||
from pathlib import Path | ||
|
||
|
||
def load_config(country: str, return_period: int, disaster_type: str, is_conflict: bool = False) -> dict: | ||
'''Load configuration for the specified case country. | ||
Args: | ||
country (str): The country for which to load the configuration. | ||
return_period (int): The return period for the disaster. | ||
disaster_type (str): The type of disaster. | ||
is_conflict (bool): Whether the country is in conflict. | ||
Returns: | ||
dict: The configuration for the specified case country. | ||
''' | ||
|
||
config_path = Path(f"../config/{country}.yaml") | ||
|
||
if not config_path.exists(): | ||
raise FileNotFoundError( | ||
f"Config file for {country} not found at {config_path}") | ||
|
||
with open(config_path, "r") as file: | ||
config = yaml.safe_load(file) | ||
|
||
check_config_parameters(config) | ||
|
||
config['constants']['return_period'] = return_period | ||
config['constants']['disaster_type'] = disaster_type | ||
|
||
if is_conflict: | ||
config['constants']['is_conflict'] = True | ||
else: | ||
config['constants']['is_conflict'] = False | ||
|
||
return config | ||
|
||
def check_config_parameters(config: dict) -> None: | ||
'''Check if the configuration parameters are valid. | ||
Args: | ||
config (dict): The configuration to check. | ||
Returns: | ||
None | ||
Raises: | ||
ValueError: If the configuration parameters are not valid. | ||
''' | ||
return_periods = [10, 50, 100, 250, 500, 1000] | ||
disaster_types = ['hurricane', 'flood'] | ||
|
||
if 'return_period' not in config['constants']: | ||
raise ValueError("Return period not specified in configuration.") | ||
|
||
if 'disaster_type' not in config['constants']: | ||
raise ValueError("Disaster type not specified in configuration.") | ||
|
||
if 'return_period' not in return_periods: | ||
raise ValueError( | ||
f"Return period {config['constants']['return_period']} not in available return periods: {return_periods}") | ||
|
||
if 'disaster_type' not in disaster_types: | ||
raise ValueError( | ||
f"Disaster type {config['constants']['disaster_type']} not in available disaster types: ['hurricane', 'flood']") | ||
|
||
neccessary_parameters = ['country', 'avg_prod', 'inc_exp_growth', 'cons_util', 'disc_rate', 'disaster_type', 'calc_exposure_params', 'identify_aff_params', 'add_inc_loss', 'pov_bias', 'lambda_incr', 'yrs_to_rec', 'rnd_inc_params', 'rnd_sav_params', 'rnd_rent_params', 'rnd_house_vuln_params', 'min_households', 'atol', 'save_households', 'save_consumption_recovery', 'regions', 'levers', 'uncertainties'] | ||
exposure_neccessary_parameters = ['distr', 'high', 'low'] | ||
identify_aff_neccessary_parameters = ['delta_pct', 'distr', 'high', 'low', 'num_masks'] | ||
rnd_inc_neccessary_parameters = ['randomize', 'distr', 'delta'] | ||
rnd_sav_neccessary_parameters = ['randomize', 'distr', 'avg', 'delta'] | ||
rnd_rent_neccessary_parameters = ['randomize', 'distr', 'avg', 'delta'] | ||
rnd_house_vuln_neccessary_parameters = ['randomize', 'distr', 'low', 'high', 'min_thresh', 'max_thresh'] | ||
|
||
for parameter in neccessary_parameters: | ||
if parameter not in config['constants']: | ||
raise ValueError(f"Parameter {parameter} not found in configuration.") | ||
|
||
for parameter in exposure_neccessary_parameters: | ||
if parameter not in config['constants']['calc_exposure_params']: | ||
raise ValueError(f"Parameter {parameter} not found in calc_exposure_params.") | ||
|
||
for parameter in identify_aff_neccessary_parameters: | ||
if parameter not in config['constants']['identify_aff_params']: | ||
raise ValueError(f"Parameter {parameter} not found in identify_aff_params.") | ||
|
||
for parameter in rnd_inc_neccessary_parameters: | ||
if parameter not in config['constants']['rnd_inc_params']: | ||
raise ValueError(f"Parameter {parameter} not found in rnd_inc_params.") | ||
|
||
for parameter in rnd_sav_neccessary_parameters: | ||
if parameter not in config['constants']['rnd_sav_params']: | ||
raise ValueError(f"Parameter {parameter} not found in rnd_sav_params.") | ||
|
||
for parameter in rnd_rent_neccessary_parameters: | ||
if parameter not in config['constants']['rnd_rent_params']: | ||
raise ValueError(f"Parameter {parameter} not found in rnd_rent_params.") | ||
|
||
for parameter in rnd_house_vuln_neccessary_parameters: | ||
if parameter not in config['constants']['rnd_house_vuln_params']: | ||
raise ValueError(f"Parameter {parameter} not found in rnd_house_vuln_params.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from pathlib import Path | ||
from ema_workbench import perform_experiments, MultiprocessingEvaluator, save_results, Model | ||
|
||
|
||
def run_experiments(experimental_setup: dict) -> None: | ||
'''Run experiments with the specified setup with the use of EMA Workbench and save the results. | ||
Args: | ||
experimental_setup (dict): A dictionary containing the setup for the experiments. | ||
Returns: | ||
None | ||
''' | ||
country = experimental_setup['country'] | ||
return_period = experimental_setup['return_period'] | ||
model = experimental_setup['model'] | ||
n_scenarios = experimental_setup['n_scenarios'] | ||
n_policies = experimental_setup['n_policies'] | ||
multiprocessing = experimental_setup['multiprocessing'] | ||
n_processes = experimental_setup['n_processes'] | ||
|
||
if multiprocessing: | ||
with MultiprocessingEvaluator(model, n_processes=n_processes) as evaluator: | ||
results = evaluator.perform_experiments( | ||
scenarios=n_scenarios, policies=n_policies) | ||
else: | ||
results = perform_experiments( | ||
models=model, scenarios=n_scenarios, policies=n_policies) | ||
|
||
save_experiment_results(country, return_period, model, | ||
results, n_scenarios, n_policies) | ||
|
||
|
||
def save_experiment_results(country: str, return_period: int, model: Model, results: dict, n_scenarios: int, n_policies: int): | ||
"""Saves experiment results to a file, taking into account if there was a conflict.""" | ||
results_path = Path(f'../results/{country}') | ||
results_path.mkdir(parents=True, exist_ok=True) | ||
|
||
is_conflict = getattr(model.constants._data.get( | ||
'is_conflict'), 'value', False) | ||
|
||
conflict_str = ", conflict=True" if is_conflict else "" | ||
filename = f"return_period={return_period}, scenarios={n_scenarios}, policies={n_policies}{conflict_str}.tar.gz" | ||
save_results(results, results_path / filename) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
from ema_workbench import Model | ||
from ema_workbench.em_framework.parameters import IntegerParameter, CategoricalParameter, Constant | ||
from ema_workbench.em_framework.outcomes import ArrayOutcome | ||
from unbreakable.model import model | ||
|
||
|
||
def setup_model(config: dict) -> Model: | ||
""" | ||
Set up the EMA Workbench model based on the provided configuration. | ||
Args: | ||
config (dict): Configuration dictionary loaded from the YAML file. | ||
Returns: | ||
Model: Configured EMA Workbench model. | ||
""" | ||
my_model = Model(name="model", function=model) | ||
|
||
# Extract and set up uncertainties, constants, and levers from the config | ||
# uncertainties = config.get("uncertainties", {}) | ||
constants = config.get("constants", {}) | ||
levers = config.get("levers", {}) | ||
|
||
# Define seed as an uncertainty for multiple runs, | ||
# By specifying a wider range, we want to ensure that the seed is likely to be different for each run | ||
seed_start = 0 | ||
seed_end = 1000000000 | ||
|
||
# Fix seed to ensure reproducibility | ||
# NOTE: If running multiple instances of the model in parallel, the seed will be the same for all instances | ||
# np.random.seed(42) | ||
|
||
my_model.uncertainties = [IntegerParameter( | ||
"random_seed", seed_start, seed_end)] | ||
|
||
# Constants | ||
my_model.constants = [Constant(key, value) | ||
for key, value in constants.items()] | ||
|
||
# Levers | ||
my_model.levers = [CategoricalParameter( | ||
'current_policy', [values for _, values in levers.items()])] | ||
|
||
# Outcomes | ||
my_model.outcomes = [ArrayOutcome(region) | ||
for region in constants.get('regions', [])] | ||
|
||
return my_model |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.