carpalx - keyboard layout optimizer - save your carpals
Carpalx optimizes keyboard layouts to create ones that require less effort and significantly reduced carpal strain!

Have ideas? Tell me.

the best layout

Partially optimized QWKRFY and fully optimized QGMLWY layouts are the last word in easier typing.

the worst layout

A fully anti-optimized TNWMLC layout is a joke and a nightmare. It's also the only keyboard layout that has its own fashion line.

download and explore

Download keyboard layouts, or run the code yourself to explore new layouts. Carpalx is licensed under CC BY-NC-SA 4.0.

layouts

Download and install the layouts.

Typing Effort Model

Developing a Model of Typing Effort

The result of any keyboard layout search is dependent on (a) the training text, (b) determination of layout suitability and (c) the search algorithm. The choice of algorithm should not change the ideal layout, but only the likelihood of finding it. In practise, a poorly devised search strategy may seriously impact the likelihood of discovering a better layout. The choice of the training text will impact the generalizability of the layout — if the text is representative of the typist's daily tasks (representative in terms of key stroke combinations), then an optimized layout will be helpful in typing future texts of similar nature.

The fact is, the choice of training text and search algorithm is less subjective than the model for typing effort. For example, unless you are concerned with typing body copy specific to a field with domain-specific terms (e.g. medical texts), a year's worth of New York Times would arguably be a good corpus. If your search algorithm is appropriate, you will find a global minimum and you will have a layout on which typing a year's worth of NYT involves minimum effort — but only as far as quantified by your typing effort model.

Characteristics of a successful model

If you explore keyboard layout projects, such as Capewell or Arensito, you'll find that each approach is different and uses a combination of heuristic and algorithmic contributions to determining the goodness of a layout. There are certain properties of a good layout, however, that are widely agreed upon

  • limited use of weak fingers, like pinky and ring finger
  • limited use of bottom row
  • increased use of home row
  • limited finger travel distance
  • limited same-finger typing (e.g. uhm)
  • balanced hand-use vs right-hand priority (see below)
  • alternating hand-use vs rolling (see below)

The question of balanced hand use is debated. Alternate-hand typing may not be as efficient as "rolling finger" typing, in which two successive strokes are typed by the same hand. Most typists find it faster and more comfortable to type "iu" than "it". The former stroke combination uses a rolling finger movement in which your wrist lightly rolls from the outside in. Generally, outward rolling (e.g. "ui", or even worse "io" or "op") is undesirable.

Some also argue for adjusting the layout to favour the right hand. The argument for this is that most individuals are right-handed and therefore their right hand is "stronger". My own experience does not reflect this, though. Being right handed and having typed for 20 years, I find my left and right hands ambidexterous when it comes to typing (but not much else).

Carpalx typing model

Carpalx uses a typing effort model which describes the perceived effort of typing. Given a training text, each layout has an associated typing effort and during layout optimization, this layout is adjusted until a global minimum in effort is reached. I've attempted to make the model flexible to avoid heuristic penalties. The model is highly parametrized, however, and you decide what is important to your layout and these parameters make the model highly subjective. The parameters can be adjusted to try to increase positive layout characteristics (see list above) and minimize aspects which make typing difficult. The task of solving the keyboard layout problem (if the problem is universally solvable — which I doubt, due to its subjective nature) can be reduced to the task of finding the ideal effort model for you.

I want to make the distinction between the ideal effort model for you and the ideal effort model for everyone. The chances of the existence of the former is much better, I think. Everyone has different typing preferences and comfort levels. Even if you eliminate typists with special needs or habits, I believe that a model which suits everyone must by necessity be very simple and be limited to isolating layout features that are desired/disliked by a large majority. For example, it can be argued that most prefer not to use their pinky or limit successive same-finger strokes, there's less consensus about the balanced hand use or desirability of individual key positions.

The carpalx typing effort model is based on triads, which are three character substrings formed from the training text. A triad starts at each letter position. Thus, triads overlap, though this is configurable. The effort model takes into account contributions of the following characteristics

  • finger travel distance
  • hand, finger and row penalties
  • stroke path

