HamiltonZero / src /hamiltonzero /router /permutation.py
Aleksei Ustimenko
Initial HamiltonZero release
5ccb4fd
Raw
History Blame Contribute Delete
2.16 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
from jaxtyping import Array, Float, Int
from hamiltonzero.model.context import MultiSystemContext, SpinContext
def permute_ctx_prefix(ctx: SpinContext, perm: Int[Array, "n"]) -> SpinContext:
return eqx.tree_at(
lambda c: (
c.h_prime,
c.J_double_prime,
c.mask,
c.route_quotient_node_key,
c.route_quotient_edge_key,
),
ctx,
(
ctx.h_prime[perm],
ctx.J_double_prime[perm][:, perm, :],
ctx.mask[perm],
ctx.route_quotient_node_key[perm],
(
ctx.route_quotient_edge_key
if ctx.route_quotient_edge_key.shape[-1] == 0
else ctx.route_quotient_edge_key[perm][:, perm]
),
),
)
def permute_multi_ctx_prefix(
ctx: MultiSystemContext,
perms: Int[Array, "s n"],
) -> MultiSystemContext:
return eqx.tree_at(
lambda c: (
c.h_prime,
c.J_double_prime,
c.mask,
c.route_quotient_node_key,
c.route_quotient_edge_key,
),
ctx,
(
jax.vmap(lambda x, p: x[p])(ctx.h_prime, perms),
jax.vmap(lambda x, p: x[p][:, p, :])(ctx.J_double_prime, perms),
jax.vmap(lambda x, p: x[p])(ctx.mask, perms),
jax.vmap(lambda x, p: x[p])(ctx.route_quotient_node_key, perms),
(
ctx.route_quotient_edge_key
if ctx.route_quotient_edge_key.shape[-1] == 0
else jax.vmap(lambda x, p: x[p][:, p])(
ctx.route_quotient_edge_key, perms
)
),
),
)
def permute_q_prefix(q: Float[Array, "s b r n d"], perms: Int[Array, "s n"]):
idx = jnp.broadcast_to(perms[:, None, None, :, None], q.shape)
return jnp.take_along_axis(q, idx, axis=3)
__all__ = [
"permute_ctx_prefix",
"permute_multi_ctx_prefix",
"permute_q_prefix",
]