# kn-evaluator 2: open-string tree amplitudes at finite alpha', with certified error

This package evaluates the color-ordered open-string tree amplitude
A_n (the n-point Koba-Nielsen integral) at one kinematic point, given
as exact rational planar invariants, and returns a number with a
rigorous error statement.  In the SL(2,R) gauge z_1 = 0, z_{n-1} = 1,
z_n = infinity, with the canonical Parke-Taylor factor and alpha' = 1
(the massless Z-integral normalization; conventions in
`kn-evaluator/k2_chart.py`),

    A_n = int_{0 < z_2 < ... < z_{n-2} < 1} prod dz_i
          prod_{1 <= i < j <= n-1} (z_j - z_i)^{-alpha' s_ij} x PT(1,...,n),

so that at n = 4 A_4 = B(-s,-t) = Gamma(-s)Gamma(-t)/Gamma(-s-t).  The
integral converges when every planar invariant P(a,b) = s_{a,...,b-1}
is negative (the "convergent region", also called the chamber below);
at general kinematics it is defined by analytic continuation, which is
unique because A_n is meromorphic in the Mandelstam invariants.  The
package covers n = 4, 5, 6, 7, 8, 10 in the convergent region and
n = 4, 5, 6, 7 at general kinematics.

Two engines do the work: an exact associahedron-fan decomposition with
tensor Gauss-Jacobi quadrature in a C/MPFR kernel for the convergent
region (`kn-evaluator/`), and a Taylor-model engine in Julia that
continues each cone integral analytically, axis by axis, by
m = floor(-kappa)+1 subtractions on every axis whose exponent kappa is
negative, and returns an interval that contains the continued value
(`engines/`; derivation and proofs in `engines/CONTINUATION_V2_DESIGN.md`).
A single driver, `n_point.py`, builds the fan, classifies every cone
axis, chooses the route, prints a cost estimate, and (with `--run`)
executes and assembles the result exactly.

## Quick start

    sha256sum -c --quiet SHA256S.txt && echo MANIFEST OK   # verify the files
    # install: INSTALL.md (Julia 1.12.6 + a pinned environment, a C kernel, a few pip packages)
    python3 smoke_test.py --cores 0,1,2,3                   # a few minutes

The smoke test runs the driver end to end on both engines at five
points with closed-form references.  The transcript of the run that
produced this package's validation records (SMOKE_LOG.txt; four cores
of a loaded server, fresh Python environment and Julia depot) is:

    smoke test  2026-09-02T22:28:52Z  cores 80,81,82,83  run dir runs/smoke_20260902T222852Z/ (fresh, no resume)
      [PASS] S1 n=4 chamber vs Gamma: engine 4.20654631597636278 vs closed form 4.20654631597636278: 36.9 digits agree, pair-certified 30.8 digits, 1s
      [PASS] S4 n=5 chamber vs 3F2: engine 5.54313290646666392 vs closed form 5.54313290646666392: 24.3 digits agree, pair-certified 22.0 digits, 1s
      [PASS] S2 n=4 kappa=-1/2 (m=1) TM vs Gamma: TM [-1.198140234766, -1.1981402346653] (10.4 digits, guaranteed=True) vs closed form -1.198140234735592: CONTAINED, 2 fresh julia receipts, cpu 13s wall 20s
      [PASS] S3 n=4 kappa=-3/2 (m=2) TM vs Gamma: TM [-0.59907011767023, -0.59907011671521] (9.1 digits, guaranteed=True) vs closed form -0.5990701173677961: CONTAINED, 2 fresh julia receipts, cpu 13s wall 20s
      [PASS] S5 n=5 kappa=-1/3 (m=1) TM vs 3F2 continuation: TM [-1.9227770784216, -1.9227770131547] (7.8 digits, guaranteed=True) vs closed form -1.92277704780522: CONTAINED, 5 fresh julia receipts, cpu 36s wall 39s
    == SMOKE PASS (5 pass / 0 fail, 84s) ==  run dir runs/smoke_20260902T222852Z/
      evidence copied to: validation/smoke/smoke_20260902T222852Z

The interval endpoints and the closed-form agreements should be
reproduced exactly on any machine (they come from directed-rounding
interval arithmetic and pinned libraries); the wall times will differ.

A dry run of the driver at the n = 7 continued point
(`validation/n7/dry_run.txt`):

    $ python3 n_point.py 7 points/n7_continued.json
    n=7: fan 42 cones, dim 4; point n7_continued.json
      planar invariants: P(1, 3)=1/2, P(1, 4)=-2/3, P(1, 5)=-3/4, P(1, 6)=-3/5, P(2, 4)=-2/5, P(2, 5)=-5/7, P(2, 6)=-4/7, P(2, 7)=-5/8, P(3, 5)=-4/9, P(3, 6)=-5/9, P(3, 7)=-6/11, P(4, 6)=-3/7, P(4, 7)=-7/11, P(5, 7)=-7/12
      axis census: continued m=1: 14, convergent: 154
      all continued (dim, kappa) classes have been validated against an independent computation (README.md "Validated continuation classes"; python3 n_point.py --list-validated)
      route: tm
      TM route: 42 cones, NGRID=6, ORD=[8, 9], floor rad<=1e-6|mid| per cone, one NGRID+1 retry if a cone misses the floor
      per-cone: 0:+/+/1/+; 1:+/+/+/1; 2:+/+/1/+; 3:+/+/+/1; 4:+/+/+/1; 5:+/+/1/+; 6:+/+/+/1; 7:+/+/1/+; 8:+/+/1/+; 9:+/+/+/1; 10:+/+/+/+; 11:+/+/+/1; 12:+/+/+/+; 13:+/+/+/1; 14:+/+/+/+; 15:+/+/+/1; 16:+/+/+/+; 17:+/+/+/1; 18:+/+/+/+; 19:+/+/+/+; 20:+/+/+/+; 21:+/+/+/+; 22:+/+/+/+; 23:+/+/+/+; 24:+/+/+/+; 25:+/+/+/+; 26:+/+/+/+; 27:+/+/+/+; 28:+/+/+/+; 29:+/+/+/+; 30:+/+/+/+; 31:+/+/+/+; 32:+/+/+/+; 33:+/+/+/+; 34:+/+/+/+; 35:+/+/+/+; 36:+/+/+/+; 37:+/+/+/+; 38:+/+/+/+; 39:+/+/+/+; 40:+/+/+/+; 41:+/+/+/+
      PRE-RUN ESTIMATE (measured basis: the n=7 convergent-region and continued points and the n=6 and n=5 runs under validation/; NGRID scaling (n/ref)^dim and m>=2 overheads are EXTRAPOLATIONS): median-class 9.92 core-h, worst-class 28.14 core-h; + retries/tightening after a missed floor (measured at the n=7 continued point: 10.02 core-h first pass -> 19.92 core-h total, validation/n7/); at 1 core(s): 9.92-28.14 h wall; per-cone CPU limit 3600 s
    dry run only; add --run --cores c1,c2,...
    # exit code 0

