Diagram#
- class discopy.symmetric.Diagram(inside, dom, cod, _scan=True)[source]#
Bases:
discopy.balanced.Diagram,discopy.abc.SymmetricCategoryA symmetric diagram is a balanced diagram with
Swapboxes.- Parameters:
inside (Layer) – The layers inside the diagram.
dom (monoidal.Ty) – The domain of the diagram, i.e. its input.
cod (monoidal.Ty) – The codomain of the diagram, i.e. its output.
Note
Equality and hashing of symmetric diagrams is always syntactic: two diagrams are equal if and only if they are built from the same layers. To compare diagrams up to hypergraph isomorphism (swaps, spider fusion, trace plumbing) use
from discopy.symmetric import Equation, i.e. theEquationwhoseup_toisto_hypergraph.>>> x, y = Ty("x"), Ty("y") >>> a = Swap(x, y) >> Swap(y, x) >>> assert a != Id(x @ y) >>> assert Equation(a, Id(x @ y))
Note
Symmetric diagrams can be defined using the standard syntax for functions.
>>> x = Ty('x') >>> f = Box('f', x @ x, x) >>> g = Box('g', x, x @ x)
>>> @Diagram.from_callable(x @ x @ x, x @ x @ x) ... def diagram(x0, x1, x2): ... x3 = f(x2, x0) ... x4, x5 = g(x1) ... return x5, x3, x4 >>> diagram.draw(wire_labels=False, ... doctest='docs/_static/symmetric/decorator.svg')
Every variable must be used exactly once or this will raise an error.
>>> from pytest import raises >>> from discopy.utils import AxiomError
>>> with raises(AxiomError) as err: ... Diagram.from_callable(x, x @ x)(lambda x: (x, x)) >>> print(err.value) symmetric.Diagram has no cups or caps for the wiring of this map.
>>> with raises(AxiomError) as err: ... Diagram.from_callable(x, Ty())(lambda x: ()) >>> print(err.value) symmetric.Diagram has no cups or caps for the wiring of this map.
Note
As for
discopy.balanced.Diagram, our symmetric diagrams are traced by default. However now we have that the axioms for trace hold on the nose.Note
The swaps of atomic types are generated by
swap_factory, which subclasses should set to their own subclass ofSwap. It is the braid of a symmetric category, i.e.braided.Diagram.braid_factoryreads it:>>> class Permutation(Diagram): ... >>> class Transposition(Swap, Permutation): ... >>> Permutation.swap_factory = Transposition >>> assert Permutation.braid_factory is Transposition
- property is_plumbing: bool#
Whether one of the layers plumbs its wires non-trivially.
- classmethod swap(left, right)[source]#
The diagram that swaps the
leftandrightwires.- Parameters:
- Return type:
Note
This calls
balanced.hexagon()andswap_factory.
- classmethod permutation(xs, doms=None)[source]#
The diagram that encodes a given permutation as a composition of swaps.
- classmethod from_permutation(perm, dom=None)[source]#
Encode a permutation natively when the category has a matching
Permutationfactory. Descendant categories without one use their own swap decomposition instead. An identity permutation always becomes the identity diagram.- Parameters:
perm (Sequence[int]) – A permutation, as a sequence of integers or a
finset.Permutation.dom (Ty) – A type of the same length as
perm, default isNat(len(perm)).
- Return type:
Examples
>>> x, y, z = Ty('x'), Ty('y'), Ty('z') >>> assert Diagram.from_permutation([1, 2, 0], x @ y @ z)\ ... == Permutation(x @ y @ z, [1, 2, 0]) >>> assert Diagram.from_permutation( ... [0, 1, 2], x @ y @ z) == Id(x @ y @ z)
- permute(*xs)[source]#
Post-compose with a permutation written as the historical swap decomposition. Use
from_permutation()to construct a nativePermutationbox.- Parameters:
xs (int) – A list of integers representing a permutation.
- Return type:
Examples
>>> x, y, z = Ty('x'), Ty('y'), Ty('z') >>> assert Id(x @ y @ z).permute(2, 0, 1).cod == z @ x @ y
- foliation()[source]#
Merge independent generators, keeping native plumbing compact.
A hypergraph forgets that plumbing is native, so a diagram with a
Permutationis foliated by merging its layers instead.>>> x, y = Ty('x'), Ty('y') >>> perm = Permutation(x @ y, [1, 0]) >>> assert perm.foliation() == perm
- depth()[source]#
The depth of a symmetric diagram.
Examples
>>> x = Ty('x') >>> f = Box('f', x, x) >>> assert Id(x).depth() == Id().depth() == 0 >>> assert f.depth() == (f @ f).depth() == 1 >>> assert (f @ f >> Swap(x, x)).depth() == 1 >>> assert (f >> f).depth() == 2 and (f >> f >> f).depth() == 3
- permutation_factory#
alias of
Permutation
- trace_factory#
alias of
Trace