FeynmanDiagram

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

FeynmanDiagram

class FeynmanDiagram

A generated or imported Feynman diagram, with particles, momenta and Feynman rules.

Obtain diagrams from Model.process(...).generate_diagrams().diagrams; use from_json or from_dot to restore a saved diagram with its model. There is no direct Python constructor. internal_edges are propagators, whereas external_edges carry the scattering or decay states.

Use numerator_expression() for symbolic algebra, integral_family() for loop-integral preparation, and render() for an SVG. Graph selections from subgraph and filter retain the original routing and identities. Routing changes return new diagrams. A diagram alone does not perform loop integration or supply a cross section.

Examples

Generate a one-loop scalar scattering diagram, inspect its propagators, and prepare its integral family. In a notebook, displaying diagram renders the graph. The methods below reuse this setup.

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]
diagram.validate()
assert diagram.loop_count == 1
propagators = [(edge.id, edge.particle_name) for edge in diagram.internal_edges]
numerator = diagram.numerator_expression()
family = diagram.integral_family()
assert family.is_complete

Attributes

Name Description
cuts Return physical final-state cuts selected during generation.
edges Return every particle line, including dangling and sewn external carriers.
external_edges Return incoming or outgoing external-state momentum carriers.
half_edges Return native Linnet half-edge views; data records their native diagram IDs.
id Return the stable content-derived hexadecimal diagram ID.
internal_edges Return propagators excluding external momentum carriers and dummy edges.
linnet_selection Return the canonical Linnet selection representing this physics region.
loop_count Return the number of independent loops in the diagram topology.
loop_momentum_basis Return the loop-momentum routing selected during generation.
name Return the deterministic name assigned during diagram generation.
numerator Return the diagram numerator annotation as source text.
overall_factor Return the diagram-wide multiplicative factor as Symbolica source text
symmetry_factor Return the positive integer denominator of the graph symmetry factor.
topology_threshold_candidates Return topology threshold candidates separately from physical cuts.
vertices Return the diagram’s interaction vertices with stable integer identifiers.

cuts

FeynmanDiagram.cuts: builtins.list[DiagramCut]

Return physical final-state cuts selected during generation.

Examples

Using the setup in the FeynmanDiagram class example:

physical_cuts = [cut.edges for cut in diagram.cuts]
assert physical_cuts == []  # ordinary amplitude, not a sewn cross section

edges

FeynmanDiagram.edges: builtins.list[DiagramEdge]

Return every particle line, including dangling and sewn external carriers.

Examples

Using the setup in the FeynmanDiagram class example:

particles_by_edge = {edge.id: edge.particle_name for edge in diagram.edges}

external_edges

FeynmanDiagram.external_edges: builtins.list[DiagramEdge]

Return incoming or outgoing external-state momentum carriers.

Examples

Using the setup in the FeynmanDiagram class example:

external_particles = [edge.particle_name for edge in diagram.external_edges]

half_edges

FeynmanDiagram.half_edges: list[linnet.HalfEdge]

Return native Linnet half-edge views; data records their native diagram IDs.

Examples

Using the setup in the FeynmanDiagram class example:

half_edge_payloads = [half_edge.data for half_edge in diagram.half_edges]

id

FeynmanDiagram.id: builtins.str

Return the stable content-derived hexadecimal diagram ID.

Examples

Using the setup in the FeynmanDiagram class example:

selected = process.generate_diagrams(loops=1, select_diagrams=[diagram.id])
assert len(selected.diagrams) == 1

internal_edges

FeynmanDiagram.internal_edges: builtins.list[DiagramEdge]

Return propagators excluding external momentum carriers and dummy edges.

Examples

Using the setup in the FeynmanDiagram class example:

propagators = [(edge.id, edge.particle_name) for edge in diagram.internal_edges]
assert len(propagators) == 2

linnet_selection

FeynmanDiagram.linnet_selection: linnet.Subgraph

Return the canonical Linnet selection representing this physics region.

Examples

Using the setup in the FeynmanDiagram class example:

region = diagram.subgraph(diagram.linnet_selection)
assert region.n_half_edges == len(diagram.half_edges)

loop_count

FeynmanDiagram.loop_count: builtins.int

Return the number of independent loops in the diagram topology.

Examples

Using the setup in the FeynmanDiagram class example:

basis = diagram.loop_momentum_bases(limit=1)[0]
len(basis.loop_edges) == diagram.loop_count
True

loop_momentum_basis

FeynmanDiagram.loop_momentum_basis: LoopMomentumBasis

Return the loop-momentum routing selected during generation.

Examples

Using the setup in the FeynmanDiagram class example:

basis = diagram.loop_momentum_basis
assert len(basis.loop_edges) == diagram.loop_count

name

FeynmanDiagram.name: builtins.str

Return the deterministic name assigned during diagram generation.

Examples

Using the setup in the FeynmanDiagram class example:

by_name = {item.name: item for item in result.diagrams}

numerator

FeynmanDiagram.numerator: builtins.str

Return the diagram numerator annotation as source text.

Examples

Using the setup in the FeynmanDiagram class example:

