IntegralFamily

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

IntegralFamily

class IntegralFamily

An ordered set of inverse propagators sharing loop momenta and external kinematics.

Pass denominators such as k.k - m2, not their reciprocals. An integral with powers [a1, a2, ...] has integrand 1/(D1**a1 * D2**a2 * ...): zero powers omit a denominator and negative powers put it in the numerator. All power vectors and denominator labels follow the original input order.

Declare independent external momenta and their scalar products through Kinematics. is_independent checks the denominator basis for linear dependence; is_complete checks whether it spans every loop scalar product. For L loops and E independent external momenta this space has L(L+1)/2 + LE coordinates. complete() returns a new family with missing coordinates appended; give these auxiliary slots nonpositive integral powers. Use partial_fraction() before completion when denominators are dependent.

Use this class to rewrite scalar numerators, compare momentum routings, test scalelessness, and construct Symanzik polynomials. Reduction is provided by hep.IBPFamily or, for one loop, hep.oneloop.reduce. No integration prescription or loop-measure normalization is inferred by this container.

Examples

Build a massless bubble with external virtuality p.p = s. The method examples below reuse this family and its symbols.

from symbolica import S, E
from symbolica.community import hepkit as hep
D, k, p, s = S("D", "k", "p", "s")
d1, d2, x1, x2 = S("d1", "d2", "x1", "x2")
kin = hep.Kinematics(D, momenta=[k, p]).with_scalar_product(p, p, s)
denominators = [kin.scalar_product(k, k), kin.scalar_product(k-p, k-p)]
family = hep.IntegralFamily([k], [p], denominators, kinematics=kin)
assert family.rank == 2 and family.is_complete and family.is_independent
rewritten = family.rewrite_numerator(kin.scalar_product(k, p), [d1, d2])
assert (rewritten - (d1 - d2 + s)/2).expand() == E("0")
U, F = family.symanzik([x1, x2])
assert U == x1 + x2

Attributes

Name Description
denominators Ordered inverse propagators, including any auxiliary completion terms.
external_momenta Independent external momentum names in their original order.
is_complete Whether the inverse propagators span every loop scalar product.
is_independent Whether no denominator can be eliminated by an affine relation.
kinematics Scoped kinematics, including the family momentum declarations.
loop_momenta Integrated momentum names in their original order.
rank Number of independent affine forms in the loop scalar products.
scalar_products Loop-loop and loop-external products spanning the numerator space.

denominators

IntegralFamily.denominators: builtins.list[Expression]

Ordered inverse propagators, including any auxiliary completion terms.

Examples

Using the setup in the IntegralFamily class example:

assert family.denominators == denominators
weighted = list(zip(family.denominators, [1, 2]))

external_momenta

IntegralFamily.external_momenta: builtins.list[Expression]

Independent external momentum names in their original order.

Examples

Using the setup in the IntegralFamily class example:

assert family.external_momenta == [p]

is_complete

IntegralFamily.is_complete: builtins.bool

Whether the inverse propagators span every loop scalar product.

Examples

Using the setup in the IntegralFamily class example:

assert family.is_complete
assert family.rank == len(family.scalar_products)

is_independent

IntegralFamily.is_independent: builtins.bool

Whether no denominator can be eliminated by an affine relation.

Examples

Using the setup in the IntegralFamily class example:

assert family.is_independent
assert family.rank == len(family.denominators)

kinematics

IntegralFamily.kinematics: Kinematics

Scoped kinematics, including the family momentum declarations.

Examples

Using the setup in the IntegralFamily class example:

assert family.kinematics.scalar_product(p, p) == s

loop_momenta

IntegralFamily.loop_momenta: builtins.list[Expression]

Integrated momentum names in their original order.

Examples

Using the setup in the IntegralFamily class example:

assert family.loop_momenta == [k]

rank

IntegralFamily.rank: builtins.int

Number of independent affine forms in the loop scalar products.

Examples

Using the setup in the IntegralFamily class example:

assert family.rank == 2

scalar_products