The effort associated with typing has two components: effort to hit a key (independently of preceeding and successive strokes) and effort to hit a group of keys. Independent effort is based on finger distance and includes hand/finger/row penalties associated with that key. The penalties provide a means to tune the parameters to reflect your typing abilities and preferences. The effort of hitting a group of keys is measured based on stroke path which assigns desirability to certain patterns of finger movement. More about stroke path below.

Triads: 3-key Effort

Introduced above, the input document is divided into triads, which are three-character substrings. The triad overlap is an adjustable parameter but generally is set to 2 to avoid starting position bias. Space characters are removed from the text up-front and do not impact the formation of triads, since the space bar is not considered relocatable and enjoys dedicated service by the thumbs. I chose to model effort using triads to help evaluate single-key and multi-key effort contributions.

For example, consider the text "typing is hard". If triad overlap is set to 2 (default), after the removal of spaces, the triads are

  TEXT:    typingishard
  TRIADS:  typ
            ypi
               ....
                   har
                    ard

The typing effort for the text is the normalized total of triad typing efforts $$E = \frac{1}{N} \sum_{i} n_i e_i$$

where `N = \sum_i n_i` is the total number of triads and `e_i` is the effort of typing triad `i`. The number of unique triads is limited by the variety of characters in the input text and it is efficient to index all unique triads, each having `n_i` instances. The validity of the model is based on the assumption that the desirability of a keyboard layout can be determined by considering the effort of individual triads. The use of triads limits the interaction effect of near-neighbouring keys on the final layout. By choosing to work with three-key combinations, I am limiting the degree to which long-range effects affect the final layout.

Long-range interaction of keys can be illustrated by considering typing the two strings "zqzqaa zq" and "zqazqa zq". In the first text, the pinky gets a double break when two a's are typed before the final "zq". Presumably, after hammering "zqzq" the pinky can be considered spent. In the second example, the home-row rest for the pinky is interspersed with the difficult "zq" doublet. Thus, when it comes time to type the final "zq" the pinky is still tired. A more sophisticated model could include the notion of accumulated tiredness of a finger, which decays based on a set recovery rate. Thus, if a pinky has recently been called to expend a lot of effort by typing z's and q's, its subsequent use would be penalized until the finger has had a chance to rest.

The effort `e_i` of typing a triad is given by $$ e_i = k_b b_i + k_p p_i + k_s s_i $$

where `b_i`, `p_i` and `s_i` are the base, penalty and stroke path effort components of triad `i`. In turn, the base and penalty components are given by $$b_i = k_1 b_{i1} (1 + k_2 b_{i2} ( 1+ k_3 b_{i3}))$$ $$p_i = k_1 p_{i1} (1 + k_2 p_{i2} ( 1+ k_3 p_{i3}))$$

Notice that the baseline and penalty efforts are defined symmetrically, with `b_{ij}` and `p_ij` being the base and penalty factors of key `j` in triad `i`. The stroke path term `s_i` is discussed further below.

The role of the `k_b`, `k_p` and `k_s` factors is to weight the indidividual effort components. For example, by setting `k_s=0`, the triad effort is no longer influenced by the stroke path.

Within each triad, the efforts of each key are combined using the `k_1`, `k_2` and `k_3` parameters. For example, if `k_2 = k_3 = 0`, then the effort of each triad is solely based on the effort of the first key in the triad. With this setting, the typing model contains no interaction terms between keys. However, as soon as `k_2 > 0` and/or `k_3 > 0`, efforts of the second and/or third keys in the triad add to the total triad effort in proportion to the effort of the previous key(s). Now, the triad effort is compounded geometrically over the first two or three keys of the triad. The effect of this is that triads such as "zza" have a larger effort than the individual effort of their single-character components (the purpose of this is to model tiredness associated with typing successivel high-effort keys).

All weight factors ki should be non-negative, since negative typing effort has no interpretation within the model.

No negative effort?

