Rumora

Methods — the model, its parameters, and how to check them.

Methods

Everything the essay claims came out of the simulator on this site. This page states the model precisely enough to argue with, lists the parameters the published figures were produced at, and links to the source — which this site serves directly, so nothing here needs taking on trust.

The model

Every agent occupies one of four states. Unaware has not heard the claim. Believer heard it, holds it, and is still repeating it. Doubter heard it and rejects it, and may carry the correction. Fatigued still holds it but has stopped raising it — a silent carrier, and the reason a wave can return.

Agents also carry a conviction in [0,1], raised by every reinforcing contact. Conviction has three effects: it increases how often an agent brings the claim up, it reduces the probability a correction moves them, and it slows the rate at which they lose interest.

Uptake

For a believer contacting an unaware agent j, adoption probability is

p = virality · (1 − skeptic[j]) · (1 + socialProof · 2 · proof[j]) · (1 + repetition · exposures[j])

capped at 0.95, and multiplied by 0.45 if j has already met the correction. proof[j] is the fraction of j's own contacts currently repeating the claim — this is the complex-contagion term, and it is why four friends are not four times one friend. skeptic[j] is drawn per agent from a normal distribution around the population skepticism, so there are always credulous and stubborn tails.

Loss of interest

After a believer's contacts for a tick, they fall silent with probability

quit = stifling · (1 + 1.5 · staleFraction) · (1 − 0.6 · conviction)

where staleFraction is the share of that tick's contacts who already knew. This is the Daley–Kendall stifling rule, and it is what gives the model a finite infectious period and therefore a genuine epidemic threshold. An earlier revision omitted it; every parameter setting then saturated at about 98% reach and virality changed nothing but timing.

Correction

A correction converts believers with probability correctionStrength · (1 − resistance), where resistance rises with conviction and with local social proof. A correction that fails to land is not neutral: it raises conviction by 0.14 · backfire, and against a fatigued agent it may return them to actively spreading. Corrections also reach unaware agents, who become doubters — this inoculation is the mechanism behind the timing result, since its value is proportional to how many people the claim has not yet reached.

Networks

Generated fresh per run: Watts–Strogatz small world, Barabási–Albert scale-free, a stochastic block model for communities, and Erdős–Rényi as a null case. A node's audience per telling scales with the square root of its degree. Without that term, degree affects only who you hear from, hubs stop behaving like hubs, and scale-free networks wrongly resist spread more than clustered ones do.

Parameters

Published figures use these values unless the text says otherwise. They are the same defaults the simulator loads, in src/sim/model.js.

ParameterValueWhat it sets
n520agents
avgDegree7mean contacts
rewire0.09small-world shortcuts
seeds3agents who start believing
virality0.11base chance one telling lands
socialProof0.55weight on the complex-contagion term
repetition0.12illusory-truth gain per exposure
skepticism0.35population mean resistance
chattiness3tellings per believer per tick
amplification0.25popularity bias and out-of-network delivery
stifling0.18rate of losing interest
correctionStrength0.30persuasiveness of a fact-check
backfire0.35hardening from a failed correction

Reproducing the figures

Every number in the essay is a mean over 30 independent runs, each on a freshly generated network with a fresh seed. Runs are seeded, so a given seed reproduces a run exactly.

The quickest check is the page itself: set the controls to the values above, press Run 40 trials, and compare. For the table showing that timing beats strength, vary only factCheckTick and correctionStrength.

To run it outside the browser, the modules are plain ES modules with no dependencies and no build step. Fetch model.js, generators.js, rng.js and sweep.js, then:

import { runSweep } from './src/sim/sweep.js';
import { DEFAULTS } from './src/sim/model.js';

const early = await runSweep({ ...DEFAULTS, virality: 0.13, factCheckTick: 8,
  factCheckReach: 0.08, correctionStrength: 0.2 }, 30);
const late  = await runSweep({ ...DEFAULTS, virality: 0.13, factCheckTick: 55,
  factCheckReach: 0.08, correctionStrength: 0.8 }, 30);

console.log(early.mean, late.mean);   // ≈ 0.25, ≈ 0.97

The source

This site serves its own source. Nothing is minified and there is no build step, so these are the files the simulator above is actually running:

MIT licensed. If you find an error in the model, it is an error in the findings too, and I would like to know.

← Back to the essay