CUQIpy 1.3.0.post0.dev383__py3-none-any.whl → 1.3.0.post0.dev401__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 CUQIpy might be problematic. Click here for more details.

cuqi/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-09-12T11:00:39+0200",
11
+ "date": "2025-09-21T15:00:42+0200",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "37e1d4431766233eccce97c09eb773486ed25032",
15
- "version": "1.3.0.post0.dev383"
14
+ "full-revisionid": "f08eb2ae4f6f5209d4a06a4e031bc61bb746ce01",
15
+ "version": "1.3.0.post0.dev401"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -1,5 +1,6 @@
1
1
  from cuqi.geometry import _DefaultGeometry, _get_identity_geometries
2
2
  from cuqi.distribution import Distribution
3
+ from cuqi.density import Density
3
4
 
4
5
  # ========================================================================
5
6
  class Posterior(Distribution):
@@ -25,6 +26,14 @@ class Posterior(Distribution):
25
26
  self.prior = prior
26
27
  super().__init__(**kwargs)
27
28
 
29
+ def get_density(self, name) -> Density:
30
+ """ Return a density with the given name. """
31
+ if name == self.likelihood.name:
32
+ return self.likelihood
33
+ if name == self.prior.name:
34
+ return self.prior
35
+ raise ValueError(f"No density with name {name}.")
36
+
28
37
  @property
29
38
  def data(self):
30
39
  return self.likelihood.data
@@ -1,7 +1,6 @@
1
- from cuqi.distribution import JointDistribution
1
+ from cuqi.distribution import JointDistribution, Posterior
2
2
  from cuqi.experimental.mcmc import Sampler
3
3
  from cuqi.samples import Samples, JointSamples
4
- from cuqi.experimental.mcmc import NUTS
5
4
  from typing import Dict
6
5
  import numpy as np
7
6
  import warnings
@@ -36,11 +35,10 @@ class HybridGibbs:
36
35
  Gelman et al. "Bayesian Data Analysis" (2014), Third Edition
37
36
  for more details.
38
37
 
39
- In each Gibbs step, the corresponding sampler has the initial_point
40
- and initial_scale (if applicable) set to the value of the previous step
41
- and the sampler is reinitialized. This means that the sampling is not
42
- fully stateful at this point. This means samplers like NUTS will lose
43
- their internal state between Gibbs steps.
38
+ In each Gibbs step, the corresponding sampler state and history are stored,
39
+ then the sampler is reinitialized. After reinitialization, the sampler state
40
+ and history are set back to the stored values. This ensures preserving the
41
+ statefulness of the samplers.
44
42
 
45
43
  The order in which the conditionals are sampled is the order of the
46
44
  variables in the sampling strategy, unless a different sampling order
@@ -177,8 +175,8 @@ class HybridGibbs:
177
175
  # ------------ Public methods ------------
178
176
  def validate_targets(self):
179
177
  """ Validate each of the conditional targets used in the Gibbs steps """
180
- if not isinstance(self.target, JointDistribution):
181
- raise ValueError('Target distribution must be a JointDistribution.')
178
+ if not isinstance(self.target, (JointDistribution, Posterior)):
179
+ raise ValueError('Target distribution must be a JointDistribution or Posterior.')
182
180
  for sampler in self.samplers.values():
183
181
  sampler.validate_target()
184
182
 
@@ -257,19 +255,15 @@ class HybridGibbs:
257
255
  # before reinitializing the sampler and then set the state and history back to the sampler
258
256
 
259
257
  # Extract state and history from sampler
260
- if isinstance(sampler, NUTS): # Special case for NUTS as it is not playing nice with get_state and get_history
261
- sampler.initial_point = sampler.current_point
262
- else:
263
- sampler_state = sampler.get_state()
264
- sampler_history = sampler.get_history()
258
+ sampler_state = sampler.get_state()
259
+ sampler_history = sampler.get_history()
265
260
 
266
261
  # Reinitialize sampler
267
262
  sampler.reinitialize()
268
263
 
269
264
  # Set state and history back to sampler