source_text = diagram.numerator
numerator = diagram.numerator_expression()

overall_factor

FeynmanDiagram.overall_factor: builtins.str

Return the diagram-wide multiplicative factor as Symbolica source text.

This string form is useful for serialization. For algebra or notebook display, prefer overall_factor_expression() so Symbolica’s native rich formatting is preserved.

Examples

Using the setup in the FeynmanDiagram class example:

source = diagram.overall_factor
factor = diagram.overall_factor_expression()
factor  # rich Symbolica output in a notebook

symmetry_factor

FeynmanDiagram.symmetry_factor: builtins.int

Return the positive integer denominator of the graph symmetry factor.

Examples

Using the setup in the FeynmanDiagram class example:

graph_weight = 1 / diagram.symmetry_factor

topology_threshold_candidates

FeynmanDiagram.topology_threshold_candidates: builtins.list[DiagramThresholdCandidate]

Return topology threshold candidates separately from physical cuts.

Examples

Using the setup in the FeynmanDiagram class example:

partitions = [candidate.edges for candidate in diagram.topology_threshold_candidates]

vertices

FeynmanDiagram.vertices: builtins.list[DiagramVertex]

Return the diagram’s interaction vertices with stable integer identifiers.

Examples

Using the setup in the FeynmanDiagram class example:

interactions = [model.vertex_rule(vertex.interaction) for vertex in diagram.vertices]

Methods

Name Description
__repr__ Return a concise description of the diagram and its loop count.
_repr_html_ Render the diagram as HTML in Marimo, Jupyter, and IPython.
_repr_pretty_ Write a concise summary to an IPython pretty printer.
_repr_svg_ Return the raw SVG representation used by rich notebook frontends.
all_bonds Enumerate minimal cutsets, independently of physical final-state cuts.
all_cuts Enumerate separating partitions between disjoint interaction vertex groups.
all_spanning_forests Enumerate spanning forests within the selected topology.
boundary Return boundaries around the selected interaction region
breadth_first_traverse Traverse a selected interaction region in breadth-first order.
bridges Return lines whose removal disconnects the selection.
build_cff Build the diagram’s Cross-Free Family representation
compatible_momentum_basis Reuse a parent basis’s loop coordinates wherever the selected topology permits it.
connected_components Return connected interaction regions as reusable selections.
contracted_momentum_basis Route the selected region after contracting complete internal edges.
cycle_basis Return a cycle basis and its covered half-edges.
denominator_expression Return the product of internal propagator denominators as a scalar TensorExpression
depth_first_traverse Traverse a selected interaction region in depth-first order.
filter Select by predicates on Linnet views; their data is a physics object.
from_dot Parse a Feynman diagram from Graphviz DOT text.
from_json Deserialize a Feynman diagram from its JSON representation.
integral_family Build a complete integral family with preferred or automatic ISPs
is_connected Test connectivity of the current diagram or selected region.
loop_momentum_bases Enumerate valid loop-momentum bases for this diagram.
momentum_basis Construct the canonical routing of the selected interaction region.
numerator_expression Return the diagram numerator as a Spenso TensorExpression.
numerator_prefactor_expression Return the request-wide numerator multiplier as a Symbolica expression.
overall_factor_expression Return the diagram-wide multiplicative factor as a Symbolica expression
projector_expression Return the external-state projector as a Symbolica expression.
propagator_family Extract the physical propagators using the diagram’s stored momentum routing
reduce_tensor_graphs Split the tensor numerator into scalar contributions on this topology
reduce_tensor_numerator Reduce the finalized numerator and projector with a tensor reducer
render Render an interactive, transparent SVG using the shared physics renderer
subgraph Select graph elements using canonical Linnet IDs, or import a graph-bound selection
superficial_degree_of_divergence Return the local superficial UV degree of divergence
tensor_reduce Reduce the numerator and projector using the diagram’s internal edge momenta
to_dot Serialize the diagram topology and annotations to Graphviz DOT text.
to_html Render an HTML figure with the same options and hover information as render.
to_json Serialize the complete diagram to JSON text.
to_linnest Export a self-contained Typst document embedding the rendered SVG
to_linnet Return the canonical installed Linnet graph with physics objects as payloads
uv_counterterm Return the additive local UV counterterm, the negative of uv_expansion
uv_expansion Expand the local integrand through its UV degree of divergence
validate Validate particle and interaction references against a physics model.
with_loop_momentum_edges Return a diagram using the specified loop-edge coordinates, in the supplied order.
with_loop_momentum_tree_edges Return a diagram whose momentum routing uses the specified spanning forest.

__repr__

FeynmanDiagram.__repr__() -> builtins.str

Return a concise description of the diagram and its loop count.

Examples

Using the setup in the FeynmanDiagram class example:

print(diagram)

_repr_html_

FeynmanDiagram._repr_html_() -> builtins.str

Render the diagram as HTML in Marimo, Jupyter, and IPython.

Examples

Using the setup in the FeynmanDiagram class example:

from IPython.display import display
display(diagram)

_repr_pretty_

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

