hypergraph#

Hypergraph categories.

Note

Spiders

We can check spider fusion, i.e. special commutative Frobenius algebra.

>>> x, y, z = types("x y z")
>>> split, merge = Spider(1, 2, x), Spider(2, 1, x)
>>> unit, counit = Spider(0, 1, x), Spider(1, 0, x)
  • (Co)commutative (co)monoid:

>>> assert unit @ Id(x) >> merge == Id(x) == Id(x) @ unit >> merge
>>> assert merge @ Id(x) >> merge == Id(x) @ merge >> merge
>>> assert Swap(x, x) >> merge == merge
>>> assert split >> counit @ Id(x) == Id(x) == split >> Id(x) @ counit
>>> assert split >> split @ Id(x) == split >> Id(x) @ split
>>> assert split >> Swap(x, x) == split
  • Frobenius:

>>> assert split @ Id(x) >> Id(x) @ merge\
...     == merge >> split\
...     == Id(x) @ split >> merge @ Id(x)\
...     == Spider(2, 2, x)
  • Speciality:

>>> assert split >> merge == Spider(1, 1, x) == Id(x)
  • Coherence:

>>> assert Spider(0, 1, x @ x) == unit @ unit
>>> assert Spider(2, 1, x @ x) == Id(x) @ Swap(x, x) @ Id(x) >> merge @ merge
>>> assert Spider(1, 0, x @ x) == counit @ counit
>>> assert Spider(1, 2, x @ x) == split @ split >> Id(x) @ Swap(x, x) @ Id(x)

Snakes

Special commutative Frobenius algebras imply compact-closedness, i.e.

  • Snake equations:

>>> left_snake = lambda x: Cap(x, x.r) @ Id(x) >> Id(x) @ Cup(x.r, x)
>>> right_snake = lambda x: Id(x) @ Cap(x.r, x) >> Cup(x, x.r) @ Id(x)
>>> assert left_snake(x) == Id(x) == right_snake(x)
>>> assert left_snake(x @ y) == Id(x @ y) == right_snake(x @ y)
  • Yanking (a.k.a. Reidemeister move 1):

>>> right_loop = lambda x: Id(x) @ Cap(x, x.r)\
...     >> Swap(x, x) @ Id(x.r) >> Id(x) @ Cup(x, x.r)
>>> left_loop = lambda x: Cap(x.r, x) @ Id(x)\
...     >> Id(x.r) @ Swap(x, x) >> Cup(x.r, x) @ Id(x)
>>> top_loop = lambda x: Cap(x, x.r) >> Swap(x, x.r)
>>> bottom_loop = lambda x: Swap(x, x.r) >> Cup(x.r, x)
>>> reidemeister1 = lambda x:\
...     top_loop(x) == Cap(x.r, x) and bottom_loop(x) == Cup(x, x.r)\
...     and left_loop(x) == Id(x) == right_loop(x)
>>> assert reidemeister1(x) and reidemeister1(x @ y) and reidemeister1(Ty())
  • Coherence:

>>> assert Cap(x @ y, y @ x)\
...     == Cap(x, x) @ Cap(y, y) >> Id(x) @ Swap(x, y @ y)\
...     == Spider(0, 2, x @ y) >> Id(x @ y) @ Swap(x, y)
>>> assert Cap(x, x) >> Cup(x, x) == Spider(0, 0, x)

Swaps

We can also check that the axioms for symmetry hold on the nose.

  • Involution (a.k.a. Reidemeister move 2):

>>> reidermeister2 = lambda x, y: Swap(x, y) >> Swap(y, x) == Id(x @ y)
>>> assert reidermeister2(x, y) and reidermeister2(x @ y, z)
  • Yang-Baxter (a.k.a. Reidemeister move 3):

>>> left = Swap(x, y) @ Id(z)\
...     >> Id(y) @ Swap(x, z)\
...     >> Swap(y, z) @ Id(x)
>>> right = Id(x) @ Swap(y, z)\
...     >> Swap(x, z) @ Id(y)\
...     >> Id(z) @ Swap(x, y)
>>> assert left == right
  • Coherence (a.k.a. pentagon equations):

>>> assert Swap(x, y @ z) == Swap(x, y) @ Id(z) >> Id(y) @ Swap(x, z)
>>> assert Swap(x @ y, z) == Id(x) @ Swap(y, z) >> Swap(x, z) @ Id(y)
  • Naturality:

>>> f = Box("f", x, y)
>>> assert f @ Id(z) >> Swap(f.cod, z) == Swap(f.dom, z) >> Id(z) @ f
>>> assert Id(z) @ f >> Swap(z, f.cod) == Swap(z, f.dom) >> f @ Id(z)

discopy.hypergraph.pushout(left, right, ...)

Computes the pushout of two finite mappings using connected components.

discopy.hypergraph.Ty(*t)

Self-dual types in a hypergraph diagram.

discopy.hypergraph.Diagram(dom, cod, boxes, ...)

Diagram in a hypergraph category.

discopy.hypergraph.Box(name, dom, cod, **params)

Box in a discopy.hypergraph.Diagram.

discopy.hypergraph.Id([dom])

Identity diagram.

discopy.hypergraph.Swap(left, right)

Swap diagram.

discopy.hypergraph.Spider(n_legs_in, ...)

Spider diagram.

discopy.hypergraph.Cup(left, right)

Cup diagram.

discopy.hypergraph.Cap(left, right)

Cap diagram.