CUQIpy 1.1.1.post0.dev38__py3-none-any.whl → 1.1.1.post0.dev78__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: CUQIpy
3
- Version: 1.1.1.post0.dev38
3
+ Version: 1.1.1.post0.dev78
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,10 +1,10 @@
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=3KpJ9KDrHyWyhVheV_2POh7YE6IniyOZ6NJqYlKpZYU,509
3
+ cuqi/_version.py,sha256=gD2Xsdgd9KtxRR21WMPf1lwpL2_y736taJdOyU6AmrE,509
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
7
- cuqi/array/_array.py,sha256=Xm2n1MFnLhR3KUjoCzMc-tnZ5HBX1mQ8MyxhZnIvSCA,4400
7
+ cuqi/array/_array.py,sha256=UJoWyQjDpl8g2q4wuuz_ufpr2JoYL0BbCxrxZpZR99I,4303
8
8
  cuqi/data/__init__.py,sha256=1aGgPmtG_Kqbb880vLnPksGvyYQB_6o2mz_q-4KGYaU,173
9
9
  cuqi/data/_data.py,sha256=PgdYJ6MHgNY37Ak8wUYwvxcAwOYSNjnf1-BXMdbnuv4,10716
10
10
  cuqi/data/astronaut.npz,sha256=vVTb6eJLMZhrEZuOYzQWN3V2EhhVH6sHzrrf_7mstcw,786696
@@ -15,21 +15,21 @@ cuqi/data/satellite.mat,sha256=a0Nz_Ak-Y0m360dH74pa_rpk-MhaQ91ftGTKhQX7I8g,16373
15
15
  cuqi/density/__init__.py,sha256=0zfVcPgqdqiPkss5n_WP_PUt-G3ovHXjokhqEKIlLwA,48
16
16
  cuqi/density/_density.py,sha256=BG7gtP0cbFYLVgjYQGkNAhM95PR5ocBVLKRlOVX2PyM,7253
17
17
  cuqi/distribution/__init__.py,sha256=4vVLArg6NVzBj67vVioK8BY6wISJKb5cOxdoHMuUb_s,714
18
- cuqi/distribution/_beta.py,sha256=hdAc6Tbuz9Yqf76NSHxpaUgN7s6Z2lNV7YSRD3JhyCU,2997
18
+ cuqi/distribution/_beta.py,sha256=lgN6PGoF9RXQtrMGqSaSBV0hw-LEsOfRTD2Q2L3-Ok4,2903
19
19
  cuqi/distribution/_cauchy.py,sha256=UsVXYz8HhagXN5fIWSAIyELqhsJAX_-wk9kkRGgRmA8,3296
20
20
  cuqi/distribution/_cmrf.py,sha256=tCbEulM_O7FB3C_W-3IqZp9zGHkTofCdFF0ybHc9UZI,3745
21
- cuqi/distribution/_custom.py,sha256=3toVV_ntnWAGlI7pNQLS7-7m5i-34sTWQrxL-SMweq0,10681
22
- cuqi/distribution/_distribution.py,sha256=G7BCpVueK4QLoLa_hu9h-Euh58Yp9SrgUKuudUlg-pw,18351
23
- cuqi/distribution/_gamma.py,sha256=9vljt5iaBDCHRhrVCMLc2RWDuBchZRQcv9buJMDYPlM,3434
24
- cuqi/distribution/_gaussian.py,sha256=DmmgVxKp4iEiEYWDdDcRoh35y14Oepn-zDHex0WVaYo,33316
21
+ cuqi/distribution/_custom.py,sha256=11lnAG7CS15bpV6JOOP--2YyKnAduvXY1IjAOJ1tqO0,10504
22
+ cuqi/distribution/_distribution.py,sha256=Yvohy-ZCxFSmeQxVVyaZ959tsPea38ER862aOjvBtKI,17774
23
+ cuqi/distribution/_gamma.py,sha256=VcvBJS51N-MxuX42r9L2j2QYRlzhdgAtQ6Wa5IFO_YE,3536
24
+ cuqi/distribution/_gaussian.py,sha256=3L1L_3W6i6YuPQ8vnFmju5QsvkLlg4VsgCnj11lYBUE,32977
25
25
  cuqi/distribution/_gmrf.py,sha256=OwId8qQWEtmC2fxVhL4iBHZnc8ZCrZzfV6yGXDE3k30,9522
