smif.model package

Submodules

smif.model.dependency module

class smif.model.dependency.Dependency(source_model, source, function=None)[source]

Bases: object

Parameters:
  • source_model (smif.composite.Model) – The source model object
  • source (smif.metadata.Metadata) – The source parameter (output) object
  • function=None (func) – A conversion function
convert(data, model_input)[source]
get_data(timestep, model_input)[source]

smif.model.model_set module

Wrap and solve a set of interdependent models

Given a directed graph of dependencies between models, any cyclic dependencies are contained within the strongly-connected components of the graph.

A ModelSet corresponds to the set of models within a single strongly- connected component. This class provides the machinery necessary to find a solution to each of the interdependent models.

The current implementation first estimates the outputs for each model in the set, guaranteeing that each model will then be able to run, then begins iterating, running every model in the set at each iteration, monitoring the model outputs over the iterations, and stopping at timeout, divergence or convergence.

class smif.model.model_set.ModelSet(models, max_iterations=25, relative_tolerance=1e-05, absolute_tolerance=1e-08)[source]

Bases: smif.model.Model

Wraps a set of interdependent models

Parameters:
  • models (list) – A list of smif.model.composite.Model
  • max_iterations (int, default=25) – The maximum number of iterations that the model set will run before returning results
  • relative_tolerance (float, default=1e-05) – Used to calculate when the model interations have converged
  • absolute_tolerance (float, default=1e-08) – Used to calculate when the model interations have converged
converged()[source]

Check whether the results of a set of models have converged.

Returns:converged – True if the results have converged to within a tolerance
Return type:bool
Raises:DiverganceError – If the results appear to be diverging
get_last_iteration_results()[source]

Return results from the last iteration

Returns:results – Dictionary of Model results, keyed by model name
Return type:dict
guess_results(model, timestep, data)[source]

Dependency-free guess at a model’s result set.

Initially, guess zeroes, or the previous timestep’s results.

Parameters:
  • model (smif.model.composite.Model) –
  • timestep (int) –
  • data (dict) –
Returns:

results

Return type:

dict

simulate(timestep, data=None)[source]

Runs a set of one or more models

Parameters:
  • timestep (int) –
  • data (dict, default=None) –

smif.model.scenario_model module

class smif.model.scenario_model.ScenarioModel(name, output=None)[source]

Bases: smif.model.Model

Represents exogenous scenario data

Parameters:
  • name (string) – The unique name of this scenario
  • output (smif.metadata.MetaData) – A name for the scenario output parameter
add_data(data, timesteps)[source]

Add data to the scenario

Parameters:

Example

>>> elec_scenario = ScenarioModel('elec_scenario')
>>> data = np.array([[[120.23]]])
>>> timesteps = [2010]
>>> elec_scenario.add_data(data, timesteps)
add_output(name, spatial_resolution, temporal_resolution, units)[source]

Add an output to the scenario model

Parameters:
simulate(timestep, data=None)[source]

Returns the scenario data

smif.model.sector_model module

This module acts as a bridge to the sector models from the controller

The SectorModel exposes several key methods for running wrapped sector models. To add a sector model to an instance of the framework, first implement SectorModel.

Key Functions

This class performs several key functions which ease the integration of sector models into the system-of-systems framework.

The user must implement the various abstract functions throughout the class to provide an interface to the sector model, which can be called upon by the framework. From the model’s perspective, SectorModel provides a bridge from the sector-specific problem representation to the general representation which allows reasoning across infrastructure systems.

The key functions include

  • converting input/outputs to/from geographies/temporal resolutions
  • converting control vectors from the decision layer of the framework, to asset Interventions specific to the sector model
  • returning scaler/vector values to the framework to enable measurements of performance, particularly for the purposes of optimisation and rule-based approaches
class smif.model.sector_model.SectorModel(name)[source]

Bases: smif.model.Model

A representation of the sector model with inputs and outputs

Parameters:name (str) – The unique name of the sector model
add_input(name, spatial_resolution, temporal_resolution, units)[source]

Add an input to the sector model

The inputs should be specified in a list. For example:

- name: electricity_price
  spatial_resolution: GB
  temporal_resolution: annual
  units: £/kWh
Parameters:
add_output(name, spatial_resolution, temporal_resolution, units)[source]

Add an output to the sector model

Parameters:
extract_obj(results)[source]

Implement this method to return a scalar value objective function

This method should take the results from the output of the simulate() method, process the results, and return a scalar value which can be used as a component of the objective function by the decision layer

Parameters:results (dict) – A nested dict of the results from the simulate() method
Returns:A scalar component generated from the simulation model results
Return type:float
initialise(initial_conditions)[source]

Implement this method to set up the model system

Parameters:initial_conditions (list) – A list of past Interventions, with build dates and locations as necessary to specify the infrastructure system to be modelled.
intervention_names

The names of the interventions

Returns:A list of the names of the interventions
Return type:list
simulate(timestep, data=None)[source]

