#[derive(Clone, Debug)]
pub struct EMOutput<M, E2M> {
pub models: Vec<M>,
pub expectations: Vec<E2M>,
pub last_model: M,
pub iterations: usize,
}
#[derive(Debug)]
pub struct EM<'a, M, E, EStep, E2M, MStep, Stop>
where
M: Clone,
E2M: Clone,
EStep: Fn(&M, &E) -> E2M,
MStep: Fn(&M, &E2M) -> M,
Stop: Fn(&M, &M, usize) -> bool,
{
initial_model: &'a M,
evidence: &'a E,
expectation: &'a EStep,
maximization: &'a MStep,
stop: &'a Stop,
}
impl<'a, M, E, EStep, E2M, MStep, Stop> EM<'a, M, E, EStep, E2M, MStep, Stop>
where
M: Clone,
E2M: Clone,
EStep: Fn(&M, &E) -> E2M,
MStep: Fn(&M, &E2M) -> M,
Stop: Fn(&M, &M, usize) -> bool,
{
pub fn fit(&self) -> EMOutput<M, E2M> {
let mut output = EMOutput {
models: Vec::new(),
expectations: Vec::new(),
last_model: self.initial_model.clone(),
iterations: 0,
};
let mut prev_model: M;
let mut curr_model: M = self.initial_model.clone();
while {
prev_model = curr_model;
output.models.push(prev_model.clone());
let expectation = (self.expectation)(&prev_model, self.evidence);
output.expectations.push(expectation.clone());
curr_model = (self.maximization)(&prev_model, &expectation);
output.last_model = curr_model.clone();
output.iterations += 1;
!(self.stop)(&prev_model, &curr_model, output.iterations)
} {}
output
}
}
pub struct EMBuilder<'a, M, E, EStep, E2M, MStep, Stop>
where
M: Clone,
E2M: Clone,
EStep: Fn(&M, &E) -> E2M,
MStep: Fn(&M, &E2M) -> M,
Stop: Fn(&M, &M, usize) -> bool,
{
initial_model: &'a M,
evidence: &'a E,
expectation: Option<&'a EStep>,
maximization: Option<&'a MStep>,
stop: Option<&'a Stop>,
}
impl<'a, M, E, EStep, E2M, MStep, Stop> EMBuilder<'a, M, E, EStep, E2M, MStep, Stop>
where
M: Clone,
E2M: Clone,
EStep: Fn(&M, &E) -> E2M,
MStep: Fn(&M, &E2M) -> M,
Stop: Fn(&M, &M, usize) -> bool,
{
pub fn new(initial_model: &'a M, evidence: &'a E) -> Self {
Self {
initial_model,
evidence,
expectation: None,
maximization: None,
stop: None,
}
}
pub fn with_e_step(mut self, expectation: &'a EStep) -> Self {
self.expectation = Some(expectation);
self
}
pub fn with_m_step(mut self, maximization: &'a MStep) -> Self {
self.maximization = Some(maximization);
self
}
pub fn with_stop(mut self, stop: &'a Stop) -> Self {
self.stop = Some(stop);
self
}
pub fn build(self) -> EM<'a, M, E, EStep, E2M, MStep, Stop> {
EM {
initial_model: self.initial_model,
evidence: self.evidence,
expectation: self.expectation.expect("Expectation step not set"),
maximization: self.maximization.expect("Maximization step not set"),
stop: self.stop.expect("Stopping criteria not set"),
}
}
}