flandrade/sat-solver-ts
SAT problem with Z3 (TypeScript)
Keyboard Mnemonics: SAT problem with Z3 (TypeScript)
Assign keyboard mnemonics to a list of options. Given a set of options in a menu, we want to assign
a mnemonic to every option such that there are not two options with the same mnemonic. The solution
has to meet the following constraints:
- Each option must have a mnemonic.
- An option cannot have more than one mnemonic.
- A given character cannot be a mnemonic of two different options.
The problem can be reduced to a SAT. This repository includes the formalization and the implementation. It uses Z3's bindings in TypeScript.
Formalization
Formalizing the problem
Each option i in the menu has a set of characters associated with it, a set called
instance, if option 1 is "Undo",
The task is to determine whether a particular character c is the mnemonic for a specific i.
The menu with
that belong to the
Here,
Formalization with examples
Let's consider options "undo", "copy", "mod" which can be written as:
Uu1, Un1, Ud1, Uo1
Uc2, Uo2, Up2, Uy2
Um3, Uo3, Ud3
graph TD
A[Menu Options] --> B["Option 1: Chars(1) = {u, n, d, o}"]
A --> C["Option 2: Chars(2) = {c, o, p, y}"]
A --> D["Option 3: Chars(3) = {m, o, d}"]
B --> |Mnemonic: U| E["U(u,1) = True"]
C --> |Mnemonic: Y| F["U(y,2) = True"]
D --> |Mnemonic: D| G["U(d,3) = True"]
Each option must have a mnemonic
This constraint ensures that every option has at least one character assigned as its mnemonic. Formally, for each option i, at least one of the Boolean variables true:
Formalization according to our example:
An option cannot have more than one mnemonic
If a character is chosen, no other character for the same option can be a mnemonic. Formally, for each option i and each character c in Chars(i), if true, then all
other characters t in Chars(i) must have false:
Formalization according to our example:
A given character cannot be a mnemonic of two different options
This constraint ensures that no single character is used as the mnemonic for more than one option. Formally, for each option i and each character c in Chars(i), if true, then c
cannot be the mnemonic for any other option j where j ≠ i:
Formalization according to our example:
Installation
OS X & Linux:
Install Node with asdf (version manager):
asdf install
Install dependencies:
npm installUsage example
Define options in index.ts:
// Menu options
const OPTIONS = ["cut", "copy", "cost"];Run program:
npm startThe program will print the answers:
Starting...
Problem was determined to be sat in 252 ms
---- Result: option [mnemonic] ----
cut u
copy y
mod d
Implementation in TypeScript
For more details on the problem and the implementation, visit the
blogpost.
Acknowledgment
Assignment from "Static Program Analysis and Constraint Solving" at Universidad Complutense de Madrid. Prof. Manuel Montenegro.