Implement this method to run the model

Parameters:
  • timestep (int) – The timestep for which to run the SectorModel
  • data (dict) –
Returns:

results – This method should return a results dictionary

Return type:

dict

Notes

In the results returned from the simulate() method:

interval
should reference an id from the interval set corresponding to the output parameter, as specified in model configuration
region
should reference a region name from the region set corresponding to the output parameter, as specified in model configuration
validate()[source]

Validate that this SectorModel has been set up with sufficient data to run

class smif.model.sector_model.SectorModelBuilder(name, sector_model=None)[source]

Bases: object

Build the components that make up a sectormodel from the configuration

Parameters:
  • name (str) – The name of the sector model
  • sector_model (smif.model.SectorModel, default=None) – The sector model object
Returns:

Return type:

SectorModel

Examples

Call SectorModelBuilder.construct() to populate a SectorModel object and SectorModelBuilder.finish() to return the validated and dependency-checked system-of-systems model.

>>> builder = SectorModelBuilder(name, secctor_model)
>>> builder.construct(config_data)
>>> sos_model = builder.finish()
add_inputs(input_dicts)[source]

Add inputs to the sector model

add_interventions(intervention_list)[source]

Add interventions to the sector model

Parameters:intervention_list (list) – A list of dicts of interventions
add_outputs(output_dicts)[source]

Add outputs to the sector model

construct(model_data)[source]

Constructs the sector model

Parameters:model_data (dict) – The sector model configuration data
create_initial_system(initial_conditions)[source]

Set up model with initial system

finish()[source]

Validate and return the sector model

load_model(model_path, classname)[source]

Dynamically load model module

Parameters:
  • model_path (str) – The path to the python module which contains the SectorModel implementation
  • classname (str) – The name of the class of the SectorModel implementation
validate()[source]

Check and/or assert that the sector model is correctly set up - should raise errors if invalid

smif.model.sos_model module

This module coordinates the software components that make up the integration framework.

class smif.model.sos_model.RunMode[source]

Bases: enum.Enum

Enumerates the operating modes of a SoS model

dynamic_optimisation = 3
sequential_simulation = 1
static_optimisation = 2
static_simulation = 0
class smif.model.sos_model.SosModel(name)[source]

Bases: smif.model.Model

Consists of the collection of models joined via dependencies

This class is populated at runtime by the SosModelBuilder and called from smif.cli.run_model(). SosModel inherits from smif.composite.Model.

Parameters:name (str) – The unique name of the SosModel
add_model(model)[source]

Adds a sector model to the system-of-systems model

Parameters:model (smif.sector_model.SectorModel) – A sector model wrapper
check_dependencies()[source]

For each contained model, compare dependency list against list of available models and build the dependency graph

determine_running_mode()[source]

Determines from the config in what mode to run the model

Returns:The mode in which to run the model
Return type:RunMode
free_inputs

Returns the free inputs not linked to a dependency at this layer

For this composite Model this includes the free_inputs from all contained Model objects

Free inputs are passed up to higher layers for deferred linkages to dependencies.

Returns:
Return type:smif.metadata.MetadataSet
get_decisions(model, timestep)[source]

Gets the interventions that correspond to the decisions

Parameters:
  • model (smif.sector_model.SectorModel) – The instance of the sector model wrapper to run
  • timestep (int) – The current model year
  • TODO (Move into DecisionManager class) –
get_state(model, timestep)[source]

Gets the state to pass to SectorModel.simulate

intervention_names

Names (id-like keys) of all known asset type

results

Get nested dict of model results

Returns:Nested dictionary in the format results[str:model][str:parameter]
Return type:dict
scenario_models

The list of scenario model names

Returns:A list of scenario model names
Return type:list
sector_models

The list of sector model names

Returns:A list of sector model names
Return type:list
set_data(model, timestep, results)[source]

Sets results output from model as data available to other/future models

Stores only latest estimated results (i.e. not holding on to iterations here while trying to solve interdependencies)

set_state(model, from_timestep, state)[source]

Sets state output from model ready for next timestep

simulate(timestep, data=None)[source]

Run the SosModel

timestep_after(timestep)[source]

Returns the timestep after a given timestep, or None

Parameters:timestep (str) –
Returns:
Return type:str
timestep_before(timestep)[source]

Returns the timestep previous to a given timestep, or None

Parameters:timestep (str) –
Returns:
Return type:str
class smif.model.sos_model.SosModelBuilder(name='')[source]

Bases: object

Constructs a system-of-systems model

Builds a SosModel.

Parameters:name (str, default='') – The unique name of the SosModel

Examples

Call SosModelBuilder.construct() to populate a SosModel object and SosModelBuilder.finish() to return the validated and dependency-checked system-of-systems model.

>>> builder = SosModelBuilder('test_model')
>>> builder.construct(config_data, timesteps)
>>> sos_model = builder.finish()
add_dependencies(dependency_list)[source]

