use cambrian::meta::AlgoConfigBuilder; use cambrian::result::FinalReport; use cambrian::{self, meta, spec_util}; use cambrian::{sync_launch, termination::TerminationCriterion}; use float_cmp::approx_eq; use serde::Deserialize; use std::time::Duration; #[derive(Debug, Deserialize)] struct TestValue { x: f64, y: f64, } fn get_result( explicit_init_value_json: Option, termination_criteria: Vec, ) -> FinalReport { let spec_str = " x: type: real init: 1.0 scale: 0.1 y: type: real init: 1.0 scale: 0.1 "; let spec = spec_util::from_yaml_str(spec_str).unwrap(); let obj_func = meta::make_obj_func(|value| { let value: TestValue = TestValue::deserialize(value).unwrap(); let x = value.x; let y = value.y; Some(x * x + y * y) }); let algo_config = AlgoConfigBuilder::new().build().unwrap(); sync_launch::launch( spec, obj_func, algo_config, termination_criteria, explicit_init_value_json, true, None, ) .unwrap() } #[test] fn convergence() { let termination_criteria = vec![ TerminationCriterion::TargetObjFuncVal(1e-6), TerminationCriterion::TerminateAfter(Duration::from_secs(1)), ]; let result = get_result(None, termination_criteria); let value = TestValue::deserialize(result.best_seen.value).unwrap(); let obj_func_val = result.best_seen.obj_func_val; assert!(approx_eq!(f64, obj_func_val, 0.0, epsilon = 1e-2)); assert!(approx_eq!(f64, value.x, 0.0, epsilon = 1e-2)); assert!(approx_eq!(f64, value.y, 0.0, epsilon = 1e-2)); } #[test] fn explicit_initial_value_equivalence() { let termination_criteria = vec![TerminationCriterion::NumObjFuncEval(10)]; let json_str = r#"{"x": 1.0, "y": 1.0}"#; let json_val = serde_json::from_str(json_str).unwrap(); let result_explicit_init = get_result(Some(json_val), termination_criteria.clone()); let result_implicit_init = get_result(None, termination_criteria); assert_eq!( result_explicit_init.best_seen.obj_func_val, result_implicit_init.best_seen.obj_func_val ); }