Download src/hamiltonzero/model/context.py from simulacra-research/HamiltonZero: direct link, hf CLI and curl.
- Browser
- Download file 13.8 kB
-
https://huggingface.co/simulacra-research/HamiltonZero/resolve/main/src/hamiltonzero/model/context.py
- Command line
-
hf download hf://simulacra-research/HamiltonZero/src/hamiltonzero/model/context.py
-
curl -L -o context.py https://huggingface.co/simulacra-research/HamiltonZero/resolve/main/src/hamiltonzero/model/context.py
13.8 kB
| # Copyright (c) 2026 Simulacra Research Inc. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| from __future__ import annotations | |
| import equinox as eqx | |
| import jax | |
| import jax.numpy as jnp | |
| import numpy as np | |
| from jaxtyping import Array, Float, Int | |
| def _balanced_mask(mask: Int[Array, "n"]) -> Int[Array, "n"]: | |
| width = int(mask.shape[-1]) | |
| n_real = jnp.sum(mask.astype(jnp.int32)) | |
| max_power = max(1, (width - 1).bit_length()) | |
| powers = 2 ** jnp.arange(max_power + 1, dtype=jnp.int32) | |
| sentinel = jnp.asarray(1 << 30, dtype=jnp.int32) | |
| next_power = jnp.min(jnp.where(powers >= jnp.maximum(n_real, 1), powers, sentinel)) | |
| return (jnp.arange(width, dtype=jnp.int32) < next_power).astype(jnp.int32) | |
| _EPS_ABC = jnp.asarray( | |
| [ | |
| [[0.0, 0.0, 0.0], [0.0, 0.0, 1.0], [0.0, -1.0, 0.0]], | |
| [[0.0, 0.0, -1.0], [0.0, 0.0, 0.0], [1.0, 0.0, 0.0]], | |
| [[0.0, 1.0, 0.0], [-1.0, 0.0, 0.0], [0.0, 0.0, 0.0]], | |
| ], | |
| dtype=jnp.float32, | |
| ) | |
| def _real_dtype(dtype): | |
| return jnp.real(jnp.zeros((), dtype)).dtype | |
| def _host_eigvalsh(x): | |
| out_dtype = _real_dtype(x.dtype) | |
| out_shape = jax.ShapeDtypeStruct(x.shape[:-1], out_dtype) | |
| def callback(a): | |
| values = np.linalg.eigvalsh(np.asarray(a)) | |
| return values.astype(np.dtype(out_dtype)) | |
| return jax.pure_callback( | |
| callback, | |
| out_shape, | |
| x, | |
| vmap_method="sequential", | |
| ) | |
| def _compute_J_double_prime_batched( | |
| J_full: Float[Array, "s n n 3 3"], | |
| h: Float[Array, "s n 3"], | |
| mask: Int[Array, "s n"], | |
| ) -> tuple[Float[Array, "s n n 10"], Float[Array, "s"]]: | |
| n = J_full.shape[1] | |
| n_systems = J_full.shape[0] | |
| dtype = J_full.dtype | |
| J_filled = (J_full + jnp.conj(jnp.transpose(J_full, (0, 2, 1, 4, 3)))) / 2.0 | |
| eps_abc = _EPS_ABC.astype(_real_dtype(dtype)) | |
| M_h = jnp.einsum("abc,sic->siab", eps_abc, h.astype(eps_abc.dtype)) * 0.5 | |
| M_h = M_h * mask.astype(M_h.dtype)[:, :, None, None] | |
| diagonal = jnp.arange(n) | |
| complex_dtype = jnp.result_type(J_filled.dtype, jnp.complex64) | |
| M_h_diagonal = ( | |
| jnp.zeros(J_filled.shape, dtype=complex_dtype) | |
| .at[:, diagonal, diagonal] | |
| .set((2j * M_h).astype(complex_dtype)) | |
| ) | |
| J_for_norm = J_filled.astype(complex_dtype) + M_h_diagonal | |
| J_matrix = jnp.transpose(J_for_norm, (0, 1, 3, 2, 4)).reshape( | |
| n_systems, 3 * n, 3 * n | |
| ) | |
| eigh_epsilon = jnp.asarray(1e-6, dtype=_real_dtype(J_matrix.dtype)) | |
| eye_3n = jnp.eye(3 * n, dtype=J_matrix.dtype) | |
| eigenvalues = _host_eigvalsh(J_matrix + eigh_epsilon * eye_3n[None]) - eigh_epsilon | |
| s_norm = jnp.maximum( | |
| jnp.max(jnp.abs(eigenvalues), axis=-1), | |
| jnp.asarray(1e-12, eigenvalues.dtype), | |
| ).astype(dtype) | |
| J_normalized = J_filled / s_norm[:, None, None, None, None] | |
| J_normalized = J_normalized.at[:, diagonal, diagonal, :, :].set(0.0) | |
| J_flat = jnp.real(J_normalized).reshape(n_systems, n, n, 9).astype(dtype) | |
| identity_column = jnp.broadcast_to( | |
| jnp.eye(n, dtype=dtype)[None, ..., None], | |
| (n_systems, n, n, 1), | |
| ) | |
| return jnp.concatenate([J_flat, identity_column], axis=-1), s_norm | |
| def _compute_J_double_prime( | |
| J_full: Float[Array, "n n 3 3"], | |
| h: Float[Array, "n 3"], | |
| mask: Int[Array, "n"], | |
| ) -> tuple[Float[Array, "n n 10"], Float[Array, ""]]: | |
| J_double_prime, s_norm = _compute_J_double_prime_batched( | |
| J_full[None], h[None], mask[None] | |
| ) | |
| return J_double_prime[0], s_norm[0] | |
| class SpinContext(eqx.Module): | |
| mask: Int[Array, "n"] | |
| bmask: Int[Array, "n"] | |
| J_double_prime: Float[Array, "n n 10"] | |
| s_norm: Float[Array, ""] | |
| h_prime: Float[Array, "n 3"] | |
| route_quotient_node_key: Int[Array, "n"] | |
| route_quotient_edge_key: Int[Array, "n n"] | |
| needs_fwl2: Array | |
| route_perm: Int[Array, "n"] | |
| def __init__( | |
| self, | |
| J_full: Float[Array, "n n 3 3"], | |
| h: Float[Array, "n 3"], | |
| mask: Int[Array, "n"], | |
| *, | |
| needs_fwl2: Array | bool, | |
| ) -> None: | |
| from .route_quotient import route_quotient_keys | |
| self.mask = mask.astype(jnp.int32) | |
| self.bmask = _balanced_mask(self.mask) | |
| self.J_double_prime, self.s_norm = _compute_J_double_prime(J_full, h, self.mask) | |
| self.h_prime = h / jnp.real(self.s_norm).astype(h.dtype) | |
| ( | |
| self.route_quotient_node_key, | |
| self.route_quotient_edge_key, | |
| ) = route_quotient_keys(J_full, h, self.mask, self.bmask) | |
| self.needs_fwl2 = jnp.asarray(needs_fwl2, dtype=jnp.bool_) | |
| self.route_perm = jnp.arange(self.mask.shape[0], dtype=jnp.int32) | |
| def from_precomputed( | |
| cls, | |
| *, | |
| mask, | |
| bmask, | |
| J_double_prime, | |
| s_norm, | |
| h_prime, | |
| route_quotient_node_key, | |
| route_quotient_edge_key, | |
| needs_fwl2, | |
| route_perm, | |
| ) -> "SpinContext": | |
| self = object.__new__(cls) | |
| fields = { | |
| "mask": mask, | |
| "bmask": bmask, | |
| "J_double_prime": J_double_prime, | |
| "s_norm": s_norm, | |
| "h_prime": h_prime, | |
| "route_quotient_node_key": route_quotient_node_key, | |
| "route_quotient_edge_key": route_quotient_edge_key, | |
| "needs_fwl2": needs_fwl2, | |
| "route_perm": route_perm, | |
| } | |
| for name, value in fields.items(): | |
| dtype = ( | |
| jnp.bool_ | |
| if name == "needs_fwl2" | |
| else jnp.int32 | |
| if name | |
| in { | |
| "mask", | |
| "bmask", | |
| "route_quotient_node_key", | |
| "route_quotient_edge_key", | |
| "route_perm", | |
| } | |
| else None | |
| ) | |
| object.__setattr__(self, name, jnp.asarray(value, dtype=dtype)) | |
| return self | |
| def n_sites(self) -> int: | |
| return int(self.mask.shape[0]) | |
| class MultiSystemContext(eqx.Module): | |
| mask: Int[Array, "s n"] | |
| bmask: Int[Array, "s n"] | |
| J_double_prime: Float[Array, "s n n 10"] | |
| s_norm: Float[Array, "s"] | |
| h_prime: Float[Array, "s n 3"] | |
| route_quotient_node_key: Int[Array, "s n"] | |
| route_quotient_edge_key: Int[Array, "s n n"] | |
| needs_fwl2: Array | |
| route_perm: Int[Array, "s n"] | |
| def __init__( | |
| self, | |
| J_full: Float[Array, "s n n 3 3"], | |
| h: Float[Array, "s n 3"], | |
| mask: Int[Array, "s n"], | |
| *, | |
| needs_fwl2: Array | bool, | |
| ) -> None: | |
| from .route_quotient import route_quotient_keys | |
| self.mask = mask.astype(jnp.int32) | |
| self.bmask = jax.vmap(_balanced_mask)(self.mask) | |
| self.J_double_prime, self.s_norm = _compute_J_double_prime_batched( | |
| J_full, h, self.mask | |
| ) | |
| self.h_prime = h / jnp.real(self.s_norm).astype(h.dtype)[:, None, None] | |
| n_systems = self.mask.shape[0] | |
| ( | |
| self.route_quotient_node_key, | |
| self.route_quotient_edge_key, | |
| ) = jax.jit(jax.vmap(route_quotient_keys))(J_full, h, self.mask, self.bmask) | |
| self.needs_fwl2 = jnp.broadcast_to( | |
| jnp.asarray(needs_fwl2, dtype=jnp.bool_), | |
| (n_systems,), | |
| ) | |
| self.route_perm = jnp.broadcast_to( | |
| jnp.arange(self.mask.shape[1], dtype=jnp.int32)[None, :], | |
| self.mask.shape, | |
| ) | |
| def from_precomputed( | |
| cls, | |
| *, | |
| mask, | |
| bmask, | |
| J_double_prime, | |
| s_norm, | |
| h_prime, | |
| route_quotient_node_key, | |
| route_quotient_edge_key, | |
| needs_fwl2, | |
| route_perm, | |
| ) -> "MultiSystemContext": | |
| self = object.__new__(cls) | |
| fields = { | |
| "mask": mask, | |
| "bmask": bmask, | |
| "J_double_prime": J_double_prime, | |
| "s_norm": s_norm, | |
| "h_prime": h_prime, | |
| "route_quotient_node_key": route_quotient_node_key, | |
| "route_quotient_edge_key": route_quotient_edge_key, | |
| "needs_fwl2": needs_fwl2, | |
| "route_perm": route_perm, | |
| } | |
| for name, value in fields.items(): | |
| dtype = ( | |
| jnp.bool_ | |
| if name == "needs_fwl2" | |
| else jnp.int32 | |
| if name | |
| in { | |
| "mask", | |
| "bmask", | |
| "route_quotient_node_key", | |
| "route_quotient_edge_key", | |
| "route_perm", | |
| } | |
| else None | |
| ) | |
| object.__setattr__(self, name, jnp.asarray(value, dtype=dtype)) | |
| return self | |
| def from_single(cls, context: SpinContext) -> "MultiSystemContext": | |
| return cls.from_precomputed( | |
| mask=context.mask[None], | |
| bmask=context.bmask[None], | |
| J_double_prime=context.J_double_prime[None], | |
| s_norm=context.s_norm[None], | |
| h_prime=context.h_prime[None], | |
| route_quotient_node_key=context.route_quotient_node_key[None], | |
| route_quotient_edge_key=context.route_quotient_edge_key[None], | |
| needs_fwl2=context.needs_fwl2[None], | |
| route_perm=context.route_perm[None], | |
| ) | |
| def stack(cls, contexts: list[SpinContext]) -> "MultiSystemContext": | |
| if not contexts: | |
| raise ValueError("MultiSystemContext.stack requires a context") | |
| widths = [int(context.mask.shape[0]) for context in contexts] | |
| n_max = max(widths) | |
| def pad_sites(value, n): | |
| return ( | |
| value | |
| if n == n_max | |
| else jnp.pad(value, ((0, n_max - n),) + ((0, 0),) * (value.ndim - 1)) | |
| ) | |
| def pad_pairs(value, n): | |
| padding = n_max - n | |
| return ( | |
| value | |
| if padding == 0 | |
| else jnp.pad( | |
| value, | |
| ((0, padding), (0, padding)) + ((0, 0),) * (value.ndim - 2), | |
| ) | |
| ) | |
| mask = jnp.stack( | |
| [ | |
| pad_sites(context.mask, width) | |
| for context, width in zip(contexts, widths, strict=True) | |
| ] | |
| ) | |
| bmask = jax.vmap(_balanced_mask)(mask) | |
| J_double_prime = jnp.stack( | |
| [ | |
| pad_pairs(context.J_double_prime, width) | |
| for context, width in zip(contexts, widths, strict=True) | |
| ] | |
| ) | |
| diagonal = jnp.arange(n_max, dtype=jnp.int32) | |
| J_double_prime = J_double_prime.at[:, diagonal, diagonal, 9].set(1.0) | |
| s_norm = jnp.stack([context.s_norm for context in contexts]) | |
| h_prime = jnp.stack( | |
| [ | |
| pad_sites(context.h_prime, width) | |
| for context, width in zip(contexts, widths, strict=True) | |
| ] | |
| ) | |
| edge_shapes = { | |
| tuple(context.route_quotient_edge_key.shape) for context in contexts | |
| } | |
| compact_edges = all(shape == (0, 0) for shape in edge_shapes) | |
| full_edges = all( | |
| shape == (width, width) | |
| for shape, width in zip( | |
| [context.route_quotient_edge_key.shape for context in contexts], | |
| widths, | |
| strict=True, | |
| ) | |
| ) | |
| if not (compact_edges or full_edges): | |
| raise ValueError("cannot stack mixed quotient edge carriers") | |
| route_edge = ( | |
| jnp.zeros((len(contexts), 0, 0), dtype=jnp.int32) | |
| if compact_edges | |
| else jnp.stack( | |
| [ | |
| pad_pairs(context.route_quotient_edge_key, width) | |
| for context, width in zip(contexts, widths, strict=True) | |
| ] | |
| ) | |
| ) | |
| def pad_node_key(value, n): | |
| padding = n_max - n | |
| return ( | |
| value | |
| if padding == 0 | |
| else jnp.pad(value, ((0, padding),), constant_values=-1) | |
| ) | |
| def pad_perm(value, n): | |
| if n == n_max: | |
| return value | |
| return jnp.concatenate([value, jnp.arange(n, n_max, dtype=value.dtype)]) | |
| return cls.from_precomputed( | |
| mask=mask, | |
| bmask=bmask, | |
| J_double_prime=J_double_prime, | |
| s_norm=s_norm, | |
| h_prime=h_prime, | |
| route_quotient_node_key=jnp.stack( | |
| [ | |
| pad_node_key(context.route_quotient_node_key, width) | |
| for context, width in zip(contexts, widths, strict=True) | |
| ] | |
| ), | |
| route_quotient_edge_key=route_edge, | |
| needs_fwl2=jnp.stack([context.needs_fwl2 for context in contexts]), | |
| route_perm=jnp.stack( | |
| [ | |
| pad_perm(context.route_perm, width) | |
| for context, width in zip(contexts, widths, strict=True) | |
| ] | |
| ), | |
| ) | |
| def select(self, system_id: int) -> SpinContext: | |
| return SpinContext.from_precomputed( | |
| mask=self.mask[system_id], | |
| bmask=self.bmask[system_id], | |
| J_double_prime=self.J_double_prime[system_id], | |
| s_norm=self.s_norm[system_id], | |
| h_prime=self.h_prime[system_id], | |
| route_quotient_node_key=self.route_quotient_node_key[system_id], | |
| route_quotient_edge_key=self.route_quotient_edge_key[system_id], | |
| needs_fwl2=self.needs_fwl2[system_id], | |
| route_perm=self.route_perm[system_id], | |
| ) | |
| def n_systems(self) -> int: | |
| return int(self.mask.shape[0]) | |
| def n_sites(self) -> int: | |
| return int(self.mask.shape[1]) | |
| __all__ = [ | |
| "MultiSystemContext", | |
| "SpinContext", | |
| ] | |