pySecDec and FIESTA (external)

The content on this page was written by AI under human supervision.

pySecDec is public software from the SecDec collaboration (S. Borowka, G. Heinrich, S. Jahn, S. P. Jones, M. Kerner, J. Schlenk, T. Zirke and later contributors); FIESTA is public software by A. V. Smirnov and collaborators. Both compute a Feynman integral numerically by sector decomposition, starting from its list of propagators and a kinematic point. BootLoops uses them unmodified, as a numerical check that shares no code with any other method in the toolkit. It adds two small packages around them. hiprec-sectordecomp evaluates the same parametric integral in arbitrary precision for finite integrals in the Euclidean region. pysecdec-point runs one pySecDec evaluation of a compiled integral library at one Euclidean point in resumable stages and reports how many digits of the result can be trusted.

What it does

Every Feynman integral can be rewritten in its Feynman-parameter formthe representation that trades the product of propagators for one integration variable per propagator, over a simplex, with two polynomials U and F built from the graph and the kinematics. For $N$ propagators, $L$ loops and dimension $d = 4 - 2\varepsilon$,

$$ I \;=\; \Gamma\!\left(N - \tfrac{L d}{2}\right) \int d^N x \;\delta\!\Big(1-\sum_i x_i\Big)\, \frac{U^{\,N-(L+1)d/2}}{F^{\,N-L d/2}} . $$

Sector decompositiona recursive splitting of the integration region that untangles overlapping singularities splits the integration region until every divergence is an explicit power of one variable, subtracts the poles in $\varepsilon$, and integrates the rest numerically. pySecDec drives this from Python and compiles a C++ library for the integrand; FIESTA is an independent implementation in Mathematica and C. The input is the propagator list, the loop and external momenta, the kinematic substitution rules and a numerical point. The output is the Laurent series in $\varepsilon$ with a numerical coefficient and an error estimate at each order; in the standard double-precision modes that means about 8 to 9 digits, with no proven bound. Installation and use are documented by the two projects themselves (links below).

BootLoops keeps these programs for their independence. They use no integration-by-parts reduction, no differential equations and no auxiliary mass, so agreement between a sector-decomposition value and an AMFlow value confirms the number by two methods with nothing in common. They also give a quick first read on whether an unfamiliar integral is numerically tractable, and pySecDec's front end supplies the $U$ and $F$ polynomials to other tools (SubTropica's graph front end was checked against it on five graphs and agreed exactly).

The BootLoops package hiprec-sectordecomp goes past the double-precision ceiling for one class of integrals: finite ($\varepsilon^0$) scalar integrals in the deep-Euclidean regions and t negative and internal masses positive, so F is positive on the whole simplex and the integrand is smooth and real; no contour deformation, no thresholds. It takes $U$ and $F$ from pySecDec's LoopIntegralFromPropagators in the same normalization, so its values compare digit for digit with pySecDec's. Before any numerics it integrates out in closed form a parameter that enters $F$ linearly, using $\int_0^\infty dx/(Ax+B)^2 = 1/(AB)$ (valid because $A, B \gt 0$ here); if a second parameter is then linear in both factors $A$ and $B$, that one goes out too, by partial fractions, leaving a logarithm. For box-like integrals one parameter that enters quadratically can be removed instead. Each such step removes one integration dimension exactly, which is how the one-loop box becomes a two-dimensional integral. What remains goes to one of three arbitrary-precision engines. A fixed tensor-product Gauss–Legendre rule serves effective dimension up to 3 and converges spectrally for these smooth integrands: on the one-loop massive box, two reductions that share no algebra beyond $U$ and $F$ (box and box_crosschart) agree to about 46 digits, and the package stores 40-digit reference values. Nested tanh-sinh quadrature serves dimension up to 2 as a quick check, to roughly 17 digits. A randomly shifted rank-1 lattice rule (quasi-Monte Carlo) serves dimensions 4 to 7 and returns a value with a statistical error bar. A generic pathway accepts any finite projective parametric integrand written as a JSON "UF-spec" (each polynomial as exponent vectors with rational coefficients, plus numerator terms) and feeds it to the lattice engine.

