evaluate: fix RNG — xorshift32 replaces degenerate LCG

The LCG was producing only 2 distinct matchup pairs due to poor
constants. Switch to xorshift32 for proper coverage of all type pairs.

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
ProofOfConcept 2026-03-14 19:57:58 -04:00
parent 16777924d0
commit c959b2c964

View file

@ -262,15 +262,20 @@ pub fn cmd_evaluate_agents(matchups: usize, model: &str, dry_run: bool) -> Resul
// Load persisted ratings // Load persisted ratings
let mut ratings = load_elo_ratings(&agent_types); let mut ratings = load_elo_ratings(&agent_types);
let config = EloConfig { k: 32.0 }; let config = EloConfig { k: 32.0 };
let mut rng_state = std::time::SystemTime::now() // Simple but adequate RNG: xorshift32
.duration_since(std::time::UNIX_EPOCH).unwrap().subsec_nanos(); let mut rng = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH).unwrap().subsec_nanos() | 1;
let mut next_rng = || -> usize {
rng ^= rng << 13;
rng ^= rng >> 17;
rng ^= rng << 5;
rng as usize
};
for i in 0..matchups { for i in 0..matchups {
// Pick two different random agent types // Pick two different random agent types
rng_state = rng_state.wrapping_mul(1103515245).wrapping_add(12345); let idx_a = next_rng() % active_types.len();
let idx_a = (rng_state as usize) % active_types.len(); let mut idx_b = next_rng() % active_types.len();
rng_state = rng_state.wrapping_mul(1103515245).wrapping_add(12345);
let mut idx_b = (rng_state as usize) % active_types.len();
if idx_b == idx_a { idx_b = (idx_b + 1) % active_types.len(); } if idx_b == idx_a { idx_b = (idx_b + 1) % active_types.len(); }
let type_a = active_types[idx_a]; let type_a = active_types[idx_a];
@ -279,10 +284,8 @@ pub fn cmd_evaluate_agents(matchups: usize, model: &str, dry_run: bool) -> Resul
// Pick random recent action from each // Pick random recent action from each
let acts_a = &actions[type_a]; let acts_a = &actions[type_a];
let acts_b = &actions[type_b]; let acts_b = &actions[type_b];
rng_state = rng_state.wrapping_mul(1103515245).wrapping_add(12345); let act_a = &acts_a[next_rng() % acts_a.len()];
let act_a = &acts_a[(rng_state as usize) % acts_a.len()]; let act_b = &acts_b[next_rng() % acts_b.len()];
rng_state = rng_state.wrapping_mul(1103515245).wrapping_add(12345);
let act_b = &acts_b[(rng_state as usize) % acts_b.len()];
let sample_a = (type_a.to_string(), act_a.0.clone(), act_a.1.clone()); let sample_a = (type_a.to_string(), act_a.0.clone(), act_a.1.clone());
let sample_b = (type_b.to_string(), act_b.0.clone(), act_b.1.clone()); let sample_b = (type_b.to_string(), act_b.0.clone(), act_b.1.clone());