26
- cuqi/distribution/_inverse_gamma.py,sha256=XRcNGW_jzORL08V7VvtsuMUoQioBAGbN12qe8hCXJvg,3309
26
+ cuqi/distribution/_inverse_gamma.py,sha256=oPJuiYp3O1m547pmmIz9OWesky9YpwLTHT7-9MmcYss,3159
27
27
  cuqi/distribution/_joint_distribution.py,sha256=7TxDaZ7y362LfxEpD4I5Z0icdtsBmOBJGnpIkz_bYXA,15900
28
28
  cuqi/distribution/_laplace.py,sha256=5exLvlzJm2AgfvZ3KUSkjfwlGwwbsktBxP8z0iLMik8,1401
29
29
  cuqi/distribution/_lmrf.py,sha256=rdGoQ-fPe1oW6Z29P-l3woq0NX3_RxUQ2rzm1VzemNM,3290
30
- cuqi/distribution/_lognormal.py,sha256=st1Uhf67qy2Seo65hA88JQ7lkEjQkW6KxznXahF_0SU,2844
31
- cuqi/distribution/_modifiedhalfnormal.py,sha256=gB9fj10hdMvr05aa_xhAirJATLqKh1gpbdSs2pRoAVM,7267
32
- cuqi/distribution/_normal.py,sha256=UeoTtGDT7YSf4ZNo2amlVF9K-YQpYbf8q76jcRJTVFw,1914
30
+ cuqi/distribution/_lognormal.py,sha256=8_hOFQ3iu88ujX8vxmfVEZ0fdmlhTY98PlG5PasPjEg,2612
31
+ cuqi/distribution/_modifiedhalfnormal.py,sha256=eCg9YhH-zyX25V5WqdBwQykwG_90lm5Qc2901z7jFUE,7390
32
+ cuqi/distribution/_normal.py,sha256=ohBk5bTZbDEkU0JqcNkkSQ4bDhTR2s-PXjA8d91L7Y4,1682
33
33
  cuqi/distribution/_posterior.py,sha256=zAfL0GECxekZ2lBt1W6_LN0U_xskMwK4VNce5xAF7ig,5018
34
34
  cuqi/distribution/_smoothed_laplace.py,sha256=p-1Y23mYA9omwiHGkEuv3T2mwcPAAoNlCr7T8osNkjE,2925
35
35
  cuqi/distribution/_uniform.py,sha256=7xJmCZH_LPhuGkwEDGh-_CTtzcWKrXMOxtTJUFb7Ydo,1607
@@ -39,7 +39,7 @@ cuqi/experimental/mcmc/_conjugate.py,sha256=VNPQkGity0mposcqxrx4UIeXm35EvJvZED4p
39
39
  cuqi/experimental/mcmc/_conjugate_approx.py,sha256=uEnY2ea9su5ivcNagyRAwpQP2gBY98sXU7N0y5hTADo,3653
40
40
  cuqi/experimental/mcmc/_cwmh.py,sha256=BQE7-4kbiC32TJ38rlVtfSQieoKBK5GDca3HCqHJ7zE,7135
41
41
  cuqi/experimental/mcmc/_direct.py,sha256=9pQS_2Qk2-ybt6m8WTfPoKetcxQ00WaTRN85-Z0FrBY,777
42
- cuqi/experimental/mcmc/_gibbs.py,sha256=6CCbasY8YJwDUnvHMKeV5pK0nr4T89BSklGaE-ZIP4I,10569
42
+ cuqi/experimental/mcmc/_gibbs.py,sha256=JwQQgKd-5IPVErUgMyxtG4sCVhf7gdzSr8ttn3trktY,12596
43
43
  cuqi/experimental/mcmc/_hmc.py,sha256=h63KT0jYq86H541hQzhHHzuLEn7vrRE_2r1o1mTEcZo,19261
44
44
  cuqi/experimental/mcmc/_langevin_algorithm.py,sha256=GKC_mlix3si_3J8E6I58ozh3ErB0XPmHMjV7sFyKLEQ,8200
45
45
  cuqi/experimental/mcmc/_laplace_approximation.py,sha256=rdiE3cMQFq6FLQcOQwPpuGIxrTAp3aoGPxMDSdeopV0,5688
