Optimiser

class saco.Optimiser(ds: Dataset, scenarios: List[str] = None, percentiles: List[int] = None, domain: List[str] = None, objectives: List[str] | str = None, solver: str = 'SCIPY', raise_external_hof_error: bool = False, primary_relaxation_factor: float = None, reference_dataset: Dataset = None, lta_base_percentile: int = 95, infeasible_targets_method: str = 'drop', constants: Constants = None)

For finding abstraction impact reductions that help to meet flow targets.

In most use cases, the steps needed to use the Optimiser are (code example below):

  • Prepare/load an input Dataset

  • Create an instance of this (the Optimiser) class

  • Execute the optimisation using the run method.

The run method obtains a solution via mixed integer (binary) linear programming and returns a Dataset augmented with required impact reductions (see below).

Parameters:
  • ds – Input Dataset.

  • scenarios – Names/abbreviations of artificial influences scenarios for which optimisation should be performed. If None (default) then taken from input_dataset.

  • percentiles – Flow percentiles (natural) for which optimisation should be performed. If None (default) then taken from input_dataset.

  • domain – List of waterbody IDs indicating domain/catchment to be optimised. If None (default) then all waterbodies in input_dataset will be included in the domain.

  • objectives – Sequence of objectives to use in optimisation. Current options are either ‘max-abstraction’ or [‘max-abstraction’, ‘max-point-equality’]. The latter is the default. See discussion above for a description of objectives.

  • solver – Solver name understood by cvxpy.

  • raise_external_hof_error – Whether to raise an error if the waterbody defining a HOF condition is located outside the domain. If False (default), it is assumed that the HOF condition is met (and it does not form an explicit constraint in the problem).

  • primary_relaxation_factor – If running with both objectives, this factor is used to relax the total abstraction constraint used when solving for the second objective (‘max-point-equality’). A value of 0.01 means that the constraint is relaxed by 1% of the maximum possible total abstraction. Default is not to apply any relaxation.

  • reference_dataset – Optional dataset to use as a reference against which to derive changes (i.e. for inference of required impact reductions after optimisation conducted). Default (None) is not to use this argument (and derive changes relative to input_dataset).

  • lta_base_percentile – Flow percentile (natural) to use when inferring long-term average abstraction (after optimisation complete).

  • infeasible_targets_method – Approach to use to infeasible flow targets: either ‘drop’ entirely or ‘relax’ to maximum feasible flow.

  • constants – Global constants defined by default in config.Constants.

Notes

A starting point for the input_dataset might be a Dataset comprising the WRGIS tables. Make any desired modifications to this (or some other) “base” Dataset before creating an instance of Optimiser. See Dataset documentation and examples.

It is currently recommended to run with the default objectives. These are to solve for maximum total abstraction in the domain first and then maximum equality of any proportional impact reductions second. The maximum total abstraction from solving for the first objective becomes a constraint when solving for the second objective. This constraint can be relaxed using the primary_relaxation_factor argument (see above).

Sometimes a flow target might be impossible meet. This can occur if some impacts are held constant (i.e. not available for the Optimiser to change). Currently, discharges (Discharges_NBB) and complex impacts (SupResGW_NBB) are held constant. A user may specify that certain rows in SWABS_NBB and GWABs_NBB should also be left alone. If a target cannot feasibly be met, by default the Optimiser drops the target and provides a warning to the user, so that they can reconsider the setup if need be. However, the infeasible_targets_method argument can also be changed to ‘relax’ to indicate that the Optimiser should try to hit the maximum feasible flow for any impossible targets.

Long-term average abstraction is recalculated after optimisation under the assumption that the relative impact profile across the FDC remains constant. However, SWABS with hands-off flow (HOF) conditions are omitted from the recalculation at present to avoid introducing a conservative bias into the estimates. See Dataset for more details.

Examples

>>> from saco import Dataset, Optimiser
>>>
>>> ds = Dataset(data_folder='/path/to/data/files')
>>> ds.load_data()
>>> ds.set_flow_targets()
>>> ds.set_optimise_flag()
>>>
>>> optimiser = Optimiser(ds)
>>> output_dataset = optimiser.run()
__init__(ds: Dataset, scenarios: List[str] = None, percentiles: List[int] = None, domain: List[str] = None, objectives: List[str] | str = None, solver: str = 'SCIPY', raise_external_hof_error: bool = False, primary_relaxation_factor: float = None, reference_dataset: Dataset = None, lta_base_percentile: int = 95, infeasible_targets_method: str = 'drop', constants: Constants = None)

Methods

run()

Formulate and solve optimisation problem.