With `--run --cores 0,1,...` the same command runs the 42 cones and
prints the certified interval; the value at this point, established by
two independent certified routes, is A_7 = 123.5059237 +/- 8.8e-6 (see
"Validation summary").  The measured cost of this point was 19.92
core-hours of wall time including retries on a heavily loaded server
(the CPU time at a comparable n=7 point was 0.55 of the wall time); see
"Measured cost" and KNOWN_LIMITATIONS.md item 2.

## Input format

A point is a JSON file `{"P": {"(a,b)": "p/q", ...}}` giving all
n(n-3)/2 planar invariants P(a,b) = s_{a,a+1,...,b-1} (polygon diagonal
{a,b}, 1 <= a < b <= n, 2 <= b-a <= n-2) as exact rationals; pair
invariants s_ij follow by second differences and momentum conservation
is checked exactly.  Examples for every packaged n are in `points/`,
with their invariants and roles listed in `points/README.md`
(`n7_convergent.json` is a convergent-region point; `n7_continued.json`
is the same point with P(1,3) = s_12 = +1/2, above the first resonance).

## The three routes

The driver picks the route from the cone exponents kappa (affine in the
Mandelstams); `--engine` forces one.

- **chamber** — every planar P(a,b) < 0 (every kappa > 0): the fan
  decomposition and the C/MPFR quadrature kernel.  Two evaluations on
  distinct grids, differing in both quadrature order and working
  precision, are run; their agreeing digits are the certified prefix.
  Seconds to minutes; n = 4, 5, 6, 7, 8, 10 (`kn-evaluator/README.md`).
- **tm** — any planar invariant positive (some kappa < 0): the
  Taylor-model continuation engine, cone by cone, with exact
  det-weighted rational assembly.  Certified interval; the driver refuses
  points on or within `--pole-dist` (default 1/32) of a string resonance
  (a non-positive-integer kappa), where the amplitude has a pole, and
  refuses n >= 8 (exit 3): the continuation route is validated for
  n <= 7 in this release; the n = 8 and 10 fans are included for the
  chamber route only (KNOWN_LIMITATIONS.md item 3).  Under a minute
  at n = 4-5; about five CPU-minutes at n = 6 (measured,
  `validation/n6/`); tens of core-hours at n = 7 (measured).
- **kinsys** — n = 6 with P(1,3) free and the other eight invariants at
  the n = 6 convergent-region point: an exact differential operator in
  an auxiliary variable, transported numerically (`kinsys/README.md`).
  Seconds per point, 27-29 digits, validated but not certified.

## What the words mean

- **certified**: a rigorous enclosure.  For the Taylor-model route the
  interval [inf, sup] contains the continued cone sum by theorem, given
  the three pinned Julia libraries (TaylorModels v0.12.0,
  IntervalArithmetic v1.0.11, TaylorSeries v0.22.4): every scalar enters
  as an exact rational, every integer power is a running product, the
  libraries' `guaranteed` flag is carried through every operation and
  checked at the two places a magnitude is extracted, the engine asserts
  the positivity that log and inv need, and an unbounded or
  non-guaranteed enclosure is a refusal at the engine, the assembler and
  the driver.  The continuation identity itself is Theorems 1 and 3 of
  the design note (elementary).  For the chamber route "certified" means
  the two-grid pair described above.  Arb balls from the independent
  contour engine used in validation are certified modulo Arb.
- **validated**: agrees with an independent computation to the stated
  digits (no enclosure is claimed).
- **reference**: a closed form, the analytic continuation of a closed
  form, or an independently computed number, used only for comparison.
- **extrapolated**: an estimate with no measurement behind it (cost
  figures marked as such).
- **receipt**: the JSON record written by one computation, carrying the
  value, its certified digits, the inputs and the cost
  (`runs/<point>/POINT_RECEIPT.json` for a point; `cone_<i>_n<NGRID>.json`
  per cone).
- **cone**: one maximal cone of the associahedron fan (42 at n = 7); the
  unit of work of both engines.  **cell**: the unit of the independent
  contour engine used in validation (a cone with a continued axis is two
  cells there).  **leg**: one of the two evaluations of a chamber-route
  pair.  **NGRID**: the number of boxes per axis into which the
  Taylor-model engine cuts a cone; a cone is retried once at NGRID+1 if
  its enclosure misses the **floor** (radius <= 10^-6 |mid|, the 6-digit
  requirement); the NGRID a cone ends at is its **generation**.
  **corner box**: a box touching w_a = 0 on a continued axis a, where the
  subtractions act; **spectator axis**: an axis of a corner box that is
  not continued; **slab**: a range of box indices on the last axis (the
  engine can integrate one slab per process).

Every printed number carries one of three grades.  **PROVEN**: a
certified interval, or a certified pair.  **ASSUMPTION**: certified
modulo an explicitly stated, untested class — today this means a
continued (dim, kappa) class that has not been cross-checked against an
independent computation at that dimension (only n = 7 classes other than
kappa = -1/2), which the driver lists at dry-run time and records in the
receipt; the theorem applies there just as elsewhere, but no second
route has been run.  Underlying every continued value is one further
identification, made with its motivation: that the continued cone sum
is "the amplitude" rests on the meromorphy of A_n in the Mandelstams
(Eberhardt-Mizera 2403.07051, Sec 2).  **REFERENCE**: comparison only.

## Validated continuation classes

The continuation theorem does not depend on the value of kappa or on
the cone dimension, but the package only calls a class **validated**
when the interval has been checked against an independent computation
at that dimension.  `python3 n_point.py --list-validated` prints this
table; a continued axis outside it puts the run in the ASSUMPTION grade.

| dim (n) | kappa | subtractions | checked against | record |
|---|---|---|---|---|
| 1 (n=4) | -1/2 | 1 | the Gamma closed form | validation/closed_form/ |
| 1 (n=4) | -3/2 | 2 | the Gamma closed form | validation/closed_form/ |
| 2 (n=5) | -1/3, -1/5 | 1 | the 3F2 closed form, continued in its parameters | validation/closed_form/ |
| 2 (n=5) | -3/2, -7/4, -6/5 | 2 (two cones with two continued axes) | the 3F2 closed form | validation/closed_form/ |
| 3 (n=6) | -1/2 | 1 | the holonomic reference value of the paper | validation/n6/ |
| 4 (n=7) | -1/2 | 1 | an independent Arb-ball contour computation | validation/n7/ |

## Validation summary