When not to use it: the package does not handle poles in $\varepsilon$, physical-region kinematics or thresholds. The lattice engine's error falls only like a power of the number of points. In six or more dimensions expect an independent confirmation to a few digits (about 3 on the six-dimensional benchmark below), far short of a thirty-digit reference. Quote its value only within its error bar, and at high dimension raise the point count and watch for drift, because with few points the bar can be too small. Before quoting box digits beyond the stored 40, run at two working precisions (say dps and dps+15) and keep only the digits on which the two runs agree. Give the kinematics as exact numbers (integers, Fractions or decimal strings). A constant rounded at low precision, such as mpf(-1)/3 at mpmath's default setting, is a slightly different number; the engines then converge to the integral of that number, and agreement with the true value stops near the input's own precision.

The second package, pysecdec-point, stays in double precision and addresses a different need: one careful pySecDec evaluation of a large integral that runs for hours, with an independent check of its error estimate. The input is an integral library already compiled with pySecDec (loop_package then make disteval; the compiled library is specific to the machine it was built on and is not part of BootLoops) and a Euclidean point. The script runs pySecDec's disteval evaluator over the library three times. Stage A uses a coarse lattice ($10^4$ points), stage B a fine one ($10^5$ points, relative target $10^{-7}$), and stage C disteval's alternative median-lattice rule at the stage-B targets. B and C are therefore two different quasi-Monte Carlo constructions applied to the same integrands. Stages B and C run in chunks of sectors whose results are written to disk as they finish, so an interrupted stage resumes where it stopped; there is no time limit. The acceptance test then compares the three results order by order in $\varepsilon$: it fails if B and C differ by more than 3 standard deviations anywhere, and otherwise reports for each order the smallest of the B–C agreement and what the two error bars allow. It also checks itself, by confirming that a copy of the B result shifted by one part in a thousand is caught and that two coarse independent evaluations agree with stage A. On the package's reference case, the eight-propagator double pentagon of a five-point family with generic mass parameters (332 sectors), stage B gives $\varepsilon^0 = 0.8246341249 \pm 7.3\times 10^{-8}$ and the test reports 7 digits at every order. That is a double-precision value with a checked error bar, not a high-precision reference, and points in the physical region are out of scope because the reference library was generated without contour deformation.

Examples

Run the self-tests. From the package directory:

python3 selftest.py
python3 selftest.py --full
python3 selftest_parametric.py

By default the suite runs on one process in well under a minute and prints a [name] block per check followed by PASS or FAIL. The checks touch every code path. The closed-form kernel is tested on both of its branches and on its series branch near a double root, and the reductions against exact values. Each engine runs against a known answer: the box against its stored 40-digit reference through both reductions, with a deliberately rounded kinematic input that must lose digits, and the six-dimensional fixture toy_qmc_spec.json, exact value $13/1080$. The spec checks must reject two deliberately broken specs. The last check has the pySecDec front end reproduce the box's $F$ polynomial exactly, and prints SKIP when pySecDec is absent. --full runs the heavier multi-process checks instead: the box at 30 digits against the stored reference, and a 16-shift lattice run on the fixture with 8 worker processes that must agree with $13/1080$ within its own error bar. Every script exits nonzero on a failure.

Build $U$ and $F$ from a propagator list. The one-loop box with three equal internal masses and one distinct mass M5, as the self-test sets it up:

import feynman
props = ['k**2 - M5', '(k+p1)**2 - m2', '(k+p1+p2)**2 - m2', '(k-p4)**2 - m2']
rr = [('p1*p1', 0), ('p2*p2', 0), ('p3*p3', 0), ('p4*p4', 0),
      ('p1*p2', 's/2'), ('p3*p4', 's/2'),
      ('p2*p3', '(-s-t)/2'), ('p1*p4', '(-s-t)/2'),
      ('p1*p3', 't/2'), ('p2*p4', 't/2')]
U, F, xs, L, Nprop = feynman.build_UF(props, ['k'], ['p1', 'p2', 'p3', 'p4'], rr)

build_UF calls pySecDec's LoopIntegralFromPropagators and returns $U$ and $F$ as sympy polynomials in the Feynman parameters xs, with the loop count (L is 1) and propagator count (Nprop is 4). Here $U$ is the sum of the four parameters and $F$ still carries the symbols s, t, m2, M5. Substitute numbers, then pass $F$ to reduce_linear or reduce_one_quadratic to remove a dimension before choosing an engine.

Run the two benchmarks. As the README shows them:

python3 bench_box.py 35
python3 bench_se3l.py --N 64007 --shifts 24 --p 3 --dps 40 --nproc 24 --out result.json