Although hitting any key is associated with a finite amount of typing effort (some keys may be effortless for certain parameter combinations), the concept of negative effort is an interesting one. For example, the notion of recuperation could be considered by extending the correlation length of effort beyond the length of the triad. For example, after a long run of easy-to-type triads, one might consider that a certain amount of "finger rest" has been accumulated, which goes to offset the effort of subsequent, harder-to-type triads.

base effort is finger travel distance

The base effort for a key is defined solely by the finger travel distance for that key. This distance corresponds to the physical distance between keys, as measured on my BenQ x120 keyboard. This value is shown on each key in the figure below.

The role of the base effort is to measure the total distance traveled by fingers during typing. Layouts that keep this value low are those that place frequently used keys on home row.

Instead of using a subjective measure of key effort, I decided to objectively define the effort by a combination of the physical keyboard distance and finger/row penalties (see below). This combination naturally results in a higher effort for z than q, because the bottom row carries a larger penalty than the top row (for both keys the base effort given by the finger travel distance is the same, as is the finger penalty)..

penalty component is hand, row and finger cost

The penalty component for a key is associated with the hand, row and finger for that key. Each hand, row and finger have unique penalties that reflect the degree to which using them is difficult. The penalty for key `j` of triad `i` is $$p_{ij} = w_0 + w_\text{hand} P_{\text{hand}_j} + w_\text{row} P_{\text{row}_j} + w_\text{finger} P_{\text{finger}_j}$$

where the `w` terms are weights and the `P` terms are the penalties associated with the hand, row and finger for key `j`. Typically, `w_0 = 0` (no default penalty), and `P_\text{hand}=0` (neither left nor right hands are penalized).

The role of the penalty is to model increased effort of the use of weak fingers (e.g. pinky) or hard-to-reach rows (e.g. bottom row). The penalty term can also differentially penalize one of the hands (e.g. associate a penalty with the left hand to favour the use of the right hand).

Layouts that have a low penalty are those that limit the use of the pinky, ring finger and the bottom row (note that this statement applies to a model parameter set that associates penalties with the use of these fingers and row).

personalized penalties

You can personalize the key stroke effort by adjusting hand, row and finger penalties to model use of any injured fingers or hands.

effortless keys and triads

Now a note about keys with zero-effort. Since a key's sum of base and penalty components, `b_ij` and `p_ij`, may be zero (such as the key "f"), if the key is the first in the triad, the triad has zero effort (excluding stroke path). If this is undesirable, set the baseline penalty, `w_0`, to a positive value as described above.

For example, in the word coffee, which has triads cof/off/ffe/fee, the triads which start with f, a key with zero effort, will not count total effort of typing coffee if no stroke path contribution exists (`k_4 = 0`). However, all triads count towards the total number of triads which is used to normalize the total effort sum. In the model, such effortless triads are like little typing breaks. This behaviour can be counteracted by ensuring that all `e_i > 0` by setting `b_{ij} > 0` or `w_0 > 0`.

Evaluating the Stroke Path

Not all triads, even those with equivalent baseline effort, are as easy to type. Consider "fjo" and "jfy". The former uses the ring finger which is penalized and the latter requires that the strong index finger reach for the y, a distant key. Depending on the model parameters, these triads may have the same effort. However, fjo is easier to type then jfy, which uses the same finger twice. Therefore, it's appropriate to add to the effort model a cost function which augments the typing cost with additional weighting of uncomfortable key combinations.

The effort associated with the stroke path is parameterized by the following indexes

  • hand-alternation, `p_\text{h}`
  • row-alternation, `p_\text{r}`
  • finger-alternation, `p_\text{f}`

Each of these indexes `(p_\text{h}, p_\text{r}, p_\text{f})` may take the following values

