use blr_active::active_learning::acquisition::recommend_next_samples;
#[test]
fn test_acquisition_top_k_are_highest_variance() {
let grid: Vec<f64> = (0..10).map(|i| i as f64).collect();
let stds: Vec<f64> = grid
.iter()
.map(|&x| -(x - 7.0).powi(2) / 10.0 + 1.0)
.collect();
let recs = recommend_next_samples(&grid, &stds, &[], 3, 0.0);
assert_eq!(recs.len(), 3);
assert!(
(recs[0].input_value - 7.0).abs() < 0.5,
"peak should be first: {:?}",
recs[0]
);
for w in recs.windows(2) {
assert!(
w[0].expected_std >= w[1].expected_std,
"recommendations not sorted: {} vs {}",
w[0].expected_std,
w[1].expected_std
);
}
}
#[test]
fn test_exclusion_radius_no_near_existing() {
let grid = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
let stds = vec![0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.05];
let existing = vec![1.0]; let recs = recommend_next_samples(&grid, &stds, &existing, 5, 1.5);
for r in &recs {
for s in &existing {
assert!(
(r.input_value - s).abs() > 1.5,
"recommended {:.1} is too close to existing {:.1}",
r.input_value,
s
);
}
}
}
#[test]
fn test_ranking_one_indexed() {
let grid = vec![1.0, 2.0, 3.0];
let stds = vec![0.5, 0.9, 0.3];
let recs = recommend_next_samples(&grid, &stds, &[], 3, 0.0);
for (i, r) in recs.iter().enumerate() {
assert_eq!(r.rank, i + 1);
}
}
#[test]
fn test_fewer_than_k_available() {
let grid = vec![1.0, 2.0];
let stds = vec![0.5, 0.9];
let recs = recommend_next_samples(&grid, &stds, &[], 5, 0.0);
assert_eq!(recs.len(), 2, "should return all 2 available");
}
#[test]
fn test_integration_with_algorithm1_output() {
use blr_active::active_learning::variance::posterior_std_grid;
let d = 2usize;
let sigma_cov = vec![0.5, 0.0, 0.0, 0.1];
let feature_fn = |x: f64| vec![1.0, x];
let (grid, stds) = posterior_std_grid(1.0, &sigma_cov, d, 0.0, 10.0, 50, &feature_fn);
let recs = recommend_next_samples(&grid, &stds, &[5.0], 3, 0.5);
assert!(!recs.is_empty() || grid.is_empty());
for r in &recs {
assert!(r.expected_std >= 0.0);
assert!(r.input_value.is_finite());
}
}