def test_simple_graph(self, get_sector_model): regions = Mock() regions.name = 'test_regions' intervals = Mock() intervals.name = 'test_intervals' SectorModel = get_sector_model elec_scenario = ScenarioModel('scenario') elec_scenario.add_output('output', regions, intervals, 'unit') energy_model = SectorModel('model') energy_model.add_input('input', regions, intervals, 'unit') energy_model.add_dependency(elec_scenario, 'output', 'input') sos_model = SosModel('energy_sos_model') sos_model.add_model(energy_model) sos_model.add_model(elec_scenario) # Builds the dependency graph sos_model.check_dependencies() graph = sos_model.dependency_graph assert energy_model in graph assert elec_scenario in graph assert list(graph.edges()) == [(elec_scenario, energy_model)]
def test_model_set_deps(self, get_water_sector_model, get_energy_sector_model): pop_scenario = ScenarioModel('population') pop_scenario.add_output('population', pop_scenario.regions.get_entry('LSOA'), pop_scenario.intervals.get_entry('annual'), 'unit') energy_model = get_energy_sector_model energy_model.add_input('population', energy_model.regions.get_entry('LSOA'), energy_model.intervals.get_entry('annual'), 'unit') water_model = get_water_sector_model energy_model.add_dependency(pop_scenario, 'population', 'population') energy_model.add_dependency(water_model, 'electricity_demand', 'electricity_demand_input') water_model.add_dependency(energy_model, 'fluffiness', 'fluffyness') model_set = ModelSet({ energy_model.name: energy_model, water_model.name: water_model }) # ModelSet should derive inputs as any input to one of its models which # is not met by an internal dependency print(model_set.inputs) assert len(model_set.inputs) == 1 assert 'population' in model_set.inputs.names # ModelSet should derive dependencies as links to any model which # supplies a dependency not met internally assert len(model_set.deps) == 1 assert model_set.deps['population'].source_model is pop_scenario
def test_get_model_sets(self, get_sector_model): regions = Mock() regions.name = 'test_regions' intervals = Mock() intervals.name = 'test_intervals' elec_scenario = ScenarioModel('scenario') elec_scenario.add_output('output', regions, intervals, 'unit') SectorModel = get_sector_model energy_model = SectorModel('model') energy_model.add_input('input', regions, intervals, 'unit') energy_model.add_dependency(elec_scenario, 'output', 'input') sos_model = SosModel('energy_sos_model') sos_model.add_model(energy_model) sos_model.add_model(elec_scenario) sos_model.check_dependencies() actual = sos_model._get_model_sets_in_run_order() expected = ['scenario', 'model'] for model, name in zip(actual, expected): assert model.name == name
def test_model_set(self): elec_scenario = ScenarioModel('scenario') elec_scenario.add_output('output', elec_scenario.regions.get_entry('LSOA'), elec_scenario.intervals.get_entry('annual'), 'unit') ModelSet({elec_scenario.name: elec_scenario})
def get_scenario(): scenario = ScenarioModel('electricity_demand_scenario') scenario.scenario_name = 'Arbitrary Demand Scenario' scenario.add_output('electricity_demand_output', scenario.regions.get_entry('LSOA'), scenario.intervals.get_entry('annual'), 'unit') return scenario
def get_scenario_model_object(): scenario_model = ScenarioModel('test_scenario_model') scenario_model.add_output('raininess', scenario_model.regions.get_entry('LSOA'), scenario_model.intervals.get_entry('annual'), 'ml') # data = np.array([[[3.]], [[5.]], [[1.]]], dtype=float) # scenario_model.add_data('raininess', data, [2010, 2011, 2012]) return scenario_model
def get_scenario_model_object(): scenario_model = ScenarioModel('test_scenario_model') scenario_model.add_output('raininess', scenario_model.regions.get_entry('LSOA'), scenario_model.intervals.get_entry('annual'), 'ml') scenario_model.scenario_set = 'raininess' return scenario_model
def test_dependency_not_present(self, get_sector_model): SectorModel = get_sector_model elec_scenario = ScenarioModel('scenario') elec_scenario.add_output('output', Mock(), Mock(), 'unit') energy_model = SectorModel('model') energy_model.add_input('input', Mock(), Mock(), 'unit') with raises(ValueError): energy_model.add_dependency(elec_scenario, 'not_present', 'input') with raises(ValueError): energy_model.add_dependency(elec_scenario, 'output', 'not_correct_input_name')
def test_nested_graph(self, get_sector_model): """If we add a nested model, all Sectormodel and ScenarioModel objects are added as nodes in the graph with edges along dependencies. SosModel objects are not included, as they are just containers for the SectorModel and ScenarioModel objects, passing up inputs for deferred linkages to dependencies. Not implemented yet: """ SectorModel = get_sector_model energy_model = SectorModel('energy_sector_model') input_metadata = { 'name': 'electricity_demand_input', 'spatial_resolution': Mock(), 'temporal_resolution': Mock(), 'units': 'unit' } energy_model._model_inputs = MetadataSet([input_metadata]) sos_model_lo = SosModel('lower') sos_model_lo.add_model(energy_model) sos_model_high = SosModel('higher') sos_model_high.add_model(sos_model_lo) with raises(NotImplementedError): sos_model_high.check_dependencies() graph = sos_model_high.dependency_graph assert graph.edges() == [] expected = networkx.DiGraph() expected.add_node(sos_model_lo) expected.add_node(energy_model) assert energy_model in graph.nodes() scenario = ScenarioModel('electricity_demand') scenario.add_output('elec_demand_output', Mock(), Mock(), 'kWh') sos_model_high.add_dependency(scenario, 'elec_demand_output', 'electricity_demand_input') sos_model_high.check_dependencies() assert graph.edges() == [(scenario, sos_model_high)]
def load_scenario_models(self, scenario_list, scenario_data, timesteps): """Loads the scenario models into the system-of-systems model Note that we currently use the same name for the scenario name, and the name of the output of the ScenarioModel. Arguments --------- scenario_list : list A list of dicts with keys:: 'name': 'mass', 'spatial_resolution': 'country', 'temporal_resolution': 'seasonal', 'units': 'kg' scenario_data : dict A dict-of-list-of-dicts with keys ``param_name``: ``year``, ``region``, ``interval``, ``value`` timesteps : list Example ------- >>> builder = SosModelBuilder('test_sos_model') >>> model_list = [{'name': 'mass', 'spatial_resolution': 'country', 'temporal_resolution': 'seasonal', 'units': 'kg'}] >>> data = {'mass': [{'year': 2015, 'region': 'GB', 'interval': 'wet_season', 'value': 3}]} >>> timesteps = [2015, 2016] >>> builder.load_scenario_models(model_list, data, timesteps) """ self.logger.info("Loading scenarios") for scenario_meta in scenario_list: name = scenario_meta['name'] if name not in scenario_data: msg = "Parameter '{}' in scenario definitions not registered in scenario data" raise ValueError(msg.format(name)) scenario = ScenarioModel(name) spatial = scenario_meta['spatial_resolution'] temporal = scenario_meta['temporal_resolution'] spatial_res = self.region_register.get_entry(spatial) temporal_res = self.interval_register.get_entry(temporal) scenario.add_output(name, spatial_res, temporal_res, scenario_meta['units']) data = self._data_list_to_array(name, scenario_data[name], timesteps, spatial_res, temporal_res) scenario.add_data(data, timesteps) self.sos_model.add_model(scenario)
def get_scenario(): scenario = ScenarioModel('electricity_demand_scenario') scenario.add_output('electricity_demand_output', scenario.regions.get_entry('LSOA'), scenario.intervals.get_entry('annual'), 'unit') scenario.add_data(np.array([[[123]]]), [2010]) return scenario
def test_topological_sort(self, get_sector_model): regions = Mock() regions.name = 'test_regions' intervals = Mock() intervals.name = 'test_intervals' SectorModel = get_sector_model elec_scenario = ScenarioModel('scenario') elec_scenario.add_output('output', regions, intervals, 'unit') energy_model = SectorModel('model') energy_model.add_input('input', regions, intervals, 'unit') energy_model.add_dependency(elec_scenario, 'output', 'input') sos_model = SosModel('energy_sos_model') sos_model.add_model(energy_model) sos_model.add_model(elec_scenario) sos_model.check_dependencies() graph = sos_model.dependency_graph actual = list(networkx.topological_sort(graph)) assert actual == [elec_scenario, energy_model]
def test_model_set(self): elec_scenario = ScenarioModel('scenario') elec_scenario.add_output('output', elec_scenario.regions.get_entry('LSOA'), elec_scenario.intervals.get_entry('annual'), 'unit') elec_scenario.add_data(np.array([[[123]]]), [2010]) model_set = ModelSet([elec_scenario]) model_set.simulate(2010)
def test_serialise_scenario_two_outputs(self): scenario_model = ScenarioModel('High Population (ONS)') scenario_model.add_output('population_count', scenario_model.regions.get_entry('LSOA'), scenario_model.intervals.get_entry('annual'), 'people') scenario_model.add_output('population_density', scenario_model.regions.get_entry('LSOA'), scenario_model.intervals.get_entry('annual'), 'people/km^2') scenario_model.description = 'The High ONS Forecast for UK population out to 2050' scenario_model.scenario_set = 'population' actual = scenario_model.as_dict() # sort to match expected output actual['parameters'].sort(key=lambda p: p['name']) expected = { 'name': 'High Population (ONS)', 'description': 'The High ONS Forecast for UK population out to 2050', 'scenario_set': 'population', 'parameters': [{ 'name': 'population_count', 'spatial_resolution': 'LSOA', 'temporal_resolution': 'annual', 'units': 'people' }, { 'name': 'population_density', 'spatial_resolution': 'LSOA', 'temporal_resolution': 'annual', 'units': 'people/km^2' }] } assert actual == expected
def test_scenario_dependencies(self): scenario_model = ScenarioModel('test_scenario') scenario_model.add_output('scenario_output', Mock(), Mock(), 'units') data = np.array([[[120.23]]]) timesteps = [2010] scenario_model.add_data(data, timesteps) model = EmptySectorModel('test_model') model.add_input('input_name', Mock(), Mock(), 'units') model.add_dependency(scenario_model, 'scenario_output', 'input_name') assert 'input_name' in model.deps assert model.get_scenario_data('input_name') == data
def test_topological_sort(self, get_sector_model): SectorModel = get_sector_model elec_scenario = ScenarioModel('scenario') elec_scenario.add_output('output', Mock(), Mock(), 'unit') elec_scenario.add_data(np.array([[[123]]]), [2010]) energy_model = SectorModel('model') energy_model.add_input('input', Mock(), Mock(), 'unit') energy_model.add_dependency(elec_scenario, 'output', 'input') sos_model = SosModel('energy_sos_model') sos_model.add_model(energy_model) sos_model.add_model(elec_scenario) sos_model.check_dependencies() graph = sos_model.dependency_graph actual = networkx.topological_sort(graph, reverse=False) assert actual == [elec_scenario, energy_model]
def test_simple_graph(self, get_sector_model): SectorModel = get_sector_model elec_scenario = ScenarioModel('scenario') elec_scenario.add_output('output', Mock(), Mock(), 'unit') elec_scenario.add_data(np.array([[[123]]]), [2010]) energy_model = SectorModel('model') energy_model.add_input('input', Mock(), Mock(), 'unit') energy_model.add_dependency(elec_scenario, 'output', 'input') sos_model = SosModel('energy_sos_model') sos_model.add_model(energy_model) sos_model.add_model(elec_scenario) # Builds the dependency graph sos_model.check_dependencies() graph = sos_model.dependency_graph assert energy_model in graph assert elec_scenario in graph assert graph.edges() == [(elec_scenario, energy_model)]
def test_get_model_sets(self, get_sector_model): SectorModel = get_sector_model elec_scenario = ScenarioModel('scenario') elec_scenario.add_output('output', Mock(), Mock(), 'unit') elec_scenario.add_data(np.array([[[123]]]), [2010]) energy_model = SectorModel('model') energy_model.add_input('input', Mock(), Mock(), 'unit') energy_model.add_dependency(elec_scenario, 'output', 'input') sos_model = SosModel('energy_sos_model') sos_model.add_model(energy_model) sos_model.add_model(elec_scenario) sos_model.check_dependencies() actual = sos_model._get_model_sets_in_run_order() expected = ['scenario', 'model'] for model, name in zip(actual, expected): assert model.name == name
def test_composite_nested_sos_model(self, get_sector_model): """System of systems example with two nested SosModels, two Scenarios and one SectorModel. One dependency is defined at the SectorModel level, another at the lower SosModel level """ SectorModel = get_sector_model elec_scenario = ScenarioModel('electricity_demand_scenario') elec_scenario.add_output('electricity_demand_output', Mock(), Mock(), 'unit') energy_model = SectorModel('energy_sector_model') energy_model.add_input( 'electricity_demand_input', Mock(), Mock(), 'unit') energy_model.add_input('fluffiness_input', Mock(), Mock(), 'unit') energy_model.add_output('cost', Mock(), Mock(), 'unit') energy_model.add_output('fluffyness', Mock(), Mock(), 'unit') def energy_function(timestep, input_data): """Mimics the running of a sector model """ results = {} demand = input_data['electricity_demand_input'] fluff = input_data['fluffiness_input'] results['cost'] = demand * 1.2894 results['fluffyness'] = fluff * 22 return results energy_model.simulate = energy_function energy_model.add_dependency(elec_scenario, 'electricity_demand_output', 'electricity_demand_input') sos_model_lo = SosModel('lower') sos_model_lo.add_model(elec_scenario) sos_model_lo.add_model(energy_model) fluf_scenario = ScenarioModel('fluffiness_scenario') fluf_scenario.add_output('fluffiness', Mock(), Mock(), 'unit') # fluf_scenario.add_data('fluffiness', np.array([[[12]]]), [2010]) assert sos_model_lo.free_inputs.names == ['fluffiness_input'] sos_model_lo.add_dependency(fluf_scenario, 'fluffiness', 'fluffiness_input') assert sos_model_lo.inputs.names == [] sos_model_high = SosModel('higher') sos_model_high.add_model(sos_model_lo) sos_model_high.add_model(fluf_scenario) data_handle = get_data_handle(sos_model_high) actual = sos_model_high.simulate(data_handle) expected = { 'fluffiness_scenario': { 'fluffiness': 12 }, 'lower': { 'electricity_demand_scenario': { 'electricity_demand_output': 123 }, 'energy_sector_model': { 'cost': 158.5962, 'fluffyness': 264 } } } assert actual == expected