CUQIpy 0.8.0.post0.dev82__tar.gz → 0.8.0.post0.dev92__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.

Files changed (101) hide show
  1. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/CUQIpy.egg-info/PKG-INFO +1 -1
  2. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/PKG-INFO +1 -1
  3. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/_version.py +3 -3
  4. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_beta.py +1 -1
  5. CUQIpy-0.8.0.post0.dev92/cuqi/distribution/_gamma.py +105 -0
  6. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_conjugate.py +2 -0
  7. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_distribution.py +51 -0
  8. CUQIpy-0.8.0.post0.dev82/cuqi/distribution/_gamma.py +0 -37
  9. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/CUQIpy.egg-info/SOURCES.txt +0 -0
  10. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/CUQIpy.egg-info/dependency_links.txt +0 -0
  11. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/CUQIpy.egg-info/requires.txt +0 -0
  12. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/CUQIpy.egg-info/top_level.txt +0 -0
  13. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/LICENSE +0 -0
  14. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/README.md +0 -0
  15. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/__init__.py +0 -0
  16. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/_messages.py +0 -0
  17. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/array/__init__.py +0 -0
  18. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/array/_array.py +0 -0
  19. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/config.py +0 -0
  20. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/data/__init__.py +0 -0
  21. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/data/_data.py +0 -0
  22. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/data/astronaut.npz +0 -0
  23. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/data/camera.npz +0 -0
  24. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/data/cat.npz +0 -0
  25. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/data/cookie.png +0 -0
  26. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/data/satellite.mat +0 -0
  27. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/density/__init__.py +0 -0
  28. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/density/_density.py +0 -0
  29. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/diagnostics.py +0 -0
  30. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/__init__.py +0 -0
  31. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_cauchy.py +0 -0
  32. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_cmrf.py +0 -0
  33. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_custom.py +0 -0
  34. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_distribution.py +0 -0
  35. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_gaussian.py +0 -0
  36. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_gmrf.py +0 -0
  37. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_inverse_gamma.py +0 -0
  38. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_joint_distribution.py +0 -0
  39. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_laplace.py +0 -0
  40. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_lmrf.py +0 -0
  41. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_lognormal.py +0 -0
  42. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_normal.py +0 -0
  43. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_posterior.py +0 -0
  44. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/distribution/_uniform.py +0 -0
  45. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/geometry/__init__.py +0 -0
  46. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/geometry/_geometry.py +0 -0
  47. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/implicitprior/__init__.py +0 -0
  48. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/implicitprior/_regularizedGMRF.py +0 -0
  49. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/implicitprior/_regularizedGaussian.py +0 -0
  50. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/likelihood/__init__.py +0 -0
  51. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/likelihood/_likelihood.py +0 -0
  52. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/model/__init__.py +0 -0
  53. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/model/_model.py +0 -0
  54. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/operator/__init__.py +0 -0
  55. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/operator/_operator.py +0 -0
  56. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/pde/__init__.py +0 -0
  57. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/pde/_pde.py +0 -0
  58. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/problem/__init__.py +0 -0
  59. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/problem/_problem.py +0 -0
  60. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/__init__.py +0 -0
  61. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_conjugate_approx.py +0 -0
  62. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_cwmh.py +0 -0
  63. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_gibbs.py +0 -0
  64. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_hmc.py +0 -0
  65. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_langevin_algorithm.py +0 -0
  66. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_laplace_approximation.py +0 -0
  67. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_mh.py +0 -0
  68. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_pcn.py +0 -0
  69. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_rto.py +0 -0
  70. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/sampler/_sampler.py +0 -0
  71. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/samples/__init__.py +0 -0
  72. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/samples/_samples.py +0 -0
  73. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/solver/__init__.py +0 -0
  74. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/solver/_solver.py +0 -0
  75. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/testproblem/__init__.py +0 -0
  76. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/testproblem/_testproblem.py +0 -0
  77. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/utilities/__init__.py +0 -0
  78. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/utilities/_get_python_variable_name.py +0 -0
  79. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/cuqi/utilities/_utilities.py +0 -0
  80. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/pyproject.toml +0 -0
  81. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/requirements.txt +0 -0
  82. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/setup.cfg +0 -0
  83. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/setup.py +0 -0
  84. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_MRFs.py +0 -0
  85. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_abstract_distribution_density.py +0 -0
  86. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_bayesian_inversion.py +0 -0
  87. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_density.py +0 -0
  88. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_distributions_shape.py +0 -0
  89. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_geometry.py +0 -0
  90. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_implicit_priors.py +0 -0
  91. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_joint_distribution.py +0 -0
  92. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_likelihood.py +0 -0
  93. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_model.py +0 -0
  94. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_pde.py +0 -0
  95. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_posterior.py +0 -0
  96. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_problem.py +0 -0
  97. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_sampler.py +0 -0
  98. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_samples.py +0 -0
  99. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_solver.py +0 -0
  100. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_testproblem.py +0 -0
  101. {CUQIpy-0.8.0.post0.dev82 → CUQIpy-0.8.0.post0.dev92}/tests/test_utilities.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: CUQIpy
