Uncertainties

Because WDNs are subject to many different types of uncertainties, EPyT-Flow comes with a set of pre-defined and implemented uncertainties that allow the user to introduce uncertainties and noise in the scenario generation.

Most types of uncertainty exist in two versions: absolute and relative. While absolute uncertainties usually refer to the addition of noise that follows some distribution, relative uncertainties usually refer to some kind of multiplication. A complete list of pre-defined and implemented uncertainties is given in the following table:

Implementation

Description

AbsoluteGaussianUncertainty

Gaussian noise is added.

RelativeGaussianUncertainty

Gaussian noise centered at zero is added.

AbsoluteUniformUncertainty

Uniform noise is added.

RelativeUniformUncertainty

Data is multiplied by uniform noise.

PercentageDeviationUncertainty

Data can deviate up to some percentage from its original value.

AbsoluteDeepUniformUncertainty

Uniform noise (changing over time) is added.

RelativeDeepUniformUncertainty

Data is multiplied by uniform noise that is changing over time.

AbsoluteDeepGaussianUncertainty

Gaussian noise (changing over time) is added.

RelativeDeepGaussianUncertainty

Gaussian noise (changing over time) centered add zero is added.

AbsoluteDeepUncertainty

Random pattern/noise (chaning over time) is added.

RelativeDeepUncertainty

Data is multiplied by random pattern/noise (chaning over time).

Note

A custom type of uncertainty can be implemented by deriving a sub-class from Uncertainty.

Model Uncertainty

Model uncertainty refers to uncertainties in the WDN model – i.e. uncertainties in pipe lengths, pipe diameters, base demands, demand patterns, etc.

EPyT-Flow allows the user to specify model uncertainties by instantiating ModelUncertainty. This instance can then be passed to the scenario simulator (instance of ScenarioSimulator) by calling set_model_uncertainty() BEFORE the simulation is run. Note that by default, uncertainties are only applied once even if the simulation is run multiple times. If the parameter reapply_uncertainties (in the run_simulation() function) is set to True, the uncertainties are re-applied to the original properties before every simulation run. As a consequence, the simulation runs might no longer be deterministic.

See below for a full list of all quantities that can be affected by uncertainties:

Quantities that can be affected by uncertainties

Node elevation

Pipe length

Pipe diameter

Pipe roughness coefficient

Base demand

Demand pattern

EPANET-MSX constants

EPANET-MSX parameters

Note

For the purpose of ensuring reproducibility, the ModelUncertainty class has an optional seed parameter which makes the uncertainty (i.e. random number generations) deterministic and therefore reproducible.

Uncertainties can be either on a global or local level. In global uncertainties, a specific quantity (e.g. pipe length) is always affected by the same uncertainty – e.g. all pipe’s length are affected by the same uncertainty. On the other hand, local uncertainties allow to specify the uncertainties for each element and quantity separately – e.g. only a sub-set of pipes is affected by some uncertainty, also, the type and magnitude of uncertainty could vary between the pipes.

Example of setting global pipe length, and demand pattern uncertainty – in both cases the global uncertainty corresponds to a uniform deviation of up to 10%:

# Open/Create a new scenario based on the Hanoi network
network_config = load_hanoi()
with ScenarioSimulator(scenario_config=network_config) as sim:
    # Specify pipe length and demand pattern uncertainty
    uncertainty = PercentageDeviationUncertainty(deviation_percentage=.1)
    model_uncertainty = ModelUncertainty(global_pipe_length_uncertainty=uncertainty,
                                         global_demand_pattern_uncertainty=uncertainty)
    sim.set_model_uncertainty(model_uncertainty)

    # Run the simulation
    # ...

Sensor Uncertainty

Sensor uncertainty (also referred to as sensor noise) can either act on a global level – i.e. all sensor readings are perturbed by the given uncertainty –, or on a local level by just affecting a sub-set of sensors. In EPyT-Flow, sensor uncertainties have to be Uncertainty instances wrapped inside a SensorNoise instance.

Note

For the purpose of ensuring reproducibility, the SensorNoise class has an optional seed parameter which makes the uncertainty (random number generations) deterministic and therefore reproducible.

Sensor uncertainty/noise can be added BEFORE the simulation is run by calling set_sensor_noise() of a ScenarioSimulator instance.

Example setting a global Gaussian uncertainty BEFORE the simulation is run:

# Open/Create a new scenario based on the Hanoi network
network_config = load_hanoi()
with ScenarioSimulator(scenario_config=network_config) as sim:
    # Sensor readings are affected by relative Gaussian uncertainty with scale=1
    uncertainty = RelativeGaussianUncertainty(scale=1.)
    sim.set_sensor_noise(SensorNoise(global_uncertainty=uncertainty))

    # Run simulation
    # ....

AFTERWARDS, the sensor uncertainty/noise can be set or changed by calling change_sensor_noise() of a ScadaData instance.

Example of setting/changing a global sensor uniform deviation uncertainty AFTER the simulation was run:

# Load scenario
# ...

# Run simulation
scada_data = sim.run_simulation()

# Sensor readings deviate (uniformly) up to 10% from their original value
uncertainty = PercentageDeviationUncertainty(deviation_percentage=.1)
scada_data.change_sensor_noise(SensorNoise(global_uncertainty=uncertainty))