Write a concise summary to an IPython pretty printer.

Examples

Using the setup in the FeynmanDiagram class example:

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

Parameters

  • pretty (Any) The IPython pretty-printer object.
  • cycle (bool) Whether this object is part of a recursive formatting cycle.

_repr_svg_

FeynmanDiagram._repr_svg_() -> builtins.str

Return the raw SVG representation used by rich notebook frontends.

Examples

Using the setup in the FeynmanDiagram class example:

from IPython.display import display
display(diagram)

all_bonds

FeynmanDiagram.all_bonds(
    *,
    min_size: typing.Optional[builtins.int] = None,
    max_size: typing.Optional[builtins.int] = None,
) -> builtins.list[Subgraph]

Enumerate minimal cutsets, independently of physical final-state cuts.

Examples

Using the setup in the FeynmanDiagram class example:

bonds = diagram.all_bonds(min_size=2, max_size=3)

Parameters

  • min_size (int or None, optional) Minimum number of crossing edges.
  • max_size (int or None, optional) Maximum number of crossing edges.

all_cuts

FeynmanDiagram.all_cuts(
    source: typing.Sequence[builtins.int],
    target: typing.Sequence[builtins.int],
) -> list[linnet.CutPartition]

Enumerate separating partitions between disjoint interaction vertex groups.

Examples

Using the setup in the FeynmanDiagram class example:

partitions = diagram.all_cuts([0], [1])

Parameters

  • source (list[int]) Canonical Linnet vertices required on the first side.
  • target (list[int]) Canonical Linnet vertices required on the opposite side.

all_spanning_forests

FeynmanDiagram.all_spanning_forests() -> builtins.list[Subgraph]

Enumerate spanning forests within the selected topology.

Examples

Using the setup in the FeynmanDiagram class example:

forests = diagram.all_spanning_forests()

boundary

FeynmanDiagram.boundary() -> Subgraph

Return boundaries around the selected interaction region.

The current region determines which interaction boundaries are returned.

Examples

Using the setup in the FeynmanDiagram class example:

region = diagram.subgraph(nodes=[0])
boundary = region.boundary()

breadth_first_traverse

FeynmanDiagram.breadth_first_traverse(
    root: builtins.int,
    *,
    include: typing.Optional[builtins.int] = None,
) -> linnet.TraversalTree

Traverse a selected interaction region in breadth-first order.

Examples

Using the setup in the FeynmanDiagram class example:

tree = diagram.breadth_first_traverse(0)

Parameters

  • root (int) Canonical Linnet vertex ID at which traversal starts.
  • include (int or None, optional) Canonical Linnet half-edge ID to prioritize at the root.

bridges

FeynmanDiagram.bridges() -> Subgraph

Return lines whose removal disconnects the selection.

Examples

Using the setup in the FeynmanDiagram class example:

bridges = diagram.bridges()

build_cff

FeynmanDiagram.build_cff(
    *,
    max_orientations: typing.Optional[builtins.int] = None,
    fixed_orientations: typing.Optional[typing.Mapping[builtins.int, builtins.bool]] = None,
    contracted_edges: typing.Optional[typing.Sequence[builtins.int]] = None,
    initial_state_edges: typing.Optional[typing.Sequence[builtins.int]] = None,
) -> CffResult

Build the diagram’s Cross-Free Family representation.

Edge constraints use the stable integer IDs exposed by diagram.edges. False fixes an edge in its stored direction and True reverses it.

Examples

Using the setup in the FeynmanDiagram class example:

Construct and display the causal denominators of a one-loop diagram:

cff = diagram.build_cff(max_orientations=10_000)
cff.to_expression()  # native Symbolica display in a notebook

Parameters

  • max_orientations (int or None, optional) Maximum number of candidate orientations to inspect.
  • fixed_orientations (mapping[int, bool] or None, optional) Edge IDs mapped to stored (false) or reversed (true) directions.
  • contracted_edges (iterable[int], optional) Edge IDs to contract before constructing denominator surfaces.
  • initial_state_edges (iterable[int], optional) Edge IDs to classify as incoming external lines.

compatible_momentum_basis

FeynmanDiagram.compatible_momentum_basis(parent: LoopMomentumBasis) -> LoopMomentumBasis

Reuse a parent basis’s loop coordinates wherever the selected topology permits it.

Examples

Using the setup in the FeynmanDiagram class example:

basis = diagram.compatible_momentum_basis(diagram.loop_momentum_basis)

Parameters

  • parent (LoopMomentumBasis) Parent coordinates belonging to this same diagram instance.

connected_components

FeynmanDiagram.connected_components() -> builtins.list[Subgraph]

Return connected interaction regions as reusable selections.

Examples

Using the setup in the FeynmanDiagram class example:

components = diagram.connected_components()

contracted_momentum_basis

FeynmanDiagram.contracted_momentum_basis(contracted: Subgraph | linnet.Subgraph) -> LoopMomentumBasis

Route the selected region after contracting complete internal edges.

Examples

Using the setup in the FeynmanDiagram class example:

