Published
Edited
Dec 9, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function sim(opts) {
const W = opts.GENERATIONS + 1;
const M = 0.01 * opts.MUTATION_PERCENT;
const S = 0.01 * opts.SYNONYMOUS_PERCENT;
let counts = new Float32Array(W * W);
counts[0] = 100;
const data = [];
for (let generation = 1; generation <= opts.GENERATIONS; ++generation) {
// Mutate.
const next = new Float32Array(W * W);
const stats = {};
for (let s = 0; s < W; ++s) {
for (let n = 0; n < W; ++n) {
const c = counts[s + n * W];
{
const k = opts.fn(s, n);
stats[k] = (stats[k] || 0) + c;
}
next[s + n * W] += c * (1 - M);
next[s + n * W + 1] += c * M * S;
next[s + n * W + W] += c * M * (1 - S);
}
}
// Grow.
for (let s = 0; s < W; ++s) {
for (let n = 0; n < W; ++n) {
next[s + n * W] *= 0.01 * (100 + n * opts.PRESSURE);
}
}
// Scale down, make sure we don't hit infinity.
const total = next.reduce((a, b) => a + b);
const CAP = POPULATION_MODE == 'Scale to unit population' ? 100 : 10**30;
if (POPULATION_MODE == 'Scale to unit population' || total > CAP) {
for (let i = 0; i < W * W; ++i) {
next[i] *= CAP / total;
if (next[i] > CAP) next[i] = CAP; // If we already hit infinity.
}
}
// Store the results.
counts = next;
for (const k in stats) {
data.push({
generation,
population: stats[k],
value: parseFloat(k),
});
}
}
return data;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more