r2l_core/on_policy/
algorithm.rs1use crate::{
2 HookResult, break_on_hook_result,
3 buffers::{TrajectoryBatch, buffer::TrajectoryView},
4 error::Error,
5 models::Actor,
6 return_on_hook_result,
7 tensor::R2lTensor,
8 utils::{actor_wrapper::ActorWrapper, buffer_wrapper::TrajectoryViewsWrapper},
9};
10
11pub trait Agent {
13 type Tensor: R2lTensor;
15
16 type Actor: Actor<Tensor = Self::Tensor> + Clone;
18
19 fn actor(&self) -> Self::Actor;
21
22 fn learn<B: TrajectoryBatch<Self::Tensor>>(&mut self, buffers: &[B]) -> Result<(), Error>;
28
29 fn set_learning_rate(&mut self, learning_rate: f64);
31}
32
33pub trait Sampler {
35 type Tensor: R2lTensor;
37
38 fn reset_all_envs(&mut self) -> Result<(), Error> {
44 Ok(())
45 }
46
47 fn collect_rollouts<A: Actor<Tensor = Self::Tensor> + Clone>(
53 &mut self,
54 actor: A,
55 ) -> Result<(), Error>;
56
57 fn trajectory_views(&mut self) -> impl AsRef<[TrajectoryView<'_, Self::Tensor>]>;
59}
60
61pub struct OnPolicyRuntime<A: Agent, S: Sampler> {
63 pub agent: A,
65 pub sampler: S,
67}
68
69impl<A: Agent, S: Sampler> OnPolicyRuntime<A, S> {
70 pub fn collect(&mut self) -> Result<(), Error> {
76 let actor = self.agent.actor();
77 let actor = ActorWrapper::new(actor);
78 self.sampler.collect_rollouts(actor)
79 }
80
81 pub fn trajectory_containers(&mut self) -> impl AsRef<[TrajectoryView<'_, S::Tensor>]> {
83 self.sampler.trajectory_views()
84 }
85
86 pub fn learn(&mut self) -> Result<(), Error> {
92 let views = self.sampler.trajectory_views();
93 let buffers = views
94 .as_ref()
95 .iter()
96 .map(TrajectoryViewsWrapper::from_view)
97 .collect::<Result<Vec<_>, _>>()?;
98 self.agent.learn(&buffers)
99 }
100
101 pub fn actor(&self) -> A::Actor {
103 self.agent.actor()
104 }
105}
106
107pub trait OnPolicyAlgorithmHooks {
109 type A: Agent;
111 type S: Sampler;
113
114 fn init_hook(&mut self, runtime: &mut OnPolicyRuntime<Self::A, Self::S>) -> HookResult;
116
117 fn post_rollout_hook(&mut self, runtime: &mut OnPolicyRuntime<Self::A, Self::S>) -> HookResult;
119
120 fn post_training_hook(&mut self, runtime: &mut OnPolicyRuntime<Self::A, Self::S>)
122 -> HookResult;
123
124 fn finish_training_hook(
130 &mut self,
131 runtime: &mut OnPolicyRuntime<Self::A, Self::S>,
132 ) -> Result<(), Error>;
133}
134
135pub struct OnPolicyAlgorithm<A: Agent, S: Sampler, H: OnPolicyAlgorithmHooks<A = A, S = S>> {
137 pub runtime: OnPolicyRuntime<A, S>,
139 pub hooks: H,
141}
142
143impl<A: Agent, S: Sampler, H: OnPolicyAlgorithmHooks<A = A, S = S>> OnPolicyAlgorithm<A, S, H> {
144 fn training_loop(&mut self) -> Result<(), Error> {
145 return_on_hook_result!(self.hooks.init_hook(&mut self.runtime));
146 loop {
147 self.runtime.collect()?;
148 break_on_hook_result!(self.hooks.post_rollout_hook(&mut self.runtime));
149
150 self.runtime.learn()?;
151 break_on_hook_result!(self.hooks.post_training_hook(&mut self.runtime));
152 }
153 Ok(())
154 }
155}
156
157impl<A: Agent, S: Sampler, H: OnPolicyAlgorithmHooks<A = A, S = S>> OnPolicyAlgorithm<A, S, H> {
158 pub fn new(runtime: OnPolicyRuntime<A, S>, hooks: H) -> Self {
160 Self { runtime, hooks }
161 }
162
163 pub fn train(&mut self) -> Result<(), Error> {
170 let training_result = self.training_loop();
171 let finalization_result = self.hooks.finish_training_hook(&mut self.runtime);
172 training_result.and(finalization_result)
173 }
174}