The records are under `validation/`; `validation/VALIDATION.md` is the
one-page index with every number.  All of them were produced by the
shipped files from a copy of this package installed in a fresh Python
environment and an empty Julia depot, except the n = 7 records, which
are the evidence of the 20-core-hour runs and were produced by the
engine's single-subtraction predecessor (`validation/engine_builds.md`).

| domain | what was checked | result | record |
|---|---|---|---|
| n=4, 5 chamber | pair vs the Gamma and 3F2 closed forms | 30.8 / 22.0 certified digits; agree to 36.9 / 24.3 | validation/smoke/ |
| n=7, 8, 10 chamber | pairs at two symmetric points | 13.9-17.1 / 10.7-14.3 / 3.4-5.8 digits | kn-evaluator/README.md, kn-evaluator/SMOKE_LOG.txt (n=7) |
| n=4 continued, kappa = -1/2 and -3/2 (one and two subtractions) | interval vs the Gamma closed form | contains it; 10.38 / 9.10 certified digits | validation/closed_form/ |
| n=5 continued, kappa = -1/3, -1/5 (one subtraction) | interval vs the 3F2 closed form continued in its parameters | contains it; 7.77 / 8.31 digits | validation/closed_form/ |
| n=5 continued, kappa in {-3/2, -7/4, -6/5} (two subtractions; two cones with two continued axes; NGRID 20) | same | contains it; 6.89 digits | validation/closed_form/ |
| n=5 P(1,3) line (kinsys, four points) | driver vs the 3F2 closed form | 32.2-34.6 digits of agreement | validation/closed_form/ |
| n=6 continued point, kappa = -1/2 on five cone axes | interval vs the holonomic reference value; kinsys route vs the same | contains it, 7.64 certified digits; kinsys agrees to 33.3 digits | validation/n6/ |
| n=7 convergent-region point | chamber kernel, contour computation (Arb), Taylor-model cones | the contour ball contains the kernel value (7.3 digits); 42/42 cone enclosures overlap the contour balls | validation/n7/ |
| n=7 continued point (14 cones at kappa = -1/2) | Taylor-model interval vs the contour computation, each fixed in a file whose hash was recorded before the comparison | the contour ball lies inside the interval; A_7 = 123.5059237 +/- 8.8e-6; the two enclosures overlap on an interval that fixes 6 digits | validation/n7/ |
| the same point, 4 cones re-run with the shipped engine | hex endpoints vs the records of the run above | 4/4 bit-identical | validation/n7/rerun/ |
| n=7 fresh continued point | Taylor-model route only | 129.0863406 +/- 6.07e-5, 6.33 certified digits; no second route | validation/n7/ |
| installs | fresh Python environment and empty Julia depot on the build machine; tarball install on a second machine | smoke test PASS | validation/VALIDATION.md; INSTALL.md |

What the n = 7 two-route agreement does and does not prove is stated in
KNOWN_LIMITATIONS.md item 9.

## Measured cost

Times are what the driver prints and records, not estimates, unless
marked.

- Chamber route (engine-reported core-seconds): n=4/5 seconds; n=7 0.10
  core-h for 3 evaluations on an idle machine (`kn-evaluator/README.md`;
  the pair in `kn-evaluator/SMOKE_LOG.txt`, run on the loaded server,
  is the transcript to compare with); n=8 2.7 core-h; n=10 70 core-h.
- Continuation, n=7, the continued point (14 cones with a continued axis
  at kappa = -1/2 + 28 with all axes convergent; NGRID 6, ORD 8/9):
  first pass 36071 s = 10.02 core-h (median 676 s, mean 859 s, max 2211 s
  per cone); 16 NGRID=7 retries 5.05 core-h; 9 NGRID=8 tightenings 4.85
  core-h: 19.92 core-h of wall-clock seconds on a 96-core server at load
  average about 600 (`validation/n7/README.md`, from the per-cone records).
- Continuation, n=7, the fresh point (CPU and wall both recorded,
  `validation/n7/n7_fresh_continued_value.json`): 11.6 core-h CPU against
  20.9 core-h wall on the loaded server.  On an idle machine expect the
  CPU figure.
- Continuation, n=6 (dim 3), the continued point through the driver at
  NGRID=8 (14 cones, 5 with a continued axis): 317 CPU-s, 152 s wall
  on 4 cores of the loaded server (`validation/n6/`), 7.64 certified digits.
- Continuation, n=5 (dim 2): the point with two subtractions per
  continued axis at NGRID=20: 40 CPU-s, 36 s wall on 4 cores
  (`validation/closed_form/`), 6.89 certified digits; the two
  one-subtraction points at NGRID=8: 32 and 31 CPU-s.  n=4:
  13 and 12 CPU-s per point (compile-dominated).
- Not measured: any continued point at n=8 or n=10 (the driver refuses;
  a scaling estimate is 100+ core-h per point at n=8), and any n=7 class
  other than kappa = -1/2 (KNOWN_LIMITATIONS.md items 1 and 3).

## Limitations

KNOWN_LIMITATIONS.md lists what is not established: the single
validated n=7 continuation class, the difference between the wall and
CPU figures, the refusal of the continuation route at n >= 8, slow
convergence of cones with two continued axes at two subtractions, the
validated-not-certified kinsys route, the single-route fresh n=7 point,
the pair-not-interval nature of chamber certification, the Julia 1.12.6
requirement, what the n=7 two-route agreement is conditional on, and
that the n=7 records were produced by the engine's predecessor.

## Files

    n_point.py                 the driver (n = 4, 5, 6, 7, 8, 10; dry run by default; --help; --list-validated)
    fan_units.py               exact fan/cone construction for one point
    smoke_test.py              5 checks vs closed forms, fresh run directory, a few minutes on four cores
    SMOKE_LOG.txt              transcript of the smoke test that produced validation/smoke/
    INSTALL.md                 fresh-machine instructions (exact commands; verify the manifest first)
    KNOWN_LIMITATIONS.md       what is not established
    SHA256S.txt                sha256 of every file in the package except runs/ and built kernels
    engines/tm_cell_v2.jl      the certified continuation engine (m subtractions, any number of axes)
    engines/assemble_tm_v2.py  exact rational det-weighted assembly (refuses on non-guaranteed cones)
    engines/CONTINUATION_V2_DESIGN.md   derivation, proofs, implementation, checks
    engines/tm_env/            pinned Julia Project.toml + Manifest.toml (julia_version 1.12.6)
    kn-evaluator/              the chamber engine: fans for n = 4..8, 10, C kernel source, checks, demos, its own README
    kinsys/                    the n=6 P(1,3)-line evaluator, its exact operator data and README
    points/                    example points for every packaged n, with a README listing their invariants
    validation/                the records behind every number above (VALIDATION.md; engine_builds.md;
                               CHANGES_FROM_TESTED_BUILD.md)
    runs/                      written by every evaluation and by smoke_test.py; not in the manifest, not in the tarball

