use super::{StructuredEnvDist, StructuredEnvironment};
use crate::spaces::Space;
use crate::Prng;
use std::convert::Infallible;
use thiserror::Error;
pub trait CloneBuild: Clone {}
pub trait BuildEnv {
type Observation: Clone + Send;
type Action: Clone + Send;
type Feedback: Clone + Send;
type ObservationSpace: Space<Element = Self::Observation>;
type ActionSpace: Space<Element = Self::Action>;
type FeedbackSpace: Space<Element = Self::Feedback>;
type Environment: StructuredEnvironment<
Observation = Self::Observation,
Action = Self::Action,
Feedback = Self::Feedback,
ObservationSpace = Self::ObservationSpace,
ActionSpace = Self::ActionSpace,
FeedbackSpace = Self::FeedbackSpace,
>;
fn build_env(&self, rng: &mut Prng) -> Result<Self::Environment, BuildEnvError>;
}
impl<T: CloneBuild + StructuredEnvironment + ?Sized> BuildEnv for T {
type Observation = T::Observation;
type Action = T::Action;
type Feedback = T::Feedback;
type ObservationSpace = T::ObservationSpace;
type ActionSpace = T::ActionSpace;
type FeedbackSpace = T::FeedbackSpace;
type Environment = Self;
fn build_env(&self, _: &mut Prng) -> Result<Self::Environment, BuildEnvError> {
Ok(self.clone())
}
}
#[derive(Debug, Error)]
pub enum BuildEnvError {
#[error(transparent)]
Boxed(#[from] Box<dyn std::error::Error>),
}
impl From<Infallible> for BuildEnvError {
fn from(_: Infallible) -> Self {
unreachable!();
}
}
pub trait BuildEnvDist {
type Observation: Clone + Send;
type Action: Clone + Send;
type Feedback: Clone + Send;
type ObservationSpace: Space<Element = Self::Observation>;
type ActionSpace: Space<Element = Self::Action>;
type FeedbackSpace: Space<Element = Self::Feedback>;
type EnvDistribution: StructuredEnvDist<
Observation = Self::Observation,
Action = Self::Action,
Feedback = Self::Feedback,
ObservationSpace = Self::ObservationSpace,
ActionSpace = Self::ActionSpace,
FeedbackSpace = Self::FeedbackSpace,
>;
fn build_env_dist(&self) -> Self::EnvDistribution;
}
impl<T> BuildEnvDist for T
where
T: StructuredEnvDist + CloneBuild,
{
type Observation = <T::ObservationSpace as Space>::Element;
type Action = <T::ActionSpace as Space>::Element;
type Feedback = <T::FeedbackSpace as Space>::Element;
type ObservationSpace = T::ObservationSpace;
type ActionSpace = T::ActionSpace;
type FeedbackSpace = T::FeedbackSpace;
type EnvDistribution = Self;
#[inline]
fn build_env_dist(&self) -> Self::EnvDistribution {
self.clone()
}
}