use serde::{Deserialize, Serialize};
use crate::{
datasets::GaussType,
models::HasLabels,
types::{Error, Labels, Result, Set},
};
#[non_exhaustive]
#[derive(Clone, Debug, Serialize, Deserialize)]
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: evidence, ..
} => *evidence = event,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GaussEv {
labels: Labels,
evidences: Vec<Option<GaussEvT>>,
}
impl HasLabels 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, evidence| -> Result<_> {
let event = evidence.event();
if event >= evidences.len() {
return Err(Error::IndexOutOfBounds(event));
}
evidences[event] = Some(evidence);
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, evidence| -> Result<_> {
let event_name = labels
.get_index(evidence.event())
.ok_or_else(|| Error::IndexOutOfBounds(evidence.event()))?;
let event = new_labels
.get_index_of(event_name)
.ok_or_else(|| Error::MissingLabel(event_name))?;
let evidence = match evidence {
E::CertainPositive { value, .. } => E::CertainPositive { event, value },
};
new_evidences[event] = Some(evidence);
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 evidence| {
evidence.set_event(i);
evidence
})
});
Self::new(labels, evidences)
}
}