pygeoinf 1.3.8__py3-none-any.whl → 1.3.9__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.
- pygeoinf/__init__.py +36 -0
- pygeoinf/gaussian_measure.py +42 -12
- pygeoinf/plot.py +7 -1
- pygeoinf/preconditioners.py +1 -1
- pygeoinf/subsets.py +845 -0
- pygeoinf/subspaces.py +173 -23
- pygeoinf/symmetric_space/sphere.py +1 -1
- pygeoinf/utils.py +15 -0
- {pygeoinf-1.3.8.dist-info → pygeoinf-1.3.9.dist-info}/METADATA +2 -1
- {pygeoinf-1.3.8.dist-info → pygeoinf-1.3.9.dist-info}/RECORD +12 -10
- {pygeoinf-1.3.8.dist-info → pygeoinf-1.3.9.dist-info}/WHEEL +0 -0
- {pygeoinf-1.3.8.dist-info → pygeoinf-1.3.9.dist-info}/licenses/LICENSE +0 -0
pygeoinf/__init__.py
CHANGED
|
@@ -104,8 +104,27 @@ from .nonlinear_optimisation import (
|
|
|
104
104
|
|
|
105
105
|
from .subspaces import OrthogonalProjector, AffineSubspace, LinearSubspace
|
|
106
106
|
|
|
107
|
+
from .subsets import (
|
|
108
|
+
Subset,
|
|
109
|
+
EmptySet,
|
|
110
|
+
UniversalSet,
|
|
111
|
+
Complement,
|
|
112
|
+
Intersection,
|
|
113
|
+
Union,
|
|
114
|
+
SublevelSet,
|
|
115
|
+
LevelSet,
|
|
116
|
+
ConvexSubset,
|
|
117
|
+
Ellipsoid,
|
|
118
|
+
NormalisedEllipsoid,
|
|
119
|
+
EllipsoidSurface,
|
|
120
|
+
Ball,
|
|
121
|
+
Sphere,
|
|
122
|
+
)
|
|
123
|
+
|
|
107
124
|
from .plot import plot_1d_distributions, plot_corner_distributions
|
|
108
125
|
|
|
126
|
+
from .utils import configure_threading
|
|
127
|
+
|
|
109
128
|
__all__ = [
|
|
110
129
|
# random_matrix
|
|
111
130
|
"fixed_rank_random_range",
|
|
@@ -184,7 +203,24 @@ __all__ = [
|
|
|
184
203
|
"OrthogonalProjector",
|
|
185
204
|
"AffineSubspace",
|
|
186
205
|
"LinearSubspace",
|
|
206
|
+
# Subsets
|
|
207
|
+
"Subset",
|
|
208
|
+
"EmptySet",
|
|
209
|
+
"UniversalSet",
|
|
210
|
+
"Complement",
|
|
211
|
+
"Intersection",
|
|
212
|
+
"Union",
|
|
213
|
+
"SublevelSet",
|
|
214
|
+
"LevelSet",
|
|
215
|
+
"ConvexSubset",
|
|
216
|
+
"Ellipsoid",
|
|
217
|
+
"NormalisedEllipsoid",
|
|
218
|
+
"EllipsoidSurface",
|
|
219
|
+
"Ball",
|
|
220
|
+
"Sphere",
|
|
187
221
|
# plot
|
|
188
222
|
"plot_1d_distributions",
|
|
189
223
|
"plot_corner_distributions",
|
|
224
|
+
# utils
|
|
225
|
+
"configure_threading",
|
|
190
226
|
]
|
pygeoinf/gaussian_measure.py
CHANGED
|
@@ -27,7 +27,7 @@ import numpy as np
|
|
|
27
27
|
from scipy.linalg import eigh
|
|
28
28
|
from scipy.sparse import diags
|
|
29
29
|
from scipy.stats import multivariate_normal
|
|
30
|
-
|
|
30
|
+
from joblib import Parallel, delayed
|
|
31
31
|
|
|
32
32
|
from .hilbert_space import EuclideanSpace, HilbertModule, Vector
|
|
33
33
|
|
|
@@ -44,7 +44,6 @@ from .direct_sum import (
|
|
|
44
44
|
# This block is only processed by type checkers, not at runtime.
|
|
45
45
|
if TYPE_CHECKING:
|
|
46
46
|
from .hilbert_space import HilbertSpace
|
|
47
|
-
from .typing import Vector
|
|
48
47
|
|
|
49
48
|
|
|
50
49
|
class GaussianMeasure:
|
|
@@ -402,24 +401,52 @@ class GaussianMeasure:
|
|
|
402
401
|
raise NotImplementedError("A sample method is not set for this measure.")
|
|
403
402
|
return self._sample()
|
|
404
403
|
|
|
405
|
-
def samples(
|
|
406
|
-
|
|
404
|
+
def samples(
|
|
405
|
+
self, n: int, /, *, parallel: bool = False, n_jobs: int = -1
|
|
406
|
+
) -> List[Vector]:
|
|
407
|
+
"""
|
|
408
|
+
Returns a list of n random samples from the measure.
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
n: Number of samples to draw.
|
|
412
|
+
parallel: If True, draws samples in parallel.
|
|
413
|
+
n_jobs: Number of CPU cores to use. -1 means all available.
|
|
414
|
+
"""
|
|
407
415
|
if n < 1:
|
|
408
416
|
raise ValueError("Number of samples must be a positive integer.")
|
|
409
|
-
return [self.sample() for _ in range(n)]
|
|
410
417
|
|
|
411
|
-
|
|
412
|
-
|
|
418
|
+
if not parallel:
|
|
419
|
+
return [self.sample() for _ in range(n)]
|
|
420
|
+
|
|
421
|
+
return Parallel(n_jobs=n_jobs)(delayed(self.sample)() for _ in range(n))
|
|
422
|
+
|
|
423
|
+
def sample_expectation(
|
|
424
|
+
self, n: int, /, *, parallel: bool = False, n_jobs: int = -1
|
|
425
|
+
) -> Vector:
|
|
426
|
+
"""
|
|
427
|
+
Estimates the expectation by drawing n samples.
|
|
428
|
+
|
|
429
|
+
Args:
|
|
430
|
+
n: Number of samples to draw.
|
|
431
|
+
parallel: If True, draws samples in parallel.
|
|
432
|
+
n_jobs: Number of CPU cores to use. -1 means all available.
|
|
433
|
+
"""
|
|
413
434
|
if n < 1:
|
|
414
435
|
raise ValueError("Number of samples must be a positive integer.")
|
|
415
|
-
return self.domain.sample_expectation(
|
|
436
|
+
return self.domain.sample_expectation(
|
|
437
|
+
self.samples(n, parallel=parallel, n_jobs=n_jobs)
|
|
438
|
+
)
|
|
416
439
|
|
|
417
|
-
def sample_pointwise_variance(
|
|
440
|
+
def sample_pointwise_variance(
|
|
441
|
+
self, n: int, /, *, parallel: bool = False, n_jobs: int = -1
|
|
442
|
+
) -> Vector:
|
|
418
443
|
"""
|
|
419
444
|
Estimates the pointwise variance by drawing n samples.
|
|
420
445
|
|
|
421
|
-
|
|
422
|
-
|
|
446
|
+
Args:
|
|
447
|
+
n: Number of samples to draw.
|
|
448
|
+
parallel: If True, draws samples in parallel.
|
|
449
|
+
n_jobs: Number of CPU cores to use. -1 means all available.
|
|
423
450
|
"""
|
|
424
451
|
if not isinstance(self.domain, HilbertModule):
|
|
425
452
|
raise NotImplementedError(
|
|
@@ -428,7 +455,10 @@ class GaussianMeasure:
|
|
|
428
455
|
if n < 1:
|
|
429
456
|
raise ValueError("Number of samples must be a positive integer.")
|
|
430
457
|
|
|
431
|
-
|
|
458
|
+
# Step 1: Draw samples (Parallelized)
|
|
459
|
+
samples = self.samples(n, parallel=parallel, n_jobs=n_jobs)
|
|
460
|
+
|
|
461
|
+
# Step 2: Compute variance using vector arithmetic
|
|
432
462
|
expectation = self.expectation
|
|
433
463
|
variance = self.domain.zero
|
|
434
464
|
|
pygeoinf/plot.py
CHANGED
|
@@ -220,6 +220,8 @@ def plot_corner_distributions(
|
|
|
220
220
|
show_plot: bool = True,
|
|
221
221
|
include_sigma_contours: bool = True,
|
|
222
222
|
colormap: str = "Blues",
|
|
223
|
+
parallel: bool = False,
|
|
224
|
+
n_jobs: int = -1,
|
|
223
225
|
):
|
|
224
226
|
"""
|
|
225
227
|
Create a corner plot for multi-dimensional posterior distributions.
|
|
@@ -233,6 +235,8 @@ def plot_corner_distributions(
|
|
|
233
235
|
show_plot: Whether to display the plot
|
|
234
236
|
include_sigma_contours: Whether to include 1-sigma contour lines
|
|
235
237
|
colormap: Colormap for 2D plots
|
|
238
|
+
parallel: Compute dense covariance matrix in parallel, default False.
|
|
239
|
+
n_jobs: Number of cores to use in parallel calculations, default -1.
|
|
236
240
|
|
|
237
241
|
Returns:
|
|
238
242
|
fig, axes: Figure and axes array
|
|
@@ -243,7 +247,9 @@ def plot_corner_distributions(
|
|
|
243
247
|
posterior_measure, "covariance"
|
|
244
248
|
):
|
|
245
249
|
mean_posterior = posterior_measure.expectation
|
|
246
|
-
cov_posterior = posterior_measure.covariance.matrix(
|
|
250
|
+
cov_posterior = posterior_measure.covariance.matrix(
|
|
251
|
+
dense=True, parallel=parallel, n_jobs=n_jobs
|
|
252
|
+
)
|
|
247
253
|
else:
|
|
248
254
|
raise ValueError(
|
|
249
255
|
"posterior_measure must have 'expectation' and 'covariance' attributes"
|
pygeoinf/preconditioners.py
CHANGED
|
@@ -36,7 +36,7 @@ class JacobiPreconditioningMethod(LinearSolver):
|
|
|
36
36
|
method: str = "variable",
|
|
37
37
|
rtol: float = 1e-2,
|
|
38
38
|
block_size: int = 10,
|
|
39
|
-
parallel: bool =
|
|
39
|
+
parallel: bool = False,
|
|
40
40
|
n_jobs: int = -1,
|
|
41
41
|
) -> None:
|
|
42
42
|
# Damping is removed: the operator passed to __call__ is already damped
|