3
- Version: 0.8.0.post0.dev82
3
+ Version: 0.8.0.post0.dev92
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.1
2
2
  Name: CUQIpy
3
- Version: 0.8.0.post0.dev82
3
+ Version: 0.8.0.post0.dev92
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": "2024-01-22T07:47:25+0100",
11
+ "date": "2024-02-19T05:04:22+0100",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "26e399cc13e1d7bf982d16d1d345b6d6616dac92",
15
- "version": "0.8.0.post0.dev82"
14
+ "full-revisionid": "f274c4a7b3044d1ba3e9567bb167a1cdbea05283",
15
+ "version": "0.8.0.post0.dev92"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -69,7 +69,7 @@ class Beta(Distribution):
69
69
  def _sample(self, N=1, rng=None):
70
70
  return sps.beta.rvs(a=self.alpha, b=self.beta, size=(N,self.dim), random_state=rng).T
71
71
 
72
- def _gradient(self, x):
72
+ def _gradient(self, x, *args, **kwargs):
73
73
  #Avoid complicated geometries that change the gradient.
74
74
  if not type(self.geometry) in _get_identity_geometries():
75
75
  raise NotImplementedError("Gradient not implemented for distribution {} with geometry {}".format(self,self.geometry))
@@ -0,0 +1,105 @@
1
+ import numpy as np
2
+ import scipy.stats as sps
3
+ from cuqi.distribution import Distribution
4
+ from cuqi.utilities import force_ndarray
5
+
6
+ class Gamma(Distribution):
7
+ """
8
+ Represents a multivariate Gamma distribution characterized by shape and rate parameters of independent random variables x_i. Each is distributed according to the PDF function
9
+
10
+ f(x_i; shape, rate) = rate^shape * x_i^(shape-1) * exp(-rate * x_i) / Gamma(shape)
11
+
12
+ where `shape` and `rate` are the parameters of the distribution, and Gamma is the Gamma function.
13
+
14
+ In case shape and/or rate are arrays, the pdf looks like
15
+
16
+ f(x_i; shape_i, rate_i) = rate_i^shape_i * x_i^(shape_i-1) * exp(-rate_i * x_i) / Gamma(shape_i)
17
+
18
+ Parameters
19
+ ----------
20
+ shape : float or array_like, optional
21
+ The shape parameter of the Gamma distribution. Must be positive.
22
+
23
+ rate : float or array_like, optional
24
+ The rate parameter of the Gamma distribution. Must be positive.
25
+
26
+ Examples
27
+ --------
28
+ .. code-block:: python
29
+
30
+ import numpy as np
31
+ import cuqi
32
+ import matplotlib.pyplot as plt
33
+
34
+ # Create a multivariate Gamma distribution with the same shape and rate parameters
35
+ shape = 1
36
+ rate = 1e-4
37
+ gamma_dist = cuqi.distribution.Gamma(shape=shape, rate=rate, geometry=10)
38
+
39
+ # Generate samples
40
+ samples = gamma_dist.sample(10000)
41
+
42
+ # Plot histogram of samples for index 0
43
+ samples.hist_chain(0, bins=70)
44
+
45
+
46
+ .. code-block:: python
47
+
48
+ import numpy as np
49
+ import cuqi
50
+ import matplotlib.pyplot as plt
51
+
52
+ # Create a multivariate Gamma distribution with different shape and rate parameters
53
+ shape = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
54
+ rate = [1e-4, 1e-3, 1e-2, 1e-1, 1, 1e1, 1e2, 1e3, 1e4, 1e5]
55
+ gamma_dist = cuqi.distribution.Gamma(shape=shape, rate=rate)
56
+
57
+ # Generate samples
58
+ samples = gamma_dist.sample(10000)
59
+
60
+ # Plot histogram of samples for index 0
61
+ samples.hist_chain(0, bins=70)
62
+
63
+ """
64
+ def __init__(self, shape=None, rate=None, is_symmetric=False, **kwargs):
65
+ # Init from abstract distribution class
66
+ super().__init__(is_symmetric=is_symmetric,**kwargs)
67
+
68
+ self.shape = shape
69
+ self.rate = rate
70
+
71
+ @property
72
+ def shape(self):
73
+ """ Shape parameter of the Gamma distribution. Must be positive. """
74
+ return self._shape
75
+
76
+ @shape.setter
77
+ def shape(self, value):
78
+ self._shape = force_ndarray(value, flatten=True)
79
+
80
+ @property
81
+ def rate(self):
82
+ """ Rate parameter of the Gamma distribution. Must be positive. """
83
+ return self._rate
84
+
85
+ @rate.setter
86
+ def rate(self, value):
87
+ self._rate = force_ndarray(value, flatten=True)
88
+
89
+ @property
90
+ def scale(self):
91
+ """ Scale parameter of the Gamma distribution. Must be positive. This is the inverse of the rate parameter. """
92
+ return 1/self.rate
93
+
94
+ def logpdf(self, x):
95
+ return np.sum(sps.gamma.logpdf(x, a=self.shape, loc=0, scale=self.scale))
96
+
97
+ def cdf(self, x):
98
+ return np.prod(sps.gamma.cdf(x, a=self.shape, loc=0, scale=self.scale))
99
+
100
+ def _sample(self, N, rng=None):
101
+ if rng is not None:
102
+ return rng.gamma(shape=self.shape, scale=self.scale, size=(N, self.dim)).T
103
+ else:
104
+ return np.random.gamma(shape=self.shape, scale=self.scale, size=(N, self.dim)).T
105
+
@@ -25,6 +25,8 @@ class Conjugate: # TODO: Subclass from Sampler once updated
25
25
  raise ValueError("Conjugate sampler only works with a Gaussian-type likelihood function")
