Skip to content

policies

eigenkit.reservoir.policies

Reservoir policies — how each timestep maps the carried state and the current input to the circuit's (initial_state, gate_inputs).

Two execution shapes, because they are genuinely different computations:

  • Sequential (a fold over time). The quantum state is the memory: \(\psi_t\) depends on \(\psi_{t-1}\), so timesteps must run in order. These policies implement initial / inject / advance (Carry, LeakyCarry).
  • Parallel (a map over time). The quantum state carries nothing between steps — each step's input is a pure function of the raw input sequence (e.g. a sliding window). These policies expose expand_inputs(sequences) and the driver runs all B·T evaluations in one batched sweep instead of a Python timestep loop (Stateless).

The driver prefers expand_inputs when a policy has it (idiomatic optional method, like the backends' statevector / probabilities).

Carry dataclass

Policy that applies the circuit to the carried state: ψ_t = U(x_t) ψ_{t-1}.

The quantum state is the memory of the reservoir, and the first step starts from |0…0⟩. This policy is equivalent to LeakyCarry(alpha=1.0).

advance(x_t, evolved, state)

Build the state for the next timestep from the result of this step.

Parameters:

Name Type Description Default
x_t ndarray

The input of this timestep, of shape (B, F).

required
evolved ndarray

The statevector that the circuit produced.

required
state ReservoirState

The state that went into this step.

required

Returns:

Type Description
ReservoirState

The state for the next timestep.

initial(batch)

Return the state carried into the first timestep.

Parameters:

Name Type Description Default
batch int

The number of sequences that run in parallel.

required

Returns:

Type Description
ReservoirState

The initial ReservoirState.

inject(x_t, state)

Turn the input of this timestep into the arguments of the circuit call.

Parameters:

Name Type Description Default
x_t ndarray

The input of this timestep, of shape (B, F).

required
state ReservoirState

The state carried over from the previous step.

required

Returns:

Name Type Description
initial_state ndarray | None

The state to evaluate the circuit from, or None to start from |0…0⟩.

gate_inputs ndarray

The values to pass to the gates of the circuit.

LeakyCarry dataclass

Policy that mixes the carried state with a reset state and renormalises it.

It approximates a leaky, dissipative reservoir with pure states: ψ_t = normalise(α U(x_t) ψ_{t-1} + (1 − α) reset).

reset defaults to |0…0⟩ and should be a normalised statevector; this is not checked. With alpha=1, the policy is exactly Carry. This is not a true dissipative channel, which would need density matrices that the pure-state backends do not provide. It is an approximation that uses pure states only.

Attributes:

Name Type Description
alpha float

The mixing weight of the carried state, in [0, 1]. Lower values forget faster, and 1 keeps everything, which is exactly Carry.

reset ndarray | None

The state that is mixed in, a normalised statevector. None means |0…0⟩. The default is None.

advance(x_t, evolved, state)

Build the state for the next timestep from the result of this step.

Parameters:

Name Type Description Default
x_t ndarray

The input of this timestep, of shape (B, F).

required
evolved ndarray

The statevector that the circuit produced.

required
state ReservoirState

The state that went into this step.

required

Returns:

Type Description
ReservoirState

The state for the next timestep.

initial(batch)

Return the state carried into the first timestep.

Parameters:

Name Type Description Default
batch int

The number of sequences that run in parallel.

required

Returns:

Type Description
ReservoirState

The initial ReservoirState.

inject(x_t, state)

Turn the input of this timestep into the arguments of the circuit call.

Parameters:

Name Type Description Default
x_t ndarray

The input of this timestep, of shape (B, F).

required
state ReservoirState

The state carried over from the previous step.

required

Returns:

Name Type Description
initial_state ndarray | None

The state to evaluate the circuit from, or None to start from |0…0⟩.

gate_inputs ndarray

The values to pass to the gates of the circuit.

ReservoirPolicy

Bases: Protocol

A reservoir policy that carries state from one timestep to the next.

Parallel policies, which carry no state, do not implement this protocol. They provide expand_inputs(sequences), which returns the inputs of every timestep with shape (B, T, n_inputs), and the driver evaluates all timesteps at once. See Stateless.

advance(x_t, evolved, state)

Build the state for the next timestep from the result of this step.

Parameters:

Name Type Description Default
x_t ndarray

The input of this timestep, of shape (B, F).

required
evolved ndarray

The statevector that the circuit produced.

required
state ReservoirState

The state that went into this step.

required

Returns:

Type Description
ReservoirState

The state for the next timestep.

initial(batch)

Return the state carried into the first timestep.

Parameters:

Name Type Description Default
batch int

The number of sequences that run in parallel.

required

Returns:

Type Description
ReservoirState

The initial ReservoirState.

inject(x_t, state)

Turn the input of this timestep into the arguments of the circuit call.

Parameters:

Name Type Description Default
x_t ndarray

The input of this timestep, of shape (B, F).

required
state ReservoirState

The state carried over from the previous step.

required

Returns:

Name Type Description
initial_state ndarray | None

The state to evaluate the circuit from, or None to start from |0…0⟩.

gate_inputs ndarray

The values to pass to the gates of the circuit.

ReservoirState dataclass

The state that sequential policies carry from one timestep to the next.

vector is the (B, 2**n) statevector to inject at the next step, and None means that the step starts from |0…0⟩. history holds the recent raw inputs, of shape (B, k, F), for a sequential policy that encodes a window of inputs.

Attributes:

Name Type Description
vector ndarray | None

The statevector to inject at the next step, of shape (B, 2**n). None means that the step starts from |0…0⟩.

history ndarray | None

The last k raw inputs, of shape (B, k, F), for a policy that encodes a window of them. It is None when the policy keeps no history.

Stateless dataclass

Parallel policy that carries no state.

Every step starts from |0…0⟩, and the last window inputs are encoded as rotation angles of the circuit's gates. The memory is purely classical (the window), and the quantum state carries nothing from one step to the next. Every timestep is therefore independent, and the driver evaluates all of them in one batched run. With window=1, the policy has no memory: it encodes only the current input.

The circuit's n_inputs must equal window * F, where F is the number of features per step, because each step passes the whole flattened window to the encoding gates.

Attributes:

Name Type Description
window int

The number of consecutive inputs to encode at each step. 1 means no memory: only the current input is encoded. Whatever the value, the circuit's n_inputs must equal window * F. The default is 1.

expand_inputs(sequences)

Return the gate inputs of every timestep, with shape (B, T, window * F).

Step t encodes the inputs t - window + 1 to t. The first window - 1 steps are padded with zeros at the front. No quantum state is involved, so this is only a reshaping of the input sequence.

Parameters:

Name Type Description Default
sequences ndarray

The whole input batch, of shape (B, T, F).

required

Returns:

Type Description
ndarray

The gate inputs for every timestep, of shape (B, T, window * F).