value hand, `p_\text{h}` row, `p_\text{r}` finger, `p_\text{f}`
0 both used, not alternating
eem ope
same
ert als
all different, monotonic progression
asd pua
1 alternating
aja sot
downward progression, with repetition
ern kam
some different, key repeat, monotonic progression
app err
2 same
ase mon
upward progression, with repetition
ade nal
rolling
bih fad
3 - some different, not monotonic, max row change 1
jab oar
all different, not monotonic
yak nep
4 - downward progression
eln pax
some different, not monotonic progression
kri maj
5 - some different, not monotonic, max row change downward >1
hen kib
same, key repeat
cee loo
6 - upward progression
zaw nap
some different, no key repeat, monotonic progression
abr bde
7 - some different, not monotonic, max row change upward >1
abe axe
same, no key repeat
tfb dec

Any given triad has a unique stroke path index triplet `(p_\text{h}, p_\text{r}, p_\text{f})`. This triplet is used to calculate the path effort for the triad. Note that some triplet values do not describe a valid path (e.g. `0*4` = alternating hand, same finger). The path effort for each triad is calculated as a weighted sum of the index values. This linear composition of triplet elements is appropriate because more difficult typing scenarios are parametrized by larger index values (e.g. `p_\text{f} = 0` is more desirable than `p_\text{f} = 7`). $$s_i = \sum_{j \,=\, \text{hand, row, finger}} f_j p_j$$

The parameters `f_\text{h,r,f}` assign a weight to each triplet element value. For example, consider the triad "abz". This triad is associated with the path triplet `(p_\text{h}, p_\text{r}, p_\text{f}) = (2,1,4)`. Consider a stroke model that uses the following stroke path weights, `(f_\text{h}, f_\text{r}, f_\text{f} )=(1,2,3)`. $$s(2,1,4) = 2 f_\text{h} + 1 f_\text{r} + 4 f_\text{f} = 2 \times 1 + 1 \times 2 + 4 \times 3 = 16$$

In this example, the contributions of effort towards the stroke path from hand, row and finger terms is unbalanced: the finger term contributes `+12` whereas the hand and row contribute `+2` each. Using the English corpus, the weights `(f_\text{h}, f_\text{r}, f_\text{f} )=(1,0.3,0.3)` yield approximately a `1:1:1` ratio of hand, row and finger contributions to the stroke path over the entire corpus.

Below are the path efforts for weights `(1,0.3,0.3)`.