@@ -77,16 +77,16 @@ cuqi/sampler/_pcn.py,sha256=F0h9-nUFtkqn-o-1s8BCsmr8V7u6R7ycoCOeeV1uhj0,8601
77
77
  cuqi/sampler/_rto.py,sha256=-AtMiYq4fh7pF9zVqfYjYtQbIIEGayrWyRGTj8KecfE,11518
78
78
  cuqi/sampler/_sampler.py,sha256=TkZ_WAS-5Q43oICa-Elc2gftsRTBd7PEDUMDZ9tTGmU,5712
79
79
  cuqi/samples/__init__.py,sha256=E7B9IBUsiOBr-HAKH9o3_Lqhq4KeWO87hmesHkdbwTY,30
80
- cuqi/samples/_samples.py,sha256=Pfy2piHmvZ3_fxh3c3BsQtX3mryIsDqRrqJ-Q7zw4Zo,35161
80
+ cuqi/samples/_samples.py,sha256=axcneMWISG9Lz9fPac03Gs_-ouB4podTfBj0e74KvRs,34738
81
81
  cuqi/solver/__init__.py,sha256=DGl8IdUnochRXHNDEy_13o_VT0vLFY6FjMmmSH6YUkY,169
82
- cuqi/solver/_solver.py,sha256=TgezixCVf8nKGtEF9ZrkaTtAfxSs1Z8CR_cmhdTMqRw,22776
82
+ cuqi/solver/_solver.py,sha256=eRmpBkHv_RXFdZTWhYqebH-toNbQcPgEgklNd5zOyOw,22803
83
83
  cuqi/testproblem/__init__.py,sha256=DWTOcyuNHMbhEuuWlY5CkYkNDSAqhvsKmJXBLivyblU,202
84
84
  cuqi/testproblem/_testproblem.py,sha256=x769LwwRdJdzIiZkcQUGb_5-vynNTNALXWKato7sS0Q,52540
85
85
  cuqi/utilities/__init__.py,sha256=H7xpJe2UinjZftKvE2JuXtTi4DqtkR6uIezStAXwfGg,428
86
86
  cuqi/utilities/_get_python_variable_name.py,sha256=QwlBVj2koJRA8s8pWd554p7-ElcI7HUwY32HknaR92E,1827
87
87
  cuqi/utilities/_utilities.py,sha256=Jc4knn80vLoA7kgw9FzXwKVFGaNBOXiA9kgvltZU3Ao,11777
88
- CUQIpy-1.1.1.post0.dev38.dist-info/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
89
- CUQIpy-1.1.1.post0.dev38.dist-info/METADATA,sha256=9IgjNCMFhKM_SpVro0PcDrLpD86gGG4rHD261xleUqw,18410
90
- CUQIpy-1.1.1.post0.dev38.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
91
- CUQIpy-1.1.1.post0.dev38.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
92
- CUQIpy-1.1.1.post0.dev38.dist-info/RECORD,,
88
+ CUQIpy-1.1.1.post0.dev78.dist-info/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
89
+ CUQIpy-1.1.1.post0.dev78.dist-info/METADATA,sha256=7AYkCLYMaKu0ow2DU_n9p2aq-1NPGYlgFHKb9sRGGGc,18410
90
+ CUQIpy-1.1.1.post0.dev78.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
91
+ CUQIpy-1.1.1.post0.dev78.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
92
+ CUQIpy-1.1.1.post0.dev78.dist-info/RECORD,,
cuqi/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2024-09-09T21:48:47+0200",
11
+ "date": "2024-09-11T08:37:02+0200",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "98a74d508a1aa4659a6176a0126a90371a6be581",
15
- "version": "1.1.1.post0.dev38"
14
+ "full-revisionid": "e332fa9b589e70ff3171d724fcc381c556631eb4",
15
+ "version": "1.1.1.post0.dev78"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
cuqi/array/_array.py CHANGED
@@ -15,19 +15,7 @@ class CUQIarray(np.ndarray):
15
15
  Boolean flag whether input_array is to be interpreted as parameter (True) or function values (False).
16
16
 
17
17
  geometry : cuqi.geometry.Geometry, default None