26
26
  if not isinstance(target.prior, Gamma):
27
27
  raise ValueError("Conjugate sampler only works with Gamma prior")
28
+ if not target.prior.dim == 1:
29
+ raise ValueError("Conjugate sampler only works with univariate Gamma prior")
28
30
 
29
31
  if isinstance(target.likelihood.distribution, (RegularizedGaussian, RegularizedGMRF)) and target.likelihood.distribution.preset not in ["nonnegativity"]:
30
32
  raise ValueError("Conjugate sampler only works implicit regularized Gaussian likelihood with nonnegativity constraints")
@@ -375,6 +375,32 @@ def test_InverseGamma(a, location, scale, x, func):
375
375
 
376
376
  else:
377
377
  raise ValueError
378
+
379
+ @pytest.mark.parametrize("shape", [1, 2, 3, 5])
380
+ @pytest.mark.parametrize("rate", [1e-4, 1e-3, 1e-2, 1e-1, 1, 1e4, 1e5])
381
+ @pytest.mark.parametrize("value", [1, 2, 3, 4, 5])
382
+ def test_Gamma_pdf(shape, rate, value):
383
+ G = cuqi.distribution.Gamma(shape, rate)
384
+ assert np.isclose(G.pdf(value), scipy_stats.gamma(shape, scale=1/rate).pdf(value))
385
+
386
+ @pytest.mark.parametrize("shape", [1, 2, 3, 5])
387
+ @pytest.mark.parametrize("rate", [1e-4, 1e-3, 1e-2, 1e-1, 1, 1e4, 1e5])
388
+ @pytest.mark.parametrize("value", [1, 2, 3, 4, 5])
389
+ def test_Gamma_cdf(shape, rate, value):
390
+ G = cuqi.distribution.Gamma(shape, rate)
391
+ assert np.isclose(G.cdf(value), scipy_stats.gamma(shape, scale=1/rate).cdf(value))
392
+
393
+ @pytest.mark.parametrize("shape", [1, 2, 3, 5])
394
+ @pytest.mark.parametrize("rate", [1e-4, 1e-3, 1e-2, 1e-1, 1, 1e4, 1e5])
395
+ def test_Gamma_sample(shape, rate):
396
+ rng = np.random.RandomState(3)
397
+ G = cuqi.distribution.Gamma(shape, rate)
398
+ cuqi_samples = G.sample(3, rng=rng)
399
+
400
+ rng2 = np.random.RandomState(3)
401
+ np_samples = rng2.gamma(shape=shape, scale=1/rate, size=(3, 1)).T
402
+
403
+ assert np.allclose(cuqi_samples.samples, np_samples)
378
404
 