contracted = diagram.filter(edge=lambda edge: edge.data.is_dummy)
basis = diagram.contracted_momentum_basis(contracted)

Parameters

  • contracted (Subgraph or linnet.Subgraph) Complete internal edges to contract, selected from this diagram.

cycle_basis

FeynmanDiagram.cycle_basis() -> tuple[list[linnet.Cycle], Subgraph]

Return a cycle basis and its covered half-edges.

Examples

Using the setup in the FeynmanDiagram class example:

cycles, covered = diagram.cycle_basis()

denominator_expression

FeynmanDiagram.denominator_expression(
    *,
    edge_powers: typing.Optional[typing.Mapping[builtins.int, builtins.int]] = None,
    dimension: typing.Optional[Expression | int | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | ComplexFloat | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | builtins.complex | tuple[Float | builtins.int | builtins.float | builtins.str | decimal.Decimal, Float | builtins.int | builtins.float | builtins.str | decimal.Decimal]] = None,
    in_lmb: builtins.bool = False,
    lmb: typing.Optional[LoopMomentumBasis] = None,
) -> TensorExpression

Return the product of internal propagator denominators as a scalar TensorExpression.

Each factor retains GammaLoop’s four-argument denom annotation around q_e² - m_e², with matching momentum labels and symbolic masses. Dimension defaults to GammaLoop’s symbolic dimension; powers may be signed. The default region excludes external carriers and dummy edges. An explicit region follows GammaLoop and includes every complete selected edge. Widths, an imaginary prescription, and custom UFO denominator formulas are excluded. A selection without internal edges returns one.

Examples

Using the setup in the FeynmanDiagram class example:

denominator = diagram.denominator_expression(in_lmb=True)
integrand = diagram.numerator_expression(in_lmb=True) / denominator
basis = diagram.loop_momentum_bases()[0]
denominator = diagram.denominator_expression(lmb=basis)

Parameters

  • A complete diagram defaults to internal propagators; a Subgraph uses its region.
  • edge_powers (mapping[int, int] or None, optional) Signed propagator powers by diagram edge ID; omitted edges have power one.
  • dimension (Expression or int or None, optional) Lorentz dimension; defaults to the shared symbolic dimension.
  • in_lmb (bool, optional) Express edge momenta in the diagram’s stored loop-momentum basis.
  • lmb (LoopMomentumBasis or None, optional) Basis from this diagram instance. Supplying it enables routing and takes precedence over in_lmb, including for a selected region.

depth_first_traverse

FeynmanDiagram.depth_first_traverse(
    root: builtins.int,
    *,
    include: typing.Optional[builtins.int] = None,
) -> linnet.TraversalTree

Traverse a selected interaction region in depth-first order.

Examples

Using the setup in the FeynmanDiagram class example:

tree = diagram.depth_first_traverse(0)

Parameters

  • root (int) Canonical Linnet vertex ID at which traversal starts.
  • include (int or None, optional) Canonical Linnet half-edge ID to prioritize at the root.

filter

FeynmanDiagram.filter(
    *,
    node: typing.Callable[[linnet.Node], bool] | None = None,
    edge: typing.Callable[[linnet.Edge], bool] | None = None,
    half_edge: typing.Callable[[linnet.HalfEdge], bool] | None = None,
) -> Subgraph

Select by predicates on Linnet views; their data is a physics object.

Examples

Using the setup in the FeynmanDiagram class example:

region = diagram.filter(edge=lambda edge: edge.data.particle_name == "g")

Parameters

  • node (callable or None, optional) Predicate on canonical Linnet node views.
  • edge (callable or None, optional) Predicate on canonical Linnet edge views.
  • half_edge (callable or None, optional) Predicate on canonical Linnet half-edge views.

from_dot

FeynmanDiagram.from_dot(model: Model, dot: builtins.str) -> FeynmanDiagram

Parse a Feynman diagram from Graphviz DOT text.

Examples

Using the setup in the FeynmanDiagram class example:

dot = diagram.to_dot()
restored = hep.FeynmanDiagram.from_dot(model, dot)
restored.validate()
restored  # preserve topology through a Graphviz workflow

Parameters

  • model (Model) Model used to resolve particles and interactions or validate annotated IDs.
  • dot (str) Compact physics DOT or annotated HEP DOT. Compact cross-sections pair initial-state legs with is_cut and specify comma-separated final_state particles.

from_json

FeynmanDiagram.from_json(model: Model, json: builtins.str) -> FeynmanDiagram

Deserialize a Feynman diagram from its JSON representation.

Examples

Using the setup in the FeynmanDiagram class example:

encoded = diagram.to_json()
restored = hep.FeynmanDiagram.from_json(model, encoded)
restored.validate()
restored  # render the recovered graph in a notebook

Parameters

  • model (Model) Model whose stable IDs and fingerprint are referenced by the diagram.
  • json (str) JSON text produced by :meth:FeynmanDiagram.to_json or another schema-compatible producer.

integral_family

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

Build a complete integral family with preferred or automatic ISPs.

