Skip to main content

rlevo_core/
evaluation.rs

1//! Object-safe environment interface consumed by external evaluators.
2//!
3//! [`BenchEnv`] is intentionally narrower than [`Environment`] so consumers
4//! (benchmarking harnesses, evolutionary outer loops) do not have to thread
5//! const-generic dimensions through their signatures. Adapters that wrap
6//! concrete [`Environment`] impls live in `rlevo-environments` (behind the
7//! `bench` feature).
8//!
9//! `reset` and `step` return `Result<_, BenchError>` so adapters preserve
10//! upstream recoverable errors ([`EnvironmentError`]) without escalating
11//! them to panics. Consuming harnesses still wrap callers in `catch_unwind`
12//! to capture genuine programming-bug panics separately.
13//!
14//! [`Environment`]: crate::environment::Environment
15//! [`EnvironmentError`]: crate::environment::EnvironmentError
16
17use crate::environment::EnvironmentError;
18
19#[derive(Debug, Clone)]
20pub struct BenchStep<Obs> {
21    pub observation: Obs,
22    pub reward: f64,
23    pub done: bool,
24}
25
26/// Recoverable error reported by a [`BenchEnv`] impl.
27///
28/// Wraps [`EnvironmentError`] so adapters preserve the typed upstream
29/// error rather than collapsing it to a string.
30#[derive(Debug, thiserror::Error)]
31pub enum BenchError {
32    #[error("environment reset failed: {0}")]
33    Reset(#[source] EnvironmentError),
34    #[error("environment step failed: {0}")]
35    Step(#[source] EnvironmentError),
36}
37
38pub trait BenchEnv {
39    type Observation;
40    type Action;
41
42    fn reset(&mut self) -> Result<Self::Observation, BenchError>;
43    fn step(
44        &mut self,
45        action: Self::Action,
46    ) -> Result<BenchStep<Self::Observation>, BenchError>;
47}