use crate::distributions::*;
#[derive(Debug, Clone, Copy)]
pub struct Pareto {
alpha: f64,
minval: f64,
}
impl Pareto {
pub fn new(alpha: f64, minval: f64) -> Self {
if alpha <= 0. || minval <= 0. {
panic!("Both alpha and beta must be positive.");
}
Pareto { alpha, minval }
}
pub fn set_alpha(&mut self, alpha: f64) -> &mut Self {
if alpha <= 0. {
panic!("Alpha must be positive.");
}
self.alpha = alpha;
self
}
pub fn set_minval(&mut self, minval: f64) -> &mut Self {
if minval <= 0. {
panic!("minval must be positive.");
}
self.minval = minval;
self
}
}
impl Default for Pareto {
fn default() -> Self {
Self::new(1., 1.)
}
}
impl Distribution for Pareto {
type Output = f64;
fn sample(&self) -> f64 {
let u = alea::f64();
self.minval / u.powf(1. / self.alpha)
}
}
impl Distribution1D for Pareto {
fn update(&mut self, params: &[f64]) {
assert!(params.len() == 2);
self.set_alpha(params[0]).set_minval(params[1]);
}
}
impl Continuous for Pareto {
type PDFType = f64;
fn pdf(&self, x: f64) -> f64 {
if x < self.minval {
return 0.;
}
self.alpha * self.minval.powf(self.alpha) / x.powf(self.alpha - 1.)
}
}
impl Mean for Pareto {
type MeanType = f64;
fn mean(&self) -> f64 {
if self.alpha <= 1. {
f64::INFINITY
} else {
self.alpha * self.minval / (self.alpha - 1.)
}
}
}
impl Variance for Pareto {
type VarianceType = f64;
fn var(&self) -> f64 {
if self.alpha <= 2. {
f64::INFINITY
} else {
self.minval.powi(2) * self.alpha / ((self.alpha - 1.).powi(2) * (self.alpha - 2.))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::statistics::{mean, var};
use approx_eq::assert_approx_eq;
#[test]
fn test_moments() {
let dist = Pareto::new(4., 4.);
let data = dist.sample_n(1e6 as usize);
assert_approx_eq!(dist.mean(), mean(&data), 0.05);
assert_approx_eq!(dist.var(), var(&data), 0.05);
}
}