IntegralFamily.scalar_products: builtins.list[Expression]

Loop-loop and loop-external products spanning the numerator space.

Examples

Using the setup in the IntegralFamily class example:

assert len(family.scalar_products) == 2

Methods

Name Description
__new__ Compute the independent loop scalar products and denominator rank.
__repr__ Return a compact summary of the family and its scalar-product rank.
_repr_html_ Display ordered inverse propagators and family metadata in a notebook
_repr_pretty_ Write the summary and ordered denominators using Symbolica’s text printer.
complete Complete a basis, preferring supplied inverse propagators
find_mapping Find a verified affine loop-momentum shift into the target family
find_mappings Group families and return verified maps to their representatives
from_diagram Build a complete family from the diagram’s routed internal propagators
mapping_to Verify explicit source-loop images in another family’s coordinates
parametric_mapping Find a parameter permutation identifying both Symanzik polynomials
partial_fraction Partial-fraction dependent propagators while preserving family order
rewrite_numerator Rewrite a numerator in inverse-propagator variables and expand it.
scalar_product_rules Solve loop scalar products in terms of inverse-propagator labels.
scaleless_scaling Find parameter weights proving a sector scaleless in dimensional regularization
scaleless_transverse_direction Find an unconstrained transverse loop direction proving scalelessness
sector Select the positive-power propagators of an integral’s sector
symanzik Compute the Symanzik polynomials U and F in propagator order

__new__

IntegralFamily.__new__(
    loop_momenta: typing.Sequence[Expression],
    external_momenta: typing.Sequence[Expression],
    denominators: typing.Sequence[Expression],
    *,
    kinematics: typing.Optional[Kinematics] = None,
) -> IntegralFamily

Compute the independent loop scalar products and denominator rank.

Examples

from symbolica import S, E
from symbolica.community import hepkit as hep
D, k, p, s = S("D", "k", "p", "s")
d1, d2, x1, x2 = S("d1", "d2", "x1", "x2")
kin = hep.Kinematics(D, momenta=[k, p]).with_scalar_product(p, p, s)
denominators = [kin.scalar_product(k, k), kin.scalar_product(k-p, k-p)]
family = hep.IntegralFamily([k], [p], denominators, kinematics=kin)
assert family.rank == 2

Parameters

  • loop_momenta (list[Expression]) Distinct unindexed integrated momentum names.
  • external_momenta (list[Expression]) Independent unindexed external momentum names.
  • denominators (list[Expression]) Ordered inverse propagators, not their reciprocals.
  • kinematics (Kinematics | None) External assumptions and dimension; defaults to unconstrained 4D.

__repr__

IntegralFamily.__repr__() -> builtins.str

Return a compact summary of the family and its scalar-product rank.

Examples

Using the setup in the IntegralFamily class example:

print(family)

_repr_html_

IntegralFamily._repr_html_() -> builtins.str

Display ordered inverse propagators and family metadata in a notebook.

Expressions use Symbolica’s native HTML printer.

Examples

Using the setup in the IntegralFamily class example:

from IPython.display import display
display(family)

_repr_pretty_

IntegralFamily._repr_pretty_(pretty: typing.Any, cycle: builtins.bool) -> None

Write the summary and ordered denominators using Symbolica’s text printer.

Examples

Using the setup in the IntegralFamily class example:

from IPython.lib.pretty import pretty
text = pretty(family)

Parameters

  • pretty (object) IPython’s pretty printer, providing a text method.
  • cycle (bool) Whether this family is part of a recursive formatting cycle.

complete

IntegralFamily.complete(
    *,
    candidates: typing.Optional[typing.Sequence[Expression]] = None,
) -> IntegralFamily

Complete a basis, preferring supplied inverse propagators.

Original propagators retain their positions. Dependent families must first be partial-fractioned. Added propagators carry nonpositive powers when used to represent numerator factors in an IBP integral list. Candidates are tried in order after applying this family’s kinematics. Redundant candidates are skipped; bare scalar products fill any missing directions. All candidates must be affine in the loop scalar products.

