use scirs2_core::ndarray::{array, Array2};
use sklears::metrics::classification::accuracy_score;
use sklears::neighbors::KNeighborsClassifier;
use sklears::prelude::*;
use sklears::traits::PredictProba;
use sklears::utils::data_generation::make_classification;
#[test]
#[allow(non_snake_case)]
fn test_simple_classification_pipeline() {
let (X, y) = make_classification(50, 4, 3, None, None, 0.0, 1.0, Some(42))
.expect("operation should succeed");
let X_scaled = X.clone();
let classifier = KNeighborsClassifier::new(3);
let fitted_classifier = classifier
.fit(&X_scaled, &y)
.expect("model fitting should succeed");
let predictions = fitted_classifier
.predict(&X_scaled)
.expect("prediction should succeed");
let accuracy = accuracy_score(&y, &predictions).expect("operation should succeed");
assert!(
accuracy > 0.6,
"Accuracy should be reasonable, got {}",
accuracy
);
assert_eq!(predictions.len(), y.len());
for &pred in predictions.iter() {
assert!(
(0..=2).contains(&pred),
"Predicted class {} should be in [0, 2]",
pred
);
}
}
#[test]
#[allow(non_snake_case)]
fn test_knn_probability_predictions() {
let (X, y) = make_classification(30, 3, 2, None, None, 0.0, 1.0, Some(42))
.expect("operation should succeed");
let classifier = KNeighborsClassifier::new(5);
let fitted_classifier = classifier
.fit(&X, &y)
.expect("model fitting should succeed");
let probabilities = fitted_classifier
.predict_proba(&X)
.expect("operation should succeed");
assert_eq!(probabilities.nrows(), X.nrows());
assert_eq!(probabilities.ncols(), 2);
for i in 0..probabilities.nrows() {
let row_sum: f64 = probabilities.row(i).sum();
assert!(
(row_sum - 1.0).abs() < 1e-10,
"Probabilities should sum to 1, got {}",
row_sum
);
}
for &prob in probabilities.iter() {
assert!(
(0.0..=1.0).contains(&prob),
"Probability should be in [0, 1], got {}",
prob
);
}
}
#[test]
#[allow(non_snake_case)]
#[ignore = "StandardScaler not available in facade crate"]
fn test_preprocessing_consistency() {
}
#[test]
#[allow(non_snake_case)]
fn test_data_generation_functions() {
let (X, y) = make_classification(20, 3, 2, None, None, 0.0, 1.0, Some(42))
.expect("operation should succeed");
assert_eq!(X.shape(), &[20, 3]);
assert_eq!(y.len(), 20);
let mut classes: Vec<i32> = y.iter().copied().collect();
classes.sort_unstable();
classes.dedup();
assert_eq!(classes.len(), 2);
let (X2, y2) = make_classification(20, 3, 2, None, None, 0.0, 1.0, Some(42))
.expect("operation should succeed");
assert_eq!(X, X2);
assert_eq!(y, y2);
}
#[test]
#[allow(non_snake_case)]
#[ignore = "StandardScaler not available in facade crate"]
fn test_cross_crate_compatibility() {
let (X, y) = make_classification(30, 4, 3, None, None, 0.0, 1.0, Some(42))
.expect("operation should succeed");
let X_scaled = X.clone();
let classifier = KNeighborsClassifier::new(3);
let fitted_classifier = classifier
.fit(&X_scaled, &y)
.expect("model fitting should succeed");
let predictions = fitted_classifier
.predict(&X_scaled)
.expect("prediction should succeed");
let accuracy = accuracy_score(&y, &predictions).expect("operation should succeed");
assert!(accuracy > 0.6, "Should achieve reasonable accuracy");
assert_eq!(predictions.len(), y.len());
}
#[test]
#[allow(non_snake_case)]
fn test_error_handling() {
let X_train = Array2::from_shape_vec((3, 2), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
.expect("shape and data length should match");
let y_train = array![0, 1, 2];
let X_test = Array2::from_shape_vec((2, 3), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
.expect("shape and data length should match");
let classifier = KNeighborsClassifier::new(2);
let fitted_classifier = classifier
.fit(&X_train, &y_train)
.expect("model fitting should succeed");
let result = fitted_classifier.predict(&X_test);
assert!(result.is_err(), "Should fail with dimension mismatch");
}