379
405
  @pytest.mark.parametrize("location", [-1, -2, -3, 0, 1, 2, 3])
380
406
  @pytest.mark.parametrize("scale", [1e-3, 1e-1, 1e0, 1e1, 1e3])
@@ -563,6 +589,31 @@ def test_beta(): #TODO. Make more tests
563
589
  FD_gradient = cuqi.utilities.approx_gradient(BD.logpdf, x, epsilon=0.000000001)
564
590
  assert np.allclose(BD.gradient(x),FD_gradient,rtol=1e-3) or (np.all(np.isnan(FD_gradient)) and np.all(np.isnan(BD.gradient(x))))
565
591
 
592
+ # Fixture for beta distribution where beta is a likelihood
593
+ @pytest.fixture
594
+ def beta_likelihood():
595
+ # simple forward model
596
+ A = cuqi.model.Model(
597
+ lambda x: x**2,
598
+ range_geometry=1,
599
+ domain_geometry=1,
600
+ gradient=lambda direction, wrt: 2*wrt*direction)
601
+
602
+ # set a gaussian prior
603
+ x = cuqi.distribution.Gaussian(0, 1)
604
+ # Beta data distribution
605
+ y = cuqi.distribution.Beta(A(x),1)
606
+ # set the observed data
607
+ y=y(y=0.5)
608
+ return y
609
+
610
+ def test_gradient_for_Beta_as_likelihood_raises_error(beta_likelihood):
611
+ """Test computing the gradient of the Beta distribution as a likelihood
612
+ raises a NotImplementedError"""
613
+
614
+ with pytest.raises(NotImplementedError,
615
+ match=r"Gradient is not implemented for CUQI Beta."):
616
+ beta_likelihood.gradient(1)
566
617
 
567
618
  @pytest.mark.parametrize("C",[1, np.ones(5), np.eye(5), sps.eye(5), sps.diags(np.ones(5))])
568
619
  def test_Gaussian_Cov_sample(C):
@@ -1,37 +0,0 @@
1
- import numpy as np
2
- from scipy.special import loggamma, gammainc
3
- from cuqi.distribution import Distribution
4
-
5
- class Gamma(Distribution):
6
-
7
- def __init__(self, shape=None, rate=None, is_symmetric=False, **kwargs):
8
- # Init from abstract distribution class
9
- super().__init__(is_symmetric=is_symmetric,**kwargs)
10
-
11
- # Init specific to this distribution
12
- self.shape = shape
13
- self.rate = rate
14
-
15
- @property
16
- def scale(self):
17
- return 1/self.rate
18
-
19
- def pdf(self, x):
20
- # sps.gamma.pdf(x, a=self.shape, loc=0, scale=self.scale)
21
- # (self.rate**self.shape)/(gamma(self.shape)) * (x**(self.shape-1)*np.exp(-self.rate*x))
22
- return np.exp(self.logpdf(x))
23
-
24
- def logpdf(self, x):
25
- # sps.gamma.logpdf(x, a=self.shape, loc=0, scale=self.scale)
26
- return (self.shape*np.log(self.rate)-loggamma(self.shape)) + ((self.shape-1)*np.log(x) - self.rate*x)
27
-
28
- def cdf(self, x):
29
- # sps.gamma.cdf(x, a=self.shape, loc=0, scale=self.scale)
30
- return gammainc(self.shape, self.rate*x)
31
-
32
- def _sample(self, N, rng=None):
33
- if rng is not None:
34
- return rng.gamma(shape=self.shape, scale=self.scale, size=(N))
35
- else:
36
- return np.random.gamma(shape=self.shape, scale=self.scale, size=(N))
37
-