epyt-flow 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +28 -0
  2. epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +21 -0
  3. epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +18 -0
  4. epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +134 -0
  5. epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +5578 -0
  6. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +865 -0
  7. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +131 -0
  8. epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +73 -0
  9. epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +193 -0
  10. epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +1000 -0
  11. epyt_flow/EPANET/EPANET/SRC_engines/hash.c +177 -0
  12. epyt_flow/EPANET/EPANET/SRC_engines/hash.h +28 -0
  13. epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +1151 -0
  14. epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +1117 -0
  15. epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +720 -0
  16. epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +476 -0
  17. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +431 -0
  18. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +1786 -0
  19. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +468 -0
  20. epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +810 -0
  21. epyt_flow/EPANET/EPANET/SRC_engines/input1.c +707 -0
  22. epyt_flow/EPANET/EPANET/SRC_engines/input2.c +864 -0
  23. epyt_flow/EPANET/EPANET/SRC_engines/input3.c +2170 -0
  24. epyt_flow/EPANET/EPANET/SRC_engines/main.c +93 -0
  25. epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +142 -0
  26. epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +24 -0
  27. epyt_flow/EPANET/EPANET/SRC_engines/output.c +852 -0
  28. epyt_flow/EPANET/EPANET/SRC_engines/project.c +1359 -0
  29. epyt_flow/EPANET/EPANET/SRC_engines/quality.c +685 -0
  30. epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +743 -0
  31. epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +694 -0
  32. epyt_flow/EPANET/EPANET/SRC_engines/report.c +1489 -0
  33. epyt_flow/EPANET/EPANET/SRC_engines/rules.c +1362 -0
  34. epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +871 -0
  35. epyt_flow/EPANET/EPANET/SRC_engines/text.h +497 -0
  36. epyt_flow/EPANET/EPANET/SRC_engines/types.h +874 -0
  37. epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +53 -0
  38. epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +27 -0
  39. epyt_flow/EPANET/EPANET-MSX/Src/hash.c +107 -0
  40. epyt_flow/EPANET/EPANET-MSX/Src/hash.h +28 -0
  41. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +102 -0
  42. epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +42 -0
  43. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +937 -0
  44. epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +39 -0
  45. epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +204 -0
  46. epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +24 -0
  47. epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +1285 -0
  48. epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +368 -0
  49. epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +42 -0
  50. epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +586 -0
  51. epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +116 -0
  52. epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +260 -0
  53. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +175 -0
  54. epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +35 -0
  55. epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +1504 -0
  56. epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +401 -0
  57. epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +791 -0
  58. epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +2010 -0
  59. epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +400 -0
  60. epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +422 -0
  61. epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +1164 -0
  62. epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +551 -0
  63. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +524 -0
  64. epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +56 -0
  65. epyt_flow/EPANET/EPANET-MSX/Src/newton.c +158 -0
  66. epyt_flow/EPANET/EPANET-MSX/Src/newton.h +34 -0
  67. epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +287 -0
  68. epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +39 -0
  69. epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +293 -0
  70. epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +35 -0
  71. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +816 -0
  72. epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +29 -0
  73. epyt_flow/EPANET/EPANET-MSX/readme.txt +14 -0
  74. epyt_flow/EPANET/compile.sh +4 -0
  75. epyt_flow/VERSION +1 -0
  76. epyt_flow/__init__.py +24 -0
  77. epyt_flow/data/__init__.py +0 -0
  78. epyt_flow/data/benchmarks/__init__.py +11 -0
  79. epyt_flow/data/benchmarks/batadal.py +257 -0
  80. epyt_flow/data/benchmarks/batadal_data.py +28 -0
  81. epyt_flow/data/benchmarks/battledim.py +473 -0
  82. epyt_flow/data/benchmarks/battledim_data.py +51 -0
  83. epyt_flow/data/benchmarks/gecco_water_quality.py +267 -0
  84. epyt_flow/data/benchmarks/leakdb.py +592 -0
  85. epyt_flow/data/benchmarks/leakdb_data.py +18923 -0
  86. epyt_flow/data/benchmarks/water_usage.py +123 -0
  87. epyt_flow/data/networks.py +650 -0
  88. epyt_flow/gym/__init__.py +4 -0
  89. epyt_flow/gym/control_gyms.py +47 -0
  90. epyt_flow/gym/scenario_control_env.py +101 -0
  91. epyt_flow/metrics.py +404 -0
  92. epyt_flow/models/__init__.py +2 -0
  93. epyt_flow/models/event_detector.py +31 -0
  94. epyt_flow/models/sensor_interpolation_detector.py +118 -0
  95. epyt_flow/rest_api/__init__.py +4 -0
  96. epyt_flow/rest_api/base_handler.py +70 -0
  97. epyt_flow/rest_api/res_manager.py +95 -0
  98. epyt_flow/rest_api/scada_data_handler.py +476 -0
  99. epyt_flow/rest_api/scenario_handler.py +352 -0
  100. epyt_flow/rest_api/server.py +106 -0
  101. epyt_flow/serialization.py +438 -0
  102. epyt_flow/simulation/__init__.py +5 -0
  103. epyt_flow/simulation/events/__init__.py +6 -0
  104. epyt_flow/simulation/events/actuator_events.py +259 -0
  105. epyt_flow/simulation/events/event.py +81 -0
  106. epyt_flow/simulation/events/leakages.py +404 -0
  107. epyt_flow/simulation/events/sensor_faults.py +267 -0
  108. epyt_flow/simulation/events/sensor_reading_attack.py +185 -0
  109. epyt_flow/simulation/events/sensor_reading_event.py +170 -0
  110. epyt_flow/simulation/events/system_event.py +88 -0
  111. epyt_flow/simulation/parallel_simulation.py +147 -0
  112. epyt_flow/simulation/scada/__init__.py +3 -0
  113. epyt_flow/simulation/scada/advanced_control.py +134 -0
  114. epyt_flow/simulation/scada/scada_data.py +1589 -0
  115. epyt_flow/simulation/scada/scada_data_export.py +255 -0
  116. epyt_flow/simulation/scenario_config.py +608 -0
  117. epyt_flow/simulation/scenario_simulator.py +1897 -0
  118. epyt_flow/simulation/scenario_visualizer.py +61 -0
  119. epyt_flow/simulation/sensor_config.py +1289 -0
  120. epyt_flow/topology.py +290 -0
  121. epyt_flow/uncertainty/__init__.py +3 -0
  122. epyt_flow/uncertainty/model_uncertainty.py +302 -0
  123. epyt_flow/uncertainty/sensor_noise.py +73 -0
  124. epyt_flow/uncertainty/uncertainties.py +555 -0
  125. epyt_flow/uncertainty/utils.py +206 -0
  126. epyt_flow/utils.py +306 -0
  127. epyt_flow-0.1.0.dist-info/LICENSE +21 -0
  128. epyt_flow-0.1.0.dist-info/METADATA +139 -0
  129. epyt_flow-0.1.0.dist-info/RECORD +131 -0
  130. epyt_flow-0.1.0.dist-info/WHEEL +5 -0
  131. epyt_flow-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,555 @@
