Ratfit
The content on this page was written by AI under human supervision.
Ratfit recovers an exact rational function of one variable (a ratio of two polynomials with rational coefficients) from exact values of that function at rational sample points, and confirms the answer on samples kept out of the fit. The same package chooses safe sample points along a straight path in kinematic space, checks new sample points against an already-reconstructed function, and, in a separate submodule, turns a class of one-dimensional logarithmic integrals into closed forms. A small classifier, degree_alias, serves reconstructions done modulo primes instead: when some coefficients refuse to come out as fractions, it says whether to add a prime or to enlarge the sampling grid. Everything runs in exact rational arithmetic; nothing here is a floating-point fit.
What it does
When differential equations for Feynman integrals are built from integration-by-parts reduction, each entry of the coefficient matrix is a rational function of the variable $t$ along the chosen kinematic path. A reduction run, however, returns only its value at one numeric point. Ratfit takes sample points xs and values ys (Python Fractions) and returns numerator and denominator as exact flint.fmpq_poly polynomials. The blind route, thiele_loo, builds a Thiele continued fractiona classical way to interpolate a rational function through sample points one at a time, without solving a linear system for the coefficients through most of the samples and keeps six evenly spaced samples out. It reports success only if the result reproduces every sample exactly. When the denominator is already known, for example from a lower order in the dimensional-regularization parameter $\varepsilon$, ratrecon_with_denom fits the numerator alone and reaches further. From $n$ samples a blind fit resolves numerator and denominator degrees up to about $(n-6)/2$ each, a known-denominator fit reaches numerator degree $n-8$; degree_budget reports these limits before any reduction is run. Candidate denominators are built from ones already validated in the same run and screened modulo a 61-bit prime before the exact test, which still follows every pass. Fits that fail at the degree limit need more samples or a known denominator; fits that fail below it usually mean a bad sample point.
Bad sample points are what the grid designer prevents. On a straight path between two kinematic points, parametrized by $t\in(0,1)$, there are rational values of $t$ where two invariants coincide. A reduction there finishes normally and is reproducible, but it belongs to a degenerate configuration and silently spoils every fit that uses it. coincidence_loci lists those values exactly; design_grid returns fresh rational points that avoid them, avoid a user-supplied list of poles, and never repeat a point already used. Both stop with an error instead of returning a short or unsafe grid.
The thiele_gate submodule takes a family of quantities (every entry of a matrix) sampled at trusted points and fits each component as a continued fraction that must reproduce the trusted samples not used in the fit. It then accepts a new, untrusted sample only if it lies exactly on the reconstructed function. A sample from a wrong configuration or a corrupted file has a negligible chance of passing.
The degree_alias submodule is for the other common way of recovering a rational function: sampling it on a grid with all arithmetic done modulo a large prime, fitting at several primes, and lifting each coefficient to an exact fraction with the Chinese remainder theorem. When some entries will not lift however many primes are added, there are two causes that look alike. Either the combined modulus is still too small for the size of the coefficients (a "height" problem, which one more prime fixes), or the grid has too few points on one axis for the true degree (an "alias"). In the second case the fit returns the degree $n-1$ polynomial through all $n$ points on the short axis, the same wrong function at every prime, so more primes never help and only more points on that axis do. classify takes the grid size $(n_d, n_\eta)$ and, for a handful of failing entries, the numerator and denominator degrees fitted at each prime. It returns ALIAS, with the axis to extend, when every entry has a numerator at the ceiling ($n_d-1$ or $n_\eta-1$) over a trivial denominator, identically at every prime. It returns HEIGHT when the degrees sit below the ceiling with a nontrivial denominator (one such entry among pinned ones is enough). Degrees that differ between primes, or a numerator at the ceiling over a nontrivial denominator, give INCONCLUSIVE, and then you probe more entries or primes rather than choose. The submodule names the axis and does not perform the extension, and it should be given failing entries only. Before acting on a live verdict it is good practice to run it on entries from the same computation that already lifted, where the answer is known.
The li2close submodule does a different job. Its input is a list of "atoms", each standing for $\int_{lo}^{hi} c\,\ln\lvert P_0+P_1t\rvert\,/\,(W_0+W_1t)\,dt$ with coefficients rational or rational in one symbolic parameter, where $lo$ may be $0$ and $hi$ may be $\infty$. It returns the sum in closed form in the real dilogarithm $\mathrm{Re}\,\mathrm{Li}_2$ and products of logarithms, carrying the endpoint divergences as symbols $\ln\epsilon$ and $\ln\Lambda$. Every divergent coefficient must cancel across the sum; if one survives, close_atoms raises DivergenceError, because an incomplete atom list is a wrong answer. It does not check that a denominator root inside an atom's range cancels between atoms; that remains the caller's job. Ratfit reconstructs rational functions of one variable (parametric_rec_interp adds exact polynomial dependence on extra parameters for the coefficients of a sampled recurrence); Numkin builds two-variable reconstructions on top of it.
Examples
Reconstruct a rational function from 24 samples. The package's test samples $f=(3-2x+x^2)/(1+5x^2+7x^3)$ at $x=k/97$ and recovers it with and without the denominator.
from fractions import Fraction
import flint
import ratfit
P_TRUE = flint.fmpq_poly([3, -2, 1])
Q_TRUE = flint.fmpq_poly([1, 0, 5, 7])
N_NODES = 24
XS = [Fraction(k, 97) for k in range(1, N_NODES + 1)]
def frac(v):
return Fraction(int(v.p), int(v.q))
def feval(x):
xq = ratfit.fq(x)
return frac(P_TRUE(xq) / Q_TRUE(xq))
YS = [feval(x) for x in XS]
P, Q, ok, deg = ratfit.thiele_loo(XS, YS)
Pn, Qd, ok, deg = ratfit.ratrecon_with_denom(XS, YS, Q_TRUE)
assert ratfit.screen_modp(XS, YS, Q_TRUE) is True
Each fit returns numerator and denominator as fmpq_poly objects (ascending coefficients), a flag ok that is True only when the kept-out samples were reproduced exactly, and the degree; here both give ok true and deg == 3, with str(Pn) == str(P_TRUE). The known-denominator route divides out common factors, so passing Q_TRUE * flint.fmpq_poly([-2, 1]) returns the same reduced pair. Adding 1 to ys[2] makes both blind routes return ok false, and screen_modp with the wrong cubic flint.fmpq_poly([2, 3, 1, 1]) returns False.
Design a sample grid on a kinematic path. For the straight path between two five-point configurations used in the tests, list the degenerate values of $t$, then ask for 30 fresh points that also avoid a known pole and two points sampled earlier.
from fractions import Fraction
from ratfit import coincidence_loci, design_grid
PA = dict(s12=-3, s23=-5, s34=-7, s45=-2, s15=-11, mm=1)
PB = dict(s12=-3, s23=-5, s34=-7, s45=-11, s15=-17, mm=2)
loci = coincidence_loci(PA, PB)
grid = design_grid(PA, PB, 30, exclude=("1/2", Fraction(7, 60)),
poles=("11/60",))
loci is keyed by exact fractions: on this path $s_{45}$ equals $s_{12}$, $s_{23}$ and $s_{34}$ at $t=1/9$, $1/3$ and $5/9$. grid is a list of 30 entries {"t": "p/q", "checked": ["no-coincidence", "no-pole", "fresh"]} drawn from $k/60$, $k/120$ and $k/240$, none equal to a locus, to $11/60$, or to an excluded point. Asking for more than the denominators can supply, design_grid(PA, PB, 6, denominators=(9,)), raises ValueError ("only 5/6 admissible t values ...") instead of returning five points.
Close a logarithmic integral and check that its divergences cancel. $\int_0^\infty \ln(1+t)\,/\,(t(1+t))\,dt=\pi^2/6$; after partial fractions it is two atoms, each divergent like $\ln^2\Lambda$ on its own.
import sympy as sp
from sympy import oo
import li2close as lc
atoms = [lc.Atom(1, 0, 1, 1, 1, 0, oo, 'pf.t'),
lc.Atom(-1, 1, 1, 1, 1, 0, oo, 'pf.1pt')]
cl = lc.close_atoms(atoms)
f = lc.emitted_function(lc.emit_mpmath(cl.finite, 'val'), 'val')
Atom(c, W0, W1, P0, P1, lo, hi, tag) gives the coefficient, the denominator $W_0+W_1t$, the logarithm's argument $P_0+P_1t$ and the range. cl.finite is a sympy expression satisfying sp.simplify(cl.finite - sp.pi**2/6) == 0, and cl.ledger records the 'LE^0 LL^2' term with a verdict field showing it canceled. emit_mpmath writes standalone mpmath source for the closed form and emitted_function compiles it; f(dps=50) agrees with $\pi^2/6$ to at least 45 digits. Passing only the first atom raises DivergenceError; atoms depending on a sympy symbol u need close_atoms(atoms, param=u, domain=(0, 1)).
Decide between another prime and a larger grid. Five coefficients on a $(50,100)$ grid refuse to lift; each was fitted at seven primes with the same degrees. The call is the first case of the submodule's self-test:
from ratfit.degree_alias import classify r = classify((50, 100), [[((49, 99), (0, 0))] * 7] * 5)
Each inner list is one failing entry, each tuple one prime's fit as ((num_d, num_e), (den_d, den_e)). Here every numerator sits at the ceiling $(49, 99)$ over a trivial denominator, so r['verdict'] is 'ALIAS' and r['axis'] is 'd' (both axes are pinned and ties go to d); r['counts'] gives the breakdown, with n_fits and alias both 5. Three entries on a $(29,101)$ grid with fits such as ((12, 46), (9, 47)) repeated at five primes give 'HEIGHT' with axis None, and replacing any entry by fits that disagree between primes makes the verdict 'INCONCLUSIVE'. python3 -m ratfit.degree_alias --selftest (with tools/ on PYTHONPATH) replays these cases and prints a line beginning degree_alias selftest PASS.
Routines
Exact fitting (import ratfit)
thiele(xs, ys)— Thiele continued-fraction interpolation through all samples; returns(P, Q).thiele_loo(xs, ys, n_loo=6)— blind fit withn_loosamples kept out; returns(P, Q, ok, deg).thiele_loo_screened(xs, ys, n_loo=6)— same result asthiele_loo, with a modular pre-test that makes failing fits cheaper.ratrecon_with_denom(xs, ys, Qknown, n_loo=6)— numerator over a supplied denominator, tested on the kept-out samples, common factors divided out; returns(Pnum, Qden, ok, deg).okis alsoFalsewhenQknownvanishes at any sample point, because that sample would otherwise drop out of the fit unnoticed.screen_modp(xs, ys, Q, n_loo=6)— fast modular version of that test; never rejects a correctQ; follow aTruewithratrecon_with_denom.newton_interp(xv, yv)(aliasnewton_interp_fmpq) — exact polynomial interpolation.fq,qpoly,poly_lcm,exact_div,SCREEN_PRIMES— helpers: convert toflint.fmpq, build anfmpq_polyfrom ascending coefficients, polynomial lcm, exact division (Nonewhen not exact), and the two screening primes.
Denominator candidates, sample budgets and parametric coefficients (qex maps each matrix entry $(i,j)$ and $\varepsilon$-order to a validated denominator's coefficients; results are keyed by matrix row $i$)
extract_stairs(qex, cap=12)— per row, the distinct exact ratios $Q_{m+1}/Q_m$ between consecutive orders.row_lcm(qex)— per row, the least common multiple of all validated denominators.degree_budget(qex, n, n_loo=6, project_extra=4)— per row, fornsamples: blind degree ceiling, highest denominator degree worth screening, and projected denominator degrees for the next orders.parametric_rec_interp(rec_at_point, param_grid, normalize_key, deg_bound=12)— exact polynomial dependence of recurrence coefficients on parameters.rec_at_point(params)returns{key: value}at one parameter tuple; the routine evaluates it on the complete tensor-product gridparam_grid, divides by thenormalize_keycoefficient, and interpolates each coefficient as a multivariate polynomial, returned as{key: {exponent_tuple: Fraction}}. The result is re-evaluated at two parameter tuples off the grid and must agree exactly; a mismatch, an incomplete grid, a vanishing normalizer or an axis with more thandeg_bound + 1nodes raisesValueError.mpoly_eval(poly_coeffs, params)— exact value of one returned polynomial{exponent_tuple: Fraction}at a parameter tuple.
Sample-grid design
coincidence_loci(PA, PB, vars=None)— every $t\in(0,1)$ on the straight path fromPAtoPB(dicts of variable name to rational value) where two variables are equal, as{Fraction: "si=sj"};ValueErrorif two variables agree along the whole path.design_grid(PA, PB, n_points, denominators=(60, 120, 240), exclude=(), poles=(), vars=None)—n_pointsfresh rational $t$ values avoiding the loci, the given poles and already-used points;ValueErrorif it cannot supply them all.
Checking new samples against a reconstructed family (ratfit.thiele_gate)
fit(xs, ys, max_fit=None, probe=4, interleave=True, retries=8)— early-stopping continued-fraction fit on the firstmax_fitpoints; the rest must be reproduced exactly; returns aThieleCF(evaluate withcf(x);cf.depthterms;CFDeadat a true pole) orNone.validate(cf, holdout_pairs)—Trueifcfreproduces every(x, y)pair exactly.gate(cf, new_pairs)— test untrusted samples; returns{'ok': n, 'fail': m, 'fails': [...]}.gate_family(banked, new, max_fit=140, probe=4, labels=None, retries=4, progress=None, workers=1)— the same for vector-valued samples[(x, [y_0, ..., y_m]), ...](banked= the trusted samples), one fit per component, in parallel whenworkers > 1; returns a report with keysentries_ok,entries_fail,new_ok,new_fail,cf_depths,fails.python3 tools/thiele_gate.py IN.json [-o REPORT.json]— command-line form ofgate_family;IN.jsonis{"banked": [[x, [y, ...]], ...], "new": [...], "max_fit": 140}(optional"labels","probe","workers") with numbers as fraction strings; prints a summary, writes the report, exits with status 1 on any failure.
Primes or grid: triage for stalled modular reconstructions (ratfit.degree_alias)
classify_cell(grid, fits)— one failing entry;grid = (nd, ne)is the number of points per axis andfitsthe per-prime list of((num_d, num_e), (den_d, den_e))fitted degrees; returns'ALIAS','HEIGHT'or'INCONCLUSIVE'.classify(grid, cells)— a list of such entries; returns{'verdict', 'axis', 'counts'}withaxisequal to'd','eta'orNone. The verdict is ALIAS only when every entry is, and INCONCLUSIVE as soon as one entry is.discriminator(path=None),DISCRIMINATOR_PATH— the parsed reference fileDEGREE_ALIAS_DISCRIMINATOR.jsonthat comes with the package, beside the module (the two reference cases: grid sizes, fitted degrees, number of primes, and what happened when primes were added), and its location.python3 -m ratfit.degree_alias --selftest(withtools/onPYTHONPATH) orpython3 tools/ratfit/degree_alias.py --selftest— replays the two reference cases, two inputs that must come back INCONCLUSIVE, and a check that the reference file beside the module still matches them; run without--selftestit prints the usage text.
Closed forms for logarithmic integrals (ratfit.li2close)
Atom(c, W0, W1, P0, P1, lo, hi, tag='')— one term $c\ln\lvert P_0+P_1t\rvert/(W_0+W_1t)$ on $(lo, hi)$.ilin_atoms(c_outer, A0, A1, B0, B1, lo_i, hi_i, tv, sup, tag)— the four atoms produced by the closed form of $\int dc/((A_0+A_1c)(B_0+B_1c))$ over $[lo_i, hi_i]$, as a function oftv.close_atoms(atoms, param=None, domain=None, nsamples=6, dps=60, tol=None)— closed form of the atom sum with the divergence-cancellation check; returns aClosure(.finite,.ledger,.pieces) or raisesDivergenceError.emit_mpmath(expr, name='K_closed', param=None)— standalonempmathsource definingname(dps=50)orname(param, dps=50).emitted_function(src, name)— execute that source and return the function.RLi2— the sympy function $\mathrm{Re}\,\mathrm{Li}_2(x)$ used in the results.
Flat import names: tools/thiele_gate.py (also the command line), tools/li2close.py and tools/pathgrid.py forward to the package, so import thiele_gate, import li2close and from pathgrid import design_grid work too. degree_alias has no shim; it uses only the standard library, so import degree_alias also works with tools/ratfit/ itself on the path.
Used on this site
- Non-planar hexa-box — exact reconstruction of the path connection matrix from numeric reduction samples, with the sample grid designed around the path's coincidence points.
- Non-planar $q\bar q\to W^+W^-$ — exact reconstruction of the connection along each kinematic line from numeric reductions, including known-denominator fits for entries a blind fit did not reach.
Requirements and source
Python 3 with python-flint for the fitting core, sympy and mpmath for li2close, nothing beyond the standard library for degree_alias when it is run as tools/ratfit/degree_alias.py or imported flat (the ratfit.degree_alias form loads the package and so needs python-flint), and pytest for the tests. From the repository root, PYTHONPATH=<repo>/tools python3 -m pytest tools/ratfit/tests -q runs the self-tests: 53 pass and 2 are skipped, the two being comparisons against reference data not included in the public repository (they run when the environment variables RATFIT_THIELE_REF_DIR and RATFIT_KCLOSE_DIR point to that data). The code is tools/ratfit/ in BootLoops' bootloops-dev repository (GitHub organization BootLoops-ai), released under the MIT license. Vopclose calls Ratfit for its exact entry reconstruction, and the sampled reductions typically come from Kira, FireFly and Fermat. Thiele interpolation is classical; screening modulo a prime before an exact reconstruction follows FireFly's approach (arXiv:1904.00009).