pygeoinf 1.0.9__py3-none-any.whl → 1.1.1__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/__init__.py +5 -1
- pygeoinf/direct_sum.py +101 -75
- pygeoinf/forward_problem.py +33 -32
- pygeoinf/gaussian_measure.py +97 -71
- pygeoinf/hilbert_space.py +517 -241
- pygeoinf/inversion.py +16 -4
- pygeoinf/linear_bayesian.py +57 -36
- pygeoinf/linear_forms.py +169 -0
- pygeoinf/linear_optimisation.py +34 -23
- pygeoinf/linear_solvers.py +74 -247
- pygeoinf/operators.py +175 -36
- pygeoinf/random_matrix.py +36 -32
- pygeoinf/symmetric_space/circle.py +347 -202
- pygeoinf/symmetric_space/sphere.py +335 -448
- pygeoinf/symmetric_space/symmetric_space.py +330 -142
- {pygeoinf-1.0.9.dist-info → pygeoinf-1.1.1.dist-info}/METADATA +11 -9
- pygeoinf-1.1.1.dist-info/RECORD +20 -0
- pygeoinf/forms.py +0 -128
- pygeoinf/symmetric_space/line.py +0 -384
- pygeoinf-1.0.9.dist-info/RECORD +0 -21
- {pygeoinf-1.0.9.dist-info → pygeoinf-1.1.1.dist-info}/LICENSE +0 -0
- {pygeoinf-1.0.9.dist-info → pygeoinf-1.1.1.dist-info}/WHEEL +0 -0
pygeoinf/forms.py
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Module defining the LinearForm class.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from __future__ import annotations
|
|
6
|
-
from typing import Callable, Optional, Any, TYPE_CHECKING
|
|
7
|
-
|
|
8
|
-
import numpy as np
|
|
9
|
-
|
|
10
|
-
# This block only runs for type checkers, not at runtime
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from .hilbert_space import HilbertSpace, EuclideanSpace
|
|
13
|
-
from .operators import LinearOperator
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class LinearForm:
|
|
17
|
-
"""
|
|
18
|
-
Represents a linear form, which is a linear functional that maps
|
|
19
|
-
vectors from a Hilbert space to a scalar value (a real number).
|
|
20
|
-
|
|
21
|
-
Internally, the form is represented by its components relative to the basis for
|
|
22
|
-
its domain, with these components stored as in a numpy vector.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def __init__(
|
|
26
|
-
self,
|
|
27
|
-
domain: "HilbertSpace",
|
|
28
|
-
/,
|
|
29
|
-
*,
|
|
30
|
-
mapping: Optional[Callable[[Any], float]] = None,
|
|
31
|
-
components: Optional[np.ndarray] = None,
|
|
32
|
-
) -> None:
|
|
33
|
-
"""
|
|
34
|
-
Initializes the LinearForm.
|
|
35
|
-
|
|
36
|
-
A form can be defined either by its mapping or its component vector.
|
|
37
|
-
|
|
38
|
-
Args:
|
|
39
|
-
domain (HilbertSpace): The Hilbert space on which the form is defined.
|
|
40
|
-
mapping (callable, optional): A function defining the action of the form.
|
|
41
|
-
components (np.ndarray, optional): The component representation of
|
|
42
|
-
the form.
|
|
43
|
-
"""
|
|
44
|
-
|
|
45
|
-
self._domain: "HilbertSpace" = domain
|
|
46
|
-
|
|
47
|
-
if components is None:
|
|
48
|
-
if mapping is None:
|
|
49
|
-
raise AssertionError("Neither mapping nor components specified.")
|
|
50
|
-
self._components = np.zeros(self.domain.dim)
|
|
51
|
-
cx = np.zeros(self.domain.dim)
|
|
52
|
-
for i in range(self.domain.dim):
|
|
53
|
-
cx[i] = 1
|
|
54
|
-
x = self.domain.from_components(cx)
|
|
55
|
-
self._components[i] = mapping(x)
|
|
56
|
-
cx[i] = 0
|
|
57
|
-
else:
|
|
58
|
-
self._components: np.ndarray = components
|
|
59
|
-
|
|
60
|
-
@staticmethod
|
|
61
|
-
def from_linear_operator(operator: "LinearOperator") -> "LinearForm":
|
|
62
|
-
"""
|
|
63
|
-
Creates a LinearForm from an operator that maps to a 1D Euclidean space.
|
|
64
|
-
"""
|
|
65
|
-
from .hilbert_space import EuclideanSpace
|
|
66
|
-
|
|
67
|
-
assert operator.codomain == EuclideanSpace(1)
|
|
68
|
-
return LinearForm(operator.domain, mapping=lambda x: operator(x)[0])
|
|
69
|
-
|
|
70
|
-
@property
|
|
71
|
-
def domain(self) -> "HilbertSpace":
|
|
72
|
-
"""The Hilbert space on which the form is defined."""
|
|
73
|
-
return self._domain
|
|
74
|
-
|
|
75
|
-
@property
|
|
76
|
-
def components(self) -> np.ndarray:
|
|
77
|
-
"""
|
|
78
|
-
The component vector of the form.
|
|
79
|
-
"""
|
|
80
|
-
return self._components
|
|
81
|
-
|
|
82
|
-
@property
|
|
83
|
-
def as_linear_operator(self) -> "LinearOperator":
|
|
84
|
-
"""
|
|
85
|
-
Represents the linear form as a LinearOperator mapping to a
|
|
86
|
-
1D Euclidean space.
|
|
87
|
-
"""
|
|
88
|
-
from .hilbert_space import EuclideanSpace
|
|
89
|
-
from .operators import LinearOperator
|
|
90
|
-
|
|
91
|
-
return LinearOperator(
|
|
92
|
-
self.domain,
|
|
93
|
-
EuclideanSpace(1),
|
|
94
|
-
lambda x: np.array([self(x)]),
|
|
95
|
-
dual_mapping=lambda y: y * self,
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
def __call__(self, x: Any) -> float:
|
|
99
|
-
"""Applies the linear form to a vector."""
|
|
100
|
-
return np.dot(self._components, self.domain.to_components(x))
|
|
101
|
-
|
|
102
|
-
def __neg__(self) -> "LinearForm":
|
|
103
|
-
"""Returns the additive inverse of the form."""
|
|
104
|
-
return LinearForm(self.domain, components=-self._components)
|
|
105
|
-
|
|
106
|
-
def __mul__(self, a: float) -> "LinearForm":
|
|
107
|
-
"""Returns the product of the form and a scalar."""
|
|
108
|
-
return LinearForm(self.domain, components=a * self._components)
|
|
109
|
-
|
|
110
|
-
def __rmul__(self, a: float) -> "LinearForm":
|
|
111
|
-
"""Returns the product of the form and a scalar."""
|
|
112
|
-
return self * a
|
|
113
|
-
|
|
114
|
-
def __truediv__(self, a: float) -> "LinearForm":
|
|
115
|
-
"""Returns the division of the form by a scalar."""
|
|
116
|
-
return self * (1.0 / a)
|
|
117
|
-
|
|
118
|
-
def __add__(self, other: "LinearForm") -> "LinearForm":
|
|
119
|
-
"""Returns the sum of this form and another."""
|
|
120
|
-
return LinearForm(self.domain, components=self.components + other.components)
|
|
121
|
-
|
|
122
|
-
def __sub__(self, other: "LinearForm") -> "LinearForm":
|
|
123
|
-
"""Returns the difference between this form and another."""
|
|
124
|
-
return LinearForm(self.domain, components=self.components - other.components)
|
|
125
|
-
|
|
126
|
-
def __str__(self) -> str:
|
|
127
|
-
"""Returns the string representation of the form's components."""
|
|
128
|
-
return self.components.__str__()
|
pygeoinf/symmetric_space/line.py
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Sobolev spaces for functions on a line.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from __future__ import annotations
|
|
6
|
-
from typing import Callable, Any, Tuple, Optional
|
|
7
|
-
import matplotlib.pyplot as plt
|
|
8
|
-
import numpy as np
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
from matplotlib.figure import Figure
|
|
12
|
-
from matplotlib.axes import Axes
|
|
13
|
-
from pygeoinf.operators import LinearOperator
|
|
14
|
-
from pygeoinf.forms import LinearForm
|
|
15
|
-
from pygeoinf.gaussian_measure import GaussianMeasure
|
|
16
|
-
|
|
17
|
-
from pygeoinf.operators import LinearOperator
|
|
18
|
-
from pygeoinf.gaussian_measure import GaussianMeasure
|
|
19
|
-
from pygeoinf.symmetric_space.symmetric_space import SymmetricSpaceSobolev
|
|
20
|
-
from pygeoinf.symmetric_space.circle import Sobolev as CircleSobolev
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class Sobolev(SymmetricSpaceSobolev):
|
|
24
|
-
"""
|
|
25
|
-
Implementation of the Sobolev space H^s on a finite line interval.
|
|
26
|
-
|
|
27
|
-
This class models functions on an interval [x0, x1] by mapping the problem
|
|
28
|
-
to a periodic domain (a circle) with padding. This avoids explicit
|
|
29
|
-
boundary conditions by using smooth tapers.
|
|
30
|
-
"""
|
|
31
|
-
|
|
32
|
-
def __init__(
|
|
33
|
-
self,
|
|
34
|
-
kmax: int,
|
|
35
|
-
order: float,
|
|
36
|
-
scale: float,
|
|
37
|
-
/,
|
|
38
|
-
*,
|
|
39
|
-
x0: float = 0.0,
|
|
40
|
-
x1: float = 1.0,
|
|
41
|
-
) -> None:
|
|
42
|
-
"""
|
|
43
|
-
Args:
|
|
44
|
-
kmax: The maximum Fourier degree for the underlying circle representation.
|
|
45
|
-
order: The Sobolev order, controlling function smoothness.
|
|
46
|
-
scale: The Sobolev length-scale.
|
|
47
|
-
x0: The left boundary of the interval. Defaults to 0.0.
|
|
48
|
-
x1: The right boundary of the interval. Defaults to 1.0.
|
|
49
|
-
|
|
50
|
-
Raises:
|
|
51
|
-
ValueError: If `x0 >= x1` or if `scale <= 0` when `order` is non-zero.
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
if x0 >= x1:
|
|
55
|
-
raise ValueError("Invalid interval parameters: x0 must be less than x1.")
|
|
56
|
-
if order != 0 and scale <= 0:
|
|
57
|
-
raise ValueError("Length-scale must be positive for non-L2 spaces.")
|
|
58
|
-
|
|
59
|
-
self._kmax: int = kmax
|
|
60
|
-
self._x0: float = x0
|
|
61
|
-
self._x1: float = x1
|
|
62
|
-
|
|
63
|
-
# Work out the padding.
|
|
64
|
-
padding_scale: float = 5 * scale if scale > 0 else 0.1 * (x1 - x0)
|
|
65
|
-
number_of_points: int = 2 * kmax
|
|
66
|
-
width: float = x1 - x0
|
|
67
|
-
self._start_index: int = int(
|
|
68
|
-
number_of_points * padding_scale / (width + 2 * padding_scale)
|
|
69
|
-
)
|
|
70
|
-
self._finish_index: int = 2 * kmax - self._start_index + 1
|
|
71
|
-
self._padding_length: float = (
|
|
72
|
-
self._start_index * width / (number_of_points - 2 * self._start_index)
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
self._jac: float = (width + 2 * self._padding_length) / (2 * np.pi)
|
|
76
|
-
self._ijac: float = 1.0 / self._jac
|
|
77
|
-
self._sqrt_jac: float = np.sqrt(self._jac)
|
|
78
|
-
self._isqrt_jac: float = 1.0 / self._sqrt_jac
|
|
79
|
-
|
|
80
|
-
# Set up the related Sobolev space on the unit circle.
|
|
81
|
-
circle_scale: float = scale * self._ijac
|
|
82
|
-
self._circle_space: CircleSobolev = CircleSobolev(kmax, order, circle_scale)
|
|
83
|
-
|
|
84
|
-
super().__init__(
|
|
85
|
-
order,
|
|
86
|
-
scale,
|
|
87
|
-
self._circle_space.dim,
|
|
88
|
-
self._to_components,
|
|
89
|
-
self._from_components,
|
|
90
|
-
self._inner_product,
|
|
91
|
-
self._to_dual,
|
|
92
|
-
self._from_dual,
|
|
93
|
-
vector_multiply=lambda u1, u2: u1 * u2,
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
@staticmethod
|
|
97
|
-
def from_sobolev_parameters(
|
|
98
|
-
order: float,
|
|
99
|
-
scale: float,
|
|
100
|
-
/,
|
|
101
|
-
*,
|
|
102
|
-
x0: float = 0.0,
|
|
103
|
-
x1: float = 1.0,
|
|
104
|
-
rtol: float = 1e-8,
|
|
105
|
-
power_of_two: bool = False,
|
|
106
|
-
) -> "Sobolev":
|
|
107
|
-
"""
|
|
108
|
-
Creates an instance with `kmax` selected based on the Sobolev parameters.
|
|
109
|
-
|
|
110
|
-
Args:
|
|
111
|
-
order: The Sobolev order.
|
|
112
|
-
scale: The Sobolev length-scale.
|
|
113
|
-
x0: The left boundary of the interval. Defaults to 0.0.
|
|
114
|
-
x1: The right boundary of the interval. Defaults to 1.0.
|
|
115
|
-
rtol: Relative tolerance for truncation error assessment.
|
|
116
|
-
power_of_two: If True, `kmax` is set to the next power of two.
|
|
117
|
-
|
|
118
|
-
Returns:
|
|
119
|
-
An instance of the Sobolev class with an appropriate `kmax`.
|
|
120
|
-
"""
|
|
121
|
-
if x0 >= x1:
|
|
122
|
-
raise ValueError("Invalid interval parameters")
|
|
123
|
-
|
|
124
|
-
circle_scale = scale / (x1 - x0)
|
|
125
|
-
circle_space = CircleSobolev.from_sobolev_parameters(
|
|
126
|
-
order, circle_scale, rtol=rtol, power_of_two=power_of_two
|
|
127
|
-
)
|
|
128
|
-
kmax = circle_space.kmax
|
|
129
|
-
return Sobolev(kmax, order, scale, x0=x0, x1=x1)
|
|
130
|
-
|
|
131
|
-
@property
|
|
132
|
-
def kmax(self) -> int:
|
|
133
|
-
"""The maximum Fourier degree of the underlying circle representation."""
|
|
134
|
-
return self._kmax
|
|
135
|
-
|
|
136
|
-
@property
|
|
137
|
-
def x0(self) -> float:
|
|
138
|
-
"""The left boundary point of the interval."""
|
|
139
|
-
return self._x0
|
|
140
|
-
|
|
141
|
-
@property
|
|
142
|
-
def x1(self) -> float:
|
|
143
|
-
"""The right boundary point of the interval."""
|
|
144
|
-
return self._x1
|
|
145
|
-
|
|
146
|
-
@property
|
|
147
|
-
def width(self) -> float:
|
|
148
|
-
"""The width of the interval, `x1 - x0`."""
|
|
149
|
-
return self._x1 - self._x0
|
|
150
|
-
|
|
151
|
-
@property
|
|
152
|
-
def point_spacing(self) -> float:
|
|
153
|
-
"""The spacing between grid points on the interval."""
|
|
154
|
-
return self._circle_space.angle_spacing * self._jac
|
|
155
|
-
|
|
156
|
-
def computational_points(self) -> np.ndarray:
|
|
157
|
-
"""Returns the grid points on the full computational domain, including padding."""
|
|
158
|
-
return self._x0 - self._padding_length + self._jac * self._circle_space.angles()
|
|
159
|
-
|
|
160
|
-
def points(self) -> np.ndarray:
|
|
161
|
-
"""Returns the grid points within the primary interval `[x0, x1]`."""
|
|
162
|
-
return self.computational_points()[self._start_index : self._finish_index]
|
|
163
|
-
|
|
164
|
-
def project_function(self, f: Callable[[float], float]) -> np.ndarray:
|
|
165
|
-
"""
|
|
166
|
-
Returns an element of the space by projecting a given function.
|
|
167
|
-
|
|
168
|
-
The function `f` is evaluated at the computational grid points and
|
|
169
|
-
multiplied by a smooth tapering function.
|
|
170
|
-
|
|
171
|
-
Args:
|
|
172
|
-
f: A function that takes a position `x` and returns a value.
|
|
173
|
-
"""
|
|
174
|
-
return np.fromiter(
|
|
175
|
-
(f(x) * self._taper(x) for x in self.computational_points()), float
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
def random_point(self) -> float:
|
|
179
|
-
"""Returns a random point within the interval `[x0, x1]`."""
|
|
180
|
-
return np.random.uniform(self._x0, self._x1)
|
|
181
|
-
|
|
182
|
-
def plot(
|
|
183
|
-
self,
|
|
184
|
-
u: np.ndarray,
|
|
185
|
-
fig: Optional[Figure] = None,
|
|
186
|
-
ax: Optional[Axes] = None,
|
|
187
|
-
/,
|
|
188
|
-
*,
|
|
189
|
-
computational_domain: bool = False,
|
|
190
|
-
**kwargs,
|
|
191
|
-
) -> Tuple[Figure, Axes]:
|
|
192
|
-
"""
|
|
193
|
-
Makes a simple plot of a function from the space.
|
|
194
|
-
|
|
195
|
-
Args:
|
|
196
|
-
u: The vector representing the function to be plotted.
|
|
197
|
-
fig: An existing Matplotlib Figure object. Defaults to None.
|
|
198
|
-
ax: An existing Matplotlib Axes object. Defaults to None.
|
|
199
|
-
computational_domain: If True, plot the whole computational
|
|
200
|
-
domain including the tapered padding. Defaults to False.
|
|
201
|
-
**kwargs: Keyword arguments forwarded to `ax.plot()`.
|
|
202
|
-
|
|
203
|
-
Returns:
|
|
204
|
-
A tuple (figure, axes) containing the plot objects.
|
|
205
|
-
"""
|
|
206
|
-
figsize = kwargs.pop("figsize", (10, 8))
|
|
207
|
-
|
|
208
|
-
if fig is None:
|
|
209
|
-
fig = plt.figure(figsize=figsize)
|
|
210
|
-
if ax is None:
|
|
211
|
-
ax = fig.add_subplot()
|
|
212
|
-
|
|
213
|
-
if computational_domain:
|
|
214
|
-
ax.plot(self.computational_points(), u, **kwargs)
|
|
215
|
-
else:
|
|
216
|
-
ax.plot(self.points(), u[self._start_index : self._finish_index], **kwargs)
|
|
217
|
-
|
|
218
|
-
return fig, ax
|
|
219
|
-
|
|
220
|
-
def plot_pointwise_bounds(
|
|
221
|
-
self,
|
|
222
|
-
u: np.ndarray,
|
|
223
|
-
u_bound: np.ndarray,
|
|
224
|
-
fig: Optional[Figure] = None,
|
|
225
|
-
ax: Optional[Axes] = None,
|
|
226
|
-
/,
|
|
227
|
-
*,
|
|
228
|
-
computational_domain: bool = False,
|
|
229
|
-
**kwargs,
|
|
230
|
-
) -> Tuple[Figure, Axes]:
|
|
231
|
-
"""
|
|
232
|
-
Plots a function with pointwise error bounds.
|
|
233
|
-
|
|
234
|
-
Args:
|
|
235
|
-
u: The vector representing the mean function.
|
|
236
|
-
u_bound: A vector giving pointwise standard deviations.
|
|
237
|
-
fig: An existing Matplotlib Figure object. Defaults to None.
|
|
238
|
-
ax: An existing Matplotlib Axes object. Defaults to None.
|
|
239
|
-
computational_domain: If True, plot the whole computational domain.
|
|
240
|
-
**kwargs: Keyword arguments forwarded to `ax.fill_between()`.
|
|
241
|
-
|
|
242
|
-
Returns:
|
|
243
|
-
A tuple (figure, axes) containing the plot objects.
|
|
244
|
-
"""
|
|
245
|
-
figsize = kwargs.pop("figsize", (10, 8))
|
|
246
|
-
|
|
247
|
-
if fig is None:
|
|
248
|
-
fig = plt.figure(figsize=figsize)
|
|
249
|
-
if ax is None:
|
|
250
|
-
ax = fig.add_subplot()
|
|
251
|
-
|
|
252
|
-
if computational_domain:
|
|
253
|
-
ax.fill_between(
|
|
254
|
-
self.computational_points(), u - u_bound, u + u_bound, **kwargs
|
|
255
|
-
)
|
|
256
|
-
else:
|
|
257
|
-
ax.fill_between(
|
|
258
|
-
self.points(),
|
|
259
|
-
u[self._start_index : self._finish_index]
|
|
260
|
-
- u_bound[self._start_index : self._finish_index],
|
|
261
|
-
u[self._start_index : self._finish_index]
|
|
262
|
-
+ u_bound[self._start_index : self._finish_index],
|
|
263
|
-
**kwargs,
|
|
264
|
-
)
|
|
265
|
-
|
|
266
|
-
return fig, ax
|
|
267
|
-
|
|
268
|
-
def invariant_automorphism(self, f: Callable[[float], float]) -> "LinearOperator":
|
|
269
|
-
A = self._circle_space.invariant_automorphism(lambda k: f(self._ijac * k))
|
|
270
|
-
return LinearOperator.formally_self_adjoint(self, A)
|
|
271
|
-
|
|
272
|
-
def invariant_gaussian_measure(
|
|
273
|
-
self, f: Callable[[float], float], /, *, expectation: Optional[Any] = None
|
|
274
|
-
) -> "GaussianMeasure":
|
|
275
|
-
mu = self._circle_space.invariant_gaussian_measure(
|
|
276
|
-
lambda k: f(self._ijac * k), expectation=expectation
|
|
277
|
-
)
|
|
278
|
-
covariance = LinearOperator.self_adjoint(self, mu.covariance)
|
|
279
|
-
return GaussianMeasure(
|
|
280
|
-
covariance=covariance, expectation=expectation, sample=mu.sample
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
def dirac(self, point: float) -> "LinearForm":
|
|
284
|
-
theta = self._inverse_transformation(point)
|
|
285
|
-
up = self._circle_space.dirac(theta)
|
|
286
|
-
cp = self._circle_space.dual.to_components(up) * self._isqrt_jac
|
|
287
|
-
return self.dual.from_components(cp)
|
|
288
|
-
|
|
289
|
-
def __eq__(self, other: object) -> bool:
|
|
290
|
-
"""
|
|
291
|
-
Checks for mathematical equality with another Sobolev space on a line.
|
|
292
|
-
|
|
293
|
-
Two spaces are considered equal if they are of the same type and have
|
|
294
|
-
the same defining parameters (kmax, order, scale, x0, and x1).
|
|
295
|
-
"""
|
|
296
|
-
|
|
297
|
-
if not isinstance(other, Sobolev):
|
|
298
|
-
return NotImplemented
|
|
299
|
-
|
|
300
|
-
return (
|
|
301
|
-
self.kmax == other.kmax
|
|
302
|
-
and self.order == other.order
|
|
303
|
-
and self.scale == other.scale
|
|
304
|
-
and self.x0 == other.x0
|
|
305
|
-
and self.x1 == other.x1
|
|
306
|
-
)
|
|
307
|
-
|
|
308
|
-
# =============================================================#
|
|
309
|
-
# Private methods #
|
|
310
|
-
# =============================================================#
|
|
311
|
-
|
|
312
|
-
def _step(self, x: float) -> float:
|
|
313
|
-
if x > 0:
|
|
314
|
-
return np.exp(-1.0 / x)
|
|
315
|
-
else:
|
|
316
|
-
return 0.0
|
|
317
|
-
|
|
318
|
-
def _bump_up(self, x: float, x1: float, x2: float) -> float:
|
|
319
|
-
s1 = self._step(x - x1)
|
|
320
|
-
s2 = self._step(x2 - x)
|
|
321
|
-
return s1 / (s1 + s2)
|
|
322
|
-
|
|
323
|
-
def _bump_down(self, x: float, x1: float, x2: float) -> float:
|
|
324
|
-
s1 = self._step(x2 - x)
|
|
325
|
-
s2 = self._step(x - x1)
|
|
326
|
-
return s1 / (s1 + s2)
|
|
327
|
-
|
|
328
|
-
def _taper(self, x: float) -> float:
|
|
329
|
-
s1 = self._bump_up(x, self._x0 - self._padding_length, self._x0)
|
|
330
|
-
s2 = self._bump_down(x, self._x1, self._x1 + self._padding_length)
|
|
331
|
-
return s1 * s2
|
|
332
|
-
|
|
333
|
-
def _transformation(self, th: float) -> float:
|
|
334
|
-
return self._x0 - self._padding_length + self._jac * th
|
|
335
|
-
|
|
336
|
-
def _inverse_transformation(self, x: float) -> float:
|
|
337
|
-
return (x - self._x0 + self._padding_length) * self._ijac
|
|
338
|
-
|
|
339
|
-
def _to_components(self, u: np.ndarray) -> np.ndarray:
|
|
340
|
-
c = self._circle_space.to_components(u)
|
|
341
|
-
c *= self._sqrt_jac
|
|
342
|
-
return c
|
|
343
|
-
|
|
344
|
-
def _from_components(self, c: np.ndarray) -> np.ndarray:
|
|
345
|
-
u = self._circle_space.from_components(c)
|
|
346
|
-
u *= self._isqrt_jac
|
|
347
|
-
return u
|
|
348
|
-
|
|
349
|
-
def _inner_product(self, u1: np.ndarray, u2: np.ndarray) -> float:
|
|
350
|
-
return self._jac * self._circle_space.inner_product(u1, u2)
|
|
351
|
-
|
|
352
|
-
def _to_dual(self, u: np.ndarray) -> "LinearForm":
|
|
353
|
-
up = self._circle_space.to_dual(u)
|
|
354
|
-
cp = self._circle_space.dual.to_components(up) * self._sqrt_jac
|
|
355
|
-
return self.dual.from_components(cp)
|
|
356
|
-
|
|
357
|
-
def _from_dual(self, up: "LinearForm") -> np.ndarray:
|
|
358
|
-
cp = self.dual.to_components(up)
|
|
359
|
-
vp = self._circle_space.dual.from_components(cp) * self._isqrt_jac
|
|
360
|
-
return self._circle_space.from_dual(vp)
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
class Lebesgue(Sobolev):
|
|
364
|
-
"""
|
|
365
|
-
Implementation of the Lebesgue space L^2 on a line.
|
|
366
|
-
|
|
367
|
-
This is a special case of the Sobolev space with order `s=0`.
|
|
368
|
-
"""
|
|
369
|
-
|
|
370
|
-
def __init__(
|
|
371
|
-
self,
|
|
372
|
-
kmax: int,
|
|
373
|
-
/,
|
|
374
|
-
*,
|
|
375
|
-
x0: float = 0.0,
|
|
376
|
-
x1: float = 1.0,
|
|
377
|
-
) -> None:
|
|
378
|
-
"""
|
|
379
|
-
Args:
|
|
380
|
-
kmax: The maximum Fourier degree for the underlying representation.
|
|
381
|
-
x0: The left boundary of the interval. Defaults to 0.0.
|
|
382
|
-
x1: The right boundary of the interval. Defaults to 1.0.
|
|
383
|
-
"""
|
|
384
|
-
super().__init__(kmax, 0.0, 1.0, x0=x0, x1=x1)
|
pygeoinf-1.0.9.dist-info/RECORD
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
pygeoinf/__init__.py,sha256=PsUfD2hfc-eoIz6fHSC-Mn3MHflaU07W2mHT6fLYKr0,1076
|
|
2
|
-
pygeoinf/direct_sum.py,sha256=jgG1BTDfoU7rg_YYBKWZU08Ugj9Vfo7PaDuF3XXIcOo,15706
|
|
3
|
-
pygeoinf/forms.py,sha256=ddgXrRmM3CCBWjSE2RQUFbIlEiBCAlnVVIRwnQ50TaA,4362
|
|
4
|
-
pygeoinf/forward_problem.py,sha256=4V40qvHN4qAu8CXsxGAuJ5F9oukqXbXbGCARFpBYaD0,9546
|
|
5
|
-
pygeoinf/gaussian_measure.py,sha256=UEFViRtLYU730U4upV33KB_ksg78tpW0dwGVFgt1hOw,21595
|
|
6
|
-
pygeoinf/hilbert_space.py,sha256=m0wbzm2XIITs8KenwrNrgvRKilsf-KrX6SR0ylKyhLg,14342
|
|
7
|
-
pygeoinf/inversion.py,sha256=0O1ZVZSyvHaS63XovMtAmhwQwnl0OBfiSD9JwEt95bg,2560
|
|
8
|
-
pygeoinf/linear_bayesian.py,sha256=9PQWq3nzNN2KR5fDbDqE8rv0mszIe53_7M40jeD_26U,8374
|
|
9
|
-
pygeoinf/linear_optimisation.py,sha256=C2kA1QZC4BlSF0txfpr2_c3A2lCAIklijqY8sgs5OZE,10316
|
|
10
|
-
pygeoinf/linear_solvers.py,sha256=ieRscHbI7On_4E0h_U-CAKOGlMYKwB2W-dR-Gh4Iwp4,17481
|
|
11
|
-
pygeoinf/operators.py,sha256=SZRmzUL6KiJA1fh5PoWqLwyDYWDo5ooJ_CbMD3TCvFA,24912
|
|
12
|
-
pygeoinf/random_matrix.py,sha256=d6apC9Sd5ud-QgLnvvXaURdar3LiYJPwz-CYbDojH54,7545
|
|
13
|
-
pygeoinf/symmetric_space/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
pygeoinf/symmetric_space/circle.py,sha256=TWjQwX42EvZ4-zOIJKATo8lVg0YbXRaQgxVzj6xXYlM,12467
|
|
15
|
-
pygeoinf/symmetric_space/line.py,sha256=FoZL5qVEVWzOkWwhbmwsg3D_0ceX9Nj8L8OJXQevtr4,13203
|
|
16
|
-
pygeoinf/symmetric_space/sphere.py,sha256=re-TjugmBABcBpR5LEMhSCxJn0T_h3TRm4tjyGGwTyE,24664
|
|
17
|
-
pygeoinf/symmetric_space/symmetric_space.py,sha256=E-8lXZmW5WWaHgX-YTu--NwV6dXP3M7hIP3J3H6uv3U,9067
|
|
18
|
-
pygeoinf-1.0.9.dist-info/LICENSE,sha256=GrTQnKJemVi69FSbHprq60KN0OJGsOSR-joQoTq-oD8,1501
|
|
19
|
-
pygeoinf-1.0.9.dist-info/METADATA,sha256=HkPhf8yGiBK2x6bjYgATq-6rr8Y7oVxib31fBqcz_Po,14416
|
|
20
|
-
pygeoinf-1.0.9.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
21
|
-
pygeoinf-1.0.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|