r2l-core 0.0.3

A rust reinforcement learning library
Documentation
use std::any::TypeId;

use crate::{
    buffers::{TrajectoryBatch, buffer::TrajectoryView},
    error::TensorError,
    tensor::R2lTensor,
};

pub struct OwnedView<T: R2lTensor> {
    states: Vec<T>,
    next_states: Vec<T>,
    actions: Vec<T>,
    rewards: Vec<f32>,
    terminated: Vec<bool>,
    truncated: Vec<bool>,
}

impl<T: R2lTensor> OwnedView<T> {
    fn new(
        states: Vec<T>,
        next_states: Vec<T>,
        actions: Vec<T>,
        rewards: Vec<f32>,
        terminated: Vec<bool>,
        truncated: Vec<bool>,
    ) -> Self {
        Self {
            states,
            next_states,
            actions,
            rewards,
            terminated,
            truncated,
        }
    }
}

pub enum TrajectoryViewsWrapper<'a, T: R2lTensor> {
    Borrowed(TrajectoryView<'a, T>),
    Owned(OwnedView<T>),
}

impl<T: R2lTensor> TrajectoryViewsWrapper<'_, T> {
    pub fn from_view<'b, S: R2lTensor>(
        view: &'b TrajectoryView<'b, S>,
    ) -> Result<TrajectoryViewsWrapper<'b, T>, TensorError> {
        if TypeId::of::<S>() == TypeId::of::<T>() {
            let states = unsafe { &*(std::ptr::from_ref::<[S]>(view.states()) as *const [T]) };
            let next_states =
                unsafe { &*(std::ptr::from_ref::<[S]>(view.next_states()) as *const [T]) };
            let actions = unsafe { &*(std::ptr::from_ref::<[S]>(view.actions()) as *const [T]) };
            return Ok(TrajectoryViewsWrapper::Borrowed(TrajectoryView {
                states,
                next_states,
                actions,
                rewards: view.rewards(),
                terminated: view.terminated(),
                truncated: view.truncated(),
            }));
        }
        let states = view
            .states()
            .iter()
            .map(T::convert)
            .collect::<Result<Vec<_>, _>>()?;
        let next_states = view
            .next_states()
            .iter()
            .map(T::convert)
            .collect::<Result<Vec<_>, _>>()?;
        let actions = view
            .actions()
            .iter()
            .map(T::convert)
            .collect::<Result<Vec<_>, _>>()?;
        let rewards = view.rewards().to_vec();
        let terminated = view.terminated().to_vec();
        let truncated = view.truncated().to_vec();
        Ok(TrajectoryViewsWrapper::Owned(OwnedView::new(
            states,
            next_states,
            actions,
            rewards,
            terminated,
            truncated,
        )))
    }
}

impl<T: R2lTensor> TrajectoryBatch<T> for TrajectoryViewsWrapper<'_, T> {
    fn len(&self) -> usize {
        match self {
            Self::Borrowed(t) => t.len(),
            Self::Owned(o) => o.states.len(),
        }
    }

    fn is_empty(&self) -> bool {
        match self {
            Self::Borrowed(t) => t.is_empty(),
            Self::Owned(o) => o.states.is_empty(),
        }
    }

    fn states(&self) -> &[T] {
        match self {
            Self::Borrowed(t) => t.states(),
            Self::Owned(o) => &o.states,
        }
    }

    fn next_states(&self) -> &[T] {
        match self {
            Self::Borrowed(t) => t.next_states(),
            Self::Owned(o) => &o.next_states,
        }
    }

    fn actions(&self) -> &[T] {
        match self {
            Self::Borrowed(t) => t.actions(),
            Self::Owned(o) => &o.actions,
        }
    }

    fn rewards(&self) -> &[f32] {
        match self {
            Self::Borrowed(t) => t.rewards(),
            Self::Owned(o) => &o.rewards,
        }
    }

    fn terminated(&self) -> &[bool] {
        match self {
            Self::Borrowed(t) => t.terminated(),
            Self::Owned(o) => &o.terminated,
        }
    }

    fn truncated(&self) -> &[bool] {
        match self {
            Self::Borrowed(t) => t.truncated(),
            Self::Owned(o) => &o.truncated,
        }
    }
}