use std::{fmt, ops::{Add, Div, Mul, Sub}};
use probability::prelude::*;
use rand::{self, FromEntropy, prelude::ThreadRng, rngs::StdRng};
use rand::distributions::Distribution as Distr;
use statrs::function::gamma::gamma;
#[cfg(test)]
mod tests {
}
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Boolean(bool),
Integer(i64),
Real(f64),
Vector(Vec<Value>)
}
impl fmt::Display for Value {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Value::Boolean(b) => {
write!(formatter, "{}", b)
},
Value::Integer(i) => {
write!(formatter, "{}", i)
},
Value::Real(r) => {
write!(formatter, "{}", r)
},
Value::Vector(v) => {
write!(formatter, "{:?}", v)
},
}
}
}
impl From<bool> for Value {
fn from(b: bool) -> Self {
Value::Boolean(b)
}
}
impl From<f64> for Value {
fn from(f: f64) -> Self {
Value::Real(f)
}
}
impl From<f32> for Value {
fn from(f: f32) -> Self {
Value::Real(f as f64)
}
}
impl From<i8> for Value {
fn from(i: i8) -> Self {
Value::Integer(i as i64)
}
}
impl From<i16> for Value {
fn from(i: i16) -> Self {
Value::Integer(i as i64)
}
}
impl From<i32> for Value {
fn from(i: i32) -> Self {
Value::Integer(i as i64)
}
}
impl From<i64> for Value {
fn from(i: i64) -> Self {
Value::Integer(i)
}
}
impl From<u8> for Value {
fn from(i: u8) -> Self {
Value::Integer(i as i64)
}
}
impl From<u16> for Value {
fn from(i: u16) -> Self {
Value::Integer(i as i64)
}
}
impl From<u32> for Value {
fn from(i: u32) -> Self {
Value::Integer(i as i64)
}
}
impl From<u64> for Value {
fn from(i: u64) -> Self {
Value::Integer(i as i64)
}
}
impl From<usize> for Value {
fn from(i: usize) -> Self {
Value::Integer(i as i64)
}
}
impl Into<f64> for Value {
fn into(self) -> f64 {
match self {
Value::Real(r) => r,
_ => panic!("Cannot convert non-Real to f64.")
}
}
}
impl Into<i64> for Value {
fn into(self) -> i64 {
match self {
Value::Integer(i) => i,
_ => panic!("Cannot convert non-Integer to i64.")
}
}
}
impl Into<bool> for Value {
fn into(self) -> bool {
match self {
Value::Boolean(b) => b,
_ => panic!("Cannot convert non-Boolean to bool.")
}
}
}
impl Add<Value> for Value {
type Output = Value;
fn add(self, rhs: Value) -> Self::Output {
match self {
Self::Integer(i1) => {
match rhs {
Self::Integer(i2) => Self::Integer(i1+i2),
Self::Real(r2) => Self::Real(i1 as f64 + r2),
Self::Boolean(_) => panic!("Unable to add boolean values."),
Self::Vector(_) => panic!("Ubalbe to add integer to vector.")
}
},
Self::Real(r1) => {
match rhs {
Self::Integer(i2) => Self::Real(r1 + i2 as f64),
Self::Real(r2) => Self::Real(r1 + r2),
Self::Boolean(_) => panic!("Unable to add boolean values."),
Self::Vector(_) => panic!("Unable to add Real value to Vector")
}
},
Self::Boolean(_) => panic!("Unable to add boolean values."),
Self::Vector(vl) => {
match rhs {
Self::Vector(vr) => Self::Vector(vl.iter().zip(vr.iter()).map(|(l, r)| l.clone() + r.clone()).collect()),
_ => panic!("Unable to add Vector to non-Vector.")
}
}
}
}
}
impl Sub<Value> for Value {
type Output = Value;
fn sub(self, rhs: Value) -> Self::Output {
match self {
Self::Integer(i1) => {
match rhs {
Self::Integer(i2) => Self::Integer(i1 - i2),
Self::Real(r2) => Self::Real(i1 as f64 - r2),
Self::Boolean(_) => panic!("Unable to subtract boolean values."),
Self::Vector(_) => panic!("Ubalbe to subtract vector form integer.")
}
},
Self::Real(r1) => {
match rhs {
Self::Integer(i2) => Self::Real(r1 - i2 as f64),
Self::Real(r2) => Self::Real(r1 - r2),
Self::Boolean(_) => panic!("Unable to subtract boolean values."),
Self::Vector(_) => panic!("Unalbe to subtract Real from Vector.")
}
},
Self::Boolean(_) => panic!("Unable to subtract boolean values."),
Self::Vector(vl) => {
match rhs {
Self::Vector(vr) => Self::Vector(vl.iter().zip(vr.iter()).map(|(l, r)| l.clone() - r.clone()).collect()),
_ => panic!("Unable to subtract non-Vector from Vector.")
}
}
}
}
}
impl Mul<Value> for Value {
type Output = Value;
fn mul(self, rhs: Value) -> Self::Output {
match self {
Self::Integer(i1) => {
match rhs {
Self::Integer(i2) => Self::Integer(i1 * i2),
Self::Real(r2) => Self::Real(i1 as f64 * r2),
Self::Boolean(_) => panic!("Unable to multiply boolean values."),
Self::Vector(_) => panic!("Unable to multiply vectors.")
}
},
Self::Real(r1) => {
match rhs {
Self::Integer(i2) => Self::Real(r1 * i2 as f64),
Self::Real(r2) => Self::Real(r1 * r2),
Self::Boolean(_) => panic!("Unable to multiply boolean values."),
Self::Vector(_) => panic!("Unable to multiply vectors.")
}
},
Self::Boolean(_) => panic!("Unable to multiply boolean values."),
Self::Vector(_) => panic!("Unable to multiply vectors.")
}
}
}
impl Div<Value> for Value {
type Output = Value;
fn div(self, rhs: Value) -> Self::Output {
match self {
Self::Integer(i1) => {
match rhs {
Self::Integer(i2) => Self::Integer(i1 / i2),
Self::Real(r2) => Self::Real(i1 as f64 / r2),
Self::Boolean(_) => panic!("Unable to divide boolean values."),
Self::Vector(_) => panic!("Unable to divide vectors.")
}
},
Self::Real(r1) => {
match rhs {
Self::Integer(i2) => Self::Real(r1 / i2 as f64),
Self::Real(r2) => Self::Real(r1 / r2),
Self::Boolean(_) => panic!("Unable to divide boolean values."),
Self::Vector(_) => panic!("Unable to divide vectors.")
}
},
Self::Boolean(_) => panic!("Unable to divide boolean values."),
Self::Vector(_) => panic!("Unable to divide vectors.")
}
}
}
#[derive(Debug)]
pub enum Distribution {
Bernoulli(f64),
Binomial(i64, f64),
Normal(f64, f64),
Gamma(f64, f64),
Beta(f64, f64),
LogNormal(f64, f64),
Categorical(Vec<f64>),
Dirichlet(Vec<f64>),
}
pub trait Sampleable {
fn sample(&self) -> Value;
fn liklihood(&self, value : &Value) -> Result<f64, &str>;
}
pub(crate) struct Source<T>(pub T);
impl<T: rand::RngCore> source::Source for Source<T> {
fn read_u64(&mut self) -> u64 {
self.0.next_u64()
}
}
impl Sampleable for Distribution {
fn sample(&self) -> Value {
match self {
Distribution::Bernoulli(p) => {
let d = rand::distributions::Bernoulli::new(*p);
let v = d.sample(&mut ThreadRng::default());
Value::Boolean(v)
},
Distribution::Binomial(n, p) => {
let b = probability::distribution::Binomial::new(*n as usize, *p);
Value::Integer(b.sample(&mut Source(StdRng::from_entropy())) as i64)
},
Distribution::Normal(mu, sigma_squared) => {
let n = probability::distribution::Gaussian::new(*mu, *sigma_squared);
Value::Real(n.sample(&mut Source(StdRng::from_entropy())))
},
Distribution::Gamma(alpha, beta) => {
let g = probability::distribution::Gamma::new(*alpha, *beta);
Value::Real(g.sample(&mut Source(StdRng::from_entropy())))
},
Distribution::Beta(alpha, beta) => {
let b = probability::distribution::Beta::new(*alpha, *beta, 0.0, 1.0);
Value::Real(b.sample(&mut Source(StdRng::from_entropy())))
},
Distribution::LogNormal(mu, sigma) => {
let n = probability::distribution::Lognormal::new(*mu, *sigma);
Value::Real(n.sample(&mut Source(StdRng::from_entropy())))
},
Distribution::Categorical(v) => {
let c = probability::distribution::Categorical::new(&v[..]);
Value::Integer(c.sample(&mut Source(StdRng::from_entropy())) as i64)
},
Distribution::Dirichlet(xs) => {
let ys : Vec<f64> = xs.iter().map(|x|{
let beta = probability::distribution::Beta::new(*x, 1.0, 0.0, 1.0);
beta.sample(&mut Source(StdRng::from_entropy()))
}).collect();
let sum : f64 = ys.iter().sum();
let ys = ys.iter().map(|y| Value::Real(y / sum)).collect();
Value::Vector(ys)
}
}
}
fn liklihood(&self, value : &Value) -> Result<f64, &str> {
match self {
Distribution::Bernoulli(p) => {
match value {
Value::Boolean(b) => {
match b {
true => Ok(p.ln()),
false => Ok((1.0 - p).ln()),
}
},
_ => Err("Value of wrong type, expected Boolean.")
}
},
Distribution::Binomial(n, p) => {
match value {
Value::Integer(k) => {
let norm = probability::distribution::Binomial::new(*n as usize, *p);
Ok(norm.mass(*k as usize).ln())
},
_ => Err("Value of wrong type, expected Integer.")
}
},
Distribution::Normal(mu, sigma_squared) => {
match value {
Value::Real(n) => {
let norm = probability::distribution::Gaussian::new(*mu, *sigma_squared);
Ok(norm.density(*n).ln())
},
_ => Err("Value of wrong type, expected Real.")
}
},
Distribution::Gamma(alpha, beta) => {
match value {
Value::Real(n) => {
let g = probability::distribution::Gaussian::new(*alpha, *beta);
Ok(g.density(*n).ln())
},
_ => Err("Value of wrong type, expected Real.")
}
},
Distribution::Beta(alpha, beta) => {
match value {
Value::Real(n) => {
let b = probability::distribution::Beta::new(*alpha, *beta, 0.0, 1.0);
Ok(b.density(*n).ln())
},
_ => Err("Value of wrong type, expected Real.")
}
},
Distribution::LogNormal(mu, sigma) => {
match value {
Value::Real(n) => {
let l = probability::distribution::Lognormal::new(*mu, *sigma);
Ok(l.density(*n).ln())
},
_ => Err("Value of wrong type, expected Real.")
}
},
Distribution::Categorical(p) => {
match value {
Value::Integer(i) => {
let c = probability::distribution::Categorical::new(&p[..]);
Ok(c.mass(*i as usize).ln())
},
_ => Err("Value of wrong type, expected Integer.")
}
},
Distribution::Dirichlet(a) => {
match value {
Value::Vector(x) => {
let ba_numerator : f64 = a.iter().fold(1.0, |acc, x| acc * gamma(*x));
let ba_denominator : f64 = gamma(a.iter().sum());
let ba = ba_numerator / ba_denominator;
Ok((1.0/ba) * x.iter().map(|x| {
match *x {
Value::Real(x) => x,
_ => 1.0,
}
}).zip(a.iter()).fold(1.0, |acc, (x, a)| {
acc * x.powf(a-1.0)
}))
},
_ => Err("Value of wrong type, expected Vector.")
}
}
}
}
}