`p_\text{h} = 0`
triplet path effort example
0 0 0 0 adh adj adk adl afh
0 0 1 0.3 aah aaj aak aal ahh
0 1 0 0.3 abm abn acm acn adm
0 1 1 0.6 aam aan amm ann ddm
0 0 2 0.6 akh akj alh alj alk
0 1 2 0.9 akm akn alm aln dkm
0 2 0 0.6 adi ado adp adu ady
0 2 1 0.9 aai aao aap aau aay
0 2 2 1.2 aiu aiy aku aky ali
0 0 3 0.9 bcm bcn bxm bxn bzm
0 1 3 1.2 dam dan dsm dsn dxm
0 2 3 1.5 bah baj bak bal bch
0 3 0 0.9 abh abj abk abl ach
0 3 1 - -
0 3 2 1.5 aih aij aoh aoj aok
0 3 3 1.8 bam ban bdm bdn bsm
0 0 4 - -
0 1 4 - -
0 2 4 - -
0 3 4 - -
0 4 0 1.2 efm efn egm egn idx
0 4 1 - -
0 4 2 1.8 ekm ekn elm eln iab
0 4 3 2.1 eam ean esm esn ilb
0 4 4 - -
0 0 5 - -
0 1 5 - -
0 2 5 - -
0 3 5 - -
0 4 5 - -
0 5 0 1.5 abi abo abp abu aby
0 5 1 - -
0 5 2 2.1 bih bij boh boj bok
0 5 3 2.4 beh bej bek bel bqh
0 5 4 - -
0 5 5 - -
0 0 6 1.8 ahj ajh bmn bnm bvm
0 1 6 2.1 ahm ahn ajm ajn amn
0 2 6 2.4 ahu ahy aju ajy aki
0 3 6 2.7 aik amh amj anh anj
0 4 6 3 edm edn ehm ehn ejm
0 5 6 3.3 amu amy anu any azi
0 6 0 1.8 bhi bho bhp bji bjo
0 6 1 - -
0 6 2 2.4 bku bky bli blu bly
0 6 3 2.7 bai bao bap bau bay
0 6 4 - -
0 6 5 - -
0 6 6 3.6 bfi bfo bfp bfu bfy
0 0 7 - -
0 1 7 - -
0 2 7 - -
0 3 7 - -
0 4 7 - -
0 5 7 - -
0 6 7 - -
0 7 0 2.1 aem aen arm arn atm
0 7 1 - -
0 7 2 2.7 aim ain aom aon apm
0 7 3 3 bem ben bqm bqn bwm
0 7 4 - -
0 7 5 - -
0 7 6 3.9 aqm aqn aum aun aym
0 7 7 - -
`p_\text{h} = 1`
triplet path effort example
1 0 0 - -
1 0 1 - -
1 1 0 - -
1 1 1 - -
1 0 2 1.6 ahd ahf ahg ahs ajd
1 1 2 1.9 ahb ahc ahv ahx ajb
1 2 0 - -
1 2 1 - -
1 2 2 2.2 ahe ahr aht ahw aie
1 0 3 1.9 bmc bmx bmz bnc bnx
1 1 3 2.2 dhx dhz djx djz dkx
1 2 3 2.5 bha bhd bhs bie biq
1 3 0 - -
1 3 1 - -
1 3 2 2.5 aid aif aig ais amd
1 3 3 2.8 bhc bhx bhz bjc bjx
1 0 4 2.2 aha aja aka ala bmb
1 1 4 2.5 ahz ajz akz alz amz
1 2 4 2.8 ahq aiq ajq akq alq
1 3 4 3.1 aia ama ana aoa apa
1 4 0 - -
1 4 1 - -
1 4 2 2.8 ehb ehv ejb ejv ekb
1 4 3 3.1 ehx ehz ejx ejz ekx
1 4 4 3.4 ehc ejc ekc elc qhz
1 0 5 - -
1 1 5 - -
1 2 5 - -
1 3 5 - -
1 4 5 - -
1 5 0 - -
1 5 1 - -
1 5 2 3.1 ame amr amt amw ane
1 5 3 3.4 bia bid bis boa bod
1 5 4 3.7 amq anq bif big bof
1 5 5 - -
1 0 6 - -
1 1 6 - -
1 2 6 - -
1 3 6 - -
1 4 6 - -
1 5 6 - -
1 6 0 - -
1 6 1 - -
1 6 2 3.4 chr cht cjr cjt ckr
1 6 3 3.7 bhe bhq bhw bje bjq
1 6 4 4 bhr bht bjr bjt bkr
1 6 5 - -
1 6 6 - -
1 0 7 - -
1 1 7 - -
1 2 7 - -
1 3 7 - -
1 4 7 - -
1 5 7 - -
1 6 7 - -
1 7 0 - -
1 7 1 - -
1 7 2 3.7 aib aic aiv aix aob
1 7 3 4 bic bix biz boc box
1 7 4 4.3 aiz aoz apz auz ayz
1 7 5 - -
1 7 6 - -
1 7 7 - -
`p_\text{h} = 2`
triplet path effort example
2 0 0 2 adf adg asd asf asg
2 0 1 2.3 aad aaf aag aas add
2 1 0 2.3 acb acv adb adv asb
2 1 1 2.6 aab aac aav aax abb
2 0 2 2.6 ads afd afs agd ags
2 1 2 2.9 abc abx acx adx afc
2 2 0 2.6 adr adt aer aet ase
2 2 1 2.9 aae aar aat aaw aee
2 2 2 3.2 adw aew afe afw age
2 0 3 2.9 cbx cbz cvx cvz cxb
2 1 3 3.2 dab dav dbx dbz dfx
2 2 3 3.5 caf cag cba cbq cbs
2 3 0 2.9 acf acg aef aeg awd
2 3 1 - -
2 3 2 3.5 abd abs acs aes ard
2 3 3 3.8 cab cav cfx cfz cgx
2 0 4 3.2 ada afa aga asa bcb
2 1 4 3.5 abz acz adz afz agz
2 2 4 3.8 adq aeq afq agq arq
2 3 4 4.1 aba aca aea ara ata
2 4 0 3.2 esz okm okn pkm pkn
2 4 1 - -
2 4 2 3.8 eax qdx qfc qfx qgc
2 4 3 4.1 eab eav efx efz egx
2 4 4 4.4 eac efc egc esc qdz
2 0 5 3.5 bbv bvb bvv ffg fgf
2 1 5 3.8 aaz azz dcc ddc ecc
2 2 5 4.1 aaq aqq bbf bbg bbr
2 3 5 4.4 aqa aza bfb bgb cdc
2 4 5 - -
2 5 0 3.5 acr act axe axr axt
2 5 1 - -
2 5 2 4.1 abe abw acw ave avw
2 5 3 4.4 cqf cqg cra crs cta
2 5 4 4.7 abq acq avq axq bef
2 5 5 - -
2 0 6 3.8 afg agf bvc bvx bvz
2 1 6 4.1 abv adc afb afv agb
2 2 6 4.4 ade afr aft agr agt
2 3 6 4.7 abf abg acd aed aqd
2 4 6 5 eaz edb edv edx edz
2 5 6 5.3 abr abt ace avr avt
2 6 0 3.8 bdq bdw bsq csq mko
2 6 1 - -
2 6 2 4.4 bae baw bse caw mli
2 6 3 4.7 car cat cfq cfw cgq
2 6 4 5 bar bat bdr bdt bsr
2 6 5 - -
2 6 6 5.6 baq bde bfe bfq bfw
2 0 7 - -
2 1 7 4.4 fbv fgb fgv fvb gbv
2 2 7 4.7 bfg bgf brt btr bvf
2 3 7 5 bfv bgv fbg frg ftg
2 4 7 5.3 edc qaz rfb rfv rgb
2 5 7 5.6 azq brf brg btf btg
2 6 7 5.9 bfr bft bgr bgt cde
2 7 0 4.1 aeb aev awb awc awv
2 7 1 - -
2 7 2 4.7 aex arc arx atc atx
2 7 3 5 cqb cqv crx crz ctx
2 7 4 5.3 aez arz atz awz beb
2 7 5 5.6 brb btb cec ece mum
2 7 6 5.9 aec aqb aqc aqv aqx
2 7 7 6.2 aqz brv btv dec ecd

