Repository URL to install this package:
|
Version:
5.0.3.post1 ▾
|
import numpy as np
__all__ = ["Wiener"]
class Wiener:
"""
Wiener process.
"""
def __init__(self, t0, dt, generator, shape):
self.t0 = t0
self.dt = dt
self.generator = generator
self.t_end = t0
self.shape = shape
self.process = np.zeros((1,) + shape, dtype=float)
def _extend(self, t):
N_new_vals = int((t - self.t_end + self.dt*0.01) // self.dt)
dW = self.generator.normal(
0, np.sqrt(self.dt), size=(N_new_vals,) + self.shape
)
W = self.process[-1, :, :] + np.cumsum(dW, axis=0)
self.process = np.concatenate((self.process, W), axis=0)
self.t_end = self.t0 + (self.process.shape[0] - 1) * self.dt
def dW(self, t, N):
if t + N * self.dt > self.t_end:
self._extend(t + N * self.dt)
idx0 = int((t - self.t0 + self.dt * 0.01) // self.dt)
return np.diff(self.process[idx0:idx0 + N + 1, :, :], axis=0)
def __call__(self, t):
if t > self.t_end:
self._extend(t)
idx = int((t - self.t0 + self.dt * 0.01) // self.dt)
return self.process[idx, 0, :]
class _Noise:
"""
Wiener process generator used for tests.
"""
def __init__(self, T, dt, num=1):
N = int(np.round(T / dt))
self.T = T
self.dt = dt
self.num = num
self.noise = np.random.randn(N, num) * dt**0.5
def dw(self, dt):
"""
Ito integral I(i).
"""
N = int(np.round(dt / self.dt))
return self.noise.reshape(-1, N, self.num).sum(axis=1)
def dz(self, dt):
"""
Ito integral I(0, i).
"""
N = int(np.round(dt / self.dt))
return (
np.einsum(
"ijk,j->ik",
self.noise.reshape(-1, N, self.num),
np.arange(N - 0.5, 0, -1),
)
* self.dt
)
def dW(self, dt):
"""
Noise used for Ito-Taylor integrators of order up to 1.5.
"""
N = int(np.round(dt / self.dt))
noise = self.noise.copy()
if noise.shape[0] % N:
noise = noise[: -(noise.shape[0] % N)]
out = np.empty((noise.shape[0] // N, 2, self.num), dtype=float)
out[:, 0, :] = noise.reshape(-1, N, self.num).sum(axis=1)
out[:, 1, :] = (
np.einsum(
"ijk,j->ik",
self.noise.reshape(-1, N, self.num),
np.arange(N - 0.5, 0, -1),
)
* self.dt
)
return out