#[test]
fn test_tpe_model_phase_with_log_scale() {
let space: SearchSpace<RF> = SearchSpace::new().add_log_scale(
RF::NEstimators,
crate::automl::LogScale {
low: 1e-4,
high: 1.0,
},
);
let mut tpe = TPE::new(100).with_startup_trials(3).with_seed(42);
for i in 0..3 {
let mut values = std::collections::HashMap::new();
values.insert(RF::NEstimators, ParamValue::Float(0.001 * (i as f64 + 1.0)));
let trial = Trial { values };
let result = TrialResult {
trial,
score: i as f64 * 0.3,
metrics: std::collections::HashMap::new(),
};
tpe.update(&[result]);
}
assert!(tpe.should_use_model());
let trials = tpe.suggest(&space, 2);
assert_eq!(trials.len(), 2);
}
#[test]
fn test_tpe_model_phase_with_categorical() {
let space: SearchSpace<RF> =
SearchSpace::new().add_categorical(RF::MaxFeatures, ["sqrt", "log2", "auto"]);
let mut tpe = TPE::new(100).with_startup_trials(3).with_seed(42);
for i in 0..3 {
let mut values = std::collections::HashMap::new();
let choices = ["sqrt", "log2", "auto"];
values.insert(
RF::MaxFeatures,
ParamValue::String(choices[i % 3].to_string()),
);
let trial = Trial { values };
let result = TrialResult {
trial,
score: i as f64 * 0.2,
metrics: std::collections::HashMap::new(),
};
tpe.update(&[result]);
}
assert!(tpe.should_use_model());
let trials = tpe.suggest(&space, 3);
assert_eq!(trials.len(), 3);
for trial in &trials {
let v = trial.get(&RF::MaxFeatures).expect("should have value");
let s = v.as_str().expect("should be string");
assert!(
["sqrt", "log2", "auto"].contains(&s),
"Categorical value '{s}' not in choices"
);
}
}
#[test]
fn test_tpe_zero_remaining() {
let space: SearchSpace<RF> = SearchSpace::new().add(RF::NEstimators, 10..100);
let mut tpe = TPE::new(0);
let trials = tpe.suggest(&space, 10);
assert!(trials.is_empty());
}
#[test]
fn test_tpe_with_startup_trials() {
let tpe = TPE::new(50).with_startup_trials(20);
assert_eq!(tpe.config.n_startup_trials, 20);
}
#[test]
fn test_kde_density_multiple_samples() {
let samples = vec![0.2, 0.4, 0.6, 0.8];
let bw = TPE::compute_bandwidth(&samples);
let density_center = TPE::kde_density(&samples, 0.5, bw);
assert!(density_center > 0.0);
let density_far = TPE::kde_density(&samples, 10.0, bw);
assert!(density_center > density_far);
}
#[test]
fn test_tpe_suggest_empty_space_with_model() {
let space: SearchSpace<RF> = SearchSpace::new();
let mut tpe = TPE::new(100).with_startup_trials(0).with_seed(42);
let trials = tpe.suggest(&space, 3);
assert_eq!(trials.len(), 3);
}
#[test]
fn test_split_observations_with_nan_scores() {
let mut tpe = TPE::new(100).with_gamma(0.5);
tpe.history.push(Observation {
values: vec![0.3],
score: f64::NAN,
});
tpe.history.push(Observation {
values: vec![0.5],
score: 0.5,
});
tpe.history.push(Observation {
values: vec![0.7],
score: 0.8,
});
let (good, bad) = tpe.split_observations();
assert_eq!(good.len() + bad.len(), 3);
}