pyvale 2025.4.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.

Potentially problematic release.


This version of pyvale might be problematic. Click here for more details.

Files changed (157) hide show
  1. pyvale/__init__.py +75 -0
  2. pyvale/core/__init__.py +7 -0
  3. pyvale/core/analyticmeshgen.py +59 -0
  4. pyvale/core/analyticsimdatafactory.py +63 -0
  5. pyvale/core/analyticsimdatagenerator.py +160 -0
  6. pyvale/core/camera.py +146 -0
  7. pyvale/core/cameradata.py +64 -0
  8. pyvale/core/cameradata2d.py +82 -0
  9. pyvale/core/cameratools.py +328 -0
  10. pyvale/core/cython/rastercyth.c +32267 -0
  11. pyvale/core/cython/rastercyth.py +636 -0
  12. pyvale/core/dataset.py +250 -0
  13. pyvale/core/errorcalculator.py +112 -0
  14. pyvale/core/errordriftcalc.py +146 -0
  15. pyvale/core/errorintegrator.py +339 -0
  16. pyvale/core/errorrand.py +614 -0
  17. pyvale/core/errorsysdep.py +331 -0
  18. pyvale/core/errorsysfield.py +407 -0
  19. pyvale/core/errorsysindep.py +905 -0
  20. pyvale/core/experimentsimulator.py +99 -0
  21. pyvale/core/field.py +136 -0
  22. pyvale/core/fieldconverter.py +154 -0
  23. pyvale/core/fieldsampler.py +112 -0
  24. pyvale/core/fieldscalar.py +167 -0
  25. pyvale/core/fieldtensor.py +221 -0
  26. pyvale/core/fieldtransform.py +384 -0
  27. pyvale/core/fieldvector.py +215 -0
  28. pyvale/core/generatorsrandom.py +528 -0
  29. pyvale/core/imagedef2d.py +566 -0
  30. pyvale/core/integratorfactory.py +241 -0
  31. pyvale/core/integratorquadrature.py +192 -0
  32. pyvale/core/integratorrectangle.py +88 -0
  33. pyvale/core/integratorspatial.py +90 -0
  34. pyvale/core/integratortype.py +44 -0
  35. pyvale/core/optimcheckfuncs.py +153 -0
  36. pyvale/core/raster.py +31 -0
  37. pyvale/core/rastercy.py +76 -0
  38. pyvale/core/rasternp.py +604 -0
  39. pyvale/core/rendermesh.py +156 -0
  40. pyvale/core/sensorarray.py +179 -0
  41. pyvale/core/sensorarrayfactory.py +210 -0
  42. pyvale/core/sensorarraypoint.py +280 -0
  43. pyvale/core/sensordata.py +72 -0
  44. pyvale/core/sensordescriptor.py +101 -0
  45. pyvale/core/sensortools.py +143 -0
  46. pyvale/core/visualexpplotter.py +151 -0
  47. pyvale/core/visualimagedef.py +71 -0
  48. pyvale/core/visualimages.py +75 -0
  49. pyvale/core/visualopts.py +180 -0
  50. pyvale/core/visualsimanimator.py +83 -0
  51. pyvale/core/visualsimplotter.py +182 -0
  52. pyvale/core/visualtools.py +81 -0
  53. pyvale/core/visualtraceplotter.py +256 -0
  54. pyvale/data/__init__.py +7 -0
  55. pyvale/data/case13_out.e +0 -0
  56. pyvale/data/case16_out.e +0 -0
  57. pyvale/data/case17_out.e +0 -0
  58. pyvale/data/case18_1_out.e +0 -0
  59. pyvale/data/case18_2_out.e +0 -0
  60. pyvale/data/case18_3_out.e +0 -0
  61. pyvale/data/case25_out.e +0 -0
  62. pyvale/data/case26_out.e +0 -0
  63. pyvale/data/optspeckle_2464x2056px_spec5px_8bit_gblur1px.tiff +0 -0
  64. pyvale/examples/__init__.py +7 -0
  65. pyvale/examples/analyticdatagen/__init__.py +7 -0
  66. pyvale/examples/analyticdatagen/ex1_1_scalarvisualisation.py +38 -0
  67. pyvale/examples/analyticdatagen/ex1_2_scalarcasebuild.py +46 -0
  68. pyvale/examples/analyticdatagen/ex2_1_analyticsensors.py +83 -0
  69. pyvale/examples/ex1_1_thermal2d.py +89 -0
  70. pyvale/examples/ex1_2_thermal2d.py +111 -0
  71. pyvale/examples/ex1_3_thermal2d.py +113 -0
  72. pyvale/examples/ex1_4_thermal2d.py +89 -0
  73. pyvale/examples/ex1_5_thermal2d.py +105 -0
  74. pyvale/examples/ex2_1_thermal3d .py +87 -0
  75. pyvale/examples/ex2_2_thermal3d.py +51 -0
  76. pyvale/examples/ex2_3_thermal3d.py +109 -0
  77. pyvale/examples/ex3_1_displacement2d.py +47 -0
  78. pyvale/examples/ex3_2_displacement2d.py +79 -0
  79. pyvale/examples/ex3_3_displacement2d.py +104 -0
  80. pyvale/examples/ex3_4_displacement2d.py +105 -0
  81. pyvale/examples/ex4_1_strain2d.py +57 -0
  82. pyvale/examples/ex4_2_strain2d.py +79 -0
  83. pyvale/examples/ex4_3_strain2d.py +100 -0
  84. pyvale/examples/ex5_1_multiphysics2d.py +78 -0
  85. pyvale/examples/ex6_1_multiphysics2d_expsim.py +118 -0
  86. pyvale/examples/ex6_2_multiphysics3d_expsim.py +158 -0
  87. pyvale/examples/features/__init__.py +7 -0
  88. pyvale/examples/features/ex_animation_tools_3dmonoblock.py +83 -0
  89. pyvale/examples/features/ex_area_avg.py +89 -0
  90. pyvale/examples/features/ex_calibration_error.py +108 -0
  91. pyvale/examples/features/ex_chain_field_errs.py +141 -0
  92. pyvale/examples/features/ex_field_errs.py +78 -0
  93. pyvale/examples/features/ex_sensor_single_angle_batch.py +110 -0
  94. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +86 -0
  95. pyvale/examples/rasterisation/ex_rastenp.py +154 -0
  96. pyvale/examples/rasterisation/ex_rastercyth_oneframe.py +220 -0
  97. pyvale/examples/rasterisation/ex_rastercyth_static_cypara.py +194 -0
  98. pyvale/examples/rasterisation/ex_rastercyth_static_pypara.py +193 -0
  99. pyvale/simcases/case00_HEX20.i +242 -0
  100. pyvale/simcases/case00_HEX27.i +242 -0
  101. pyvale/simcases/case00_TET10.i +242 -0
  102. pyvale/simcases/case00_TET14.i +242 -0
  103. pyvale/simcases/case01.i +101 -0
  104. pyvale/simcases/case02.i +156 -0
  105. pyvale/simcases/case03.i +136 -0
  106. pyvale/simcases/case04.i +181 -0
  107. pyvale/simcases/case05.i +234 -0
  108. pyvale/simcases/case06.i +305 -0
  109. pyvale/simcases/case07.geo +135 -0
  110. pyvale/simcases/case07.i +87 -0
  111. pyvale/simcases/case08.geo +144 -0
  112. pyvale/simcases/case08.i +153 -0
  113. pyvale/simcases/case09.geo +204 -0
  114. pyvale/simcases/case09.i +87 -0
  115. pyvale/simcases/case10.geo +204 -0
  116. pyvale/simcases/case10.i +257 -0
  117. pyvale/simcases/case11.geo +337 -0
  118. pyvale/simcases/case11.i +147 -0
  119. pyvale/simcases/case12.geo +388 -0
  120. pyvale/simcases/case12.i +329 -0
  121. pyvale/simcases/case13.i +140 -0
  122. pyvale/simcases/case14.i +159 -0
  123. pyvale/simcases/case15.geo +337 -0
  124. pyvale/simcases/case15.i +150 -0
  125. pyvale/simcases/case16.geo +391 -0
  126. pyvale/simcases/case16.i +357 -0
  127. pyvale/simcases/case17.geo +135 -0
  128. pyvale/simcases/case17.i +144 -0
  129. pyvale/simcases/case18.i +254 -0
  130. pyvale/simcases/case18_1.i +254 -0
  131. pyvale/simcases/case18_2.i +254 -0
  132. pyvale/simcases/case18_3.i +254 -0
  133. pyvale/simcases/case19.geo +252 -0
  134. pyvale/simcases/case19.i +99 -0
  135. pyvale/simcases/case20.geo +252 -0
  136. pyvale/simcases/case20.i +250 -0
  137. pyvale/simcases/case21.geo +74 -0
  138. pyvale/simcases/case21.i +155 -0
  139. pyvale/simcases/case22.geo +82 -0
  140. pyvale/simcases/case22.i +140 -0
  141. pyvale/simcases/case23.geo +164 -0
  142. pyvale/simcases/case23.i +140 -0
  143. pyvale/simcases/case24.geo +79 -0
  144. pyvale/simcases/case24.i +123 -0
  145. pyvale/simcases/case25.geo +82 -0
  146. pyvale/simcases/case25.i +140 -0
  147. pyvale/simcases/case26.geo +166 -0
  148. pyvale/simcases/case26.i +140 -0
  149. pyvale/simcases/run_1case.py +61 -0
  150. pyvale/simcases/run_all_cases.py +69 -0
  151. pyvale/simcases/run_build_case.py +64 -0
  152. pyvale/simcases/run_example_cases.py +69 -0
  153. pyvale-2025.4.0.dist-info/METADATA +140 -0
  154. pyvale-2025.4.0.dist-info/RECORD +157 -0
  155. pyvale-2025.4.0.dist-info/WHEEL +5 -0
  156. pyvale-2025.4.0.dist-info/licenses/LICENSE +21 -0
  157. pyvale-2025.4.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,528 @@
