CUQIpy 1.3.0.post0.dev86__py3-none-any.whl → 1.3.0.post0.dev104__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-04-10T10:50:04+0200",
11
+ "date": "2025-04-28T12:59:25+0200",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "fe056d15f6ff918511cf7ee579dc8e7689c1dbc4",
15
- "version": "1.3.0.post0.dev86"
14
+ "full-revisionid": "c62aed4105837bc321e7e325f1b1a2286c659b2f",
15
+ "version": "1.3.0.post0.dev104"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -3,7 +3,7 @@ from scipy.linalg.interpolative import estimate_spectral_norm
3
3
  from scipy.sparse.linalg import LinearOperator as scipyLinearOperator
4
4
  import numpy as np
5
5
  import cuqi
6
- from cuqi.solver import CGLS, FISTA, ADMM, ScipyLinearLSQ
6
+ from cuqi.solver import CGLS, FISTA, ADMM, ScipyLinearLSQ, ScipyMinimizer
7
7
  from cuqi.experimental.mcmc import Sampler
8
8
 
9
9
 
@@ -167,6 +167,7 @@ class RegularizedLinearRTO(LinearRTO):
167
167
  ADMM: [2] Boyd et al. "Distributed optimization and statistical learning via the alternating direction method of multipliers."Foundations and Trends® in Machine learning, 2011.
168
168
  Used when prior.proximal is a list of penalty terms.
169
169
  ScipyLinearLSQ: Wrapper for Scipy's lsq_linear for the Trust Region Reflective algorithm. Optionally used when the constraint is either "nonnegativity" or "box".
170
+ ScipyMinimizer: Wrapper for Scipy's minimize. Optionally used when the constraint is either "nonnegativity" or "box".
170
171
 
171
172
  Parameters
172
173
  ------------
@@ -177,7 +178,7 @@ class RegularizedLinearRTO(LinearRTO):
177
178
  Initial point for the sampler. *Optional*.
178
179
 
179
180
  maxit : int
180
- Maximum number of iterations of the FISTA/ADMM/ScipyLinearLSQ solver. *Optional*.
181
+ Maximum number of iterations of the FISTA/ADMM/ScipyLinearLSQ/ScipyMinimizer solver. *Optional*.
181
182
 
182
183
  inner_max_it : int
183
184
  Maximum number of iterations of the CGLS solver used within the ADMM solver. *Optional*.
@@ -191,7 +192,7 @@ class RegularizedLinearRTO(LinearRTO):
191
192
  See [2] or `cuqi.solver.ADMM`
192
193
 
193
194
  abstol : float
194
- Absolute tolerance of the FISTA/ScipyLinearLSQ solver. *Optional*.
195
+ Absolute tolerance of the FISTA/ScipyLinearLSQ/ScipyMinimizer solver. *Optional*.
195
196
 
196
197
  inner_abstol : float
197
198
  Tolerance parameter for ScipyLinearLSQ's inner solve of the unbounded least-squares problem. *Optional*.
@@ -200,7 +201,7 @@ class RegularizedLinearRTO(LinearRTO):
200
201
  If True, FISTA is used as solver, otherwise ISTA is used. *Optional*.
201
202
 
202
203
  solver : string
203
- If set to "ScipyLinearLSQ", solver is set to cuqi.solver.ScipyLinearLSQ, otherwise FISTA/ISTA or ADMM is used. Note "ScipyLinearLSQ" can only be used with `RegularizedGaussian` of `box` or `nonnegativity` constraint. *Optional*.
204
+ 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*.
204
205
 
205
206
  callback : callable, optional
206
207
  A function that will be called after each sampling step. It can be useful for monitoring the sampler during sampling.
@@ -234,11 +235,11 @@ class RegularizedLinearRTO(LinearRTO):
234
235
 
235
236
  @solver.setter
236
237
  def solver(self, value):
237
- if value == "ScipyLinearLSQ":
238
+ if value == "ScipyLinearLSQ" or value == "ScipyMinimizer":
238
239
  if (self.target.prior.preset["constraint"] == "nonnegativity" or self.target.prior.preset["constraint"] == "box"):
239
240
  self._solver = value
240
241
  else:
241
- raise ValueError("ScipyLinearLSQ only supports RegularizedGaussian with box or nonnegativity constraint.")
242
+ raise ValueError("ScipyLinearLSQ and ScipyMinimizer only support RegularizedGaussian with box or nonnegativity constraint.")
242
243
  else:
243
244
  self._solver = value
244
245
 
