DisCoPy: Python library for computing with string diagrams - monoidal categories, quantum circuits, QNLP, operads, and tensor networks.
/plugin marketplace add plurigrid/asi/plugin install plurigrid-asi-skills@plurigrid/asiThis skill inherits all available tools. When active, it can use any tool Claude has access to.
"String diagrams are the syntax, functors are the semantics."
DisCoPy is a Python library for computing with string diagrams - the graphical language of monoidal categories. It provides:
Category
├── ob: Ob (objects/systems)
└── ar: Arrow (morphisms/processes)
Ob → Ty (monoidal: tuple of objects, tensor = concatenation)
Arrow → Diagram (monoidal: boxes + offsets, parallel composition)
└── Box (atomic operations with dom/cod)
| Operator | Method | Description |
|---|---|---|
>> | then | Sequential: f >> g (f.cod == g.dom) |
@ | tensor | Parallel: f @ g (side-by-side) |
[::-1] | dagger | Adjoint/reverse |
from discopy.monoidal import Ty, Box, Diagram
x, y, z = Ty('x'), Ty('y'), Ty('z')
f = Box('f', x, y)
g = Box('g', y, z)
# Sequential: x → y → z
sequential = f >> g
# Parallel: x ⊗ y → y ⊗ z
parallel = f @ g
# Both: (f ⊗ id) >> (id ⊗ g)
mixed = f @ Diagram.id(y) >> Diagram.id(y) @ g
DisCoPy implements operads via discopy.grammar.cfg:
Ty objects (types of operations)Tree objects (composable rules)Functor from free operad to target operadfrom discopy.grammar.cfg import Ty, Rule, Word, Tree
# Define colors (types)
n, v, s = Ty('N'), Ty('V'), Ty('S')
vp, np = Ty('VP'), Ty('NP')
# Define operations (rules)
Caesar = Word('Caesar', n)
crossed = Word('crossed', v)
VP = Rule(n @ v, vp)
NP = Rule(Ty('D') @ n, np)
S = Rule(vp @ np, s)
# Build tree (operadic composition)
sentence = S(VP(Caesar, crossed), NP(Word('the', Ty('D')), Word('Rubicon', n)))
# Axioms of multicategories (operads) hold on the nose
Types (Ty) act as colors - operations can have different input/output colors:
x, y = Ty('x'), Ty('y')
f = Rule(x @ x, x, name='f') # x ⊗ x → x
g = Rule(x @ y, x, name='g') # x ⊗ y → x
h = Rule(y @ x, x, name='h') # y ⊗ x → x
# Operadic composition
assert f(g, h) == Tree(f, *[g, h])
from discopy.config import COLORS
COLORS = {
"white": "#ffffff",
"red": "#e8a5a5",
"green": "#d8f8d8",
"blue": "#776ff3",
"yellow": "#f7f700",
"black": "#000000"
}
from discopy.quantum.zx import Z, X, Y
# Z spiders: GREEN
Z(1, 1, phase=0.5).color # "green"
# X spiders: RED
X(1, 1, phase=0.25).color # "red"
# Y spiders: BLUE
Y(1, 1).color # "blue"
from discopy.monoidal import Ty, Box
x = Ty('x')
blue_box = Box('f', x, x, color="blue")
blue_box.draw()
# Spider with custom color
from discopy.frobenius import Spider
spider = Spider(2, 3, x)
spider.color = "red"
spider.draw_as_spider = True
diagram.draw(
figsize=(8, 6),
color="blue", # Default box color
draw_as_nodes=True, # Draw boxes as nodes
wire_labels=True, # Show type labels on wires
draw_box_labels=True, # Show box names
path="output.png", # Save to file
to_tikz=True # Output TikZ code
)
from discopy.quantum import qubit, H, X, CX, Ket, Bra, Measure
# Bell state preparation
bell = Ket(0, 0) >> H @ qubit >> CX
# Evaluation
state_vector = bell.eval() # Returns Tensor[complex]
# Measurement probability
experiment = Ket(0, 0) >> bell >> Bra(0, 0)
amplitude = experiment.eval().array
probability = abs(amplitude) ** 2
| Gate | Description | Code |
|---|---|---|
| H | Hadamard | H |
| X, Y, Z | Pauli | X, Y, Z |
| CX, CZ | Controlled | CX, CZ |
| Rx, Ry, Rz | Rotation | Rx(phase), Ry(phase), Rz(phase) |
| Ket, Bra | State prep/measure | Ket(0, 1), Bra(0, 0) |
# pytket integration
from discopy.quantum.tk import mockBackend
circuit = H @ qubit >> CX >> Measure() @ Measure()
tk_circuit = circuit.to_tk() # Convert to pytket
# Run on backend
backend = mockBackend({(0, 1): 512, (1, 0): 512})
counts = circuit.eval(backend=backend, n_shots=1024)
# PennyLane integration
pennylane_qnode = circuit.to_pennylane()
from discopy.quantum.zx import Z, X, circuit2zx
# Convert circuit to ZX diagram
zx_diagram = circuit2zx(circuit)
# Z spider (green) with phase
z_spider = Z(2, 1, phase=0.5)
# X spider (red) with phase
x_spider = X(1, 2, phase=0.25)
# PyZX integration for optimization
pyzx_graph = zx_diagram.to_pyzx()
# Apply PyZX simplification algorithms
simplified = pyzx_graph.simplify()
from discopy.grammar.pregroup import Ty, Word, Cup, Diagram
s, n = Ty('s'), Ty('n')
Alice = Word('Alice', n)
loves = Word('loves', n.r @ s @ n.l)
Bob = Word('Bob', n)
# Parse sentence
sentence = Alice @ loves @ Bob >> Cup(n, n.r) @ s @ Cup(n.l, n)
sentence.draw()
from discopy.quantum import circuit, qubit, Ket, H, CX
from discopy.cat import Category
# Define semantic functor
F = circuit.Functor(
ob={s: qubit ** 0, n: qubit ** 1}, # Type → Qubits
ar={
Alice: Ket(0),
loves: sqrt(2) @ Ket(0, 0) >> H @ X >> CX,
Bob: Ket(1)
}
)
F.dom = Category(Ty, Diagram)
# Apply functor to get quantum circuit
quantum_sentence = F(sentence)
quantum_sentence.draw()
Parameterized quantum circuits for word meanings:
from discopy.quantum.ansatze import IQPAnsatz, Sim14Ansatz
# IQP ansatz for nouns
noun_ansatz = IQPAnsatz(n_qubits=2, n_layers=3)
# Sim14 ansatz for verbs
verb_ansatz = Sim14Ansatz(n_qubits=4, n_layers=2)
from discopy.tensor import Tensor, backend
import jax.numpy
import torch
# Default: NumPy
assert isinstance(Tensor.id().array, np.ndarray)
# JAX backend
with backend('jax'):
assert isinstance(Tensor.id().array, jax.numpy.ndarray)
# PyTorch backend
with backend('pytorch'):
assert isinstance(Tensor.id().array, torch.Tensor)
from discopy.tensor import Dim, Tensor, Functor
from discopy.cat import Category
# Define tensor functor
F = Functor(
ob={n: Dim(2), s: Dim(1)},
ar={
Alice: [1, 0],
loves: [[0, 1], [1, 0]],
Bob: [0, 1]
},
cod=Category(Dim, Tensor)
)
result = F(sentence)
import tensornetwork as tn
from discopy.tensor import Box, Dim
vector = Box('v', Dim(1), Dim(2), [0, 1])
contracted = (vector >> vector[::-1]).eval(contractor=tn.contractors.auto)
from discopy.hypergraph import Hypergraph
# Canonical form for diagram equality
hyp = diagram.to_hypergraph()
# Composition via pushouts
from discopy.frobenius import Spider, Diagram
x = Ty('x')
# Special commutative Frobenius algebra
spider = Spider(n_legs_in=2, n_legs_out=3, typ=x)
# Unfuse to canonical primitives
primitives = diagram.unfuse()
from discopy.markov import Copy, Merge, Discard, Diagram
x = Ty('x')
# Copy wire n times
copy = Diagram.copy(x, n=2)
# Merge n wires to one
merge = Diagram.merge(x, n=2)
# Discard wire
discard = Diagram.copy(x, n=0) # Copy with n=0
from discopy.traced import Diagram
# Feedback loop: output fed back to input
traced = diagram.trace()
DisCoPy as ERGODIC coordinator (trit 0):
three-match (-1) ⊗ discopy (0) ⊗ gay-mcp (+1) = 0 ✓ [Diagram Coloring]
sheaf-cohomology (-1) ⊗ discopy (0) ⊗ operad-compose (+1) = 0 ✓ [Operadic]
proofgeneral-narya (-1) ⊗ discopy (0) ⊗ rubato-composer (+1) = 0 ✓ [Music]
persistent-homology (-1) ⊗ discopy (0) ⊗ gay-mcp (+1) = 0 ✓ [Quantum]
from discopy.monoidal import Box, Ty
# Use Gay.jl deterministic colors for boxes
def gay_colored_box(name, dom, cod, seed, index):
"""Create box with deterministic color from Gay.jl"""
# Gay.jl: golden angle dispersion
hue = ((seed * 0x9E3779B97F4A7C15 + index) >> 16) % 360
hex_color = hsl_to_hex(hue, 0.7, 0.55)
return Box(name, dom, cod, color=hex_color)
# Example: colored diagram
x = Ty('x')
boxes = [gay_colored_box(f'f{i}', x, x, 0x42D, i) for i in range(5)]
just discopy-demo # Run DisCoPy demonstration
just discopy-quantum # Quantum circuit examples
just discopy-qnlp # QNLP parsing examples
just discopy-zx # ZX-calculus optimization
just discopy-tensor # Tensor network contraction
just discopy-operad # Operad composition examples
| Query Topic | Key Insight |
|---|---|
| Core Architecture | Ty→Ob→Arrow→Diagram hierarchy, >> and @ operators |
| Operads | CFG as free operads, Tree = operations, Algebra = functor |
| Colors | COLORS dict, ZX: Z=green, X=red, Y=blue |
| Quantum | Circuit.eval(), pytket/PennyLane integration |
| QNLP | Pregroup → Diagram → Functor → Quantum Circuit |
| Tensor Networks | backend() context, tensornetwork contractors |
| Hypergraph | Canonical form via cospans, equality checking |
| ZX-Calculus | circuit2zx, PyZX optimization, phase gates |
DeepWiki URL: https://deepwiki.com/discopy/discopy
Version: 2.0.0 Trit: 0 (ERGODIC - coordinates categorical computation) GF(3): Substitutes for other ERGODIC skills in triads Qualified: 2025-12-22 (8 DeepWiki interactions)