10#ifdef MOOSE_LIBTORCH_ENABLED
16#include "libmesh/utility.h"
21 const unsigned int input_timesteps,
22 const unsigned int timestep_window,
23 const bool shift_outputs,
24 const bool average_reward_over_timestep_window)
25 : _timestep_window(timestep_window),
26 _shift_outputs(shift_outputs),
27 _average_reward_over_timestep_window(average_reward_over_timestep_window),
28 _observation_history(input_timesteps)
31 mooseError(
"The RL trajectory timestep window must be at least 1.");
34std::vector<LibtorchRLTrajectoryBuffer::Trajectory>
38 const std::vector<std::vector<Real>> & rewards)
const
40 if (actions.size() != log_probabilities.size())
41 mooseError(
"The number of log-probability reporters (",
42 log_probabilities.size(),
43 ") must match the number of action reporters (",
51 std::vector<LibtorchRLTrajectoryBuffer::Trajectory> trajectories;
53 for (
const auto sample_i : index_range(rewards))
55 const auto & reward_sample = rewards[sample_i];
60 std::vector<std::vector<Real>> component_trajectories(observations.size());
61 for (
const auto observation_i : index_range(observations))
62 component_trajectories[observation_i] =
63 downsample((*observations[observation_i])[sample_i], 0, num_transitions + 1);
68 trajectory.
actions.assign(num_transitions, std::vector<Real>());
71 for (
auto & action_row : trajectory.
actions)
72 action_row.reserve(actions.size());
74 log_probability_row.reserve(log_probabilities.size());
76 for (
const auto step_i : make_range(num_transitions))
84 for (
const auto action_i : index_range(actions))
86 const auto action_sequence =
88 const auto log_probability_sequence =
91 for (
const auto step_i : make_range(num_transitions))
93 trajectory.
actions[step_i].push_back(action_sequence[step_i]);
102 trajectory.
terminals.assign(num_transitions,
false);
105 trajectories.push_back(std::move(trajectory));
120 const std::string & quantity,
121 const std::size_t num_samples)
123 for (
const auto component_i : index_range(data))
124 if (data[component_i]->size() != num_samples)
130 data[component_i]->size(),
131 " samples, but the reward reporter holds ",
138 const unsigned int offset,
139 const unsigned int num_entries)
const
142 values.reserve(num_entries);
144 for (
const auto entry_i : make_range(num_entries))
147 if (raw_index >= sample.size())
148 mooseError(
"Reporter data is shorter than required by the configured timestep window and "
149 "history stacking.");
150 values.push_back(sample[raw_index]);
158 const unsigned int num_entries)
const
161 values.reserve(num_entries);
163 for (
const auto entry_i : make_range(num_entries))
167 if (window_end > sample.size())
169 "Reporter reward data is shorter than required by the configured timestep window.");
172 std::accumulate(sample.begin() + window_begin, sample.begin() + window_end, 0.0);
void mooseError(Args &&... args)
std::array< Real, 2 > values
std::vector< Real > stackTrajectoryObservation(const std::vector< std::vector< Real > > &component_trajectories, unsigned int time_index) const
std::vector< Real > windowAverage(const std::vector< Real > &sample, unsigned int num_entries) const
Average a raw reporter sequence over consecutive timestep windows after the initial entry.
const bool _average_reward_over_timestep_window
Whether rewards are averaged over each window instead of sampled at its end.
unsigned int numTransitions(std::size_t raw_sequence_size) const
Count the transitions available in a raw reporter sequence.
LibtorchRLTrajectoryAssembler(unsigned int input_timesteps, unsigned int timestep_window, bool shift_outputs, bool average_reward_over_timestep_window)
Build the trajectory assembler.
const LibtorchObservationHistoryHelper _observation_history
Observation history stacking helper.
const unsigned int _timestep_window
Raw reporter entries per transition.
std::vector< Real > downsample(const std::vector< Real > &sample, unsigned int offset, unsigned int num_entries) const
Take every timestep_window-th entry of a raw reporter sequence.
std::vector< LibtorchRLTrajectoryBuffer::Trajectory > assemble(const ReporterData &observations, const ReporterData &actions, const ReporterData &log_probabilities, const std::vector< std::vector< Real > > &rewards) const
Assemble one trajectory per sample that holds at least one transition.
const bool _shift_outputs
Whether actions and log probabilities are read one raw entry after the observation.
static void checkSampleCount(const ReporterData &data, const std::string &quantity, std::size_t num_samples)
Check that every component of a rollout quantity holds one sequence per sample.
Vector data for one on-policy trajectory.
std::vector< Real > rewards
Scalar rewards for each transition.
std::vector< std::vector< Real > > observations
Observations for each transition.
std::vector< std::vector< Real > > actions
Actions applied at each transition.
std::vector< std::vector< Real > > next_observations
Next observations for each transition.
std::vector< std::vector< Real > > log_probabilities
Action log-probabilities recorded during rollout.
std::vector< bool > terminals
Terminal flags for each transition. A true value cuts value bootstrapping at that step.