#!/bin/bash # Standalone test for DropoutScheduler logic verification cat > /tmp/test_dropout.rs << 'EOF' /// Adaptive dropout scheduler that decreases dropout rate over training #[derive(Debug, Clone)] pub struct DropoutScheduler { initial_rate: f64, final_rate: f64, decay_steps: usize, current_step: usize, } impl DropoutScheduler { pub fn new(initial_rate: f64, final_rate: f64, decay_steps: usize) -> Self { Self { initial_rate, final_rate, decay_steps, current_step: 0, } } pub fn get_rate(&self) -> f64 { if self.decay_steps == 0 { return self.final_rate; } let progress = (self.current_step as f64 / self.decay_steps as f64).min(1.0); self.initial_rate * (1.0 - progress) + self.final_rate * progress } pub fn step(&mut self, steps: usize) { self.current_step = self.current_step.saturating_add(steps); } pub fn current_step(&self) -> usize { self.current_step } } fn main() { println!("Testing DropoutScheduler...\n"); // Test 1: Basic creation let scheduler = DropoutScheduler::new(0.5, 0.1, 10000); println!("✓ Test 1: Creation - initial rate: {}", scheduler.get_rate()); assert!((scheduler.get_rate() - 0.5).abs() < 1e-6); // Test 2: Linear decay let mut scheduler = DropoutScheduler::new(0.5, 0.1, 10000); scheduler.step(2500); // 25% let rate_25 = scheduler.get_rate(); println!("✓ Test 2: 25% progress - rate: {:.6} (expected: 0.4)", rate_25); assert!((rate_25 - 0.4).abs() < 1e-6); scheduler.step(2500); // 50% let rate_50 = scheduler.get_rate(); println!("✓ Test 3: 50% progress - rate: {:.6} (expected: 0.3)", rate_50); assert!((rate_50 - 0.3).abs() < 1e-6); scheduler.step(2500); // 75% let rate_75 = scheduler.get_rate(); println!("✓ Test 4: 75% progress - rate: {:.6} (expected: 0.2)", rate_75); assert!((rate_75 - 0.2).abs() < 1e-6); scheduler.step(2500); // 100% println!("✓ Test 5: 100% progress - rate: {:.6} (expected: 0.1)", scheduler.get_rate()); assert!((scheduler.get_rate() - 0.1).abs() < 1e-6); // Test 3: Beyond decay steps scheduler.step(5000); // 150% println!("✓ Test 6: Beyond decay - rate stays at: {:.6}", scheduler.get_rate()); assert!((scheduler.get_rate() - 0.1).abs() < 1e-6); // Test 4: Step tracking let mut scheduler = DropoutScheduler::new(0.8, 0.2, 1000); assert_eq!(scheduler.current_step(), 0); scheduler.step(100); assert_eq!(scheduler.current_step(), 100); println!("✓ Test 7: Step tracking works correctly"); // Test 5: Zero decay steps edge case let scheduler = DropoutScheduler::new(0.5, 0.1, 0); println!("✓ Test 8: Zero decay steps - immediately at final: {:.6}", scheduler.get_rate()); assert!((scheduler.get_rate() - 0.1).abs() < 1e-6); // Test 6: Constant rate let mut scheduler = DropoutScheduler::new(0.3, 0.3, 1000); scheduler.step(500); println!("✓ Test 9: Constant rate - stays at: {:.6}", scheduler.get_rate()); assert!((scheduler.get_rate() - 0.3).abs() < 1e-6); // Test 7: Realistic schedule let mut scheduler = DropoutScheduler::new(0.5, 0.05, 100_000); scheduler.step(10_000); // Early training let early = scheduler.get_rate(); println!("✓ Test 10: Realistic early training (10k/100k) - rate: {:.6}", early); assert!(early > 0.4); scheduler.step(40_000); // Mid training (total 50k) let mid = scheduler.get_rate(); println!("✓ Test 11: Realistic mid training (50k/100k) - rate: {:.6}", mid); assert!((mid - 0.275).abs() < 0.01); scheduler.step(50_000); // Late training (total 100k) let late = scheduler.get_rate(); println!("✓ Test 12: Realistic late training (100k/100k) - rate: {:.6}", late); assert!((late - 0.05).abs() < 1e-6); println!("\n✅ All tests passed!"); } EOF rustc /tmp/test_dropout.rs -o /tmp/test_dropout && /tmp/test_dropout