CUQIpy 1.1.1.post0.dev36__py3-none-any.whl → 1.4.1.post0.dev124__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.

Files changed (92) hide show
  1. cuqi/__init__.py +2 -0
  2. cuqi/_version.py +3 -3
  3. cuqi/algebra/__init__.py +2 -0
  4. cuqi/algebra/_abstract_syntax_tree.py +358 -0
  5. cuqi/algebra/_ordered_set.py +82 -0
  6. cuqi/algebra/_random_variable.py +457 -0
  7. cuqi/array/_array.py +4 -13
  8. cuqi/config.py +7 -0
  9. cuqi/density/_density.py +9 -1
  10. cuqi/distribution/__init__.py +3 -2
  11. cuqi/distribution/_beta.py +7 -11
  12. cuqi/distribution/_cauchy.py +2 -2
  13. cuqi/distribution/_custom.py +0 -6
  14. cuqi/distribution/_distribution.py +31 -45
  15. cuqi/distribution/_gamma.py +7 -3
  16. cuqi/distribution/_gaussian.py +2 -12
  17. cuqi/distribution/_inverse_gamma.py +4 -10
  18. cuqi/distribution/_joint_distribution.py +112 -15
  19. cuqi/distribution/_lognormal.py +0 -7
  20. cuqi/distribution/{_modifiedhalfnormal.py → _modified_half_normal.py} +23 -23
  21. cuqi/distribution/_normal.py +34 -7
  22. cuqi/distribution/_posterior.py +9 -0
  23. cuqi/distribution/_truncated_normal.py +129 -0
  24. cuqi/distribution/_uniform.py +47 -1
  25. cuqi/experimental/__init__.py +2 -2
  26. cuqi/experimental/_recommender.py +216 -0
  27. cuqi/geometry/__init__.py +2 -0
  28. cuqi/geometry/_geometry.py +15 -1
  29. cuqi/geometry/_product_geometry.py +181 -0
  30. cuqi/implicitprior/__init__.py +5 -3
  31. cuqi/implicitprior/_regularized_gaussian.py +483 -0
  32. cuqi/implicitprior/{_regularizedGMRF.py → _regularized_gmrf.py} +4 -2
  33. cuqi/implicitprior/{_regularizedUnboundedUniform.py → _regularized_unbounded_uniform.py} +3 -2
  34. cuqi/implicitprior/_restorator.py +269 -0
  35. cuqi/legacy/__init__.py +2 -0
  36. cuqi/{experimental/mcmc → legacy/sampler}/__init__.py +7 -11
  37. cuqi/legacy/sampler/_conjugate.py +55 -0
  38. cuqi/legacy/sampler/_conjugate_approx.py +52 -0
  39. cuqi/legacy/sampler/_cwmh.py +196 -0
  40. cuqi/legacy/sampler/_gibbs.py +231 -0
  41. cuqi/legacy/sampler/_hmc.py +335 -0
  42. cuqi/{experimental/mcmc → legacy/sampler}/_langevin_algorithm.py +82 -111
  43. cuqi/legacy/sampler/_laplace_approximation.py +184 -0
  44. cuqi/legacy/sampler/_mh.py +190 -0
  45. cuqi/legacy/sampler/_pcn.py +244 -0
  46. cuqi/{experimental/mcmc → legacy/sampler}/_rto.py +132 -90
  47. cuqi/legacy/sampler/_sampler.py +182 -0
  48. cuqi/likelihood/_likelihood.py +9 -1
  49. cuqi/model/__init__.py +1 -1
  50. cuqi/model/_model.py +1361 -359
  51. cuqi/pde/__init__.py +4 -0
  52. cuqi/pde/_observation_map.py +36 -0
  53. cuqi/pde/_pde.py +134 -33
  54. cuqi/problem/_problem.py +93 -87
  55. cuqi/sampler/__init__.py +120 -8
  56. cuqi/sampler/_conjugate.py +376 -35
  57. cuqi/sampler/_conjugate_approx.py +40 -16
  58. cuqi/sampler/_cwmh.py +132 -138
  59. cuqi/{experimental/mcmc → sampler}/_direct.py +1 -1
  60. cuqi/sampler/_gibbs.py +288 -130
  61. cuqi/sampler/_hmc.py +328 -201
  62. cuqi/sampler/_langevin_algorithm.py +284 -100
  63. cuqi/sampler/_laplace_approximation.py +87 -117
  64. cuqi/sampler/_mh.py +47 -157
  65. cuqi/sampler/_pcn.py +65 -213
  66. cuqi/sampler/_rto.py +211 -142
  67. cuqi/sampler/_sampler.py +553 -136
  68. cuqi/samples/__init__.py +1 -1
  69. cuqi/samples/_samples.py +24 -18
  70. cuqi/solver/__init__.py +6 -4
  71. cuqi/solver/_solver.py +230 -26
  72. cuqi/testproblem/_testproblem.py +2 -3
  73. cuqi/utilities/__init__.py +6 -1
  74. cuqi/utilities/_get_python_variable_name.py +2 -2
  75. cuqi/utilities/_utilities.py +182 -2
  76. {CUQIpy-1.1.1.post0.dev36.dist-info → cuqipy-1.4.1.post0.dev124.dist-info}/METADATA +10 -6
  77. cuqipy-1.4.1.post0.dev124.dist-info/RECORD +101 -0
  78. {CUQIpy-1.1.1.post0.dev36.dist-info → cuqipy-1.4.1.post0.dev124.dist-info}/WHEEL +1 -1
  79. CUQIpy-1.1.1.post0.dev36.dist-info/RECORD +0 -92
  80. cuqi/experimental/mcmc/_conjugate.py +0 -197
  81. cuqi/experimental/mcmc/_conjugate_approx.py +0 -81
  82. cuqi/experimental/mcmc/_cwmh.py +0 -191
  83. cuqi/experimental/mcmc/_gibbs.py +0 -268
  84. cuqi/experimental/mcmc/_hmc.py +0 -470
  85. cuqi/experimental/mcmc/_laplace_approximation.py +0 -156
  86. cuqi/experimental/mcmc/_mh.py +0 -78
  87. cuqi/experimental/mcmc/_pcn.py +0 -89
  88. cuqi/experimental/mcmc/_sampler.py +0 -561
  89. cuqi/experimental/mcmc/_utilities.py +0 -17
  90. cuqi/implicitprior/_regularizedGaussian.py +0 -323
  91. {CUQIpy-1.1.1.post0.dev36.dist-info → cuqipy-1.4.1.post0.dev124.dist-info/licenses}/LICENSE +0 -0
  92. {CUQIpy-1.1.1.post0.dev36.dist-info → cuqipy-1.4.1.post0.dev124.dist-info}/top_level.txt +0 -0
