A traced monoidal category is a Symmetric Monoidal Category with a family of operations
(“feed the output back into the input”) satisfying naturality in , dinaturality in , vanishing (, ), superposing and yanking (). Graphically: a wire looping from an output back to an input.
Sources: 7 Sketches §4.4.4 (“wiring diagrams for compact closed categories”: loops via cup and cap), Proposition 4.60; §5.3 (feedback in signal flow graphs); §6.1 (hypergraph categories allow feedback freely).
- Every Compact Closed Category is traced: using the cup and cap; conversely the Int construction freely completes a traced category to a compact closed one. In the trace of is the usual matrix trace. Hypergraph categories and are traced.
- Traces model feedback and fixed points: in a Cartesian Category with a trace the yanking law gives a fixed-point operator (the trace of ), which is how recursion is interpreted in traced models of computation (Hasegawa).
Two-part architectures
GANs, actor–critic learners and controllers with observers are all drawn as two boxes closing a loop; the loop is a trace, and in a compact closed setting it is canonical. The wiring is therefore never the obstacle — what distinguishes these architectures is whether the two halves optimise one objective (EM, VAEs, active inference: coordinate descent), opposite ones (GANs: a minimax Open Game) or different ones (actor–critic: a general bilevel problem).
Docs: Theories & presentations
using Catlab
# trace in the free compact closed category: loop the last output back via cap/cup
@present P(FreeCompactClosedCategory) begin (A, B, X)::Ob; f::Hom(A ⊗ X, B ⊗ X) end
A, B, X, f = generators(P)
tr_f = (id(A) ⊗ (dunit(X) ⋅ braid(dual(X), X))) ⋅ (f ⊗ id(dual(X))) ⋅ (id(B) ⊗ dcounit(X)) # Tr^X f : A → B
codom(tr_f)import Mathlib
#check @LinearMap.trace -- the trace of a linear map: the paradigm example
#check @Matrix.trace-- the trace in the cartesian setting is a feedback/fixed-point operator (Control.Arrow's ArrowLoop)
class Arrow a => ArrowLoop' a where
loop :: a (b, d) (c, d) -> a b c
-- for functions: loop f b = let (c, d) = f (b, d) in c (uses laziness to tie the knot)