StatefulMapping#

class brainstate.transform.StatefulMapping(fun, in_axes=0, out_axes=0, state_in_axes=None, state_out_axes=None, unexpected_out_state_mapping='auto', static_argnums=(), static_argnames=(), axis_env=None, return_only_write=True, axis_size=None, axis_name=None, name=None, mapping_fn=<function vmap>, mapping_kwargs=None)#

State-aware mapping wrapper built on the shared brainstate.transform mapping engine.

StatefulMapping augments a JAX mapping primitive (jax.vmap or jax.pmap) with awareness of State instances. It tracks reads and writes across the mapped axis, splits random states so each lane is seeded independently, scatters batched writes back to the right axis, and restores the global RNG so randomness is consumed exactly once per call. It is normally constructed by brainstate.transform.vmap2() or brainstate.transform.pmap2(), but can be used directly for custom mapping primitives.

Parameters:
origin_fun#

The wrapped callable.

Type:

callable

in_axes, out_axes

Argument/return mapping specification.

Type:

int, tuple, or None

state_in_axes, state_out_axes

Normalized {axis: predicate} state selectors.

Type:

dict

axis_size#

Mapped axis size, if explicitly provided.

Type:

int or None

axis_name#

Axis identifier forwarded to collectives.

Type:

hashable or None

mapping_fn#

The underlying mapping primitive.

Type:

callable

Notes

Random states are always split along the mapped axis and restored afterwards; this cannot be disabled. Plans (state groupings, batch sizes) are cached per abstract argument signature so repeated calls with the same structure avoid re-tracing.

Examples

>>> import brainstate
>>> import jax.numpy as jnp
>>> from brainstate.util.filter import OfType
>>>
>>> counter = brainstate.ShortTermState(jnp.zeros(3))
>>>
>>> def accumulate(x):
...     counter.value = counter.value + x
...     return counter.value
>>>
>>> batched = brainstate.transform.StatefulMapping(
...     accumulate,
...     in_axes=0,
...     out_axes=0,
...     state_in_axes={0: OfType(brainstate.ShortTermState)},
...     state_out_axes={0: OfType(brainstate.ShortTermState)},
...     name="batched_accumulate",
... )
>>>
>>> batched(jnp.asarray([1., 2., 3.]))
Array([1., 2., 3.], dtype=float32)
>>> counter.value
Array([1., 2., 3.], dtype=float32)