use ml::hyperopt::adapters::ppo::PPOParams; use ml::hyperopt::traits::ParameterSpace; #[test] fn test_from_continuous_6_params() { let x = vec![ 1e-6_f64.ln(), // policy_lr 0.001_f64.ln(), // value_lr 0.2, // clip_epsilon 1.0, // value_loss_coeff 0.01_f64.ln(), // entropy_coeff 128.0, // minibatch_size ]; let params = PPOParams::from_continuous(&x).unwrap(); assert_eq!(params.minibatch_size, 128); } #[test] fn test_from_continuous_rejects_5_params() { let x = vec![1e-6_f64.ln(), 0.001_f64.ln(), 0.2, 1.0, 0.01_f64.ln()]; assert!(PPOParams::from_continuous(&x).is_err()); } #[test] fn test_to_continuous_returns_6_values() { let params = PPOParams::default(); let continuous = params.to_continuous(); assert_eq!(continuous.len(), 6); } #[test] fn test_roundtrip_conversion() { let original = PPOParams { policy_learning_rate: 1e-6, value_learning_rate: 0.002, clip_epsilon: 0.15, value_loss_coeff: 1.5, entropy_coeff: 0.02, minibatch_size: 192, }; let continuous = original.to_continuous(); let reconstructed = PPOParams::from_continuous(&continuous).unwrap(); assert_eq!(reconstructed.minibatch_size, 192); assert!((reconstructed.policy_learning_rate - 1e-6).abs() < 1e-9); } #[test] fn test_param_names_has_6_entries() { let names = PPOParams::param_names(); assert_eq!(names.len(), 6); assert_eq!(names[5], "minibatch_size"); } #[test] fn test_minibatch_size_clamped_to_vram_limits() { // Test lower bound let x = vec![1e-6_f64.ln(), 0.001_f64.ln(), 0.2, 1.0, 0.01_f64.ln(), 32.0]; let params = PPOParams::from_continuous(&x).unwrap(); assert_eq!(params.minibatch_size, 64); // Clamped to lower bound // Test upper bound let x = vec![ 1e-6_f64.ln(), 0.001_f64.ln(), 0.2, 1.0, 0.01_f64.ln(), 500.0, ]; let params = PPOParams::from_continuous(&x).unwrap(); assert_eq!(params.minibatch_size, 230); // Clamped to upper bound }