Physical propagators retain their edge order and model masses. Preferred independent dot products are appended when they increase the rank; automatic scalar products fill any remaining directions. Auxiliary entries have zero powers in the original scalar integral. Equivalent to IntegralFamily.from_diagram(self, independent_dot_products, kinematics=kinematics). Tree diagrams and dependent propagators raise DiagramError. Use propagator_family() to extract dependent propagators for partial fractioning before completing their families.

Examples

Using the setup in the FeynmanDiagram class example:

family = diagram.integral_family()

Parameters

  • 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.

is_connected

FeynmanDiagram.is_connected() -> builtins.bool

Test connectivity of the current diagram or selected region.

Examples

Using the setup in the FeynmanDiagram class example:

connected = diagram.is_connected()

loop_momentum_bases

FeynmanDiagram.loop_momentum_bases(limit: typing.Optional[builtins.int] = None) -> builtins.list[LoopMomentumBasis]

Enumerate valid loop-momentum bases for this diagram.

Examples

Using the setup in the FeynmanDiagram class example:

Limit exploratory calculations to the first basis:

basis = diagram.loop_momentum_bases(limit=1)[0]
routing = {
    edge_id: signature.format_momentum()
    for edge_id, signature in basis.edge_signatures.items()
}

Parameters

  • limit (int or None) Maximum number of bases to return. Pass None to enumerate every valid basis.

momentum_basis

FeynmanDiagram.momentum_basis() -> LoopMomentumBasis

Construct the canonical routing of the selected interaction region.

Examples

Using the setup in the FeynmanDiagram class example:

basis = diagram.momentum_basis()
routed = basis.route_expression(diagram.numerator_expression())

numerator_expression

FeynmanDiagram.numerator_expression(
    *,
    without: Subgraph | linnet.Subgraph | None = None,
    in_lmb: builtins.bool = False,
    lmb: typing.Optional[LoopMomentumBasis] = None,
) -> TensorExpression

Return the diagram numerator as a Spenso TensorExpression.

Examples

Using the setup in the FeynmanDiagram class example:

numerator = diagram.numerator_expression(in_lmb=True)
basis = diagram.loop_momentum_bases()[0]
numerator = diagram.numerator_expression(lmb=basis)
integrand_numerator = diagram.overall_factor_expression() * numerator
integrand_numerator  # native Symbolica algebra and rich display

Parameters

  • without (Subgraph or linnet.Subgraph or None, optional) Ignored region, using GammaLoop boundary and local-factor selection semantics.
  • in_lmb (bool, optional) Express edge momenta in the diagram’s stored loop-momentum basis.
  • lmb (LoopMomentumBasis or None, optional) Basis from this diagram instance. Supplying it enables routing and takes precedence over in_lmb, including for a selected region.

numerator_prefactor_expression

FeynmanDiagram.numerator_prefactor_expression() -> Expression

Return the request-wide numerator multiplier as a Symbolica expression.

Examples

Using the setup in the FeynmanDiagram class example:

prefactor = diagram.numerator_prefactor_expression()
weighted_numerator = prefactor * diagram.numerator_expression()
weighted_numerator

overall_factor_expression

FeynmanDiagram.overall_factor_expression(*, evaluate: builtins.bool = False) -> Expression

Return the diagram-wide multiplicative factor as a Symbolica expression.

evaluate=True evaluates the generator’s sign, multiplicity and symmetry annotations using the shared graph-factor evaluator. Other symbolic factors remain unchanged.

Examples

Using the setup in the FeynmanDiagram class example:

factor = diagram.overall_factor_expression()
weighted_numerator = factor * diagram.numerator_expression()
weighted_numerator

Parameters

  • evaluate (bool) Evaluate known graph-factor annotations while preserving other symbols.

projector_expression

FeynmanDiagram.projector_expression() -> Expression

Return the external-state projector as a Symbolica expression.

Examples

Using the setup in the FeynmanDiagram class example:

projector = diagram.projector_expression()
projected_numerator = projector * diagram.numerator_expression()
projected_numerator

propagator_family

FeynmanDiagram.propagator_family(
    *,
    kinematics: typing.Optional[Kinematics] = None,
) -> IntegralFamily

Extract the physical propagators using the diagram’s stored momentum routing.

Reuses the shared propagator builder and model masses. Denominators follow ascending internal edge IDs, as in internal_edges, retaining bridges and repeated propagators. Dependent external coordinates are eliminated; external carriers and dummy edges are excluded. Widths, prescriptions and custom UFO denominator formulas are not inferred. Tree diagrams raise DiagramError because they contain no loop integral. Use diagram.integral_family() to also complete the basis with automatic or explicitly chosen auxiliary scalar products.

Examples

Using the setup in the FeynmanDiagram class example:

family = diagram.propagator_family()
assert len(family.denominators) == len(diagram.internal_edges)

Parameters

  • kinematics (Kinematics or None, optional) Assumptions on routed momentum names and the Lorentz dimension. None uses the shared symbolic dimension with no on-shell assumptions.

reduce_tensor_graphs

FeynmanDiagram.reduce_tensor_graphs(reducer: TensorReducer) -> builtins.list[FeynmanDiagram]

