use crate::feature_selection::mrmr::mrmr_error::MrmrError;
use crate::mrmr::mrmr_utils;
use deep_causality_tensor::CausalTensor;
#[test]
fn pearson_large_offset_retains_affine_correlation() {
let tensor = CausalTensor::new(
vec![1e12, 3.0, 1e12 + 1.0, 5.0, 1e12 + 2.0, 7.0, 1e12 + 3.0, 9.0],
vec![4, 2],
)
.unwrap();
let (r, n) = mrmr_utils::pearson_correlation(&tensor, 0, 1).unwrap();
assert!((r - 1.0).abs() < 1e-14);
assert_eq!(n, 4.0);
}
#[test]
fn pearson_infinity_is_a_calculation_error() {
let tensor = CausalTensor::new(vec![1.0, 2.0, 2.0, f64::INFINITY], vec![2, 2]).unwrap();
assert!(matches!(
mrmr_utils::pearson_correlation(&tensor, 0, 1),
Err(MrmrError::CalculationError(_))
));
}
#[test]
fn pearson_drops_a_nan_pair_rather_than_refusing_the_column() {
let tensor = CausalTensor::new(
vec![1.0, 2.0, 2.0, 4.0, f64::NAN, 99.0, 4.0, 8.0],
vec![4, 2],
)
.unwrap();
let (r, n) = mrmr_utils::pearson_correlation(&tensor, 0, 1).unwrap();
assert_eq!(n, 3.0, "the NaN row is deleted, leaving three pairs");
assert!((r - 1.0).abs() < 1e-14, "expected r = 1, got {r}");
}
#[test]
fn test_pearson_correlation() {
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 4.0, 3.0, 2.0, 1.0];
let shape = vec![2, 5];
let tensor = CausalTensor::new(data, shape).unwrap();
let (corr, _) = mrmr_utils::pearson_correlation(&tensor, 0, 4).unwrap();
assert!((corr - (-1.0)).abs() < 1e-9);
}
#[test]
fn test_pearson_correlation_non_2d_tensor() {
let data = vec![1.0, 2.0, 3.0, 4.0];
let shape = vec![4]; let tensor = CausalTensor::new(data, shape).unwrap();
let result = mrmr_utils::pearson_correlation(&tensor, 0, 1);
assert!(matches!(result, Err(MrmrError::InvalidInput(_))));
assert_eq!(
result.unwrap_err().to_string(),
"Invalid input: Input tensor must be 2-dimensional"
);
}
#[test]
fn test_pearson_correlation_index_out_of_bounds() {
let data = vec![1.0, 2.0, 3.0, 4.0];
let shape = vec![2, 2];
let tensor = CausalTensor::new(data, shape).unwrap();
let result = mrmr_utils::pearson_correlation(&tensor, 0, 2);
assert!(matches!(result, Err(MrmrError::InvalidInput(_))));
assert_eq!(
result.unwrap_err().to_string(),
"Invalid input: Column index out of bounds"
);
}
#[test]
fn test_pearson_correlation_sample_too_small() {
let data = vec![1.0, 2.0];
let shape = vec![1, 2]; let tensor = CausalTensor::new(data, shape).unwrap();
let result = mrmr_utils::pearson_correlation(&tensor, 0, 1);
assert!(matches!(result, Err(MrmrError::SampleTooSmall(2))));
assert_eq!(
result.unwrap_err().to_string(),
"Sample size is too small. At least 2 samples are required."
);
}
#[test]
fn test_f_statistic() {
let data = vec![1.0, 2.0, 2.0, 4.0, 3.0, 6.0];
let shape = vec![3, 2];
let tensor = CausalTensor::new(data, shape).unwrap();
let f_stat = mrmr_utils::f_statistic(&tensor, 0, 1).unwrap();
assert_eq!(f_stat, 1e12);
}
#[test]
fn test_f_statistic_sample_too_small() {
let data = vec![1.0, 2.0, 3.0, 4.0];
let shape = vec![2, 2]; let tensor = CausalTensor::new(data, shape).unwrap();
let result = mrmr_utils::f_statistic(&tensor, 0, 1);
assert!(matches!(result, Err(MrmrError::SampleTooSmall(3))));
assert_eq!(
result.unwrap_err().to_string(),
"Sample size is too small. At least 3 samples are required."
);
}
#[test]
fn test_f_statistic_non_2d_tensor() {
let data = vec![1.0, 2.0, 3.0, 4.0];
let shape = vec![4]; let tensor = CausalTensor::new(data, shape).unwrap();
let result = mrmr_utils::f_statistic(&tensor, 0, 1);
assert!(matches!(result, Err(MrmrError::InvalidInput(_))));
assert_eq!(
result.unwrap_err().to_string(),
"Invalid input: Input tensor must be 2-dimensional"
);
}
#[test]
fn test_f_statistic_index_out_of_bounds() {
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let shape = vec![3, 2];
let tensor = CausalTensor::new(data, shape).unwrap();
let result = mrmr_utils::f_statistic(&tensor, 0, 2);
assert!(matches!(result, Err(MrmrError::InvalidInput(_))));
assert_eq!(
result.unwrap_err().to_string(),
"Invalid input: Column index out of bounds"
);
}