270
- if not isinstance(sampler, NUTS): # Again, special case for NUTS.
271
- sampler.set_state(sampler_state)
272
- sampler.set_history(sampler_history)
265
+ sampler.set_state(sampler_state)
266
+ sampler.set_history(sampler_history)
273
267
 
274
268
  # Allow for multiple sampling steps in each Gibbs step
275
269
  for _ in range(self.num_sampling_steps[par_name]):
@@ -309,8 +303,6 @@ class HybridGibbs:
309
303
  def _initialize_samplers(self):
310
304
  """ Initialize samplers """
311
305
  for sampler in self.samplers.values():
312
- if isinstance(sampler, NUTS):
313
- print(f'Warning: NUTS sampler is not fully stateful in HybridGibbs. Sampler will be reinitialized in each Gibbs step.')
314
306
  sampler.initialize()
315
307
 
316
308
  def _initialize_num_sampling_steps(self):
@@ -118,8 +118,10 @@ class NUTS(Sampler):
118
118
  # to epsilon_bar for the remaining sampling steps.
119
119
  if self.step_size is None:
120
120
  self._epsilon = self._FindGoodEpsilon()
121
+ self.step_size = self._epsilon
121
122
  else:
122
123
  self._epsilon = self.step_size
124
+
123
125
  self._epsilon_bar = "unset"
124
126
 
125
127
  # Parameter mu, does not change during the run
@@ -127,7 +129,7 @@ class NUTS(Sampler):
127
129
 
128
130
  self._H_bar = 0
129
131
 
130
- # NUTS run diagnostic:
132
+ # NUTS run diagnostics
131
133
  # number of tree nodes created each NUTS iteration
132
134
  self._num_tree_node = 0
133
135
 
@@ -203,13 +203,16 @@ class Sampler(ABC):
203
203
 
204
204
  self.set_state(state)
205
205
 
206
- def sample(self, Ns, batch_size=0, sample_path='./CUQI_samples/') -> 'Sampler':
206
+ def sample(self, Ns, Nt=1, batch_size=0, sample_path='./CUQI_samples/') -> 'Sampler':
207
207
  """ Sample Ns samples from the target density.
208
208
 
209
209
  Parameters
210
210
  ----------
211
211
  Ns : int
212
212
  The number of samples to draw.
213
+
214
+ Nt : int, optional, default=1
215
+ The thinning interval. If Nt >= 1, every Nt'th sample is stored. The larger Nt, the fewer samples are stored.
213
216
 
214
217
  batch_size : int, optional
215
218
  The batch size for saving samples to disk. If 0, no batching is used. If positive, samples are saved to disk in batches of the specified size.
@@ -233,7 +236,8 @@ class Sampler(ABC):
233
236
 
234
237
  # Store samples
235
238
  self._acc.append(acc)
236
- self._samples.append(self.current_point)
239
+ if (Nt > 0) and ((idx + 1) % Nt == 0):
240
+ self._samples.append(self.current_point)
237
241
 
238
242
  # display acc rate at progress bar
239
243
  pbar.set_postfix_str(f"acc rate: {np.mean(self._acc[-1-idx:]):.2%}")
@@ -248,7 +252,7 @@ class Sampler(ABC):
248
252
  return self
249
253
 
250
254
 
251
- def warmup(self, Nb, tune_freq=0.1) -> 'Sampler':
255
+ def warmup(self, Nb, Nt=1, tune_freq=0.1) -> 'Sampler':
252
256
  """ Warmup the sampler by drawing Nb samples.
253
257
 
254
258
  Parameters
@@ -256,6 +260,9 @@ class Sampler(ABC):
256
260
  Nb : int
257
261
  The number of samples to draw during warmup.
258
262
 
263
+ Nt : int, optional, default=1
264
+ The thinning interval. If Nt >= 1, every Nt'th sample is stored. The larger Nt, the fewer samples are stored.
265
+
259
266
  tune_freq : float, optional
260
267
  The frequency of tuning. Tuning is performed every tune_freq*Nb samples.
261
268
 
@@ -278,7 +285,8 @@ class Sampler(ABC):
278
285
 
279
286
  # Store samples
280
287
  self._acc.append(acc)
