Runs
Runs appear here.
Results
1. Melodies as programs
A melody can be stored note by note, or as a short program that generates it. Programs are cheaper to store when the melody has structure — repetition, scales, mirror images. The model looks for programs that describe a melody well, and with a library it can reuse programs that worked before.
As notes this takes 12 symbols. As programs it is repeat C E F three times, then start at G and go up twice.
2. The notes
Six notes, from low to high. Click a note to hear it. Steps up and down move to the neighbouring note, and wrap around: one step up from B is C.
3. Primitives
The building blocks. In the Explore tab programs are shown in this function form, e.g.
repeat(C F, 3); tick raw terms there to see how they are actually written.
| Primitive | What it does | Example | Output |
|---|
Composing primitives
The output of one primitive can be the input of another:
4. Combinators
Programs are written as nested triples [r, f, x]: apply f to
x, where the router r says where each of the program's own
inputs goes. This is how a program can leave some arguments open — for example a library
program of type note_count→note still takes a note and a count. A router has one
letter per input:
| Letter | The input goes to… |
|---|---|
B | the argument x only |
C | the function f only |
S | both f and x |
K | neither — it is discarded |
For example [KK,[repeat,note_4],count_3] discards both of its two inputs and
computes repeat(G, 3). When all arguments are filled in, as in the programs the
model outputs, you can read [r, f, x] simply as f applied to x. Arguments
are written note_1_3 (the notes C F) and count_3 (the number 3).
5. Rate, distortion and β
Rate is how much it costs to store the programs: −log of their prior probability under the grammar, in nats. Long, unusual programs have a high rate.
Distortion is how many notes the programs get wrong: the edit distance between each melody segment and the program's output.
The model minimises
distortion + β · rate
With a small β it prefers exact but long programs (often memorize); with a
large β it prefers short programs even if they make mistakes. Sweep β in the Explore
tab traces this trade-off.
6. Libraries: PCFG, AG and HAG
A melody is split into segments — one per line in the Explore tab — that are compressed in order.
PCFG — a fixed grammar with no library. Every segment is compressed from scratch.
AG (adaptor grammar) — one global library. Programs used in a melody are cached once the whole melody is done, and become cheaper to reuse in later melodies.
HAG (hierarchical AG) — a local library is built up segment by segment, so programs from earlier segments become cheaper in later ones. After the melody they are merged into the global library.
The libraries follow a Pitman–Yor process. With m different programs used n times in total, a new program is built with probability
(α + d·m) / (α + n)
and a cached program used k times is reused with probability (k − d) / (α + n). Larger α and d favour new programs; smaller values favour reuse.
The bad recorder
Playing a tune from memory is lossy compression: you keep the gist and lose a few notes. Here the model stores each phrase of a tune as a program, with seven notes and no rhythm. Each player has a different β — the larger it is, the more the player wants a short program, and the more notes it gets wrong. Pick a tune and listen.
Your own tune
' or
, for an octave up or down, e.g. G, C E G C'. Each player takes
a little while, since the model runs in your browser.