18
- Contains the geometry related of the data
19
-
20
- Attributes
21
- ----------
22
- funvals : CUQIarray
23
- Returns itself as function values.
24
-
25
- parameters : CUQIarray
26
- Returns itself as parameters.
27
-
28
- Methods
29
- ----------
30
- :meth:`plot`: Plots the data as function or parameters.
18
+ Contains the geometry related of the data.
31
19
  """
32
20
 
33
21
  def __repr__(self) -> str:
@@ -62,6 +50,7 @@ class CUQIarray(np.ndarray):
62
50
 
63
51
  @property
64
52
  def funvals(self):
53
+ """ Returns itself as function values. """
65
54
  if self.is_par is True:
66
55
  vals = self.geometry.par2fun(self)
67
56
  else:
@@ -82,6 +71,7 @@ class CUQIarray(np.ndarray):
82
71
 
83
72
  @property
84
73
  def parameters(self):
74
+ """ Returns itself as parameters. """
85
75
  if self.is_par is False:
86
76
  if self.dtype == np.dtype('O'):
87
77
  # If the current state if the CUQIarray is function values, and
@@ -109,6 +99,7 @@ class CUQIarray(np.ndarray):
109
99
  f"Cannot convert {self.__class__.__name__} to numpy array")
110
100
 
111
101
  def plot(self, plot_par=False, **kwargs):
102
+ """ Plot the data as function or parameters. """
112
103
  if plot_par:
113
104
  kwargs["is_par"]=True
114
105
  return self.geometry.plot(self.parameters, plot_par=plot_par, **kwargs)
@@ -9,23 +9,19 @@ class Beta(Distribution):
9
9
  """
10
10
  Multivariate beta distribution of independent random variables x_i. Each is distributed according to the PDF function
11
11
 
12
- f(x) = x^(alpha-1) * (1-x)^(beta-1) * Gamma(alpha+beta) / (Gamma(alpha)*Gamma(beta))
12
+ .. math::
13
13
 
14
- where Gamma is the Gamma function.
14
+ f(x) = x^{(\\alpha-1)}(1-x)^{(\\beta-1)}\Gamma(\\alpha+\\beta) / (\Gamma(\\alpha)\Gamma(\\beta))
15
+
16
+ where :math:`\Gamma` is the Gamma function.
15
17
 
16
18
  Parameters
17
19
  ------------
18
20
  alpha: float or array_like
21
+ The shape parameter :math:`\\alpha` of the beta distribution.
19
22
 
20
23
  beta: float or array_like
21
-
22
- Methods
23
- -----------
24
- sample: generate one or more random samples
25
- pdf: evaluate probability density function
26
- logpdf: evaluate log probability density function
27
- cdf: evaluate cumulative probability function
28
- gradient: evaluate the gradient of the logpdf
24
+ The shape parameter :math:`\\beta` of the beta distribution.
29
25
 
30
26
  Example
31
27
  -------
@@ -12,12 +12,6 @@ class UserDefinedDistribution(Distribution):
12
12
  gradient_func: Function evaluating the gradient of the logpdf. Callable.
13
13
  sample_func: Function drawing samples from distribution. Callable.
14
14
 
15
- Methods
16
- -----------
17
- sample: generate one or more random samples
18
- logpdf: evaluate log probability density function
19
- gradient: evaluate gradient of logpdf
20
-
21
15
  Example
22
16
  -----------
23
17
  .. code-block:: python
@@ -28,37 +28,6 @@ class Distribution(Density, ABC):
28
28
  is_symmetric : bool, default None
29
29
  Indicator if distribution is symmetric.
30
30
 
31
- Attributes
32
- ----------
33
- dim : int or None
34
- Dimension of distribution.
35
-
36
- name : str or None
37
- Name of distribution.
38
-
39
- geometry : Geometry or None
40
- Geometry of distribution.
41
-
42
- is_cond : bool
43
- Indicator if distribution is conditional.
44
-
45
- Methods
46
- -------
47
- pdf():
48
- Evaluate the probability density function.
49
-
50
- logpdf():
51
- Evaluate the log probability density function.
52
-
53
- sample():
54
- Generate one or more random samples.
55
-
56
- get_conditioning_variables():
57
- Return the conditioning variables of distribution.
58
-
59
- get_mutable_variables():
60
- Return the mutable variables (attributes and properties) of distribution.
61
-
62
31
  Notes
63
32
  -----
64
33
  A distribution can be conditional if one or more mutable variables are unspecified.
@@ -239,6 +208,7 @@ class Distribution(Density, ABC):
239
208
  "enable_FD().")
240
209
 
241
210
  def sample(self,N=1,*args,**kwargs):
211
+ """ Sample from the distribution. """
242
212
 
243
213
  if self.is_cond:
