Files
smoothlife/plans/00_model_contract_and_historical_options.md

13 KiB
Raw Permalink Blame History

Macrostep 00 — Model contract and retained historical options

Objective

Create the permanent in-repository source of truth for the rewrite. Freeze the new deterministic behavior and exactly three retained historical options: RK4 relaxation reference, packed-unitary FFT, and sphere model. After this macrostep, normal implementation work must not depend on repeatedly reading /home/fpasqua/Nextcloud/VecchiProgetti/SmoothLifeAll.

Dependencies

None.

Required outputs

  • docs/model-contract.md: exact mathematics and update semantics.
  • docs/historical-options.md: the three retained options, their exact semantics, constraints, and rejected historical behavior.
  • docs/legacy-source-map.md: provenance with source file, line range, and source-file hash.
  • tests/fixtures/contract/: small deterministic scalar/field fixtures.

Phase 0.1 — Freeze the shared mathematical contract

Substep 0.1.1 — State, topology, and indexing

Record these invariants verbatim in docs/model-contract.md:

  • State is a scalar A ∈ [0,1] after every committed update.
  • Base domains are periodic: a 1-D circle, 2-D torus, or 3-D torus.
  • Storage is x-fast row-major. Define and test one canonical index mapping.
  • Signed periodic offset for even extent N is i for i < N/2, otherwise i-N.
  • Sphere is a closed spherical surface; delayed time is a 2-D spatial torus with circular temporal history.

Substep 0.1.2 — Sampled kernels

Freeze the exact base construction:

ri = ra / rr
w  = ra / rb
L(r;a,w) = 0                         when r < a-w/2
           1                         when r > a+w/2
           (r-a)/w + 1/2             otherwise
KD(r) = 1 - L(r;ri,w)
KR(r) = L(r;ri,w) * (1-L(r;ra,w))
M = circular_convolution(A,KD) / sum(KD)
N = circular_convolution(A,KR) / sum(KR)

Document that weights are sampled at lattice points. Generate the complete nonzero support and warn when radii are unsuitable for the domain. The historical component cutoff is not retained.

Record the known 2-D check for ra=10, rr=3, rb=10:

sum(KR) ≈ 279.216312
sum(KD) ≈  35.524035

Substep 0.1.3 — All rule curves

Use conventional TAU = 2π; the legacy shader variable called pi actually stores tau.

Freeze rising curves 07:

0 hard:       x >= a ? 1 : 0
1 linear:     compact linear transition over a±e/2
2 Hermite:    u²(3-2u), u=(x-a+e/2)/e, compactly clamped
3 sine:       0.5*sin((TAU/2)*(x-a)/e)+0.5, compactly clamped
4 logistic:   1/(1+exp(-4(x-a)/e))
5 atan:       atan((x-a)*(TAU/2)/e)/(TAU/2)+0.5
6 atan/cos:   (1.1*atan((x-a)/e)/(TAU/4)*cos(1.4(x-a))+1)/2
7 overshoot:  (logistic-0.5)*(1+exp(-(x-a)²/e²))+0.5

For types 07, W(n;a,b)=P(n,a,sn)*(1-P(n,b,sn)). Hard windows are exactly [a,b). Types 8 and 9 are complete windows:

base = logistic(n,a,sn) * (1-logistic(n,b,sn))
mid  = (a+b)/2
type 8 = base*(1-0.2*exp(-(20*(n-mid))²))
type 9 = base*(1+0.2*exp(-(20*(n-mid))²))

The mixer uses only curves 07 at center 0.5 and width sm. Curves 6/7 and resulting targets may overshoot; clamp only at the integration/commit points specified below.

Substep 0.1.4 — Four rule constructions

Freeze:

B = W(N;b1,b2)
D = W(N;d1,d2)
Q = selected mixer at M
1: S = mix(B,D,M)
2: S = mix(B,D,Q)
3: S = W(N, mix(b1,d1,M), mix(b2,d2,M))
4: S = W(N, mix(b1,d1,Q), mix(b2,d2,Q))

Phase 0.2 — Freeze dynamics and integration

Substep 0.2.1 — Base dynamics

mode 0 / Discrete:   A' = clamp(S)
mode 1 / Growth:     dA/dt = 2S-1
mode 2 / Relaxation: dA/dt = S-A

The base discrete path ignores dt and selected integrator. Modes 3/4 found in old keyboard code are experimental and excluded from the supported contract unless later added with explicit names.