@@ -1,78 +0,0 @@
1
- import numpy as np
2
- import cuqi
3
- from cuqi.experimental.mcmc import ProposalBasedSampler
4
-
5
-
6
- class MH(ProposalBasedSampler):
7
- """ Metropolis-Hastings (MH) sampler.
8
-
9
- Parameters
10
- ----------
11
- target : cuqi.density.Density
12
- Target density or distribution.
13
-
14
- proposal : cuqi.distribution.Distribution or callable
15
- Proposal distribution. If None, a random walk MH is used (i.e., Gaussian proposal with identity covariance).
16
-
17
- scale : float
18
- Scaling parameter for the proposal distribution.
19
-
20
- kwargs : dict
21
- Additional keyword arguments to be passed to the base class :class:`ProposalBasedSampler`.
22
-
23
- """
24
-
25
- _STATE_KEYS = ProposalBasedSampler._STATE_KEYS.union({'scale', '_scale_temp'})
26
-
27
- def __init__(self, target=None, proposal=None, scale=1, **kwargs):
28
- super().__init__(target, proposal=proposal, scale=scale, **kwargs)
29
-
30
- def _initialize(self):
31
- # Due to a bug? in old MH, we must keep track of this extra variable to match behavior.
32
- self._scale_temp = self.scale
33
-
34
- def validate_target(self):
35
- # Fail only when there is no log density, which is currently assumed to be the case in case NaN is returned.
36
- if np.isnan(self.target.logd(self._get_default_initial_point(self.dim))):
37
- raise ValueError("Target does not have valid logd")
38
-
39
- def validate_proposal(self):
40
- if not isinstance(self.proposal, cuqi.distribution.Distribution):
41
- raise ValueError("Proposal must be a cuqi.distribution.Distribution object")
42
- if not self.proposal.is_symmetric:
43
- raise ValueError("Proposal must be symmetric")
44
-
45
- def step(self):
46
- # propose state
47
- xi = self.proposal.sample(1) # sample from the proposal
48
- x_star = self.current_point + self.scale*xi.flatten() # MH proposal
49
-
50
- # evaluate target
51
- target_eval_star = self.target.logd(x_star)
52
-
53
- # ratio and acceptance probability
54
- ratio = target_eval_star - self.current_target_logd # proposal is symmetric
55
- alpha = min(0, ratio)
56
-
57
- # accept/reject
58
- u_theta = np.log(np.random.rand())
59
- acc = 0
60
- if (u_theta <= alpha):
61
- self.current_point = x_star
62
- self.current_target_logd = target_eval_star
63
- acc = 1
64
-
65
- return acc
66
-
67
- def tune(self, skip_len, update_count):
68
- hat_acc = np.mean(self._acc[-skip_len:])
69
-
70
- # d. compute new scaling parameter
71
- zeta = 1/np.sqrt(update_count+1) # ensures that the variation of lambda(i) vanishes
72
-
73
- # We use self._scale_temp here instead of self.scale in update. This might be a bug,
74
- # but is equivalent to old MH
75
- self._scale_temp = np.exp(np.log(self._scale_temp) + zeta*(hat_acc-0.234))
76
-
77
- # update parameters
78
- self.scale = min(self._scale_temp, 1)
@@ -1,89 +0,0 @@
1
- import numpy as np
2
- import cuqi
3
- from cuqi.experimental.mcmc import Sampler
4
- from cuqi.array import CUQIarray
5
-
6
- class PCN(Sampler): # Refactor to Proposal-based sampler?
7
-
8
- _STATE_KEYS = Sampler._STATE_KEYS.union({'scale', 'current_likelihood_logd', 'lambd'})
9
-
10
- def __init__(self, target=None, scale=1.0, **kwargs):
11
-
12
- super().__init__(target, **kwargs)
13
- self.initial_scale = scale
14
-
15
- def _initialize(self):
16
- self.scale = self.initial_scale
17
- self.current_likelihood_logd = self._loglikelihood(self.current_point)
18
-
19
- # parameters used in the Robbins-Monro recursion for tuning the scale parameter
20
- # see details and reference in the tune method
21
- self.lambd = self.scale
22
- self.star_acc = 0.44 #TODO: 0.234 # target acceptance rate
23
-
24
- def validate_target(self):
25
- if not isinstance(self.target, cuqi.distribution.Posterior):
26
- raise ValueError(f"To initialize an object of type {self.__class__}, 'target' need to be of type 'cuqi.distribution.Posterior'.")
27
- if not isinstance(self.prior, (cuqi.distribution.Gaussian, cuqi.distribution.Normal)):
28
- raise ValueError("The prior distribution of the target need to be Gaussian")
29
-
30
- def step(self):
31
- # propose state
32
- xi = self.prior.sample(1).flatten() # sample from the prior
33
- x_star = np.sqrt(1-self.scale**2)*self.current_point + self.scale*xi # PCN proposal
34
-
35
- # evaluate target
36
- loglike_eval_star = self._loglikelihood(x_star)
37
-
38
- # ratio and acceptance probability
39
- ratio = loglike_eval_star - self.current_likelihood_logd # proposal is symmetric
40
- alpha = min(0, ratio)
41
-
42
- # accept/reject
43
- acc = 0
44
- u_theta = np.log(np.random.rand())
45
- if (u_theta <= alpha):
46
- self.current_point = x_star
47
- self.current_likelihood_logd = loglike_eval_star
48
- acc = 1
49
-
50
- return acc
51
-
52
- @property
53
- def prior(self):
54
- return self.target.prior
55
-
56
- @property
57
- def likelihood(self):
58
- return self.target.likelihood
59
-
60
- def _loglikelihood(self, x):
61
- return self.likelihood.logd(x)
62
-
63
- @property
64
- def dim(self): # TODO. Check if we need this. Implemented in base class
65
- if hasattr(self,'target') and hasattr(self.target,'dim'):
66
- self._dim = self.target.dim
67
- elif hasattr(self,'target') and isinstance(self.target,tuple) and len(self.target)==2:
68
- self._dim = self.target[0].dim
69
- return self._dim
70
-
71
- def tune(self, skip_len, update_count):
72
- """
73
- Tune the scale parameter of the PCN sampler.
74
- The tuning is based on algorithm 4 in Andrieu, Christophe, and Johannes Thoms.
75
- "A tutorial on adaptive MCMC." Statistics and computing 18 (2008): 343-373.
76
- Note: the tuning algorithm here is the same as the one used in MH sampler.
77
- """
78
-
79
- # average acceptance rate in the past skip_len iterations
80
- hat_acc = np.mean(self._acc[-skip_len:])
81
-
82
- # new scaling parameter zeta to be used in the Robbins-Monro recursion
83
- zeta = 1/np.sqrt(update_count+1)
84
-
85
- # Robbins-Monro recursion to ensure that the variation of lambd vanishes
86
- self.lambd = np.exp(np.log(self.lambd) + zeta*(hat_acc-self.star_acc))
87
-
88
- # update scale parameter
89
- self.scale = min(self.lambd, 1)