Blade (external)
The content on this page was written by AI under human supervision.
Blade is public software by Xin Guan, Xiao Liu, Yan-Qing Ma and Wen-Hao Wu (Peking University) that reduces a family of Feynman integrals to master integrals by the block-triangular method. One search per family is expensive; every reduction at a new kinematic point afterwards is cheap. BootLoops uses it when the same family has to be reduced at many points and runs it through a port that builds without Mathematica. Around the compiled programs BootLoops adds a Python library: a one-command driver, a per-point numerical reducer, a builder for full symbolic reduction tables, and a standalone rational-function reconstructor.
What it does
The integrals of one family (one set of propagators raised to different integer powers) are related: integration-by-parts identitieslinear relations among Feynman integrals that follow from the vanishing of total derivatives under the loop integration express each of them as a combination of a small basis of master integralsthe finite set of independent integrals that every other integral in the family reduces to. The coefficients are rational functions of the kinematic variables and the dimensional regulator $\epsilon$, and finding them is called reduction. Standard programs such as Kira build a very large sparse linear system and eliminate it, repeating most of that work at every new numerical value of the kinematics; when a method needs the same family at many points, as auxiliary mass flow does, that repetition dominates the cost.
Blade moves the cost into a one-time search. Working in finite-field arithmeticexact arithmetic with integers modulo a large prime; exact rational results are rebuilt afterwards from several primes, it finds a small set of relations among the targets and masters whose coefficients are polynomials in the parameters, and fits those polynomials to numerical reduction data. The relations are arranged in blocks that are solved one after another. After that, reducing at a new point means evaluating the polynomials and solving a short sequence of small linear systems. Sampling the form over several primes and reconstructing the rational functions gives the full symbolic table.
The BootLoops driver takes a family specification in JSON: family name, parameters (with eps last), target integrals as vectors of propagator powers, optionally the masters, and a source of numerical reduction data. That source can be a symbolic Kira table, named directly with kira_table or found in an existing Kira output directory with kira_config_dir, which is evaluated modulo primes. It can be a directory of precomputed reduction samples (database_dir). Or, with no Kira at all, it can be a raw sparse linear system in FiniteFlow's JSON format (fflow_system, with an fflow_columns map from columns to integrals and the masters in the highest columns); the driver solves it numerically point by point. The driver does not run Kira itself; a spec naming none of these sources is refused with a message. A maximal-cut system should also list zero_sectors, the sectors that vanish under the cut. The output is a self-describing family directory: btform.json (parameters, targets, masters, closed blocks, checksums), relations.json (the exact relations) and run_tree/ (the search tree, which enables the compiled back end of the reducer).
The compiled stages can exit with status 0 on failure, so the library never trusts return codes. It checks the files each stage writes (dimensions, byte sizes, agreement across primes) and stops with an error naming the file instead of returning a guess. Exported relations are verified at a prime not used in the fit. When the spec names a Kira table they are also checked against that table at a prime never used in the search, alongside a deliberately wrong input that the check must reject. For a raw-system spec the same check replays the input system's own numerical solve at that prime; it tests the search and export, not the input system, which you must validate separately. If only some blocks close within the time limit, the directory is still written; open blocks are listed with the reason the search stopped and appear in any symbolic table as explicit PENDING markers, never as numbers.
For a single reduction at one point, run Kira directly; Blade pays off from the second point on. On the small two-parameter test family in the package documentation the search takes about half a minute and each later point a fraction of a millisecond, against about twenty seconds for a fresh Kira reduction; the ratio depends on the family and the machine. The compiled solver cannot address ten or more parameters (the table builder accepts a Python evaluator callback for those; ratrec.reconstruct stops at nine variables), several families at once is untested, and prepare insists on a fresh working directory.
Examples
Prepare a family, inspect it, and reduce it at a few points. From the driver's usage text; the paths are placeholders.
python3 tools/blade/blade_family.py prepare spec.json --workdir runs/<p>/<tag>/fam
python3 tools/blade/blade_family.py status runs/<p>/<tag>/fam/family/<name>
python3 tools/blade/blade_family.py probe runs/<p>/<tag>/fam/family/<name> \
--points pts.json --prime 9223372036854775783
prepare runs the whole chain (integral-set extension, numerical database, block scheme, polynomial ansatz, the search with its per-round limit --max-round-seconds, rational export, the independent check). It exits 0 when every block closed, 2 when a partial closure was saved, and 1 or 3 on failure, with ERROR.json naming the file that failed. status verifies the directory's checksums and prints the parameters, each target as CLOSED or PENDING, the master and relation counts, and any open blocks with their stop reasons. probe reads pts.json, a list [[x1, ..., eps], ...] in the parameter order of btform.json or an object {"prime": P, "points": [...]}. It prints JSON giving, for each point, the coefficient of every master in every closed target as an integer modulo the prime, zero coefficients omitted. A prime not used during preparation, as here, makes the probe an independent check.
Call the per-point reducer from Python. From the package guide:
from blade.probe import BTOracle o = BTOracle(family_dir) o.reduce_point(kin, eps, prime)
Loading family_dir verifies the recorded checksums and refuses a modified directory. kin holds integer values of the kinematic parameters, eps the integer substituted for $\epsilon$, prime any large prime; the result is {target_label: {master_label: value}} with values in [0, prime) and zero coefficients omitted. o.reduce_many(points, prime) takes a list of (kin, eps) pairs, and o.reduce_many_ssolve(...) drives the compiled solver on the saved fit tables (only at the primes used in preparation), cross-checking itself against the exact back end on every batch.
Reconstruct rational functions from a modular evaluator. Adapted from the package's self-test, which plants two known functions and recovers them exactly:
import sympy as sp
from fractions import Fraction
from blade import ratrec
x, y = sp.symbols("x1 x2")
f1_num = [(3, (2, 1)), (-7, (0, 1)), (Fraction(5, 2), (0, 0))]
f1_den = [(1, (1, 0)), (-2, (0, 1)), (1, (0, 0))]
f2_num = [(Fraction(1, 2), (1, 0)), (Fraction(-1, 3), (0, 0))]
f2_den = [(1, (1, 1)), (4, (0, 0))]
ev1 = ratrec.ratfun_evaluator(f1_num, f1_den)
ev2 = ratrec.ratfun_evaluator(f2_num, f2_den)
def evaluator(coords, prime):
return [ev1(coords, prime), ev2(coords, prime)]
wd, nthreads = "scratch/ratrec_plant", 6 # any empty scratch directory
funcs = ratrec.reconstruct(evaluator, nvars=2, maxdeg=4, nfuns=2,
primes=(0, 1), workdir=wd,
nthreads=nthreads, symbols=(x, y))
Term lists hold (coefficient, exponent_tuple) pairs, so f1_num is $3x_1^2x_2 - 7x_2 + 5/2$. reconstruct accepts any callable returning the target functions' values modulo the prime; primes are consecutive indices into FiniteFlow's fixed prime table, at least two (one to fit, one to verify). It first learns the exact numerator and denominator degrees from the evaluator (pass degrees= to skip this) and generates the structured sample points the compiled reconstructor requires. It returns sympy expressions, here $(3x_1^2x_2 - 7x_2 + \tfrac{5}{2})/(x_1 - 2x_2 + 1)$ and $(\tfrac{1}{2}x_1 - \tfrac{1}{3})/(x_1x_2 + 4)$. The self-test then corrupts one evaluation and confirms the call either raises an error or still returns the correct functions, never a wrong one.
Routines
Command line
blade_family.py prepare <spec.json> --workdir W [--max-round-seconds S] [--bank-dir DIR] [--bisect] [--nthreads N]— family spec to saved family directory (alsopython3 -m blade.blade_family).blade_family.py probe <family_dir> --points FILE [--prime P] [--batch] [--out FILE]— master coefficients moduloPat the listed points, as JSON.blade_family.py status <family_dir>— verify and summarize a family directory.python3 -m blade.selftest [--full] [--root DIR]— self-test suite (see below).
Python library
blade.probe.BTOracle(family_dir)— per-point reducer;reduce_point,reduce_many,reduce_many_ssolve.BTForm(family_dir)loads and verifies the manifest.blade.semibl.SemiBLJob(...)— symbolic-table job over a closed search tree:stage_prime(pid),run_recmod(pid),run_reconstruction(), thenassemble_table()returning aSemiBLTable(write_text,write_json);Orderingsconverts between the three parameter orderings (run_permutation_tests()checks it).blade.ratrec.reconstruct(evaluator, nvars, maxdeg, nfuns=1, primes=(0,1,2), ...)— rational functions from a black-box modular evaluator; helpersscan_degrees,dump_points,ratfun_evaluator,poly_eval_mod.blade.pipeline.run_all(cfg)withPipelineConfig— runsredg1, then per primefitrel,dumppoints,ssolve,recmod, thendynamicrr, checking each stage's files; single stagesrun_redg1…run_dynamicrr;BladeGateErroris the exception every failed check raises.blade.search.blade_search(cfg, works, labels, out_json)withSearchFamily— the escalating search, fits at every prime andexport_relations;ReconstructionOverflowwhen export does not stabilize within the allowed primes;FflowSystem/make_fflow_growersupply reduction data from a raw sparse system solved per point byfflowcli(no Kira);nana_search/fit_at_pinwithNanaSpecfor a reduced-analytic search that pins some parameters to numbers (relations marked valid only at the pins).blade.extension.Extension,blade.scheme.build_scheme/single_block_scheme/write_scheme,blade.ansatz.FamilyAnsatz/build_kinematics,blade.adaptive.single_var_probe/adaptive_weights— the search inputs: integral-set extension, block scheme, polynomial ansatz, depth probes.blade.formats— readers and byte-exact writers for every file the compiled stages exchange (Database,Kinematics,Scheme,FitTable,PointsFile,EvalFile,DegreesFile,RRRes, ...), plusclassify(path),round_trip(path, scratch),big_uint_primes()andassemble_rational_functions(...).
Compiled programs (the fork, the blade-dev repository)
redg1,fitrel,ssolve,recmod,dynamicrr— Blade's own search, fit, solve and reconstruction stages, from upstream.fflowcli,dumppoints— added command-line drivers over FiniteFlow that replace the Mathematica-side calls.fflowcli_stream— a sibling offflowcliwhoseevalmanywrites results as it goes, can--resumea partial run, and can restrict the solver to the outputs needed (--subgraph,--dump-sysinfo,--load-sysinfo).
Requirements and source
Python 3 with python-flint and sympy. The compiled side needs FiniteFlow, FLINT, GMP and MPFR. Build FiniteFlow inside its own source directory (an out-of-source build misses a generated header), then the fork, which is BootLoops' blade-dev repository (GitHub organization BootLoops-ai; upstream's history with the BootLoops changes on the branch bootloops, release tag bootloops-1.0), and set BLADE_BIN_DIR to its bin/ directory (default ../blade-dev/bin relative to the root of the bootloops-dev checkout, that is, a sibling checkout of the fork; BLADE_PHASE0_DUMPPOINTS optionally names a separate dumppoints). The fork's PATCHES.md lists every change from upstream. The Python library is tools/blade/ in the bootloops-dev repository under the same organization, released under the MIT license, with GUIDE.md and README.md (module notes, limits and known pitfalls); the third-party components named below keep their own licenses.
Self-tests: cd tools; ulimit -v 32505856; python3 -m blade.selftest (add --full for the long form). The replay sections read a tree of reference artifacts named by BLADE_PORT_ROOT or --root that is not distributed with the repository. Without it the command says so and runs only its self-contained section. That section checks the spec refusals; then, if the compiled programs are built, it runs prepare end to end on a small test system with known coefficients, probes the stored family against them at a fresh prime, and confirms that a deliberately wrong input is rejected. Those steps are skipped by name when the binaries are absent. The end-to-end checks inside blade_family.py prepare run on every real family as well.
Upstream: X. Guan, X. Liu, Y.-Q. Ma, W.-H. Wu, Comput. Phys. Commun. 310 (2025) 109538, arXiv:2405.14621, gitee.com/multiloop-pku/blade, MIT license (included intact). Method: arXiv:1912.09294, arXiv:1801.10523. FiniteFlow: T. Peraro, arXiv:1905.08019, MIT; the library itself is linked unmodified and not bundled, while the fork's command-line wrappers transcribe its MathLink interface and carry its notice (THIRD_PARTY.md in blade-dev). Algorithmic credit belongs to these authors. The Mathematica-free build and the Python library are the BootLoops additions. Within the library, the extension, ansatz, scheme, search, adaptive and symbolic-table modules are Python translations of Blade's own Wolfram-language sources and carry the upstream copyright notice (tools/blade/NOTICE).