As it is, these stroke efforts are very subjective. There are certain triads that I find particularly difficult to type. For example, I don't like upward row progressions (`p_\text{r} = 6`) when the same hand and finger is used (`p_\text{h} = 2, p_\text{f} = 7`) . Triads such as "bfr", "cde" and "nhu" are examples and have high stroke effort of 5.9.

Families of Typing Models

I applied different parameter sets to the layout optimization problem to examine the effect of model complexity. Values of baseline key stroke efforts based on finger travel distance, `d_i`, are described in the figure above and do not vary between model families. A list of parameter sets is found in the Carpalx — Model Parameters section.

Training Texts

For optimizing English text, I use a corpus composed of the following

  • Alice in Wonderland, by Lewis Carroll
  • Dracula, by Bram Stoker
  • Great Expectations, by Charles Dickens
  • Huckleberry Finn, by Mark Twain
  • Moby Dick, by Herman Melville
  • Picture of Dorian Grey, by Oscar Wilde
  • Pride and Prejudice, by Jane Austen
  • Sense and Sensibility, by Jane Austen
  • The Adventures of Tom Sawyer, by Mark Twain
  • The Adventures of Sherlock Holmes, by Sir Arthur Conan Doyle
  • The Count of Monte Cristo, by Alexandre Dumas
  • Ulysses, by James Joyce
  • Walden, by Henry Thoreau

These books are freely available from Project Gutenberg.

Another source of corpora is the Natural Language Toolkit Project.