use nalgebra::DVector;
use rand::Rng;
use rand_distr::{Distribution, StandardNormal};
use crate::mcmc::engine::{EssParam, EssParamSummary};
pub trait ComponentPrior: Clone + Send + Sync {
type Inclusion: EssParam + Clone + Send;
type Effect: EssParamSummary + Clone + Send;
type Theta: Clone + Send;
fn draw_inclusion(&self, p: usize, rng: &mut impl Rng) -> Self::Inclusion;
fn draw_effect(&self, rng: &mut impl Rng) -> Self::Effect;
fn to_alpha(&self, raw: &Self::Inclusion) -> Vec<f32>;
fn combine(&self, alphas: &[Vec<f32>], effects: &[Self::Effect]) -> Self::Theta;
fn remove_component_inplace(
&self,
theta: &mut Self::Theta,
alpha: &[f32],
effect: &Self::Effect,
);
fn add_component_inplace(&self, theta: &mut Self::Theta, alpha: &[f32], effect: &Self::Effect);
fn effect_var(&self) -> f32;
fn zero_theta(&self, p: usize) -> Self::Theta;
}
#[derive(Clone)]
pub struct SoftmaxNormalPrior {
pub logit_var: f32,
pub effect_var: f32,
}
impl SoftmaxNormalPrior {
pub fn new(logit_var: f32, effect_var: f32) -> Self {
Self {
logit_var,
effect_var,
}
}
}
impl ComponentPrior for SoftmaxNormalPrior {
type Inclusion = DVector<f32>;
type Effect = DVector<f32>; type Theta = DVector<f32>;
fn draw_inclusion(&self, p: usize, rng: &mut impl Rng) -> DVector<f32> {
let std = self.logit_var.sqrt();
DVector::from_fn(p, |_, _| {
let v: f64 = StandardNormal.sample(rng);
v as f32 * std
})
}
fn draw_effect(&self, rng: &mut impl Rng) -> DVector<f32> {
let std = self.effect_var.sqrt();
let v: f64 = StandardNormal.sample(rng);
DVector::from_element(1, v as f32 * std)
}
fn to_alpha(&self, raw: &DVector<f32>) -> Vec<f32> {
softmax(raw)
}
fn combine(&self, alphas: &[Vec<f32>], effects: &[Self::Effect]) -> DVector<f32> {
let p = alphas[0].len();
let mut theta = DVector::from_element(p, 0.0f32);
for (alpha, effect) in alphas.iter().zip(effects.iter()) {
let beta = effect[0];
for (j, &a) in alpha.iter().enumerate() {
theta[j] += a * beta;
}
}
theta
}
fn remove_component_inplace(
&self,
theta: &mut DVector<f32>,
alpha: &[f32],
effect: &DVector<f32>,
) {
let beta = effect[0];
for (j, &a) in alpha.iter().enumerate() {
theta[j] -= a * beta;
}
}
fn add_component_inplace(
&self,
theta: &mut DVector<f32>,
alpha: &[f32],
effect: &DVector<f32>,
) {
let beta = effect[0];
for (j, &a) in alpha.iter().enumerate() {
theta[j] += a * beta;
}
}
fn effect_var(&self) -> f32 {
self.effect_var
}
fn zero_theta(&self, p: usize) -> DVector<f32> {
DVector::from_element(p, 0.0f32)
}
}
pub(crate) fn softmax(v: &DVector<f32>) -> Vec<f32> {
let max_v = v.max();
let mut out: Vec<f32> = v.iter().map(|&x| (x - max_v).exp()).collect();
let sum: f32 = out.iter().sum();
let inv = 1.0 / sum;
for x in &mut out {
*x *= inv;
}
out
}
pub(crate) fn sigmoid(v: &DVector<f32>) -> Vec<f32> {
v.iter()
.map(|&x| {
if x >= 0.0 {
let e = (-x).exp();
1.0 / (1.0 + e)
} else {
let e = x.exp();
e / (1.0 + e)
}
})
.collect()
}
#[derive(Clone)]
pub struct BernoulliNormalPrior {
pub logit_var: f32,
pub effect_var: f32,
}
impl BernoulliNormalPrior {
pub fn new(logit_var: f32, effect_var: f32) -> Self {
Self {
logit_var,
effect_var,
}
}
}
impl ComponentPrior for BernoulliNormalPrior {
type Inclusion = DVector<f32>;
type Effect = DVector<f32>; type Theta = DVector<f32>;
fn draw_inclusion(&self, p: usize, rng: &mut impl Rng) -> DVector<f32> {
let std = self.logit_var.sqrt();
DVector::from_fn(p, |_, _| {
let v: f64 = StandardNormal.sample(rng);
v as f32 * std
})
}
fn draw_effect(&self, rng: &mut impl Rng) -> DVector<f32> {
let std = self.effect_var.sqrt();
let v: f64 = StandardNormal.sample(rng);
DVector::from_element(1, v as f32 * std)
}
fn to_alpha(&self, raw: &DVector<f32>) -> Vec<f32> {
sigmoid(raw)
}
fn combine(&self, alphas: &[Vec<f32>], effects: &[Self::Effect]) -> DVector<f32> {
let p = alphas[0].len();
let mut theta = DVector::from_element(p, 0.0f32);
for (alpha, effect) in alphas.iter().zip(effects.iter()) {
let beta = effect[0];
for (j, &a) in alpha.iter().enumerate() {
theta[j] += a * beta;
}
}
theta
}
fn remove_component_inplace(
&self,
theta: &mut DVector<f32>,
alpha: &[f32],
effect: &DVector<f32>,
) {
let beta = effect[0];
for (j, &a) in alpha.iter().enumerate() {
theta[j] -= a * beta;
}
}
fn add_component_inplace(
&self,
theta: &mut DVector<f32>,
alpha: &[f32],
effect: &DVector<f32>,
) {
let beta = effect[0];
for (j, &a) in alpha.iter().enumerate() {
theta[j] += a * beta;
}
}
fn effect_var(&self) -> f32 {
self.effect_var
}
fn zero_theta(&self, p: usize) -> DVector<f32> {
DVector::from_element(p, 0.0f32)
}
}