smif.decision.decision module

The decision module handles the three planning levels

Currently, only pre-specified planning is implemented.

The choices made in the three planning levels influence the set of interventions and assets available within a model run.

The interventions available in a model run are stored in a dict keyed by name.

Summary

Classes:

DecisionManager A DecisionManager is initialised with one or more model run strategies that refer to DecisionModules such as pre-specified planning, a rule-based models or multi-objective optimisation.
DecisionModule Abstract class which provides the interface to user defined decision modules.
PreSpecified Pre-specified planning
RuleBased Rule-base decision modules

Reference

class smif.decision.decision.DecisionManager(store, timesteps, modelrun_name, sos_model)[source]

Bases: object

A DecisionManager is initialised with one or more model run strategies that refer to DecisionModules such as pre-specified planning, a rule-based models or multi-objective optimisation. These implementations influence the combination and ordering of decision iterations and model timesteps that need to be performed by the model runner.

The DecisionManager presents a simple decision loop interface to the model runner, in the form of a generator which allows the model runner to iterate over the collection of independent simulations required at each step.

The DecisionManager collates the output of the decision algorithms and writes the post-decision state through a ResultsHandle. This allows Models to access a given decision state (identified uniquely by timestep and decision iteration id).

The get_decisions() method passes a ResultsHandle down to a DecisionModule, allowing the DecisionModule to access model results from previous timesteps and decision iterations when making decisions

Parameters:store (smif.data_layer.store.Store) –
available_interventions

Returns a register of available interventions, i.e. those not planned

get_intervention(value)[source]
decision_loop()[source]

Generate bundles of simulation steps to run

Each call to this method returns a dict:

{

‘decision_iterations’: list of decision iterations (int), ‘timesteps’: list of timesteps (int), ‘decision_links’: (optional) dict of {

decision iteration in current bundle: decision iteration of previous bundle

}

}

A bundle is composed differently according to the implementation of the contained DecisionModule. For example:

With only pre-specified planning, there is a single step in the loop, with a single decision iteration with timesteps covering the entire model horizon.

With a rule based approach, there might be many steps in the loop, each with a single decision iteration and single timestep, moving on once some threshold is satisfied.

With a genetic algorithm, there might be a configurable number of steps in the loop, each with multiple decision iterations (one for each member of the algorithm’s population) and timesteps covering the entire model horizon.

Implicitly, if the bundle returned in an iteration contains multiple decision iterations, they can be performed in parallel. If each decision iteration contains multiple timesteps, they can also be parallelised, so long as there are no temporal dependencies.

Decision links are only required if the bundle timesteps do not start from the first timestep of the model horizon.

get_and_save_decisions(iteration, timestep)[source]

Retrieves decisions for given timestep and decision iteration from each decision module and writes them to the store as state.

Calls each contained DecisionModule for the given timestep and decision iteration in the data_handle, retrieving a list of decision dicts (keyed by intervention name and build year).

These decisions are then written to a state file using the data store.

Parameters:
  • timestep (int) –
  • iteration (int) –
class smif.decision.decision.DecisionModule(timesteps, register)[source]

Bases: object

Abstract class which provides the interface to user defined decision modules.

These mechanisms could include a Rule-based Approach or Multi-objective Optimisation.

This class provides two main methods, __next__ which is normally called implicitly as a call to the class as an iterator, and get_decision() which takes as arguments a smif.data_layer.data_handle.ResultsHandle object.

Parameters:
  • timesteps (list) – A list of planning timesteps
  • register (dict) – Reference to a dict of iterventions
interventions

Return the list of available interventions

Returns:
Return type:list
get_intervention(name)[source]

Return an intervention dict

Returns:
Return type:dict
get_decision(results_handle)[source]

Return decisions for a given timestep and decision iteration

Parameters:results_handle (smif.data_layer.data_handle.ResultsHandle) –
Returns:
Return type:list of dict

Examples

>>> register = {'intervention_a': {'capital_cost': {'value': 1234}}}
>>> dm = DecisionModule([2010, 2015], register)
>>> dm.get_decision(results_handle)
[{'name': 'intervention_a', 'build_year': 2010}])
class smif.decision.decision.PreSpecified(timesteps, register, planned_interventions)[source]

Bases: smif.decision.decision.DecisionModule

Pre-specified planning

Parameters:
  • timesteps (list) – A list of the timesteps included in the model horizon
  • register (dict) – A dict of intervention dictionaries keyed by unique intervention name
  • planned_interventions (list) – A list of dicts {'name': 'intervention_name', 'build_year': 2010} representing historical or planned interventions
get_decision(results_handle)[source]

Return a dict of intervention names built in timestep

Parameters:results_handle (smif.data_layer.data_handle.ResultsHandle) – A reference to a smif results handle
Returns:
Return type:list of dict

Examples

>>> dm = PreSpecified([2010, 2015], register,
[{'name': 'intervention_a', 'build_year': 2010}])
>>> dm.get_decision(results_handle)
[{'name': intervention_a', 'build_year': 2010}]
buildable(build_year, timestep)[source]

Interventions are deemed available if build_year is less than next timestep

For example, if a is built in 2011 and timesteps are [2005, 2010, 2015, 2020] then buildable returns True for timesteps 2010, 2015 and 2020 and False for 2005.

within_lifetime(build_year, timestep, lifetime)[source]

Interventions are deemed active if build_year + lifetime >= timestep

Parameters:
  • build_year (int) –
  • timestep (int) –
  • lifetime (int) –
class smif.decision.decision.RuleBased(timesteps, register)[source]

Bases: smif.decision.decision.DecisionModule

Rule-base decision modules

next_timestep
previous_timestep
first_timestep
last_timestep
get_decision(results_handle)[source]

Return decisions for a given timestep and decision iteration

Parameters:results_handle (smif.data_layer.data_handle.ResultsHandle) –
Returns:
Return type:list of dict

Examples

>>> register = {'intervention_a': {'capital_cost': {'value': 1234}}}
>>> dm = DecisionModule([2010, 2015], register)
>>> dm.get_decision(results_handle)
[{'name': 'intervention_a', 'build_year': 2010}])