FORM (external)

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

FORM is public software by Jos Vermaseren and the form-dev developers: a symbolic manipulation program made for expressions far too large to fit in memory. You write a short program in FORM's own language, run it from the command line, and FORM expands, substitutes and sorts the terms, using disk when they outgrow memory. BootLoops uses FORM unmodified for three jobs: the Dirac-trace and color algebra that turns a scattering process into a set of loop integrals, FORM 5's built-in Feynman-diagram generator, and FORM 5's arbitrary-precision multiple zeta values as an independent check on constants. What BootLoops adds is the wrapper package Formglue and the worked example on this page.

What it does

A FORM program declares symbols, vectors, indices and functions, defines expressions with Local, and applies substitution rules (id old = new;) and built-in operations in modules, each closed by .sort. FORM never holds a whole expression as a tree. It streams the terms through each module one at a time and merge-sorts the result, spilling to disk when needed, which is how it processes billions of terms where general computer-algebra systems stop. It does exactly what the program says: no automatic simplification, integration or equation solving. For particle physics it provides gamma matrices (g_), $d$-dimensional Dirac tracestraces of products of gamma matrices: the spin algebra that turns a squared amplitude into scalar products of momenta (tracen), index contraction, wildcard patterns and repeat loops, enough to write SU($N$) color algebra in a few lines; results are exact, with rational coefficients. The threaded build tform runs the same programs on several cores.

FORM 5 adds the two features BootLoops relies on most. diagrams_ generates the Feynman diagrams of a process from a Model block of particles and vertices and returns one term per diagram, whose node_ factors record each vertex with its fields and momenta; options such as OnShell_, NoTadpole_ and OnePI_ filter the set. #StartFloat <digits>d switches on arbitrary-precision floating point, after which Evaluate replaces multiple zeta valuesnested sums $\zeta(s_1,\dots,s_k)=\sum_{n_1\gt\cdots\gt n_k\ge 1} n_1^{-s_1}\cdots n_k^{-s_k}$, constants that appear in the expansions of many loop integrals (mzv_) and alternating Euler sums (euler_) by numbers. FORM's implementation shares no code with the mpmath library BootLoops otherwise uses, so agreement between the two is a meaningful check. The printed value is a plain decimal with no error bound, good to about the number of digits requested; Formglue asks for ten more than it needs.

There are limits to know before you start. The diagrams_ output gives every internal line its own momentum label and does not route loop momenta; Formglue's form_route.py does that. Masses are not in the model language, so a massive line is a distinct particle with the mass kept in your own table. In FORM 5.0.1 lin_, hpl_ and mpl_ are reserved names that never evaluate, so FORM is not a polylogarithm evaluator. #write crashes on symbol names longer than about 100 characters (keep them to 80 or fewer) and wraps long lines mid-token, so parse its output with Formglue's reader. The FORM 4.3 packaged by Linux distributions runs the algebra examples below but has no float mode and no diagram generator.

Examples

Tree-level $gg\to q\bar q$ in massless QCD, checked against the textbook. gg2qq.frm (downloads at the end of the page) multiplies the three-diagram amplitude by its conjugate with physical gluon polarization sums, takes the $d$-dimensional trace with tracen,1;, and imposes massless kinematics. It then reduces the color factors with the SU($N$) Fierz identity. That step, copied from the file, shows what FORM code looks like (NF is the number of colors; the preprocessor variable CFIERZ holds -1/(2*NF)):

repeat;
  id TrF(?x,a0?,?y)*TrF(?z,a0?,?w) = 1/2*TrF(?x,?w,?z,?y) `CFIERZ'*TrF(?x,?y)*TrF(?z,?w);
  id TrF(?x,a0?,?y,a0?,?z)         = 1/2*TrF(?x,?z)*TrF(?y) `CFIERZ'*TrF(?x,?y,?z);
  id TrF(a0?) = 0;
  id TrF      = NF;
endrepeat;

Run FORM, then the check (Python 3 with SymPy; set FORM_BIN if the binary is not called form):

form gg2qq.frm
python3 check_gg2qq.py

In a fraction of a second FORM prints Msq, the squared amplitude summed over spins, polarizations and colors and divided by $g^4$: a polynomial in $s$, $t$, $u$ and their inverses with d and NF symbolic, also written to gg2qq.out (FORM 4.3 and 5.0.1 give identical output). The check script reruns FORM, averages over the initial state, sets $d=4$, $N=3$, $u=-s-t$, and tests exact equality with the textbook result (Ellis, Stirling and Webber),

$$\overline{|\mathcal M|^2}/g^4 \;=\; \frac{t^2+u^2}{6\,tu}\;-\;\frac{3}{8}\,\frac{t^2+u^2}{s^2}\,.$$

The script then reruns with form -D MUT=1 gg2qq.frm (three-gluon vertex sign flipped) and -D MUT=2 (wrong $1/N$ term in the Fierz identity) and requires both comparisons to fail. It prints a PASS: line per step and exits 0; exit code 1 means a comparison went the wrong way, 2 that FORM or SymPy is missing.

