On this page

For developers

Idenso FORM color and Dirac source map

Mixed shipped evidence and target specification · reviewed 2026-08-21Implementation source mapproposal

FORM sources, Symbolica and Spenso target patterns, implementation mappings, historical validation commands, and unresolved provenance retained behind the concise public convention contract.

View the source note

Lifecycle
proposal
Owner
Ownership decision required
Review
2026-08-21 · umvyopkm
Freshness
reviewed
Evidence
Not an evidence record
Verified scopes
No verified code scopes recorded

FORM color and Dirac rules

This specification records source-backed replacement rules for FORM gamma-algebra simplification and the FORM color.h color-algebra package. The mathematical notation is independent of FORM token names except where a source symbol is documented literally. Open gamma strings always carry explicit bispinor indices; closed gamma traces are written as explicit bispinor contractions, not as a separate trace-index placeholder.

The Symbolica + spenso section uses the approved chain and trace tensor-pattern notation:

chain(bis(4,a),bis(4,c),
  gamma(in,out,p(2,mink(4))),
  gamma(in,out,mink(4,mu)))

and

chain(cof(Nc,i),dind(cof(Nc,j)),
  t(coad(Nc^2-1,a),in,out),
  t(coad(Nc^2-1,b),in,out))

This is a specification-level pattern notation. GammaLoop currently has internal helpers named spenso::gamma_chain and spenso::gamma_trace; those names are mentioned only when documenting the implementation source.

Source Inventory

Notational Conventions

Lorentz indices are written as 𝜇,𝜈,𝜌,𝜎 and are raised and lowered with 𝜂𝜇𝜈 and 𝜂𝜇𝜈. The dimension is denoted by 𝐷 in dimension-generic identities and fixed to 4 in the four-dimensional FORM trace4 rules. Repeated Lorentz labels are contracted.

Bispinor indices are 𝛼,𝛽,𝜒,𝛿. An open gamma chain is written as (Γ𝜇1𝜇𝑛)𝛼𝛽. A closed trace is an explicit contraction (Γ𝜇1𝜇𝑛)𝛼𝛼.

Fundamental color indices are 𝑖,𝑗,𝑘,𝑙. Adjoint color indices are 𝑎,𝑏,𝑐,𝑑,𝑒. Fundamental generators are (𝑇𝑎)𝑖𝑗. The package constants are mapped as 𝐶𝐴 cA, 𝐶𝐹 cR, 𝑇𝑅 I2R, and 𝑁𝑐 NR; NA is the adjoint dimension. For ordinary SU(𝑁𝑐), 𝐶𝐴=𝑁𝑐, 𝑇𝑅=12, and 𝐶𝐹=𝑁𝑐212𝑁𝑐, but color.h is written in terms of invariants.

The word product denotes an ordered noncommutative string inside a chain. It is not used as FORM syntax.

Gamma-algebra replacement rules

Overview

RuleDimensionPurpose
Gamma collectionallCollect adjacent bispinor-contracted gamma factors into an ordered chain.
Chain joiningallJoin two open chains when the outgoing bispinor index of one equals the incoming index of the next.
Metric contractionall or 𝐷Replace 𝛾𝜇𝛾𝜇 and related repeated Lorentz slots by the active dimension.
Trace closureallTurn an open chain with equal endpoints into an explicit bispinor contraction.
Trace recursion𝐷 or 4Evaluate even traces recursively and annihilate odd traces without gamma-five insertions.
Chisholm reduction4 onlyReduce 𝛾𝜇Γ𝛾𝜇 using four-dimensional identities.
Gamma-five and epsilon4 onlyUse Levi-Civita and gamma-five branch logic in FORM trace4.

G1. Gamma-chain product and joining

Mathematical identity:

𝛾(𝑣)𝛼𝛽𝛾(𝑤)𝛽𝜒=(Γ𝑣𝑤)𝛼𝜒

For longer strings, the same rule constructs an ordered product inside the chain:

(Γ𝑣1𝑣𝑚)𝛼𝛽(Γ𝑤1𝑤𝑛)𝛽𝜒=(Γ𝑣1𝑣𝑚𝑤1𝑤𝑛)𝛼𝜒

FORM source context:

/* Trace4 receives a string of gamma matrices in 'instring'. */
number = *params - 6;
...
for ( i = 0; i < number; i++ ) *p++ = *m++;

Source: https://github.com/form-dev/form/blob/master/sources/opera.c#L670-L686, https://github.com/form-dev/form/blob/master/sources/opera.c#L715-L745. Manual: https://www.nikhef.nl/~form/maindir/documentation/reference/html/manual.html#dx1-85012.

GammaLoop/idenso implementation currently collects adjacent gamma matrices by replacing two contracted spenso::gamma calls with an internal chain:

AGS.gamma_pattern(RS.a__, RS.b__, RS.c__) * AGS.gamma_pattern(RS.d__, RS.c__, RS.e__),
GS.chain_pattern(RS.b__, RS.e__, [RS.a__, RS.c__, RS.d__]),

Source: https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/dirac/mod.rs#L604-L613.

Symbolica + spenso pattern:

gamma(bis(4,a),bis(4,b),p(2,mink(4)))
* gamma(bis(4,b),bis(4,c),mink(4,mu))
  -> chain(bis(4,a),bis(4,c),
       gamma(in,out,p(2,mink(4))),
       gamma(in,out,mink(4,mu)))

Assumptions: in and out are local slots of each factor in the chain. Dummy bispinor labels consumed during collection are not retained as free indices.

G2. Chain orientation and reversal

Mathematical identity:

(Γ𝑣1𝑣𝑛)𝛼𝛽=((Γ𝑣𝑛𝑣1)𝛽𝛼)rev

Here rev means that the implementation may represent the same contracted tensor network with opposite local slot orientation. This is not a gamma-algebra identity by itself; it is a tensor-pattern canonicalization convention.

Pattern examples:

A(1,j,la,i,mu) * B(j,k) * C(k,l)
  -> chain(rep,i,l,A(1,out,la,in,mu),B(in,out),C(in,out))

B(j,k) * C(l,k)
  -> chain(rep,j,l,B(in,out),C(out,in))

Source context: Symbolica matches syntactically with wildcard variables and respects function-argument ordering for non-symmetric functions; see https://symbolica.io/docs/pattern_matching.html. spenso provides symbolic tensor structures and contraction support; see https://docs.rs/spenso/latest/spenso/.

G3. Metric contraction in gamma chains

Dimension-generic terminal identity:

𝛾𝛼𝛽𝜇𝛾𝜇,𝛽𝜒=𝐷𝛿𝛼𝜒

In the approved chain notation:

chain(bis(D,a),bis(D,c),
  gamma(in,out,mink(D,mu)),
  gamma(in,out,mink(D,mu)))
  -> D * g(bis(D,a),bis(D,c))

FORM source context: Trace4Gen tests repeated adjacent objects and puts the repeated pair into the accumulated delta list before recursing.

if ( *p == p[1] ) {
  *(t->accup)++ = *p;
  *(t->accup)++ = *p;
  ...
  Trace4Gen(..., number-2)
}

Source: https://github.com/form-dev/form/blob/master/sources/opera.c#L958-L972. Manual: https://www.nikhef.nl/~form/maindir/documentation/reference/html/manual.html#dx1-85012.

GammaLoop/idenso records the dimension contraction in its repeated-Lorentz chain patterns:

function!(GS.gamma_chain, ..., mink(d_,a_), ..., mink(d_,a_), ...)
  -> function!(GS.gamma_chain, ...) * d_

Source: https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/dirac/mod.rs#L784-L829.

