A graph of futures, weighted by chance.
Click empty space to add a state. Drag from one state to another to draw a transition. Press play — a token random-walks across your graph at the pace you set. The bars beside each state count visits; given enough time they settle into the chain's stationary distribution, which is why this little toy quietly underpins PageRank, language models, queueing theory, and most of statistical mechanics.
Selected state · stationary distribution
§ 02 · Live readoutWhy a graph of dice rolls explains so much
§ 03 · Notesπ. For most graphs you build, the bars line up within a few thousand steps.Implementation notes — sampling, normalisation, computing π
Each state stores an array of outgoing edges with raw weights. To sample a transition the simulator scales weights by their sum, draws a uniform random number, and walks the cumulative table — O(out-degree) per step. Weights are kept un-normalised internally so editing one slider doesn't irreversibly redistribute the others; the displayed percentages are always weight ÷ sum.
The stationary distribution is computed by power iteration: start with π uniform, then repeat π ← πP for a few hundred steps. For ergodic chains this converges to the dominant left eigenvector of P with eigenvalue 1. Disconnected components or pure cycles can produce no unique stationary — the readout in that case will simply not converge to the observed fractions, which is itself instructive.
Edge geometry is a cubic Bézier whose control points are offset perpendicular to the chord, so opposite-direction edges curve in opposite hemispheres and never overlap. Self-loops are a small circle anchored above the node. The token's position interpolates along the edge during each step, so faster speeds visibly trace the path it took.
Everything is one HTML file. Save it, open it offline, edit the
presets at the bottom of the script — they are just arrays of
{x,y,name} and adjacency dictionaries.