1
+ """
2
+ Module provides classes for implementing different types of uncertainties.
3
+ """
4
+ from abc import ABC, abstractmethod
5
+ import numpy as np
6
+
7
+ from .utils import generate_deep_random_gaussian_noise, create_deep_random_pattern
8
+ from ..serialization import serializable, JsonSerializable, ABSOLUTE_GAUSSIAN_UNCERTAINTY_ID, \
9
+ RELATIVE_GAUSSIAN_UNCERTAINTY_ID, ABSOLUTE_UNIFORM_UNCERTAINTY_ID, \
10
+ RELATIVE_UNIFORM_UNCERTAINTY_ID, ABSOLUTE_DEEP_UNIFORM_UNCERTAINTY_ID, \
11
+ RELATIVE_DEEP_UNIFORM_UNCERTAINTY_ID, ABSOLUTE_DEEP_GAUSSIAN_UNCERTAINTY_ID, \
12
+ RELATIVE_DEEP_GAUSSIAN_UNCERTAINTY_ID, ABSOLUTE_DEEP_UNCERTAINTY_ID, \
13
+ RELATIVE_DEEP_UNCERTAINTY_ID, PERCENTAGE_DEVIATON_UNCERTAINTY_ID
14
+
15
+
16
+ class Uncertainty(ABC):
17
+ """
18
+ Base class for uncertainties -- i.e. perturbations of data/signals.
19
+
20
+ Parameters
21
+ ----------
22
+ min_value : `float`, optional
23
+ Lower bound on the data/signal that is perturbed by this uncertainty.
24
+
25
+ The default is None.
26
+ max_value : `float`, optional
27
+ Upper bound on the data/signal that is perturbed by this uncertainty.
28
+
29
+ The default is None.
30
+ """
31
+ def __init__(self, min_value: float = None, max_value: float = None, **kwds):
32
+ super().__init__(**kwds)
33
+
34
+ self.__min_value = min_value
35
+ self.__max_value = max_value
36
+
37
+ @property
38
+ def min_value(self) -> float:
39
+ """
40
+ Gets the lower bound on the data/signal.
41
+
42
+ Returns
43
+ -------
44
+ `float`
45
+ Lower bound.
46
+ """
47
+ return self.__min_value
48
+
49
+ @property
50
+ def max_value(self) -> float:
51
+ """
52
+ Gets the upper bound on the data/signal.
53
+
54
+ Returns
55
+ -------
56
+ `float`
57
+ Upper bound.
58
+ """
59
+ return self.__max_value
60
+
61
+ def get_attributes(self) -> dict:
62
+ """
63
+ Gets all attributes to be serialized -- these attributes are passed to the
64
+ constructor when the object is deserialized.
65
+
66
+ Returns
67
+ -------
68
+ `dict`
69
+ Dictionary of attributes -- i.e. pairs of attribute name + value.
70
+ """
71
+ return {"min_value": self.__min_value, "max_value": self.__max_value}
72
+
73
+ def __eq__(self, other) -> bool:
74
+ if not isinstance(other, Uncertainty):
75
+ raise TypeError("Can not compare 'Uncertainty' instance " +
76
+ f"with '{type(other)}' instance")
77
+
78
+ return self.__min_value == other.min_value and self.__max_value == other.max_value
79
+
80
+ def __str__(self) -> str:
81
+ return f"min_value: {self.__min_value} max_value: {self.__max_value}"
82
+
83
+ def clip(self, data: np.ndarray) -> np.ndarray:
84
+ """
85
+ Clips values in a given array -- i.e. every value must be in [min_value, max_value].
86
+
87
+ Parameters
88
+ ----------
89
+ data : `numpy.ndarray`
90
+ Array to be clipped.
91
+
92
+ Returns
93
+ -------
94
+ `numpy.ndarray`
95
+ Clipped data.
96
+ """
97
+ if self.__min_value is not None:
98
+ data = np.min([data, self.__min_value])
99
+ if self.__max_value is not None:
100
+ data = np.max([data, self.__max_value])
101
+
102
+ return data
103
+
104
+ @abstractmethod
105
+ def apply(self, data: float):
106
+ """
107
+ Applies the uncertainty to a single value.
108
+
109
+ Parameters
110
+ ----------
111
+ data : `float`
112
+ The value to which the uncertainty is applied.
113
+
114
+ Returns
115
+ -------
116
+ `float`
117
+ Uncertainty applied to 'data'.
118
+ """
119
+ raise NotImplementedError()
120
+
121
+ def apply_batch(self, data: np.ndarray) -> np.ndarray:
122
+ """
123
+ Applies the uncertainty to an array of values.
124
+
125
+ Parameters
126
+ ----------
127
+ data : `numpy.ndarray`
128
+ Array of values to which the uncertainty is applied.
129
+
130
+ Returns
131
+ -------
132
+ `numpy.ndarray`
133
+ Uncertainty applied to `data`.
134
+ """
135
+ for t in range(data.shape[0]):
136
+ data[t] = self.apply(data[t])
137
+ return data
138
+
139
+
140
+ class GaussianUncertainty(Uncertainty):
141
+ """
142
+ Base class implementing Gaussian uncertainty
143
+
144
+ Parameters
145
+ ----------
146
+ mean : `float`, optional
147
+ Mean of the Gaussian noise.
148
+
149
+ If None, mean will be assigned a random value between 0 and 1.
150
+
151
+ The default is None.
152
+ scale : `float`, optional
153
+ Scale (i.e. standard deviation) of the Gaussian noise.
154
+
155
+ If None, scale will be assigned a random value between 0 and 1.
156
+
157
+ The default is None.
158
+ """
159
+ def __init__(self, mean: float = None, scale: float = None, **kwds):
160
+ super().__init__(**kwds)
161
+
162
+ self.__mean = np.random.rand() if mean is None else mean
163
+ self.__scale = np.random.rand() if scale is None else scale
164
+
165
+ @property
166
+ def mean(self) -> float:
167
+ """
168
+ Gets the mean of the Gaussian noise.
169
+
170
+ Returns
171
+ -------
172
+ `float`
173
+ Mean of the Gaussian noise.
174
+ """
175
+ return self.__mean
176
+
177
+ @property
178
+ def scale(self) -> float:
179
+ """
180
+ Gets the scale (i.e. standard deviation) of the Gaussian noise.
181
+
182
+ Returns
183
+ -------
184
+ `float`
185
+ Scale (i.e. standard deviation) of the Gaussian noise.
186
+ """
187
+ return self.__scale
188
+
189
+ def get_attributes(self) -> dict:
190
+ return super().get_attributes() | {"mean": self.__mean, "scale": self.__scale}
191
+
192
+ def __eq__(self, other) -> bool:
193
+ if not isinstance(other, GaussianUncertainty):
194
+ raise TypeError("Can not compare 'GaussianUncertainty' instance " +
195
+ f"with '{type(other)}' instance")
196
+
197
+ return super().__eq__(other) and self.__mean == other.mean and self.__scale == other.scale
198
+
199
+ def __str__(self) -> str:
200
+ return super().__str__() + f" mean: {self.__mean} scale: {self.__scale}"
201
+
202
+
203
+ @serializable(ABSOLUTE_GAUSSIAN_UNCERTAINTY_ID, ".epytflow_uncertainty_absolute_gaussian")
204
+ class AbsoluteGaussianUncertainty(GaussianUncertainty, JsonSerializable):
205
+ """
206
+ Class implementing absolute Gaussian uncertainty -- i.e. Gaussian noise is added to the data.
207
+ """
208
+ def apply(self, data: float) -> float:
209
+ data += np.random.normal(loc=self.mean, scale=self.scale)
210
+
211
+ return self.clip(data)
212
+
213
+
214
+ @serializable(RELATIVE_GAUSSIAN_UNCERTAINTY_ID, ".epytflow_uncertainty_relative_gaussian")
215
+ class RelativeGaussianUncertainty(GaussianUncertainty, JsonSerializable):
216
+ """
217
+ Class implementing relative Gaussian uncertainty -- i.e. data is perturbed by Gaussian noise
218
+ centered at zero.
219
+
220
+ Parameters
221
+ ----------
222
+ scale : `float`, optional
223
+ Scale (i.e. standard deviation) of the Gaussian noise.
224
+
225
+ If None, scale will be assigned a random value between 0 and 1.
226
+
227
+ The default is None.
228
+ """
229
+ def __init__(self, scale: float = None, **kwds):
230
+ super().__init__(mean=0., scale=scale, **kwds)
231
+
232
+ def apply(self, data: float) -> float:
233
+ data += np.random.normal(loc=0, scale=self.scale)
234
+
235
+ return self.clip(data)
236
+
237
+
238
+ class UniformUncertainty(Uncertainty):
239
+ """
240
+ Base class implementing uniform uncertainty.
241
+
242
+ Parameters
243
+ ----------
244
+ low : `float`, optional
245
+ Lower bound of the uniform noise.
246
+
247
+ The default is zero.
248
+ high : `float`, optional
249
+ Upper bound of the uniform noise.
250
+
251
+ The default is one.
252
+ """
253
+ def __init__(self, low: float = 0., high: float = 1., **kwds):
254
+ super().__init__(**kwds)
255
+
256
+ self.__low = low
257
+ self.__high = high
258
+
259
+ @property
260
+ def low(self) -> float:
261
+ """
262
+ Gets the lower bound of the uniform noise.
263
+
264
+ Returns
265
+ -------
266
+ `float`
267
+ Lower bound of the uniform noise.
268
+ """
269
+ return self.__low
270
+
271
+ @property
272
+ def high(self) -> float:
273
+ """
274
+ Gets the upper bound of the uniform noise.
275
+
276
+ Returns
277
+ -------
278
+ `float`
279
+ Upper bound of the uniform noise.
280
+ """
281
+ return self.__high
282
+
283
+ def get_attributes(self) -> dict:
284
+ return super().get_attributes() | {"low": self.__low, "high": self.__high}
285
+
286
+ def __eq__(self, other) -> bool:
287
+ if not isinstance(other, UniformUncertainty):
288
+ raise TypeError("Can not compare 'UniformUncertainty' instance " +
289
+ f"with '{type(other)}' instance")
290
+
291
+ return super().__eq__(other) and self.__low == other.low and self.__high == other.high
292
+
293
+ def __str__(self) -> str:
294
+ return super().__str__() + f" low: {self.__low} high: {self.__high}"
295
+
296
+
297
+ @serializable(ABSOLUTE_UNIFORM_UNCERTAINTY_ID, ".epytflow_uncertainty_absolute_uniform")
298
+ class AbsoluteUniformUncertainty(UniformUncertainty, JsonSerializable):
299
+ """
300
+ Class implementing absolute uniform uncertainty -- i.e. uniform noise is added to the data.
301
+ """
302
+ def apply(self, data: float) -> float:
303
+ data += np.random.uniform(low=self.low, high=self.high)
304
+
305
+ return self.clip(data)
306
+
307
+
308
+ @serializable(RELATIVE_UNIFORM_UNCERTAINTY_ID, ".epytflow_uncertainty_relative_uniform")
309
+ class RelativeUniformUncertainty(UniformUncertainty, JsonSerializable):
310
+ """
311
+ Class implementing relative uniform uncertainty -- i.e. data is multiplied by uniform noise.
312
+ """
313
+ def apply(self, data: float) -> float:
314
+ data *= np.random.uniform(low=self.low, high=self.high)
315
+
316
+ return self.clip(data)
317
+
318
+
319
+ @serializable(PERCENTAGE_DEVIATON_UNCERTAINTY_ID, ".epytflow_uncertainty_percentage_deviation")
320
+ class PercentageDeviationUncertainty(UniformUncertainty, JsonSerializable):
321
+ """
322
+ Class implementing a uniform data deviation -- i.e. the data can deviate up to some percentage
323
+ from its original value.
324
+
325
+ Parameters
326
+ ----------
327
+ deviation_percentage : `float`
328
+ Percentage (0-1) the data can deviate from its original value.
329
+ """
330
+ def __init__(self, deviation_percentage: float, **kwds):
331
+ if not isinstance(deviation_percentage, float):
332
+ raise TypeError("'deviation_percentage' must be an instance of 'float' " +
333
+ f"but not of {type(deviation_percentage)}")
334
+ if not 0 < deviation_percentage < 1:
335
+ raise ValueError("'deviation_percentage' must be in (0,1)")
336
+
337
+ super().__init__(low=1. - deviation_percentage, high=1. + deviation_percentage, **kwds)
338
+
339
+ def apply(self, data: float) -> float:
340
+ data *= np.random.uniform(low=self.low, high=self.high)
341
+
342
+ return self.clip(data)
343
+
344
+
345
+ class DeepUniformUncertainty(Uncertainty):
346
+ """
347
+ Base class implementing deep uniform uncertainty.
348
+ """
349
+ def __init__(self, **kwds):
350
+ super().__init__(**kwds)
351
+
352
+ self.__create_uncertainties()
353
+
354
+ def __create_uncertainties(self, n_samples: int = 500):
355
+ self._uncertainties_idx = 0
356
+ rand_low = create_deep_random_pattern(n_samples)
357
+ rand_high = create_deep_random_pattern(n_samples)
358
+ rand_low = np.minimum(rand_low, rand_high)
359
+ rand_high = np.maximum(rand_low, rand_high)
360
+ self._uncertainties = [np.random.uniform(low, high)
361
+ for low, high in zip(rand_low, rand_high)]
362
+
363
+ @abstractmethod
364
+ def apply(self, data: float) -> float:
365
+ self._uncertainties_idx += 1
366
+ if self._uncertainties_idx >= len(self._uncertainties):
367
+ self.__create_uncertainties()
368
+
369
+ return self.clip(data)
370
+
371
+
372
+ @serializable(ABSOLUTE_DEEP_UNIFORM_UNCERTAINTY_ID, ".epytflow_uncertainty_absolute_deep_uniform")
373
+ class AbsoluteDeepUniformUncertainty(DeepUniformUncertainty, JsonSerializable):
374
+ """
375
+ Class implementing absolute deep uniform uncertainty -- i.e. random uniform noise
376
+ (shape of the noise is changing over time) is added to the data.
377
+ """
378
+ def apply(self, data: float) -> float:
379
+ data += self._uncertainties[self._uncertainties_idx]
380
+
381
+ return super().apply(data)
382
+
383
+
384
+ @serializable(RELATIVE_DEEP_UNIFORM_UNCERTAINTY_ID, ".epytflow_uncertainty_relative_deep_uniform")
385
+ class RelativeDeepUniformUncertainty(DeepUniformUncertainty, JsonSerializable):
386
+ """
387
+ Class implementing relative deep uniform uncertainty -- i.e. data is multiplied by
388
+ random uniform noise (shape of the noise is changing over time).
389
+ """
390
+ def apply(self, data: float) -> float:
391
+ data *= self._uncertainties[self._uncertainties_idx]
392
+
393
+ return super().apply(data)
394
+
395
+
396
+ class DeepGaussianUncertainty(Uncertainty, JsonSerializable):
397
+ """
398
+ Base class implementing deep Gaussian uncertainty.
399
+
400
+ Parameters
401
+ ----------
402
+ mean : `float`, optional
403
+ Fixed mean of Gaussian noise.
404
+ If None, random means are generated.
405
+
406
+ The default is None.
407
+ """
408
+ def __init__(self, mean: float = None, **kwds):
409
+ self.__mean = mean
410
+
411
+ super().__init__(**kwds)
412
+
413
+ self.__create_uncertainties()
414
+
415
+ def __create_uncertainties(self, n_samples: int = 500) -> None:
416
+ self._uncertainties_idx = 0
417
+ self._uncertainties = generate_deep_random_gaussian_noise(n_samples, self.__mean)
418
+
419
+ @abstractmethod
420
+ def apply(self, data: float) -> float:
421
+ self._uncertainties_idx += 1
422
+ if self._uncertainties_idx >= len(self._uncertainties):
423
+ self.__create_uncertainties()
424
+
425
+ return self.clip(data)
426
+
427
+
428
+ @serializable(ABSOLUTE_DEEP_GAUSSIAN_UNCERTAINTY_ID, ".epytflow_uncertainty_absolute_deep_gaussian")
429
+ class AbsoluteDeepGaussianUncertainty(DeepGaussianUncertainty, JsonSerializable):
430
+ """
431
+ Class implementing absolute deep Gaussian uncertainty -- i.e. random Gaussian noise
432
+ (mean and variance are changing over time) is added to the data.
433
+ """
434
+ def apply(self, data: float) -> float:
435
+ data += self._uncertainties[self._uncertainties_idx]
436
+
437
+ return super().apply(data)
438
+
439
+
440
+ @serializable(RELATIVE_DEEP_GAUSSIAN_UNCERTAINTY_ID, ".epytflow_uncertainty_relative_deep_gaussian")
441
+ class RelativeDeepGaussianUncertainty(DeepGaussianUncertainty, JsonSerializable):
442
+ """
443
+ Class implementing realtive deep Gaussian uncertainty -- i.e. data is multiplied by
444
+ random Gaussian noise (mean and variance are changing over time).
445
+ """
446
+ def __init__(self, **kwds):
447
+ super().__init__(mean=0., **kwds)
448
+
449
+ def apply(self, data: float) -> float:
450
+ data += self._uncertainties[self._uncertainties_idx]
451
+
452
+ return super().apply(data)
453
+
454
+
455
+ class DeepUncertainty(Uncertainty):
456
+ """
457
+ Base class implementing deep uncertainty.
458
+
459
+ Parameters
460
+ ----------
461
+ min_noise_value : `float`
462
+ Lower bound on the noise.
463
+ max_noise_value : `float`
464
+ Upper bound on the noise.
465
+ """
466
+ def __init__(self, min_noise_value: float = 0., max_noise_value: float = 1., **kwds):
467
+ super().__init__(**kwds)
468
+
469
+ self.__min_noise_value = min_noise_value
470
+ self.__max_noise_value = max_noise_value
471
+
472
+ self._uncertainties_idx = None
473
+ self._uncertainties = None
474
+ self.__create_uncertainties()
475
+
476
+ @property
477
+ def min_noise_value(self) -> float:
478
+ """
479
+ Gets the lower bound on the noise.
480
+
481
+ Returns
482
+ -------
483
+ `float`
484
+ Lower bound on the noise.
485
+ """
486
+ return self.__min_noise_value
487
+
488
+ @property
489
+ def max_noise_value(self) -> float:
490
+ """
491
+ Gets the upper bound on the noise.
492
+
493
+ Returns
494
+ -------
495
+ `float`
496
+ Upper bound on the noise.
497
+ """
498
+ return self.__max_noise_value
499
+
500
+ def get_attributes(self) -> dict:
501
+ return super().get_attributes() | {"min_noise_value": self.__min_noise_value,
502
+ "max_noise_value": self.__max_noise_value}
503
+
504
+ def __eq__(self, other) -> bool:
505
+ if not isinstance(other, DeepUncertainty):
506
+ raise TypeError("Can not compare 'DeepUncertainty' instance " +
507
+ f"with '{type(other)}' instance")
508
+
509
+ return super().__eq__(other) and self.__min_noise_value == other.min_noise_value and \
510
+ self.__max_noise_value == other.max_noise_value
511
+
512
+ def __str__(self) -> str:
513
+ return super().__str__() + f" min_noise_value: {self.__min_noise_value} " +\
514
+ f"max_noise_value: {self.__max_noise_value}"
515
+
516
+ def __create_uncertainties(self, n_samples: int = 500) -> None:
517
+ init_value = None
518
+ if self._uncertainties_idx is not None:
519
+ init_value = self._uncertainties[-1]
520
+
521
+ self._uncertainties_idx = 0
522
+ self._uncertainties = create_deep_random_pattern(n_samples, self.__min_noise_value,
523
+ self.__max_noise_value, init_value)
524
+
525
+ @abstractmethod
526
+ def apply(self, data: float) -> float:
527
+ self._uncertainties_idx += 1
528
+ if self._uncertainties_idx >= len(self._uncertainties):
529
+ self.__create_uncertainties()
530
+
531
+ return self.clip(data)
532
+
533
+
534
+ @serializable(ABSOLUTE_DEEP_UNCERTAINTY_ID, ".epytflow_uncertainty_absolute_deep")
535
+ class AbsoluteDeepUncertainty(DeepUncertainty, JsonSerializable):
536
+ """
537
+ Class implementing absolute deep uncertainty -- i.e. completely random noise
538
+ is added to the data.
539
+ """
540
+ def apply(self, data: float) -> float:
541
+ data += self._uncertainties[self._uncertainties_idx]
542
+
543
+ return super().apply(data)
544
+
545
+
546
+ @serializable(RELATIVE_DEEP_UNCERTAINTY_ID, ".epytflow_uncertainty_relative_deep")
547
+ class RelativeDeepUncertainty(DeepUncertainty, JsonSerializable):
548
+ """
549
+ Class implementing relative deep uncertainty -- i.e. data is multiplied by
550
+ completely random noise.
551
+ """
552
+ def apply(self, data: float) -> float:
553
+ data *= self._uncertainties[self._uncertainties_idx]
554
+
555
+ return super().apply(data)