Assumptions: 𝐷 is the dimension attached to the Lorentz representation. Four-dimensional Chisholm rules below require 𝐷=4.

G4. Trace closure with explicit bispinor contraction

Mathematical identity:

(Γ𝑣1𝑣𝑛)𝛼𝛼=𝛾(𝑣1)𝛼𝛽𝛾(𝑣𝑛)𝜒𝛼

Pattern:

chain(bis(4,a),bis(4,a),
  gamma(in,out,p(2,mink(4))),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,p(3,mink(4))))
  -> trace(bis(4),
       gamma(in,out,p(2,mink(4))),
       gamma(in,out,mink(4,mu)),
       gamma(in,out,p(3,mink(4))))

FORM source context: FORM trace4 and tracen operate on a spin line, represented internally as a string of gamma matrices. Trace4 copies that string into t->inlist and then dispatches to Trace4Gen.

t->inlist = AT.WorkPointer;
...
for ( i = 0; i < number; i++ ) *p++ = *m++;
...
ret = Trace4Gen(...);

Source: https://github.com/form-dev/form/blob/master/sources/opera.c#L730-L745, https://github.com/form-dev/form/blob/master/sources/opera.c#L820-L823. Manual: https://www.nikhef.nl/~form/maindir/documentation/reference/html/manual.html#dx1-85012.

GammaLoop/idenso closes chains when the endpoints agree:

replace(function!(GS.gamma_chain, RS.a__, RS.x_, RS.x_).to_pattern())
  .repeat()
  .with(function!(GS.gamma_trace, RS.a__).to_pattern())

Source: https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/dirac/mod.rs#L877-L879.

G5. Odd and even trace recursion

Odd trace without gamma-five:

(Γ𝑣1𝑣2𝑘+1)𝛼𝛼=0

Two-gamma trace:

𝛾𝛼𝛽𝜇𝛾𝛽𝛼𝜈=4𝜂𝜇𝜈

Recursive even trace:

(Γ𝑣1𝑣2𝑘)𝛼𝛼=𝑟=22𝑘(1)𝑟𝜂𝑣1𝑣𝑟(Γ𝑣2𝑣𝑟̂𝑣2𝑘)𝛽𝛽

FORM source context:

if ( ( number < 0 ) || ( number & 1 ) ) return(0);
...
if ( number == 2 ) { *kron++ = *t->inlist; *kron++ = t->inlist[1]; }

Source: https://github.com/form-dev/form/blob/master/sources/opera.c#L424-L432. The recursive trace generator comments describe zero- and two-gamma terminal cases before general recursion: https://github.com/form-dev/form/blob/master/sources/opera.c#L830-L856. Manual: https://www.nikhef.nl/~form/maindir/documentation/reference/html/manual.html#dx1-85012.

Symbolica + spenso pattern:

trace(bis(4),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,mink(4,nu)))
  -> 4 * g(mink(4,mu),mink(4,nu))

Dummy-index freshness: recursive trace replacement removes the paired Lorentz argument and must not reuse bound labels introduced by metric contractions.

G6. Four-dimensional Chisholm reductions

Odd interior:

𝛾𝛼𝛽𝜇(Γ𝜈1𝜈2𝑘+1)𝛽𝜒𝛾𝜇,𝜒𝛿=2(Γ𝜈2𝑘+1𝜈1)𝛼𝛿

Even interior:

𝛾𝛼𝛽𝜇(Γ𝜈1𝜈2𝑘)𝛽𝜒𝛾𝜇,𝜒𝛿=2(Γ𝜈2𝑘𝜈1𝜈2𝑘1)𝛼𝛿+2(Γ𝜈2𝑘1𝜈1𝜈2𝑘)𝛼𝛿

Special two-interior case:

𝛾𝛼𝛽𝜇𝛾𝛽𝜒𝜈𝛾𝜒𝜆𝜌𝛾𝜇,𝜆𝛿=4𝜂𝜈𝜌𝛿𝛼𝛿

FORM source comment:

g(mu)*g(a1)*...*g(an)*g(mu)=
n=odd:  -2*g(an)*...*g(a1)
n=even: 2*g(an)*g(a1)*...*g(a(n-1))
    +2*g(a(n-1))*...*g(a1)*g(an)
There is a special case for n=2 : 4*d(a1,a2)*gi

Source: https://github.com/form-dev/form/blob/master/sources/opera.c#L670-L680. Implementation odd contraction: https://github.com/form-dev/form/blob/master/sources/opera.c#L978-L1012. Implementation even contraction: https://github.com/form-dev/form/blob/master/sources/opera.c#L1021-L1096, https://github.com/form-dev/form/blob/master/sources/opera.c#L1118-L1157. Manual: https://www.nikhef.nl/~form/maindir/documentation/reference/html/manual.html#dx1-85012.

Pattern:

chain(bis(4,a),bis(4,d),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,mink(4,nu1)),
  gamma(in,out,mink(4,nu2)),
  gamma(in,out,mink(4,nu3)),
  gamma(in,out,mink(4,mu)))
  -> -2 * chain(bis(4,a),bis(4,d),
       gamma(in,out,mink(4,nu3)),
       gamma(in,out,mink(4,nu2)),
       gamma(in,out,mink(4,nu1)))

Assumptions: The contracted Lorentz label must belong to a four-dimensional Lorentz representation. The source code checks dimension equality with 4 before applying the Chisholm branches.

G7. Gamma-five and epsilon rules

FORM trace4 uses the four-dimensional identity:

𝛾𝜇𝛾𝜈𝛾𝜌=𝜀𝜇𝜈𝜌𝜎𝛾5𝛾𝜎+𝜂𝜇𝜈𝛾𝜌𝜂𝜇𝜌𝛾𝜈+𝜂𝜈𝜌𝛾𝜇

Source comment:

g_(j,mu)*g_(j,nu)*g_(j,ro)=e_(mu,nu,ro,si)*g5_(j)*g_(j,si)
+d_(mu,nu)*g_(j,ro)-d_(mu,ro)*g_(j,nu)+d_(nu,ro)*g_(j,mu)
which is for 4 dimensions only!

Source: https://github.com/form-dev/form/blob/master/sources/opera.c#L320-L329. The gamma-five branch logic in trace generation is at https://github.com/form-dev/form/blob/master/sources/opera.c#L480-L489 and https://github.com/form-dev/form/blob/master/sources/opera.c#L808-L813. Manual: https://www.nikhef.nl/~form/maindir/documentation/reference/html/manual.html#dx1-85012.

Pattern:

chain(bis(4,a),bis(4,b),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,mink(4,nu)),
  gamma(in,out,mink(4,rho)))
  -> epsilon(mink(4,mu),mink(4,nu),mink(4,rho),mink(4,sigma))
     * chain(bis(4,a),bis(4,b),
         gamma5(in,out),
         gamma(in,out,mink(4,sigma)))
     + g(mink(4,mu),mink(4,nu)) * chain(... gamma(rho) ...)
     - g(mink(4,mu),mink(4,rho)) * chain(... gamma(nu) ...)
     + g(mink(4,nu),mink(4,rho)) * chain(... gamma(mu) ...)

This is explicitly four-dimensional and requires a fresh dummy Lorentz label sigma.

Color-algebra replacement rules from color.h

Overview

