hypergraph
Contents
hypergraph#
The free hypergraph category with diagrams encoded as cospans of hypergraphs.
Summary#
Diagram in a hypergraph category. |
|
Box in a |
Functions
Computes the pushout of two finite mappings using connected components. |
Axioms#
Spiders
We can check spider fusion, i.e. special commutative Frobenius algebra.
>>> x, y, z = map(Ty, "xyz")
>>> split, merge = spiders(1, 2, x), spiders(2, 1, x)
>>> unit, counit = spiders(0, 1, x), spiders(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)\
... == spiders(2, 2, x)
Speciality:
>>> assert split >> merge == spiders(1, 1, x) == Id(x)
Coherence:
>>> assert spiders(0, 1, x @ x) == unit @ unit
>>> assert spiders(2, 1, x @ x) == Id(x) @ Swap(x, x) @ Id(x) >> merge @ merge
>>> assert spiders(1, 0, x @ x) == counit @ counit
>>> assert spiders(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: caps(x, x.r) @ Id(x) >> Id(x) @ cups(x.r, x)
>>> right_snake = lambda x: Id(x) @ caps(x.r, x) >> cups(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) @ caps(x, x.r)\
... >> Swap(x, x) @ Id(x.r) >> Id(x) @ cups(x, x.r)
>>> left_loop = lambda x: caps(x.r, x) @ Id(x)\
... >> Id(x.r) @ Swap(x, x) >> cups(x.r, x) @ Id(x)
>>> top_loop = lambda x: caps(x, x.r) >> Swap(x, x.r)
>>> bottom_loop = lambda x: Swap(x, x.r) >> cups(x.r, x)
>>> reidemeister1 = lambda x:\
... top_loop(x) == caps(x.r, x) and bottom_loop(x) == cups(x, x.r)\
... and left_loop(x) == Id(x) == right_loop(x)
>>> assert reidemeister1(x) and reidemeister1(x @ y) and reidemeister1(Ty())
Coherence:
>>> assert caps(x @ y, y @ x)\
... == caps(x, x) @ caps(y, y) >> Id(x) @ Swap(x, y @ y)\
... == spiders(0, 2, x @ y) >> Id(x @ y) @ Swap(x, y)
>>> assert caps(x, x) >> cups(x, x) == spiders(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)