244
214
  raise ValueError(f"Cannot sample from conditional distribution. Missing conditioning variables: {self.get_conditioning_variables()}")
@@ -263,6 +233,7 @@ class Distribution(Density, ABC):
263
233
  pass
264
234
 
265
235
  def pdf(self,x):
236
+ """ Evaluate the log probability density function of the distribution. """
266
237
  return np.exp(self.logpdf(x))
267
238
 
268
239
  def _condition(self, *args, **kwargs):
@@ -6,14 +6,18 @@ from cuqi.utilities import force_ndarray
6
6
  class Gamma(Distribution):
7
7
  """
8
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
+ .. math::
9
11
 
10
- f(x_i; shape, rate) = rate^shape * x_i^(shape-1) * exp(-rate * x_i) / Gamma(shape)
12
+ f(x_i; \\alpha, \\beta) = \\beta^\\alpha x_i^{\\alpha-1} \\exp(-\\beta x_i) / \Gamma(\\alpha)
11
13
 
12
- where `shape` and `rate` are the parameters of the distribution, and Gamma is the Gamma function.
14
+ where shape :math:`\\alpha` and rate :math:`\\beta` are the parameters of the distribution, and :math:`\Gamma` is the Gamma function.
13
15
 
14
16
  In case shape and/or rate are arrays, the pdf looks like
15
17
 
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)
18
+ .. math::
19
+
20
+ f(x_i; \\alpha_i, \\beta_i) = \\beta_i^{\\alpha_i} x_i^{\\alpha_i-1} \\exp(-\\beta_i x_i) / \Gamma(\\alpha_i)
17
21
 
18
22
  Parameters
19
23
  ----------
@@ -730,18 +730,6 @@ class JointGaussianSqrtPrec(Distribution):
730
730
  ------------
731
731
  means: List of means for each Gaussian distribution.
732
732
  sqrtprecs: List of sqrt precision matricies for each Gaussian distribution.
733
-
734
- Attributes
735
- ------------
736
- sqrtprec: Returns the sqrt precision matrix of the joined gaussian in stacked form.
737
- sqrtprecTimesMean: Returns the sqrt precision matrix times the mean of the distribution.
738
-
739
- Methods
740
- -----------
741
- sample: generate one or more random samples (NotImplemented)
742
- pdf: evaluate probability density function (NotImplemented)
743
- logpdf: evaluate log probability density function (NotImplemented)
744
- cdf: evaluate cumulative probability function (NotImplemented)
745
733
  """
746
734
  def __init__(self,means=None,sqrtprecs=None,is_symmetric=True,**kwargs):
747
735
 
@@ -783,6 +771,7 @@ class JointGaussianSqrtPrec(Distribution):
783
771
 
784
772
  @property
785
773
  def sqrtprec(self):
774
+ """ Returns the sqrt precision matrix of the joined gaussian in stacked form. """
786
775
  if spa.issparse(self._sqrtprecs[0]):
787
776
  return spa.vstack((self._sqrtprecs))
788
777
  else:
@@ -790,6 +779,7 @@ class JointGaussianSqrtPrec(Distribution):
790
779
 
791
780
  @property
792
781
  def sqrtprecTimesMean(self):
782
+ """ Returns the sqrt precision matrix times the mean of the distribution."""
793
783
  result = []
794
784
  for i in range(len(self._means)):
795
785
  result.append((self._sqrtprecs[i]@self._means[i]).flatten())
