diff options
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 138 |
1 files changed, 77 insertions, 61 deletions
diff --git a/src/main.rs b/src/main.rs index 3fee6a7..dfc791e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,8 +12,8 @@ use layout::*; use std::time::Instant; -const NUM_CONTESTANTS: usize = 24; -const SURVIVE_THRESHOLD: usize = 4; +const NUM_CONTESTANTS: usize = 64; +const NUM_PERSIST: usize = 8; // TODO: Layout is really pre-layout, have something that takes a layout and // re-orders columns to balance hands, and keys per column (block really @@ -23,84 +23,100 @@ const SURVIVE_THRESHOLD: usize = 4; // from file? Might as well make num_contestants and survive_threshold // configurable, and number of swaps when generating new layout +struct Tournament<'a> { + rngs: Vec<Pcg64>, + top_prelayouts: Vec<(Prelayout, u32)>, + corpus: &'a Corpus, +} + +impl<'a> Tournament<'a> { + fn new_from_seed_prelayout(seed_prelayout: &Prelayout, corpus: &'a Corpus) -> Tournament<'a> { + let mut rngs: Vec<Pcg64> = Vec::new(); + for _ in 0..NUM_CONTESTANTS { + rngs.push(Pcg64::from_entropy()); + } + + let mut top_prelayouts: Vec<(Prelayout, u32)> = Vec::new(); + let score = corpus.prelayout_fitness(&seed_prelayout); + for _ in 0..NUM_PERSIST { + top_prelayouts.push((seed_prelayout.clone(), score)); + } + + Tournament { + rngs, + top_prelayouts, + corpus, + } + } + + fn run_round(&mut self) -> Option<Prelayout> { + let rngs = &mut self.rngs; + + let mut tournament = rngs + .into_par_iter() + .map(|mut rng| { + let layout = Prelayout::new_random_from( + &self.top_prelayouts[rng.gen_range(0..NUM_PERSIST)].0, + &mut rng, + ); + return (layout, self.corpus.prelayout_fitness(&layout)); + }) + .collect::<Vec<(Prelayout, u32)>>(); + + let best = self.top_prelayouts[0].1; + tournament.append(&mut self.top_prelayouts); + tournament.sort_by(|(_, lscore), (_, rscore)| lscore.cmp(rscore)); + + let result; + if tournament[0].1 < best { + result = Some(tournament[0].0); + } else { + result = None; + } + + for i in 0..NUM_PERSIST { + self.top_prelayouts.push(tournament[i]); + } + + result + } +} + fn main() { let corpus = Corpus::load("new.txt").unwrap(); println!("{}", corpus); - let starting_prelayout = Layout::from_verbose( - " - Y W F L M K P O , Q - U R S N H D T E A I - Z X C V J B G ' . / - ", - ) - .unwrap() - .as_prelayout(); + let seed_prelayout = Layout::from_verbose("QWERTYUIOPASDFGHJKL'ZXCVBNM,./") + .unwrap() + .as_prelayout(); - let mut rng = Pcg64::from_entropy(); - - type Fun = Vec<(Prelayout, u32)>; - - let mut best = std::u32::MAX; - let mut prelayouts: Fun = (0..NUM_CONTESTANTS) - .into_iter() - .map(|i| { - if i > 0 { - let layout; - layout = Prelayout::new_random_from(&starting_prelayout, &mut rng); - return (layout, std::u32::MAX); - } else { - (starting_prelayout, std::u32::MAX) - } - }) - .collect(); + let mut tournament = Tournament::new_from_seed_prelayout(&seed_prelayout, &corpus); let mut count: usize = 0; let mut current = Instant::now(); loop { - let new_prelayouts = prelayouts - .iter() - .enumerate() - .map(|(i, (kbd, _))| { - if i > SURVIVE_THRESHOLD { - let parent = rng.gen_range(0..=SURVIVE_THRESHOLD); - Prelayout::new_random_from(&prelayouts[parent].0, &mut rng) - } else { - kbd.clone() - } - }) - .collect::<Vec<Prelayout>>(); + let improvement = tournament.run_round(); - new_prelayouts - .par_iter() - .map(|layout| { - return (*layout, corpus.prelayout_fitness(layout)); - }) - .collect_into_vec(&mut prelayouts); + if let Some(prelayout) = improvement { + let layout = Layout::from_prelayout(&prelayout); + let evl = corpus.evaluate_layout(&layout); + println!(""); + println!("================================================================================\nLayout:\n{}", + layout + ); - prelayouts.sort_by(|(_, lfit), (_, rfit)| lfit.cmp(rfit)); + println!("{}", evl); + } count += 1; if count > 65535 { let duration = current.elapsed(); eprint!( - "\u{001b}[2K\u{001b}[1000D{} iters/s", - count as f32 / duration.as_millis() as f32 * 1000.0 + "\u{001b}[2K\u{001b}[1000D{} layouts/s", + (count * NUM_CONTESTANTS) as f32 / duration.as_millis() as f32 * 1000.0 ); current = Instant::now(); count = 0; } - - if prelayouts[0].1 < best { - best = prelayouts[0].1; - let layout = Layout::from_prelayout(&prelayouts[0].0); - let evl = corpus.evaluate_layout(&layout); - println!(""); - println!("================================================================================\nLayout:\n{}", - layout - ); - - println!("{}", evl); - } } } |
