fix: update CI tests for expanded search space (45D) and wider v_range (±240)

- dqn_action_collapse_fix_test: search space grew from 39D to 45D
  (added c51_warmup, her_ratio, curiosity, cvar, dt_pretrain). Updated
  assertions to use >= 39 and dynamic index lookup for cql_alpha.
- training_stability: Q-value assertion widened from 2.5 to 300.0
  to match v_range ±240 (computed from reward_scale=10, gamma=0.95).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-03-25 21:01:00 +01:00
parent b555aafe77
commit 5a35741da3
2 changed files with 16 additions and 20 deletions

View File

@@ -313,9 +313,11 @@ fn test_50_epoch_convergence() -> anyhow::Result<()> {
// ═══════════════════════════════════════════════════════════
let avg_q = metrics.additional_metrics.get("avg_q_value").copied().unwrap_or(0.0);
assert_finite(avg_q, "avg_q_value");
// v_range is now ±240 (computed from reward_scale=10, gamma=0.95).
// Q-values should stay within the C51 support range with some margin.
assert!(
avg_q.abs() < 2.5,
"ANOMALY 3: Q-value {:.4} saturating v_range ±2.0. C51 atoms exhausted.",
avg_q.abs() < 300.0,
"ANOMALY 3: Q-value {:.4} exceeding v_range ±240. C51 atoms exhausted.",
avg_q
);

View File

@@ -217,31 +217,24 @@ fn test_hyperopt_26d_includes_cql_alpha() {
use ml::hyperopt::traits::ParameterSpace;
let bounds = DQNParams::continuous_bounds();
assert_eq!(
bounds.len(),
39,
"Search space should be 39D (31 base + 8 reward/policy weights), got {}D",
assert!(
bounds.len() >= 39,
"Search space should be >= 39D, got {}D",
bounds.len()
);
let names = DQNParams::param_names();
assert_eq!(
names.len(),
39,
"param_names should return 39 entries, got {}",
names.len()
bounds.len(),
"param_names length should match continuous_bounds length: {} vs {}",
names.len(), bounds.len()
);
// cql_alpha at index 22
assert_eq!(
names.get(22).copied(),
Some("cql_alpha"),
"Parameter 22 should be cql_alpha, got {:?}",
names.get(22)
);
// cql_alpha bounds: (0.0, 1.0) — full offline-RL range
let (lo, hi) = bounds.get(22).copied().unwrap_or((0.0, 0.0));
// cql_alpha must exist in search space with bounds (0.0, 1.0)
let cql_idx = names.iter().position(|&n| n == "cql_alpha")
.expect("cql_alpha should be in param_names");
let (lo, hi) = bounds[cql_idx];
assert!(
(lo - 0.0).abs() < 1e-6 && (hi - 1.0).abs() < 1e-6,
"cql_alpha bounds should be (0.0, 1.0), got ({}, {})",
@@ -289,7 +282,8 @@ fn test_hyperopt_cql_alpha_round_trip() {
params.cql_alpha = 0.25;
let continuous = params.to_continuous();
assert_eq!(continuous.len(), 39);
let bounds = DQNParams::continuous_bounds();
assert_eq!(continuous.len(), bounds.len(), "to_continuous length should match bounds");
let reconstructed =
DQNParams::from_continuous(&continuous).expect("from_continuous should succeed");