@@ -8,9 +8,11 @@ class InverseGamma(Distribution):
8
8
  """
9
9
  Multivariate inverse gamma distribution of independent random variables x_i. Each is distributed according to the PDF function
10
10
 
11
- f(x) = (x-location)^(-shape-1) * exp(-scale/(x-location)) / (scale^(-shape)*Gamma(shape))
11
+ .. math::
12
12
 
13
- where shape, location and scale are the shape, location and scale of x_i, respectively. And Gamma is the Gamma function.
13
+ f(x) = (x-\\beta)^{(-\\alpha-1)} * \exp(-\\gamma/(x-\\beta)) / (\\gamma^{(-\\alpha)}*\Gamma(\\alpha))
14
+
15
+ where shape :math:`\\alpha`, location :math:`\\beta` and scale :math:`\\gamma` are the shape, location and scale of x_i, respectively. And :math:`\Gamma` is the Gamma function.
14
16
 
15
17
  Parameters
16
18
  ------------
@@ -23,14 +25,6 @@ class InverseGamma(Distribution):
23
25
  scale: float or array_like
24
26
  The scale of the inverse gamma distribution (non-negative)
25
27
 
26
-
27
- Methods
28
- -----------
29
- sample: generate one or more random samples
30
- pdf: evaluate probability density function
31
- logpdf: evaluate log probability density function
32
- cdf: evaluate cumulative probability function
33
-
34
28
  Example
35
29
  -------
36
30
  .. code-block:: python
@@ -16,13 +16,6 @@ class Lognormal(Distribution):
16
16
  cov: np.ndarray
17
17
  Covariance matrix of the normal distribution used to define the lognormal distribution
18
18
 
19
- Methods
20
- -----------
21
- sample: generate one or more random samples
22
- pdf: evaluate probability density function
23
- logpdf: evaluate log probability density function
24
- cdf: evaluate cumulative probability function
25
-
26
19
  Example
27
20
  -------
28
21
  .. code-block:: python
@@ -7,14 +7,17 @@ from cuqi.utilities import force_ndarray
7
7
  class ModifiedHalfNormal(Distribution):
8
8
  """
9
9
  Represents a modified half-normal (MHN) distribution, a three-parameter family of distributions generalizing the Gamma distribution.
10
- The distribution is continuous with pdf
11
- f(x; alpha, beta, gamma) propto x^(alpha-1) * exp(-beta * x^2 + gamma * x)
10
+ The distribution is continuous with pdf
11
+
12
+ .. math::
13
+
14
+ f(x; \\alpha, \\beta, \\gamma) \propto x^{(\\alpha-1)} * \exp(-\\beta * x^2 + \\gamma * x)
12
15
 
13
16
  The MHN generalizes the half-normal distribution, because
14
- f(x; 1, beta, 0) propto exp(-beta * x^2)
17
+ :math:`f(x; 1, \\beta, 0) \propto \exp(-\\beta * x^2)`
15
18
 
16
19
  The MHN generalizes the gamma distribution because
17
- f(x; alpha, 0, -gamma) propto x^(alpha-1) * exp(- gamma * x)
20
+ :math:`f(x; \\alpha, 0, -\\gamma) \propto x^{(\\alpha-1)} * \exp(- \\gamma * x)`
18
21
 
19
22
  Reference:
20
23
  [1] Sun, et al. "The Modified-Half-Normal distribution: Properties and an efficient sampling scheme." Communications in Statistics-Theory and Methods
@@ -22,13 +25,13 @@ class ModifiedHalfNormal(Distribution):
22
25
  Parameters
23
26
  ----------
24
27
  alpha : float
25
- The polynomial exponent parameter of the MHN distribution. Must be positive.
28
+ The polynomial exponent parameter :math:`\\alpha` of the MHN distribution. Must be positive.
26
29
 
27
30
  beta : float
28
- The quadratic exponential parameter of the MHN distribution. Must be positive.
31
+ The quadratic exponential parameter :math:`\\beta` of the MHN distribution. Must be positive.
29
32
 
30
33
  gamma : float
31
- The linear exponential parameter of the MHN distribution.
34
+ The linear exponential parameter :math:`\\gamma` of the MHN distribution.
32
35
 