## How to cite

If you use this package, please cite Matthew D. Schwartz, "Grassmannian
string integrals" (the paper this evaluator accompanies), and this
package as kn-evaluator 2, version 2026-09-02-r5.

## Attribution

Matthew D. Schwartz, Department of Physics, Harvard University.  Code
written by Claude (Anthropic) under the supervision of Matthew D. Schwartz.
# validation/n7 — the n = 7 records

Three n = 7 points appear here.  Their invariants are in `points/`
(`points/README.md`); throughout, "the convergent-region point" is
`points/n7_convergent.json`, "the continued point" is
`points/n7_continued.json` (the same invariants with P(1,3) = s12 = +1/2,
above the first resonance; 14 of the 42 cones then have one axis with
exponent kappa = -1/2), and "the fresh point" is
`points/n7_fresh_continued.json`.

Two words are used for the pieces of a computation.  A **cone** is one
of the 42 maximal cones of the n = 7 fan; the Taylor-model route
encloses each cone's integral in one interval.  A **cell** is the unit
of the independent contour route (an Arb-ball code that integrates each
cone over a deformed contour and splits a cone with a continued axis into
two cells): 42 cells at the convergent-region point, 56 at the
continued point.

## 1. The convergent-region point: three methods agree

| method | value | record |
|---|---|---|
| chamber kernel of this package, nq=20, prec=160 | 233.7029376813043394... | reproducible: `python3 n_point.py 7 points/n7_convergent.json --run --cores ...` (the pair nq=16/18 certifies 13.9-17.1 digits; the nq=20 value is the reference quoted in the next row); `dry_run` transcripts in `../dry_runs/` |
| contour route (Arb), 42 cells, exact prefactors, prec 160 | [233.7029 +/- 5.04e-5], imaginary part [+/- 1.37e-6] contains 0; 7.30 certified digits; CONTAINS the kernel value | `n7_convergent_arb_assembly.json` |
| Taylor-model cones, NGRID 6-7 | all 42 cone enclosures OVERLAP the contour route's cell balls; 0 disjoint | `n7_convergent_cones_taylor_vs_arb.txt` (one line per cone: NGRID, midpoint, radius, certified digits, guarantee flag, verdict) |

## 2. The continued point: two independent certified routes agree

    A_7 = 123.5059237 +/- 8.8e-6        (i.e. 123.50592(4))

| route | enclosure | record |
|---|---|---|
| contour route (Arb ball), 56 cells | 123.505923704821 +/- 8.7076e-6 (7.15 certified digits; imaginary part [2.3e-20 +/- 1.9e-6] contains 0; 6-digit floor pass) | `n7_continued_arb_ball.json` |
| Taylor-model route, 42 cones, single-subtraction continuation on the 14 continued cones | [123.505863253614, 123.505978832680] = 123.505921043147 +/- 5.7790e-5 (6-digit floor pass) | `n7_continued_taylor_assembly.json` (the assembled interval, hex endpoints, and the NGRID each cone ended at); per-cone results in `cones_continued/` |

Comparison (`n7_continued_two_route_comparison.md` gives the exact
rationals): the Arb ball lies entirely inside the Taylor-model interval,
so the intersection of the two enclosures is the ball; the two midpoints
differ by 2.66e-6; the intersection has width 1.74e-5 and fixes 6
digits.  KNOWN_LIMITATIONS.md item 9 states what this agreement is
conditional on.

