pygeoinf 1.1.2__py3-none-any.whl → 1.1.4__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.
pygeoinf/operators.py CHANGED
@@ -48,8 +48,8 @@ class Operator:
48
48
 
49
49
  def __init__(
50
50
  self,
51
- domain: "HilbertSpace",
52
- codomain: "HilbertSpace",
51
+ domain: HilbertSpace,
52
+ codomain: HilbertSpace,
53
53
  mapping: Callable[[Any], Any],
54
54
  ) -> None:
55
55
  """
@@ -61,17 +61,17 @@ class Operator:
61
61
  mapping (callable): The function defining the mapping from the
62
62
  domain to the codomain.
63
63
  """
64
- self._domain: "HilbertSpace" = domain
65
- self._codomain: "HilbertSpace" = codomain
64
+ self._domain: HilbertSpace = domain
65
+ self._codomain: HilbertSpace = codomain
66
66
  self.__mapping: Callable[[Any], Any] = mapping
67
67
 
68
68
  @property
69
- def domain(self) -> "HilbertSpace":
69
+ def domain(self) -> HilbertSpace:
70
70
  """The domain of the operator."""
71
71
  return self._domain
72
72
 
73
73
  @property
74
- def codomain(self) -> "HilbertSpace":
74
+ def codomain(self) -> HilbertSpace:
75
75
  """The codomain of the operator."""
76
76
  return self._codomain
77
77
 
@@ -111,8 +111,8 @@ class LinearOperator(Operator):
111
111
 
