Noncommutative algebra API
Expressions over noncommutative symbols (pool.symbol(name, commutative=False)) read as noncommutative polynomials, with word-rewriting
normal forms. See the Noncommutative algebra chapter of the user guide.
nc_expand(expr) -> Expr
Expand expr as a polynomial in noncommutative symbols: products
distribute keeping factor order, non-negative integer powers of
noncommutative factors unroll, equal words collect and their commutative
coefficients are simplified.
>>> sx, sy = (p.symbol(n, commutative=False) for n in ("sx", "sy"))
>>> nc_expand((sx + sy)**2) # sx^2 + sx*sy + sy*sx + sy^2Raises NcError E-NC-002 past the size caps.
nc_terms(expr) -> list[tuple[Expr, list[Expr]]]
The terms (coefficient, word) of expr read as a noncommutative
polynomial (see nc_expand()): coefficient is commutative and
word is the ordered list of noncommutative factors (empty for the
scalar part).
nc_rewrite(expr, rules, *, max_steps=200000) -> Expr
Rewrite expr to a normal form with literal word rules made by
make_rule(): every occurrence of a rule's left-hand word inside a
longer word is replaced (make_rule(X*P, P*X + I*hbar) rewrites
X*P*P), the result is re-expanded, and the process repeats until no
rule applies.
Each left-hand side must be a single product of noncommutative factors with coefficient 1; symbols in these rules are literal (no wildcards).
Raises NcError: E-NC-003 for a malformed left-hand side,
E-NC-001 when no normal form is reached within max_steps rewrites
(non-terminating rules), E-NC-002 past the size caps.
commutator(a, b, rules=None) -> Expr
[a, b] = a*b - b*a, expanded as a noncommutative polynomial. With
rules (from make_rule()) the result is rewritten to normal form
with nc_rewrite(), e.g. commutator(X, P**2, [make_rule(X*P, P*X + I*hbar)])` gives `2*I*hbar*P.
anticommutator(a, b, rules=None) -> Expr
{a, b} = a*b + b*a, expanded; rules as for commutator().
normal_order(expr, bosons=None, fermions=None) -> Expr
Normal-order expr with the canonical commutation relations: every
creation operator moves left of every annihilation operator using
[a, a†] = 1 for bosonic modes and {c, c†} = 1, c**2 = 0 for
fermionic ones (Wick's theorem: the contractions appear as the extra
terms). Operators of different modes are ordered by their position in the
mode lists (bosons first), with a sign for each swap of two fermionic
operators.
expran expression in noncommutative symbols.
bosonsan
(a, adag)pair or a list of them.fermionsa
(c, cdag)pair or a list of them.
Each operator must be a noncommutative symbol (commutative=False).
Other noncommutative factors stay in place and block reordering.
>>> a, ad = p.symbol("a", commutative=False), p.symbol("ad", commutative=False)
>>> normal_order(a * ad**3, bosons=(a, ad)) # ad^3*a + 3*ad^2Raises NcError E-NC-004 for a malformed mode list.
vacuum_expectation(expr, bosons=None, fermions=None) -> Expr
<0| expr |0>: the scalar part of normal_order() (expr).
E.g. vacuum_expectation(a*a*ad*ad, bosons=(a, ad)) == 2.
Raises NcError E-NC-007 when expr contains a noncommutative
factor that is not one of the listed ladder operators.
gamma_trace(slots, pool=None) -> Expr
Trace of a product of Dirac matrices in four dimensions, metric
diag(+1, -1, -1, -1), {γ^μ, γ^ν} = 2 g^{μν}, tr 1 = 4,
γ^5 = i γ^0 γ^1 γ^2 γ^3.
slotsa list whose entries are
0–3(γ^0…γ^3),5(γ^5), or a commutativeExprpstanding for the slashed vectorp̸ = p_μ γ^μ(equally, a free Lorentz index).poolthe pool for the result when
slotsholds noExpr.
A polynomial in
dot(p, q)(p·q;dot(k, p) = p^kfor anexplicit index
k) andlevi_civita(a, b, c, d)``= ε^{μνρσ}a_μ b_ν c_ρ d_σ
withε^{0123} = +1, sotr(γ^5 a̸ b̸ c̸ d̸) =-4i·levi_civita(a, b, c, d)
. Withγ^5`` and more than four otherslots,
γ^5is expanded asiγ^0γ^1γ^2γ^3and the answer usesexplicit components
dot(k, p).
>>> gamma_trace([p, q, k, l]) # 4*dot(p,q)*dot(k,l) - 4*dot(k,p)*dot(l,q) + ...
>>> gamma_trace([5, 0, 1, 2, 3], pool=pool) # -4*IWith dim (an integer or a symbolic d) the trace is taken in
dim dimensions (tr 1 = 4, as in FORM / FeynCalc): every slot is a
commutative Expr label, indices lists the labels that are Lorentz
indices, and an index occurring twice is summed with g^μ_μ = dim:
gamma_trace([mu, mu], dim=d, indices=[mu]) # 4*d
gamma_trace([mu, nu, mu, nu], dim=d, indices=[mu, nu]) # 4*d*(2 - d)An index occurring once stays free (dot(μ, ν) = g^{μν}); contract
products of traces with lorentz_contract(). γ^5 and explicit
components 0-3 are four-dimensional and are refused here.
Raises NcError: E-NC-005 for an invalid slot (or γ^5 /
an explicit component with dim), E-NC-006 for more than 14 slots
to expand.
lorentz_contract(expr, indices, dim) -> Expr
Contract the dummy Lorentz indices indices of a polynomial in
dot(a, b) factors (dot(μ, μ) -> d; dot(μ, a)*dot(μ, b) -> dot(a, b)). An index occurring once is free and kept. Use it on products
of traces, e.g. tr(γ^μγ^νγ^ργ^σ) tr(γ_μγ_νγ_ργ_σ) = 16 d (3d - 2):
t = gamma_trace([m, n, r, s], dim=d) # free indices
lorentz_contract(t * t, [m, n, r, s], d) # 48*d**2 - 32*d (up to form)Raises NcError E-NC-005 for an index occurring more than twice or
inside a factor that is not a dot (e.g. levi_civita).
gamma_contract(slots, indices, dim) -> list[tuple[Expr, list[Expr]]]
Contract the dummy Lorentz indices of a product of gamma matrices in
dim dimensions using only {γ^μ, γ^ν} = 2 g^{μν}. slots are
commutative labels; a label listed in indices that occurs twice is a
summed index. Returns terms (coefficient, labels) meaning
coefficient * γ(labels[0]) γ(labels[1]) ..., with no index repeated:
γ^μ γ_μ = d->[(d, [])]γ^μ γ^ν γ_μ = (2 - d) γ^νγ^μ γ^ν γ^ρ γ_μ = 2 γ^ρ γ^ν + (d - 2) γ^ν γ^ρ(= 4 g^{νρ} - (4-d) γ^ν γ^ρ)
Raises NcError E-NC-005 for non-commutative labels or an index
repeated more than twice, E-NC-006 past 14 slots.
lie_algebra(generators, structure_constants, *, check_jacobi=True) -> LieAlgebra
A Lie algebra on noncommutative generators with
[T_a, T_b] = i Σ_c f_{abc} T_c. structure_constants maps 1-based
triples (a, b, c) to f_{abc} (Expr or int); an entry with
a > b means f_{abc} = -f_{bac} and both orders may be given if
they agree; absent entries are zero. The returned LieAlgebra
reduces commutators of arbitrary noncommutative polynomials in the
generators (commutator), normal-orders words (normal_order) and
builds the Casimir.
The table is checked against the Jacobi identity (check_jacobi=False
skips it). Raises NcError E-NC-008 for generators that are not
distinct noncommutative symbols, bad or inconsistent entries, or a failed
(or symbolically unverifiable) Jacobi identity.
Example:
J = [p.symbol(f"J{i}", commutative=False) for i in (1, 2, 3)]
su2 = lie_algebra(J, {(1, 2, 3): 1, (2, 3, 1): 1, (3, 1, 2): 1})
su2.commutator(J[0], J[1]) # I*J3lie_su2(pool, generators=None, *, prefix="J") -> LieAlgebra
su(2): [J_a, J_b] = i ε_{abc} J_c (J = σ/2, spin matrices). With
no generators it creates noncommutative symbols J1, J2, J3. The
Casimir J1² + J2² + J3² commutes with every generator.
lie_su3(pool, generators=None, *, prefix="T") -> LieAlgebra
su(3) in the Gell-Mann basis: [T_a, T_b] = i f_{abc} T_c with
T = λ/2 (f_{123} = 1, f_{458} = f_{678} = √3/2, …; see
su3_f()). With no generators it creates T1 … T8. The
Casimir Σ T_a² equals 4/3 in the fundamental representation.
su3_f(pool) -> dict[tuple[int, int, int], Expr]
The Gell-Mann structure constants f_{abc} (1-based, all nonzero
entries in all six index orders): [λ_a/2, λ_b/2] = i f_{abc} λ_c/2.
su3_d(pool) -> dict[tuple[int, int, int], Expr]
The Gell-Mann symmetric constants d_{abc} (1-based, all nonzero
entries in every index order): {λ_a, λ_b} = (4/3) δ_{ab} + 2 d_{abc} λ_c.
make_rule(lhs, rhs, sequence=[X, ...]) declares noncommutative symbols of
lhs to be sequence wildcards matching a contiguous, possibly empty run of
factors (leftmost start, shortest run), usable through simplify_with;
E-NC-009 for a malformed pattern.
simplify_pauli reduces any word over sx, sy, sz with the full
Pauli algebra; make_rule / simplify_with match product patterns inside
longer products (contiguous runs for noncommutative products, sub-multisets for
commutative ones).
Refusals raise NcError (E-NC-001 … E-NC-009); see errors.
Lie algebras
A Lie algebra given by [T_a, T_b] = i Σ_c f_{abc} T_c on noncommutative
generators (see lie_algebra()).
The ordering rules T_a T_b -> T_b T_a + [T_a, T_b] (a > b) as
RewriteRule objects, usable with nc_rewrite().
[a, b] reduced with the table: commutator(T_a, T_b) is
i Σ f_abc T_c; for polynomials the result is in normal order
(generators in increasing index order).
Rewrite expr to normal order: generators in increasing table order
(Poincaré–Birkhoff–Witt basis), commutator terms added.
The quadratic Casimir Σ g^{ab} T_a T_b. inverse_metric is an
n × n nested list g^{ab} (ints or Expr); the default is the
identity, i.e. Σ T_a², correct for the su(n) tables of this module
(basis orthonormal under the Killing form).