aboutsummaryrefslogtreecommitdiff
path: root/srchr/src/main.rs
diff options
context:
space:
mode:
authortslil clingman <tslil@posteo.de>2022-09-28 00:12:11 +0200
committertslil clingman <tslil@posteo.de>2022-09-28 00:20:29 +0200
commit785fa20b4e4a5372857f6f033b9d478685460cea (patch)
treedf5ef4b2a3ead571a7de84c1bb2395917b5f4fee /srchr/src/main.rs
parentc4e7a97fd7efecdb85f362f04434ea8470a1927f (diff)
Throwing in kicad stuff
Diffstat (limited to 'srchr/src/main.rs')
-rw-r--r--srchr/src/main.rs118
1 files changed, 118 insertions, 0 deletions
diff --git a/srchr/src/main.rs b/srchr/src/main.rs
new file mode 100644
index 0000000..2762646
--- /dev/null
+++ b/srchr/src/main.rs
@@ -0,0 +1,118 @@
+mod corpus;
+mod layout;
+
+use rayon::prelude::*;
+
+use rand::prelude::*;
+use rand_pcg::*;
+
+use corpus::*;
+use layout::*;
+
+use std::time::Instant;
+
+const NUM_CONTESTANTS: usize = 128;
+const NUM_PERSIST: usize = 8;
+
+// TODO: command line arguments to start at a given layout string, maybe read
+// from file? Might as well make num_contestants and survive_threshold
+// configurable, and number of swaps when generating new layout, and index
+// finger threshold.
+
+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("books.txt").unwrap();
+ println!("{}", corpus);
+
+ let seed_prelayout = Layout::from_verbose("QWERTYUIOPASDFGHJKL'ZXCVBNM,./")
+ .unwrap()
+ .as_prelayout();
+
+ let mut tournament = Tournament::new_from_seed_prelayout(&seed_prelayout, &corpus);
+
+ let mut count: usize = 0;
+ let mut current = Instant::now();
+ loop {
+ let improvement = tournament.run_round();
+
+ if let Some(prelayout) = improvement {
+ let layout = Layout::from_prelayout(&prelayout, &corpus);
+ let evl = corpus.evaluate_layout(&layout);
+ println!("");
+ println!("================================================================================\n\n{}",
+ layout
+ );
+
+ println!("{}", evl);
+ }
+
+ count += 1;
+ if count > 65535 {
+ let duration = current.elapsed();
+ eprint!(
+ "\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;
+ }
+ }
+}