CUQIpy 0.5.0.post0.dev9__tar.gz → 0.5.0.post0.dev19__tar.gz
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 CUQIpy might be problematic. Click here for more details.
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/CUQIpy.egg-info/PKG-INFO +1 -1
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/PKG-INFO +1 -1
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/_version.py +3 -3
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/geometry/_geometry.py +105 -26
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_geometry.py +95 -5
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/CUQIpy.egg-info/SOURCES.txt +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/CUQIpy.egg-info/dependency_links.txt +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/CUQIpy.egg-info/requires.txt +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/CUQIpy.egg-info/top_level.txt +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/LICENSE +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/README.md +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/_messages.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/array/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/array/_array.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/config.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/data/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/data/_data.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/data/astronaut.npz +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/data/camera.npz +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/data/cat.npz +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/data/satellite.mat +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/density/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/density/_density.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/diagnostics.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_beta.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_cauchy.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_cmrf.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_custom.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_distribution.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_gamma.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_gaussian.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_gmrf.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_inverse_gamma.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_joint_distribution.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_laplace.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_lmrf.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_lognormal.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_normal.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_posterior.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_uniform.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/geometry/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/likelihood/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/likelihood/_likelihood.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/model/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/model/_model.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/operator/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/operator/_operator.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/pde/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/pde/_pde.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/problem/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/problem/_problem.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_conjugate.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_conjugate_approx.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_cwmh.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_gibbs.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_hmc.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_langevin_algorithm.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_laplace_approximation.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_mh.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_pcn.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_rto.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/sampler/_sampler.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/samples/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/samples/_samples.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/solver/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/solver/_solver.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/testproblem/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/testproblem/_testproblem.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/utilities/__init__.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/utilities/_get_python_variable_name.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/utilities/_utilities.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/pyproject.toml +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/requirements.txt +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/setup.cfg +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/setup.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_MRFs.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_abstract_distribution_density.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_bayesian_inversion.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_density.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_distribution.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_distributions_shape.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_joint_distribution.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_likelihood.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_model.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_pde.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_posterior.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_problem.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_sampler.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_samples.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_solver.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_testproblem.py +0 -0
- {CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_utilities.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: CUQIpy
|
|
3
|
-
Version: 0.5.0.post0.
|
|
3
|
+
Version: 0.5.0.post0.dev19
|
|
4
4
|
Summary: Computational Uncertainty Quantification for Inverse problems in Python
|
|
5
5
|
Maintainer-email: "Nicolai A. B. Riis" <nabr@dtu.dk>, "Jakob S. Jørgensen" <jakj@dtu.dk>, "Amal M. Alghamdi" <amaal@dtu.dk>
|
|
6
6
|
License: Apache License
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: CUQIpy
|
|
3
|
-
Version: 0.5.0.post0.
|
|
3
|
+
Version: 0.5.0.post0.dev19
|
|
4
4
|
Summary: Computational Uncertainty Quantification for Inverse problems in Python
|
|
5
5
|
Maintainer-email: "Nicolai A. B. Riis" <nabr@dtu.dk>, "Jakob S. Jørgensen" <jakj@dtu.dk>, "Amal M. Alghamdi" <amaal@dtu.dk>
|
|
6
6
|
License: Apache License
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2023-09-
|
|
11
|
+
"date": "2023-09-20T22:14:47+0200",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.5.0.post0.
|
|
14
|
+
"full-revisionid": "85066baa356c88fbab83075272f0337134b6d832",
|
|
15
|
+
"version": "0.5.0.post0.dev19"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -331,6 +331,36 @@ class Continuous(Geometry, ABC):
|
|
|
331
331
|
|
|
332
332
|
def fun2par(self,funvals):
|
|
333
333
|
return funvals
|
|
334
|
+
|
|
335
|
+
def _reshape_par2fun_input(self, pars):
|
|
336
|
+
"""Make sure that the parameter last dimension reflects the number of
|
|
337
|
+
parameter vectors: 1 for a single parameter vector and n for n parameter
|
|
338
|
+
vectors."""
|
|
339
|
+
# Ensure pars shape is correct (either squeezed single vector or
|
|
340
|
+
# multiple vectors with the correct shape).
|
|
341
|
+
if pars.shape != self.par_shape and\
|
|
342
|
+
pars.shape[:-1] != self.par_shape:
|
|
343
|
+
raise ValueError(
|
|
344
|
+
f"pars must have shape {self.par_shape} or {self.par_shape}"
|
|
345
|
+
+ "+(n,) where n is the number of parameter vectors")
|
|
346
|
+
|
|
347
|
+
# Add dim to pars if pars is a single parameter vector.
|
|
348
|
+
return pars.reshape(self.par_shape + (-1,))
|
|
349
|
+
|
|
350
|
+
def _reshape_fun2par_input(self, funvals):
|
|
351
|
+
"""Make sure that the function value last dimension reflects the number
|
|
352
|
+
of functions: 1 for a single function and n for n functions."""
|
|
353
|
+
# Ensure funvals shape is correct (either squeezed single function or
|
|
354
|
+
# multiple functions with the correct shape).
|
|
355
|
+
if funvals.shape != self.fun_shape and\
|
|
356
|
+
funvals.shape[:-1] != self.fun_shape:
|
|
357
|
+
raise ValueError(
|
|
358
|
+
f"funvals must have shape {self.fun_shape} or {self.fun_shape}"
|
|
359
|
+
+ "+(n,) where n is the number of functions")
|
|
360
|
+
|
|
361
|
+
# Add dim to funvals if funvals is a single function.
|
|
362
|
+
return funvals.reshape(self.fun_shape + (-1,))
|
|
363
|
+
|
|
334
364
|
|
|
335
365
|
class Continuous1D(Continuous):
|
|
336
366
|
"""A class that represents a continuous 1D geometry.
|
|
@@ -769,6 +799,7 @@ class KLExpansion(Continuous1D):
|
|
|
769
799
|
self._normalizer = normalizer # normalizer factor
|
|
770
800
|
self._num_modes = num_modes # number of modes
|
|
771
801
|
self._coefs = None
|
|
802
|
+
self._coefs_inverse = None
|
|
772
803
|
|
|
773
804
|
@property
|
|
774
805
|
def par_shape(self):
|
|
@@ -796,10 +827,22 @@ class KLExpansion(Continuous1D):
|
|
|
796
827
|
# If the coefficients are not computed, compute them.
|
|
797
828
|
if self._coefs is None or len(self._coefs) != self.num_modes:
|
|
798
829
|
eigvals = np.array(range(1, self.par_dim+1)) # KL eigvals
|
|
799
|
-
self._coefs = 1/np.float_power(eigvals, self.decay_rate)
|
|
830
|
+
self._coefs = np.diag(1/np.float_power(eigvals, self.decay_rate))
|
|
800
831
|
|
|
801
832
|
# Return the coefficients.
|
|
802
833
|
return self._coefs
|
|
834
|
+
|
|
835
|
+
@property
|
|
836
|
+
def coefs_inverse(self):
|
|
837
|
+
"""Computes the inverse of the coefficients diagonal matrix."""
|
|
838
|
+
|
|
839
|
+
# If the matrix is not computed, compute it.
|
|
840
|
+
if self._coefs_inverse is None or\
|
|
841
|
+
len(self._coefs_inverse) != self.num_modes:
|
|
842
|
+
self._coefs_inverse = np.diag(np.float_power(np.diag(self.coefs), -1))
|
|
843
|
+
|
|
844
|
+
# Return the inverse coefficients matrix.
|
|
845
|
+
return self._coefs_inverse
|
|
803
846
|
|
|
804
847
|
@property
|
|
805
848
|
def num_modes(self):
|
|
@@ -816,19 +859,22 @@ class KLExpansion(Continuous1D):
|
|
|
816
859
|
|
|
817
860
|
# computes the real function out of expansion coefs
|
|
818
861
|
def par2fun(self, p):
|
|
819
|
-
# Check that the input is of the correct shape
|
|
820
|
-
if len(p) != self.par_dim:
|
|
821
|
-
raise ValueError(
|
|
822
|
-
"Input array p must have length {}".format(self.par_dim))
|
|
823
862
|
|
|
824
|
-
|
|
863
|
+
# Reshape the parameter vector
|
|
864
|
+
p = self._reshape_par2fun_input(p)
|
|
825
865
|
|
|
826
|
-
|
|
827
|
-
|
|
866
|
+
modes = self.coefs@p/self.normalizer
|
|
867
|
+
|
|
868
|
+
# pad the remaining modes with zeros (for single or multiple parameter
|
|
869
|
+
# parameter vectors)
|
|
870
|
+
modes = np.pad(modes, ((0, self.fun_dim-self.par_dim), (0, 0)),
|
|
828
871
|
'constant', constant_values=0)
|
|
829
872
|
|
|
830
|
-
real = idst(modes)/2
|
|
831
|
-
|
|
873
|
+
real = idst(modes.T).T/2
|
|
874
|
+
|
|
875
|
+
# squeeze to return single function value if only one parameter vector
|
|
876
|
+
# was given
|
|
877
|
+
return real.squeeze()
|
|
832
878
|
|
|
833
879
|
def fun2par(self, funvals):
|
|
834
880
|
"""The function to parameter map used to map function values back to
|
|
@@ -837,11 +883,9 @@ class KLExpansion(Continuous1D):
|
|
|
837
883
|
always the inverse of `par2fun` but it is the closest estimation of the
|
|
838
884
|
function on the KL expansion coefficient space."""
|
|
839
885
|
|
|
840
|
-
#
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
"Input array funvals must have length {}".format(self.fun_dim))
|
|
844
|
-
|
|
886
|
+
# Reshape the function values
|
|
887
|
+
funvals = self._reshape_fun2par_input(funvals)
|
|
888
|
+
|
|
845
889
|
warnings.warn(
|
|
846
890
|
f"fun2par for {self.__class__} is a projection on "
|
|
847
891
|
+ "the KL expansion coefficients space where only "
|
|
@@ -865,10 +909,14 @@ class KLExpansion(Continuous1D):
|
|
|
865
909
|
# However, if we use, for example, scipy.fft instead of scipy.fftpack,
|
|
866
910
|
# then this scaling is not needed.
|
|
867
911
|
|
|
868
|
-
|
|
869
|
-
|
|
912
|
+
# Transform (single or multiple functions) to expansion coefficients
|
|
913
|
+
p_temp = dst(funvals.T*2).T[:self.par_dim,:]
|
|
914
|
+
p = self.coefs_inverse@p_temp*self.normalizer/(2*self.fun_dim)
|
|
915
|
+
|
|
916
|
+
# squeeze to return single parameter vector if only one function value
|
|
917
|
+
# was given
|
|
918
|
+
return p.squeeze()
|
|
870
919
|
|
|
871
|
-
return p
|
|
872
920
|
|
|
873
921
|
class KLExpansion_Full(Continuous1D):
|
|
874
922
|
'''
|
|
@@ -1138,24 +1186,55 @@ class StepExpansion(Continuous1D):
|
|
|
1138
1186
|
return self._n_steps
|
|
1139
1187
|
|
|
1140
1188
|
def par2fun(self, p):
|
|
1141
|
-
|
|
1189
|
+
|
|
1190
|
+
# Reshape the parameter vector
|
|
1191
|
+
p = self._reshape_par2fun_input(p)
|
|
1192
|
+
|
|
1193
|
+
# Extended fun_shape to include multiple functions.
|
|
1194
|
+
ext_fun_shape = self.fun_shape + (p.shape[-1],)
|
|
1195
|
+
|
|
1196
|
+
# Initialize fun to zeros.
|
|
1197
|
+
fun = np.zeros(ext_fun_shape)
|
|
1198
|
+
|
|
1199
|
+
# Fill fun with the step function values.
|
|
1142
1200
|
for i in range(self._n_steps):
|
|
1143
|
-
|
|
1201
|
+
fun[self._indices[i],:] = p[i,:]
|
|
1202
|
+
|
|
1203
|
+
# Squeeze to return single evaluated function if only one parameter
|
|
1204
|
+
# vector was given.
|
|
1205
|
+
return fun.squeeze()
|
|
1144
1206
|
|
|
1145
|
-
return real
|
|
1146
1207
|
|
|
1147
1208
|
def fun2par(self,f):
|
|
1148
|
-
|
|
1209
|
+
|
|
1210
|
+
# Reshape the function values
|
|
1211
|
+
f = self._reshape_fun2par_input(f)
|
|
1212
|
+
|
|
1213
|
+
# Extended par_shape to include multiple parameter vectors.
|
|
1214
|
+
ext_par_shape = self.par_shape + (f.shape[-1],)
|
|
1215
|
+
|
|
1216
|
+
# Initialize par to zeros.
|
|
1217
|
+
par = np.zeros(ext_par_shape)
|
|
1218
|
+
|
|
1219
|
+
# Fill par with the projection of the function values.
|
|
1149
1220
|
for i in range(self._n_steps):
|
|
1150
1221
|
if self._fun2par_projection.lower() == 'mean':
|
|
1151
|
-
|
|
1222
|
+
projection_method = np.mean
|
|
1152
1223
|
elif self._fun2par_projection.lower() == 'max':
|
|
1153
|
-
|
|
1224
|
+
projection_method = np.max
|
|
1154
1225
|
elif self._fun2par_projection.lower() == 'min':
|
|
1155
|
-
|
|
1226
|
+
projection_method = np.min
|
|
1156
1227
|
else:
|
|
1157
1228
|
raise ValueError("Invalid projection option.")
|
|
1158
|
-
|
|
1229
|
+
|
|
1230
|
+
# Apply projection method to the function values in the ith
|
|
1231
|
+
# interval.
|
|
1232
|
+
par[i,:] = projection_method(f[self._indices[i],:], axis=0)
|
|
1233
|
+
|
|
1234
|
+
# Squeeze to return single parameter vector if only one function value
|
|
1235
|
+
# was given.
|
|
1236
|
+
return par.squeeze()
|
|
1237
|
+
|
|
1159
1238
|
|
|
1160
1239
|
def _check_grid_setup(self):
|
|
1161
1240
|
|
|
@@ -145,8 +145,8 @@ def test_geometry_equality(g1, g2, truth_value):
|
|
|
145
145
|
"""Ensure geometry arrays compare correctly"""
|
|
146
146
|
assert (g1==g2) == truth_value
|
|
147
147
|
|
|
148
|
-
@pytest.mark.parametrize("n_steps",[1,2,6,7,9,10,20, 21])
|
|
149
|
-
def test_StepExpansion_geometry(n_steps):
|
|
148
|
+
@pytest.mark.parametrize("n_steps", [1, 2, 6, 7, 9, 10, 20, 21])
|
|
149
|
+
def test_StepExpansion_geometry(n_steps, copy_reference):
|
|
150
150
|
"""Check StepExpansion geometry correctness"""
|
|
151
151
|
grid = np.linspace(0,1,20)
|
|
152
152
|
if n_steps > np.size(grid):
|
|
@@ -159,8 +159,18 @@ def test_StepExpansion_geometry(n_steps):
|
|
|
159
159
|
par = np.random.randn(n_steps)
|
|
160
160
|
geom.plot(par,linestyle = '', marker='.')
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
fun = geom.par2fun(par)
|
|
163
|
+
par2 = geom.fun2par(fun)
|
|
164
|
+
|
|
165
|
+
assert np.allclose(par, par2) \
|
|
163
166
|
and geom.par_dim == n_steps
|
|
167
|
+
|
|
168
|
+
# Assert fun and par2 matches the values in the data file
|
|
169
|
+
ref_file = copy_reference(
|
|
170
|
+
f"data/geometry/test_StepExpansion_{n_steps}.npz")
|
|
171
|
+
ref = np.load(ref_file)
|
|
172
|
+
assert np.allclose(fun, ref["fun"])
|
|
173
|
+
assert np.allclose(par2, ref["par2"])
|
|
164
174
|
|
|
165
175
|
@pytest.mark.parametrize("projection, func",[('MiN', np.min),
|
|
166
176
|
('mAX', np.max),('mean', np.mean)])
|
|
@@ -186,8 +196,13 @@ def test_stepExpansion_fun2par(projection, func):
|
|
|
186
196
|
assert np.allclose(p, qa_f.parameters)
|
|
187
197
|
|
|
188
198
|
@pytest.mark.parametrize("num_modes",[1, 10, 20, 25])
|
|
189
|
-
def test_KL_expansion(num_modes):
|
|
199
|
+
def test_KL_expansion(num_modes, copy_reference):
|
|
190
200
|
"""Check KL expansion geometry correctness"""
|
|
201
|
+
|
|
202
|
+
# File name for reference data
|
|
203
|
+
ref_fname = f"data/geometry/KL_expansion_{num_modes}.npz"
|
|
204
|
+
|
|
205
|
+
# Set up KL expansion geometry
|
|
191
206
|
N = 20
|
|
192
207
|
grid = np.linspace(0, 1, N)
|
|
193
208
|
decay_rate = 2.5
|
|
@@ -199,6 +214,7 @@ def test_KL_expansion(num_modes):
|
|
|
199
214
|
if num_modes > len(grid):
|
|
200
215
|
num_modes = len(grid)
|
|
201
216
|
|
|
217
|
+
# Apply par2fun and check results
|
|
202
218
|
p = np.random.randn(N)
|
|
203
219
|
f_geom = geom.par2fun(p[:num_modes])
|
|
204
220
|
|
|
@@ -211,6 +227,10 @@ def test_KL_expansion(num_modes):
|
|
|
211
227
|
assert geom.par_dim == geom.num_modes
|
|
212
228
|
assert len(geom.grid) == geom.fun_dim
|
|
213
229
|
|
|
230
|
+
# Verify the KL expansion results against the reference data
|
|
231
|
+
ref_file = copy_reference(ref_fname)
|
|
232
|
+
ref = np.load(ref_file)
|
|
233
|
+
assert np.allclose(f_geom, ref["f_geom"])
|
|
214
234
|
|
|
215
235
|
def test_KLExpansion_set_grid():
|
|
216
236
|
"""Check updating grid in KL expansion geometry"""
|
|
@@ -371,7 +391,7 @@ def test_create_CustomKL_geometry():
|
|
|
371
391
|
geom.trunc_term==trunc_term
|
|
372
392
|
|
|
373
393
|
|
|
374
|
-
def test_KLExpansion_projection():
|
|
394
|
+
def test_KLExpansion_projection(copy_reference):
|
|
375
395
|
"""Check KLExpansion geometry projection performed by the method fun2par)"""
|
|
376
396
|
# Set up a KLExpansion geometry
|
|
377
397
|
num_modes = 95
|
|
@@ -399,6 +419,11 @@ def test_KLExpansion_projection():
|
|
|
399
419
|
rel_err = np.linalg.norm(signal-signal_proj)/np.linalg.norm(signal)
|
|
400
420
|
assert np.isclose(rel_err, 0.0, atol=1e-5)
|
|
401
421
|
|
|
422
|
+
# Compare results with reference data
|
|
423
|
+
ref_file = copy_reference("data/geometry/test_KLExpansion_projection.npz")
|
|
424
|
+
ref = np.load(ref_file)
|
|
425
|
+
assert np.allclose(p, ref["p"])
|
|
426
|
+
|
|
402
427
|
def test_DefaultGeometry2D_should_be_image2D():
|
|
403
428
|
geom2D = cuqi.geometry._DefaultGeometry2D((100, 100))
|
|
404
429
|
|
|
@@ -458,3 +483,68 @@ def test_Continuous2D_plot_multiple_funvals_pass(geom2D_funvals):
|
|
|
458
483
|
# Convert to parameters then plot
|
|
459
484
|
multiple_funvals_topar = geom2D.fun2par(multiple_funvals)
|
|
460
485
|
geom2D.plot(multiple_funvals_topar, is_par=True)
|
|
486
|
+
|
|
487
|
+
# Create fixture for KLExpansion geometry
|
|
488
|
+
@pytest.fixture
|
|
489
|
+
def geom_KL():
|
|
490
|
+
"""Returns a KLExpansion geometry"""
|
|
491
|
+
N = 20
|
|
492
|
+
grid = np.linspace(0, 1, N)
|
|
493
|
+
decay_rate = 2.5
|
|
494
|
+
normalizer = 12
|
|
495
|
+
geom = cuqi.geometry.KLExpansion(grid,
|
|
496
|
+
decay_rate=decay_rate,
|
|
497
|
+
normalizer=normalizer,
|
|
498
|
+
num_modes=10)
|
|
499
|
+
return geom
|
|
500
|
+
|
|
501
|
+
# Create fixture for StepExpansion geometry
|
|
502
|
+
@pytest.fixture
|
|
503
|
+
def geom_Step():
|
|
504
|
+
"""Returns a StepExpansion geometry"""
|
|
505
|
+
N = 20
|
|
506
|
+
grid = np.linspace(0, 1, N)
|
|
507
|
+
n_steps = 10
|
|
508
|
+
geom = cuqi.geometry.StepExpansion(grid, n_steps=n_steps)
|
|
509
|
+
return geom
|
|
510
|
+
|
|
511
|
+
# Create fixture to parametrize the tests by geometry
|
|
512
|
+
@pytest.fixture
|
|
513
|
+
def geom(request):
|
|
514
|
+
return request.getfixturevalue(request.param)
|
|
515
|
+
|
|
516
|
+
# Compare par2fun and fun2par for each geometry for individual parameters
|
|
517
|
+
# vectors and multiple parameter vectors
|
|
518
|
+
@pytest.mark.parametrize('geom', ['geom_KL', 'geom_Step'], indirect=True)
|
|
519
|
+
def test_par2fun_and_fun2par_correctness_for_multiple_values(geom):
|
|
520
|
+
"""Check the correctness of the par2fun and fun2par methods for different
|
|
521
|
+
geometries for multiple parameter vectors"""
|
|
522
|
+
|
|
523
|
+
# Create random parameter values
|
|
524
|
+
np.random.seed(0)
|
|
525
|
+
n = 5
|
|
526
|
+
par = np.random.randn(geom.par_dim, n)
|
|
527
|
+
|
|
528
|
+
# run par2fun (first for multiple parameter vectors at once)
|
|
529
|
+
fun = geom.par2fun(par)
|
|
530
|
+
|
|
531
|
+
# run par2fun (for each parameter vector individually)
|
|
532
|
+
fun_ind = np.array([geom.par2fun(par[:, i]) for i in range(n)]).T
|
|
533
|
+
|
|
534
|
+
# Check that the results are the same
|
|
535
|
+
assert np.allclose(fun, fun_ind)
|
|
536
|
+
|
|
537
|
+
# Check plotting runs
|
|
538
|
+
geom.plot(fun, is_par=False)
|
|
539
|
+
|
|
540
|
+
# run fun2par (first for multiple functions at once)
|
|
541
|
+
par2 = geom.fun2par(fun)
|
|
542
|
+
|
|
543
|
+
# run fun2par (for each function individually)
|
|
544
|
+
par2_ind = np.array([geom.fun2par(fun[:, i]) for i in range(n)]).T
|
|
545
|
+
|
|
546
|
+
# Check that the results are the same
|
|
547
|
+
assert np.allclose(par2, par2_ind)
|
|
548
|
+
|
|
549
|
+
# Check plotting runs
|
|
550
|
+
geom.plot(par2, is_par=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/distribution/_joint_distribution.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/cuqi/utilities/_get_python_variable_name.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{CUQIpy-0.5.0.post0.dev9 → CUQIpy-0.5.0.post0.dev19}/tests/test_abstract_distribution_density.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|