use greeners::{Bootstrap, HypothesisTest};
use ndarray::{Array1, Array2};
#[test]
fn test_bootstrap_pairs_basic() {
let y = Array1::from(vec![5.0, 8.0, 11.0, 14.0, 17.0]);
let x = Array2::from_shape_vec((5, 2), vec![
1.0, 1.0,
1.0, 2.0,
1.0, 3.0,
1.0, 4.0,
1.0, 5.0,
]).unwrap();
let n_bootstrap = 100;
let boot_coefs = Bootstrap::pairs_bootstrap(&y, &x, n_bootstrap).unwrap();
assert_eq!(boot_coefs.nrows(), n_bootstrap);
assert_eq!(boot_coefs.ncols(), 2);
for i in 0..n_bootstrap {
assert!(boot_coefs[[i, 0]].is_finite());
assert!(boot_coefs[[i, 1]].is_finite());
}
}
#[test]
fn test_bootstrap_standard_errors() {
let y = Array1::from(vec![3.0, 5.0, 7.0, 9.0, 11.0, 13.0]);
let x = Array2::from_shape_vec((6, 2), vec![
1.0, 1.0,
1.0, 2.0,
1.0, 3.0,
1.0, 4.0,
1.0, 5.0,
1.0, 6.0,
]).unwrap();
let boot_coefs = Bootstrap::pairs_bootstrap(&y, &x, 200).unwrap();
let boot_se = Bootstrap::bootstrap_se(&boot_coefs);
assert_eq!(boot_se.len(), 2);
assert!(boot_se[0] > 0.0);
assert!(boot_se[1] > 0.0);
assert!(boot_se.iter().all(|&se| se.is_finite()));
}
#[test]
fn test_bootstrap_percentile_ci() {
let y = Array1::from(vec![2.5, 4.8, 7.1, 9.3, 11.7, 14.2, 16.5]);
let x = Array2::from_shape_vec((7, 2), vec![
1.0, 1.0,
1.0, 2.0,
1.0, 3.0,
1.0, 4.0,
1.0, 5.0,
1.0, 6.0,
1.0, 7.0,
]).unwrap();
let boot_coefs = Bootstrap::pairs_bootstrap(&y, &x, 500).unwrap();
let (lower, upper) = Bootstrap::percentile_ci(&boot_coefs, 0.05);
assert_eq!(lower.len(), 2);
assert_eq!(upper.len(), 2);
assert!(lower[0] < upper[0]);
assert!(lower[1] < upper[1]);
assert!(lower.iter().all(|&l| l.is_finite()));
assert!(upper.iter().all(|&u| u.is_finite()));
}
#[test]
fn test_bootstrap_confidence_interval_coverage() {
let y = Array1::from(vec![3.0, 5.0, 7.0, 9.0, 11.0]);
let x = Array2::from_shape_vec((5, 2), vec![
1.0, 1.0,
1.0, 2.0,
1.0, 3.0,
1.0, 4.0,
1.0, 5.0,
]).unwrap();
let boot_coefs = Bootstrap::pairs_bootstrap(&y, &x, 1000).unwrap();
let (lower, upper) = Bootstrap::percentile_ci(&boot_coefs, 0.05);
let true_intercept = 1.0;
let true_slope = 2.0;
assert!(lower[0] <= true_intercept + 0.5 && upper[0] >= true_intercept - 0.5);
assert!(lower[1] <= true_slope + 0.5 && upper[1] >= true_slope - 0.5);
}
#[test]
fn test_wald_test_basic() {
let beta = Array1::from(vec![2.0, 3.5]); let cov_matrix = Array2::from_shape_vec((2, 2), vec![
0.25, 0.0,
0.0, 0.16,
]).unwrap();
let r = Array2::from_shape_vec((1, 2), vec![0.0, 1.0]).unwrap();
let q = Array1::from(vec![0.0]);
let (wald_stat, p_value, df) = HypothesisTest::wald_test(&beta, &cov_matrix, &r, &q).unwrap();
assert_eq!(df, 1);
assert!(wald_stat > 0.0);
assert!(p_value >= 0.0 && p_value <= 1.0);
assert!((wald_stat - 76.5625).abs() < 0.01);
assert!(p_value < 0.01); }
#[test]
fn test_wald_test_joint_hypothesis() {
let beta = Array1::from(vec![1.0, 2.0, 3.0]); let cov_matrix = Array2::from_shape_vec((3, 3), vec![
0.25, 0.0, 0.0,
0.0, 0.16, 0.0,
0.0, 0.0, 0.09,
]).unwrap();
let r = Array2::from_shape_vec((2, 3), vec![
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
]).unwrap();
let q = Array1::from(vec![0.0, 0.0]);
let (wald_stat, p_value, df) = HypothesisTest::wald_test(&beta, &cov_matrix, &r, &q).unwrap();
assert_eq!(df, 2); assert!(wald_stat > 0.0);
assert!(p_value >= 0.0 && p_value <= 1.0);
}
#[test]
fn test_joint_significance_test() {
let beta = Array1::from(vec![1.5, 2.5, 3.5]); let cov_matrix = Array2::from_shape_vec((3, 3), vec![
0.25, 0.0, 0.0,
0.0, 0.16, 0.0,
0.0, 0.0, 0.09,
]).unwrap();
let (wald_stat, p_value, df) = HypothesisTest::joint_significance(&beta, &cov_matrix, true).unwrap();
assert_eq!(df, 2);
assert!(wald_stat > 0.0);
assert!(p_value >= 0.0 && p_value <= 1.0);
assert!(p_value < 0.01);
}
#[test]
fn test_f_test_nested_models() {
let ssr_r = 150.0;
let ssr_f = 100.0;
let n = 50;
let k_f = 4;
let k_r = 2;
let (f_stat, p_value, df_num, df_denom) =
HypothesisTest::f_test_nested(ssr_r, ssr_f, n, k_f, k_r).unwrap();
assert_eq!(df_num, 2); assert_eq!(df_denom, 46);
assert!(f_stat > 0.0);
assert!(p_value >= 0.0 && p_value <= 1.0);
let expected_f = ((ssr_r - ssr_f) / (k_f - k_r) as f64) / (ssr_f / (n - k_f) as f64);
assert!((f_stat - expected_f).abs() < 0.01);
}
#[test]
fn test_f_test_no_improvement() {
let ssr_r = 100.0;
let ssr_f = 100.0;
let n = 50;
let k_f = 4;
let k_r = 2;
let (f_stat, p_value, _, _) =
HypothesisTest::f_test_nested(ssr_r, ssr_f, n, k_f, k_r).unwrap();
assert!(f_stat.abs() < 1e-10);
assert!(p_value > 0.95);
}
#[test]
fn test_wald_test_specific_value() {
let beta = Array1::from(vec![2.0, 5.2]);
let cov_matrix = Array2::from_shape_vec((2, 2), vec![
0.25, 0.0,
0.0, 0.04,
]).unwrap();
let r = Array2::from_shape_vec((1, 2), vec![0.0, 1.0]).unwrap();
let q = Array1::from(vec![5.0]);
let (wald_stat, p_value, _) = HypothesisTest::wald_test(&beta, &cov_matrix, &r, &q).unwrap();
assert!((wald_stat - 1.0).abs() < 0.01);
assert!(p_value > 0.10); }
#[test]
fn test_bootstrap_reproduces_coefficients() {
let y = Array1::from(vec![3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0]);
let x = Array2::from_shape_vec((8, 2), vec![
1.0, 1.0,
1.0, 2.0,
1.0, 3.0,
1.0, 4.0,
1.0, 5.0,
1.0, 6.0,
1.0, 7.0,
1.0, 8.0,
]).unwrap();
let boot_coefs = Bootstrap::pairs_bootstrap(&y, &x, 5000).unwrap();
let mean_intercept: f64 = boot_coefs.column(0).mean().unwrap();
let mean_slope: f64 = boot_coefs.column(1).mean().unwrap();
assert!((mean_intercept - 1.0).abs() < 0.2);
assert!((mean_slope - 2.0).abs() < 0.2);
}