pub struct RecurrentRolloutBuffer { /* private fields */ }Expand description
Rollout buffer that preserves temporal order for a recurrent policy.
Stores the same nine [num_steps, num_envs] transition arrays as
RolloutBuffer (via composition) plus
per-step recurrent state hidden / cell, each shaped
[num_steps, num_envs, hidden_dim].
Implementations§
Source§impl RecurrentRolloutBuffer
impl RecurrentRolloutBuffer
Sourcepub fn new(
num_steps: usize,
num_envs: usize,
obs_dim: usize,
hidden_dim: usize,
) -> Self
pub fn new( num_steps: usize, num_envs: usize, obs_dim: usize, hidden_dim: usize, ) -> Self
Create a new recurrent rollout buffer.
§Arguments
num_steps- Number of timesteps per rolloutnum_envs- Number of parallel environmentsobs_dim- Dimensionality of observationshidden_dim- Width of the LSTM(h, c)state
Sourcepub fn add(
&mut self,
step: usize,
env_id: usize,
observation: &[f32],
action: i64,
reward: f32,
value: f32,
log_prob: f32,
terminated: bool,
truncated: bool,
)
pub fn add( &mut self, step: usize, env_id: usize, observation: &[f32], action: i64, reward: f32, value: f32, log_prob: f32, terminated: bool, truncated: bool, )
Add a transition to the buffer.
Delegates verbatim to
RolloutBuffer::add; see that
method for argument semantics. The recurrent (h, c) for this step
is recorded separately via Self::add_recurrent_state.
Sourcepub fn add_recurrent_state(
&mut self,
step: usize,
env_id: usize,
h: &[f32],
c: &[f32],
)
pub fn add_recurrent_state( &mut self, step: usize, env_id: usize, h: &[f32], c: &[f32], )
Record the recurrent state (h, c) entering step step for
env env_id.
The rollout loop calls this before the env step, so the stored
state is the one that entered the step — used for warm-start
verification (via Self::seed_warm_start) and reserved as the
hook a future Strategy B trainer would reuse. The training forward
itself does not read these back (it recomputes states from a zeroed
initial_state).
§Panics
Panics (debug builds) if step/env_id are out of range or if
h/c do not have length hidden_dim.
Sourcepub fn seed_warm_start(
&mut self,
last_step: usize,
final_hidden: &[Vec<f32>],
final_cell: &[Vec<f32>],
)
pub fn seed_warm_start( &mut self, last_step: usize, final_hidden: &[Vec<f32>], final_cell: &[Vec<f32>], )
Seed the step-0 recurrent state for the next rollout iteration, in place.
For each env, if it did not end its episode
(terminated || truncated) on step last_step, its final recurrent
state final_hidden[env] / final_cell[env] (the state exiting the
last collected step) is carried into hidden[0][env] /
cell[0][env]. If it did end its episode, step 0 is seeded with
zeros — the episode already ended, so no memory should survive into
the fresh one. This is the warm-start half of the GAE/state-reset
asymmetry: the carry decision follows terminated || truncated, not
terminated alone.
final_hidden / final_cell are indexed [env][hidden_dim] and
must have num_envs rows.
This method also records the per-env cross-iteration carry-in flag
that becomes episode_starts[0] of the next materialized batch: an
env that ended its episode gets flag 1.0 (its step-0 state resets),
a live env gets 0.0 (its state continues). The flag is set in
lockstep with the (h, c) carry so the reset mask and the seeded
state always agree.
§Strategy A note (the (h, c) carry is a Strategy-B hook)
The (h, c) seeded into hidden[0] / cell[0] here is not
consumed by Strategy A’s Self::to_sequence_batch, which always
passes initial_state: None (zeros) to the forward — an intentional
BPTT truncation at the iteration boundary. Cross-iteration continuity
is instead approximated only through the carry-in flag above (which
controls the reset, not the value, of step 0’s state). The seeded
(h, c) storage is a forward-looking hook a future Strategy B trainer
(fixed-length subsequences with stored boundary states) would feed in;
under Strategy A it is deliberately left unread.
§Panics
Panics if last_step >= num_steps, if final_hidden / final_cell
do not have num_envs rows, or (debug builds) if any row is not
hidden_dim wide.
Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Reset the buffer’s advantages/returns for a new rollout.
Delegates to
RolloutBuffer::reset.
The recurrent (h, c) arrays and the episode_start_carry flag are
intentionally left in place — (h, c) is overwritten by
Self::add_recurrent_state during the next collection, and both the
step-0 state and the carry flag are seeded by
Self::seed_warm_start so they must survive the reset to bridge the
iteration boundary.
Sourcepub fn compute_advantages(
&mut self,
last_values: &[f32],
gamma: f32,
gae_lambda: f32,
)
pub fn compute_advantages( &mut self, last_values: &[f32], gamma: f32, gae_lambda: f32, )
Compute GAE over the full [num_steps, num_envs] capacity.
Delegates unchanged to
compute_advantages — the
[step][env] advantage/return grid is byte-identical to the
feedforward path (GAE bootstraps on terminated only).
Sourcepub fn compute_advantages_partial(
&mut self,
valid_steps: usize,
last_values: &[f32],
gamma: f32,
gae_lambda: f32,
)
pub fn compute_advantages_partial( &mut self, valid_steps: usize, last_values: &[f32], gamma: f32, gae_lambda: f32, )
Compute GAE over the first valid_steps rows.
Delegates unchanged to
compute_advantages_partial.
Width of the recurrent (h, c) state.
Sourcepub fn observations(&self) -> &[Vec<Vec<f32>>]
pub fn observations(&self) -> &[Vec<Vec<f32>>]
Per-step observations, indexed [step][env] then by obs dimension.
Sourcepub fn log_probs(&self) -> &[Vec<f32>]
pub fn log_probs(&self) -> &[Vec<f32>]
Per-step behavior-policy log-probs, indexed [step][env].
Sourcepub fn terminated(&self) -> &[Vec<bool>]
pub fn terminated(&self) -> &[Vec<bool>]
Per-step terminal flags, indexed [step][env].
Sourcepub fn advantages(&self) -> &[Vec<f32>]
pub fn advantages(&self) -> &[Vec<f32>]
Per-step GAE advantages, indexed [step][env].
Recurrent hidden state entering each step, indexed
[step][env] then by hidden dimension.
Sourcepub fn cell(&self) -> &[Vec<Vec<f32>>]
pub fn cell(&self) -> &[Vec<Vec<f32>>]
Recurrent cell state entering each step, indexed [step][env]
then by hidden dimension.
Sourcepub fn episode_start_carry(&self) -> &[f32]
pub fn episode_start_carry(&self) -> &[f32]
Per-env cross-iteration carry-in flag (episode_starts[0] source),
indexed [env]. 1.0 marks that the env’s episode ended at the end
of the previous rollout iteration (step 0 resets); 0.0 marks a
carried-over episode.
Sourcepub fn to_sequence_batch<B: Backend>(
&self,
device: &B::Device,
) -> RecurrentRolloutBatch<B>
pub fn to_sequence_batch<B: Backend>( &self, device: &B::Device, ) -> RecurrentRolloutBatch<B>
Materialize the full buffer as a rank-3 sequence batch (T = num_steps).
Convenience wrapper over Self::to_sequence_batch_partial with
valid_steps == num_steps.
Sourcepub fn to_sequence_batch_partial<B: Backend>(
&self,
valid_steps: usize,
device: &B::Device,
) -> RecurrentRolloutBatch<B>
pub fn to_sequence_batch_partial<B: Backend>( &self, valid_steps: usize, device: &B::Device, ) -> RecurrentRolloutBatch<B>
Materialize the first valid_steps rows as a rank-3 sequence batch
(T = valid_steps).
Selects all envs. See RecurrentRolloutBatch for the exact
field shapes. Env-major layout: each env-trajectory is one
contiguous row of length T.
§Panics
Panics if valid_steps > num_steps.
Sourcepub fn to_minibatches<'a, B: Backend>(
&'a self,
envs_per_minibatch: usize,
shuffle: bool,
device: &B::Device,
) -> RecurrentMinibatchIterator<'a, B> ⓘ
pub fn to_minibatches<'a, B: Backend>( &'a self, envs_per_minibatch: usize, shuffle: bool, device: &B::Device, ) -> RecurrentMinibatchIterator<'a, B> ⓘ
Build an env-major minibatch iterator over full trajectories
(T = num_steps).
Shuffles environment indices (not global timesteps) and chunks
them by envs_per_minibatch — the recurrent analogue of the
feedforward batch_size, counting whole env-trajectories rather
than loose timesteps. Over one epoch every env index appears in
exactly one minibatch.
When shuffle is false the env order is 0..num_envs (useful for
deterministic tests / reproducible evaluation).
Trait Implementations§
Source§impl Clone for RecurrentRolloutBuffer
impl Clone for RecurrentRolloutBuffer
Source§fn clone(&self) -> RecurrentRolloutBuffer
fn clone(&self) -> RecurrentRolloutBuffer
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for RecurrentRolloutBuffer
impl RefUnwindSafe for RecurrentRolloutBuffer
impl Send for RecurrentRolloutBuffer
impl Sync for RecurrentRolloutBuffer
impl Unpin for RecurrentRolloutBuffer
impl UnsafeUnpin for RecurrentRolloutBuffer
impl UnwindSafe for RecurrentRolloutBuffer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more