Examples

Using the bubble setup in IntegralFamily:

incomplete = hep.IntegralFamily([k], [p], denominators[:1], kinematics=kin)
completed = incomplete.complete()
assert not incomplete.is_complete and completed.is_complete
assert completed.denominators[0] == denominators[0]
powers = [1, 0]  # the appended slot is absent from the original integral

Parameters

  • candidates (list[Expression] | None) Preferred auxiliary inverse propagators in this family’s momentum coordinates. Defaults to using only bare scalar products.

find_mapping

IntegralFamily.find_mapping(
    target: IntegralFamily,
    *,
    max_candidates: builtins.int = 100000,
) -> typing.Optional[IntegralMapping]

Find a verified affine loop-momentum shift into the target family.

Search derives candidates from independent quadratic propagators, then checks every propagator, including eikonal and auxiliary entries. It includes loop mixtures, reversals and external shifts. It does not test parametric identities that have no affine loop-momentum map.

Examples

Using the bubble setup in IntegralFamily:

target = hep.IntegralFamily([k], [p], list(reversed(denominators)), kinematics=kin)
mapping = family.find_mapping(target)
assert mapping is not None
transformed = mapping.apply(kin.scalar_product(k, p))

Parameters

  • target (IntegralFamily) Target family with the same external kinematics and loop count.
  • max_candidates (int) Candidate budget; exhaustion raises IntegralFamilyError.

Returns

  • IntegralMapping | None Verified mapping, or None if no supported candidate matches.

find_mappings

IntegralFamily.find_mappings(
    families: typing.Sequence[IntegralFamily],
    *,
    max_candidates: builtins.int = 100000,
) -> builtins.list[tuple[builtins.int, IntegralMapping]]

Group families and return verified maps to their representatives.

Returns one (target_index, mapping) per input family in input order. Indices refer to the original list. Representatives map to themselves; every other mapping goes directly to a retained representative. The first compatible representative wins. Symbolica canonizes each Symanzik pair once, then native affine-shift search verifies all merges. A parametric equivalence without a verified loop map remains separate.

Families need compatible external kinematics and nonsingular quadratic forms. Unsupported shift searches and exhausted budgets raise errors. Different propagator counts stay separate. Select sectors and remove certified scaleless integrals before grouping; complete bases afterwards. This does not exchange external momenta or infer integration prescriptions.

Examples

Using the bubble setup in IntegralFamily:

families = [family, family]
mappings = hep.IntegralFamily.find_mappings(families)
assert [target for target, mapping in mappings] == [0, 0]

Parameters

  • families (list[IntegralFamily]) Ordered families; earlier entries are preferred as representatives.
  • max_candidates (int) Affine-shift candidate budget per pair; exhaustion raises an error.

Returns

  • list[tuple[int, IntegralMapping]] Target index and verified map for each input, including representatives.

from_diagram

IntegralFamily.from_diagram(
    diagram: FeynmanDiagram,
    independent_dot_products: typing.Optional[typing.Sequence[Expression]] = None,
    *,
    kinematics: typing.Optional[Kinematics] = None,
) -> IntegralFamily

Build a complete family from the diagram’s routed internal propagators.

Graph propagators retain their edge order and model masses. Preferred independent dot products are appended in order when they increase the rank; automatic scalar products fill any remaining directions. Auxiliary denominators have nonpositive powers when representing the original integral. Tree diagrams and dependent graph propagators raise DiagramError. Use diagram.propagator_family() to extract dependent propagators for partial fractioning before completing the resulting families.

Examples

from symbolica import S, E
from symbolica.community import hepkit as hep
model = hep.Model.phi4()
process = model.process(["phi", "phi"], ["phi", "phi"])
result = process.generate_diagrams(loops=1)
diagram = result.diagrams[0]
family = hep.IntegralFamily.from_diagram(diagram)
assert family.is_complete

