border_core/base/
policy.rs

1//! Policy interface for reinforcement learning.
2//!
3//! This module defines the core interface for policies in reinforcement learning.
4//! A policy represents a decision-making strategy that maps observations to actions,
5//! which can be either deterministic or stochastic.
6
7use super::Env;
8use anyhow::Result;
9use serde::de::DeserializeOwned;
10use std::path::Path;
11
12/// A policy that maps observations to actions in a reinforcement learning environment.
13///
14/// This trait defines the interface for policies, which are the core decision-making
15/// components in reinforcement learning. A policy can be:
16/// - Deterministic: Always returns the same action for a given observation
17/// - Stochastic: Returns actions sampled from a probability distribution
18///
19/// # Type Parameters
20///
21/// * `E` - The environment type that this policy operates on
22///
23/// # Examples
24///
25/// A simple deterministic policy might look like:
26/// ```ignore
27/// struct SimplePolicy;
28///
29/// impl<E: Env> Policy<E> for SimplePolicy {
30///     fn sample(&mut self, obs: &E::Obs) -> E::Act {
31///         // Always return the same action for a given observation
32///         E::Act::default()
33///     }
34/// }
35/// ```
36///
37/// A stochastic policy might look like:
38/// ```ignore
39/// struct StochasticPolicy;
40///
41/// impl<E: Env> Policy<E> for StochasticPolicy {
42///     fn sample(&mut self, obs: &E::Obs) -> E::Act {
43///         // Sample an action from a probability distribution
44///         // based on the observation
45///         E::Act::random()
46///     }
47/// }
48/// ```
49pub trait Policy<E: Env> {
50    /// Samples an action given an observation from the environment.
51    ///
52    /// This method is the core of the policy interface, defining how the policy
53    /// makes decisions based on the current state of the environment.
54    ///
55    /// # Arguments
56    ///
57    /// * `obs` - The current observation from the environment
58    ///
59    /// # Returns
60    ///
61    /// An action to be taken in the environment
62    fn sample(&mut self, obs: &E::Obs) -> E::Act;
63}
64
65/// A trait for objects that can be configured and built from configuration files.
66///
67/// This trait provides a standardized way to create objects from configuration
68/// parameters, either directly or from YAML files. It is commonly used for
69/// creating policies, environments, and other components of a reinforcement
70/// learning system.
71///
72/// # Associated Types
73///
74/// * `Config` - The configuration type that can be deserialized from YAML
75///
76/// # Examples
77///
78/// ```ignore
79/// #[derive(Clone, Deserialize)]
80/// struct MyConfig {
81///     learning_rate: f32,
82///     hidden_size: usize,
83/// }
84///
85/// struct MyObject {
86///     config: MyConfig,
87/// }
88///
89/// impl Configurable for MyObject {
90///     type Config = MyConfig;
91///
92///     fn build(config: Self::Config) -> Self {
93///         Self { config }
94///     }
95/// }
96///
97/// // Build from a YAML file
98/// let obj = MyObject::build_from_path("config.yaml")?;
99/// ```
100pub trait Configurable {
101    /// The configuration type for this object.
102    ///
103    /// This type must implement `Clone` and `DeserializeOwned` to support
104    /// building from configuration files.
105    type Config: Clone + DeserializeOwned;
106
107    /// Builds a new instance of this object from the given configuration.
108    ///
109    /// # Arguments
110    ///
111    /// * `config` - The configuration parameters
112    ///
113    /// # Returns
114    ///
115    /// A new instance of the object
116    fn build(config: Self::Config) -> Self;
117
118    /// Builds a new instance from a YAML configuration file.
119    ///
120    /// This is a convenience method that reads a YAML file and builds
121    /// the object using the deserialized configuration.
122    ///
123    /// # Arguments
124    ///
125    /// * `path` - Path to the YAML configuration file
126    ///
127    /// # Returns
128    ///
129    /// A new instance of the object or an error if the file cannot be read
130    /// or parsed
131    fn build_from_path(path: impl AsRef<Path>) -> Result<Self>
132    where
133        Self: Sized,
134    {
135        let file = std::fs::File::open(path)?;
136        let rdr = std::io::BufReader::new(file);
137        let config = serde_yaml::from_reader(rdr)?;
138        Ok(Self::build(config))
139    }
140}