RuleConventionPurpose
Line joiningT(i,j,?a)Join open noncommutative color lines.
Trace closurecOlTr, cOlTtConvert closed lines to trace blocks and choose trace blocks to simplify.
Casimir reductioncR, cARemove repeated adjacent or separated generators in traces.
Trace normalizationI2REvaluate two-generator trace.
Structure constantsf antisymmetricContract small f loops and rewrite larger loops through invariants.
Symmetric invariantscOldR, cOldARepresent and contract generalized d tensors.
simpli strategyprocedureEliminate f tensors in environments of invariants using generalized Jacobi moves.

C1. Open color-line joining

Mathematical identity:

(𝑇𝑎1𝑇𝑎𝑚)𝑖𝑗(𝑇𝑏1𝑇𝑏𝑛)𝑗𝑘=(𝑇𝑎1𝑇𝑎𝑚𝑇𝑏1𝑇𝑏𝑛)𝑖𝑘

FORM source:

repeat id T(cOli1?,cOli2?,?a)*T(cOli2?,cOli3?,?b) = T(cOli1,cOli3,?a,?b);
id  T(cOli1?,cOli1?,?a) = cOlTr(?a);

Source package lines: color.h lines 91–93 at https://www.nikhef.nl/~form/maindir/packages/color/color.h. Package documentation: https://www.nikhef.nl/~form/maindir/packages/color/color.html. No official GitHub line anchor was found for color.h; see the validation appendix.

Pattern:

chain(cof(Nc,i),dind(cof(Nc,j)),
  t(coad(Nc^2-1,a1),in,out),
  t(coad(Nc^2-1,a2),in,out))
*
chain(cof(Nc,j),dind(cof(Nc,k)),
  t(coad(Nc^2-1,b1),in,out))
  -> chain(cof(Nc,i),dind(cof(Nc,k)),
       t(coad(Nc^2-1,a1),in,out),
       t(coad(Nc^2-1,a2),in,out),
       t(coad(Nc^2-1,b1),in,out))

C2. Trace closure and trace normalization

Closed line:

(𝑇𝑎1𝑇𝑎𝑛)𝑖𝑖=tr𝑅(𝑇𝑎1𝑇𝑎𝑛)

One generator:

tr𝑅(𝑇𝑎)=0

Two generators:

tr𝑅(𝑇𝑎𝑇𝑏)=𝑇𝑅𝛿𝑎𝑏

FORM source:

id  cOlTt(cOli1?) = 0;
id  cOlTt(cOli1?,cOli2?) = I2R*d_(cOli1,cOli2);
id  cOlTt(cOli1?,cOli2?,cOli3?) = cOldR(...) + i_/2*f(...)*I2R;

Source package lines: color.h lines 459–461 at https://www.nikhef.nl/~form/maindir/packages/color/color.h. Package documentation: https://www.nikhef.nl/~form/maindir/packages/color/color.html.

Pattern:

chain(cof(Nc,i),dind(cof(Nc,i)),
  t(coad(Nc^2-1,a),in,out),
  t(coad(Nc^2-1,b),in,out))
  -> trace(cof(Nc),
       t(coad(Nc^2-1,a),in,out),
       t(coad(Nc^2-1,b),in,out))
  -> TR * g(coad(Nc^2-1,a),coad(Nc^2-1,b))

C3. Fundamental Casimir and adjacent contractions

Mathematical identities:

(𝑇𝑎)𝑖𝑗(𝑇𝑎)𝑗𝑘=𝐶𝐹𝛿𝑖𝑘tr𝑅(𝑇𝑎𝑇𝑏𝑇𝑎product(𝑋))=(𝐶𝐹𝐶𝐴2)tr𝑅(𝑇𝑏product(𝑋))

FORM source:

id  cOlTr(cOli1?,cOli1?,?a) = cR*cOlTr(?a);
id  cOlTr(cOli1?,cOli2?,cOli1?,?a) = [cR-cA/2]*cOlTr(cOli2,?a);

Source package lines: color.h lines 108–111 at https://www.nikhef.nl/~form/maindir/packages/color/color.h, repeated for cOlTt at lines 173–175. Package documentation: https://www.nikhef.nl/~form/maindir/packages/color/color.html.

Pattern:

chain(cof(Nc,i),dind(cof(Nc,k)),
  t(coad(Nc^2-1,a),in,out),
  t(coad(Nc^2-1,a),in,out))
  -> C_F * g(cof(Nc,i),dind(cof(Nc,k)))

Assumptions: color.h keeps C_F as cR, not automatically as 𝑁𝑐212𝑁𝑐.

C4. Fundamental Fierz generator contraction

Mathematical identity:

(𝑇𝑎)𝑖𝑗(𝑇𝑎)𝑘𝑙=𝑇𝑅(𝛿𝑖𝑙𝛿𝑘𝑗𝑁𝑐1𝛿𝑖𝑗𝛿𝑘𝑙)

This identity is not written in this explicit form in color.h, whose main algorithm uses trace joining and invariant reductions. It is implemented directly in GammaLoop/idenso:

t(e,a,b) * t(e,c,d)
  -> TR * (id(a,d) * id(c,b) - id(a,b) * id(c,d) / Nc)

Source: https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/color/mod.rs#L407-L414. Symbolica documentation for replacement mechanics: https://symbolica.io/docs/pattern_matching.html.

Pattern:

t(coad(Nc^2-1,a),cof(Nc,i),dind(cof(Nc,j)))
* t(coad(Nc^2-1,a),cof(Nc,k),dind(cof(Nc,l)))
  -> TR * (
       g(cof(Nc,i),dind(cof(Nc,l)))
       * g(cof(Nc,k),dind(cof(Nc,j)))
       - g(cof(Nc,i),dind(cof(Nc,j)))
       * g(cof(Nc,k),dind(cof(Nc,l))) / Nc)

C5. Structure-constant loop contractions

Mathematical identities:

𝑓𝑎𝑐𝑑𝑓𝑏𝑐𝑑=𝐶𝐴𝛿𝑎𝑏𝑓𝑎𝑏𝑒𝑓𝑏𝑐𝑓𝑓𝑐𝑎𝑔=𝐶𝐴2𝑓𝑒𝑓𝑔

FORM source:

ReplaceLoop,f,a=3,l<4,outfun=cOlff;
id  cOlff(cOli1?,cOli2?) = -cA*d_(cOli1,cOli2);
id  cOlff(cOli1?,cOli2?,cOli3?) = cA/2*f(cOli1,cOli2,cOli3);

Source package lines: color.h lines 148–150, 208–210, 505–507, and 538–541 at https://www.nikhef.nl/~form/maindir/packages/color/color.h. Package documentation: https://www.nikhef.nl/~form/maindir/packages/color/color.html.

Pattern:

f(coad(Nc^2-1,a),coad(Nc^2-1,c),coad(Nc^2-1,d))
* f(coad(Nc^2-1,b),coad(Nc^2-1,c),coad(Nc^2-1,d))
  -> ca * g(coad(Nc^2-1,a),coad(Nc^2-1,b))

Sign note: FORM’s ReplaceLoop loop orientation produces -cA*d_(...) for the two-argument cyclic helper. The standard identity above assumes the displayed orientation 𝑓𝑎𝑐𝑑𝑓𝑏𝑐𝑑.

C6. Mixed trace–structure contraction

Mathematical identity:

tr𝑅(𝑇𝑎𝑇𝑏product(𝑋))𝑓𝑎𝑏𝑐=𝑖𝐶𝐴2tr𝑅(𝑇𝑐product(𝑋))

FORM source:

id  cOlTr(cOli1?,cOli2?,?a)*f(cOli1?,cOli2?,cOli3?) =
  i_*cA/2*cOlTr(cOli3,?a);

Source package lines: color.h lines 108–111 and 173–175 at https://www.nikhef.nl/~form/maindir/packages/color/color.h. Package documentation: https://www.nikhef.nl/~form/maindir/packages/color/color.html.

