IBPFamily

Symbolica documentation for getting started, symbolic expressions, numerical evaluation, pattern matching, and APIs in Python and Rust.

IBPFamily

class IBPFamily

Find exact integration-by-parts (IBP) relations for a complete integral family.

Wrap a hep.IntegralFamily after checking is_complete and is_independent. The denominator order, signs, masses, dimension and external scalar products are preserved. Supply a symbolic dimension through Kinematics. Missing scalar-product coordinates must be added explicitly with family.complete(); auxiliary denominators normally have nonpositive powers.

Choose solve_parametric for a reusable symbolic recurrence in a sector, or reduce_laporta for a finite set of integer-power targets. Inspect the returned rules and residual integrals before using a reduction. Searches are bounded: they do not certify a complete master-integral basis.

Searches accept 1–12 denominators and integer powers from -64 through 63. Applying a discovered rule accepts signed 64-bit powers. Booleans are not powers.

Examples

from symbolica import S, E
from symbolica.community import hepkit as hep
d, k, m2 = S("d", "k", "m2")
kin = hep.Kinematics(d, momenta=[k])
family = hep.IntegralFamily([k], [], [kin.scalar_product(k, k) - m2], kinematics=kin)
ibp = hep.IBPFamily(family, name="T")
solution = ibp.solve_parametric([True])
terms = solution.reduce([2])
assert terms[0][0] == [1]
assert (terms[0][1] - (d-2)/(2*m2)).together() == E("0")

Parameters

  • family (IntegralFamily) Complete, independent denominator basis with symbolic dimension.
  • name (str, optional) Family label used in diagnostic output; default “F”.

Attributes

Name Description
denominator_count Number of entries required in every sector, target and fixed-power vector.
index_symbols Formal integral-index symbols, one per denominator in family order

denominator_count

IBPFamily.denominator_count: int

Number of entries required in every sector, target and fixed-power vector.

Examples

Using the setup in the IBPFamily class example:

assert ibp.denominator_count == len(family.denominators)

index_symbols

IBPFamily.index_symbols: list[Expression]

Formal integral-index symbols, one per denominator in family order.

These symbols occur in ibp_identities and parametric rules. Use the returned symbols for substitutions: freshly creating a symbol named n1 does not identify this family’s privately scoped index.

Examples

Using the setup in the IBPFamily class example:

n = ibp.index_symbols[0]
assert len(ibp.index_symbols) == ibp.denominator_count

Methods

Name Description
__init__ Prepare a complete denominator basis for exact IBP searches
__repr__ Summarize this IBPFamily for interactive inspection.
ibp_identities Generate the L*(L+E) ordinary IBP equations with symbolic indices
reduce_laporta Reduce requested integer-power integrals by exact finite-target elimination
solve_parametric Search for symbolic recurrences within one positive/nonpositive power sector

__init__

IBPFamily.__init__(family: IntegralFamily, *, name: str = 'F') -> None

Prepare a complete denominator basis for exact IBP searches.

Raises ValueError for an incomplete/dependent basis, unsupported kinematics, or too many denominators. Complete missing coordinates before constructing this object; dependent propagators require partial fractions.

Examples

from symbolica import S, E
from symbolica.community import hepkit as hep
d, k, m2 = S("d", "k", "m2")
kin = hep.Kinematics(d, momenta=[k])
family = hep.IntegralFamily([k], [], [kin.scalar_product(k, k) - m2], kinematics=kin)
ibp = hep.IBPFamily(family, name="T")
assert ibp.denominator_count == 1

Parameters

  • family (IntegralFamily) Complete, independent family; its denominator order is retained.
  • name (str, optional) Diagnostic family label; default “F”.

__repr__

IBPFamily.__repr__() -> str

Summarize this IBPFamily for interactive inspection.

Examples

Using the setup in the IBPFamily class example:

summary = repr(ibp)

ibp_identities

IBPFamily.ibp_identities() -> list[list[tuple[list[Expression], Expression]]]

Generate the L*(L+E) ordinary IBP equations with symbolic indices.

Each row is a list of (powers, coefficient) pairs representing sum(coefficient * I(*powers)) = 0. Powers contain index symbols and integer shifts, not just shifts. Coefficients retain the family’s kinematics. This method generates equations without solving them.

Examples

Using the setup in the IBPFamily class example:

I = S("I")
equations = [sum((coefficient * I(*powers) for powers, coefficient in row), E("0"))
             for row in ibp.ibp_identities()]
assert len(equations) == 1  # one loop, no external momenta

reduce_laporta

IBPFamily.reduce_laporta(
    targets: list[list[int]],
    *,
    max_depth: int = 2,
    include_lorentz: bool = False,
    max_targets: int = 1024,
) -> IBPSolution

Reduce requested integer-power integrals by exact finite-target elimination.

The solver searches seed neighborhoods and back-substitutes solved targets. solution.residuals lists the basis left at this search depth, which is not a certified set of independent master integrals. Increase max_depth when more relations are needed. Exceeding max_targets raises ValueError rather than silently truncating the search.

Examples

Using the setup in the IBPFamily class example:

solution = ibp.reduce_laporta([[3]], max_depth=1)
terms = solution.reduce([3])
assert terms[0][0] == [1]  # solved intermediate powers are back-substituted

Parameters

  • targets (list[list[int]]) Power vectors, one integer in -64..63 per denominator.
  • max_depth (int, optional) Nonnegative signed L1 seed radius; default 2.
  • include_lorentz (bool, optional) Add Lorentz-invariance identities; default False.
  • max_targets (int, optional) Limit on distinct integrals searched, including discovered targets; default 1024.

solve_parametric

IBPFamily.solve_parametric(
    sector: list[bool],
    *,
    fixed: list[int | None] | None = None,
    max_depth: int = 2,
    include_lorentz: bool = False,
) -> IBPSolution

Search for symbolic recurrences within one positive/nonpositive power sector.

True means a strictly positive denominator power; False means zero or negative. The sector and optional fixed vector must each have one entry per denominator. None leaves an index symbolic; an integer fixes its absolute power and must agree with the sector.

Returns an IBPSolution whose rules carry explicit nonzero conditions and exceptional branches. reduce performs one recurrence step per call. Increasing max_depth searches more seeds but does not guarantee closure.

Examples

Using the setup in the IBPFamily class example:

solution = ibp.solve_parametric([True], fixed=[None], max_depth=1)
assert solution.rules
lowered = solution.reduce([3])
assert lowered[0][0] == [2]  # one recurrence step

Parameters

  • sector (list[bool]) Positive/nonpositive support, in denominator order.
  • fixed (list[int | None] or None, optional) Fixed absolute powers in -64..63; default all symbolic.
  • max_depth (int, optional) Nonnegative seed-search depth; default 2.
  • include_lorentz (bool, optional) Add Lorentz-invariance identities; default False.