112
112
  def __init__(
113
113
  self,
114
- domain: "HilbertSpace",
115
- codomain: "HilbertSpace",
114
+ domain: HilbertSpace,
115
+ codomain: HilbertSpace,
116
116
  mapping: Callable[[Any], Any],
117
117
  /,
118
118
  *,
@@ -158,21 +158,21 @@ class LinearOperator(Operator):
158
158
 
159
159
  @staticmethod
160
160
  def self_dual(
161
- domain: "HilbertSpace", mapping: Callable[[Any], Any]
161
+ domain: HilbertSpace, mapping: Callable[[Any], Any]
162
162
  ) -> LinearOperator:
163
163
  """Creates a self-dual operator."""
164
164
  return LinearOperator(domain, domain.dual, mapping, dual_mapping=mapping)
165
165
 
166
166
  @staticmethod
167
167
  def self_adjoint(
168
- domain: "HilbertSpace", mapping: Callable[[Any], Any]
168
+ domain: HilbertSpace, mapping: Callable[[Any], Any]
169
169
  ) -> LinearOperator:
170
170
  """Creates a self-adjoint operator."""
171
171
  return LinearOperator(domain, domain, mapping, adjoint_mapping=mapping)
172
172
 
173
173
  @staticmethod
174
174
  def from_formal_adjoint(
175
- domain: "HilbertSpace", codomain: "HilbertSpace", operator: LinearOperator
175
+ domain: HilbertSpace, codomain: HilbertSpace, operator: LinearOperator
176
176
  ) -> LinearOperator:
177
177
  """
178
178
  Constructs an operator on weighted spaces from one on the underlying spaces.
@@ -183,6 +183,10 @@ class LinearOperator(Operator):
183
183
  correctly defines the new operator's adjoint with respect to the
184
184
  weighted inner products.
185
185
 
186
+ This method automatically handles cases where the domain and/or codomain
187
+ are a `HilbertSpaceDirectSum`, recursively building the necessary
188
+ block-structured mass operators.
189
+
186
190
  Args:
187
191
  domain: The (potentially) mass-weighted domain of the new operator.
188
192
  codomain: The (potentially) mass-weighted codomain of the new operator.
@@ -193,23 +197,40 @@ class LinearOperator(Operator):
193
197
  A new `LinearOperator` that acts between the mass-weighted spaces.
194
198
  """
195
199
  from .hilbert_space import MassWeightedHilbertSpace
200
+ from .direct_sum import HilbertSpaceDirectSum, BlockDiagonalLinearOperator
201
+
202
+ def get_properties(space: HilbertSpace):
203
+ if isinstance(space, MassWeightedHilbertSpace):
204
+ return (
205
+ space.underlying_space,
206
+ space.mass_operator,
207
+ space.inverse_mass_operator,
208
+ )
209
+ elif isinstance(space, HilbertSpaceDirectSum):
210
+ properties = [get_properties(subspace) for subspace in space.subspaces]
211
+ underlying_space = HilbertSpaceDirectSum(
212
+ [property[0] for property in properties]
213
+ )
214
+ mass_operator = BlockDiagonalLinearOperator(
215
+ [property[1] for property in properties]
216
+ )
217
+ inverse_mass_operator = BlockDiagonalLinearOperator(
218
+ [property[2] for property in properties]
219
+ )
220
+ return (
221
+ underlying_space,
222
+ mass_operator,
223
+ inverse_mass_operator,
224
+ )
225
+ else:
226
+ return space, space.identity_operator(), space.identity_operator()
196
227
 
197
- if isinstance(domain, MassWeightedHilbertSpace):
198
- domain_base = domain.underlying_space
199
- domain_inverse_mass_operator = domain.inverse_mass_operator
200
- else:
201
- domain_base = domain
202
- domain_inverse_mass_operator = domain.identity_operator()
203
-
204
- if isinstance(codomain, MassWeightedHilbertSpace):
205
- codomain_base = codomain.underlying_space
206
- codomain_mass_operator = codomain.mass_operator
207
- else:
208
- codomain_base = codomain
209
- codomain_mass_operator = codomain.identity_operator()
228
+ domain_base, _, domain_inverse_mass_operator = get_properties(domain)
229
+ codomain_base, codomain_mass_operator, _ = get_properties(codomain)
210
230
 
211
231
  if domain_base != operator.domain:
212
232
  raise ValueError("Domain mismatch")
233
+
213
234
  if codomain_base != operator.codomain:
214
235
  raise ValueError("Codomain mismatch")
215
236
 
@@ -224,26 +245,25 @@ class LinearOperator(Operator):
224
245
 
225
246
  @staticmethod
226
247
  def from_formally_self_adjoint(
227
- domain: "HilbertSpace", operator: LinearOperator
248
+ domain: HilbertSpace, operator: LinearOperator
228
249
  ) -> LinearOperator:
229
250
  """
230
- Method to construct LinearOperators on MassWeightedHilbertSpaces
231
- that are self-adjoint on the underlying space.
251
+ Constructs a self-adjoint operator on a weighted space.
252
+
253
+ This method takes an operator that is formally self-adjoint on an
254
+ underlying (unweighted) space and promotes it to a truly self-adjoint
255
+ operator on the `MassWeightedHilbertSpace`. It automatically handles
256
+ `HilbertSpaceDirectSum` domains.
232
257
 
233
258
  Args:
234
- domain (MassWeightedHilbertSpace): The domain of the operator.
235
- operator (LinearOperator): The operator to be converted
236
-
237
- Notes:
238
- If the domain is not a MassWeightedHilbertSpace, the underlying
239
- domain is taken to be the domain, and the mass operator the identity.
240
- In such cases the method is well-defined but pointless as the output
241
- operator is identical to the input operator.
259
+ domain (HilbertSpace): The domain of the operator, which can be a
260
+ `MassWeightedHilbertSpace` or a `HilbertSpaceDirectSum`.
261
+ operator (LinearOperator): The operator to be converted.
242
262
  """
243
263
  return LinearOperator.from_formal_adjoint(domain, domain, operator)
244
264
 
245
265
  @staticmethod
246
- def from_linear_forms(forms: List["LinearForm"]) -> LinearOperator:
266
+ def from_linear_forms(forms: List[LinearForm]) -> LinearOperator:
247
267
  """
248
268
  Creates an operator from a list of linear forms.
249
269
 
@@ -275,8 +295,8 @@ class LinearOperator(Operator):
275
295
 
276
296
  @staticmethod
277
297
  def from_matrix(
278
- domain: "HilbertSpace",
279
- codomain: "HilbertSpace",
298
+ domain: HilbertSpace,
299
+ codomain: HilbertSpace,
280
300
  matrix: Union[np.ndarray, ScipyLinOp],
281
301
  /,
282
302
  *,
@@ -365,7 +385,7 @@ class LinearOperator(Operator):
365
385
 
366
386
  @staticmethod
367
387
  def self_adjoint_from_matrix(
368
- domain: "HilbertSpace", matrix: Union[np.ndarray, ScipyLinOp]
388
+ domain: HilbertSpace, matrix: Union[np.ndarray, ScipyLinOp]
369
389
  ) -> LinearOperator:
370
390
  """Forms a self-adjoint operator from its Galerkin matrix."""
371
391
 
@@ -379,8 +399,8 @@ class LinearOperator(Operator):
379
399
 
380
400
  @staticmethod
381
401
  def from_tensor_product(
382
- domain: "HilbertSpace",
383
- codomain: "HilbertSpace",
402
+ domain: HilbertSpace,
403
+ codomain: HilbertSpace,
384
404
  vector_pairs: List[Tuple[Any, Any]],
385
405
  /,
386
406
  *,
@@ -414,7 +434,7 @@ class LinearOperator(Operator):
414
434
 
415
435
  @staticmethod
416
436
  def self_adjoint_from_tensor_product(
417
- domain: "HilbertSpace",
437
+ domain: HilbertSpace,
418
438
  vectors: List[Any],
419
439
  /,
420
440
  *,
@@ -697,7 +717,7 @@ class LinearOperator(Operator):
697
717
  galerkin=True,
698
718
  )
699
719
 
700
- def _dual_mapping_default(self, yp: Any) -> "LinearForm":
720
+ def _dual_mapping_default(self, yp: Any) -> LinearForm:
701
721
  from .linear_forms import LinearForm
702
722
 
703
723
  return LinearForm(self.domain, mapping=lambda x: yp(self(x)))
@@ -809,8 +829,8 @@ class DiagonalLinearOperator(LinearOperator):
809
829
 
810
830
  def __init__(
811
831
  self,
812
- domain: "HilbertSpace",
813
- codomain: "HilbertSpace",
832
+ domain: HilbertSpace,
833
+ codomain: HilbertSpace,
814
834
  diagonal_values: np.ndarray,
815
835
  /,
816
836
  *,
@@ -425,6 +425,18 @@ class Lebesgue(SphereHelper, HilbertModule, AbstractInvariantLebesgueSpace):
425
425
  """
426
426
  return x1 * x2
427
427
 
428
+ def __eq__(self, other: object) -> bool:
429
+ """
430
+ Checks for mathematical equality with another Sobolev space on a sphere.
431
+
432
+ Two spaces are considered equal if they are of the same type and have
433
+ the same defining parameters (kmax, order, scale, and radius).
434
+ """
435
+ if not isinstance(other, Lebesgue):
436
+ return NotImplemented
437
+
438
+ return self.lmax == other.lmax and self.radius == other.radius
439
+
428
440
  def eigenfunction_norms(self) -> np.ndarray:
429
441
  """Returns a list of the norms of the eigenfunctions."""
430
442
  return np.fromiter(
@@ -445,10 +457,6 @@ class Lebesgue(SphereHelper, HilbertModule, AbstractInvariantLebesgueSpace):
445
457
 
446
458
  return LinearOperator.self_adjoint(self, mapping)
447
459
 
448
- # ================================================================ #
449
- # Private methods #
450
- # ================================================================ #
451
-
452
460
 
453
461
  class Sobolev(SphereHelper, MassWeightedHilbertModule, AbstractInvariantSobolevSpace):
454
462
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pygeoinf
3
- Version: 1.1.2
3
+ Version: 1.1.4
4
4
  Summary: A package for solving geophysical inference and inverse problems
5
5
  License: BSD-3-Clause
6
6
  Author: David Al-Attar and Dan Heathcote
@@ -8,13 +8,13 @@ pygeoinf/linear_bayesian.py,sha256=aIOzTZbjJtdtwHKh5e01iS8iMiyr8XuwGx91udS3VK4,9
8
8
  pygeoinf/linear_forms.py,sha256=Uizipi67i1Sd6m0TzsrJd99Xreo_6V8Db0gMy76fG6g,5953
9
9
  pygeoinf/linear_optimisation.py,sha256=7lklTRRBGkz8M9WsfvkDl-eoGkc4Ty7BOJq7LWkdxCg,11091
10
10
  pygeoinf/linear_solvers.py,sha256=P9SEjZ1LZdulr2KQrZojbvdCtAm--hMd4EArSu73L34,12154
11
- pygeoinf/operators.py,sha256=JPDrdLSnM-Y5_CWJ58WDvHBzo3hPoFoUoAOS63QFJmc,32272
11
+ pygeoinf/operators.py,sha256=kbDfHpaWaSnd0zvoAVMBpWWiQRNfW0ImVhtzEEIH6mM,33165
12
12
  pygeoinf/random_matrix.py,sha256=_XVwXqM_c0SMpy6JU-8IboXpotug6dDDHKdSPAJpH7c,7788
13
13
  pygeoinf/symmetric_space/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  pygeoinf/symmetric_space/circle.py,sha256=0EHPg2FcvWTOvCb8ualCW0uUp8RuUNfQ7oK6NHXtG1Q,17552
15
- pygeoinf/symmetric_space/sphere.py,sha256=vKwvTa-9GMNlN-LBUWaEsZ8vM-dZtQtT71UPDSXZufY,20309
15
+ pygeoinf/symmetric_space/sphere.py,sha256=hg9eAXdwbU9l_QssEcq86FOAQc6mBf416OKVjgsU2Ic,20540
16
16
  pygeoinf/symmetric_space/symmetric_space.py,sha256=YkRjHucc2cO7IAoyJS5KMdiRBuytRpUfTUsVMHBPZYs,16146
17
- pygeoinf-1.1.2.dist-info/LICENSE,sha256=GrTQnKJemVi69FSbHprq60KN0OJGsOSR-joQoTq-oD8,1501
18
- pygeoinf-1.1.2.dist-info/METADATA,sha256=sv7ENSZqZDN3Diivozfbjyzh-OlYrJV3rbBZ-gc076c,15324
19
- pygeoinf-1.1.2.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
20
- pygeoinf-1.1.2.dist-info/RECORD,,
17
+ pygeoinf-1.1.4.dist-info/LICENSE,sha256=GrTQnKJemVi69FSbHprq60KN0OJGsOSR-joQoTq-oD8,1501
18
+ pygeoinf-1.1.4.dist-info/METADATA,sha256=jFoUW2ZH9MrnRw-ZDJvwMJXL0R3yH5KdnLt2chnThUI,15324
19
+ pygeoinf-1.1.4.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
20
+ pygeoinf-1.1.4.dist-info/RECORD,,