Pattern:

trace(cof(Nc),
  t(coad(Nc^2-1,a),in,out),
  t(coad(Nc^2-1,b),in,out),
  rest__)
* f(coad(Nc^2-1,a),coad(Nc^2-1,b),coad(Nc^2-1,c))
  -> i_ * ca / 2 * trace(cof(Nc),
       t(coad(Nc^2-1,c),in,out),
       rest__)

C7. Symmetric invariant contractions

color.h uses cOldR and cOldA for symmetric invariant tensors and reduces contractions to named invariants such as d33, d44, and d55.

Representative identities:

𝑑𝑅𝑎𝑏𝑐𝑑𝑅𝑎𝑏𝑑=𝑑33(𝑅,𝑅)𝛿𝑐𝑑𝑁𝐴𝑑𝑋𝑎𝑏𝑐𝑑𝑌𝑎𝑏𝑐=𝑑33(𝑋,𝑌)

FORM source:

id cOldr1?cOldar[cOlx3](cOli1?,cOli2?,cOli3?)
 *cOldr2?cOldar[cOlx4](cOli1?,cOli2?,cOli4?)
 = d33(...)*cOlx1*d_(cOli3,cOli4)/NA;
...
id cOldr1?cOldar[cOlx3](cOli1?,...,cOli3?)
 *cOldr2?cOldar[cOlx4](cOli1?,...,cOli3?) = d33(...);

Source package lines: color.h lines 1287–1294 and 1316–1335 at https://www.nikhef.nl/~form/maindir/packages/color/color.h. Package documentation: https://www.nikhef.nl/~form/maindir/packages/color/color.html.

Pattern:

d(sym_rep_x,coad(Nc^2-1,a),coad(Nc^2-1,b),coad(Nc^2-1,c))
* d(sym_rep_y,coad(Nc^2-1,a),coad(Nc^2-1,b),coad(Nc^2-1,d))
  -> d33(sym_rep_x,sym_rep_y)
     * g(coad(Nc^2-1,c),coad(Nc^2-1,d)) / (Nc^2 - 1)

Assumptions: The package treats these as group-invariant placeholders rather than expanding them into 𝑁𝑐 polynomials.

C8. simpli and generalized Jacobi strategy

simpli is an implementation strategy, not one scalar identity. It eliminates pairs of structure constants in environments of symmetric invariants and applies generalized Jacobi transformations.

FORM source:

* Procedure tries to eliminate f tensors in an environment of invariants.
* Apply the generalized Jacobi identity ...
if ( count(f,1) != multipleof(2) ) discard;
#call contract
...
id f(cOlpR`isimpli',cOli1?,cOli3?)*f(cOlpR`isimpli',cOli2?,cOli3?) =
  cOlpR`isimpli'(cOli1)*cOlpR`isimpli'(cOli2)*cA/2;

Source package lines: color.h lines 688–713 at https://www.nikhef.nl/~form/maindir/packages/color/color.h. Package documentation: https://www.nikhef.nl/~form/maindir/packages/color/color.html.

Pattern family:

f(coad(Nc^2-1,x),coad(Nc^2-1,a),coad(Nc^2-1,c))
* f(coad(Nc^2-1,x),coad(Nc^2-1,b),coad(Nc^2-1,c))
* invariant_environment__
  -> ca / 2 * projected_invariant(a,b,invariant_environment__)

This rule class requires canonicalization of symmetric invariants and freshness of all auxiliary adjoint labels introduced during generalized Jacobi expansion.

Symbolica and Spenso rewrite patterns

This section is written for a Rust implementation with Symbolica as a dependency. Symbolica’s Rust id module exposes pattern matching through AtomCore::replace, AtomCore::pattern_match, Replacement, MatchSettings, and ReplaceBuilder; complex right-hand sides can be built with ReplaceBuilder::with_map or with replace_map callbacks. See https://docs.rs/symbolica/latest/symbolica/id/index.html and https://docs.rs/symbolica/latest/symbolica/id/struct.ReplaceBuilder.html. spenso represents tensor slots through symbolic structures and representation slots; the crate documents tensor structures, symbolic tensors, and contraction support at https://docs.rs/spenso/latest/spenso/, with symbolic tensor-library keys in https://docs.rs/spenso/latest/src/spenso/network/library/symbolic.rs.html.

Symbolica wildcard convention: x_ is one atom, x__ is one-or-more atoms, and x___ is zero-or-more atoms. Function argument order is preserved for non-symmetric functions. Repeated wildcard names require exact structural equality; this is the right mechanism for repeated dummy labels such as mu_ or a_.

The public target syntax for this specification is chain(...) and trace(...). If implemented inside GammaLoop/idenso, the current internal Rust symbols are spenso::gamma_chain and spenso::gamma_trace; those should be adapter names only, not the public pattern vocabulary. The approved surface form remains:

chain(bis(4,a),bis(4,c),
  gamma(in,out,p(2,mink(4))),
  gamma(in,out,mink(4,mu)))

Rust pattern construction guidelines

Use concrete spenso builders for tensor slots where available and Symbolica wildcards only for the abstract labels. This keeps representation constraints attached to the pattern.

use symbolica::{
  atom::{Atom, AtomCore, AtomView, FunctionBuilder, Symbol},
  function, symbol,
  id::{Match, MatchSettings, Pattern, Replacement},
  utils::Settable,
};

Implementation rules:

  • Use Replacement::new(lhs.to_pattern(), rhs.to_pattern()) for local structural rules whose right side is another static pattern.
  • Use replace_multiple_into in a loop for FORM-style short-circuit passes where rule order matters and each pass should be followed by expansion and metric simplification.
  • Use replace_map or ReplaceBuilder::with_map for Chisholm parity, sequence reversal, trace recursion, ReplaceLoop-style loop detection, cyclic color traces, and fresh dummy allocation.
  • Add MatchSettings { rhs_cache_size: 0, ..Default::default() } for replacement maps whose right side depends on match-local fresh symbols.
  • Keep chain and trace non-symmetric. Their argument order is algebraically meaningful.

Gamma collection patterns

Mathematical identity: Equation 2. Source: https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/dirac/mod.rs#L604-L613.

Raw gamma pair:

gamma(bis(d_,a_),bis(d_,b_),x_)
* gamma(bis(d_,b_),bis(d_,c_),y_)
  -> chain(bis(d_,a_),bis(d_,c_),
       gamma(in,out,x_),
       gamma(in,out,y_))

Append and prepend raw gamma factors:

chain(bis(d_,a_),bis(d_,b_),xs___)
* gamma(bis(d_,b_),bis(d_,c_),y_)
  -> chain(bis(d_,a_),bis(d_,c_),xs___,gamma(in,out,y_))

gamma(bis(d_,a_),bis(d_,b_),x_)
* chain(bis(d_,b_),bis(d_,c_),ys___)
  -> chain(bis(d_,a_),bis(d_,c_),gamma(in,out,x_),ys___)

Join two chains:

chain(bis(d_,a_),bis(d_,b_),xs___)
* chain(bis(d_,b_),bis(d_,c_),ys___)
  -> chain(bis(d_,a_),bis(d_,c_),xs___,ys___)

Orientation case:

chain(bis(d_,a_),bis(d_,b_),xs___)
* chain(bis(d_,c_),bis(d_,b_),ys___)
  -> chain(bis(d_,a_),bis(d_,c_),xs___,reverse_flip(ys___))

reverse_flip is not a plain Symbolica replacement. Build it in Rust by reading the matched ys___ argument list, reversing the entries, and swapping in and out in each tensor factor.

Gamma terminal and trace patterns

Mathematical identity: Equation 5.

chain(bis(d_,a_),bis(d_,a_),xs___)
  -> trace(bis(d_),xs___)

trace(bis(d_),gamma(in,out,x_))
  -> 0

trace(bis(4),
  gamma(in,out,mink(4,mu_)),
  gamma(in,out,mink(4,nu_)))
  -> 4 * g(mink(4,mu_),mink(4,nu_))

Adjacent repeated Lorentz object:

chain(bis(d_,a_),bis(d_,b_),
  xs___,
  gamma(in,out,mink(d_,mu_)),
  gamma(in,out,mink(d_,mu_)),
  ys___)
  -> d_ * chain(bis(d_,a_),bis(d_,b_),xs___,ys___)

GammaLoop/idenso currently has the equivalent repeated-object contraction in Rust at https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/dirac/mod.rs#L784-L829 and trace closure at https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/dirac/mod.rs#L877-L879. FORM’s corresponding short-circuit in Trace4Gen removes adjacent equal objects before deeper recursion; source https://github.com/form-dev/form/blob/master/sources/opera.c#L958-L972.

Gamma Chisholm and trace recursion builders

Mathematical identities: Equation 9, Equation 10, and Equation 8. Source: https://github.com/form-dev/form/blob/master/sources/opera.c#L670-L680, https://github.com/form-dev/form/blob/master/sources/opera.c#L978-L1012, https://github.com/form-dev/form/blob/master/sources/opera.c#L1021-L1096, https://github.com/form-dev/form/blob/master/sources/opera.c#L1118-L1157.

Match contracted endpoints in four dimensions:

chain(bis(4,a_),bis(4,b_),
  gamma(in,out,mink(4,mu_)),
  middle___,
  gamma(in,out,mink(4,mu_)))

Rust-side builder:

fn build_chisholm(middle: &[Atom], a: Atom, b: Atom) -> Option<Atom> {
  if !all_gamma_factors(middle) {
    return None;
  }
  match middle.len() {
    n if n % 2 == 1 => {
      Some(-Atom::num(2) * chain(a, b, reverse(middle)))
    }
    2 => {
      let (x, y) = lorentz_pair(&middle[0], &middle[1])?;
      Some(Atom::num(4) * g(x, y) * bis_id(a, b))
    }
    n if n % 2 == 0 => {
      Some(Atom::num(2) * chain(a.clone(), b.clone(), move_last_to_front(middle))
        + Atom::num(2) * chain(a, b, reverse_except_last_then_last(middle)))
    }
    _ => None,
  }
}

Trace recursion should also be a Rust-side builder, not a static RHS:

trace(bis(4),first_,rest___)

Builder rule: if the trace length is odd, return zero. If the length is two, return 4 * g(first, second). Otherwise sum over all pairings of first_ with one later gamma, alternating signs and recursively rebuilding trace(bis(4), ...). This mirrors the source branch that uses zero/two-gamma terminals and then recursive generation; see https://github.com/form-dev/form/blob/master/sources/opera.c#L424-L432 and https://github.com/form-dev/form/blob/master/sources/opera.c#L830-L856.

Color collection patterns

Mathematical identity: Equation 13.

Raw generator pair:

t(coad(na_,a_),cof(nc_,i_),dind(cof(nc_,j_)))
* t(coad(na_,b_),cof(nc_,j_),dind(cof(nc_,k_)))
  -> chain(cof(nc_,i_),dind(cof(nc_,k_)),
       t(coad(na_,a_),in,out),
       t(coad(na_,b_),in,out))

Join chains:

chain(cof(nc_,i_),dind(cof(nc_,j_)),xs___)
* chain(cof(nc_,j_),dind(cof(nc_,k_)),ys___)
  -> chain(cof(nc_,i_),dind(cof(nc_,k_)),xs___,ys___)

Opposite endpoint orientation:

chain(cof(nc_,i_),dind(cof(nc_,j_)),xs___)
* chain(cof(nc_,k_),dind(cof(nc_,j_)),ys___)
  -> chain(cof(nc_,i_),dind(cof(nc_,k_)),xs___,reverse_flip(ys___))

The first two rules correspond to color.h line joining and trace closure at package lines 91–93. GammaLoop/idenso’s current direct color simplifier starts from raw spenso::t and spenso::f patterns; source https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/color/mod.rs#L360-L414.

Color trace and Casimir patterns

Mathematical identity: Equation 14 and Equation 16.

chain(cof(nc_,i_),dind(cof(nc_,i_)),xs___)
  -> trace(cof(nc_),xs___)

trace(cof(nc_),t(coad(na_,a_),in,out))
  -> 0

trace(cof(nc_),
  t(coad(na_,a_),in,out),
  t(coad(na_,b_),in,out))
  -> TR * g(coad(na_,a_),coad(na_,b_))

trace(cof(nc_),
  t(coad(na_,a_),in,out),
  t(coad(na_,b_),in,out),
  t(coad(na_,c_),in,out))
  -> dR(coad(na_,a_),coad(na_,b_),coad(na_,c_))
     + i_ / 2 * TR * f(coad(na_,a_),coad(na_,b_),coad(na_,c_))

Casimir and separated-generator shortcuts:

chain(cof(nc_,i_),dind(cof(nc_,k_)),
  xs___,
  t(coad(na_,a_),in,out),
  t(coad(na_,a_),in,out),
  ys___)
  -> CF * chain(cof(nc_,i_),dind(cof(nc_,k_)),xs___,ys___)

trace(cof(nc_),
  t(coad(na_,a_),in,out),
  t(coad(na_,b_),in,out),
  t(coad(na_,a_),in,out),
  xs___)
  -> (CF - CA / 2) * trace(cof(nc_),t(coad(na_,b_),in,out),xs___)

Source: color.h selected-trace terminal rules at lines 459–464 and easy contraction rules at lines 108–111 and 173–175.

Color structure-constant and invariant patterns

Structure-constant contractions:

f(coad(na_,a_),coad(na_,c_),coad(na_,d_))
* f(coad(na_,b_),coad(na_,c_),coad(na_,d_))
  -> CA * g(coad(na_,a_),coad(na_,b_))

f(coad(na_,a_),coad(na_,b_),coad(na_,e_))
* f(coad(na_,b_),coad(na_,c_),coad(na_,f_))
* f(coad(na_,c_),coad(na_,a_),coad(na_,g_))
  -> CA / 2 * f(coad(na_,e_),coad(na_,f_),coad(na_,g_))

Trace–structure shortcut:

trace(cof(nc_),
  t(coad(na_,a_),in,out),
  t(coad(na_,b_),in,out),
  xs___)
* f(coad(na_,a_),coad(na_,b_),coad(na_,c_))
  -> i_ * CA / 2 * trace(cof(nc_),t(coad(na_,c_),in,out),xs___)

Symmetric-invariant contraction:

d(sym_x_,coad(na_,a_),coad(na_,b_),coad(na_,c_))
* d(sym_y_,coad(na_,a_),coad(na_,b_),coad(na_,d_))
  -> d33(sym_x_,sym_y_) * g(coad(na_,c_),coad(na_,d_)) / na_

f must be registered or canonicalized as antisymmetric. Symbolica’s documentation warns that antisymmetric functions canonicalize written patterns; implementers should either use canonical argument order in the pattern or absorb the sign in a pre-canonicalization pass. Source for small f loop reductions: color.h lines 148–150, 208–210, 505–507, and 537–541. Source for d33 and higher invariant contractions: color.h lines 1287–1348.

FORM short-circuit rewrite order

These are the high-priority short-circuit patterns FORM uses before falling back to expensive generic recursion.

Gamma trace4 short-circuit order:

Color color.h short-circuit order:

  • Join open color lines and close equal endpoints before any trace selection. Source color.h lines 91–93.
  • Skip the main trace route unless at least one closed trace exists. Source color.h lines 95–103.
  • Apply easy trace contractions first: adjacent equal generator, separated a b a, and trace times f(a,b,c). Source color.h lines 108–111 and 173–175.
  • Rewrite duplicated trace blocks of lengths four, three, and two before general expansion. Source color.h lines 112–147 and 178–207.
  • Collapse small f loops via ReplaceLoop: two-leg and three-leg loops are terminal. Source color.h lines 148–150, 208–210, 505–507, 537–541, and 672–676.
  • Select the trace with the fewest different indices by wrapping traces in cOlTT. Source color.h lines 156–163.
  • Use terminal selected-trace rules for one, two, three, and four generators before converting longer traces back to T. Source color.h lines 459–466.
  • In simpli, discard odd f counts, contract matching invariant-vector f f pairs, then run generalized Jacobi/invariant passes. Source color.h lines 688–724.
  • Convert completed invariant-vector products into d33, d44, d55, and higher invariants, and discard impossible overlap topologies. Source color.h lines 1258–1294 and 1316–1348.

Rust implementation note: implement the short-circuit order as ordered passes, not as one unordered replace_multiple containing every rule. FORM’s performance relies on reducing the expression before the broader searches are attempted.

FORM-side test cases in Symbolica/Spenso syntax

This section translates the compact FORM-side rule tests and the package example cases into the chain/trace notation used above. Expected values are written in the same symbolic convention: TR for I2R, CA for cA, CF for cR, and NA for adjoint dimension. The local validation used FORM 4.3.1 for the explicitly listed compact values.

Gamma trace tests

Source basis: FORM manual gamma algebra and trace4 implementation; see https://www.nikhef.nl/~form/maindir/documentation/reference/html/manual.html#dx1-85012, https://github.com/form-dev/form/blob/master/sources/opera.c#L424-L432, and https://github.com/form-dev/form/blob/master/sources/opera.c#L867-L875.

// FORM: g_(1,mu,nu); trace4,1;
trace(bis(4),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,mink(4,nu)))
  -> 4 * g(mink(4,mu),mink(4,nu))