The three tree-level diagrams for gg → qq̄: t- and u-channel quark exchange and the s-channel three-gluon vertex.
The three tree diagrams, drawn by render_gg2qq_diagrams.py from the vertex lists the FORM 5 generator emits for this process at loop order zero.

Generating the one-loop diagrams with FORM 5. enum_1loop.frm declares a QCD model with one quark flavor (qua/QUA), ghosts and the gluon self-couplings, then calls the generator and counts the terms. The arguments of diagrams_ are the model, the incoming and outgoing particles, the external momenta, the set kint of internal-momentum names, the loop count and the filters:

L T2 = diagrams_(QCD,{glu,glu},{qua,QUA},{p1,p2,q1,q2},kint,1,
    `OnShell_'+`NoTadpole_'+`NoSnail_');
.sort
#$n2 = termsin_(T2);
#write "COUNT gg_qqbar_1loop_onshell = `$n2'"

form enum_1loop.frm prints four such COUNT lines: 3 tree diagrams, 109 connected one-loop diagrams, 30 once tadpoles, snails and self-energy insertions on external legs are dropped (the set written to enum_1loop.out), and 7 one-particle-irreducible ones. Formglue then assigns loop momenta: python3 form_route.py enum_1loop.out --externals p1,p2,q1,q2 prints a line beginning ROUTED 30 diagrams, all self-checks PASS. For the box marked in the figure, box_numerator.frm carries the algebra to an integrand (trace against the conjugate tree, color, loop-momentum dot products collected into $k^2$, $k\cdot p_1$, $k\cdot p_2$, $k\cdot p_3$). Its two TERMS lines report 4427 terms after the $d$-dimensional trace and 1225 in the integrand-ready polynomial, in well under a second. That polynomial is the input to an integration-by-parts reductionthe linear-algebra step that rewrites every integral of a family in terms of a small basis of master integrals program such as Kira; FORM does not do the loop integration.

The 30 on-shell one-loop diagrams for gg → qq̄ in a grid, with diagram 21, a box, outlined in red.
The 30 one-loop diagrams in enum_1loop.out, numbered by the generator's own indices; dashed lines are ghosts and the red frame marks the box treated in box_numerator.frm.

A multiple zeta value to 120 digits. This complete program is one of Formglue's test fixtures (tests/fixtures/routing_glue/cap_float.frm); MZV=4 is the largest weight (sum of indices) FORM should prepare for, and Format floatprecision prints the full working precision:

#StartFloat 120d, MZV=4
Format floatprecision;
L FORACLE = mzv_(2,1);
Evaluate;
Print +f;
.end

A float-enabled FORM 5 finishes it in milliseconds; the recorded output beside the fixture ends with

   FORACLE =
      1.2020569031595942853997381615114499907649862923404988817922715553418382\
      0578631309018645587360933525814619915779526071942e+00;

which is $\zeta(3)$, as Euler's identity $\zeta(2,1)=\zeta(3)$ requires (FORM puts the outer index first, $\zeta(2,1)=\sum_{m\gt n\ge1}m^{-2}n^{-1}$). The backslash is FORM's own line wrapping, one reason to parse its output with Formglue, whose command line reaches the same engine: form_oracle.py --dps 40 euler -- -2,1 returns $\sum_{m\gt n\ge 1}(-1)^m m^{-2}n^{-1}=\zeta(3)/8$ to at least 40 digits.

Routines

BootLoops adds no code inside FORM; it is built from the upstream source and called as form (or tform). The BootLoops-side code around it is the Formglue package, which has its own page, and the worked example served here.

Formglue

Worked example (downloads below)

Requirements and source

FORM is written in C and distributed under the GPL-3.0 license at github.com/form-dev/form. The algebra examples run on FORM 4.x or 5; the diagram generator and the float mode need FORM 5 built from source with --enable-float. Formglue, tools/formglue/ in BootLoops' bootloops-dev repository (GitHub organization BootLoops-ai), released under the MIT license, is Python 3 with mpmath. FORM and HyperFORM are not bundled with it: they keep their own GPL-3.0 licenses and are run as separate programs (set FORM5_BIN if the float-enabled binary is not the form on the path). Formglue's self-tests python3 tests/test_form_io.py and python3 tests/test_form_route.py run on recorded FORM output and need no FORM; python3 tests/test_form_oracle.py skips its engine-dependent parts with a message when no float-enabled FORM 5 is found. From the repository root, python3 -m pytest tools/formglue -x -q -p no:cacheprovider runs all three. The worked example needs Python 3 with SymPy for the check and matplotlib for the figures: gg2qq.frm · check_gg2qq.py · enum_1loop.frm · box_numerator.frm · render_gg2qq_diagrams.py · gg2qq_topologies.json.

References: J.A.M. Vermaseren, New features of FORM, arXiv:math-ph/0010025; J. Kuipers, T. Ueda, J.A.M. Vermaseren and J. Vollinga, FORM version 4.0, arXiv:1203.6543; J. Davies, T. Kaneko, C. Marinissen, T. Ueda and J.A.M. Vermaseren, FORM 5.0 (floating point, multiple zeta values, and the diagram generator, which builds on T. Kaneko's GRACE), arXiv:2601.19982.

← back to the tools index