Parameters

  • diagram (FeynmanDiagram) A complete diagram with its chosen loop-momentum routing.
  • independent_dot_products (list[Expression] or None, optional) Preferred auxiliary inverse propagators in the routed momenta. None selects a suitable basis automatically.
  • kinematics (Kinematics or None, optional) External assumptions and dimension; defaults to the diagram’s symbolic dimension with no on-shell assumptions.

mapping_to

IntegralFamily.mapping_to(
    target: IntegralFamily,
    loop_images: typing.Sequence[Expression],
) -> typing.Optional[IntegralMapping]

Verify explicit source-loop images in another family’s coordinates.

Real affine images must have loop determinant +1 or -1 and map every source propagator to a distinct equal target propagator. External names, dimensions and scalar-product assumptions must agree. Additional target propagators are allowed for subtopology embeddings.

Examples

Using the bubble setup in IntegralFamily:

mapping = family.mapping_to(family, [k])
assert mapping.map_powers([1, 2]) == [1, 2]

Parameters

  • target (IntegralFamily) Family in whose coordinates the images are expressed.
  • loop_images (list[Expression]) One image per source loop momentum, in source order.

Returns

  • IntegralMapping | None Verified mapping, or None when the images fail the equivalence checks.

parametric_mapping

IntegralFamily.parametric_mapping(
    target: IntegralFamily,
    parameters: typing.Sequence[Expression],
) -> typing.Optional[PropagatorMapping]

Find a parameter permutation identifying both Symanzik polynomials.

Symbolica canonizes polynomial incidence graphs, preserving coefficients, powers and the distinction between U and F. This can identify families without a loop shift at fixed external momenta. The result supplies no momentum or tensor-numerator substitution and does not check contours or propagator prescriptions. Both families must have equal denominator counts and the same external kinematics. Singular quadratic forms are rejected because their U/F polynomials can discard physical parameters.

Examples

Using the bubble setup in IntegralFamily:

target = hep.IntegralFamily([k], [p], list(reversed(denominators)), kinematics=kin)
mapping = family.parametric_mapping(target, [x1, x2])
assert mapping is not None
mapped_powers = mapping.map_powers([1, 2])

Parameters

  • target (IntegralFamily) Family whose U and F polynomials are compared.
  • parameters (list[Expression]) One distinct new symbol or labeled call per source denominator.

Returns

  • PropagatorMapping | None Formal parameter permutation, or None if the polynomials differ.

partial_fraction

IntegralFamily.partial_fraction(
    powers: typing.Sequence[builtins.int],
    *,
    max_states: builtins.int = 100000,
) -> builtins.list[tuple[Expression, builtins.list[builtins.int]]]

Partial-fraction dependent propagators while preserving family order.

Both affine mass shifts and homogeneous dependencies are supported. The identity is algebraic: no momentum shifts or scaleless-term removal are applied. Impose exceptional kinematics before building the family; generic external invariants may appear in the returned coefficients.

Examples

Using the symbols and kinematics in IntegralFamily:

m2 = S("m2")
dependent = hep.IntegralFamily([k], [], [kin.scalar_product(k, k),
    kin.scalar_product(k, k) - m2], kinematics=kin)
terms = dependent.partial_fraction([1, 1])
assert all(sum(power > 0 for power in powers) == 1 for coefficient, powers in terms)

Parameters

  • powers (list[int]) Signed powers in family order; negative powers are numerator factors.
  • max_states (int) Maximum number of intermediate exponent vectors; defaults to 100000.

Returns

  • list[tuple[Expression, list[int]]] Coefficients and powers whose positive-power denominators are independent.

rewrite_numerator

IntegralFamily.rewrite_numerator(
    numerator: Expression,
    labels: typing.Sequence[Expression],
) -> Expression

Rewrite a numerator in inverse-propagator variables and expand it.

Examples

Using the setup in the IntegralFamily class example:

numerator = kin.scalar_product(k, p)**2
reduced = family.rewrite_numerator(numerator, [d1, d2])

Parameters

  • numerator (Expression) Scalar numerator after tensor reduction and momentum routing.
  • labels (list[Expression]) One distinct symbol or labeled call per denominator, in family order.

