Layer#
- class discopy.monoidal.Layer(*inside, normalise=True)[source]#
Bases:
discopy.cat.Box,discopy.abc.ColouredMonoidA layer is a tensor product of boxes and plumbing, i.e. non-empty types.
- Parameters:
inside (Ty | Box) – Boxes and plumbing, with at least one box.
normalise (bool) – Whether to type check the components and normalise them, i.e. remove empty plumbing and tensor consecutive types. The methods below build layers that satisfy this by construction and pass
False, which skips every pass overinsideso that tensoringnlayers takes linear rather than quadratic time.
- classmethod id(dom=None)[source]#
There is no identity layer: a layer has at least one box, and a layer of empty plumbing would denote the identity diagram, which is the empty sequence of layers rather than a one-element one.
Whiskering merges a type into the boundary instead, see
whisker()andtensor().
- classmethod whisker(other)[source]#
A type stays a type, which
tensor()merges into the boundary; anything else is embedded as a layer.
- classmethod unit(colour=None)[source]#
The unit of the layer product, i.e. the empty type on a colour.
A layer has at least one box, so the unit is not one: it lands in the types rather than in the layers, which
tensor()accepts.Example
>>> x = Ty('x') >>> f = Box('f', x, x) >>> unit, layer = Layer.unit(), Layer(f) >>> assert unit @ layer == layer == layer @ unit
- static check(inside)[source]#
Check that the components are types and boxes whose domains and codomains tensor, i.e. one linear pass comparing the colours of each adjacent pair on both rows.
- classmethod normalise(inside)[source]#
The canonical word of boxes and non-empty plumbing: either we append or we tensor with the last element.
- property boxes_and_types#
The layer expanded to alternating types and boxes.
Empty types are inserted around consecutive boxes for compatibility with algorithms defined on the old layer representation.
- tensor(other)[source]#
Tensor another layer on the right, normalising the common boundary.
A type is merged into the boundary rather than embedded as a layer, so that whiskering never builds one out of empty plumbing.
- property boxes_and_offsets: list[tuple[Box, int]]#
The offsets of each box inside the layer.
Example
>>> a, b, c, d, e = map(Ty, "abcde") >>> f, g = Box('f', a, b), Box('g', c, d) >>> assert Layer(e, f, e, g, e).boxes_and_offsets == [(f, 1), (g, 3)]
- merge(other)[source]#
Merge two layers into one or raise
AxiomError, used byDiagram.foliation().Example
>>> a, b, c, d, e = map(Ty, "abcde") >>> f, g = Box('f', a, b), Box('g', c, d) >>> layer0 = Layer(e, f, e @ c @ e) >>> layer1 = Layer(e @ b @ e, g, e) >>> assert layer0.merge(layer1) == Layer(e, f, e, g, e)