use ndarray::prelude::*;
use rayon::prelude::*;
use crate::{
datasets::{CatTrj, CatType, Dataset},
models::Labelled,
types::{Labels, Set, States},
};
#[derive(Clone, Debug)]
pub struct CatWtdTrj {
trajectory: CatTrj,
weight: f64,
}
impl From<(CatTrj, f64)> for CatWtdTrj {
fn from((trajectory, weight): (CatTrj, f64)) -> Self {
Self::new(trajectory, weight)
}
}
impl From<CatWtdTrj> for (CatTrj, f64) {
fn from(other: CatWtdTrj) -> Self {
(other.trajectory, other.weight)
}
}
impl CatWtdTrj {
pub fn new(trajectory: CatTrj, weight: f64) -> Self {
assert!(
(0.0..=1.0).contains(&weight),
"Weight must be in the range [0, 1], but got {weight}."
);
Self { trajectory, weight }
}
#[inline]
pub const fn trajectory(&self) -> &CatTrj {
&self.trajectory
}
#[inline]
pub const fn weight(&self) -> f64 {
self.weight
}
#[inline]
pub const fn states(&self) -> &States {
self.trajectory.states()
}
#[inline]
pub const fn shape(&self) -> &Array1<usize> {
self.trajectory.shape()
}
#[inline]
pub const fn times(&self) -> &Array1<f64> {
self.trajectory.times()
}
}
impl Labelled for CatWtdTrj {
#[inline]
fn labels(&self) -> &Labels {
self.trajectory.labels()
}
}
impl Dataset for CatWtdTrj {
type Values = Array2<CatType>;
#[inline]
fn values(&self) -> &Self::Values {
self.trajectory.values()
}
#[inline]
fn sample_size(&self) -> f64 {
self.weight * (self.trajectory.values().nrows() as f64)
}
fn select(&self, x: &Set<usize>) -> Self {
let trajectory = self.trajectory.select(x);
let weight = self.weight;
Self::new(trajectory, weight)
}
}
#[derive(Clone, Debug)]
pub struct CatWtdTrjs {
labels: Labels,
states: States,
shape: Array1<usize>,
values: Vec<CatWtdTrj>,
}
impl CatWtdTrjs {
pub fn new<I>(values: I) -> Self
where
I: IntoIterator<Item = CatWtdTrj>,
{
let values: Vec<_> = values.into_iter().collect();
assert!(
values
.windows(2)
.all(|trjs| trjs[0].labels().eq(trjs[1].labels())),
"All trajectories must have the same labels."
);
assert!(
values
.windows(2)
.all(|trjs| trjs[0].states().eq(trjs[1].states())),
"All trajectories must have the same states."
);
assert!(
values
.windows(2)
.all(|trjs| trjs[0].shape().eq(trjs[1].shape())),
"All trajectories must have the same shape."
);
let trj = values.first().expect("No trajectory in the dataset.");
let labels = trj.labels().clone();
let states = trj.states().clone();
let shape = trj.shape().clone();
Self {
labels,
states,
shape,
values,
}
}
#[inline]
pub fn states(&self) -> &States {
&self.states
}
#[inline]
pub fn shape(&self) -> &Array1<usize> {
&self.shape
}
}
impl FromIterator<CatWtdTrj> for CatWtdTrjs {
#[inline]
fn from_iter<I: IntoIterator<Item = CatWtdTrj>>(iter: I) -> Self {
Self::new(iter)
}
}
impl FromParallelIterator<CatWtdTrj> for CatWtdTrjs {
#[inline]
fn from_par_iter<I: IntoParallelIterator<Item = CatWtdTrj>>(iter: I) -> Self {
Self::new(iter.into_par_iter().collect::<Vec<_>>())
}
}
impl<'a> IntoIterator for &'a CatWtdTrjs {
type IntoIter = std::slice::Iter<'a, CatWtdTrj>;
type Item = &'a CatWtdTrj;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.values.iter()
}
}
impl<'a> IntoParallelRefIterator<'a> for CatWtdTrjs {
type Item = &'a CatWtdTrj;
type Iter = rayon::slice::Iter<'a, CatWtdTrj>;
#[inline]
fn par_iter(&'a self) -> Self::Iter {
self.values.par_iter()
}
}
impl Labelled for CatWtdTrjs {
#[inline]
fn labels(&self) -> &Labels {
&self.labels
}
}
impl Dataset for CatWtdTrjs {
type Values = Vec<CatWtdTrj>;
#[inline]
fn values(&self) -> &Self::Values {
&self.values
}
#[inline]
fn sample_size(&self) -> f64 {
self.values.iter().map(Dataset::sample_size).sum()
}
fn select(&self, x: &Set<usize>) -> Self {
Self::new(self.values.iter().map(|trj| trj.select(x)))
}
}