// FORM: g_(1,mu,nu,rho); trace4,1;
trace(bis(4),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,mink(4,nu)),
  gamma(in,out,mink(4,rho)))
  -> 0

// FORM: g_(1,mu,nu,rho,sigma); trace4,1;
trace(bis(4),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,mink(4,nu)),
  gamma(in,out,mink(4,rho)),
  gamma(in,out,mink(4,sigma)))
  -> 4 * g(mink(4,mu),mink(4,nu)) * g(mink(4,rho),mink(4,sigma))
   - 4 * g(mink(4,mu),mink(4,rho)) * g(mink(4,nu),mink(4,sigma))
   + 4 * g(mink(4,mu),mink(4,sigma)) * g(mink(4,nu),mink(4,rho))

Chisholm and adjacent-contraction chain tests:

// FORM manual: g_(1,mu,mu) = gi_(1)*d_(mu,mu).
chain(bis(d,a),bis(d,b),
  gamma(in,out,mink(d,mu)),
  gamma(in,out,mink(d,mu)))
  -> d * g(bis(d,a),bis(d,b))

// FORM manual, four-dimensional odd interior.
chain(bis(4,a),bis(4,b),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,mink(4,nu1)),
  gamma(in,out,mink(4,nu2)),
  gamma(in,out,mink(4,nu3)),
  gamma(in,out,mink(4,mu)))
  -> -2 * chain(bis(4,a),bis(4,b),
       gamma(in,out,mink(4,nu3)),
       gamma(in,out,mink(4,nu2)),
       gamma(in,out,mink(4,nu1)))

// FORM manual, four-dimensional two-interior special case.
chain(bis(4,a),bis(4,b),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,mink(4,nu)),
  gamma(in,out,mink(4,rho)),
  gamma(in,out,mink(4,mu)))
  -> 4 * g(mink(4,nu),mink(4,rho)) * g(bis(4,a),bis(4,b))

Gamma-five epsilon test:

// FORM Trick identity in opera.c.
chain(bis(4,a),bis(4,b),
  gamma(in,out,mink(4,mu)),
  gamma(in,out,mink(4,nu)),
  gamma(in,out,mink(4,rho)))
  -> epsilon(mink(4,mu),mink(4,nu),mink(4,rho),mink(4,sigma))
     * chain(bis(4,a),bis(4,b),
         gamma5(in,out),
         gamma(in,out,mink(4,sigma)))
     + g(mink(4,mu),mink(4,nu))
       * chain(bis(4,a),bis(4,b),gamma(in,out,mink(4,rho)))
     - g(mink(4,mu),mink(4,rho))
       * chain(bis(4,a),bis(4,b),gamma(in,out,mink(4,nu)))
     + g(mink(4,nu),mink(4,rho))
       * chain(bis(4,a),bis(4,b),gamma(in,out,mink(4,mu)))

FORM manual gamma-five stress examples:

// FORM: symmetric trace of gamma5 and 12 regular matrices via distrib_ and tracen.
g5_trace_symmetric_12(m1,...,m12)
  -> 51975 terms

// FORM: regular trace g_(1,5_,m1,...,m12); trace4,1.
trace(bis(4),gamma5(in,out),gamma(in,out,mink(4,m1)),...,gamma(in,out,mink(4,m12)))
  -> 1029 output terms after FORM trace4

These are term-count regression tests from the manual, not compact algebraic values.

Compact color-rule tests

Source basis: color.h line joining, selected trace terminals, and small f loops; see https://www.nikhef.nl/~form/maindir/packages/color/color.h, especially lines 91–93, 459–464, and 505–507.

// FORM: T(i1,i1,a)
chain(cof(Nc,i),dind(cof(Nc,i)),
  t(coad(NA,a),in,out))
  -> 0

// FORM: T(i1,i1,a,b)
chain(cof(Nc,i),dind(cof(Nc,i)),
  t(coad(NA,a),in,out),
  t(coad(NA,b),in,out))
  -> TR * g(coad(NA,a),coad(NA,b))

// FORM: T(i1,i1,a,b,c)
chain(cof(Nc,i),dind(cof(Nc,i)),
  t(coad(NA,a),in,out),
  t(coad(NA,b),in,out),
  t(coad(NA,c),in,out))
  -> dR(coad(NA,a),coad(NA,b),coad(NA,c))
     + i_ / 2 * TR * f(coad(NA,a),coad(NA,b),coad(NA,c))
// FORM: f(a,c,d)*f(b,c,d)
f(coad(NA,a),coad(NA,c),coad(NA,d))
* f(coad(NA,b),coad(NA,c),coad(NA,d))
  -> CA * g(coad(NA,a),coad(NA,b))

// FORM: f(a,b,e)*f(b,c,f)*f(c,a,g)
f(coad(NA,a),coad(NA,b),coad(NA,e))
* f(coad(NA,b),coad(NA,c),coad(NA,f))
* f(coad(NA,c),coad(NA,a),coad(NA,g))
  -> CA / 2 * f(coad(NA,e),coad(NA,f),coad(NA,g))

Four-generator trace terminal:

trace(cof(Nc),
  t(coad(NA,a),in,out),
  t(coad(NA,b),in,out),
  t(coad(NA,c),in,out),
  t(coad(NA,d),in,out))
  -> dR(coad(NA,a),coad(NA,b),coad(NA,c),coad(NA,d))
     + i_ / 2 * (
         dR(coad(NA,a),coad(NA,b),coad(NA,x))
         * f(coad(NA,c),coad(NA,d),coad(NA,x))
         + dR(coad(NA,c),coad(NA,d),coad(NA,x))
         * f(coad(NA,a),coad(NA,b),coad(NA,x)))
     - TR / 6 * f(coad(NA,a),coad(NA,c),coad(NA,x))
       * f(coad(NA,b),coad(NA,d),coad(NA,x))
     + TR / 3 * f(coad(NA,a),coad(NA,d),coad(NA,x))
       * f(coad(NA,b),coad(NA,c),coad(NA,x))

FORM color.tar.gz example families

The color package page links color.tar.gz as “some FORM programs that use color.h”; see https://www.nikhef.nl/~form/maindir/packages/color/color.html and https://www.nikhef.nl/~form/maindir/packages/color/color.tar.gz. The example programs define source-side graph families. The following schematics preserve their topology in Symbolica/spenso notation.

tloop.frm cases:

// TYPE = qloop, SIZE = n.
chain(cof(Nc,i1),dind(cof(Nc,i1)),
  t(coad(NA,j1),in,out),...,t(coad(NA,jn),in,out),
  t(coad(NA,j1),in,out),...,t(coad(NA,jn),in,out))

// For SIZE = 3, FORM color+simpli expected:
Q6 -> NA * TR * CF^2 - 3/2 * NA * TR * CA * CF + 1/2 * NA * TR * CA^2

// TYPE = gloop, SIZE = n.
f(coad(NA,k1),coad(NA,k2),coad(NA,j1)) * ...
* f(coad(NA,k(2 n)),coad(NA,k1),coad(NA,jn))

// For SIZE = 3:
G6 -> 0

// TYPE = qqloop, SIZE = n: two fundamental loops linked by adjoint labels.
trace(cof(Nc),t(j1),...,t(jn)) * trace(cof(Nc),t(j1),...,t(jn))

// For SIZE = 3:
QQ3 -> -1/4 * NA * TR^2 * CA + d33(R1,R2)

// TYPE = qgloop, SIZE = n: one fundamental loop and one adjoint loop.
trace(cof(Nc),t(j1),...,t(jn)) * adjoint_loop(j1,...,jn)

// For SIZE = 3:
QG3 -> i_ / 4 * NA * TR * CA^2

// TYPE = ggloop, SIZE = n: two linked adjoint loops.
adjoint_loop(j1,...,jn) * adjoint_loop(j1,...,jn)

// For SIZE = 3:
GG3 -> 1/4 * NA * CA^3

Fixed graph examples:

// TYPE = g14: Coxeter graph with 14 trivalent adjoint vertices.
g14 -> 1/648 * NA * CA^7
    - 8/15 * d444(A1,A2,A3) * CA
    + 16/9 * d644(A1,A2,A3)

// TYPE = fiveq: five linked quark loops.
fiveq -> 1/192 * NA * TR^5 * CA^3
      + 1/4 * d33(R1,R2) * TR^3 * CA^2
      + 5/48 * d33(R1,R2) * d33(R3,R4) * NA^-1 * TR * CA
      + 5/48 * d33(R1,R3) * d33(R2,R4) * NA^-1 * TR * CA
      + 1/8 * d33(R1,R4) * d33(R2,R3) * NA^-1 * TR * CA
      + 1/16 * d44(R1,A1) * TR^4
      + 3/8 * d433(R3,R1,R2) * TR^2 * CA
      + 1/2 * d3333(R1,R2,R3,R4) * TR * CA
      + d43333a(R5,R2,R1,R4,R3)

// TYPE = g24 is a high-cost stress example in tloop.frm.
// No compact expected value is included in the package source; it is not a short unit test.

su.frm examples using #call SUn:

// CASE = F3F3.
F3F3 -> 2*a^3*NF^-1 - 5/2*a^3*NF + 1/2*a^3*NF^3

// CASE = F4F4.
F4F4 -> -3*a^4*nf^2*NF^-2 + 4*a^4*nf^2
        - 7/6*a^4*nf^2*NF^2 + 1/6*a^4*nf^2*NF^4

// CASE = F4A4.
F4A4 -> -2*a^4*nf*NF + 5/3*a^4*nf*NF^3 + 1/3*a^4*nf*NF^5

// CASE = A4A4.
A4A4 -> -24*a^4*NF^2 + 70/3*a^4*NF^4 + 2/3*a^4*NF^6

// CASE = FnFn with n = 3.
F3F3 -> 2*a^3*nf^2*NF^-1 - 2*a^3*nf^2*NF

// CASE = FnAn with n = 3.
F3A3 -> -i_*a^3*nf*NF^2 + i_*a^3*nf*NF^4

// CASE = AnAn with n = 3.
A3A3 -> -2*a^3*NF^3 + 2*a^3*NF^5

// CASE = qloop with n = 3.
Q6 -> -a^3*nf*NF^-2 + a^3*nf*NF^2

// CASE = gloop with n = 3.
G6 -> 0

The SU checker procedure uses 𝑇𝑅=𝑎, 𝐶𝐹=𝑎𝑁𝐹21𝑁𝐹, 𝐶𝐴=2𝑎𝑁𝐹, and 𝑁𝐴=𝑁𝐹21; source SUn.prc lines 26–58.

Implementation caveats

  • FORM’s four-dimensional gamma simplifications depend on index dimension checks in Trace4Gen; applying them in dimension-generic algebra is wrong.
  • trace4 accepts gamma-five branches with special sign changes and gamma-six/gamma-seven toggles; tracen is dimension-generic and does not tolerate gamma-five variants.
  • color.h is group- and representation-invariant. It intentionally keeps symbols such as cR, cA, I2R, NA, and higher d invariants rather than reducing all cases to 𝑁𝑐.
  • The simpli procedure is a rewrite strategy over invariant environments. Its output depends on canonicalization choices and on the RANK bound.
  • Symbolica matching is syntactic. Sequence reversal, parity tests, fresh dummy generation, and antisymmetric signs require Rust-side construction or explicit pattern restrictions.
  • The approved chain and trace syntax in this document is a target specification for tensor-pattern rules, not a claim that Symbolica ships built-in functions with those names.

Appendix: source map