@@ -281,15 +282,22 @@ class RegularizedLinearRTO(LinearRTO):
281
282
  sim = ADMM(self.M, y, self.proximal,
282
283
  self.current_point, self.penalty_parameter, maxit = self.maxit, inner_max_it = self.inner_max_it, adaptive = self.adaptive)
283
284
  elif self.solver == "ScipyLinearLSQ":
284
- A_op = sp.sparse.linalg.LinearOperator((sum([llh.dim for llh in self.likelihoods])+self.target.prior.dim, self.target.prior.dim),
285
- matvec=lambda x: self.M(x, 1),
286
- rmatvec=lambda x: self.M(x, 2)
287
- )
288
- sim = ScipyLinearLSQ(A_op, y, self.target.prior._box_bounds,
289
- max_iter = self.maxit,
290
- lsmr_maxiter = self.inner_max_it,
291
- tol = self.abstol,
292
- lsmr_tol = self.inner_abstol)
285
+ A_op = sp.sparse.linalg.LinearOperator((sum([llh.distribution.dim for llh in self.likelihoods])+self.target.prior.dim, self.target.prior.dim),
286
+ matvec=lambda x: self.M(x, 1),
287
+ rmatvec=lambda x: self.M(x, 2)
288
+ )
289
+ sim = ScipyLinearLSQ(A_op, y, self.target.prior._box_bounds,
290
+ max_iter = self.maxit,
291
+ lsmr_maxiter = self.inner_max_it,
292
+ tol = self.abstol,
293
+ lsmr_tol = self.inner_abstol)
294
+ elif self.solver == "ScipyMinimizer":
295
+ # Adapt bounds format, as scipy.minimize requires a bounds format
296
+ # different than that in scipy.lsq_linear.
297
+ bounds = [(self.target.prior._box_bounds[0][i], self.target.prior._box_bounds[1][i]) for i in range(self.target.prior.dim)]
298
+ # Note that the objective function is defined as 0.5*||Mx-y||^2,
299
+ # 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), self.current_point, gradfunc=lambda x: self.M(self.M(x, 1) - y, 2), bounds=bounds, tol=self.abstol, options={"maxiter": self.maxit})
293
301
  else:
294
302
  raise ValueError("Choice of solver not supported.")
295
303
 
cuqi/solver/_solver.py CHANGED
@@ -196,8 +196,11 @@ class ScipyLSQ(object):
196
196
  'trf', Trust Region Reflective algorithm: for large sparse problems with bounds.
197
197
  'dogbox', dogleg algorithm with rectangular trust regions, for small problems with bounds.
198
198
  'lm', Levenberg-Marquardt algorithm as implemented in MINPACK. Doesn't handle bounds and sparse Jacobians.
199
+ tol : The numerical tolerance for convergence checks.
200
+ maxit : The maximum number of iterations.
201
+ kwargs : Additional keyword arguments passed to scipy's least_squares. Empty by default. See documentation for scipy.optimize.least_squares
199
202
  """
200
- def __init__(self, func, x0, jacfun='2-point', method='trf', loss='linear', tol=1e-6, maxit=1e4):
203
+ def __init__(self, func, x0, jacfun='2-point', method='trf', loss='linear', tol=1e-6, maxit=1e4, **kwargs):
201
204
  self.func = func
202
205
  self.x0 = x0
203
206
  self.jacfun = jacfun
@@ -205,6 +208,7 @@ class ScipyLSQ(object):
205
208
  self.loss = loss
206
209
  self.tol = tol
207
210
  self.maxit = int(maxit)
211
+ self.kwargs = kwargs
208
212
 
209
213
  def solve(self):
210
214
  """Runs optimization algorithm and returns solution and info.
@@ -215,7 +219,7 @@ class ScipyLSQ(object):
215
219
  Solution found (array_like) and optimization information (dictionary).
