aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortslil clingman <tslil@posteo.de>2022-09-26 23:49:58 +0200
committertslil clingman <tslil@posteo.de>2022-09-27 00:03:10 +0200
commite7cd7f1d821b071a83cf003d02f8897523c8a70c (patch)
treebad0cdb68e510dfb46c10d1509c97d523dc96da6
parent938764a7328eeee747acfa4af07d3b3b91173fc1 (diff)
further optimisations
-rw-r--r--src/layout.rs2
-rw-r--r--src/main.rs138
2 files changed, 78 insertions, 62 deletions
diff --git a/src/layout.rs b/src/layout.rs
index fe853ad..2650a51 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -22,7 +22,7 @@ impl Prelayout {
let mut standard_columns = pl.standard_columns.clone();
let mut index_columns = pl.index_columns.clone();
- let mut count = rng.gen_range(1..=NUM_KEYS / 2);
+ let mut count = rng.gen_range(1..=NUM_KEYS - 1);
while count > 0 {
let source_index: bool = rng.gen();
let target_index: bool = rng.gen();
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);
- }
}
}