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}