Split the tensor numerator into scalar contributions on this topology.

Each returned diagram has one compact reduction term as its numerator, including that term’s exact projector coefficient. The graph topology, model, denominator data, and topology ID are preserved; deterministic .tensor[index] name suffixes distinguish the derived contributions. The external-state projector is consumed and reset to one, while the scalar numerator prefactor is retained. The projection must be fully contracted: any residual indexed Minkowski slot raises TensorReductionError. Use :meth:reduce_tensor_numerator when residual free Lorentz indices are intentional.

Examples

Construct scalar numerator graphs for a vacuum diagram:

from symbolica import S, E
from symbolica.community import hepkit as hep
model = hep.Model.phi4()
vacuum_diagram = model.process([], []).generate_diagrams(loops=2, factorized_loop_topologies_count_range=None).diagrams[0]
reducer = hep.TensorReducer(E("4"), integrated=[E("gammalooprs::Q")])
scalar_graphs = vacuum_diagram.reduce_tensor_graphs(reducer)

Parameters

  • reducer (TensorReducer) Tensor projector and integrated-momentum selection to apply.

reduce_tensor_numerator

FeynmanDiagram.reduce_tensor_numerator(reducer: TensorReducer) -> Expression

Reduce the finalized numerator and projector with a tensor reducer.

The result is a native Symbolica expression using spenso::dot and spenso::g. For a fully projected vacuum numerator, all Lorentz indices disappear and only scalar invariants remain. Residual free projector indices are preserved as metric tensors; use :meth:reduce_tensor_graphs when scalar graph contributions are required. The scalar numerator prefactor remains separate and is not included in this expression.

Examples

Reduce a vacuum graph after explicitly selecting its integrated momentum head:

from symbolica import S, E
from symbolica.community import hepkit as hep
model = hep.Model.phi4()
vacuum_diagram = model.process([], []).generate_diagrams(loops=2, factorized_loop_topologies_count_range=None).diagrams[0]
reducer = hep.TensorReducer(E("4"), integrated=[E("gammalooprs::Q")])
scalar_numerator = vacuum_diagram.reduce_tensor_numerator(reducer)

Parameters

  • reducer (TensorReducer) Tensor projector and integrated-momentum selection to apply.

render

FeynmanDiagram.render(
    *,
    config: builtins.dict[builtins.str, typing.Any] | None = None,
    momenta: builtins.bool = False,
    lmb: typing.Optional[LoopMomentumBasis] = None,
    highlight: Subgraph | linnet.Subgraph | None = None,
) -> builtins.str

Render an interactive, transparent SVG using the shared physics renderer.

All graph geometry is drawn in Rust; the embedded Typst compiler typesets labels and titles. layouts={"impred_labels": True} refines the layout around the drawn labels. No Python renderer or Typst graph package is needed.

Examples

Using the setup in the FeynmanDiagram class example:

svg = diagram.render(momenta=True, config={
    "layouts": {"impred_steps": 100},
    "template_options": {"show-particle": False},
})
svg = diagram.render(lmb=next(iter(diagram.loop_momentum_bases())))

Parameters

  • config (dict or None, optional) Native layouts, drawing and style dictionaries. Boolean physics controls in template_options include show-particle, show-momentum, show-edge-index, show-node-index, debug, and momentum-arrows. Cross sections open their initial-state connections by default; set split-initial-state to False to draw the sewn graph.
  • momenta (bool, optional) Show momentum arrows and labels routed in the diagram’s stored basis. Explicit physics settings in config override these display defaults.
  • lmb (LoopMomentumBasis or None, optional) Explicit routing from this diagram; also enables momentum display. Rendering never changes the diagram’s stored loop-momentum basis.
  • highlight (Subgraph or linnet.Subgraph or None, optional) Highlight a region while preserving the full diagram as muted context. A Subgraph highlights its own region by default.

subgraph

FeynmanDiagram.subgraph(
    selection: Subgraph | linnet.Subgraph | None = None,
    *,
    nodes: typing.Optional[typing.Sequence[builtins.int]] = None,
    edges: typing.Optional[typing.Sequence[builtins.int]] = None,
    half_edges: typing.Optional[typing.Sequence[builtins.int]] = None,
) -> Subgraph

Select graph elements using canonical Linnet IDs, or import a graph-bound selection. Nested selections intersect this region and retain its immutable original diagram.

Examples

Using the setup in the FeynmanDiagram class example:

region = diagram.subgraph(edges=[0, 1])
numerator = region.numerator_expression()

Parameters

  • selection (Subgraph or linnet.Subgraph or None, optional) Existing selection from the same original diagram; exclusive with element IDs.
  • nodes (list[int] or None, optional) Canonical Linnet nodes IDs to include.
  • edges (list[int] or None, optional) Canonical Linnet edges IDs to include.
  • half_edges (list[int] or None, optional) Canonical Linnet half-edges IDs to include.

superficial_degree_of_divergence

FeynmanDiagram.superficial_degree_of_divergence(*, dimension: builtins.int = 4) -> builtins.int