Substep 0.2.2 — Integrators and clamp points

  • Euler: clamp(A + dt*k1).
  • AB3: deterministic Euler first step, AB2 second step, AB3 thereafter: (23k_n-16k_{n-1}+5k_{n-2})/12.
  • RK4: clamp every intermediate state and the final state.
  • Rk4RelaxationReference::StageState is the default: every relaxation stage uses S(stage)-stage.
  • Rk4RelaxationReference::StepOrigin is the retained historical option: k1=S(A0)-A0; intermediate k2..k4 compute neighborhoods/targets from their clamped stage but subtract A0.
  • The RK4 reference field exists structurally only inside relaxation+RK4 configuration. It is absent for discrete, growth, Euler, and AB3 rather than carried and ignored.
  • Preserve AB history only for presentation, inspection, pause, and scheduler changes.
  • Invalidate it for reset, ordinary state load, initializer/seed, rule, dynamics, timestep, integrator, kernel geometry, historical-option selection, topology, shape, variant, or backend changes. Switching away from and later back to AB3 never revives old derivatives.
  • An exact continuation checkpoint may restore AB history only when its complete validated model/backend-independent arithmetic descriptor matches.

Undefined AB history is discarded. This list is the authoritative history-invalidation policy used by every later macrostep.

Substep 0.2.3 — FFT algorithms

Freeze one local FftAlgorithm option for planar and multiscale convolution:

  • Standard (default): conventional unscaled forward transform, inverse scaled by 1/sample_count, then sampled-kernel normalization.
  • LegacyPackedUnitary: power-of-two 1-D/2-D/3-D GPU path retaining adjacent-real packing, half-width x complex spectra, historical bit-reversal/twiddle plan stages, unitary butterfly scaling, real/complex conversion, and spectral correction sqrt(sample_count)/kernel_sum.

The legacy FFT is a complete algorithm backend, not a global compatibility mode. It uses the same complete kernels and safe ping-pong resource layer as the new implementation. Old OpenGL compatibility syntax, working-directory shaders, framebuffer feedback, and resource behavior are discarded. An explicit legacy FFT request on CPU or unsupported GPU hardware fails clearly; it never silently substitutes Standard. A small CPU stage oracle and fixtures validate its packing, plans, scaling, spectra, and convolution.

Phase 0.3 — Freeze variant contracts

Substep 0.3.1 — Multiscale

Record all six combinations in a 2×3 matrix:

  • Independent inputs: each scale receives (ring_i(A), disk_i(A)).
  • Chained inputs: (ring_0,ring_1), (ring_1,ring_2), (ring_2,disk_2).
  • Sequential: update and clamp between scales, recomputing from the current state.
  • Ordered clamped sum: evaluate all responses from one snapshot, add/clamp each in scale order.
  • Mean increment: evaluate from one snapshot, add the arithmetic mean once, then clamp.

The new implementation supports growth and corrected relaxation. It rejects discrete dynamics because the three composition names do not define an unambiguous target aggregator; adding it later requires an explicit target-aggregation enum and fixtures.

Sequential composition always recomputes every required input from the current state. Shared-snapshot methods always use one original state. Relaxation names that current or original reference state explicitly. Additive mode-0 responses, stale chained fields, texture feedback, and undefined mode-2 sources are discarded.

Substep 0.3.2 — Sphere

Freeze:

  • six K×K active faces, legacy default K=128, internal radius R=K/2;
  • direction map normalize(face_normal + tan(uπ/4)face_u + tan(vπ/4)face_v);
  • area-weighted sample accumulation;
  • distance R*acos(clamp(dot(a,b),-1,1));
  • ri=ra/3, transition widths 1;
  • planar-to-geodesic conversion R*acos(1-ra²/(2R²));
  • spherical cap area 2πR²(1-cos(r/R));
  • direct replacement and fixed A+0.1(2S-1) modes.

Freeze one local SphereModel option:

  • Corrected (default): complete edge/corner mapping and per-center normalization by the actual sum of cell_area*kernel_weight, preserving a constant field.
  • Legacy: original six-face atlas geometry, side gutters with masked corner sectors, analytic disk normalization cap(ri), analytic ring normalization cap(ra)-cap(ri), original radius conversion/search stencil, and original discrete/fixed-0.1 smooth dynamics.

Both models use clamped dot products, explicit initialization, and ping-pong writes. Unclamped acos, texture feedback, and undefined atlas contents are discarded.

Substep 0.3.3 — Delayed time

