aboutsummaryrefslogtreecommitdiff
path: root/srchr/src/layout.rs
diff options
context:
space:
mode:
authortslil clingman <tslil@posteo.de>2022-10-23 13:38:28 +0200
committertslil clingman <tslil@posteo.de>2022-10-23 13:38:28 +0200
commit13e282705df90829ac39b75efde47e84e35cc1b1 (patch)
treee88a0799573a035f6ee1e095c218b19c167872c9 /srchr/src/layout.rs
parent6db23c417ea59dd9b9b928f022d40e20b80d2e67 (diff)
enhanced pre-layout -> layout algorithm
Diffstat (limited to 'srchr/src/layout.rs')
-rw-r--r--srchr/src/layout.rs174
1 files changed, 121 insertions, 53 deletions
diff --git a/srchr/src/layout.rs b/srchr/src/layout.rs
index bc519c1..cc963c7 100644
--- a/srchr/src/layout.rs
+++ b/srchr/src/layout.rs
@@ -146,68 +146,136 @@ impl Layout {
result
}
- let mut balance: f32 = 0.0;
- let mut left_col: usize = 0;
- let mut right_col: usize = 9;
- let mut keys = ['x'; NUM_KEYS];
-
+ // Derive column orderings
+ let w_index_columns = weight_function(&pl.index_columns, corpus);
let w_standard_columns = weight_function(&pl.standard_columns, corpus);
- for (col, weight) in w_standard_columns.iter() {
- let left: bool = ((balance >= 0.0) && (left_col <= 2)) || (right_col <= 6);
- let ind = if left { left_col } else { right_col };
- for i in 0..3 {
- keys[ind + i * ROW_LENGTH] = col[i] as char;
- }
- if left {
- left_col += 1;
- } else {
- right_col -= 1;
- }
- balance += if left { -weight } else { *weight };
- }
- let w_index_columns = weight_function(&pl.index_columns, corpus);
+ let mut standard_column_ordering = [0; 6];
+ let mut left_ind;
+ let mut right_ind;
+
+ match PRELAYOUT_TO_LAYOUT_ALGORITHM {
+ Algorithm::MinimiseLSBThenBalance => {
+ // first we still want left pinky to have lowest load
+ let mut balance: f32 = -w_index_columns[0].1 + w_index_columns[1].1;
+ standard_column_ordering[0] = 0;
+ standard_column_ordering[5] = 1;
- let (left_ind, right_ind);
- if MINIMISE_LSB_INSTEAD_OF_OPTIMISING_BALANCE {
- // Choose index order to minimise LSB (middle-index only) even though we
- // don't directly optimise for this parameter
- let mut lsbs = [0.0; 2];
- for option in [0, 1] {
- for left in [true, false] {
- let mind = if left { 2 } else { 7 };
- let side = if left { option } else { 1 - option };
- let m1 = keys[mind + 10 * 0] as u8;
- let m2 = keys[mind + 10 * 1] as u8;
- let m3 = keys[mind + 10 * 2] as u8;
- let i1 = w_index_columns[side].0[3];
- let i2 = w_index_columns[side].0[4];
- let i3 = w_index_columns[side].0[5];
- lsbs[option] += corpus.get_bigram_perc(m1, i1)
- + corpus.get_bigram_perc(m1, i2)
- + corpus.get_bigram_perc(m1, i3)
- + corpus.get_bigram_perc(m2, i1)
- + corpus.get_bigram_perc(m2, i2)
- + corpus.get_bigram_perc(m2, i3)
- + corpus.get_bigram_perc(m3, i1)
- + corpus.get_bigram_perc(m3, i2)
- + corpus.get_bigram_perc(m3, i3);
+ // next find minimum lsb pairing
+ let mut lsbs = [0.0; 2];
+ for swap in [false, true] {
+ for first_pairing in [true, false] {
+ let mind = match (swap, first_pairing) {
+ (true, true) => 5,
+ (true, false) => 4,
+ (false, true) => 4,
+ (false, false) => 5,
+ };
+ let m1 = w_standard_columns[mind].0[0];
+ let m2 = w_standard_columns[mind].0[1];
+ let m3 = w_standard_columns[mind].0[2];
+ let iind = if first_pairing { 0 } else { 1 };
+ let i1 = w_index_columns[iind].0[3];
+ let i2 = w_index_columns[iind].0[4];
+ let i3 = w_index_columns[iind].0[5];
+ lsbs[if swap { 1 } else { 0 }] += corpus.get_bigram_perc(m1, i1)
+ + corpus.get_bigram_perc(m1, i2)
+ + corpus.get_bigram_perc(m1, i3)
+ + corpus.get_bigram_perc(m2, i1)
+ + corpus.get_bigram_perc(m2, i2)
+ + corpus.get_bigram_perc(m2, i3)
+ + corpus.get_bigram_perc(m3, i1)
+ + corpus.get_bigram_perc(m3, i2)
+ + corpus.get_bigram_perc(m3, i3);
+ }
}
+
+ // if lsbs[0] < lsbs[1] then (4, 0) and (5, 1) are paired, else (5, 0) and (4, 1)
+ // record weights of pairings and whether we swapped 4 <-> 5 for min lsb
+ let (swap, w1, w2) = if lsbs[0] < lsbs[1] {
+ (
+ false,
+ w_standard_columns[4].1 + w_index_columns[0].1,
+ w_standard_columns[5].1 + w_index_columns[1].1,
+ )
+ } else {
+ (
+ true,
+ w_standard_columns[5].1 + w_index_columns[0].1,
+ w_standard_columns[4].1 + w_index_columns[1].1,
+ )
+ };
+
+ // now we try to balance hands according to combined weight, place
+ // on left and check if we need to swap
+ let w: f32;
+ if w1 < w2 {
+ (
+ (standard_column_ordering[2], left_ind),
+ (standard_column_ordering[3], right_ind),
+ ) = if swap {
+ ((5, 0), (4, 1))
+ } else {
+ ((4, 0), (5, 1))
+ };
+ w = -w1 + w2;
+ } else {
+ (
+ (standard_column_ordering[2], left_ind),
+ (standard_column_ordering[3], right_ind),
+ ) = if swap {
+ ((4, 1), (5, 0))
+ } else {
+ ((5, 1), (4, 0))
+ };
+ w = -w2 + w1;
+ }
+ if (balance + w).abs() > (balance - w).abs() {
+ // swapping would be better
+ (left_ind, right_ind) = (right_ind, left_ind);
+ (standard_column_ordering[2], standard_column_ordering[3]) =
+ (standard_column_ordering[3], standard_column_ordering[2]);
+ balance -= w;
+ } else {
+ balance += w;
+ }
+
+ // finally we do ring finger
+ (standard_column_ordering[1], standard_column_ordering[4]) =
+ if balance >= 0.0 { (3, 2) } else { (2, 3) };
}
- (left_ind, right_ind) = if lsbs[0] < lsbs[1] { (0, 1) } else { (1, 0) };
- // if this disagrees with the balancing order, let's consider ring
- // column swaps
- if balance >= 0.0 && left_ind == 0 && w_standard_columns[2].0[0] == keys[1] as u8 {
- for i in 0..3 {
- let t = keys[8 + 10 * i];
- keys[8 + 10 * i] = keys[1 + 10 * i];
- keys[1 + 10 * i] = t;
+ Algorithm::GreedyBalance => {
+ // greedy on weight, not provably correct in *all* cases but good
+ // enough in practice
+ let mut balance: f32 = 0.0;
+ let mut left_col: usize = 0;
+ let mut right_col: usize = 9;
+
+ for (src, (_, weight)) in w_standard_columns.iter().enumerate() {
+ let left: bool = ((balance >= 0.0) && (left_col <= 2)) || (right_col <= 6);
+ let ind = if left { left_col } else { right_col };
+ standard_column_ordering[ind] = src;
+ if left {
+ left_col += 1;
+ } else {
+ right_col -= 1;
+ }
+ balance += if left { -weight } else { *weight };
}
+ (left_ind, right_ind) = if balance >= 0.0 { (0, 1) } else { (1, 0) }
}
- } else {
- (left_ind, right_ind) = if balance >= 0.0 { (0, 1) } else { (1, 0) }
}
+ // write keys
+ let mut keys = ['x'; NUM_KEYS];
+ // standard
+ for (ind, src) in standard_column_ordering.into_iter().enumerate() {
+ let target = if ind < 3 { ind } else { 4 + ind };
+ for i in 0..3 {
+ keys[target + i * ROW_LENGTH] = w_standard_columns[src].0[i] as char;
+ }
+ }
+ // index
for j in 0..3 {
keys[3 + j * ROW_LENGTH] = w_index_columns[left_ind].0[j] as char;
keys[6 + j * ROW_LENGTH] = w_index_columns[right_ind].0[j] as char;