fix(sampler): return None instead of panicking on parameter type mismatch in CompletedTrial::get()
This commit is contained in:
+6
-12
@@ -121,13 +121,9 @@ impl<V> CompletedTrial<V> {
|
||||
/// Looks up the parameter by its unique id and casts the stored
|
||||
/// [`ParamValue`] to the parameter's typed value.
|
||||
///
|
||||
/// Returns `None` if the parameter was not used in this trial.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the stored value is incompatible with the parameter type
|
||||
/// (e.g., a `Float` value stored for an `IntParam`). This indicates
|
||||
/// a bug in the program, not a runtime error.
|
||||
/// Returns `None` if the parameter was not used in this trial or if
|
||||
/// the stored value is incompatible with the parameter type (e.g., a
|
||||
/// `Float` value stored for an `IntParam`).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -150,11 +146,9 @@ impl<V> CompletedTrial<V> {
|
||||
/// assert!((-10.0..=10.0).contains(&x_val));
|
||||
/// ```
|
||||
pub fn get<P: Parameter>(&self, param: &P) -> Option<P::Value> {
|
||||
self.params.get(¶m.id()).map(|v| {
|
||||
param
|
||||
.cast_param_value(v)
|
||||
.expect("parameter type mismatch: stored value incompatible with parameter")
|
||||
})
|
||||
self.params
|
||||
.get(¶m.id())
|
||||
.and_then(|v| param.cast_param_value(v).ok())
|
||||
}
|
||||
|
||||
/// Returns `true` if all constraints are satisfied (values <= 0.0).
|
||||
|
||||
@@ -258,6 +258,28 @@ fn test_completed_trial_get() {
|
||||
assert!((1..=10).contains(&n_val));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_completed_trial_get_type_mismatch_returns_none() {
|
||||
let study: Study<f64> = Study::new(Direction::Minimize);
|
||||
let int_param = IntParam::new(1, 10).name("x");
|
||||
|
||||
study
|
||||
.optimize(1, |trial: &mut optimizer::Trial| {
|
||||
let n = int_param.suggest(trial)?;
|
||||
Ok::<_, Error>(n as f64)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let best = study.best_trial().unwrap();
|
||||
|
||||
// The stored value is ParamValue::Int, but we query with a FloatParam.
|
||||
let wrong_type = FloatParam::new(0.0, 100.0).name("x");
|
||||
assert!(
|
||||
best.get(&wrong_type).is_none(),
|
||||
"type mismatch should return None, not panic"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_single_value_int_range() {
|
||||
let param = IntParam::new(5, 5);
|
||||
|
||||
Reference in New Issue
Block a user