smif.decision package

Submodules

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.

class smif.decision.decision.DecisionManager(store: Store, timesteps: List[int], modelrun_name: str, sos_model, decision: int = 0)[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)

property available_interventions: Dict[str, Dict]

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

buildable(build_year, timestep) bool[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.

Parameters:
  • build_year (int) – The build year of the intervention

  • timestep (int) – The current timestep

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)

Notes

State contains all intervention names which are present in the system at the given timestep for the current iteration. This must include planned interventions from a previous timestep that are still within their lifetime, and interventions picked by a decision module in the previous timesteps.

After loading all historical interventions, and screening them to remove interventions from the previous timestep that have reached the end of their lifetime, new decisions are added to the list of current interventions.

Finally, the new state is written to the store.

get_intervention(value)[source]
retire_interventions(state: List[Tuple[int, str]], timestep: int) List[Tuple[int, str]][source]
static within_lifetime(build_year, timestep, lifetime) bool[source]

Interventions are deemed active if build_year + lifetime >= timestep

Parameters:
  • build_year (int)

  • timestep (int)

  • lifetime (int)

Return type:

bool

class smif.decision.decision.DecisionModule(timesteps: List[int], register: MappingProxyType)[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

available_interventions(state: List[Dict]) List[source]

Return the collection of available interventions

Available interventions are the subset of interventions that have not been implemented in a prior iteration or timestep

Return type:

List

property first_timestep: int
abstractmethod get_decision(results_handle: ResultsHandle) List[Dict][source]

Return decisions for a given timestep and decision iteration

Parameters:

results_handle (smif.data_layer.data_handle.ResultsHandle)

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}])
get_intervention(name)[source]

Return an intervention dict

Return type:

dict

abstractmethod get_previous_state(results_handle: ResultsHandle) List[Dict][source]

Return the state of the previous timestep

property last_timestep: int
class smif.decision.decision.RuleBased(timesteps, register)[source]

Bases: DecisionModule

Rule-base decision modules

get_decision(results_handle) List[Dict][source]

Return decisions for a given timestep and decision iteration

Parameters:

results_handle (smif.data_layer.data_handle.ResultsHandle)

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}])
get_previous_iteration_timestep() Tuple[int, int] | None[source]

Returns the timestep, iteration pair that describes the previous iteration

Returns:

Contains (timestep, iteration)

Return type:

tuple

get_previous_state(results_handle: ResultsHandle) List[Dict][source]

Return the state of the previous timestep

get_previous_year_iteration()[source]
property next_timestep
property previous_timestep