The first evaluates the finite one-loop massive box at $s=-1$, $t=-1/3$, $m^2=1$ for three values of M5 at 35 digits of working precision, and prints each value beside its stored reference with the number of agreeing digits. For M5=2 the value begins 0.124557057232709269. From Python the same number is box(-1, Fraction(-1, 3), 1, 2, dps=35) after from fractions import Fraction and from bench_box import box; pass the kinematics as exact numbers, not floats such as -1/3. The second evaluates the finite three-loop, eight-propagator self-energy at the same point. After one closed-form elimination it is a six-dimensional integral, run on the lattice engine with 64007 points, 24 random shifts, Korobov parameter 3 and 24 worker processes. The script prints the value, its error bar, the pySecDec target 0.52495777354 and the digits of agreement, and writes value, error, settings and run time to result.json.

Check one pySecDec evaluation in stages. With a library compiled by pySecDec under PKG/disteval and a scratch directory WORK, as the pysecdec-point README shows it:

python3 pysecdec_point.py --disteval-dir PKG/disteval --stage A --workers 8 --work WORK
python3 pysecdec_point.py --disteval-dir PKG/disteval --stage B --workers 8 --work WORK
python3 pysecdec_point.py --disteval-dir PKG/disteval --stage C --workers 8 --work WORK
python3 pysecdec_point.py --stage compare --results A=WORK/stage_A/RESULT_A.json B=WORK/stage_B/RESULT_B.json C=WORK/stage_C/RESULT_C.json --out WORK/COMPARE.json
python3 pysecdec_point.py --stage gate --work WORK --compare WORK/COMPARE.json

Each stage line prints its settings and leaves WORK/stage_<S>/RESULT_<S>.json; for B and C every chunk directory under WORK/stage_<S>/chunks/ holds its own result.json, log, run time and DONE marker, and one line per finished chunk goes to WORK/progress.jsonl. Add --max-chunks 1 to time a single chunk first, --resume to continue an interrupted stage, and --dry to rehearse the whole chain in seconds with the disteval call replaced by a library-presence check and a canned result. The last line runs the acceptance test over WORK and writes the per-order digit table, the two self-checks and the verdict beside the results (exit code 0 or 1); with --fixtures in place of --work ... --compare ... it runs over the reference results included with the package and must reproduce them. By default --disteval-dir must match the checksums of the reference library in PACKAGE_PINS.json. For your own library, write its checksums once with --emit-pins PINS.json --disteval-dir PKG/disteval --family NAME and pass --family NAME --pins PINS.json on every line, or add --unpinned-package, which runs anyway and labels every result as unverified. --point 'name=value ...' sets the kinematic point and must name every parameter of the library exactly once.

Routines

BootLoops adds no code inside pySecDec or FIESTA; the BootLoops-side code is the two packages hiprec-sectordecomp and pysecdec-point.

Scripts

Building the integrand (feynman.py)

Engines (hiprec.py)

Generic parametric pathway (parametric.py)

One pySecDec point in stages (pysecdec-point)

Used on this site

Requirements and source

pySecDec: pip install pySecDec, source at github.com/gudrunhe/secdec, cite arXiv:1703.09692. FIESTA: source at gitlab.com/feynmanintegrals/fiesta, cite arXiv:1511.03614. The method is due to T. Binoth and G. Heinrich, hep-ph/0004013.

hiprec-sectordecomp is Python 3 with mpmath, sympy and gmpy2 (pip install gmpy2). pySecDec is needed only for build_UF (and so for bench_se3l.py, which builds its integrand that way); without it that one self-test check is skipped and the UF-spec pathway still works. Worker pools start only under if __name__ == '__main__', so the scripts also run where the multiprocessing start method is spawn (the macOS default). Run the tests with python3 selftest.py (--full for the heavier multi-process checks) and python3 selftest_parametric.py from the package directory.

pysecdec-point is Python 3 with the standard library, plus GNU time (/usr/bin/time -v) for the run records; the evaluation stages need pySecDec with its pySecDecContrib worker (the reference library was generated with pySecDec 1.6.6) and a library you have compiled. Its tests need pytest and no compiled library: run python3 -m pytest -q -p no:cacheprovider tests from the package directory; the checks that import pySecDec are skipped when it is absent. The code is in tools/hiprec-sectordecomp/ and tools/pysecdec-point/ in BootLoops' bootloops-dev repository (GitHub organization BootLoops-ai), released under the MIT license. pySecDec (GPL-3.0) and FIESTA are not bundled and keep their own licenses; a program that imports pySecDec runs under its terms.

← back to the tools index