Skip to the plate
FORMA PUBLIC DOMAIN GENERATIVE ATLAS / ED. 0.28
Plate 82, Sprott Quadratic Map: a still of the map / searched, not designed plate as the atlas renders it, in the attractors accent.

PL. 82  ·  ATTRACTORS / MAP / SEARCHED, NOT DESIGNED

Sprott Quadratic Map

Julien Clinton Sprott, 1993

OPEN THE LIVE PLATE ▸

DEFINITION

xₙ₊₁ = a₀ + a₁x + a₂x² + a₃xy + a₄y + a₅y²
yₙ₊₁ = a₆ + a₇x + a₈x² + a₉xy + a₁₀y + a₁₁y²
twelve coefficients, each a letter A–Y over −1.2 … 1.2

NOTES

Sprott’s idea was to stop designing attractors and search for them instead: pick twelve coefficients at random, iterate, test whether the orbit is bounded and its Lyapunov exponent positive, and keep the ones that pass. Hundreds of strange attractors fell out, and because each coefficient quantises to one letter, every one of them has a twelve-letter name that is also its complete definition — the code below *is* the attractor. The plate carries a curated set from the paper’s own examples; the window is measured from each orbit rather than typed, since no two of them land in the same place.

PROVENANCE

Origin
J. C. Sprott, "Automatic generation of strange attractors", Computers & Graphics 17(3), 1993, 325–332, and the book Strange Attractors: Creating Patterns in Chaos, 1993. The A–Y encoding maps each coefficient to −1.2 + 0.1·(letter − A)
Standing
Public domain — an iterated map and a search procedure
Constants
The code is a CHOICES list, not a slider sweep, because the space between two valid codes is not another attractor — most coefficient sets are unbounded or collapse to a point. Every code listed was put through Sprott’s own acceptance test first: bounded orbit and positive largest Lyapunov exponent. All twelve pass, from 0.036 to 0.270, each filling 11–34 per cent of its own bounding box
Source
doi:10.1016/0097-8493(93)90082-K

HOUDINI · VEX

The same published mathematics as a Detail Wrangle body. Paste it into a Wrangle with Run Over set to Detail; every constant is the published value plus a tweak channel, so Create Spare Parameters gives a slider that starts where the paper does.

// FORMA — PL. 82 · SPROTT QUADRATIC MAP — Julien Clinton Sprott, 1993
//   xₙ₊₁ = a₀ + a₁x + a₂x² + a₃xy + a₄y + a₅y²
//   yₙ₊₁ = a₆ + a₇x + a₈x² + a₉xy + a₁₀y + a₁₁y²
//   twelve coefficients, each a letter A–Y over −1.2 … 1.2
// Paste into a Detail Wrangle (Run Over: Detail), no inputs needed.
// Written from the published mathematics, not adapted from any code.
// Constants arrive at their published values. Press the node's Create
// Spare Parameters button and every tweak becomes a slider — starting
// at 0, the published figure, and moving in the constant's own units.
// https://forma-gen.com/#plate=sprott

float p_code = 0 + chf('code_tweak');       // coefficient code · live 0 .. 11

// The plate's own colour: FORMA's ATTRACTORS accent as a cosine ramp,
// brightest near t = 0 and t = 1, near-black around t = 0.5.
vector forma_ramp(float t){
  return set(
    0.0956 + 0.1039 * cos(6.28318530718 * (t + 0)),
    0.4041 + 0.4392 * cos(6.28318530718 * (t + 0.05)),
    0.46 + 0.5 * cos(6.28318530718 * (t + 0.1)));
}

// Sprott's own encoding: one letter per coefficient, A–Y across −1.2 to 1.2
// in steps of 0.1. Decoding the letters here rather than storing numbers
// keeps the constant and the paper's name for each attractor as the same
// thing. All twelve passed Sprott's acceptance test — bounded orbit,
// positive largest Lyapunov exponent — before they were listed.
int forma_pts  = 120000;
int forma_skip = 20;

string forma_codes[] = {
    "GLXOESFTTPSV", "MCRBIPOPHTBN", "VBWNBDELYHUL", "FIRCDERRPVLD",
    "QFFVSLMJJCCR", "LUFBBFISGJYS", "EJYDREGLYQPV", "HIYIWHOKNVCG",
    "MSSSRRPADDSO", "OIHVGHAHGYRK", "RALLTIOBDULT", "WJJFXGXHTRPG" };
string code = forma_codes[int(p_code) % 12];
float A[];
for (int i = 0; i < 12; i++)
    push(A, float(ord(code[i]) - 65) * 0.1 - 1.2);

float x = 0.05, y = 0.05;
for (int i = 0; i < forma_pts + forma_skip; i++){
    float nx = A[0] + A[1] * x + A[2] * x * x + A[3] * x * y + A[4] * y + A[5] * y * y;
    float ny = A[6] + A[7] * x + A[8] * x * x + A[9] * x * y + A[10] * y + A[11] * y * y;
    // a jittered code's escape goes back to the start, not into the cloud
    if (!isfinite(nx) || !isfinite(ny) || abs(nx) > 1e5 || abs(ny) > 1e5){
        x = 0.05;  y = 0.05;  continue;
    }
    x = nx;  y = ny;
    if (i < forma_skip) continue;
    // canvas y runs down; negated so the figure sits as the plate shows it
    int pt = addpoint(0, set(x, -y, 0.0));
    float u = float(i) / float(forma_pts + forma_skip);
    setpointattrib(0, "Cd", pt, forma_ramp(0.8 + 0.3 * u));
}