use crate::{
datasets::GaussType,
models::Labelled,
types::{Error, Labels, Result, Set},
};
#[non_exhaustive]
#[derive(Clone, Debug)]
pub enum GaussEvT {
CertainPositive {
event: usize,
value: GaussType,
},
}
impl GaussEvT {
pub const fn event(&self) -> usize {
match self {
Self::CertainPositive { event, .. } => *event,
}
}
pub const fn set_event(&mut self, event: usize) {
match self {
Self::CertainPositive { event: e, .. } => *e = event,
}
}
}
#[derive(Clone, Debug)]
pub struct GaussEv {
labels: Labels,
evidences: Vec<Option<GaussEvT>>,
}
impl Labelled for GaussEv {
#[inline]
fn labels(&self) -> &Labels {
&self.labels
}
}
impl GaussEv {
pub fn new<I>(mut labels: Labels, values: I) -> Result<Self>
where
I: IntoIterator<Item = GaussEvT>,
{
use GaussEvT as E;
let mut evidences = values.into_iter().try_fold(
vec![None; labels.len()],
|mut evidences, e| -> Result<_> {
let event = e.event();
if event >= evidences.len() {
return Err(Error::IndexOutOfBounds(event));
}
evidences[event] = Some(e);
Ok(evidences)
},
)?;
if !labels.is_sorted() {
let mut new_labels = labels.clone();
new_labels.sort();
let new_evidences = evidences.into_iter().flatten().try_fold(
vec![None; new_labels.len()],
|mut new_evidences, e| -> Result<_> {
let event_name = labels
.get_index(e.event())
.ok_or_else(|| Error::IndexOutOfBounds(e.event()))?;
let event = new_labels
.get_index_of(event_name)
.ok_or_else(|| Error::MissingLabel(event_name))?;
let e = match e {
E::CertainPositive { value, .. } => E::CertainPositive { event, value },
};
new_evidences[event] = Some(e);
Ok(new_evidences)
},
)?;
labels = new_labels;
evidences = new_evidences;
}
Ok(Self { labels, evidences })
}
#[inline]
pub const fn evidences(&self) -> &Vec<Option<GaussEvT>> {
&self.evidences
}
pub fn select(&self, x: &Set<usize>) -> Result<Self>
where
Self: Sized,
{
x.iter().try_for_each(|&i| {
if i >= self.labels.len() {
return Err(Error::IndexOutOfBounds(i));
}
Ok(())
})?;
let mut x = x.clone();
x.sort();
let labels: Labels = x
.iter()
.map(|&i| {
self.labels
.get_index(i)
.cloned()
.ok_or_else(|| Error::IndexOutOfBounds(i))
})
.collect::<Result<_>>()?;
let evidences = x.into_iter().enumerate().filter_map(|(i, x)| {
self.evidences[x].clone().map(|mut e| {
e.set_event(i);
e
})
});
Self::new(labels, evidences)
}
}