Files
foxhunt/ml/tests/test_noisy_networks_integration.rs
jgrusewski 7f53baff8f feat(ml): DQN improvements and fix downstream compilation errors
DQN changes: improved attention, ensemble networks, hindsight replay,
mixed precision, noisy layers, prioritized replay, RMSNorm, hyperopt
adapter updates, and trainer enhancements with weight_decay support.

Fix downstream crates broken by DQNConfig changes:
- trading_service: import agent::DQNConfig directly, add weight_decay field
- backtesting_service: update feature vector size 54 -> 51
- ml_training_service: convert compile-time sqlx macro to runtime query_as
- pre-commit hook: add SQLX_OFFLINE=true for DB-free compilation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:07:48 +01:00

106 lines
2.8 KiB
Rust

//! Integration test for Noisy Networks in DQN
//!
//! Verifies that:
//! 1. NoisyLinear layers are correctly instantiated when use_noisy_nets=true
//! 2. reset_noise() is called before action selection
//! 3. Epsilon-greedy is disabled when using noisy nets
//! 4. Q-values change after reset_noise() (noise is working)
use ml::dqn::dqn::{DQNConfig, DQN};
#[test]
fn test_noisy_networks_enabled() -> Result<(), Box<dyn std::error::Error>> {
let config = DQNConfig {
state_dim: 54,
num_actions: 45,
hidden_dims: vec![128, 64],
use_noisy_nets: true,
noisy_sigma_init: 0.5,
warmup_steps: 0, // Disable warmup for testing
..Default::default()
};
let mut dqn = DQN::new(config)?;
// Verify noisy nets are enabled
assert!(dqn.is_using_noisy_nets());
// Create dummy state
let state = vec![0.0_f32; 54];
// Select action - this should call reset_noise() internally
let action1 = dqn.select_action(&state)?;
let action2 = dqn.select_action(&state)?;
// Actions may differ due to noise (not guaranteed, but highly likely)
// The important thing is that this doesn't panic
println!("Action 1: {:?}, Action 2: {:?}", action1, action2);
Ok(())
}
#[test]
fn test_noisy_networks_disabled() -> Result<(), Box<dyn std::error::Error>> {
let config = DQNConfig {
state_dim: 54,
num_actions: 45,
hidden_dims: vec![128, 64],
use_noisy_nets: false, // Disabled
warmup_steps: 0,
..Default::default()
};
let mut dqn = DQN::new(config)?;
// Verify noisy nets are disabled
assert!(!dqn.is_using_noisy_nets());
// Create dummy state
let state = vec![0.0_f32; 54];
// Select action - should use standard epsilon-greedy
let _action = dqn.select_action(&state)?;
Ok(())
}
#[test]
fn test_noisy_networks_epsilon_override() -> Result<(), Box<dyn std::error::Error>> {
let config = DQNConfig {
state_dim: 54,
num_actions: 45,
hidden_dims: vec![128, 64],
use_noisy_nets: true,
epsilon_start: 1.0, // Should be ignored when noisy nets enabled
epsilon_end: 0.01,
warmup_steps: 0,
..Default::default()
};
let mut dqn = DQN::new(config)?;
// Create dummy state
let state = vec![0.0_f32; 54];
// Select multiple actions
// With epsilon=0 (effective), we should get greedy actions (with learned noise)
for _ in 0..10 {
let _action = dqn.select_action(&state)?;
}
Ok(())
}
#[test]
fn test_noisy_networks_rainbow_default() -> Result<(), Box<dyn std::error::Error>> {
// Rainbow DQN should have noisy nets enabled by default
let config = DQNConfig::rainbow();
let dqn = DQN::new(config)?;
// Verify Rainbow DQN has noisy nets
assert!(dqn.is_using_noisy_nets());
Ok(())
}