Drawing#
- class discopy.drawing.drawing.Drawing(inside, dom, cod, boxes=(), width=0, height=0, _check=True)[source]#
Bases:
Composable
,Whiskerable
A drawing is a plane graph with designated input and output types.
- Parameters:
inside (PlaneGraph) – The plane graph underlying the drawing.
dom (monoidal.Ty) – The domain of the drawing, i.e. its input type.
cod (monoidal.Ty) – The codomain of the drawing, i.e. its output type.
boxes (tuple[monoidal.Box, ...]) – The boxes inside the drawing.
width (float) – The width of the drawing.
height (float) – The height of the drawing.
_check (bool) – Whether to call
validate_attributes()
.
Summary
Check that the attributes of a drawing are consistent.
draw
(**params)Call
add_box_corners()
thenbackend.draw()
.from_box
(box)Draw a diagram with just one box.
id
([dom, length])Draw the identity diagram.
then
(other[, draw_step_by_step])Draw one diagram composed with another.
tensor
(other)Draw two diagrams side by side.
dagger
()The reflection of a drawing along the the horizontal axis.
bubble
([dom, cod, name, width, height, ...])Draw a closed line around a drawing, with some wires coming in and out.
frame
(*others[, dom, cod, name, draw_vertically])>>> from discopy.monoidal import *
- validate_attributes()[source]#
Check that the attributes of a drawing are consistent.
>>> from discopy.monoidal import Ty, Id >>> x = Ty('x') >>> drawing = Id(x).to_drawing() >>> drawing.add_edges([(Node("cod", i=0, x=x), Node("dom", i=0, x=x))]) >>> drawing.validate_attributes() Traceback (most recent call last): ... ValueError: Wrong edge Node('cod', i=0, x=x) -> Node('dom', i=0, x=x)
- draw(**params)[source]#
Call
add_box_corners()
thenbackend.draw()
.
- union(other, dom, cod, width=None, height=None, _check=True)[source]#
Take the union of two drawings, assuming nodes are distinct.
- add_nodes(positions)[source]#
Add nodes to the graph given their positions.
- Parameters:
positions (dict[Node, Point]) –
- relabel_nodes(mapping={}, positions={}, copy=True, _check=False)[source]#
Relabel nodes and/or their positions.
- make_space(space, x, y_min=None, y_max=None, exclusive=False, copy=False)[source]#
Make some horizontal space after position x for all nodes between y_min and y_max (inclusive).
Example
>>> from discopy.monoidal import Ty, Box >>> x, y, z = map(Ty, "xyz") >>> f = Drawing.from_box(Box('f', x @ y, z)) >>> f.make_space(2, 0.5, 0.75, 1.0, copy=True).draw( ... aspect='equal', path="docs/_static/drawing/make-space.png")
- property is_identity#
A drawing with no boxes is the identity.
- property is_empty#
A drawing with no boxes and no wires is empty.
- property is_box#
Whether the drawing is just one box.
- property is_layer#
Whether the drawing is just one box with wires on both sides.
- property box#
Syntactic sugar for self.boxes[0] when self.is_box
- property left_is_whiskered#
Whether self = x @ f for some non-empty type x.
- property right_is_whiskered#
Whether self = f @ x for some non-empty type x.
- static from_box(box)[source]#
Draw a diagram with just one box.
>>> from discopy.monoidal import Ty, Box >>> x, y, z = map(Ty, "xyz") >>> f = Box('f', x, y @ z) >>> assert f.to_drawing() == Drawing.from_box(f) >>> for ps in f.to_drawing().positions.items(): print(*ps) Node('box', box=f, j=0) Point(x=1.0, y=0.5) Node('dom', i=0, x=x) Point(x=1.0, y=1) Node('box_dom', i=0, j=0, x=x) Point(x=1.0, y=0.75) Node('box_cod', i=0, j=0, x=y) Point(x=0.5, y=0.25) Node('box_cod', i=1, j=0, x=z) Point(x=1.5, y=0.25) Node('cod', i=0, x=y) Point(x=0.5, y=0) Node('cod', i=1, x=z) Point(x=1.5, y=0) >>> f.draw(path="docs/_static/drawing/box.png")
- Parameters:
box (monoidal.Box) –
- Return type:
- static id(dom=None, length=0)[source]#
Draw the identity diagram.
>>> from discopy.monoidal import Ty >>> Drawing.id(Ty()).draw(path="docs/_static/drawing/empty.png")
>>> Drawing.id(Ty('x')).draw(path="docs/_static/drawing/idx.png")
>>> Drawing.id(Ty('x', 'y')).draw(path="docs/_static/drawing/idxy.png")
- Parameters:
dom (monoidal.Ty) –
- Return type:
- then(other, draw_step_by_step=False)[source]#
Draw one diagram composed with another.
This is done by calling
make_space()
to align the output wires of self and the input wires of other while keeping them straight.Example
>>> from discopy.monoidal import Ty, Box, Diagram >>> x = Ty('x') >>> f = Drawing.from_box(Box('f', x, x @ x @ x)) >>> g = Drawing.from_box(Box('g', x @ x, x)) >>> u = Drawing.from_box(Box('u', Ty(), x ** 3)) >>> v = Drawing.from_box(Box('v', x ** 7, Ty()))
>>> top, bottom = u >> g @ f, g @ f @ f >> v >>> Diagram.to_gif( ... *top.then(bottom, draw_step_by_step=True), loop=True, ... draw_type_labels=False, draw_box_labels=False, ... path="docs/_static/drawing/composition.gif") <IPython.core.display.HTML object>
- stretch(y, copy=True)[source]#
Stretch input and output wires to increase the height of a diagram by a given length. . .. admonition:: Example
>>> from discopy.monoidal import Box >>> f = Drawing.from_box(Box('f', 'x', 'x')) >>> f.stretch(2).draw(path="docs/_static/drawing/stretch.png")
- tensor(other)[source]#
Draw two diagrams side by side.
Example
>>> from discopy.monoidal import Box >>> f = Drawing.from_box(Box('f', 'x', 'x')) >>> d = (f >> f >> f) @ (f >> f) >>> d.draw(path="docs/_static/drawing/tensor.png")
- static bubble_opening(dom, arg_dom, left, right, frame_boundary=False)[source]#
Construct the opening of a bubble, i.e. a box drawn as wires.
>>> from discopy.monoidal import Ty >>> x, y, z = map(Ty, "xyz") >>> Drawing.bubble_opening(x, y, z, Ty("")).draw( ... path="docs/_static/drawing/bubble-opening.png")
- static bubble_closing(arg_cod, cod, left, right, frame_boundary=False)[source]#
Construct the closing of a bubble, i.e. a box drawn as wires.
>>> from discopy.monoidal import Ty >>> x, y, z = map(Ty, "xyz") >>> Drawing.bubble_closing(x, y, z, Ty("")).draw( ... path="docs/_static/drawing/bubble-closing.png")
- static frame_opening(dom, arg_dom, left, right)[source]#
Construct the opening of a frame as the opening of a bubble squashed to zero height so that it looks like the upper half of a rectangle.
>>> from discopy.monoidal import Ty >>> x, y, z = map(Ty, "xyz") >>> Drawing.frame_opening(x, y, z, Ty("")).draw( ... path="docs/_static/drawing/frame-opening.png")
- static frame_closing(arg_cod, cod, left, right)[source]#
Construct the closing of a frame as the closing of a bubble squashed to zero height so that it looks like the lower half of a rectangle.
>>> from discopy.monoidal import Ty >>> x, y, z = map(Ty, "xyz") >>> Drawing.frame_closing(x, y, z, Ty("")).draw( ... path="docs/_static/drawing/frame-closing.png")
- bubble(dom=None, cod=None, name=None, width=None, height=None, draw_as_square=False)[source]#
Draw a closed line around a drawing, with some wires coming in and out.
- Parameters:
dom (monoidal.Ty) – The wires coming into the bubble.
cod (monoidal.Ty) – The wires coming out of the bubble.
name (str) – The label of the bubble, drawn on the top left.
width –
- Return type:
>>> from discopy.symmetric import * >>> a, b, c, d = map(Ty, "abcd") >>> f = Box('f', a @ b, c @ d).to_drawing() >>> f.bubble(d @ c @ c, b @ a @ a, name="g").draw( ... path="docs/_static/drawing/bubble-drawing.png")
- frame(*others, dom=None, cod=None, name=None, draw_vertically=False)[source]#
>>> from discopy.monoidal import * >>> x, y = Ty('x'), Ty('y') >>> f, g, h = Box('f', x, y ** 3), Box('g', y, y @ y), Box('h', x, y) >>> f.bubble(dom=x @ x, cod=y @ y, name="b", draw_as_frame=True ... ).draw(path="docs/_static/drawing/single-frame.png")
>>> Bubble(f, g, h >> h[::-1], dom=x, cod=y @ y ... ).draw(path="docs/_static/drawing/horizontal-frame.png")
>>> Bubble(f, g, h, dom=x, cod=y @ y, draw_vertically=True ... ).draw(path="docs/_static/drawing/vertical-frame.png")