Spaces:
Running
on
Zero
Running
on
Zero
| from typing import * | |
| import numpy as np | |
| __all__ = ['linear_spline_interpolate'] | |
| def linear_spline_interpolate(x: np.ndarray, t: np.ndarray, s: np.ndarray, extrapolation_mode: Literal['constant', 'linear'] = 'constant') -> np.ndarray: | |
| """ | |
| Linear spline interpolation. | |
| ### Parameters: | |
| - `x`: np.ndarray, shape (n, d): the values of data points. | |
| - `t`: np.ndarray, shape (n,): the times of the data points. | |
| - `s`: np.ndarray, shape (m,): the times to be interpolated. | |
| - `extrapolation_mode`: str, the mode of extrapolation. 'constant' means extrapolate the boundary values, 'linear' means extrapolate linearly. | |
| ### Returns: | |
| - `y`: np.ndarray, shape (..., m, d): the interpolated values. | |
| """ | |
| i = np.searchsorted(t, s, side='left') | |
| if extrapolation_mode == 'constant': | |
| prev = np.clip(i - 1, 0, len(t) - 1) | |
| suc = np.clip(i, 0, len(t) - 1) | |
| elif extrapolation_mode == 'linear': | |
| prev = np.clip(i - 1, 0, len(t) - 2) | |
| suc = np.clip(i, 1, len(t) - 1) | |
| else: | |
| raise ValueError(f'Invalid extrapolation_mode: {extrapolation_mode}') | |
| u = (s - t[prev]) / np.maximum(t[suc] - t[prev], 1e-12) | |
| y = u * x[suc] + (1 - u) * x[prev] | |
| return y | |
| def _solve_tridiagonal(a: np.ndarray, b: np.ndarray, c: np.ndarray, d: np.ndarray) -> np.ndarray: | |
| n = b.shape[-1] | |
| cc = np.zeros_like(b) | |
| dd = np.zeros_like(b) | |
| cc[..., 0] = c[..., 0] / b[..., 0] | |
| dd[..., 0] = d[..., 0] / b[..., 0] | |
| for i in range(1, n): | |
| cc[..., i] = c[..., i] / (b[..., i] - a[..., i - 1] * cc[..., i - 1]) | |
| dd[..., i] = (d[..., i] - a[..., i - 1] * dd[..., i - 1]) / (b[..., i] - a[..., i - 1] * cc[..., i - 1]) | |
| x = np.zeros_like(b) | |
| x[..., -1] = dd[..., -1] | |
| for i in range(n - 2, -1, -1): | |
| x[..., i] = dd[..., i] - cc[..., i] * x[..., i + 1] | |
| return x | |
| def cubic_spline_interpolate(x: np.ndarray, t: np.ndarray, s: np.ndarray, v0: np.ndarray = None, vn: np.ndarray = None) -> np.ndarray: | |
| """ | |
| Cubic spline interpolation. | |
| ### Parameters: | |
| - `x`: np.ndarray, shape (..., n,): the x-coordinates of the data points. | |
| - `t`: np.ndarray, shape (n,): the knot vector. NOTE: t must be sorted in ascending order. | |
| - `s`: np.ndarray, shape (..., m,): the y-coordinates of the data points. | |
| - `v0`: np.ndarray, shape (...,): the value of the derivative at the first knot, as the boundary condition. If None, it is set to zero. | |
| - `vn`: np.ndarray, shape (...,): the value of the derivative at the last knot, as the boundary condition. If None, it is set to zero. | |
| ### Returns: | |
| - `y`: np.ndarray, shape (..., m): the interpolated values. | |
| """ | |
| h = t[..., 1:] - t[..., :-1] | |
| mu = h[..., :-1] / (h[..., :-1] + h[..., 1:]) | |
| la = 1 - mu | |
| d = (x[..., 1:] - x[..., :-1]) / h | |
| d = 6 * (d[..., 1:] - d[..., :-1]) / (t[..., 2:] - t[..., :-2]) | |
| mu = np.concatenate([mu, np.ones_like(mu[..., :1])], axis=-1) | |
| la = np.concatenate([np.ones_like(la[..., :1]), la], axis=-1) | |
| d = np.concatenate([(((x[..., 1] - x[..., 0]) / h[0] - v0) / h[0])[..., None], d, ((vn - (x[..., -1] - x[..., -2]) / h[-1]) / h[-1])[..., None]], axis=-1) | |
| M = _solve_tridiagonal(mu, np.full_like(d, fill_value=2), la, d) | |
| i = np.searchsorted(t, s, side='left') | |