feat(bf16): 1722/1722 tests pass — ALL PASS, zero failures

Fix last 2 tests:
- action_masking: test used 81-action FactoredAction decoder for
  45-action mask. Fixed to use mask's own 5×9 exposure encoding.
- hyperopt bounds: test both Full (all ranges) and Fast (architecture
  fixed) phases. Implemented phase_fast override in continuous_bounds
  to pin hidden_dim_base, num_atoms, dueling_hidden_dim from TOML.

Final scorecard:
  ml-core:   300/300  (100%)
  ml-dqn:    359/359  (100%)
  ml-ppo:    168/168  (100%)
  ml:        895/895  (100%)
  Total:    1722/1722 (100%)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-03-28 13:11:47 +01:00
parent 3738677d46
commit 9b02f86fca
3 changed files with 69 additions and 45 deletions

View File

@@ -531,7 +531,7 @@ impl ParameterSpace for DQNParams {
let cw = b("c51_warmup_epochs", (3.0, 15.0));
let iq = b("iqn_lambda", (0.0, 1.0));
let bounds = vec![
let mut bounds = vec![
(lr.0.ln(), lr.1.ln()), // 0: learning_rate (log scale)
bs, // 1: batch_size
gm, // 2: gamma
@@ -556,6 +556,20 @@ impl ParameterSpace for DQNParams {
iq, // 21: iqn_lambda
];
// Phase Fast: fix architecture dims to single-point bounds
if crate::training_profile::get_hyperopt_phase() == crate::training_profile::HyperoptPhase::Fast {
if let Some(pf) = &hp.phase_fast {
let fix = |bounds: &mut Vec<(f64, f64)>, idx: usize, val: Option<f64>| {
if let Some(v) = val {
bounds[idx] = (v, v);
}
};
fix(&mut bounds, 10, pf.dueling_hidden_dim); // dueling_hidden_dim
fix(&mut bounds, 13, pf.num_atoms); // num_atoms
fix(&mut bounds, 18, pf.hidden_dim_base); // hidden_dim_base
}
}
bounds
}
@@ -3619,6 +3633,10 @@ mod tests {
#[test]
fn test_dqn_params_bounds() {
use crate::training_profile::{set_hyperopt_phase, HyperoptPhase};
// Test Full phase: all bounds must be ranges (lower < upper)
set_hyperopt_phase(HyperoptPhase::Full(vec![0.0; 22]));
let bounds = DQNParams::continuous_bounds();
assert_eq!(bounds.len(), 22); // 22D consolidated search space
@@ -3637,11 +3655,18 @@ mod tests {
assert!(lr_min > 0.0 && lr_min < 1e-3, "Learning rate lower bound should be small, got {:.2e}", lr_min);
assert!(lr_max >= 1e-4 && lr_max <= 1e-2, "Learning rate upper bound should be reasonable, got {:.2e}", lr_max);
// Check all bounds have valid ranges (lower < upper)
// Exact values may be overridden by HyperoptProfile YAML
for (i, (lo, hi)) in bounds.iter().enumerate() {
assert!(lo < hi, "Bound {i}: lower ({lo}) must be < upper ({hi})");
assert!(lo < hi, "Full phase: Bound {i}: lower ({lo}) must be < upper ({hi})");
}
// Test Fast phase: architecture dims must be fixed (single-point bounds)
set_hyperopt_phase(HyperoptPhase::Fast);
let fast_bounds = DQNParams::continuous_bounds();
assert_eq!(fast_bounds[18].0, fast_bounds[18].1, "Fast: hidden_dim_base must be fixed");
assert_eq!(fast_bounds[13].0, fast_bounds[13].1, "Fast: num_atoms must be fixed");
assert_eq!(fast_bounds[10].0, fast_bounds[10].1, "Fast: dueling_hidden_dim must be fixed");
// Learning rate must still be a range in Fast phase
assert_ne!(fast_bounds[0].0, fast_bounds[0].1, "Fast: learning_rate must still be searchable");
}
#[test]