Home Notes Research CV Projects Outside of Math

Rank Increase Simulator: Technical Summary

The simulator takes an elliptic curve over \(\mathbb{Q}\) and a target rank, then searches the quadratic twists of the curve, in order, for the first one with that rank. This page explains the mathematics it relies on and how it computes everything inside your browser.

Try it live View on GitHub

Part 1 · The Mathematics

For background on elliptic curves, rational points, and rank, see my Research page. In short: the rational points \(E(\mathbb{Q})\) of an elliptic curve form a finitely generated abelian group \(E(\mathbb{Q}) \cong E(\mathbb{Q})_{\mathrm{tors}} \oplus \mathbb{Z}^{r}\), and the rank \(r\) counts how many independent points of infinite order the curve has.

Quadratic twists

If \(E: y^{2} = x^{3} + Ax + B\) and \(d \ne 1\) is a squarefree integer, the quadratic twist of \(E\) by \(d\) is

\[E^{(d)}:\ dy^{2} = x^{3} + Ax + B, \qquad \text{or equivalently} \qquad y^{2} = x^{3} + Ad^{2}x + Bd^{3}.\]

The curves \(E\) and \(E^{(d)}\) are not isomorphic over \(\mathbb{Q}\), but they become isomorphic over \(\mathbb{Q}(\sqrt{d})\), where \((x, y) \mapsto (x, y/\sqrt{d})\) carries one onto the other. Even so, their groups of rational points can look completely different. For a curve given in general Weierstrass form, the simulator computes the twist as \(y^{2} = x^{3} - 27c_4 d^{2}x - 54c_6 d^{3}\), where \(c_4\) and \(c_6\) are the standard invariants of \(E\), and then reduces it to its minimal model.

Why twists measure rank growth

Twists are exactly what controls the rank of \(E\) over a quadratic field. If \(K = \mathbb{Q}(\sqrt{d})\), then

\[\operatorname{rank} E(K) = \operatorname{rank} E(\mathbb{Q}) + \operatorname{rank} E^{(d)}(\mathbb{Q}).\]

The reason is that the nontrivial automorphism \(\sigma\) of \(K\) acts on \(E(K)\). Up to finite index, \(E(K)\) splits into the points fixed by \(\sigma\), which are the points of \(E(\mathbb{Q})\), and the points that \(\sigma\) negates, which correspond to the points of \(E^{(d)}(\mathbb{Q})\). So asking for a twist of rank \(r\) is the same as asking for a quadratic field over which the rank of \(E\) grows by exactly \(r\). This is the question behind my paper on rank growth in quadratic extensions.

What to expect: root numbers and Goldfeld's conjecture

Every elliptic curve has a root number \(w = \pm 1\), the sign in the functional equation of its \(L\)-function, and the parity conjecture predicts \(w = (-1)^{\text{rank}}\). As \(d\) varies, the root numbers of the twists of a typical curve split evenly between \(+1\) and \(-1\), so about half of the twists should have even rank and half odd. Goldfeld's conjecture sharpens this:

Goldfeld's conjecture. Counting twists by \(|d|\), 50% of the twists \(E^{(d)}\) have rank 0, 50% have rank 1, and twists of rank 2 or more make up 0%.

“0%” is not the same as “none”: higher-rank twists do occur, just with density zero. The simulator keeps a running tally of the ranks of every twist it checks, so you can watch the 50/50 split appear, and see how much rarer the higher ranks are.

How each rank is certified

No algorithm is known that always computes the rank, so the simulator combines a computation with theorems, and labels every result with how it was obtained:

  1. 2-descent. PARI/GP's ellrank performs a 2-descent, which yields a lower bound (from points it actually finds) and an upper bound (from a 2-Selmer group). If the bounds differ, it tries again with more effort. If they agree, the rank is proven.
  2. Analytic rank 0 or 1. Otherwise the simulator computes the analytic rank, the order of vanishing of the \(L\)-function at \(s = 1\). If it is 0 or 1, the theorems of Gross–Zagier and Kolyvagin show that the rank equals it, so the rank is again proven.
  3. Analytic rank 2 or more. No theorem yet links the two in this range. Rank equals analytic rank here only if the Birch and Swinnerton-Dyer conjecture holds, and the result is labelled assumes BSD.

Finding generators

Knowing the rank is not the same as knowing the points. The simulator also produces explicit generators of \(E(\mathbb{Q})\) modulo torsion:

Each curve also shows its minimal model, conductor, discriminant, \(j\)-invariant, root number, and torsion subgroup, with a link to look it up in the LMFDB.

Part 2 · How It's Built

The simulator is a static website with no server. All of the number theory is done by PARI/GP, the standard computer algebra system for number theory, compiled to WebAssembly so that it runs inside the browser at close to native speed. Nothing you enter is sent anywhere.

Interface

Reads the curve, shows results, and keeps the tally and log.

Search engine

Orders the twists and hands them out to a pool of workers.

Workers (up to 4)

Each runs its own PARI/GP interpreter in the background.

GP code

Computes models, ranks, and generators and returns them as JSON.

PARI/GP in the browser

The site ships the official WebAssembly build of PARI/GP (about 16 MB), unmodified. A short GP script (ris.gp) is loaded into each interpreter and defines the two entry points the page calls: one that analyzes a curve, and one that builds and analyzes a single twist. Results come back as JSON, with every integer and fraction sent as a string so that large coefficients survive the trip into JavaScript without losing precision.

A pool of parallel workers

Each PARI/GP interpreter runs in its own Web Worker, a background thread, so the page stays responsive while it computes. The pool uses up to four workers, one fewer than the device's processor cores. The first worker starts alone, so the large WebAssembly file is downloaded once and cached before the others request it. A twist that takes longer than a minute is stopped and its worker is replaced, so one unusually hard twist cannot stall the search.

An ordered search, run in parallel

The search goes through every squarefree \(d \ne 1\) with \(|d| \le X\) (up to \(X = 10{,}000\)), in the order \(-1, 2, -2, 3, -3, 5, -5, \ldots\); the list itself is built with a sieve. Twists are computed several at a time, up to three per worker in flight, but their results are reported strictly in order, so the first hit really is the twist with the smallest \(|d|\). To keep the search fast, each twist is first checked without generators; only a hit is recomputed in full. Results computed ahead of the hit are kept, so “find another” picks up exactly where the search stopped, and raising the bound \(X\) extends the list without redoing any work.

Safety

The page never builds PARI/GP commands from raw text. Before anything reaches the interpreter, every argument is checked to be an integer or a fraction, so user input cannot become code. Output is wrapped in markers so that stray messages from PARI/GP can never corrupt the JSON.

Testing and deployment

A smoke test runs the same WebAssembly build of PARI/GP under Node.js and checks the GP code against known answers from the LMFDB: curves of rank 0 through 5 (11.a2, 37.a1, 389.a1, 5077.a1, 234446.a1, and 19047851.a1), the minimal model of a non-minimal equation, the error for a singular curve, and the ranks of specific twists. The site is hosted on GitHub Pages, and a build number in the worker's address makes browsers fetch updated code instead of a stale cached copy.