Add dependencies between models

Parameters:dependency_list (list) – A list of dicts of dependency configuration data

Examples

>>> dependencies = [{'source_model': 'raininess',
                     'source_model_output': 'raininess',
                     'sink_model': 'water_supply',
                     'sink_model_input': 'raininess'}]
>>> builder.add_dependencies(dependencies)
add_initial_conditions(model_name, initial_conditions)[source]

Adds initial conditions (state) for a model

add_interventions(model_name, interventions)[source]

Adds interventions for a model

add_model_data(model, model_data)[source]

Adds sector model data to the system-of-systems model which is convenient to have available at the higher level.

add_planning(planning)[source]

Loads the planning logic into the system of systems model

Pre-specified planning interventions are defined at the sector-model level, read in through the SectorModel class, but populate the intervention register in the controller.

Parameters:planning (list) – A list of planning instructions
construct(config_data, timesteps)[source]

Set up the whole SosModel

Parameters:
  • config_data (dict) – A valid system-of-systems model configuration dictionary
  • timesteps (list) – A list of timestep integers
finish()[source]

Returns a configured system-of-systems model ready for operation

Includes validation steps, e.g. to check dependencies

static intervention_state_from_data(intervention_data)[source]

Unpack an intervention from the initial system to extract StateData

load_models(model_data_list)[source]

Loads the sector models into the system-of-systems model

Parameters:
  • model_data_list (list) – A list of sector model config/data
  • assets (list) – A list of assets to pass to the sector model
load_scenario_models(scenario_list, scenario_data, timesteps)[source]

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.

Parameters:
  • 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)
set_convergence_abs_tolerance(config_data)[source]

Set the absolute tolerance for iterating class::smif.ModelSet to convergence

set_convergence_rel_tolerance(config_data)[source]

Set the relative tolerance for iterating class::smif.ModelSet to convergence

set_max_iterations(config_data)[source]

Set the maximum iterations for iterating class::smif.ModelSet to convergence

Module contents

Implements a composite scenario/sector model/system-of-systems model

Begin by declaring the atomic units (scenarios and sector models) which make up a the composite system-of-systems model and then add these to the composite. Declare dependencies by using the add_dependency() method, passing in a reference to the source model object, and a pointer to the model output and sink parameter name for the destination model.

Run the model by calling the simulate() method, passing in a dictionary containing data for any free hanging model inputs, not linked through a dependency. A fully defined SosModel should have no hanging model inputs, and can therefore be called using simulate() with no arguments.

Responsibility for passing required data to the contained models lies with the calling class. This means data is only ever passed one layer down. This simplifies the interface, and allows as little or as much hiding of data, dependencies and model inputs as required.

Example

A very simple example with just one scenario:

>>> elec_scenario = ScenarioModel('scenario', ['demand'])
>>> elec_scenario.add_data({'demand': 123})
>>> sos_model = SosModel('simple')
>>> sos_model.add_model(elec_scenario)
>>> sos_model.simulate()
{'scenario': {'demand': 123}}

A more comprehensive example with one scenario and one scenario model:

>>>  elec_scenario = ScenarioModel('scenario', ['output'])
>>>  elec_scenario.add_data({'output': 123})
>>>  energy_model = SectorModel('model', [], [])
>>>  energy_model.add_input('input')
>>>  energy_model.add_dependency(elec_scenario, 'output', 'input')
>>>  energy_model.add_executable(lambda x: x)
>>>  sos_model = SosModel('blobby')
>>>  sos_model.add_model(elec_scenario)
>>>  sos_model.add_model(energy_model)
>>>  sos_model.simulate()
{'model': {'input': 123}, 'scenario': {'output': 123}}
class smif.model.Model(name)[source]

Bases: abc.ABC

Abstract class represents the interface used to implement the composite SosModel and leaf classes SectorModel and Scenario.

Parameters:
  • name (str) –
  • inputs (smif.metadata.MetaDataSet) –
  • outputs (smif.metadata.MetaDataSet) –
add_dependency(source_model, source, sink, function=None)[source]

Adds a dependency to the current Model object

Parameters:
  • source_model (smif.composite.Model) – A reference to the source ~smif.composite.Model object
  • source (string) – The name of the model_output defined in the source_model
  • sink (string) – The name of a model_input defined in this object
free_inputs

Returns the free inputs not linked to a dependency at this layer

Free inputs are passed up to higher layers for deferred linkages to dependencies.

Returns:
Return type:smif.metadata.MetadataSet
model_inputs

All model inputs defined at this layer

Returns:
Return type:smif.metadata.MetadataSet
model_outputs

All model outputs defined at this layer

Returns:
Return type:smif.metadata.MetadataSet
simulate(timestep, data=None)[source]
smif.model.element_after(element, list_)[source]

Return the element after a given element in a list, or None if the given element is last or not in the list.

smif.model.element_before(element, list_)[source]

Return the element before a given element in a list, or None if the given element is first or not in the list.