Layer#

class discopy.symmetric.Layer(*inside)[source]#

Bases: discopy.monoidal.Layer

A tensor product \(s_0 \otimes f_1 \otimes \dots \otimes f_n \otimes s_n\) of generators \(f_i\) and routing \(s_i\), where routing is a type when it is the identity and a Permutation otherwise. Swap is a generator, distinct from [1, 0].

Routing components are coalesced, so a permutation given between two types becomes one permutation and the layer stays alternating. An identity permutation is stored as its type, hence a layer with a single permutation always permutes: the identity is the empty diagram, not a layer.

A layer with no crossing is stored exactly as a discopy.monoidal.Layer.

Parameters:

inside – Alternating routing and generators, starting and ending with routing.

Examples

>>> x, y = Ty('x'), Ty('y')
>>> f, perm = Box('f', x, y), Permutation(x @ y, [1, 0])
>>> assert Layer(x, f, y).boxes_or_types == (x, f, y)
>>> assert Layer(x, f, perm).boxes_or_types == (x, f, perm)
>>> assert Layer(x, perm, y) == Layer(Permutation(x @ x @ y @ y,
...     [0, 2, 1, 3]))

Forgetting the distinction between routing and generators gives the ordinary alternating view of a discopy.monoidal.Layer, which is what boxes, boxes_and_offsets and the rewrites indexed by them are computed from.

>>> assert Layer(x, f, perm).boxes_and_types == (
...     x, f, Ty(), perm, Ty())
>>> assert Layer(x, f, perm).boxes_and_offsets == [(f, 1), (perm, 2)]
static is_routing(value)[source]#

Whether a component routes wires rather than generating them.

>>> x = Ty('x')
>>> assert Layer.is_routing(x) and Layer.is_routing(
...     Permutation(x @ x, [1, 0]))
>>> assert not Layer.is_routing(Box('f', x, x))
Return type:

bool

property is_structural: bool#

Whether the layer routes its wires non-trivially, i.e. one of its routing components is a Permutation rather than a type.

>>> x, y = Ty('x'), Ty('y')
>>> assert Layer(Permutation(x @ y, [1, 0])).is_structural
>>> assert not Layer(x, Box('f', x, y), y).is_structural
property boxes_and_types#

Every permutation as an ordinary box between empty types.

classmethod cast(box)[source]#

Turn a generator or a permutation into a layer.

Parameters:

box (Box) –

Return type:

Layer

tensor(other)[source]#

Tensor layers, coalescing their touching routing.

Parameters:

other (Layer) –

Return type:

Layer