Return the local superficial UV degree of divergence.

Counts dimension * loops plus vertex momentum powers and internal propagator numerator powers minus two per internal propagator. Uses the stored local numerators; excludes external legs, projectors, and global prefactors. Vertex momenta scale together, before tensor cancellations. Zero is logarithmic, positive is power divergent, and negative is superficially convergent. Subdivergences are not tested.

Examples

Using the setup in the FeynmanDiagram class example:

degree = diagram.superficial_degree_of_divergence()
degree_in_six_dimensions = diagram.superficial_degree_of_divergence(dimension=6)

Parameters

  • dimension (int, optional) Spacetime dimension for each loop integration measure; defaults to four.

tensor_reduce

FeynmanDiagram.tensor_reduce(
    dimension: Expression | int | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | ComplexFloat | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | builtins.complex | tuple[Float | builtins.int | builtins.float | builtins.str | decimal.Decimal, Float | builtins.int | builtins.float | builtins.str | decimal.Decimal],
    *,
    expression: symbolica.Expression | symbolica.community.tensor.TensorExpression | None = None,
    projector: typing.Optional[Expression | int | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | ComplexFloat | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | builtins.complex | tuple[Float | builtins.int | builtins.float | builtins.str | decimal.Decimal, Float | builtins.int | builtins.float | builtins.str | decimal.Decimal]] = None,
) -> TensorExpression

Reduce the numerator and projector using the diagram’s internal edge momenta.

Four-dimensional Lorentz slots are promoted to D before reduction. External momenta remain projector vectors, and the scalar numerator prefactor remains separate. Requires at least one internal edge. A supplied expression replaces the numerator and projector, for example after a UV expansion; it must use the diagram’s edge momentum names.

Examples

Using the setup in the FeynmanDiagram class example:

from symbolica import E
reduced = diagram.tensor_reduce(E("D"))

Parameters

  • dimension (Expression or int) Lorentz dimension used for the reduction and four-dimensional input slots.
  • expression (Expression or TensorExpression, optional) Complete prepared input to reduce instead of the numerator and projector. Cannot be combined with an explicit projector.
  • projector (Expression or None, optional) Explicit external tensor projector, required for partial regions unless expression is supplied.

to_dot

FeynmanDiagram.to_dot() -> builtins.str

Serialize the diagram topology and annotations to Graphviz DOT text.

Examples

Using the setup in the FeynmanDiagram class example:

dot = diagram.to_dot()
restored = hep.FeynmanDiagram.from_dot(model, dot)
restored.validate()

to_html

FeynmanDiagram.to_html(
    *,
    config: builtins.dict[builtins.str, typing.Any] | None = None,
    momenta: builtins.bool = False,
    lmb: typing.Optional[LoopMomentumBasis] = None,
    highlight: Subgraph | linnet.Subgraph | None = None,
) -> builtins.str

Render an HTML figure with the same options and hover information as render.

Examples

Using the setup in the FeynmanDiagram class example:

import marimo as mo
mo.iframe(diagram.to_html(momenta=True))

Parameters

  • config (dict or None, optional) Layout, drawing, style and physics settings, as in render.
  • momenta (bool, optional) Draw momentum arrows and labels in the stored basis.
  • lmb (LoopMomentumBasis or None, optional) Routing from this diagram; also enables momentum display.
  • highlight (Subgraph or linnet.Subgraph or None, optional) Region to highlight in the complete diagram.

to_json

FeynmanDiagram.to_json() -> builtins.str

Serialize the complete diagram to JSON text.

Examples

Using the setup in the FeynmanDiagram class example:

encoded = diagram.to_json()
restored = hep.FeynmanDiagram.from_json(model, encoded)
restored.validate()

to_linnest

FeynmanDiagram.to_linnest(
    *,
    config: builtins.dict[builtins.str, typing.Any] | None = None,
    momenta: builtins.bool = False,
    lmb: typing.Optional[LoopMomentumBasis] = None,
    highlight: Subgraph | linnet.Subgraph | None = None,
) -> builtins.str

Export a self-contained Typst document embedding the rendered SVG.

Uses the same config, momenta, lmb and highlight settings as render. Labels are already typeset; compiling the exported source needs no Linnest, Kurvst, MiTeX, or model assets.

Examples

Using the setup in the FeynmanDiagram class example:

from pathlib import Path
Path("diagram.typ").write_text(diagram.to_linnest(momenta=True))

Parameters

  • config (dict or None, optional) Layout, drawing, style and physics settings, as in render.
  • momenta (bool, optional) Draw momentum arrows and labels in the stored basis.
  • lmb (LoopMomentumBasis or None, optional) Routing from this diagram; also enables momentum display.
  • highlight (Subgraph or linnet.Subgraph or None, optional) Region to highlight in the complete diagram.

to_linnet

FeynmanDiagram.to_linnet() -> linnet.Graph

Return the canonical installed Linnet graph with physics objects as payloads.

Node, edge, and half-edge identities are mapped explicitly. Structural edits affect this analysis graph only; the next export starts a fresh graph, and selections from the modified topology cannot be used here.