33
36
  """
34
37
  def __init__(self, alpha=None, beta=None, gamma=None, is_symmetric=False, **kwargs):
@@ -12,13 +12,6 @@ class Normal(Distribution):
12
12
  mean: mean of distribution
13
13
  std: standard deviation
14
14
 
15
- Methods
16
- -----------
17
- sample: generate one or more random samples
18
- pdf: evaluate probability density function
19
- logpdf: evaluate log probability density function
20
- cdf: evaluate cumulative probability function
21
-
22
15
  Example
23
16
  -----------
24
17
  .. code-block:: python
@@ -1,6 +1,7 @@
1
1
  from cuqi.distribution import JointDistribution
2
2
  from cuqi.experimental.mcmc import Sampler
3
3
  from cuqi.samples import Samples
4
+ from cuqi.experimental.mcmc import NUTS
4
5
  from typing import Dict
5
6
  import numpy as np
6
7
  import warnings
@@ -151,18 +152,50 @@ class HybridGibbs:
151
152
  sampler.validate_target()
152
153
 
153
154
  def sample(self, Ns) -> 'HybridGibbs':
154
- """ Sample from the joint distribution using Gibbs sampling """
155
+ """ Sample from the joint distribution using Gibbs sampling
156
+
157
+ Parameters
158
+ ----------
159
+ Ns : int
160
+ The number of samples to draw.
161
+
162
+ """
163
+
155
164
  for _ in tqdm(range(Ns)):
165
+
156
166
  self.step()
167
+
157
168
  self._store_samples()
158
169
 
159
- def warmup(self, Nb) -> 'HybridGibbs':
160
- """ Warmup (tune) the Gibbs sampler """
170
+ return self
171
+
172
+ def warmup(self, Nb, tune_freq=0.1) -> 'HybridGibbs':
173
+ """ Warmup (tune) the samplers in the Gibbs sampling scheme
174
+
175
+ Parameters
176
+ ----------
177
+ Nb : int
178
+ The number of samples to draw during warmup.
179
+
180
+ tune_freq : float, optional
181
+ Frequency of tuning the samplers. Tuning is performed every tune_freq*Nb steps.
182
+
183
+ """
184
+
185
+ tune_interval = max(int(tune_freq * Nb), 1)
186
+
161
187
  for idx in tqdm(range(Nb)):
188
+
162
189
  self.step()
163
- self.tune(idx)
190
+
191
+ # Tune the sampler at tuning intervals (matching behavior of Sampler class)
192
+ if (idx + 1) % tune_interval == 0:
193
+ self.tune(tune_interval, idx // tune_interval)
194
+
164
195
  self._store_samples()
165
196
 
197
+ return self
198
+
166
199
  def get_samples(self) -> Dict[str, Samples]:
167
200
  samples_object = {}
168
201
  for par_name in self.par_names:
@@ -182,38 +215,65 @@ class HybridGibbs:
182
215
  # Get sampler
183
216
  sampler = self.samplers[par_name]
184
217
 
185
- # Set initial parameters using current point and scale (subset of state)
186
- # This does not store the full state from e.g. NUTS sampler
187
- # But works on samplers like MH, PCN, ULA, MALA, LinearRTO, UGLA, CWMH
188
- # that only use initial_point and initial_scale
189
- sampler.initial_point = self.current_samples[par_name]
190
- if hasattr(sampler, 'initial_scale'): sampler.initial_scale = sampler.scale
218
+ # Instead of simply changing the target of the sampler, we reinitialize it.
219
+ # This is to ensure that all internal variables are set to match the new target.
220
+ # To return the sampler to the old state and history, we first extract the state and history
221
+ # before reinitializing the sampler and then set the state and history back to the sampler
222
+
223
+ # Extract state and history from sampler
224
+ if isinstance(sampler, NUTS): # Special case for NUTS as it is not playing nice with get_state and get_history
225
+ sampler.initial_point = sampler.current_point
226
+ else:
227
+ sampler_state = sampler.get_state()
228
+ sampler_history = sampler.get_history()
191
229
 
192
230
  # Reinitialize sampler
193
- # This makes the sampler lose all of its state.
194
- # This is only OK because we set the initial values above from the previous state
195
231
  sampler.reinitialize()
196
232
 
233
+ # Set state and history back to sampler
234
+ if not isinstance(sampler, NUTS): # Again, special case for NUTS.
235
+ sampler.set_state(sampler_state)
236
+ sampler.set_history(sampler_history)
237
+
197
238
  # Run pre_warmup and pre_sample methods for sampler
198
239
  # TODO. Some samplers (NUTS) seem to require to run _pre_warmup before _pre_sample
199
240
  self._pre_warmup_and_pre_sample_sampler(sampler)
200
241
 
201
- # Take MCMC steps
242
+ # Allow for multiple sampling steps in each Gibbs step
202
243
  for _ in range(self.num_sampling_steps[par_name]):
203
- sampler.step()
244
+ # Sampling step
245
+ acc = sampler.step()
246
+
247
+ # Store acceptance rate in sampler (matching behavior of Sampler class Sample method)
248
+ sampler._acc.append(acc)
204
249
 
205
250
  # Extract samples (Ensure even 1-dimensional samples are 1D arrays)
206
- self.current_samples[par_name] = sampler.current_point.reshape(-1)
251
+ if isinstance(sampler.current_point, np.ndarray):
252
+ self.current_samples[par_name] = sampler.current_point.reshape(-1)
253
+ else:
254
+ self.current_samples[par_name] = sampler.current_point
255
+
256
+ def tune(self, skip_len, update_count):
257
+ """ Run a single tuning step on each of the samplers in the Gibbs sampling scheme
258
+
259
+ Parameters
260
+ ----------
261
+ skip_len : int
262
+ Defines the number of steps in between tuning (i.e. the tuning interval).
263
+
264
+ update_count : int
265
+ The number of times tuning has been performed. Can be used for internal bookkeeping.
207
266
 
