Nestor
The content on this page was written by AI under human supervision.
Nestor computes definite integrals numerically to high precision (tens of digits or more) and reports only the digits that two successive refinements of the calculation agree on. You give it a Python integrand, an interval, the number of digits you want and, if the integrand is singular at an endpoint, a short declaration of how. It returns an mpmath number, or stops with an error and no number when the requested agreement is not reached. An integrand may itself call Nestor, so a multiple integral is done as nested one-dimensional ones, and the outermost level can be spread over many processor cores. A separate module in the package, nestor.dispersion, integrates a spectral density against a smooth kernel when the density has known singularities at thresholds, by subtracting the singular part and adding it back in closed form.
What it does
Nestor is built on tanh-sinh (double-exponential) quadrature, the rule of Takahasi and Mori: the substitution $x=\tanh(\tfrac{\pi}{2}\sinh t)$ maps the interval onto the whole line and the trapezoid rule is applied in $t$. The weights fall off doubly exponentially toward the ends, so integrable endpoint singularities such as $x^{-1/2}$ or $\log x$ cost nothing extra. Halving the step reuses every node already computed, so each refinement level contains the previous one, and Nestor uses that nesting as its test. It raises the level, working with guard digits beyond the request, until two successive levels agree to at least the requested number of digits, and returns that value together with the measured agreement. If the schedule of levels runs out first it raises CertFail, whose message states how many digits the run could have delivered, and returns no value.
Two routes do the work. The serial route drives mpmath's tanh-sinh rule through increasing depths, ten guard digits above the request; the upper limit may be mp.inf. The explicit-grid route builds Nestor's own node list at level md (step $h=2^{-md}$, default 6) and evaluates the nodes in chunks over a pool of nproc worker processes. The level md-1 result comes for free from the even-numbered nodes; if that self-consistency falls short of the request, the route climbs to md+1, md+2, md+3. The grid route is taken whenever nproc>1, md is given, a singular endpoint is declared, or wants_dists is set. Its nodes are placed by their distances from each endpoint without cancellation, whereas the stock rule loses about half its working digits at an inverse-square-root endpoint. It is also the route for expensive integrands, typically ones that are themselves inner Nestor integrals: a serial outer integral would leave all but one core idle.
Before any quadrature, singcheck tests the endpoint declaration against the integrand. The declaration is a dictionary such as {"a": {"type": "algebraic", "exponent": -0.5}, "b": {"type": "none"}}, with types none, algebraic and log; an omitted endpoint counts as none. Nestor samples $|f|$ at distances $10^{-2}$ to $10^{-6}$ from each endpoint and measures the log-log slope. The run stops with SpecRefusal if an endpoint declared regular has samples growing toward it with a slope below $-0.05$, or if a declared exponent misses the measured slope by more than 0.15. A log declaration must show growth with a slope near zero (within 0.2), or it is refused as well. An exponent of $-1$ or below (not integrable) is refused before any sampling; a sample that is not finite is refused too. With no declaration nothing is checked, and the record says so.
Every run can write a JSON record. It holds the configuration, checksums of the engine files, the singcheck result, and one entry per level (value string, elapsed seconds, agreement digits, plus node count and worker process ids on the grid route). It ends with either the value as a decimal string or the refusal's class, message and exit code. Exit codes are 0 for success, 3 for a failed check and 4 for a missing dependency or unimportable integrand (2 is reserved). A SIGTERM during a run becomes AbortRefusal, recorded before the process exits; an exception inside the integrand becomes EvalRefusal with the original attached.
Limits. Nestor is a numerical integrator, not a symbolic one, and its agreement figure is measured self-consistency rather than a proven error bound: a bias shared by every level, for example a truncated series inside your own integrand, is invisible to it. Singular behavior must sit at the endpoints and be declared; split the interval at an interior singularity yourself. For a singular endpoint at nonzero $a$, or at both ends, write the integrand as f(u, d_a, d_b) and pass wants_dists=True, so it receives the distances to both endpoints at full relative accuracy. Parallel runs need the integrand as an importable "module:function" string, because the workers re-import it; a bare Python callable is run serially, with a log line saying so.
A separate module, nestor.dispersion, handles dispersion integrals $I=\frac{1}{\pi}\int\rho(w')\,K(w')\,dw'$, in which a spectral density $\rho$ (typically the imaginary part of a self-energy, expensive to evaluate) multiplies a kernel $K$ that is cheap and analytic between thresholds. The density is not smooth: it switches on at the lowest threshold $w_\ast$ like $(w'-w_\ast)^{\alpha}[\log(w'-w_\ast)]^{m}$ and may jump at higher thresholds, so a Gauss–Legendre rule gains digits only polynomially in the number of nodes. The module breaks the range into panels at the thresholds, which is all a finite jump needs, and on a short sub-panel next to each singular threshold it subtracts the known model $S(w')=\sum_j c_j\,(w'-w_\ast)^{\alpha_j}[\log(w'-w_\ast)]^{m_j}$. The difference $(\rho-S)K$ is analytic, so tanh-sinh converges exponentially on it, and $\int S\,K$ is added back in closed form: with $K(w')=\sum_n K_n (w'-w_\ast)^n$ every term is a moment $\int_0^L u^{p}(\log u)^{m}\,du$, which is elementary. You supply $\rho$ and $K$ as Python callables and a list of panels giving each threshold's side, position, exponents and coefficients $c_j$ (known in closed form, or fitted from a few accurate values of $\rho$ near the threshold); the result is an mpf.
The dispersion module is plain quadrature without the agreement test of integrate: repeat the call at two tanh-sinh levels (the maxdegree argument) or two precisions and keep the digits that agree, or hand the panel integrands to nestor.integrate. Fixing the level also fixes the nodes in advance, so a density that obeys a differential equation can be produced at every node in one pass with Wayfinder instead of a fresh computation per node. The sub-panel width and the Taylor radius must both be smaller than the distance from the threshold to the nearest singularity of $K$, or the add-back is wrong without warning. The closed-form moments cover $p\gt-1$ and log powers 0, 1 and 2, and $K$ must be analytic inside every panel. The package includes one worked kernel, examples/box1_dilog.py: the finite part of the one-loop box with massless external legs, three internal lines of squared mass m2 and one of squared mass M5, in pySecDec's normalization. Two of its Feynman-parameter integrals are done analytically and the last by a fixed Gauss–Legendre rule whose accuracy does not depend on M5, so a call at 40 to 50 digits takes a few milliseconds; make_K turns it into a kernel $K(w')$ with M5 set to $w'$ for the panels. It covers $s\lt0$, $t\lt0$, $m^2\gt0$, $M_5\gt0$ with $u=-s-t\lt4m^2$ only and raises ValueError outside.
Examples
Run the self-tests. From the repository's tools/ directory:
python3 -m nestor.selftest --nproc 2
Six tests must return the right value: $\int_0^1 4\,dx/(1+x^2)=\pi$; $\int_0^1 x^{-1/2}dx=2$ and $\int_0^1 dx/\sqrt{x(1-x)}=\pi$ with declared endpoints; the nested $\int_0^1\!\int_0^1 dx\,dy/(1+xy)=\pi^2/12$; a two-worker grid run of $\int_0^{1/2}e^u\cos 3u\,du$ against its closed form and the serial route; and $\int_0^1\log x\,dx=-1$ with a log declaration. Three checks use deliberately wrong inputs: $x^{-1/2}$ declared regular must be refused, an exponent of $-1$ must be refused before any sampling, and the refusal record from the first must carry no value. Four more exercise the dispersion module. The closed-form moments must match adaptive quadrature to 30 digits and the closed-form add-back must match direct integration of the same product to 25. The subtracted assembly of a two-threshold test density at tanh-sinh level 5 must match a high-precision reference to 30 digits, and the same assembly with the sign of the add-back flipped must lose that agreement. Each test prints a PASS or FAIL line, and the run, which takes a few seconds, ends with
[selftest] 13/13 controls passed, wall 2.4 s -> PASS
(the time varies by machine). The exit status is 0 on pass and 3 on any failure.
Regular, singular and nested integrals. These are the calls the self-test makes (tools/ on sys.path):
import mpmath as mp
import nestor
D = 30
v = nestor.integrate(lambda x: 4 / (1 + x * x), 0, 1, dps=D)
spec = {"a": {"type": "algebraic", "exponent": -0.5}}
v = nestor.integrate(lambda x: 1 / mp.sqrt(x), 0, 1, dps=D, spec=spec)
spec = {"a": {"type": "algebraic", "exponent": -0.5},
"b": {"type": "algebraic", "exponent": -0.5}}
v = nestor.integrate(lambda u, da, db: 1 / mp.sqrt(da * db), 0, 1,
dps=D, spec=spec, wants_dists=True)
def outer(y):
return nestor.integrate(lambda x: 1 / (1 + x * y), 0, 1, dps=26)
v = nestor.integrate(outer, 0, 1, dps=20)
Each call returns an mpf good to at least the requested digits (the self-test measures 40.3 against $\pi$ for the first). The second and third take the grid route because a singular endpoint is declared, and the third uses the three-argument form so that $1/\sqrt{u(1-u)}$ is built from the endpoint distances. In the nested call the inner integral is requested at 26 digits so that its error stays below the outer target of 20 plus the guard; nestor.inner_tol_exp(D) and nestor.wp_for(D) return a suitable inner tolerance exponent and working precision for any outer D. Declaring the $x^{-1/2}$ endpoint as {"a": {"type": "none"}} instead raises SpecRefusal before any node is evaluated.
A parallel grid run that keeps the record. The self-test's grid test (in selftest.py, so __file__ is that file) integrates a module-level function by name over nproc workers:
pe = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
rec = nestor.oracle("nestor.selftest:pilot_integrand", 0, "0.5",
dps=D, md=6, nproc=nproc, f_bound=2,
path_entry=pe, log=lambda *a: None)
vf = mp.mpf(rec["value"])
The string names $e^u\cos 3u$ so the workers can import it, and path_entry is the directory they need on sys.path (here tools/). md=6 sets the grid level, f_bound=2 bounds $|f|$ for deciding where the node list may stop, and log silences the progress lines. rec["rungs"][0] holds the level, node count (541), elapsed seconds and the level-5-against-6 agreement (46.8 digits); rec["value"] is the decimal string and rec["refusal"] is None. Passing raise_on_refusal=False returns the record instead of raising when a check fails.
A dispersion integral with two thresholds. The test in tests/test_dispersion_surrogate.py integrates an inexpensive stand-in density rho against the kernel K, equal to $1/(w'+0.7)^2$, up to the cutoff WINF = 40. The density has a $(w'-1)\log(w'-1)$ turn-on at $w'=1$ with coefficient A and a $\sqrt{w'-9}$ onset at $w'=9$ with coefficient D. The panel list and call are
from nestor.dispersion import disp_subtracted
panels = [
{'a': 1, 'b': 9, 'thresh': ('left', 1, [(A, mp.mpf(1), 1)]),
'sub_width': mp.mpf('0.5'), 'radius': mp.mpf('0.6')},
{'a': 9, 'b': WINF, 'thresh': ('left', 9, [(D, mp.mpf('0.5'), 0)]),
'sub_width': mp.mpf('0.5'), 'radius': mp.mpf('0.6')},
]
J = disp_subtracted(rho, K, panels, dps=30, maxdegree=5)
The first panel declares a threshold at its left end, $w_\ast=1$, with one singular term (coefficient A, power 1, one logarithm), subtracted over a sub-panel of length 0.5 with the kernel expanded within radius 0.6; the second declares the square-root onset at $w_\ast=9$ (power 1/2, no logarithm). J is $(1/\pi)\int\rho K$ with the tanh-sinh level fixed at 5, and the test requires it to match an adaptive tanh-sinh reference to at least 30 digits (it reaches 46). A companion check applies the add-back with its sign flipped and requires the agreement to drop to 5 digits or fewer, a deliberately wrong input that the check must reject. Run directly, python3 tools/nestor/tests/test_dispersion_surrogate.py also prints how many digits Gauss–Legendre, tanh-sinh with panel breaks alone, and the subtracted assembly each reach on this density as the node budget grows. For a physical kernel, with tools/nestor/examples on the path,
from box1_dilog import box_closed_dilog, make_K value = box_closed_dilog(s, t, m2, M5, dps=40) K = make_K(s, t, m2, dps)
gives the box at one kinematic point to at least dps digits, and a memoized function K(w'), the same box with M5 equal to $w'$, ready to pass to disp_subtracted.
Routines
Entry points
nestor.integrate(f, a, b, dps=30, spec=None, md=None, nproc=1, wants_dists=False, f_bound=None, f_kwargs=None, path_entry=None, receipt_path=None, guard=10, tag="nestor", log=print)— the value atdpsagreed digits as anmpf(mpcif complex), or aNestorRefusalexception;taglabels the progress lines and messages.nestor.oracle(...)— same arguments, same run, returning the record dictionary (receipt_path=also writes it to disk atomically);raise_on_refusal=Falsereturns the record on a failed check (an abort is always raised).python3 -m nestor.selftest [--nproc N] [--receipt PATH]— the thirteen-test suite (nine quadrature checks and the four dispersion checks);nestor.selftest.run(nproc, receipt_path)from Python.
Parallel grid
nestor.farm_integrate(spec, a, b, dps, md, nproc, f_bound=1, f_kwargs=None, exp_a=0, exp_b=0, wants_dists=False, path_entry=None)— one explicit grid at levelmdover a process pool; returnsvalue,value_lo(levelmd-1),selfcons_digits,nodes,wall_sand the worker ids.exp_a,exp_bare declared endpoint exponents used in the node cutoff.nestor.farm_campaign(spec, points, out_path, **kw)—farm_integrateover a list of{"a","b","dps","md","nproc"}configurations with a JSON checkpoint atout_pathsaved after each; rerunning skips those done.nestor.ts_nodes(a, b, dps, md, f_bound, exp_a=0, exp_b=0)— the node index list, cut off where weight times the $|f|$ bound falls below $10^{-(\mathrm{dps}+15)}$.
Precision ladder (module nestor.ladder, also exported at top level)
cert_quad(f, a, b, tol_exp, wp)— serial tanh-sinh, depth raised until two successive depths agree within $10^{-\mathrm{tol\_exp}}$; returns(value, agreement, depth)or raisesCertFail.ladder(eval_at_level, levels, D, bar=None, on_rung=None)— evaluates your function up a level schedule and returns(value, agreed_digits, rungs)once two successive levels agree tobardigits (defaultD); raisesCertFailwhen exhausted.crank_check(run, D, step=8)— reruns an evaluation atD+stepdigits and requiresD-digit agreement with the run atD.escalation_schedule(D)— the default three-level schedule forDdigits.digits(a, b)— agreement of two numbers in decimal digits.wp_for(D),prec_for(wp),inner_tol_exp(D)— working decimal precision for aD-digit request, its binary precision, and the tolerance exponent to ask of an inner (nested) integral.
Checks, records, exceptions
nestor.singcheck(f, a, b, spec, wp=30, tol=0.15)— the endpoint-declaration test alone; returns slope and samples per endpoint or raisesSpecRefusal.nestor.receipts:new_receipt,add_rung,add_refusal,write,checkpoint_load,checkpoint_save— record and checkpoint-file helpers (atomic writes);NESTOR_VERSIONandSRC_SHASgo into every record.NestorRefusalwith subclassesCertFail,SpecRefusal,EvalRefusal,AbortRefusal,GateRefusal,PinRefusal,MissingRefusal; each carries.exit_codefromEXIT_OK,EXIT_PIN,EXIT_GATE,EXIT_MISSING(0, 2, 3, 4).
Dispersion integrals (nestor.dispersion; from nestor.dispersion import ... with tools/ on the path)
disp_subtracted(rho, K, panels, dps=40, kernel_nmax=None, maxdegree=None)— the full subtracted assembly; returns $(1/\pi)\int\rho K\,dw'$ as anmpf(works atdps+20internally and restores the caller's precision). Each panel is a dictionary with'a','b','thresh'(None, or('left'|'right', w*, [(c, alpha, m), ...])),'sub_width'and'radius'; a last panel with'map': 'tail'covers $[a,\infty)$ (optional'scale').maxdegreefixes the tanh-sinh level;kernel_nmaxsets the Taylor truncation (default about 1.7dps). Also exported asnestor.disp_subtracted.moment_powerlog(p, m, L)— $\int_0^L u^p(\log u)^m\,du$ in closed form, for $p\gt-1$ and $m$ equal to 0, 1 or 2.kernel_taylor(K, wstar, nmax, radius=None, dps=40, method='cheb')— Taylor coefficients $K_0,\dots,K_{nmax}$ of the kernel aboutwstar;'cheb'fits them from real samples withinradius(default 0.4),'quad'uses a Cauchy integral and needs a kernel that accepts complex arguments.addback_endpoint(coeffs, Kc, L, side='left')— the exact $\int S\,K$ over a sub-panel of lengthLwith the threshold at its left or right end, from the singular termscoeffsand the kernel coefficientsKc.tanhsinh_panel(f, a, b, dps=40, level=None)— tanh-sinh quadrature of a smooth integrand over one panel (mpmath's rule;levelfixes the level).examples/box1_dilog.py(puttools/nestor/exampleson the path):box_closed_dilog(s, t, m2, M5, dps=40)(aliasbox_closed) — the order-$\varepsilon^0$ one-loop box with three lines of squared massm2and one ofM5,ValueErroroutside its region;make_K(s, t, m2, dps)— memoized kernelK(w')fordisp_subtracted. Run aspython3 tools/nestor/examples/box1_dilog.pyit prints a comparison table against an independent two-dimensional evaluation of the same box whenBOX1_DILOG_ORACLE_DIRnames a directory holding that reference script (box1_closed.py, not in the repository); otherwise it printsSKIPand exits 0.tests/test_dispersion_moments.py,tests/test_dispersion_surrogate.py— the four dispersion checks of the self-test as stand-alone scripts or pytest files (python3 -m pytest tools/nestor/tests -q -p no:cacheproviderfrom the repository root); the second, run directly, prints the Gauss–Legendre, tanh-sinh and subtracted convergence table.
Convergence probe
nestor.probe,nestor.EnvEvaluator,nestor.quad_probe— Gatekeeper'sprobes.quad_probe(its two entry points and the module itself), re-exported unchanged: vary one quadrature level with the others fixed and read the digits gained per level before a long run. RaisesMissingRefusalif Gatekeeper is not installed beside Nestor.
Used on this site
- Modular graph functions — the parallel grid engine supplied independent high-precision values of modular graph functions for comparison with the exact formulas.
- Energy correlators — nested high-precision quadrature of the elliptic integrals, as reference values for the closed forms.
- Cosmological correlators — direct numerical integration of the correlator integrals as a check on the closed forms.
- Three-loop light-by-light — the dispersion module assembled the one-dimensional dispersion integrals of the self-energy-dressed boxes, with the threshold turn-on subtracted and added back in closed form; the evaluators offered for download there carry adapted copies of
disp_subtractedand the box kernel.
Requirements and source
Python 3 with mpmath; parallel runs use the standard multiprocessing module, the dispersion module needs nothing beyond mpmath, and the package has no hard-coded paths. Self-tests: python3 -m nestor.selftest from the repository's tools/ directory, or python3 run_selftests.py nestor from the repository root (exit 0 on pass); the dispersion checks also run under pytest with python3 -m pytest tools/nestor/tests -q -p no:cacheprovider. The code is tools/nestor/ in BootLoops' bootloops-dev repository (GitHub organization BootLoops-ai), released under the MIT license: the integrator modules at the top, the dispersion module in dispersion/, the box kernel in examples/ and its tests in tests/; the probe it re-exports is tools/gatekeeper/probes/quad_probe.py. The quadrature rule is from H. Takahasi and M. Mori, Publ. RIMS Kyoto Univ. 9 (1973) 721 (doi:10.2977/prims/1195192451); the singularity subtraction follows the classical treatment of Kahaner, Monegato, and Davis and Rabinowitz, specialized to a dispersion integral with an analytic kernel; the arbitrary-precision arithmetic is mpmath.