Invariant
Direct computation of invariant(s)
- ndmap.invariant.invariant(order: tuple[int, ...], state: torch.Tensor, knobs: list[torch.Tensor], observable: Callable, data: list, *, threshold: float = 1e-09, solve: Callable | None = None, jacobian: Callable | None = None) tuple[list, list] [source]
Compute Taylor invariant for a given derivative table
- Parameters:
order (tuple[int, ...]) – computation order
state (State) – state fixed point
knobs (Knobs) – knobs value
observable (Observable) – invariant guess
data (Table) – table mapping representation
threshold (float, default=1.0E-9) – threshold value
solve (Optional[Callable]) – linear solver(matrix, vecor)
jacobian (Optional[Callable]) – torch.func.jacfwd (default) or torch.func.jacrev
- Return type:
tuple[Table, list]
Examples
>>> import torch >>> from ndmap.util import nest >>> from ndmap.derivative import derivative >>> from ndmap.series import series >>> from ndmap.series import clean >>> from ndmap.yoshida import yoshida >>> def fn(x, t): q, p = x ; return torch.stack([q, p - t*q - t*q**2]) >>> def gn(x, t): q, p = x ; return torch.stack([q + t*p, p]) >>> l = torch.tensor(1.0, dtype=torch.float64) >>> x = torch.tensor([0.0, 0.0], dtype=torch.float64) >>> t = derivative(2, nest(100, lambda x: yoshida(0, 1, True, [fn, gn])(x, l/100)), x) >>> i, _ = invariant((3, ), x, [], lambda x: 1/2*(x**2).sum(), t, threshold=1.0E-6) >>> clean(series((2, ), (3, ), i)) {(2, 0): tensor([0.5000], dtype=torch.float64), (0, 2): tensor([0.5000], dtype=torch.float64), (3, 0): tensor([0.3333], dtype=torch.float64)}
>>> from ndmap.util import nest >>> from ndmap.derivative import derivative >>> from ndmap.series import series >>> from ndmap.series import clean >>> from ndmap.yoshida import yoshida >>> def fn(x, t, k): q, p = x ; k, = k ; return torch.stack([q, p - t*q - t*(1 + k)*q**2]) >>> def gn(x, t, k): q, p = x ; k, = k ; return torch.stack([q + t*p, p]) >>> l = torch.tensor(1.0, dtype=torch.float64) >>> x = torch.tensor([0.0, 0.0], dtype=torch.float64) >>> k = torch.tensor([0.0], dtype=torch.float64) >>> y = nest(100, lambda x, k: yoshida(0, 2, True, [fn, gn])(x, l/100, k)) >>> t = derivative((2, 1), y, x, k) >>> i, _ = invariant((3, 1), x, [k], lambda x, k: 1/2*(x**2).sum(), t, threshold=1.0E-6) >>> clean(series((2, 1), (3, 1), i)) {(2, 0, 0): tensor([0.5000], dtype=torch.float64), (0, 2, 0): tensor([0.5000], dtype=torch.float64), (3, 0, 0): tensor([0.3333], dtype=torch.float64), (3, 0, 1): tensor([0.3333], dtype=torch.float64)}
Note
Input table is assumed to be origin preserving Initial guess is required to avoid trivial solution