216
220
  """
217
221
  solution = least_squares(self.func, self.x0, jac=self.jacfun, \
218
- method=self.method, loss=self.loss, xtol=self.tol, max_nfev=self.maxit)
222
+ method=self.method, loss=self.loss, xtol=self.tol, max_nfev=self.maxit, **self.kwargs)
219
223
  info = {"success": solution['success'],
220
224
  "message": solution['message'],
221
225
  "func": solution['fun'],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: CUQIpy
3
- Version: 1.3.0.post0.dev86
3
+ Version: 1.3.0.post0.dev104
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=5BoF7RelweJtRYABv01YoLMQTIvAp9dGHYbyo9mk5u4,509
3
+ cuqi/_version.py,sha256=guMao82iJ7XuaWXVsBLkNDaBLZLETh0C0JtSWy0RCeA,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
@@ -52,7 +52,7 @@ cuqi/experimental/mcmc/_langevin_algorithm.py,sha256=1UunuocpzG1h6GiYefEHFOMykEM
52
52
  cuqi/experimental/mcmc/_laplace_approximation.py,sha256=I5ZLtU0lA34YflRbqxKi5UgJBhhHzxqUyVW5JE5-l2w,5916
53
53
  cuqi/experimental/mcmc/_mh.py,sha256=MXo0ahXP4KGFkaY4HtvcBE-TMQzsMlTmLKzSvpz7drU,2941
54
54
  cuqi/experimental/mcmc/_pcn.py,sha256=wqJBZLuRFSwxihaI53tumAg6AWVuceLMOmXssTetd1A,3374
55
- cuqi/experimental/mcmc/_rto.py,sha256=2RJm1NMIvmCbTBn0M8S8vNLaRjaS1_7S9gVOdG9I8Bo,14159
55
+ cuqi/experimental/mcmc/_rto.py,sha256=BY55Njw3-dcmjd-V1vQ58CisEDllQ8zaEj92pWB6LCM,15158
56
56
  cuqi/experimental/mcmc/_sampler.py,sha256=VK-VsPRaYET43C5quhu2f1OstEX5DKYKVyjKABTRHZE,20288
57
57
  cuqi/experimental/mcmc/_utilities.py,sha256=kUzHbhIS3HYZRbneNBK41IogUYX5dS_bJxqEGm7TQBI,525
58
58
  cuqi/geometry/__init__.py,sha256=Tz1WGzZBY-QGH3c0GiyKm9XHN8MGGcnU6TUHLZkzB3o,842
@@ -87,14 +87,14 @@ cuqi/sampler/_sampler.py,sha256=TkZ_WAS-5Q43oICa-Elc2gftsRTBd7PEDUMDZ9tTGmU,5712
87
87
  cuqi/samples/__init__.py,sha256=vCs6lVk-pi8RBqa6cIN5wyn6u-K9oEf1Na4k1ZMrYv8,44
88
88
  cuqi/samples/_samples.py,sha256=hUc8OnCF9CTCuDTrGHwwzv3wp8mG_6vsJAFvuQ-x0uA,35832
89
89
  cuqi/solver/__init__.py,sha256=KYgAi_8VoAwljTB3S2I87YnJkRtedskLee7hQp_-zp8,220
90
- cuqi/solver/_solver.py,sha256=_Q47Atv8Ze6eMJzA22s0OzdW4lcDigRhbotnCzmrQWE,30662
90
+ cuqi/solver/_solver.py,sha256=X3EWD-26o9UOBsWRuy0ktYsJiUXwpCGm0lvTdQM6dRI,30964
91
91
  cuqi/testproblem/__init__.py,sha256=DWTOcyuNHMbhEuuWlY5CkYkNDSAqhvsKmJXBLivyblU,202
92
92
  cuqi/testproblem/_testproblem.py,sha256=x769LwwRdJdzIiZkcQUGb_5-vynNTNALXWKato7sS0Q,52540
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=as8cFswoxROS0Z7WUKzLIE-ZtEKCXes5M3Gdmmb47No,18414
96
- cuqipy-1.3.0.post0.dev86.dist-info/licenses/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
97
- cuqipy-1.3.0.post0.dev86.dist-info/METADATA,sha256=lG1Acs-TjKb60yfRHgywc3q1EQY1HuI9bjLQA5CAQNE,18623
98
- cuqipy-1.3.0.post0.dev86.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
99
- cuqipy-1.3.0.post0.dev86.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
100
- cuqipy-1.3.0.post0.dev86.dist-info/RECORD,,
96
+ cuqipy-1.3.0.post0.dev104.dist-info/licenses/LICENSE,sha256=kJWRPrtRoQoZGXyyvu50Uc91X6_0XRaVfT0YZssicys,10799
97
+ cuqipy-1.3.0.post0.dev104.dist-info/METADATA,sha256=ocRbxXFZqKPsVVnPjFNgacaxLE8zeXDD71iHGk6q6j8,18624
98
+ cuqipy-1.3.0.post0.dev104.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
99
+ cuqipy-1.3.0.post0.dev104.dist-info/top_level.txt,sha256=AgmgMc6TKfPPqbjV0kvAoCBN334i_Lwwojc7HE3ZwD0,5
100
+ cuqipy-1.3.0.post0.dev104.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5