Files
wifi-densepose/crates/ruvector-mincut-gated-transformer/tests/determinism_extended.rs
ruv d803bfe2b1 Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector
git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
2026-02-28 14:39:40 -05:00

611 lines
18 KiB
Rust

//! Extended determinism and reproducibility tests.
//!
//! Tests determinism across all configurations, features, and edge cases.
use ruvector_mincut_gated_transformer::{
GateDecision, GatePacket, GatePolicy, InferInput, InferOutput, MincutGatedTransformer,
QuantizedWeights, SpikePacket, TransformerConfig,
};
fn create_transformer(config: TransformerConfig, policy: GatePolicy) -> MincutGatedTransformer {
let weights = QuantizedWeights::empty(&config);
MincutGatedTransformer::new(config, policy, weights).unwrap()
}
// ============ Cross-Configuration Determinism ============
#[test]
fn test_determinism_baseline_config() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
};
let tokens: Vec<u32> = (0..32).collect();
let input = InferInput::from_tokens(&tokens, gate);
// Run 10 times
let results: Vec<Vec<i32>> = (0..10)
.map(|_| {
let mut logits = vec![0i32; config.logits as usize];
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
transformer.reset();
logits
})
.collect();
// All results should be identical
for i in 1..results.len() {
assert_eq!(results[0], results[i], "Run {} differs from run 0", i);
}
}
#[test]
fn test_determinism_micro_config() {
let config = TransformerConfig::micro();
let policy = GatePolicy::default();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
};
let tokens: Vec<u32> = (0..16).collect();
let input = InferInput::from_tokens(&tokens, gate);
let mut logits1 = vec![0i32; config.logits as usize];
let mut logits2 = vec![0i32; config.logits as usize];
{
let mut output = InferOutput::new(&mut logits1);
transformer.infer(&input, &mut output).unwrap();
}
transformer.reset();
{
let mut output = InferOutput::new(&mut logits2);
transformer.infer(&input, &mut output).unwrap();
}
assert_eq!(logits1, logits2);
}
// ============ Policy Determinism ============
#[test]
fn test_determinism_conservative_policy() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::conservative();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 45,
lambda_prev: 50,
boundary_edges: 8,
boundary_concentration_q15: 15000,
partition_count: 6,
flags: 0,
};
let tokens: Vec<u32> = (0..32).collect();
let input = InferInput::from_tokens(&tokens, gate);
let witness1;
{
let mut logits = vec![0i32; config.logits as usize];
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
witness1 = output.witness;
}
transformer.reset();
let witness2;
{
let mut logits = vec![0i32; config.logits as usize];
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
witness2 = output.witness;
}
assert_eq!(witness1.decision, witness2.decision);
assert_eq!(witness1.reason, witness2.reason);
}
#[test]
fn test_determinism_permissive_policy() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::permissive();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 25,
lambda_prev: 35,
boundary_edges: 40,
boundary_concentration_q15: 20000,
partition_count: 15,
flags: 0,
};
let tokens: Vec<u32> = (0..32).collect();
let input = InferInput::from_tokens(&tokens, gate);
let mut results: Vec<(GateDecision, u8)> = Vec::new();
for _ in 0..5 {
let mut logits = vec![0i32; config.logits as usize];
let decision;
let tier;
{
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
decision = output.witness.decision;
tier = output.stats.tier;
}
transformer.reset();
results.push((decision, tier));
}
// All should be identical
for i in 1..results.len() {
assert_eq!(results[0].0, results[i].0);
assert_eq!(results[0].1, results[i].1);
}
}
// ============ Tier Determinism ============
#[test]
fn test_determinism_across_all_tiers() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
// Test gates for each tier
let tier_gates = vec![
// Tier 0
GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
},
// Tier 1
GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 30,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
},
// Tier 2
GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: GatePacket::FLAG_FORCE_SAFE,
},
// Tier 3
GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: GatePacket::FLAG_SKIP,
},
];
let tokens: Vec<u32> = (0..32).collect();
for gate in tier_gates {
let mut transformer = create_transformer(config.clone(), policy.clone());
let input = InferInput::from_tokens(&tokens, gate);
let mut results = Vec::new();
for _ in 0..3 {
let mut logits = vec![0i32; config.logits as usize];
let witness;
let stats;
{
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
witness = output.witness;
stats = output.stats;
}
results.push((logits, witness, stats));
transformer.reset();
}
// All runs should be identical
for i in 1..results.len() {
assert_eq!(results[0].0, results[i].0, "Logits differ");
assert_eq!(results[0].1.decision, results[i].1.decision);
assert_eq!(results[0].2.tier, results[i].2.tier);
}
}
}
// ============ Spike Determinism ============
#[test]
fn test_determinism_with_spikes() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
};
let spike = SpikePacket {
fired: 1,
rate_q15: 20000,
novelty_q15: 15000,
top_len: 4,
top_idx: [5, 10, 15, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
top_w_q15: [16384, 12288, 8192, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
flags: SpikePacket::FLAG_SPARSE_MASK,
};
let tokens: Vec<u32> = (0..32).collect();
let input = InferInput::from_tokens(&tokens, gate).with_spikes(spike);
let mut results: Vec<(Vec<i32>, u8)> = Vec::new();
for _ in 0..5 {
let mut logits = vec![0i32; config.logits as usize];
let tier;
{
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
tier = output.stats.tier;
}
transformer.reset();
results.push((logits, tier));
}
// All should be identical
for i in 1..results.len() {
assert_eq!(results[0].0, results[i].0);
assert_eq!(results[0].1, results[i].1);
}
}
#[test]
fn test_determinism_inactive_spikes() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
};
let spike = SpikePacket {
fired: 0,
rate_q15: 500,
novelty_q15: 500,
top_len: 0,
top_idx: [0; 16],
top_w_q15: [0; 16],
flags: 0,
};
let tokens: Vec<u32> = (0..32).collect();
let input = InferInput::from_tokens(&tokens, gate).with_spikes(spike);
let skip_counts: Vec<u8> = (0..10)
.map(|_| {
let mut logits = vec![0i32; config.logits as usize];
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
output.stats.skipped
})
.collect();
// All should skip
assert!(skip_counts.iter().all(|&s| s == 1));
}
// ============ Signature Caching Determinism ============
#[test]
fn test_cache_hit_determinism() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
};
let tokens: Vec<u32> = (0..32).collect();
let signature = 54321u64;
// First run - cache miss
let input = InferInput::from_tokens(&tokens, gate).with_signature(signature);
let mut logits1 = vec![0i32; config.logits as usize];
{
let mut output = InferOutput::new(&mut logits1);
transformer.infer(&input, &mut output).unwrap();
}
// Second run - cache hit with skip flag
let gate_skip = GatePacket {
lambda: 100,
flags: GatePacket::FLAG_SKIP,
..gate
};
let input = InferInput::from_tokens(&tokens, gate_skip).with_signature(signature);
let mut logits2 = vec![0i32; config.logits as usize];
{
let mut output = InferOutput::new(&mut logits2);
transformer.infer(&input, &mut output).unwrap();
}
// Third run - another cache hit
let input = InferInput::from_tokens(&tokens, gate_skip).with_signature(signature);
let mut logits3 = vec![0i32; config.logits as usize];
{
let mut output = InferOutput::new(&mut logits3);
transformer.infer(&input, &mut output).unwrap();
}
// All cached results should match original
assert_eq!(logits1, logits2);
assert_eq!(logits1, logits3);
}
// ============ Lambda Pattern Determinism ============
#[test]
fn test_determinism_lambda_sequences() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
let lambda_sequences = vec![
vec![100, 95, 90, 85, 80],
vec![50, 55, 60, 65, 70],
vec![100, 50, 100, 50, 100],
vec![30, 30, 30, 30, 30],
];
let tokens: Vec<u32> = (0..32).collect();
for sequence in lambda_sequences {
let mut transformer1 = create_transformer(config.clone(), policy.clone());
let mut transformer2 = create_transformer(config.clone(), policy.clone());
let mut results1 = Vec::new();
let mut results2 = Vec::new();
for (i, &lambda) in sequence.iter().enumerate() {
let prev_lambda = if i > 0 { sequence[i - 1] } else { lambda };
let gate = GatePacket {
lambda,
lambda_prev: prev_lambda,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
};
let input = InferInput::from_tokens(&tokens, gate);
// Run on transformer1
let mut logits1 = vec![0i32; config.logits as usize];
let decision1;
{
let mut output = InferOutput::new(&mut logits1);
transformer1.infer(&input, &mut output).unwrap();
decision1 = output.witness.decision;
}
results1.push((logits1, decision1));
// Run on transformer2
let mut logits2 = vec![0i32; config.logits as usize];
let decision2;
{
let mut output = InferOutput::new(&mut logits2);
transformer2.infer(&input, &mut output).unwrap();
decision2 = output.witness.decision;
}
results2.push((logits2, decision2));
}
// Both transformers should produce identical sequences
assert_eq!(results1, results2);
}
}
// ============ Edge Case Determinism ============
#[test]
fn test_determinism_zero_lambda() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 0,
lambda_prev: 100,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
};
let tokens: Vec<u32> = (0..32).collect();
let input = InferInput::from_tokens(&tokens, gate);
let results: Vec<GateDecision> = (0..3)
.map(|_| {
let mut logits = vec![0i32; config.logits as usize];
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
transformer.reset();
output.witness.decision
})
.collect();
// All should be identical
for i in 1..results.len() {
assert_eq!(results[0], results[i]);
}
}
#[test]
fn test_determinism_max_values() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: u32::MAX,
lambda_prev: u32::MAX,
boundary_edges: u16::MAX,
boundary_concentration_q15: 32767,
partition_count: u16::MAX,
flags: 0,
};
let tokens: Vec<u32> = (0..32).collect();
let input = InferInput::from_tokens(&tokens, gate);
let mut logits1 = vec![0i32; config.logits as usize];
let mut logits2 = vec![0i32; config.logits as usize];
{
let mut output = InferOutput::new(&mut logits1);
transformer.infer(&input, &mut output).unwrap();
}
transformer.reset();
{
let mut output = InferOutput::new(&mut logits2);
transformer.infer(&input, &mut output).unwrap();
}
assert_eq!(logits1, logits2);
}
// ============ Stats Determinism ============
#[test]
fn test_stats_reproducibility() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 15,
boundary_concentration_q15: 12000,
partition_count: 5,
flags: 0,
};
let tokens: Vec<u32> = (0..32).collect();
let input = InferInput::from_tokens(&tokens, gate);
let stats_list: Vec<_> = (0..5)
.map(|_| {
let mut logits = vec![0i32; config.logits as usize];
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
transformer.reset();
output.stats
})
.collect();
// All stats should be identical
for i in 1..stats_list.len() {
assert_eq!(
stats_list[0].effective_seq_len,
stats_list[i].effective_seq_len
);
assert_eq!(
stats_list[0].effective_window,
stats_list[i].effective_window
);
assert_eq!(stats_list[0].layers_executed, stats_list[i].layers_executed);
assert_eq!(stats_list[0].tier, stats_list[i].tier);
assert_eq!(stats_list[0].qgemm_calls, stats_list[i].qgemm_calls);
assert_eq!(stats_list[0].attn_dot_ops, stats_list[i].attn_dot_ops);
assert_eq!(stats_list[0].ffn_ops, stats_list[i].ffn_ops);
}
}
// ============ Reset Determinism ============
#[test]
fn test_reset_clears_state_deterministically() {
let config = TransformerConfig::baseline();
let policy = GatePolicy::default();
let mut transformer = create_transformer(config.clone(), policy);
let gate = GatePacket {
lambda: 100,
lambda_prev: 95,
boundary_edges: 5,
boundary_concentration_q15: 8192,
partition_count: 3,
flags: 0,
};
let tokens: Vec<u32> = (0..32).collect();
let input = InferInput::from_tokens(&tokens, gate);
let mut results = Vec::new();
// Run, reset, run pattern multiple times
for _ in 0..5 {
let mut logits = vec![0i32; config.logits as usize];
let mut output = InferOutput::new(&mut logits);
transformer.infer(&input, &mut output).unwrap();
results.push(logits);
transformer.reset();
}
// All results should be identical
for i in 1..results.len() {
assert_eq!(results[0], results[i]);
}
}