208
- def tune(self, idx):
209
- """ Tune each of the samplers """
267
+ """
210
268
  for par_name in self.par_names:
211
- self.samplers[par_name].tune(skip_len=1, update_count=idx)
269
+ self.samplers[par_name].tune(skip_len=skip_len, update_count=update_count)
212
270
 
213
271
  # ------------ Private methods ------------
214
272
  def _initialize_samplers(self):
215
273
  """ Initialize samplers """
216
274
  for sampler in self.samplers.values():
275
+ if isinstance(sampler, NUTS):
276
+ print(f'Warning: NUTS sampler is not fully stateful in HybridGibbs. Sampler will be reinitialized in each Gibbs step.')
217
277
  sampler.initialize()
218
278
 
219
279
  def _initialize_num_sampling_steps(self):
cuqi/samples/_samples.py CHANGED
@@ -36,24 +36,6 @@ class Samples(object):
36
36
  geometry : cuqi.geometry.Geometry, default None
37
37
  Contains the geometry related of the samples
38
38
 
39
- Attributes
40
- ----------
41
- shape : tuple
42
- Returns the shape of samples.
43
-
44
- Ns : int
45
- Returns the number of samples
46
-
47
- Methods
48
- ----------
49
- :meth:`plot`: Plots one or more samples.
50
- :meth:`plot_ci`: Plots a credibility interval for the samples.
51
- :meth:`plot_mean`: Plots the mean of the samples.
52
- :meth:`plot_std`: Plots the std of the samples.
53
- :meth:`plot_chain`: Plots all samples of one or more variables (MCMC chain).
54
- :meth:`hist_chain`: Plots histogram of all samples of a single variable (MCMC chain).
55
- :meth:`burnthin`: Removes burn-in and thins samples.
56
- :meth:`diagnostics`: Conducts diagnostics on the chain.
57
39
  """
58
40
  def __init__(self, samples, geometry=None, is_par=True, is_vec=True):
59
41
  self.geometry = geometry
@@ -83,6 +65,7 @@ class Samples(object):
83
65
 
84
66
  @property
85
67
  def shape(self):
68
+ """Returns the shape of samples."""
86
69
  return self.samples.shape
87
70
 
88
71
  @property
@@ -408,6 +391,7 @@ class Samples(object):
408
391
  return ax
409
392
 
410
393
  def plot(self,sample_indices=None,*args,**kwargs):
394
+ """ Plots one or more samples. """
411
395
  Ns = self.Ns
412
396
  Np = 5 # Number of samples to plot if Ns > 5
413
397
 
@@ -447,6 +431,7 @@ class Samples(object):
447
431
  return lines
448
432
 
449
433
  def hist_chain(self,variable_indices,*args,**kwargs):
434
+ """ Plots samples histogram of variables with indices specified in variable_indices. """
450
435
 
451
436
  self._raise_error_if_not_vec(self.hist_chain.__name__)
452
437
 
@@ -580,6 +565,7 @@ class Samples(object):
580
565
 
581
566
 
582
567
  def diagnostics(self):
568
+ """ Conducts diagnostics on the chain (Geweke test). """
583
569
  # Geweke test
584
570
  Geweke(self.samples.T)
585
571
 
cuqi/solver/_solver.py CHANGED
@@ -174,9 +174,12 @@ class LS(object):
174
174
  """Wrapper for :meth:`scipy.optimize.least_squares`.
175
175
 
176
176
  Solve nonlinear least-squares problems with bounds:
177
+
178
+ .. math::
177
179
 
178
- minimize F(x) = 0.5 * sum(rho(f_i(x)**2), i = 0, ..., m-1)
179
- subject to lb <= x <= ub
180
+ \min F(x) = 0.5 * \sum(\\rho(f_i(x)^2), i = 0, ..., m-1)
181
+
182
+ subject to :math:`lb <= x <= ub`.
180
183
 
181
184
  Parameters
182
185
  ----------