1
+ """
2
+ ================================================================================
3
+ pyvale: the python validation engine
4
+ License: MIT
5
+ Copyright (C) 2025 The Computer Aided Validation Team
6
+ ================================================================================
7
+ """
8
+ from abc import ABC, abstractmethod
9
+ import numpy as np
10
+
11
+
12
+ class IGeneratorRandom(ABC):
13
+ """Interface (abstract base class) for wrapping numpy random number
14
+ generation to allow probability distribution parameters to be specified in
15
+ the initialiser whereas the generation of random numbers has a common
16
+ method that just takes the require shape to return. Allows for easy
17
+ subsitution of different probability distributions.
18
+ """
19
+
20
+ @abstractmethod
21
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
22
+ """Abstract method. Generates an array of random numbers with the shape
23
+ specified by the input.
24
+
25
+ Parameters
26
+ ----------
27
+ shape : tuple[int,...]
28
+ Shape of the array of random numbers to be returned.
29
+
30
+ Returns
31
+ -------
32
+ np.ndarray
33
+ Array of random numbers with shape specified by the input shape.
34
+ """
35
+ pass
36
+
37
+
38
+ class GeneratorNormal(IGeneratorRandom):
39
+ """Class wrapping the numpy normal random number generator. Implements the
40
+ IGeneratorRandom interface to allow for interchangeability with other random
41
+ number generators.
42
+ """
43
+ __slots__ = ("_std","_mean","_rng")
44
+
45
+ def __init__(self,
46
+ std: float = 1.0,
47
+ mean: float = 0.0,
48
+ seed: int | None = None) -> None:
49
+ """Initialiser taking the parameters of the probability distribution and
50
+ an optional seed for the random generator to allow for reproducibility.
51
+
52
+ Parameters
53
+ ----------
54
+ std : float, optional
55
+ Standard deviation of the normal distribution to sample, by default
56
+ 1.0
57
+ mean : float, optional
58
+ Mean of the normal distribution to sample, by default 0.0
59
+ seed : int | None, optional
60
+ Optional seed for the random generator to allow for reproducibility
61
+ and testing, by default None
62
+ """
63
+ self._std =std
64
+ self._mean = mean
65
+ self._rng = np.random.default_rng(seed)
66
+
67
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
68
+ """Generates an array of random numbers with the shape specified by the
69
+ input.
70
+
71
+ Parameters
72
+ ----------
73
+ shape : tuple[int,...]
74
+ Shape of the array to return.
75
+
76
+ Returns
77
+ -------
78
+ np.ndarray
79
+ Array of random numbers with the specified shape.
80
+ """
81
+ return self._rng.normal(loc = self._mean,
82
+ scale = self._std,
83
+ size = shape)
84
+
85
+
86
+ class GeneratorLogNormal(IGeneratorRandom):
87
+ """Class wrapping the numpy lognormal random generator. Implements the
88
+ IGeneratorRandom interface to allow for interchangeability with other random
89
+ number generators.
90
+ """
91
+ __slots__ = ("_std","_mean","_rng")
92
+
93
+ def __init__(self,
94
+ std: float = 1.0,
95
+ mean: float = 0.0,
96
+ seed: int | None = None) -> None:
97
+ """Initialiser taking the parameters of the probability distribution and
98
+ an optional seed for the random generator to allow for reproducibility.
99
+
100
+ Parameters
101
+ ----------
102
+ std : float, optional
103
+ Standard deviation of the normal distribution to sample, by default
104
+ 1.0
105
+ mean : float, optional
106
+ Mean of the normal distribution to sample, by default 0.0
107
+ seed : int | None, optional
108
+ Optional seed for the random generator to allow for reproducibility
109
+ and testing, by default None
110
+ """
111
+ self._std =std
112
+ self._mean = mean
113
+ self._rng = np.random.default_rng(seed)
114
+
115
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
116
+ """Generates an array of random numbers with the shape specified by the
117
+ input.
118
+
119
+ Parameters
120
+ ----------
121
+ shape : tuple[int,...]
122
+ Shape of the array to return.
123
+ Returns
124
+ -------
125
+ np.ndarray
126
+ Array of random numbers with the specified shape.
127
+ """
128
+ return self._rng.lognormal(mean = self._mean,
129
+ sigma = self._std,
130
+ size = shape)
131
+
132
+
133
+ class GeneratorUniform(IGeneratorRandom):
134
+ """Class wrapping the numpy uniform random number generator. Implements the
135
+ IGeneratorRandom interface to allow for interchangeability with other random
136
+ number generators.
137
+ """
138
+ __slots__ = ("_low","_high","_rng")
139
+
140
+ def __init__(self,
141
+ low: float = -1.0,
142
+ high: float = 1.0,
143
+ seed: int | None = None) -> None:
144
+ """Initialiser taking the parameters of the probability distribution and
145
+ an optional seed for the random generator to allow for reproducibility.
146
+
147
+ Parameters
148
+ ----------
149
+ low : float, optional
150
+ Lower bound of the uniform dsitribution., by default -1.0
151
+ high : float, optional
152
+ Upper bound of the uniform distribution, by default 1.0
153
+ seed : int | None, optional
154
+ Optional seed for the random generator to allow for reproducibility
155
+ and testing, by default None
156
+ """
157
+
158
+ self._low = low
159
+ self._high = high
160
+ self._rng = np.random.default_rng(seed)
161
+
162
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
163
+ """Generates an array of random numbers with the shape specified by the
164
+ input.
165
+
166
+ Parameters
167
+ ----------
168
+ shape : tuple[int,...]
169
+ Shape of the array to return.
170
+ Returns
171
+ -------
172
+ np.ndarray
173
+ Array of random numbers with the specified shape.
174
+ """
175
+ return self._rng.uniform(low = self._low,
176
+ high = self._high,
177
+ size = shape)
178
+
179
+
180
+ class GeneratorExponential(IGeneratorRandom):
181
+ """Class wrapping the numpy exponential random generator. Implements the
182
+ IGeneratorRandom interface to allow for interchangeability with other random
183
+ number generators.
184
+ """
185
+ __slots__ = ("_scale","_rng")
186
+
187
+ def __init__(self,
188
+ scale: float = 1.0,
189
+ seed: int | None = None) -> None:
190
+ """Initialiser taking the parameters of the probability distribution and
191
+ an optional seed for the random generator to allow for reproducibility.
192
+
193
+ Parameters
194
+ ----------
195
+ scale : float, optional
196
+ Scale parameter of the distribution which must be positive, by
197
+ default 1.0
198
+ seed : int | None, optional
199
+ Optional seed for the random generator to allow for reproducibility
200
+ and testing, by default None
201
+ """
202
+ self._scale = np.abs(scale)
203
+ self._rng = np.random.default_rng(seed)
204
+
205
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
206
+ """Generates an array of random numbers with the shape specified by the
207
+ input.
208
+
209
+ Parameters
210
+ ----------
211
+ shape : tuple[int,...]
212
+ Shape of the array to return.
213
+ Returns
214
+ -------
215
+ np.ndarray
216
+ Array of random numbers with the specified shape.
217
+ """
218
+ return self._rng.exponential(scale = self._scale,
219
+ size = shape)
220
+
221
+
222
+ class GeneratorChiSquare(IGeneratorRandom):
223
+ """Class wrapping the numpy chi square random generator. Implements the
224
+ IGeneratorRandom interface to allow for interchangeability with other random
225
+ number generators.
226
+ """
227
+ __slots__ = ("_dofs","_rng")
228
+
229
+ def __init__(self,
230
+ dofs: float,
231
+ seed: int | None = None) -> None:
232
+ """Initialiser taking the parameters of the probability distribution and
233
+ an optional seed for the random generator to allow for reproducibility.
234
+
235
+ Parameters
236
+ ----------
237
+ dofs : float
238
+ Number of degrees of freedom of the distribution must be greater
239
+ than zero.
240
+ seed : int | None, optional
241
+ Optional seed for the random generator to allow for reproducibility
242
+ and testing, by default None
243
+ """
244
+ self._dofs = np.abs(dofs)
245
+ self._rng = np.random.default_rng(seed)
246
+
247
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
248
+ """Generates an array of random numbers with the shape specified by the
249
+ input.
250
+
251
+ Parameters
252
+ ----------
253
+ shape : tuple[int,...]
254
+ Shape of the array to return.
255
+ Returns
256
+ -------
257
+ np.ndarray
258
+ Array of random numbers with the specified shape.
259
+ """
260
+ return self._rng.chisquare(df = self._dofs,
261
+ size = shape)
262
+
263
+
264
+ class GeneratorDirichlet(IGeneratorRandom):
265
+ """Class wrapping the numpy dirichlet random generator. Implements the
266
+ IGeneratorRandom interface to allow for interchangeability with other random
267
+ number generators.
268
+ """
269
+ __slots__ = ("_alpha","_rng")
270
+
271
+ def __init__(self,
272
+ alpha: float,
273
+ seed: int | None = None) -> None:
274
+ """Initialiser taking the parameters of the probability distribution and
275
+ an optional seed for the random generator to allow for reproducibility.
276
+
277
+ Parameters
278
+ ----------
279
+ alpha : float
280
+ Alpha parameter of the distribution
281
+ seed : int | None, optional
282
+ Optional seed for the random generator to allow for reproducibility
283
+ and testing, by default None
284
+ """
285
+ self._alpha = alpha
286
+ self._rng = np.random.default_rng(seed)
287
+
288
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
289
+ """Generates an array of random numbers with the shape specified by the
290
+ input.
291
+
292
+ Parameters
293
+ ----------
294
+ shape : tuple[int,...]
295
+ Shape of the array to return.
296
+ Returns
297
+ -------
298
+ np.ndarray
299
+ Array of random numbers with the specified shape.
300
+ """
301
+ return self._rng.dirichlet(alpha = self._alpha, size = shape)
302
+
303
+
304
+ class GeneratorF(IGeneratorRandom):
305
+ """Class wrapping the numpy F distribution random generator. Implements the
306
+ IGeneratorRandom interface to allow for interchangeability with other random
307
+ number generators.
308
+ """
309
+ __slots__ = ("_dofs","_rng")
310
+
311
+ def __init__(self,
312
+ dofs: float,
313
+ seed: int | None = None) -> None:
314
+ """Initialiser taking the parameters of the probability distribution and
315
+ an optional seed for the random generator to allow for reproducibility.
316
+
317
+ Parameters
318
+ ----------
319
+ dofs : float
320
+ Number of degrees of freedom of the distribution must be greater
321
+ than zero
322
+ seed : int | None, optional
323
+ Optional seed for the random generator to allow for reproducibility
324
+ and testing, by default None
325
+ """
326
+ self._dofs = np.abs(dofs)
327
+ self._rng = np.random.default_rng(seed)
328
+
329
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
330
+ """Generates an array of random numbers with the shape specified by the
331
+ input.
332
+
333
+ Parameters
334
+ ----------
335
+ shape : tuple[int,...]
336
+ Shape of the array to return.
337
+ Returns
338
+ -------
339
+ np.ndarray
340
+ Array of random numbers with the specified shape.
341
+ """
342
+ return self._rng.f(dfnum = self._dofs, size = shape)
343
+
344
+
345
+ class GeneratorGamma(IGeneratorRandom):
346
+ """Class wrapping the numpy gamma random generator. Implements the
347
+ IGeneratorRandom interface to allow for interchangeability with other random
348
+ number generators.
349
+ """
350
+ __slots__ = ("_shape","_scale","_rng")
351
+
352
+ def __init__(self,
353
+ shape: float,
354
+ scale: float = 1.0,
355
+ seed: int | None = None) -> None:
356
+ """Initialiser taking the parameters of the probability distribution and
357
+ an optional seed for the random generator to allow for reproducibility.
358
+
359
+ Parameters
360
+ ----------
361
+ shape : float
362
+ Shape parameter of the gamma distribution, must be greater than zero
363
+ scale : float, optional
364
+ Scale parameter of the gamma distribution which must be greater than
365
+ zero, by default 1.0
366
+ seed : int | None, optional
367
+ Optional seed for the random generator to allow for reproducibility
368
+ and testing, by default None
369
+ """
370
+ self._shape = np.abs(shape)
371
+ self._scale = np.abs(scale)
372
+ self._rng = np.random.default_rng(seed)
373
+
374
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
375
+ """Generates an array of random numbers with the shape specified by the
376
+ input.
377
+
378
+ Parameters
379
+ ----------
380
+ shape : tuple[int,...]
381
+ Shape of the array to return.
382
+ Returns
383
+ -------
384
+ np.ndarray
385
+ Array of random numbers with the specified shape.
386
+ """
387
+ return self._rng.gamma(scale = self._scale,
388
+ size = shape)
389
+
390
+
391
+ class GeneratorStandardT(IGeneratorRandom):
392
+ """Class wrapping the numpy t distribution random generator. Implements the
393
+ IGeneratorRandom interface to allow for interchangeability with other random
394
+ number generators.
395
+ """
396
+ __slots__ = ("_dofs","_rng")
397
+
398
+ def __init__(self,
399
+ dofs: float,
400
+ seed: int | None = None) -> None:
401
+ """Initialiser taking the parameters of the probability distribution and
402
+ an optional seed for the random generator to allow for reproducibility.
403
+
404
+ Parameters
405
+ ----------
406
+ dofs : float
407
+ Number of degrees of freedom of the distribution must be greater
408
+ than zero.
409
+ seed : int | None, optional
410
+ Optional seed for the random generator to allow for reproducibility
411
+ and testing, by default None
412
+ """
413
+ self._dofs = np.abs(dofs)
414
+ self._rng = np.random.default_rng(seed)
415
+
416
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
417
+ """Generates an array of random numbers with the shape specified by the
418
+ input.
419
+
420
+ Parameters
421
+ ----------
422
+ shape : tuple[int,...]
423
+ Shape of the array to return.
424
+ Returns
425
+ -------
426
+ np.ndarray
427
+ Array of random numbers with the specified shape.
428
+ """
429
+ return self._rng.standard_t(df = self._dofs,
430
+ size = shape)
431
+
432
+
433
+ class GeneratorBeta(IGeneratorRandom):
434
+ """Class wrapping the numpy beta distribution random generator. Implements
435
+ the IGeneratorRandom interface to allow for interchangeability with other
436
+ random number generators.
437
+ """
438
+ __slots__ = ("_a","_b","_rng")
439
+
440
+ def __init__(self,
441
+ a: float,
442
+ b: float,
443
+ seed: int | None = None) -> None:
444
+ """Initialiser taking the parameters of the probability distribution and
445
+ an optional seed for the random generator to allow for reproducibility.
446
+
447
+ Parameters
448
+ ----------
449
+ a : float
450
+ Alpha parameter of the distribution which must be greater than zero
451
+ b : float
452
+ Beta parameter of the distribution which must be greater than zero
453
+ seed : int | None, optional
454
+ Optional seed for the random generator to allow for reproducibility
455
+ and testing, by default None
456
+ """
457
+ self._a = np.abs(a)
458
+ self._b = np.abs(b)
459
+ self._rng = np.random.default_rng(seed)
460
+
461
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
462
+ """Generates an array of random numbers with the shape specified by the
463
+ input.
464
+
465
+ Parameters
466
+ ----------
467
+ shape : tuple[int,...]
468
+ Shape of the array to return.
469
+ Returns
470
+ -------
471
+ np.ndarray
472
+ Array of random numbers with the specified shape.
473
+ """
474
+ return self._rng.beta(a = self._a,
475
+ b = self._b,
476
+ size = shape)
477
+
478
+
479
+ class GeneratorTriangular(IGeneratorRandom):
480
+ """Class wrapping the numpy triangular random generator. Implements the
481
+ IGeneratorRandom interface to allow for interchangeability with other random
482
+ number generators.
483
+ """
484
+ __slots__ = ("_left","_mode","_right","_rng")
485
+
486
+ def __init__(self,
487
+ left: float = -1.0,
488
+ mode: float = 0.0,
489
+ right: float = 1.0,
490
+ seed: int | None = None) -> None:
491
+ """Initialiser taking the parameters of the probability distribution and
492
+ an optional seed for the random generator to allow for reproducibility.
493
+
494
+ Parameters
495
+ ----------
496
+ left : float, optional
497
+ Left (min) corner of the triangular distribution, by default -1.0
498
+ mode : float, optional
499
+ Central peak of the triangular distribution, by default 0.0
500
+ right : float, optional
501
+ Right (max) corner of the triangular distribution , by default 1.0
502
+ seed : int | None, optional
503
+ Optional seed for the random generator to allow for reproducibility
504
+ and testing, by default None
505
+ """
506
+ self._left = left
507
+ self._mode = mode
508
+ self._right = right
509
+
510
+ self._rng = np.random.default_rng(seed)
511
+
512
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
513
+ """Generates an array of random numbers with the shape specified by the
514
+ input.
515
+
516
+ Parameters
517
+ ----------
518
+ shape : tuple[int,...]
519
+ Shape of the array to return.
520
+ Returns
521
+ -------
522
+ np.ndarray
523
+ Array of random numbers with the specified shape.
524
+ """
525
+ return self._rng.triangular(left = self._left,
526
+ mode = self._mode,
527
+ right = self._right,
528
+ size = shape)