Examples

Using the setup in the FeynmanDiagram class example:

graph = diagram.to_linnet()
gluons = graph.filter(edge=lambda edge: edge.data.particle_name == "g")

uv_counterterm

FeynmanDiagram.uv_counterterm(
    uv_mass: Expression | int | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | ComplexFloat | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | builtins.complex | tuple[Float | builtins.int | builtins.float | builtins.str | decimal.Decimal, Float | builtins.int | builtins.float | builtins.str | decimal.Decimal],
    *,
    dimension: builtins.int = 4,
    numerator: symbolica.Expression | symbolica.community.tensor.TensorExpression | None = None,
    edge_powers: typing.Optional[typing.Mapping[builtins.int, builtins.int]] = None,
) -> TensorExpression

Return the additive local UV counterterm, the negative of uv_expansion.

Arguments and selection semantics are those of :meth:uv_expansion. Add this unintegrated expression to the selected integrand to subtract its simultaneous UV limit. Subdivergences require separate forest terms.

Examples

Using the setup in the FeynmanDiagram class example:

from symbolica import S
mass = S("mUV", is_scalar=True)
counterterm = diagram.uv_counterterm(mass)

Parameters

  • uv_mass (Expression or int) Auxiliary mass used for the propagator expansion.
  • dimension (int, optional) Positive spacetime dimension for UV power counting; defaults to four.
  • numerator (Expression or TensorExpression or None, optional) Prepared numerator in edge momenta; None uses the selected local numerator.
  • edge_powers (mapping[int, int] or None, optional) Signed propagator powers by diagram edge ID; omitted edges have power one. Zero omits the denominator; negative powers put it in the numerator. Entries outside the selected internal edges are ignored.

uv_expansion

FeynmanDiagram.uv_expansion(
    uv_mass: Expression | int | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | ComplexFloat | Float | builtins.int | builtins.float | builtins.str | decimal.Decimal | builtins.complex | tuple[Float | builtins.int | builtins.float | builtins.str | decimal.Decimal, Float | builtins.int | builtins.float | builtins.str | decimal.Decimal],
    *,
    dimension: builtins.int = 4,
    numerator: symbolica.Expression | symbolica.community.tensor.TensorExpression | None = None,
    edge_powers: typing.Optional[typing.Mapping[builtins.int, builtins.int]] = None,
) -> TensorExpression

Expand the local integrand through its UV degree of divergence.

The selected region’s loop momenta are scaled together. Propagators are expanded about the auxiliary mass uv_mass, retaining every power through logarithmic divergence in dimension spacetime dimensions. The result uses edge momenta and the same tagged denom convention as :meth:denominator_expression; the diagram is unchanged.

numerator optionally replaces the local numerator (in edge momenta), for example after contracting a projector. Overall factors, numerator prefactors and projectors remain separate unless supplied in it. edge_powers uses the signed powers of :meth:denominator_expression. Move rational propagator factors out of a prepared numerator into these powers so they receive the same auxiliary-mass expansion. Powers do not change the selected region or its loop integration measure. Empty, tree and UV-convergent regions return zero. This performs one UV limit; it does not enumerate forests or integrate the counterterm.

Examples

Using the setup in the FeynmanDiagram class example:

expanded = diagram.uv_expansion(0)
expansion = expanded  # symbolic Taylor-expanded integrand

Parameters

  • uv_mass (Expression or int) Auxiliary mass used for the propagator expansion.
  • dimension (int, optional) Positive spacetime dimension for UV power counting; defaults to four.
  • numerator (Expression or TensorExpression or None, optional) Prepared numerator in edge momenta; None uses the selected local numerator.
  • edge_powers (mapping[int, int] or None, optional) Signed propagator powers by diagram edge ID; omitted edges have power one. Zero omits the denominator; negative powers put it in the numerator. Entries outside the selected internal edges are ignored.

validate

FeynmanDiagram.validate() -> None

Validate particle and interaction references against a physics model.

Examples

Using the setup in the FeynmanDiagram class example:

Validation raises DiagramError for invalid particle or interaction references:

diagram.validate()

with_loop_momentum_edges

FeynmanDiagram.with_loop_momentum_edges(edges: typing.Sequence[builtins.int]) -> FeynmanDiagram

Return a diagram using the specified loop-edge coordinates, in the supplied order.

Examples

Using the setup in the FeynmanDiagram class example:

rerouted = diagram.with_loop_momentum_edges(diagram.loop_momentum_basis.loop_edges)

Parameters

  • edges (list[int]) Diagram edge IDs specifying the requested routing coordinates.

with_loop_momentum_tree_edges

FeynmanDiagram.with_loop_momentum_tree_edges(edges: typing.Sequence[builtins.int]) -> FeynmanDiagram

Return a diagram whose momentum routing uses the specified spanning forest.

Examples

Using the setup in the FeynmanDiagram class example:

rerouted = diagram.with_loop_momentum_tree_edges(diagram.loop_momentum_basis.tree_edges)

Parameters

  • edges (list[int]) Diagram edge IDs specifying the requested routing coordinates.