# E024: Ulam spiral structure **size 101: 10,201 numbers and 1,252 primes** ```{figure} ../_static/experiments/e024_hero_101.png :width: 80% :alt: Ulam spiral preview (size 101) ``` **size 201: 40,401 numbers and 4,236 primes** ```{figure} ../_static/experiments/e024_hero_201.png :width: 80% :alt: Ulam spiral preview (size 201) ``` **size 301: 90,601 numbers and 8,769 primes** ```{figure} ../_static/experiments/e024_hero_301.png :width: 80% :alt: Ulam spiral preview (size 301) ``` **size 401: 160,801 numbers and 14,752 primes** ```{figure} ../_static/experiments/e024_hero_401.png :width: 80% :alt: Ulam spiral preview (size 401) ``` **size 999: 998,001 numbers and 78,359 primes** ```{figure} ../_static/experiments/e024_hero_999.png :width: 80% :alt: Ulam spiral preview (size 999) ``` *Prime counts shown are $\pi(\text{size}^2)$, i.e., the number of primes $\le \text{size}^2$.* **Tags:** `number-theory`, `quantitative-exploration`, `visualization` See: {doc}`../tags`. ## Highlights - Visual “pattern detector” for primes: highlights a diagonal structure that emerges in the Ulam spiral. - Parameterizable run: vary `--size` from the command line (default: `301`). - Writes reproducible artifacts (`params.json`, `report.md`, and figures) into `out/e024/`. ## Goal Render an Ulam spiral and highlight primes on the spiral grid to make diagonal structure (prime-rich diagonals) visible, then compare how that structure changes as the spiral size increases. ## Background (quick refresher) ### What is an Ulam spiral? An **Ulam spiral** places the positive integers on a square spiral (starting at 1 in the center, then winding outward) and then marks which positions are prime. A striking visual phenomenon appears: **primes cluster along certain diagonals**. A common explanation is that many diagonals correspond to simple quadratic polynomials in the spiral index; some of these produce unusually many primes for small inputs. See {cite}`WikipediaContributors2025UlamSpiral`. ### Optional background pages - {doc}`../background/prime-numbers` - {doc}`../background/quadratic-polynomials` - {doc}`../background/eulers-prime-generating-polynomial` ## Research question Which diagonals (or families of diagonals) in the Ulam spiral show unusually high prime density for a given window size, and how does that visual structure change as `size` increases? ## Why this qualifies as a mathematical experiment - **Finite procedure:** build a finite spiral window and run a deterministic primality test up to $\text{size}^2$. - **Observable(s):** diagonal structure, local “prime-rich” streaks, and how visibility changes with `size`. - **Parameter space:** the window size `size` (and, if you extend it, rendering/annotation choices). - **Outcome:** figures and a short report capturing the key observation and caveats. - **Reproducibility:** outputs saved to `out/e024/` with a parameter snapshot. ## Experiment design - **Computation:** map integers $1,\dots,\text{size}^2$ to lattice coordinates on a square spiral; mark primes. - **Coordinates:** are centered at (0,0) in the middle of the grid; x increases to the right, y increases upward; the spiral starts with 1 at the origin, then moves right to 2, and continues counterclockwise outward. - **Prime classification:** primes are computed using a sieve up to $\text{size}^2$. - **Outputs:** one or more figures showing prime positions on the spiral grid. - **Artifacts written:** - `figures/fig_01_ulam_spiral*.png` (main figure) and `figures/e024_hero_.png` (published hero) - `params.json` - `report.md` ### Plot axes and coordinate conventions The spiral is plotted on a centered Cartesian grid: - **x-axis:** horizontal offset from the center cell (0 at the center, negative left, positive right) - **y-axis:** vertical offset from the center cell (0 at the center, negative down, positive up) With an odd window size `size`, define $k=(\text{size}-1)/2$. The visible coordinate range is then $x,y\in\{-k,\dots,k\}$. If the implementation renders a 2D array with Matplotlib `imshow`, make sure the axis tick labels match these offsets (using an `extent` such as `(-k-0.5, k+0.5, -k-0.5, k+0.5)` and a consistent `origin`). When `origin="upper"` is used, the y-axis is flipped visually; interpret tick labels accordingly. ## How to run ```bash make run EXP=e024 ``` Override the spiral size (must be **odd**): ```bash make run EXP=e024 ARGS="--size 501" ``` Direct invocation (always works): ```bash uv run --extra dev python -m mathxlab.experiments.e024 --out out/e024 --size 501 ``` ## Notes / pitfalls - `size` must be **odd** so that the spiral has a single center cell. - Larger `size` means more numbers ($\text{size}^2$) and a longer run time. - “Looks-true” trap: visual regularity suggests hypotheses but does not prove theorems about primes. ## Extensions - Add a “diagonal density” quantitative overlay: estimate prime density per diagonal and plot it. - Annotate diagonals with the corresponding quadratic polynomials (for small windows). - Compare multiple sizes side-by-side (same styling and axis conventions). ## Published run snapshot If this experiment is included in the docs gallery, include the published snapshot (report + params). ```{include} ../reports/e024.md :start-after: "" :end-before: "" ``` ::: {dropdown} params.json (snapshot) :open: ```{literalinclude} ../params/e024.json :language: json ``` ::: ## References - Ulam spiral overview and basic properties: {cite}`WikipediaContributors2025UlamSpiral`. - Popular exposition and recreational-math context: {cite}`gardner1983martin`. - Narrative-style discussion of mathematical discovery/pitfalls (useful for “looks-true” effects): {cite}`hoffman1989archimedes`. See also {doc}`../references`. ## Related experiments - {doc}`e124` (Klauber triangle structure) - {doc}`e125` (Sacks spiral structure) - {doc}`e126` (Hexagonal number spiral structure) - {doc}`e127` (Quadratic prime-run atlas ($n^2 + a n + b$)) - {doc}`e128` (Quadratic modular obstructions (Euler-type)) - {doc}`e129` (Euler lucky constants for $n^2 + n + b$) ## Parameters (example) - size: `301` (implied grid: 301 × 301, integers `1..90,601`) ### Recommended `size` range The Ulam spiral is computed on a `size × size` grid, so runtime and memory scale roughly with $\text{size}^2$ (because about $\text{size}^2$ integers are classified as prime/not-prime). A practical range that works well for most runs: - **Minimum (still meaningful):** `size = 101` - **Default / recommended:** `size = 301` - **Comfortable upper range on typical laptops (varies):** `size = 999` - **Above ~`size = 1501`:** expect noticeably higher runtime (and potentially memory pressure), depending on the machine and the primality implementation. **Rule of thumb:** start with `301`, then try `501`, `701`, `901`. Increase further only if runtime remains acceptable. ## Summary We render the classic Ulam spiral for the first 90,601 positive integers and highlight primes on the spiral grid. Even at this moderate scale, faint diagonal “streaks” are visible: some diagonals contain noticeably more primes than nearby diagonals. ## Key observations - Several diagonals show higher prime density than the surrounding background. - Many regions still look close to “noise-like” at this resolution; the strongest diagonal effects are easiest to see when zooming. ## Interpretation The diagonal structure is a real phenomenon and is commonly explained by the fact that many diagonals correspond to simple quadratic polynomials in the spiral index; some quadratics produce unusually many primes for small inputs. This is therefore a useful “pattern detector” for prime-rich formulas — but it is not evidence that primes follow a simple global rule. ## Caveats - Finite window: patterns can look stronger/weaker depending on the chosen size and zoom level. - Visualization choices matter: marker size and interpolation can hide or exaggerate diagonal structure. - Grid mapping details (exact spiral convention and indexing) affect which diagonals appear most prominent.