The comparison was blind.  Each route's value was fixed in a read-only
file, and the sha256 of both files was recorded, before either value was
compared with the other:

    N7_SEALED_VALUE.json         0f55fd34bf2c395d34798b23e9c446db68a6211e2fb4bbc9c473808d3aef522c   (contour route; the value was withheld until the other route's file was fixed)
    ASSEMBLY_FLOOR_check.json    56b738be3145303a14f79fbe8803829e4b668d8169ef36eca99d0ef512d357b1   (Taylor-model route)
    pre-flight check of both files   2026-09-02T16:07:24Z
    comparison (run once)            2026-09-02T16:07:33Z
    UNSEAL_VERDICT_F7.txt        27cc0e4898b3e0ab02df20cd153b819ade566c1fd1ff881bdf2c1ef75cc080e5   (the comparison's output; its lines are quoted verbatim in n7_continued_two_route_comparison.md)

The two value files are reproduced here as `n7_continued_arb_ball.json`
and `n7_continued_taylor_assembly.json` with their label strings
reworded and decimal renderings added (each names its source file and
the sha256 above); every number in them is unchanged.

## 3. The fresh point: a single certified route

    A_7 = 129.0863406 +/- 6.07e-5      [129.08627990211872, 129.0864013076613], 6.33 certified digits

Taylor-model route only, 42 cones, no cone below the floor, NGRID 6 on
25 cones / 7 on 8 / 8 on 9; 41651.8 CPU-s = 11.6 core-hours of CPU
against 20.9 core-hours of wall-clock time on a loaded server; maximum
resident set 757 MB.  Record: `n7_fresh_continued_value.json` (assembled
value, per-cone summary of every run, CPU and wall accounting); per-cone
result files and the `/usr/bin/time` sidecars (`user sys wall
maxrss_kb exit`) in `cones_fresh/`.  No independent second route has
been run at this point (KNOWN_LIMITATIONS.md item 6).

## 4. The per-cone records and the engine that wrote them

`cones_continued/f7_<cone>_n<NGRID>.json` (67 files: 42 cones at NGRID 6,
16 retried at 7, 9 at 8) and `cones_fresh/sb2_<cone>_n<NGRID>.json` (68
files) are verbatim copies of the per-cone result files of the two
runs.  Fields: `inf_hex`, `sup_hex` (the IEEE-754 bit patterns of the
enclosure's endpoints; `inf`, `sup` decimal where present), `guaranteed`
(the interval library's flag), `boxes` (NGRID^4), `ord` (Taylor order),
`secs` (wall seconds), `method` (`optionB-subtraction` = one subtraction
on the continued axis `sub_axis`; `standard` = all axes convergent),
`uid` (cone index and cell selector), `engine`.

The engine named in every record, `tm_cell_rot.jl`, is the
single-subtraction engine that preceded the shipped `engines/tm_cell_v2.jl`
(`../engine_builds.md`); the shipped engine reproduces it operation for
operation at one subtraction on one axis (`engines/CONTINUATION_V2_DESIGN.md`,
Sec 7).  `rerun/` is the check of that statement with the shipped bytes:
`rerun_cones.py` rebuilt the job files of four cones of the continued
point exactly as the driver does, ran `engines/tm_cell_v2.jl` on them,
and compared the hex endpoints with the records above (results in
`rerun/results.json`, transcript `rerun_cones.log`, section 6).

## 5. Cost of the continued-point run (from the records in cones_continued/)

Summing the `secs` field of the per-cone files (wall-clock seconds on a
96-core server at load average about 600; CPU time was not recorded by
that run):

    NGRID 6, 42 cones:   36071 s = 10.02 core-h   (median 676 s, mean 859 s, max 2211 s, min 296 s per cone)
    NGRID 7, 16 retries: 18186 s =  5.05 core-h
    NGRID 8,  9 retries: 17444 s =  4.85 core-h
    total                          19.92 core-h

These are the "measured at the n=7 continued point" figures the driver
quotes in its pre-run estimate.  The fresh point (section 3) is the
measurement that recorded CPU time as well: its CPU total was 0.55 of
its wall total under the same load.

## 6. Re-run of four cones with the shipped engine

`python3 validation/n7/rerun_cones.py --cores 80,81,82,83 --cones 0,4,10,20 --ngrid 6`
(2026-09-02T22:58:12Z; fresh Python environment and Julia depot, `../VALIDATION.md`;
transcript `rerun_cones.log`; job files, result files and logs under
`rerun/`; summary `rerun/results.json`).  Each cone's job was built
exactly as the driver builds it and run through `engines/tm_cell_v2.jl`
at NGRID 6; the IEEE-754 hex endpoints are compared with the
corresponding `cones_continued/f7_<cone>_n6.json`:

    cone  0 (continued axis     ): [-2.2267449058541, -2.2267255511869]  hex c001d05fa2196c8a c001d0557c5c1fb6  = record  BIT-IDENTICAL   (306 CPU-s, 356 s wall; the record's wall 296 s)
    cone  4 (continued axis     ): [-5.1459124137762, -5.1458921289874]  hex c014956a1054ff55 c0149564bf0afa6b  = record  BIT-IDENTICAL   (374 CPU-s, 424 s wall; the record's wall 756 s)
    cone 10 (all axes convergent): [5.6585287774419, 5.6585293709119]  hex 4016a2555e2a5a1b 4016a25585fe16ae  = record  BIT-IDENTICAL   (1029 CPU-s, 1132 s wall; the record's wall 1732 s)
    cone 20 (all axes convergent): [8.0762753724182, 8.0762760499419]  hex 4020270d90cc0d7d 4020270da787efc8  = record  BIT-IDENTICAL   (1126 CPU-s, 1238 s wall; the record's wall 2019 s)

4 of 4 bit-identical: on these cones the shipped engine and the
engine that produced the n = 7 records compute the same floating-point
operations in the same order.
# kinsys: the n = 6 P(1,3)-line route by operator transport

`kinsys` is this package's name for a fast evaluation route that exists
for one family of n = 6 points: the planar invariant P(1,3) = s12 is
free (real or complex), the other eight planar invariants are fixed at
the n = 6 convergent-region point (`points/n6_convergent.json`; the
`base` block of `L6_p13line.json`).

## How it works

The Koba-Nielsen integral is deformed by an auxiliary variable z that
multiplies every coupled letter at once; at z = 0 the integral
factorizes into Beta functions, at z = 1 it is the amplitude.  The
deformed integral satisfies an exact linear differential equation in z
whose coefficients are polynomials in z and in P(1,3):

    L6(z; P13)   order 10, degree 16 in z, degree 11 in P13.

This operator was derived once, offline, from exact rational series and
operator guessing with exact annihilation certificates (SageMath +
ore_algebra; that derivation is not packaged).  It is shipped as
`kinsys/L6_p13line.json` together with the exact initial data (g(0) = 1),
the z = 1 exponents and the Beta prefactor.  A new point on the line
costs one exact specialization of L6 at P(1,3) plus one numerical
transport of the solution from z = 0 to z = 1.

`kinsys_driver.py` (python3 + mpmath only) does that transport with
re-expansions along a path that routes around the operator's true
singularities (the side is selectable, which implements the i-epsilon
prescription for complex P(1,3)), lands at z = 1 on the dyadic points
z = 1 - 2^-k with a Richardson elimination over the known exponent set,
and multiplies by the Beta prefactor.  It refuses points on a resonance
pole (P(1,3) a non-negative integer) and points where the analytic germ
at z = 0 is not unique.

## What the output is

The driver's number is VALIDATED, not certified: the digit estimate
comes from a two-precision run and the Richardson tail agreement, not
from a rigorous enclosure.  Its checks in this package:

- at the n = 6 continued point (`points/n6_continued.json`, P(1,3) =
  +1/2) against the holonomic reference value of the paper —
  `validation/n6/` (the agreement digits are stated there);
- on the n = 5 line (`L5_p13line.json`, the same construction with a
  3F2 operator of order 3) at four values of P(1,3) against the 3F2
  closed form — `validation/closed_form/`.

During development the driver was also compared with certified
ore_algebra transports of the same n = 6 operator at 12 points (real,
complex and near a pole): 26.8-32.0 digits of agreement, the driver's
own digit estimate within about one digit of the measured agreement.
Those transports need SageMath + ore_algebra and are not included.
Treat the driver's output as REFERENCE grade (README.md).

Measured cost: 26-47 s per point, 27-29 validated digits.

## Use

    python3 kinsys/kinsys_driver.py kinsys/L6_p13line.json --x1 3/2 --digits 30
    python3 kinsys/kinsys_driver.py kinsys/L6_p13line.json --x1 1 --imag 1/100 --side -1
    python3 n_point.py 6 points/n6_continued.json --engine kinsys --run

## Files

    kinsys_driver.py        the evaluator (python3 + mpmath)
    L6_p13line.json         the exact n=6 operator data for the P(1,3) line
    L5_p13line.json         the n=5 analogue (checked against the 3F2 closed form in validation/closed_form/)
# points/ — example kinematic points

Each file is `{"P": {"(a,b)": "p/q", ...}}`: all n(n-3)/2 planar
invariants P(a,b) = s_{a,a+1,...,b-1} of the color-ordered n-point
amplitude as exact rationals (conventions: kn-evaluator/k2_chart.py;
alpha' = 1).  P(1,3) = s_12.  A point is in the convergent region when
every P(a,b) < 0; a point with some P(a,b) > 0 needs the analytic
continuation (Taylor-model route).  The files named `*_continued*` are
the convergent-region point of the same n with one or more invariants
made positive.

| file | n | what it is | route |
|---|---|---|---|
| n4_convergent.json | 4 | P(1,3) = -1/3, P(2,4) = -1/2 | chamber |
| n4_continued_m1.json | 4 | P(1,3) = +1/2, P(2,4) = -3/4: one continued axis, kappa = -1/2 (one subtraction) | tm |
| n4_continued_m2.json | 4 | P(1,3) = +3/2, P(2,4) = -3/4: kappa = -3/2 (two subtractions) | tm |
| n5_convergent.json | 5 | P(1,3) = -1/2, P(1,4) = -2/3, P(2,4) = -3/4, P(2,5) = -4/5, P(3,5) = -5/6 | chamber |
| n5_continued_third.json | 5 | n5_convergent with P(1,3) = +1/3: kappa = -1/3 on two cones (one subtraction) | tm |
| n5_continued_fifth.json | 5 | n5_convergent with P(1,3) = +1/5: kappa = -1/5 (one subtraction) | tm |
| n5_continued_m2.json | 5 | P(1,3) = 3/2, P(2,4) = -9/8, P(3,5) = 6/5, P(1,4) = 7/4, P(2,5) = -13/16: kappa in {-3/2, -7/4, -6/5}, two subtractions on every continued axis, two cones with two continued axes | tm (use --ngrid 20) |
| n6_convergent.json | 6 | P(1,3) = -1/2, P(1,4) = -2/3, P(1,5) = -3/4, P(2,4) = -2/5, P(2,5) = -5/7, P(2,6) = -3/5, P(3,5) = -4/7, P(3,6) = -5/8, P(4,6) = -5/9; also the base of the kinsys P(1,3) line | chamber, kinsys |
| n6_continued.json | 6 | n6_convergent with P(1,3) = +1/2: kappa = -1/2 on five cone axes | tm, kinsys |
| n7_convergent.json | 7 | P(1,3) = -1/2, P(1,4) = -2/3, P(1,5) = -3/4, P(1,6) = -3/5, P(2,4) = -2/5, P(2,5) = -5/7, P(2,6) = -4/7, P(2,7) = -5/8, P(3,5) = -4/9, P(3,6) = -5/9, P(3,7) = -6/11, P(4,6) = -3/7, P(4,7) = -7/11, P(5,7) = -7/12 | chamber |
| n7_continued.json | 7 | n7_convergent with P(1,3) = +1/2: kappa = -1/2 on 14 of the 42 cones (the point of the two-route comparison, validation/n7/) | tm |
| n7_fresh_continued.json | 7 | n7_convergent perturbed by e/1000 with e successive decimal digits of pi (rule stated in the file), P(1,3) = +1/2; every negative kappa is -1/2 | tm |
| n7_continued_m2.json | 7 | n7_convergent with P(1,3) = +3/2: kappa = -3/2 (two subtractions) — a class not validated at n = 7; the driver prints the ASSUMPTION note | tm |
| n7_on_resonance.json | 7 | n7_convergent with P(1,3) = 1: on a string resonance; the driver refuses (exit 3) | — |
| n8_convergent_mild.json | 8 | symmetric family P(a,b) = -(b-a)(8-(b-a))/16 | chamber |
| n8_convergent_hard.json | 8 | symmetric family P(a,b) = -(b-a)(8-(b-a))/4 | chamber |
# kn-evaluator: open-string tree amplitudes over the associahedron fan

Standalone evaluator for the color-ordered open-string tree amplitude
(the n-point Koba-Nielsen integral) at convergent kinematics, with
certified error. Arbitrary-precision (MPFR) throughout; all chart,
kinematic, and fan construction is exact rational arithmetic.  This
directory is the chamber (convergent-kinematics) engine of the package
whose driver is `../n_point.py`; it also runs on its own as described
here.  "k=2" in the file names denotes the X(2,n) (associahedron) case
of the stringy integral, i.e. the color-ordered open-string tree
amplitude.

## What it computes

Color ordering (1,2,...,n); SL(2,R) gauge z_1 = 0, z_{n-1} = 1, z_n = inf:

    A_n = int_{0 < z_2 < ... < z_{n-2} < 1} prod dz_i
          prod_{1<=i<j<=n-1} (z_j - z_i)^{-alpha' s_ij} x PT(1,...,n),

with the canonical Parke-Taylor factor gauge-stripped (adjacent pairs
carry exponent -alpha' s_{i,i+1} - 1), alpha' = 1 by default. This is the
massless Z-integral normalization: at n=4 it gives exactly
B(-s,-t) = Gamma(-s)Gamma(-t)/Gamma(-s-t).

Kinematics: the n(n-3)/2 planar invariants P[a,b] = s_{a,...,b-1} are the
free coordinates; pair invariants follow by second differences; per-leg
conservation and every block sum are verified exactly in rational
arithmetic (massless legs; no Gram conditions imposed — valid momentum
configurations exist in sufficiently high spacetime dimension).

## Validity domain

The fan evaluator works in the **convergent chamber**: all planar
invariants P[a,b] < 0, where the integral converges as written and the
integrand is positive on every cone. It does not analytically continue.
Evaluation at general (physical) kinematics requires continuation; the
routes we follow are those of Eberhardt-Mizera [1] and
Figueiredo-Skowronek [2]. The `demos/continuation/` directory
demonstrates certified evaluation at physical kinematics (where the
defining integral diverges) at n = 4 and n = 5 on two independent
routes, validated against the classical continuations — see
`demos/continuation/README.md` for the demos' own scope and grades. The
general-kinematics evaluator for n = 4-7 is the Taylor-model
continuation route of the package driver `../n_point.py`
(`../engines/`, `../README.md`); the n = 6 value of the holonomic route
is the reference of `../validation/n6/`.

## Method

Exact associahedron-fan decomposition of the Koba-Nielsen integrand
(dimension n-3; Catalan C_{n-2} maximal cones: 42 / 132 / 1430 at
n = 7 / 8 / 10; every cone verified unimodular), then per-cone tensor
Gauss-Jacobi quadrature in a C/MPFR kernel. In-chamber the integrand is
positive on every cone, so the assembled sum has no cancellation and
per-cone-relative certification bounds the assembled relative error.

Checks that pass before any new number (`k2_fan.py`, `k2_gates.py`):

- the alpha' -> 0 limit of the fan sum equals the planar phi^3 amplitude
  as exact rational numbers at every n (e.g. n=10: 6314711/284497920 by
  fan and by triangulation sum independently);
- n=4 matches the Gamma closed form to 34.7-36.9 digits at three
  kinematic points;
- n=5 matches the exact 3F2 representation to 22.6-24.3 digits, with an
  independent double-quadrature cross-check;
- n=6 matches direct 3D quadrature to 15.7 digits;
- fan structure: cone count = Catalan(n-2), ray count = n(n-3)/2,
  unimodularity of every subcone, Monte-Carlo coverage, and an exact
  ray <-> planar-channel bijection.

## Error certification

Every quoted digit comes from a two-grid pair: two evaluations on
distinct grids, with adjacent legs differing in **both** quadrature order
n_q and working precision (one scoped exception, flagged where it occurs
in the values block below);

    cert_digits = -log10 |v1 - v2| / |v2|.

The printed digits of a certified value are its certified prefix. A
single evaluation carries unquantified quadrature error — always run a
pair before trusting digits.

## Requirements

- python3 with numpy, scipy, sympy, gmpy2, mpmath
- gcc with MPFR and GMP development headers (libmpfr-dev, libgmp-dev)
- normaliz (only for generating fans for n not shipped; fans for
  n = 4, 5, 6, 7, 8, 10 are included)

## Usage

Build the kernel:

    sh build.sh

Run the exact self-tests and closed-form checks (recommended first run;
the check suite takes about a minute):

    python3 k2_chart.py
    python3 k2_gates.py

Evaluate a point (fans for n = 4, 5, 6, 7, 8, 10 included):

    python3 evaluate.py n=7 nq=16 prec=160 procs=8
    python3 evaluate.py n=7 nq=18 prec=192 procs=8

`point=sym` (default) is the symmetric point P[a,b] = -(b-a)(n-(b-a))/4;
`point=mild` is the same family at scale 1/16; `point=FILE` reads a JSON
dictionary `{"a,b": "p/q", ...}` of all planar invariants (the "planar"
blocks in `k2_points_receipts.json` are in this format). Generate a fan
for another n (exact build + full check suite; needs normaliz):

    python3 k2_fan.py 9

The certification runs that produced the reference values below, with
per-cone checkpoint/resume:
`python3 k2_stage3.py [procs] [max_hours]` (scale-1/4 point) and
`python3 k2_stage3b.py [procs]` (scale-1/16 point). Note the n=10 legs
in these runs total ~70 core-h.

## Reference values (alpha' = 1; printed digits = certified prefix)

Both points are the symmetric dihedral family
P[a,b] = -(b-a)(n-(b-a)) * mu (exact rational tables for n = 7, 8, 10 at
mu = 1/4 in `k2_points_receipts.json`; the mu = 1/16 values are those
divided by 4).

Grading: the n=7 and n=8 values are certified to 10.7-17.1 digits by
two-grid pairs; the n=10 values are recorded at 3.4 and 5.8 digits
respectively — they are **not** under the same "certified" umbrella.
Every printed digit below is a certified digit.

    "hard" point (mu = 1/4; adjacent s_{i,i+1} = -5/2, -3, -4):
      A_7  = 6.6962601982294e-4    (13.9 certified digits; pair n_q 16/18)
      A_8  = 4.5679752769e-6       (10.7 certified digits; pair n_q 14/16)
      A_10 = 3.67e-12              (3.4 digits; pair n_q 7/8 — see rate wall)

    "mild" point (mu = 1/16; adjacent s_{i,i+1} = -5/8, -3/4, -1):
      A_7  = 80.804343524434439    (17.1 certified digits; pair n_q 16/18)
      A_8  = 67.118892116981       (14.3 certified digits; pair n_q 14/16)
      A_10 = 12.3994               (5.8 digits; pair n_q 6/7, same-precision)

One scoped exception to the both-parameters rule: the n=10 mild-point
5.8-digit pair (n_q = 6 vs 7) shares its 160-bit precision and differs
only in grid order.

Reproduction commands (each pair gives the value and its certification):

    # A_7, hard point, 13.9 digits          (~5 core-min total)
    python3 evaluate.py n=7  nq=16 prec=160 procs=8
    python3 evaluate.py n=7  nq=18 prec=192 procs=8

    # A_8, hard point, 10.7 digits          (~2.4 core-h total)
    python3 evaluate.py n=8  nq=14 prec=160 procs=16
    python3 evaluate.py n=8  nq=16 prec=192 procs=16

    # A_10, hard point, 3.4 digits          (~63 core-h total)
    python3 evaluate.py n=10 nq=7  prec=160 procs=32
    python3 evaluate.py n=10 nq=8  prec=128 procs=32

    # mild point: same commands with point=mild
    # (n=10 mild pair: nq=6 and nq=7, both prec=160)

`SMOKE_LOG.txt` in this directory is a complete transcript of a clean-
directory build + check run + the n=5 and n=7 evaluations, with the
digit-agreement checks — use it as the expected-output reference.

## The rate wall (measured)

The convergence rate of the tensor-GJ fan evaluation falls with the
maximum planar exponent X_max = alpha' |P|_max:

    n    X_max    digits per grid step
    5    1.5      1.16-1.18
    7    3        0.89          (mild point, X_max 3/4: 0.89)
    8    4        0.85          (mild point, X_max 1:   0.87)
    10   25/4     0.69          (mild point, X_max 25/16: +3.0 digits at
                                 identical grids vs the hard point)

At low X the rate saturates near the analyticity-limited quadrature rate;
by X ~ 6 the weighted-Gauss coverage threshold has cut it to ~0.69
digits/step, which prices deep-stringy 10-digit targets out of
tensor-quadrature range at n=10. The two-point comparison at identical
grids isolates the effect cleanly.

## Cost (measured)

    n    cones    cost per point (3 certification legs)
    7      42     0.10 core-h    (seconds at 32 processes)
    8     132     2.7  core-h    (minutes)
    10   1430     70   core-h    (hours)

Scaling: C_{n-2} x n_q^{n-3} quadrature points per leg; kernel throughput
1.5-3.0e4 points/s/core at 192-256 MPFR bits. For orientation: n=12 at
these targets is O(10^4) core-h for tensor quadrature — the honest wall.
Workers are single-threaded MPFR processes.

## Files

    ckernel_k2.c        MPFR tensor Gauss-Jacobi kernel (C)
    build.sh            kernel build script
    k2_chart.py         exact chart: kinematics, exponents, self-tests
    k2_fan.py           fan builder + structural checks (writes fan_k2_n*.json)
    k2_engine.py        fan evaluation driver (checkpoint/resume)
    k2_gates.py         closed-form checks (n=4 Gamma, n=5 3F2 + quadrature)
    k2_stage3.py        certification runs, scale-1/4 point
    k2_stage3b.py       certification runs, scale-1/16 point
    evaluate.py         single-point CLI
    smoke_check.py      n=5 / n=7 certification pairs vs references
    trop37.py           tropical model / exact subcone task builder
    fan_build37.py      exact BFS common-refinement fan machinery (normaliz)
    engine_run37.py     Gauss-Jacobi node builder, axis ordering, helpers
    gauss_jacobi.py     Jacobi polynomial recurrence (gmpy2)
    fan_k2_n{4,5,6,7,8,10}.json   pre-built fans, all checks passed
    k2_points_receipts.json       exact rational kinematic tables (mu=1/4)
    SMOKE_LOG.txt       expected output of a clean build + run
    demos/continuation/ certified general-kinematics demos, n=4/5
                        (contour + holonomic routes), with their logs,
                        result records, and their own README

## References

[1] L. Eberhardt and S. Mizera, "Lorentzian contours for tree-level
    string amplitudes," arXiv:2403.07051 [hep-th].

[2] C. Figueiredo and M. Skowronek, "Cuts and Contours,"
    arXiv:2506.05456 [hep-th].

## Attribution

Matthew D. Schwartz, Department of Physics, Harvard University.  Code
written by Claude (Anthropic) under the supervision of Matthew D. Schwartz.
# General-kinematics continuation demos (n = 4, 5)

These demonstrate certified evaluation at PHYSICAL kinematics — where the
defining Koba-Nielsen integral diverges — at n = 4 and n = 5, validated
against the classical continuations, on two independent routes:

- `contour/`   — certified contour evaluation (generalized Pochhammer):
  the Eberhardt-Mizera tube/cell complex [1] and the Figueiredo-Skowronek
  sum over tori [2], both built from the papers' constructions and
  checked identically. Every number is an arb ball (certified error),
  computed with python-flint's `acb.integral`.
- `holonomic/` — certified holonomic transport (SageMath + ore_algebra):
  the integral is holonomic in a worldsheet/modulus variable with the
  Mandelstams as exact rational parameters; continuation in s is carried
  by meromorphy of the exact construction (operator, initial conditions,
  canonical bases). Note the amplitude is NOT holonomic in the
  Mandelstams themselves (it has infinitely many poles per channel), so
  there is no ODE-in-s shortcut; the transport runs in the modulus.

The same conventions as the main package (k2_chart.py): massless
Z-integral normalization, alpha' = 1, planar-invariant kinematics. All
chamber anchors tie back to the fan evaluator in `kn-evaluator/`.

The same holonomic route was run at n = 6 (its pipeline is not
packaged; the n = 6 P13-line driver in `kinsys/` at the package root is
its shipped descendant); the resulting value is the reference that the
package's own routes are checked against in `validation/n6/`.

## What passes, by demo (all logs in these directories are the check runs)

`holonomic/brick1_n4.sage` (n=4, ~10 s): certified transport values at 3
chamber + 3 physical rational points, every value >= 40 certified digits
and >= 40 digits against the Gamma closed form (check threshold 12); an
exact structural check on the subdominant connection coefficient; the
branch demonstration: conjugate approach s = sigma +/- i*delta gives
certified conjugate values (Schwarz), the two approaches agree off-pole
in the delta -> 0 limit (meromorphy: poles, no cuts in s), the monodromy
lives in the transport modulus with certified loop eigenvalues
{1, e^{-2 pi i t}} (the Eberhardt-Mizera channel phase), and near the
pole s = 2 the conjugate pair A(2 +/- i/100) shows the divergent
imaginary parts of the i-epsilon structure, matching -Res/delta.

`holonomic/brick2_n5.sage` (n=5, ~15 s): the cross-term deformation
gives a 3F2 system; certified transport at the chamber anchor + 2
physical points (one and two flipped invariant axes) + 2 complex-axis
points, every value >= 40 certified digits and >= 39.7 digits against
mpmath hyp3f2's independent parameter continuation (threshold 8); closed
z-loop monodromy eigenvalue e^{+2 pi i gamma}, gamma = -alpha'*s_234
exactly; operator acquisition demonstrated three ways (classical
theta-form, exact series-annihilation certificate, and guessing from 20
exact series terms — the pattern that generalizes to higher n).

`holonomic/gate_mpmath.py` (seconds): INDEPENDENT check — plain
python3 + mpmath (no Sage) recomputes every reference and checks the
result records (`brick1_receipt.json`, `brick2_receipt.json`) written
by the two Sage scripts. Exit 0 = all checks pass.

`contour/contour_b1.py` (n=4, ~5 s): the EM tube form and the classic
Pochhammer double loop (explicit winding phases, no fitted signs).
Physical points certified to 66.5-69.9 digits, agreement with the Gamma
closed form to 76.6-85.0 digits; a complex-s phase point; chamber tie to
the package's fan evaluator at its own two-grid depth (34.7/36.9
digits). See `b1_gates.log`.

`contour/contour_b2.py` (n=5, full suite ~2-3 h single-core): BOTH n=5
cell structures — the EM pentagon complex (11 cells: interior, 5 edge, 5
vertex, per-channel Wick criterion, rigorous tail-bound balls on
unrotated axes; `cells_n5.py`) and the FS sum over tori (5 tori = the
maximal cones of the g-vector fan = Catalan C_3, all channels rotated;
`fs_n5.py`). Checks (`b2_gates.log`): exact structural identities on
every cell axis; the e_ij = 0 tiling identity; per-cell agreement with
direct quadrature; chamber assembly vs the exact 3F2 and the package
evaluator (EM 17.4-17.8, FS 34.8-37.6 digits); and the PHYSICAL points —
with 3 and 4 of 5 channels rotated — vs the 3F2's independent
continuation: EM 13.4-14.9 digits (certified 10.7-12.4), FS 35.6-39.2
digits (certified 22.3-23.7), plus EM-FS cross-agreement. The FS
structure is markedly the tighter of the two at n=5.

## Requirements and install

Contour demos: the main package requirements plus python-flint >= 0.8
(`pip install python-flint`), and the kernel built (`sh ../../build.sh`
from this directory, or `sh build.sh` from the package root).

Holonomic demos: SageMath >= 10 with the ore_algebra package. Two-line
install (any Sage >= 10 works; conda-forge shown):

    conda install -c conda-forge sage
    sage -pip install ore_algebra

`gate_mpmath.py` deliberately needs only plain python3 + mpmath.

## Run

    cd demos/continuation/contour
    python3 contour_b1.py                    # n=4, seconds
    python3 contour_b2.py                    # n=5 full check suite, hours

    cd demos/continuation/holonomic
    sage brick1_n4.sage                      # n=4, ~10 s, writes brick1_receipt.json
    sage brick2_n5.sage                      # n=5, ~15 s, writes brick2_receipt.json
    python3 gate_mpmath.py                   # independent check

The `.log` files beside the scripts are recorded runs and double as
expected-output references.  The two Sage logs (`brick1_n4.log`,
`brick2_n5.log`; SageMath 10.7 + ore_algebra 0.5, 2026-08-26) were
recorded by an earlier revision of the two `.sage` scripts whose
printed headings differ from the current ones (SageMath is not
installed on the machine that assembled this package); every number in
them is unchanged.  The python logs (`b1_gates.log`, `b2_gates.log`,
`gate_mpmath.log`) were recorded with the shipped scripts.

## References

[1] L. Eberhardt and S. Mizera, "Lorentzian contours for tree-level
    string amplitudes," arXiv:2403.07051 [hep-th].

[2] C. Figueiredo and M. Skowronek, "Cuts and Contours,"
    arXiv:2506.05456 [hep-th].
