use super::SVCRbf;
use crate::classification::svc_rbf_sklearn_fixture as fix;
use crate::primitives::Matrix;
fn train_data() -> (Matrix<f32>, Vec<usize>) {
let x = Matrix::from_vec(fix::N_TRAIN, 2, fix::TRAIN_X.to_vec()).expect("train matrix");
let y = fix::TRAIN_Y.to_vec();
(x, y)
}
fn grid_data() -> Matrix<f32> {
Matrix::from_vec(fix::N_GRID, 2, fix::GRID_X.to_vec()).expect("grid matrix")
}
#[test]
fn falsify_svc_rbf_001_sklearn_parity_grid() {
let (x, y) = train_data();
let grid = grid_data();
let mut svc = SVCRbf::new()
.with_gamma(fix::GAMMA)
.with_c(fix::C)
.with_max_iter(1000);
svc.fit(&x, &y).expect("fit");
let preds = svc.predict(&grid).expect("predict grid");
assert_eq!(
preds.len(),
fix::N_GRID,
"prediction count must match grid size"
);
let agree = preds
.iter()
.zip(fix::SKLEARN_GRID_PRED.iter())
.filter(|(a, b)| a == b)
.count();
let frac = agree as f32 / fix::N_GRID as f32;
assert!(
frac >= 0.90,
"FALSIFIED SVC-RBF-001: only {agree}/{} grid points ({frac:.3}) agree with \
pinned sklearn SVC(rbf) — RBF decision boundary diverges from reference",
fix::N_GRID
);
}
#[test]
fn falsify_svc_rbf_002_xor_train_accuracy() {
let (x, y) = train_data();
let mut svc = SVCRbf::new().with_gamma(fix::GAMMA).with_c(fix::C);
svc.fit(&x, &y).expect("fit");
let acc = svc.score(&x, &y).expect("score");
assert!(
acc >= 0.95,
"FALSIFIED SVC-RBF-002: XOR train accuracy {acc:.3} < 0.95 — RBF kernel not \
separating non-linear classes"
);
}
#[test]
fn falsify_svc_rbf_003_canonical_xor() {
let x = Matrix::from_vec(4, 2, vec![0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]).expect("xor");
let y = vec![0_usize, 1, 1, 0];
let mut svc = SVCRbf::new().with_gamma(1.0).with_c(10.0);
svc.fit(&x, &y).expect("fit");
let preds = svc.predict(&x).expect("predict");
assert_eq!(
preds, y,
"FALSIFIED SVC-RBF-003: canonical XOR not classified exactly"
);
}
#[test]
fn falsify_svc_rbf_004_deterministic() {
let (x, y) = train_data();
let grid = grid_data();
let mut a = SVCRbf::new().with_gamma(fix::GAMMA).with_c(fix::C);
a.fit(&x, &y).expect("fit a");
let pa = a.predict(&grid).expect("predict a");
let mut b = SVCRbf::new().with_gamma(fix::GAMMA).with_c(fix::C);
b.fit(&x, &y).expect("fit b");
let pb = b.predict(&grid).expect("predict b");
assert_eq!(
pa, pb,
"FALSIFIED SVC-RBF-004: same params produced different predictions"
);
}
#[test]
fn falsify_svc_rbf_005_label_subset_and_sign() {
let (x, y) = train_data();
let grid = grid_data();
let mut svc = SVCRbf::new().with_gamma(fix::GAMMA).with_c(fix::C);
svc.fit(&x, &y).expect("fit");
let preds = svc.predict(&grid).expect("predict");
for &p in &preds {
assert!(
p == 0 || p == 1,
"FALSIFIED SVC-RBF-005: predicted label {p} not in training label set"
);
}
let df = svc.decision_function(&grid).expect("decision_function");
for (i, &p) in preds.iter().enumerate() {
let expected = usize::from(df[i] > 0.0);
assert_eq!(
p, expected,
"FALSIFIED SVC-RBF-005: predict()/decision_function() sign disagree at {i}"
);
}
}
#[test]
fn falsify_svc_rbf_006_error_handling() {
let x = Matrix::from_vec(3, 2, vec![0.0, 0.0, 1.0, 1.0, 2.0, 2.0]).expect("x");
let mut svc = SVCRbf::new();
assert!(
svc.fit(&x, &[0, 0, 0]).is_err(),
"FALSIFIED SVC-RBF-006: single-class fit should error"
);
assert!(
svc.fit(&x, &[0, 1]).is_err(),
"FALSIFIED SVC-RBF-006: X/y length mismatch should error"
);
let unfitted = SVCRbf::new();
assert!(
unfitted.predict(&x).is_err(),
"FALSIFIED SVC-RBF-006: predict before fit should error"
);
}
#[test]
fn falsify_svc_rbf_007_estimator_trait_parity() {
use crate::primitives::Vector;
use crate::traits::Estimator;
let (x, _) = train_data();
let y_f = Vector::from_vec(fix::TRAIN_Y.iter().map(|&l| l as f32).collect());
let grid = grid_data();
let mut svc = SVCRbf::new().with_gamma(fix::GAMMA).with_c(fix::C);
Estimator::fit(&mut svc, &x, &y_f).expect("fit via trait");
let preds = Estimator::predict(&svc, &grid);
let agree = preds
.as_slice()
.iter()
.zip(fix::SKLEARN_GRID_PRED.iter())
.filter(|(&a, &b)| a.round() as usize == b)
.count();
let frac = agree as f32 / fix::N_GRID as f32;
assert!(
frac >= 0.90,
"FALSIFIED SVC-RBF-007: Estimator-trait grid parity {frac:.3} < 0.90"
);
}