SkillAgentSearch skills...

Discopy

The Python toolkit for computing with string diagrams.

Install / Use

/learn @discopy/Discopy
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<picture> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/discopy/discopy/raw/main/docs/_static/snake-equation-dark.svg"> <img alt="Snake equation" width="60%" src="https://github.com/discopy/discopy/raw/main/docs/_static/snake-equation.svg"> </picture>

DisCoPy

build readthedocs PyPI version DOI: 10.4204/EPTCS.333.13

DisCoPy is a Python toolkit for computing with string diagrams.

DisCoPy began as an implementation of DisCoCat and QNLP. This has now become its own library: lambeq.

Features

Quickstart

pip install discopy

If you want to see DisCoPy in action, you can check out the following notebooks:

Or you can keep scrolling down to the examples:

Contribute

We're keen to welcome new contributors!

First, read the contributing guidelines then open an issue.

How to cite

If you use DisCoPy in the context of an academic publication, we suggest you cite:

  • G. de Felice, A. Toumi & B. Coecke, DisCoPy: Monoidal Categories in Python, EPTCS 333, 2021, pp. 183-197, DOI: 10.4204/EPTCS.333.13

If furthermore your work is related to quantum computing, you can also cite:

  • A. Toumi, G. de Felice & R. Yeung, DisCoPy for the quantum computer scientist, arXiv:2205.05190

If you use any of the recent features (e.g. Hypergraph) you should also mention:

  • A. Toumi, R. Yeung, B. Poór & G. de Felice, DisCoPy: the Hierarchy of Graphical Languages in Python arXiv:2311.10608

Example: Cooking

This example is inspired from Pawel Sobocinski's blog post Crema di Mascarpone and Diagrammatic Reasoning.

from discopy.symmetric import Ty, Box, Diagram

egg, white, yolk = Ty("egg"), Ty("white"), Ty("yolk")
crack = Box("crack", egg, white @ yolk)
merge = lambda X: Box("merge", X @ X, X)

# DisCoPy allows string diagrams to be defined as Python functions

@Diagram.from_callable(egg @ egg, white @ yolk)
def crack_two_eggs(x, y):
    (a, b), (c, d) = crack(x), crack(y)
    return (merge(white)(a, c), merge(yolk)(b, d))

# ... or in point-free style using parallel (@) and sequential (>>) composition

assert crack_two_eggs == crack @ crack\
  >> white @ Diagram.swap(yolk, white) @ yolk\
  >> merge(white) @ merge(yolk)

crack_two_eggs.draw()

crack_two_eggs.draw()

By default, DisCoPy diagrams are made of layers with exactly one box in between some (possibly empty) list of wires on its left- and right-hand side. In more abstract terms, they are arrows in a free premonoidal category where the tensor product is biased to the left, i.e.

f @ g = f @ g.dom >> f.cod @ g != f.dom @ g >> f @ g.cod

We can get more general diagrams by specifying the list of layers inside manually or by calling the method Diagram.foliation.

from discopy.monoidal import Layer

crack_two_eggs_at_once = crack_two_eggs.foliation()

assert crack_two_eggs_at_once == Diagram(
  dom=egg @ egg, cod=white @ yolk, inside=(
    Layer(Ty(), crack, Ty(), crack, Ty()),
    Layer(white, Diagram.swap(yolk, white), yolk),
    Layer(Ty(), merge(white), Ty(), merge(yolk), Ty())))

crack_two_eggs_at_once.draw()

crack_two_eggs_at_once.draw()

Example: Alice loves Bob

Snakes & Sentences

Wires can be bent using two special kinds of boxes: cups and caps, which satisfy the snake equations.

from discopy.drawing import Equation
from discopy.rigid import Ty, Id, Cup, Cap

x = Ty('x')
left_snake = x @ Cap(x.r, x) >> Cup(x, x.r) @ x
right_snake =  Cap(x, x.l) @ x >> x @ Cup(x.l, x)
assert left_snake.normal_form() == Id(x) == right_snake.normal_form()

Equation(left_snake, Id(x), right_snake).draw()

Equation(left_snake, Id(x), right_snake).draw()

In particular, DisCoPy can draw the grammatical structure of natural language sentences encoded as reductions in a pregroup grammar. See Lambek, From Word To Sentence (2008) for an introduction.

from discopy.grammar.pregroup import Ty, Word, Cup

s, n = Ty('s'), Ty('n')  # sentence and noun
Alice, Bob = Word('Alice', n), Word('Bob', n)
loves = Word('loves', n.r @ s @ n.l)

sentence = Alice @ loves @ Bob >> Cup(n, n.r) @ s @ Cup(n.l, n)
sentence.foliation().draw()

Alice loves Bob

Many other grammatical frameworks can be encoded as diagrams, e.g. cfg (context-free), categorial and dependency grammars.

Functors & Rewrites

Monoidal functors compute the meaning of a diagram, given an interpretation for each wire and for each box. In particular, tensor-valued functors evaluate a diagram as a tensor network using numpy, PyTorch, TensorFlow, TensorNetwork or JAX.

Applied to pregroup diagrams, DisCoPy implements the categorical compositional distributional (DisCoCat) models of [Clark, Coecke, Sadrzadeh (2008)](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.363.8703&rep=re

View on GitHub
GitHub Stars408
CategoryDevelopment
Updated1d ago
Forks72

Languages

Python

Security Score

100/100

Audited on Mar 25, 2026

No findings