scalar_product_rules

IntegralFamily.scalar_product_rules(labels: typing.Sequence[Expression]) -> builtins.list[tuple[Expression, Expression]]

Solve loop scalar products in terms of inverse-propagator labels.

Examples

Using the setup in the IntegralFamily class example:

rules = family.scalar_product_rules([d1, d2])
assert len(rules) == 2

Parameters

  • labels (list[Expression]) One distinct symbol or labeled call per denominator, in family order.

Returns

  • list[tuple[Expression, Expression]] Simultaneous replacement pairs for an independent, complete family.

scaleless_scaling

IntegralFamily.scaleless_scaling(parameters: typing.Sequence[Expression]) -> typing.Optional[builtins.list[Expression]]

Find parameter weights proving a sector scaleless in dimensional regularization.

For G=U+F, the returned weights satisfy sum(w_ix_idG/dx_i)=G. None means this criterion did not detect scalelessness, not that the integral is nonzero. Every denominator is treated as present; use sector(powers) first to select positive-power entries. Singular quadratic loop forms raise IntegralFamilyError: their algebraic U/F polynomials do not establish this parametric scaling certificate.

Examples

Using the bubble setup in IntegralFamily:

tadpole = family.sector([1, 0])
weights = tadpole.scaleless_scaling([x1])
assert weights is not None  # massless tadpole vanishes in dimensional regularization

Parameters

  • parameters (list[Expression]) One distinct new symbol or labeled call per sector denominator.

Returns

  • list[Expression] | None Exact scaling weights in parameter order, or no certificate.

scaleless_transverse_direction

IntegralFamily.scaleless_transverse_direction() -> typing.Optional[builtins.list[Expression]]

Find an unconstrained transverse loop direction proving scalelessness.

Returns a nonzero real list w in loop order such that each inverse propagator is invariant under k_i -> k_i + w_i*r_perp for any vector orthogonal to the external span. The corresponding unrestricted transverse integral vanishes in dimensional regularization, including polynomial numerators. Apply sector(powers) first to exclude numerator-only entries.

Requires a nonsingular external Gram matrix. Symbolic dimension is interpreted generically; a concrete dimension must exceed the external basis size. None means no certificate was found. A vanishing Symanzik U alone is not sufficient, and complex loop directions are not accepted.

Examples

Using the bubble setup in IntegralFamily:

empty_sector = family.sector([0, 0])
direction = empty_sector.scaleless_transverse_direction()
assert direction is not None  # no denominators constrain the loop momentum

Returns

  • list[Expression] | None Verified real loop direction, or no certificate.

sector

IntegralFamily.sector(powers: typing.Sequence[builtins.int]) -> IntegralFamily

Select the positive-power propagators of an integral’s sector.

Zero and negative powers are omitted. Loop variables and external kinematics are retained. This selects sector support; it does not remove numerator factors algebraically from the original integrand.

Examples

Using the bubble setup in IntegralFamily:

sector = family.sector([1, 0])
assert sector.denominators == denominators[:1]

Parameters

  • powers (list[int]) One signed propagator power per family denominator.

symanzik

IntegralFamily.symanzik(parameters: typing.Sequence[Expression]) -> tuple[Expression, Expression]

Compute the Symanzik polynomials U and F in propagator order.

Uses Minkowski inverse propagators: k2-m2 gives U=x and F=m2*x2. For a weighted denominator k.M.k + 2 k.Q + J, this returns U=det(M) and F=Q.adj(M).Q-U*J, using Symbolica determinants and cofactors. Singular quadratic forms are accepted as algebraic polynomial data; they do not establish a Gaussian integration formula or scalelessness. This prepares polynomials without performing integration.

Examples

Using the setup in the IntegralFamily class example:

U, F = family.symanzik([x1, x2])
assert U == x1 + x2  # two standard one-loop propagators

Parameters

  • parameters (list[Expression]) One distinct new symbol or labeled call per inverse propagator.

Returns

  • tuple[Expression, Expression] First and second Symanzik polynomials, respectively.