Freeze:

  • periodic x/y field and history depth 16;
  • ri=ra/3, both transition widths 1, sampled stencil normalization;
  • head is the next layer to overwrite and latest=wrap(head-1,depth);
  • causal nearest-layer selection is wrap(latest-floor(distance+0.5),depth), so delay zero reads the latest committed state;
  • direct replacement or latest+0.1(2S-1), then clamp.

The historical head anomaly is discarded and has no configuration option.

Phase 0.4 — Preset baseline and fixture capture

Substep 0.4.1 — Freeze product preset authoring policy

All bundled product presets are newly authored directly in the versioned product schema established by Macrostep 01. Do not extract, convert, deduplicate, or migrate legacy preset rows, and do not require a product-preset count, grouping, or value correspondence with any legacy catalogue.

Each bundled preset must be a complete deterministic run definition with:

  • a stable ID, name, description, tags, and authoring provenance;
  • explicit variant, rules, dynamics, shape, backend, and presentation recommendations;
  • an explicit seed and deterministic initializer;
  • only the localized historical-option fields applicable to that run, with modern defaults otherwise.

Preset reviews validate schema completeness, unique identity, deterministic reproduction, and intentional coverage of supported variants and dynamics. Legacy sources remain documented provenance for the mathematical contract and retained option semantics, not input data for product presets.

Substep 0.4.2 — Freeze deterministic preset baselines

Use these modern baselines when authoring bundled presets; an individual preset may intentionally override them, but every override is explicit in that preset rather than inferred by migration:

  • Base: recommended shape 1024/512²/64³ by dimension, Euler, standard FFT, seed 1, cleared C++-inspired periodic splats, palette 2, and 3-D volume style 2. Because Euler is selected, no RK4-reference field is stored; a newly authored relaxation+RK4 preset defaults its applicable field to StageState.
  • Multiscale: 512², sequential composition, independent kernels, growth/relaxation only, standard FFT, seed 1, cleared base-style splats, and palette 7.
  • Sphere: K=128, R=K/2, SphereModel::Corrected, seed 1, cleared then seeded overlays, and palette 1. Any newly authored preset selecting SphereModel::Legacy is separately named and explicitly selects only that local option.
  • DT: 512², depth 16, causal delay, seed 1, a seeded box field replicated into all layers, and palette 7. The fixed model shape and all-layer initializer are intentional modern choices because the historical implementation followed the window.

These baselines are product-authoring policy, not legacy-row defaults.

Substep 0.4.3 — Freeze initializer algorithms

  • Base splats: clear to zero; choose continuous uniform centers; radius uniform in [0.5ra,ra); count floor(domain_volume / product(min(2ra,axis_extent)))+1; paint periodic interval/disk/ball samples to one. Use ChaCha with a specified draw order.
  • Sphere overlays: clear first; perform 1,000 draws with random face/center, radius 27, and random binary value.
  • DT boxes: build one seeded field from 1,000 rectangles with width and height independently 1019, then replicate it to all history layers. Use one documented boundary policy; do not retain gradual filling or undefined layers.

Commit exact seeded fixture arrays so later PRNG upgrades cannot silently change tests.

Substep 0.4.4 — Golden fixtures

Commit compact fixtures for:

  • scalar curve boundaries and overshoot;
  • a rule-surface grid spanning all valid enum combinations;
  • small asymmetric 1-D/2-D/3-D fields;
  • raw and normalized kernels;
  • direct convolution outputs plus legacy packed plans/stages/unitary scaling;
  • Euler/AB/RK synthetic derivatives, including both RK4 relaxation references;
  • all six corrected multiscale combinations;
  • source-frozen corrected/legacy sphere M/N/S/next fields at face centers, edges, and masked corners for both update modes, in addition to face transforms, normalization, and area totals;
  • DT layer-coded history and radial delay shells.

Use explicit arrays for essential goldens, not only PRNG seeds.

Phase 0.5 — Source retirement protocol

  1. Hash every consulted legacy source/config file and store the hashes in docs/legacy-source-map.md.
  2. Record source paths and relevant line ranges.
  3. Mark the specification plus the new contract as the implementation authority.
  4. Future legacy consultation requires a concrete discrepancy, and its finding must be copied back into the contract with provenance.
  5. The application, build, tests, and bundled preset assets must not require the legacy path.

Exit gate

  • Every formula, constant, mode, topology, retained historical option, and discarded defect has a local documented decision.
  • The newly authored bundled-preset policy and deterministic baselines are frozen independently of legacy catalogue rows.
  • Fixtures are readable without legacy tools.
  • A new implementer can build any mandatory backend using only this repository.