281
- self._samples.append(self.current_point)
288
+ if (Nt > 0) and ((idx + 1) % Nt == 0):
289
+ self._samples.append(self.current_point)
282
290
 
283
291
  # display acc rate at progress bar
284
292
  pbar.set_postfix_str(f"acc rate: {np.mean(self._acc[-1-idx:]):.2%}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: CUQIpy
3
- Version: 1.3.0.post0.dev383
3
+ Version: 1.3.0.post0.dev401
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
  cuqi/__init__.py,sha256=LsGilhl-hBLEn6Glt8S_l0OJzAA1sKit_rui8h-D-p0,488
2
2
  cuqi/_messages.py,sha256=fzEBrZT2kbmfecBBPm7spVu7yHdxGARQB4QzXhJbCJ0,415
3
- cuqi/_version.py,sha256=LUmpDb5TQH2Im-0D07aiwVInfnQ-YF_piMNHdOOlmOs,510
3
+ cuqi/_version.py,sha256=SOLnTN23-4JLBv2uoi0W2XEn60t_evUNUHfiMB7jrSo,510
4
4
  cuqi/config.py,sha256=wcYvz19wkeKW2EKCGIKJiTpWt5kdaxyt4imyRkvtTRA,526
5
5
  cuqi/diagnostics.py,sha256=5OrbJeqpynqRXOe5MtOKKhe7EAVdOEpHIqHnlMW9G_c,3029
6
6
  cuqi/array/__init__.py,sha256=-EeiaiWGNsE3twRS4dD814BIlfxEsNkTCZUc5gjOXb0,30
@@ -30,7 +30,7 @@ cuqi/distribution/_lmrf.py,sha256=rdGoQ-fPe1oW6Z29P-l3woq0NX3_RxUQ2rzm1VzemNM,32
30
30
  cuqi/distribution/_lognormal.py,sha256=8_hOFQ3iu88ujX8vxmfVEZ0fdmlhTY98PlG5PasPjEg,2612
31
31
  cuqi/distribution/_modifiedhalfnormal.py,sha256=ErULXUFRjbMyCYywaOzfuxtoy-XQmC0McMROo2mTQtc,7313
32
32
  cuqi/distribution/_normal.py,sha256=vhIiAseW09IKh1uy0KUq7RP1IuY7hH5aNM1W_R8Gd_Q,2912
33
- cuqi/distribution/_posterior.py,sha256=zAfL0GECxekZ2lBt1W6_LN0U_xskMwK4VNce5xAF7ig,5018
33
+ cuqi/distribution/_posterior.py,sha256=6LxXAIBzFxyEqx5bUfgqTXVKgXxqNhRItec6FcRVLEE,5350
34
34
  cuqi/distribution/_smoothed_laplace.py,sha256=p-1Y23mYA9omwiHGkEuv3T2mwcPAAoNlCr7T8osNkjE,2925
35
35
  cuqi/distribution/_truncated_normal.py,sha256=_ez3MmO6qpBeP6BKCUlW3IgxuF7k--A7jPGPUhtYK0g,4240
36
36
  cuqi/distribution/_uniform.py,sha256=fVgj_4SBav8JMc1pNAO1l_CZ9ZwdoMIpN9iQ3i9_Z0Q,3255
@@ -47,14 +47,14 @@ cuqi/experimental/mcmc/_conjugate.py,sha256=vqucxC--pihBCUcupdcIo4ymDPPjmMKGb7OL
47
47
  cuqi/experimental/mcmc/_conjugate_approx.py,sha256=jmxe2FEbO9fwpc8opyjJ2px0oed3dGyj0qDwyHo4aOk,3545
48
48
  cuqi/experimental/mcmc/_cwmh.py,sha256=cAvtc3tex53ZUKPMGwj2RIkHAZurpqphko8nk8_DmJs,7340
49
49
  cuqi/experimental/mcmc/_direct.py,sha256=9pQS_2Qk2-ybt6m8WTfPoKetcxQ00WaTRN85-Z0FrBY,777
50
- cuqi/experimental/mcmc/_gibbs.py,sha256=9Qutc60xoVTvKYRkirQhXEDiQ75mbjyxU7utblmu1C8,14567
51
- cuqi/experimental/mcmc/_hmc.py,sha256=LXXOb6cztfjraGIuTGpgf0ndc1xkkBW9v_PfNffu-NA,19438
50
+ cuqi/experimental/mcmc/_gibbs.py,sha256=k4lVFDha8YNYQ6EXZ6B1kb_3gnJLmsV1Sh_53TaaVME,14021
51
+ cuqi/experimental/mcmc/_hmc.py,sha256=ifDdvs1DPsgQywRyDZx_a4AfzrAM9QaAQk1y0l7Hj6g,19482
52
52
  cuqi/experimental/mcmc/_langevin_algorithm.py,sha256=1UunuocpzG1h6GiYefEHFOMykEMlYady6Fmuu9CHxHQ,15059
53
53
  cuqi/experimental/mcmc/_laplace_approximation.py,sha256=I5ZLtU0lA34YflRbqxKi5UgJBhhHzxqUyVW5JE5-l2w,5916
54
54
  cuqi/experimental/mcmc/_mh.py,sha256=MXo0ahXP4KGFkaY4HtvcBE-TMQzsMlTmLKzSvpz7drU,2941
55
55
  cuqi/experimental/mcmc/_pcn.py,sha256=wqJBZLuRFSwxihaI53tumAg6AWVuceLMOmXssTetd1A,3374
56
56
  cuqi/experimental/mcmc/_rto.py,sha256=O_bBeQbaYy5im5LKAhwin3uRCJpyFPcKVDH8GxriXEY,17196
57
- cuqi/experimental/mcmc/_sampler.py,sha256=lClOyxTnHpjohb7hQcO9SSYMvOGxZMXWK_SrEsTTsvw,20570
57
+ cuqi/experimental/mcmc/_sampler.py,sha256=7_a9i6A7AX3NNz7qK1jTsEYt6bFCUR5WK464KfH_Kvc,21034
58
58
  cuqi/geometry/__init__.py,sha256=Tz1WGzZBY-QGH3c0GiyKm9XHN8MGGcnU6TUHLZkzB3o,842
59
59
  cuqi/geometry/_geometry.py,sha256=W-oQTZPelVS7fN9qZj6bNBuh-yY0eqOHJ39UwB-WmQY,47562
60
60
  cuqi/implicitprior/__init__.py,sha256=6Fl4Lmld8ikg9sW9tReKRGTCJC6_WCTExHaYuIv34nM,323
@@ -93,8 +93,8 @@ cuqi/testproblem/_testproblem.py,sha256=EJWG_zXUtmo6GlHBZFqHlRpDC_48tE0XZEu0_C66
93
93
  cuqi/utilities/__init__.py,sha256=d5QXRzmI6EchS9T4b7eTezSisPWuWklO8ey4YBx9kI0,569
94
94
  cuqi/utilities/_get_python_variable_name.py,sha256=wxpCaj9f3ZtBNqlGmmuGiITgBaTsY-r94lUIlK6UAU4,2043
95
95
  cuqi/utilities/_utilities.py,sha256=R7BdNysrE36a4D729DvfrTisWY4paP5nfqdkQxSX3Mg,18431
96
- cuqipy-1.3.0.post0.dev383.dist-info/licenses/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
97
- cuqipy-1.3.0.post0.dev383.dist-info/METADATA,sha256=p362AuUaJVIXW8tdsO-G0DqnDMQ94iSmPmocJbXMoho,18624
98
- cuqipy-1.3.0.post0.dev383.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
99
- cuqipy-1.3.0.post0.dev383.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
100
- cuqipy-1.3.0.post0.dev383.dist-info/RECORD,,
96
+ cuqipy-1.3.0.post0.dev401.dist-info/licenses/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
97
+ cuqipy-1.3.0.post0.dev401.dist-info/METADATA,sha256=tSP-CHhdOy1toeu4080aq-6thVow3YK_LpNpT5q95T0,18624
98
+ cuqipy-1.3.0.post0.dev401.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
99
+ cuqipy-1.3.0.post0.dev401.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
100
+ cuqipy-1.3.0.post0.dev401.dist-info/RECORD,,