use nalgebra::*;
use nalgebra::storage::*;
use std::fmt::Debug;
use std::ops::AddAssign;
use crate::decision::BayesFactor;
pub mod poisson;
pub use poisson::*;
pub mod beta;
pub use beta::*;
pub mod bernoulli;
pub use bernoulli::*;
pub mod gamma;
pub use gamma::*;
pub mod normal;
pub use normal::*;
pub mod multinormal;
pub use multinormal::*;
pub mod wishart;
pub use wishart::*;
pub mod categorical;
pub use categorical::*;
pub mod dirichlet;
pub use dirichlet::*;
pub mod vonmises;
pub use vonmises::*;
pub trait Distribution
where Self : Debug + Sized
{
fn mean<'a>(&'a self) -> &'a DVector<f64>;
fn view_parameter(&self, natural : bool) -> &DVector<f64>;
fn set_parameter(&mut self, p : DVectorSlice<'_, f64>, natural : bool);
fn mode(&self) -> DVector<f64>;
fn var(&self) -> DVector<f64>;
fn cov(&self) -> Option<DMatrix<f64>>;
fn log_prob(&self, y : DMatrixSlice<f64>) -> f64;
fn sample(&self) -> DMatrix<f64>;
fn compare<'a, D>(&'a self, other : &'a D) -> BayesFactor<'a, Self, D>
where D : Distribution
{
BayesFactor::new(&self, &other)
}
}
pub trait Conditional<D>
where
Self : Distribution + Sized,
D : Distribution
{
fn condition(self, d : D) -> Self;
fn view_factor(&self) -> Option<&D>;
fn take_factor(self) -> Option<D>;
fn factor_mut(&mut self) -> Option<&mut D>;
}
#[derive(Debug, Clone)]
pub enum UnivariateFactor<D> {
Empty,
CondExpect(MultiNormal),
Conjugate(D)
}
pub trait ExponentialFamily<C>
where
C : Dim,
Self : Distribution
{
fn link<S>(
theta : &Matrix<f64, Dynamic, U1, S>
) -> Matrix<f64, Dynamic, U1, VecStorage<f64, Dynamic, U1>>
where S : Storage<f64, Dynamic, U1>;
fn link_inverse<S>(
eta : &Matrix<f64, Dynamic, U1, S>
) -> Matrix<f64, Dynamic, U1, VecStorage<f64, Dynamic, U1>>
where S : Storage<f64, Dynamic, U1>;
fn sufficient_stat(y : DMatrixSlice<'_, f64>) -> DMatrix<f64>;
fn suf_log_prob(&self, t : DMatrixSlice<'_, f64>) -> f64;
fn base_measure(y : DMatrixSlice<'_, f64>) -> DVector<f64>;
fn update_log_partition<'a>(&'a mut self, eta : DVectorSlice<'_, f64>);
fn update_grad(&mut self, eta : DVectorSlice<'_, f64>);
fn grad(&self) -> &DVector<f64>;
fn log_partition<'a>(&'a self) -> &'a DVector<f64>;
fn prob(&self, y : DMatrixSlice<f64>) -> f64 {
let bm = Self::base_measure(y.clone());
let mut unn_p = DVector::zeros(y.nrows());
for (i, _) in y.row_iter().enumerate() {
unn_p[i] = self.log_prob(y.rows(i,1)).exp();
println!("lp = {}", unn_p[i]);
}
let p = bm.component_mul(&unn_p);
let joint_p = p.iter().fold(1., |jp, p| jp * p);
joint_p
}
}
pub trait Estimator<D>
where
Self : Sized,
D : Distribution
{
fn fit<'a>(&'a mut self, y : DMatrix<f64>) -> Result<&'a D, &'static str>;
}
pub trait Likelihood<C>
where
Self : ExponentialFamily<C>,
C : Dim
{
fn mle(y : DMatrixSlice<'_, f64>) -> (f64, f64) {
(Self::mean_mle(y), Self::se_mle(y))
}
fn mean_mle(y : DMatrixSlice<'_, f64>) -> f64;
fn var_mle(y : DMatrixSlice<'_, f64>) -> f64;
fn se_mle(y : DMatrixSlice<'_, f64>) -> f64 {
let n = y.nrows() as f64;
(Self::var_mle(y) / n).sqrt()
}
fn cond_log_prob(&self, y : DMatrixSlice<'_, f64>) -> f64 {
let eta_cond = self.view_parameter(true);
let log_part = self.log_partition();
assert!(y.ncols() == eta_cond.ncols());
assert!(log_part.nrows() == eta_cond.nrows() && log_part.nrows() == y.nrows());
let mut lp = 0.0;
let lp_iter = eta_cond.row_iter().zip(y.row_iter()).zip(log_part.iter());
for ((e, y), l) in lp_iter {
lp += e.dot(&y) - l
};
lp
}
}