use crate::distributions::BetaDistribution;
use crate::distributions::Quantile;
use crate::error::{Error, Result};
pub fn beta_credible_interval(
prior_alpha: f64,
prior_beta: f64,
successes: f64,
trials: f64,
alpha: f64,
) -> Result<(f64, f64)> {
if prior_alpha <= 0.0 || prior_beta <= 0.0 {
return Err(Error::InvalidInput(
"prior parameters must be positive".to_owned(),
));
}
if successes < 0.0 || trials < successes {
return Err(Error::InvalidInput(
"need 0 <= successes <= trials".to_owned(),
));
}
let posterior = BetaDistribution {
alpha_parameter: prior_alpha + successes,
beta_parameter: prior_beta + (trials - successes),
support_lower_bound: 0.0,
support_upper_bound: 1.0,
..Default::default()
};
let lower = posterior.quantile(alpha / 2.0);
let upper = posterior.quantile(1.0 - alpha / 2.0);
Ok((lower, upper))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn all_success_interval_is_high() -> Result<()> {
let (lo, hi) = beta_credible_interval(1.0, 1.0, 10.0, 10.0, 0.05)?;
assert!(lo > 0.5 && hi <= 1.0, "interval was ({lo}, {hi})");
Ok(())
}
#[test]
fn non_positive_prior_is_invalid() {
assert!(matches!(
beta_credible_interval(0.0, 1.0, 1.0, 2.0, 0.05),
Err(Error::InvalidInput(_))
));
}
}