CUQIpy 1.3.0.post0.dev300__tar.gz → 1.3.0.post0.dev371__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-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/CUQIpy.egg-info/PKG-INFO +1 -1
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/PKG-INFO +1 -1
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/_version.py +3 -3
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_distribution.py +24 -15
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_rto.py +53 -9
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_sampler.py +10 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/likelihood/_likelihood.py +1 -1
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/model/_model.py +212 -77
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_joint_distribution.py +92 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_likelihood.py +60 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_model.py +375 -8
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_posterior.py +45 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/CUQIpy.egg-info/SOURCES.txt +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/CUQIpy.egg-info/dependency_links.txt +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/CUQIpy.egg-info/requires.txt +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/CUQIpy.egg-info/top_level.txt +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/LICENSE +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/README.md +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/_messages.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/array/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/array/_array.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/config.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/data/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/data/_data.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/data/astronaut.npz +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/data/camera.npz +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/data/cat.npz +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/data/cookie.png +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/data/satellite.mat +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/density/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/density/_density.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/diagnostics.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_beta.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_cauchy.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_cmrf.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_custom.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_gamma.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_gaussian.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_gmrf.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_inverse_gamma.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_joint_distribution.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_laplace.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_lmrf.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_lognormal.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_modifiedhalfnormal.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_normal.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_posterior.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_smoothed_laplace.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_truncated_normal.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/distribution/_uniform.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/_recommender.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/algebra/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/algebra/_ast.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/algebra/_orderedset.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/algebra/_randomvariable.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/geometry/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/geometry/_productgeometry.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_conjugate.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_conjugate_approx.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_cwmh.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_direct.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_gibbs.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_hmc.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_langevin_algorithm.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_laplace_approximation.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_mh.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/experimental/mcmc/_pcn.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/geometry/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/geometry/_geometry.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/implicitprior/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/implicitprior/_regularizedGMRF.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/implicitprior/_regularizedGaussian.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/implicitprior/_regularizedUnboundedUniform.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/implicitprior/_restorator.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/likelihood/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/model/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/operator/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/operator/_operator.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/pde/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/pde/_pde.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/problem/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/problem/_problem.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_conjugate.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_conjugate_approx.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_cwmh.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_gibbs.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_hmc.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_langevin_algorithm.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_laplace_approximation.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_mh.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_pcn.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_rto.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/sampler/_sampler.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/samples/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/samples/_samples.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/solver/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/solver/_solver.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/testproblem/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/testproblem/_testproblem.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/utilities/__init__.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/utilities/_get_python_variable_name.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/cuqi/utilities/_utilities.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/pyproject.toml +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/requirements.txt +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/setup.cfg +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/setup.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_MRFs.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_abstract_distribution_density.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_bayesian_inversion.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_density.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_distribution.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_distributions_shape.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_geometry.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_implicit_priors.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_pde.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_problem.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_sampler.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_samples.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_solver.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_testproblem.py +0 -0
- {cuqipy-1.3.0.post0.dev300 → cuqipy-1.3.0.post0.dev371}/tests/test_utilities.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: CUQIpy
|
|
3
|
-
Version: 1.3.0.post0.
|
|
3
|
+
Version: 1.3.0.post0.dev371
|
|
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>, Chao Zhang <chaz@dtu.dk>
|
|
6
6
|
License: Apache License
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: CUQIpy
|
|
3
|
-
Version: 1.3.0.post0.
|
|
3
|
+
Version: 1.3.0.post0.dev371
|
|
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>, Chao Zhang <chaz@dtu.dk>
|
|
6
6
|
License: Apache License
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2025-09-
|
|
11
|
+
"date": "2025-09-12T10:46:36+0200",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "1.3.0.post0.
|
|
14
|
+
"full-revisionid": "1bd165981a9e7200ec642e2845ffde05a7e8a168",
|
|
15
|
+
"version": "1.3.0.post0.dev371"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -105,7 +105,7 @@ class Distribution(Density, ABC):
|
|
|
105
105
|
f"Inconsistent distribution geometry attribute {self._geometry} and inferred "
|
|
106
106
|
f"dimension from distribution variables {inferred_dim}."
|
|
107
107
|
)
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
# If Geometry dimension is None, update it with the inferred dimension
|
|
110
110
|
if inferred_dim and self._geometry.par_dim is None:
|
|
111
111
|
self.geometry = inferred_dim
|
|
@@ -117,7 +117,7 @@ class Distribution(Density, ABC):
|
|
|
117
117
|
# We do not use self.name to potentially infer it from python stack.
|
|
118
118
|
if self._name:
|
|
119
119
|
self._geometry._variable_name = self._name
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
return self._geometry
|
|
122
122
|
|
|
123
123
|
@geometry.setter
|
|
@@ -160,7 +160,7 @@ class Distribution(Density, ABC):
|
|
|
160
160
|
f"{self.logd.__qualname__}: To evaluate the log density all conditioning variables and main"
|
|
161
161
|
f" parameter must be specified. Conditioning variables are: {cond_vars}"
|
|
162
162
|
)
|
|
163
|
-
|
|
163
|
+
|
|
164
164
|
# Check if all conditioning variables are specified
|
|
165
165
|
all_cond_vars_specified = all([key in kwargs for key in cond_vars])
|
|
166
166
|
if not all_cond_vars_specified:
|
|
@@ -168,7 +168,7 @@ class Distribution(Density, ABC):
|
|
|
168
168
|
f"{self.logd.__qualname__}: To evaluate the log density all conditioning variables must be"
|
|
169
169
|
f" specified. Conditioning variables are: {cond_vars}"
|
|
170
170
|
)
|
|
171
|
-
|
|
171
|
+
|
|
172
172
|
# Extract exactly the conditioning variables from kwargs
|
|
173
173
|
cond_kwargs = {key: kwargs[key] for key in cond_vars}
|
|
174
174
|
|
|
@@ -186,7 +186,7 @@ class Distribution(Density, ABC):
|
|
|
186
186
|
# Not conditional distribution, simply evaluate log density directly
|
|
187
187
|
else:
|
|
188
188
|
return super().logd(*args, **kwargs)
|
|
189
|
-
|
|
189
|
+
|
|
190
190
|
def _logd(self, *args):
|
|
191
191
|
return self.logpdf(*args) # Currently all distributions implement logpdf so we simply call this method.
|
|
192
192
|
|
|
@@ -216,7 +216,7 @@ class Distribution(Density, ABC):
|
|
|
216
216
|
# Get samples from the distribution sample method
|
|
217
217
|
s = self._sample(N,*args,**kwargs)
|
|
218
218
|
|
|
219
|
-
#Store samples in cuqi samples object if more than 1 sample
|
|
219
|
+
# Store samples in cuqi samples object if more than 1 sample
|
|
220
220
|
if N==1:
|
|
221
221
|
if len(s) == 1 and isinstance(s,np.ndarray): #Extract single value from numpy array
|
|
222
222
|
s = s.ravel()[0]
|
|
@@ -264,7 +264,7 @@ class Distribution(Density, ABC):
|
|
|
264
264
|
# Go through every mutable variable and assign value from kwargs if present
|
|
265
265
|
for var_key in mutable_vars:
|
|
266
266
|
|
|
267
|
-
#If keyword directly specifies new value of variable we simply reassign
|
|
267
|
+
# If keyword directly specifies new value of variable we simply reassign
|
|
268
268
|
if var_key in kwargs:
|
|
269
269
|
setattr(new_dist, var_key, kwargs.get(var_key))
|
|
270
270
|
processed_kwargs.add(var_key)
|
|
@@ -291,9 +291,18 @@ class Distribution(Density, ABC):
|
|
|
291
291
|
|
|
292
292
|
elif len(var_args)>0: #Some keywords found
|
|
293
293
|
# Define new partial function with partially defined args
|
|
294
|
-
|
|
294
|
+
if (
|
|
295
|
+
hasattr(var_val, "_supports_partial_eval")
|
|
296
|
+
and var_val._supports_partial_eval
|
|
297
|
+
):
|
|
298
|
+
func = var_val(**var_args)
|
|
299
|
+
else:
|
|
300
|
+
# If the callable does not support partial evaluation,
|
|
301
|
+
# we use the partial function to set the variable
|
|
302
|
+
func = partial(var_val, **var_args)
|
|
303
|
+
|
|
295
304
|
setattr(new_dist, var_key, func)
|
|
296
|
-
|
|
305
|
+
|
|
297
306
|
# Store processed keywords
|
|
298
307
|
processed_kwargs.update(var_args.keys())
|
|
299
308
|
|
|
@@ -329,7 +338,7 @@ class Distribution(Density, ABC):
|
|
|
329
338
|
|
|
330
339
|
def get_conditioning_variables(self):
|
|
331
340
|
"""Return the conditioning variables of this distribution (if any)."""
|
|
332
|
-
|
|
341
|
+
|
|
333
342
|
# Get all mutable variables
|
|
334
343
|
mutable_vars = self.get_mutable_variables()
|
|
335
344
|
|
|
@@ -338,7 +347,7 @@ class Distribution(Density, ABC):
|
|
|
338
347
|
|
|
339
348
|
# Add any variables defined through callable functions
|
|
340
349
|
cond_vars += get_indirect_variables(self)
|
|
341
|
-
|
|
350
|
+
|
|
342
351
|
return cond_vars
|
|
343
352
|
|
|
344
353
|
def get_mutable_variables(self):
|
|
@@ -347,10 +356,10 @@ class Distribution(Density, ABC):
|
|
|
347
356
|
# If mutable variables are already cached, return them
|
|
348
357
|
if hasattr(self, '_mutable_vars'):
|
|
349
358
|
return self._mutable_vars
|
|
350
|
-
|
|
359
|
+
|
|
351
360
|
# Define list of ignored attributes and properties
|
|
352
361
|
ignore_vars = ['name', 'is_symmetric', 'geometry', 'dim']
|
|
353
|
-
|
|
362
|
+
|
|
354
363
|
# Get public attributes
|
|
355
364
|
attributes = get_writeable_attributes(self)
|
|
356
365
|
|
|
@@ -396,7 +405,7 @@ class Distribution(Density, ABC):
|
|
|
396
405
|
raise ValueError(f"{self._condition.__qualname__}: {ordered_keys[index]} passed as both argument and keyword argument.\nArguments follow the listed conditioning variable order: {self.get_conditioning_variables()}")
|
|
397
406
|
kwargs[ordered_keys[index]] = arg
|
|
398
407
|
return kwargs
|
|
399
|
-
|
|
408
|
+
|
|
400
409
|
def _check_geometry_consistency(self):
|
|
401
410
|
""" Checks that the geometry of the distribution is consistent by calling the geometry property. Should be called at the end of __init__ of subclasses. """
|
|
402
411
|
self.geometry
|
|
@@ -411,4 +420,4 @@ class Distribution(Density, ABC):
|
|
|
411
420
|
def rv(self):
|
|
412
421
|
""" Return a random variable object representing the distribution. """
|
|
413
422
|
from cuqi.experimental.algebra import RandomVariable
|
|
414
|
-
return RandomVariable(self)
|
|
423
|
+
return RandomVariable(self)
|
|
@@ -36,21 +36,48 @@ class LinearRTO(Sampler):
|
|
|
36
36
|
tol : float
|
|
37
37
|
Tolerance of the inner CGLS solver. *Optional*.
|
|
38
38
|
|
|
39
|
+
inner_initial_point : string or np.ndarray or cuqi.array.CUQIArray
|
|
40
|
+
Initial point for the inner optimization problem. Can be "previous_sample" (default), "MAP", or a specific numpy or cuqi array. *Optional*.
|
|
41
|
+
|
|
39
42
|
callback : callable, optional
|
|
40
43
|
A function that will be called after each sampling step. It can be useful for monitoring the sampler during sampling.
|
|
41
44
|
The function should take three arguments: the sampler object, the index of the current sampling step, the total number of requested samples. The last two arguments are integers. An example of the callback function signature is: `callback(sampler, sample_index, num_of_samples)`.
|
|
42
45
|
|
|
43
46
|
"""
|
|
44
|
-
def __init__(self, target=None, initial_point=None, maxit=10, tol=1e-6, **kwargs):
|
|
47
|
+
def __init__(self, target=None, initial_point=None, maxit=10, tol=1e-6, inner_initial_point="previous_sample", **kwargs):
|
|
45
48
|
|
|
46
49
|
super().__init__(target=target, initial_point=initial_point, **kwargs)
|
|
47
50
|
|
|
48
51
|
# Other parameters
|
|
49
52
|
self.maxit = maxit
|
|
50
53
|
self.tol = tol
|
|
54
|
+
self.inner_initial_point = inner_initial_point
|
|
51
55
|
|
|
52
56
|
def _initialize(self):
|
|
53
57
|
self._precompute()
|
|
58
|
+
self._compute_map()
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def inner_initial_point(self):
|
|
62
|
+
if isinstance(self._inner_initial_point, str):
|
|
63
|
+
if self._inner_initial_point == "previous_sample":
|
|
64
|
+
return self.current_point
|
|
65
|
+
elif self._inner_initial_point == "map":
|
|
66
|
+
return self._map
|
|
67
|
+
else:
|
|
68
|
+
return self._inner_initial_point
|
|
69
|
+
|
|
70
|
+
@inner_initial_point.setter
|
|
71
|
+
def inner_initial_point(self, value):
|
|
72
|
+
is_correct_string = (isinstance(value, str) and
|
|
73
|
+
(value.lower() == "previous_sample" or
|
|
74
|
+
value.lower() == "map"))
|
|
75
|
+
if is_correct_string:
|
|
76
|
+
self._inner_initial_point = value.lower()
|
|
77
|
+
elif isinstance(value, (np.ndarray, cuqi.array.CUQIarray)):
|
|
78
|
+
self._inner_initial_point = value
|
|
79
|
+
else:
|
|
80
|
+
raise ValueError("Invalid value for inner_initial_point. Choose either 'previous_sample', 'MAP', or provide a numpy array/cuqi array.")
|
|
54
81
|
|
|
55
82
|
@property
|
|
56
83
|
def prior(self):
|
|
@@ -78,6 +105,10 @@ class LinearRTO(Sampler):
|
|
|
78
105
|
elif isinstance(self.target, cuqi.distribution.MultipleLikelihoodPosterior):
|
|
79
106
|
return self.target.models
|
|
80
107
|
|
|
108
|
+
def _compute_map(self):
|
|
109
|
+
sim = CGLS(self.M, self.b_tild, self.current_point, self.maxit, self.tol)
|
|
110
|
+
self._map, _ = sim.solve()
|
|
111
|
+
|
|
81
112
|
def _precompute(self):
|
|
82
113
|
L1 = [likelihood.distribution.sqrtprec for likelihood in self.likelihoods]
|
|
83
114
|
L2 = self.prior.sqrtprec
|
|
@@ -114,7 +145,7 @@ class LinearRTO(Sampler):
|
|
|
114
145
|
|
|
115
146
|
def step(self):
|
|
116
147
|
y = self.b_tild + np.random.randn(len(self.b_tild))
|
|
117
|
-
sim = CGLS(self.M, y, self.
|
|
148
|
+
sim = CGLS(self.M, y, self.inner_initial_point, self.maxit, self.tol)
|
|
118
149
|
self.current_point, _ = sim.solve()
|
|
119
150
|
acc = 1
|
|
120
151
|
return acc
|
|
@@ -203,12 +234,15 @@ class RegularizedLinearRTO(LinearRTO):
|
|
|
203
234
|
solver : string
|
|
204
235
|
Options are "FISTA" (default for a single constraint or regularization), "ADMM" (default and the only option for multiple constraints or regularizations), "ScipyLinearLSQ" and "ScipyMinimizer". Note "ScipyLinearLSQ" and "ScipyMinimizer" can only be used with `RegularizedGaussian` of a single `box` or `nonnegativity` constraint. *Optional*.
|
|
205
236
|
|
|
237
|
+
inner_initial_point : string or np.ndarray or cuqi.array.CUQIArray
|
|
238
|
+
Initial point for the inner optimization problem. Can be "previous_sample" (default), "MAP", or a specific numpy or cuqi array. *Optional*.
|
|
239
|
+
|
|
206
240
|
callback : callable, optional
|
|
207
241
|
A function that will be called after each sampling step. It can be useful for monitoring the sampler during sampling.
|
|
208
242
|
The function should take three arguments: the sampler object, the index of the current sampling step, the total number of requested samples. The last two arguments are integers. An example of the callback function signature is: `callback(sampler, sample_index, num_of_samples)`.
|
|
209
243
|
|
|
210
244
|
"""
|
|
211
|
-
def __init__(self, target=None, initial_point=None, maxit=100, inner_max_it=10, stepsize="automatic", penalty_parameter=10, abstol=1e-10, adaptive=True, solver=None, inner_abstol=None, **kwargs):
|
|
245
|
+
def __init__(self, target=None, initial_point=None, maxit=100, inner_max_it=10, stepsize="automatic", penalty_parameter=10, abstol=1e-10, adaptive=True, solver=None, inner_abstol=None, inner_initial_point="previous_sample", **kwargs):
|
|
212
246
|
|
|
213
247
|
super().__init__(target=target, initial_point=initial_point, **kwargs)
|
|
214
248
|
|
|
@@ -221,6 +255,7 @@ class RegularizedLinearRTO(LinearRTO):
|
|
|
221
255
|
self.inner_max_it = inner_max_it
|
|
222
256
|
self.penalty_parameter = penalty_parameter
|
|
223
257
|
self.solver = solver
|
|
258
|
+
self.inner_initial_point = inner_initial_point
|
|
224
259
|
|
|
225
260
|
def _initialize(self):
|
|
226
261
|
super()._initialize()
|
|
@@ -228,6 +263,7 @@ class RegularizedLinearRTO(LinearRTO):
|
|
|
228
263
|
self.solver = "FISTA" if callable(self.proximal) else "ADMM"
|
|
229
264
|
if self.solver == "FISTA":
|
|
230
265
|
self._stepsize = self._choose_stepsize()
|
|
266
|
+
self._compute_map_regularized()
|
|
231
267
|
|
|
232
268
|
@property
|
|
233
269
|
def solver(self):
|
|
@@ -272,15 +308,16 @@ class RegularizedLinearRTO(LinearRTO):
|
|
|
272
308
|
def prior(self):
|
|
273
309
|
return self.target.prior.gaussian
|
|
274
310
|
|
|
275
|
-
def
|
|
276
|
-
|
|
311
|
+
def _compute_map_regularized(self):
|
|
312
|
+
self._map = self._customized_step(self.b_tild, self.initial_point)
|
|
277
313
|
|
|
314
|
+
def _customized_step(self, y, x0):
|
|
278
315
|
if self.solver == "FISTA":
|
|
279
316
|
sim = FISTA(self.M, y, self.proximal,
|
|
280
|
-
|
|
317
|
+
x0, maxit = self.maxit, stepsize = self._stepsize, abstol = self.abstol, adaptive = self.adaptive)
|
|
281
318
|
elif self.solver == "ADMM":
|
|
282
319
|
sim = ADMM(self.M, y, self.proximal,
|
|
283
|
-
|
|
320
|
+
x0, self.penalty_parameter, maxit = self.maxit, inner_max_it = self.inner_max_it, adaptive = self.adaptive)
|
|
284
321
|
elif self.solver == "ScipyLinearLSQ":
|
|
285
322
|
A_op = sp.sparse.linalg.LinearOperator((sum([llh.distribution.dim for llh in self.likelihoods])+self.target.prior.dim, self.target.prior.dim),
|
|
286
323
|
matvec=lambda x: self.M(x, 1),
|
|
@@ -297,10 +334,17 @@ class RegularizedLinearRTO(LinearRTO):
|
|
|
297
334
|
bounds = [(self.target.prior._box_bounds[0][i], self.target.prior._box_bounds[1][i]) for i in range(self.target.prior.dim)]
|
|
298
335
|
# Note that the objective function is defined as 0.5*||Mx-y||^2,
|
|
299
336
|
# and the corresponding gradient (gradfunc) is given by M^T(Mx-y).
|
|
300
|
-
sim = ScipyMinimizer(lambda x: 0.5*np.sum((self.M(x, 1)-y)**2),
|
|
337
|
+
sim = ScipyMinimizer(lambda x: 0.5*np.sum((self.M(x, 1)-y)**2), x0, gradfunc=lambda x: self.M(self.M(x, 1) - y, 2), bounds=bounds, tol=self.abstol, options={"maxiter": self.maxit})
|
|
301
338
|
else:
|
|
302
339
|
raise ValueError("Choice of solver not supported.")
|
|
340
|
+
|
|
341
|
+
sol, _ = sim.solve()
|
|
342
|
+
return sol
|
|
343
|
+
|
|
344
|
+
def step(self):
|
|
345
|
+
y = self.b_tild + np.random.randn(len(self.b_tild))
|
|
346
|
+
|
|
347
|
+
self.current_point = self._customized_step(y, self.inner_initial_point)
|
|
303
348
|
|
|
304
|
-
self.current_point, _ = sim.solve()
|
|
305
349
|
acc = 1
|
|
306
350
|
return acc
|
|
@@ -148,6 +148,16 @@ class Sampler(ABC):
|
|
|
148
148
|
if self._target is not None:
|
|
149
149
|
self.validate_target()
|
|
150
150
|
|
|
151
|
+
@property
|
|
152
|
+
def current_point(self):
|
|
153
|
+
""" The current point of the sampler. """
|
|
154
|
+
return self._current_point
|
|
155
|
+
|
|
156
|
+
@current_point.setter
|
|
157
|
+
def current_point(self, value):
|
|
158
|
+
""" Set the current point of the sampler. """
|
|
159
|
+
self._current_point = value
|
|
160
|
+
|
|
151
161
|
# ------------ Public methods ------------
|
|
152
162
|
def get_samples(self) -> Samples:
|
|
153
163
|
""" Return the samples. The internal data-structure for the samples is a dynamic list so this creates a copy. """
|
|
@@ -212,4 +212,4 @@ class UserDefinedLikelihood(object):
|
|
|
212
212
|
return get_non_default_args(self.logpdf_func)
|
|
213
213
|
|
|
214
214
|
def __repr__(self) -> str:
|
|
215
|
-
return "CUQI {} function. Parameters {}.".format(self.__class__.__name__,self.get_parameter_names())
|
|
215
|
+
return "CUQI {} function. Parameters {}.".format(self.__class__.__name__,self.get_parameter_names())
|