RuleIdentityEquation labelPrimary source
G1𝛾(𝑣)𝛼𝛽𝛾(𝑤)𝛽𝜒=(Γ𝑣𝑤)𝛼𝜒Equation 1https://github.com/form-dev/form/blob/master/sources/opera.c#L715-L745 https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/dirac/mod.rs#L604-L613
G2chain orientationEquation 3https://symbolica.io/docs/pattern_matching.html https://docs.rs/spenso/latest/spenso/
G3𝛾𝛼𝛽𝜇𝛾𝜇,𝛽𝜒=𝐷𝛿𝛼𝜒Equation 4https://github.com/form-dev/form/blob/master/sources/opera.c#L958-L972 https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/dirac/mod.rs#L784-L829
G4(Γ𝑣1𝑣𝑛)𝛼𝛼Equation 5https://github.com/form-dev/form/blob/master/sources/opera.c#L730-L745 https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/dirac/mod.rs#L877-L879
G5odd trace zero, two traceEquation 6, Equation 7https://github.com/form-dev/form/blob/master/sources/opera.c#L424-L432 https://github.com/form-dev/form/blob/master/sources/opera.c#L830-L856
G6Chisholm odd/evenEquation 9, Equation 10https://github.com/form-dev/form/blob/master/sources/opera.c#L670-L680 https://github.com/form-dev/form/blob/master/sources/opera.c#L978-L1012 https://github.com/form-dev/form/blob/master/sources/opera.c#L1118-L1157
G7gamma-five/equation epsilon trickEquation 12https://github.com/form-dev/form/blob/master/sources/opera.c#L320-L329 https://github.com/form-dev/form/blob/master/sources/opera.c#L480-L489
C1open color-line joiningEquation 13color.h lines 91–93, https://www.nikhef.nl/~form/maindir/packages/color/color.h https://www.nikhef.nl/~form/maindir/packages/color/color.html
C2trace closure and 𝑇𝑅Equation 14, Equation 16color.h lines 459–461, https://www.nikhef.nl/~form/maindir/packages/color/color.h
C3Casimir inside traceEquation 17, Equation 18color.h lines 108–111, https://www.nikhef.nl/~form/maindir/packages/color/color.h
C4fundamental FierzEquation 19https://github.com/alphal00p/gammaloop/blob/e51747446aa724c3ffac5c42c4103d090c09c6b0/crates/idenso/src/color/mod.rs#L407-L414
C5𝑓𝑓 and 𝑓𝑓𝑓Equation 20, Equation 21color.h lines 148–150 and 505–507, https://www.nikhef.nl/~form/maindir/packages/color/color.h
C6trace–𝑓 contractionEquation 22color.h lines 108–111 and 173–175, https://www.nikhef.nl/~form/maindir/packages/color/color.h
C7d33 contractionsEquation 23, Equation 24color.h lines 1287–1294 and 1316–1335, https://www.nikhef.nl/~form/maindir/packages/color/color.h
C8simpli strategy<rule-color-simpli>color.h lines 688–713, https://www.nikhef.nl/~form/maindir/packages/color/color.h
S1Rust Symbolica pattern APISymbolica + spenso sectionhttps://docs.rs/symbolica/latest/symbolica/id/index.html https://docs.rs/symbolica/latest/symbolica/id/struct.ReplaceBuilder.html
S2spenso symbolic tensor structuresSymbolica + spenso sectionhttps://docs.rs/spenso/latest/spenso/ https://docs.rs/spenso/latest/src/spenso/network/library/symbolic.rs.html
S3FORM gamma short-circuit orderFORM short-circuit sectionhttps://github.com/form-dev/form/blob/master/sources/opera.c#L424-L432 https://github.com/form-dev/form/blob/master/sources/opera.c#L958-L972 https://github.com/form-dev/form/blob/master/sources/opera.c#L1168-L1232
S4FORM color short-circuit orderFORM short-circuit sectioncolor.h lines 91–163, 459–507, 688–724, and 1258–1348, https://www.nikhef.nl/~form/maindir/packages/color/color.h
T1FORM gamma test valuesFORM-side test sectionhttps://www.nikhef.nl/~form/maindir/documentation/reference/html/manual.html#dx1-85012 https://github.com/form-dev/form/blob/master/sources/opera.c#L424-L432
T2FORM compact color test valuesFORM-side test sectioncolor.h lines 459–464 and 505–507, https://www.nikhef.nl/~form/maindir/packages/color/color.h
T3FORM color example familiesFORM-side test sectioncolor.tar.gz: tloop.frm, su.frm, SUn.prc, https://www.nikhef.nl/~form/maindir/packages/color/color.tar.gz

Source snippets appear next to each detailed rule above. Symbolica/spenso pattern references are the code blocks in the corresponding detailed rule and in the Symbolica + spenso rewrite-pattern section.

Appendix: validation

Typst compile result

The pre-migration standalone source recorded this successful environment:

typst 0.14.2 (b33de9de)

Its captured compilation command was:

typst compile form_gamma_color_rules_from_scratch.typ form_gamma_color_rules_from_scratch.pdf

That historical command succeeded and produced form_gamma_color_rules_from_scratch.pdf; the old filename is evidence, not the current source path. The maintained specification now builds through the Idenso product route and complete PDF with:

cargo run --locked -p alphal00p-docs-builder -- build --product idenso --channel latest --output /tmp/idenso-docs --skip-rustdoc

Static checks

Checks captured against the pre-migration Typst filename:

rg -n '\b\x70rod\b' form_gamma_color_rules_from_scratch.typ
rg -n 'tr_[A-Za-z]+\(|Tr_[A-Za-z]+\(|op\("tr"\)_[A-Za-z]+\(' form_gamma_color_rules_from_scratch.typ
rg -n '#L[0-9]+' form_gamma_color_rules_from_scratch.typ
rg -n 'gamma_chain|gamma_trace' form_gamma_color_rules_from_scratch.typ
rg -n 'with_map|replace_map|FORM Short-Circuit' form_gamma_color_rules_from_scratch.typ
rg -n 'FORM-Side Test Cases|Q6 ->|F3F3 ->|g14 ->|fiveq ->' form_gamma_color_rules_from_scratch.typ

Results:

  • No word token \x70rod was found; intended occurrences use product.
  • No subscripted trace operator was immediately attached to a parenthesized argument; trace calls use explicit spacing.
  • GitHub line-anchor fragments were found for the FORM opera.c, GammaLoop Dirac, and GammaLoop color source links. color.h rules cite exact package-source line numbers because no official GitHub-hosted color.h was found in form-dev/form.
  • The internal names spenso::gamma_chain and spenso::gamma_trace occur only in source-code snippets or explanatory text documenting GammaLoop internals; target patterns use chain and trace.
  • Rust-only operations that cannot be static Symbolica RHS patterns, including sequence reversal, parity checks, cyclic loop detection, and fresh-index creation, are assigned to with_map, replace_map, or explicit Rust builders.
  • The FORM-side test-case section is present and contains expected values for compact gamma tests, compact color tests, and short color.tar.gz example instantiations.

Additional FORM checks used to populate the test-case section:

form -q /tmp/gamma-test.frm
form -q /tmp/color-trace.frm
form -q /tmp/color-short.frm
cd /tmp/form-color && form -q tloop-qloop.frm
cd /tmp/form-color && form -q tloop-gloop.frm
cd /tmp/form-color && form -q tloop-qqloop.frm
cd /tmp/form-color && form -q tloop-qgloop.frm
cd /tmp/form-color && form -q tloop-ggloop.frm
cd /tmp/form-color && form -q tloop-g14.frm
cd /tmp/form-color && form -q tloop-fiveq.frm
cd /tmp/form-color && form -q su-F3F3.frm
cd /tmp/form-color && form -q su-F4F4.frm
cd /tmp/form-color && form -q su-F4A4.frm
cd /tmp/form-color && form -q su-A4A4.frm
cd /tmp/form-color && form -q su-FnFn.frm
cd /tmp/form-color && form -q su-FnAn.frm
cd /tmp/form-color && form -q su-AnAn.frm
cd /tmp/form-color && form -q su-qloop.frm
cd /tmp/form-color && form -q su-gloop.frm

Unresolved uncertainties

  • The current official FORM GitHub repository contains sources/opera.c but not the legacy color.h package file. The package page links the actual source. Therefore color rules cite exact package-source line numbers and the package source URL, but they do not have official GitHub line anchors.
  • The approved chain and trace notation is a specification-level Symbolica/spenso tensor-pattern notation. Exact Rust constructors for sequence reversal and parity-filtered Chisholm replacement must be implemented with Rust-side match processing.

References

Developer architecture · documented revision e51747446aa7