use crate::symbolic::core::Expr;
use crate::symbolic::simplify_dag::simplify;
#[must_use]
pub fn mean(data: &[Expr]) -> Expr {
let n = data.len();
if n == 0 {
return Expr::Constant(0.0);
}
let sum = data
.iter()
.cloned()
.reduce(|acc, e| simplify(&Expr::new_add(acc, e)))
.unwrap_or(Expr::Constant(0.0));
simplify(&Expr::new_div(sum, Expr::Constant(n as f64)))
}
#[must_use]
pub fn variance(data: &[Expr]) -> Expr {
let n = data.len();
if n == 0 {
return Expr::Constant(0.0);
}
let mu = mean(data);
let squared_diffs = data
.iter()
.map(|x_i| {
let diff = Expr::new_sub(x_i.clone(), mu.clone());
Expr::new_pow(diff, Expr::Constant(2.0))
})
.reduce(|acc, e| simplify(&Expr::new_add(acc, e)))
.unwrap_or(Expr::Constant(0.0));
simplify(&Expr::new_div(squared_diffs, Expr::Constant(n as f64)))
}
#[must_use]
pub fn std_dev(data: &[Expr]) -> Expr {
simplify(&Expr::new_sqrt(variance(data)))
}
#[must_use]
pub fn covariance(
data1: &[Expr],
data2: &[Expr],
) -> Expr {
if data1.len() != data2.len() || data1.is_empty() {
return Expr::Constant(0.0);
}
let n = data1.len();
let mu_x = mean(data1);
let mu_y = mean(data2);
let sum_of_products = data1
.iter()
.zip(data2.iter())
.map(|(x_i, y_i)| {
let diff_x = Expr::new_sub(x_i.clone(), mu_x.clone());
let diff_y = Expr::new_sub(y_i.clone(), mu_y.clone());
Expr::new_mul(diff_x, diff_y)
})
.reduce(|acc, e| simplify(&Expr::new_add(acc, e)))
.unwrap_or(Expr::Constant(0.0));
simplify(&Expr::new_div(sum_of_products, Expr::Constant(n as f64)))
}
#[must_use]
pub fn correlation(
data1: &[Expr],
data2: &[Expr],
) -> Expr {
let cov_xy = covariance(data1, data2);
let std_dev_x = std_dev(data1);
let std_dev_y = std_dev(data2);
simplify(&Expr::new_div(cov_xy, Expr::new_mul(std_dev_x, std_dev_y)))
}