Arrow#

class discopy.cat.Arrow(dom, cod, boxes, _scan=True)[source]#

Bases: object

Defines an arrow in a free dagger category.

Parameters:
  • dom (cat.Ob) – Domain of the arrow.

  • cod (cat.Ob) – Codomain of the arrow.

  • boxes (list of Arrow) – Boxes of the arrow.

Raises:

cat.AxiomError – Whenever the boxes do not compose.

Examples

>>> x, y, z = Ob('x'), Ob('y'), Ob('z')
>>> f, g, h = Box('f', x, y), Box('g', y, z), Box('h', z, x)
>>> arrow = Arrow(x, x, [f, g, h])
>>> print(arrow[::-1])
h[::-1] >> g[::-1] >> f[::-1]
static upgrade(old)[source]#

Allows class inheritance.

property dom#

The domain of an arrow is immutable.

>>> arrow = Arrow(Ob('x'), Ob('x'), [])
>>> assert arrow.dom == Ob('x')
>>> arrow.dom = Ob('y')  
Traceback (most recent call last):
...
AttributeError: can't set attribute...
property cod#

The codomain of an arrow is immutable.

>>> arrow = Arrow(Ob('x'), Ob('x'), [])
>>> assert arrow.cod == Ob('x')
>>> arrow.cod = Ob('y')  
Traceback (most recent call last):
...
AttributeError: can't set attribute...
property boxes#

The list of boxes in an arrow is immutable. Use composition instead.

>>> f = Box('f', Ob('x'), Ob('y'))
>>> arrow = Arrow(Ob('x'), Ob('x'), [])
>>> arrow.boxes.append(f)  # This does nothing.
>>> assert f not in arrow.boxes
then(*others)[source]#

Returns the composition of self with arrows others.

This method is called using the binary operators >> and <<:

>>> x, y, z = Ob('x'), Ob('y'), Ob('z')
>>> f, g, h = Box('f', x, y), Box('g', y, z), Box('h', z, x)
>>> assert f.then(g) == f >> g == g << f
Parameters:

others (cat.Arrow) – such that self.cod == others[0].dom and all(x.cod == y.dom for x, y in zip(others, others[1:]).

Returns:

arrow – such that arrow.boxes == self.boxes + sum(other.boxes for other in others, []).

Return type:

cat.Arrow

Raises:

cat.AxiomError – whenever self and others do not compose.

Notes

We can check the axioms of categories (i.e. composition is unital and associative):

>>> assert f >> Id(y) == f == Id(x) >> f
>>> assert (f >> g) >> h == f >> (g >> h)
dagger()[source]#

Returns the dagger of self, this method is called using the unary operator [::-1], i.e. self[::-1] == self.dagger().

Returns:

arrow – Such that arrow.boxes == [box[::-1] for box in self[::-1]].

Return type:

cat.Arrow

Notes

We can check the axioms of dagger (i.e. a contravariant involutive identity-on-objects endofunctor):

>>> x, y, z = Ob('x'), Ob('y'), Ob('z')
>>> f, g = Box('f', x, y), Box('g', y, z)
>>> assert f[::-1][::-1] == f
>>> assert Id(x)[::-1] == Id(x)
>>> assert (f >> g)[::-1] == g[::-1] >> f[::-1]
static id(dom)[source]#

Returns the identity arrow on dom.

>>> x = Ob('x')
>>> assert Arrow.id(x) == Id(x) == Arrow(x, x, [])
Parameters:

dom (cat.Ob) – Any object.

Return type:

cat.Id

property free_symbols#

Free symbols in a Arrow.

>>> from sympy.abc import phi, psi
>>> x, y = Ob('x'), Ob('y')
>>> f = Box('f', x, y, data={"Alice": [phi + 1]})
>>> g = Box('g', y, x, data={"Bob": [psi / 2]})
>>> assert (f >> g).free_symbols == {phi, psi}
subs(*args)[source]#

Substitute a variable by an expression.

Parameters:
  • var (sympy.Symbol) – Subtituted variable.

  • expr (sympy.Expr) – Substituting expression.

Returns:

arrow

Return type:

Arrow

Note

You can give a list of (var, expr) pairs for multiple substitution.

Examples

>>> from sympy.abc import phi, psi
>>> x, y = Ob('x'), Ob('y')
>>> f = Box('f', x, y, data={"Alice": [phi + 1]})
>>> g = Box('g', y, x, data={"Bob": [psi / 2]})
>>> assert (f >> g).subs(phi, phi + 1) == f.subs(phi, phi + 1) >> g
>>> assert (f >> g).subs(phi, 1) == f.subs(phi, 1) >> g
>>> assert (f >> g).subs(psi, 1) == f >> g.subs(psi, 1)
lambdify(*symbols, **kwargs)[source]#

Turns a symbolic diagram into a function from parameters to diagram.

Parameters:
  • symbols (list of sympy.Symbol) – Inputs of the lambda.

  • kwargs (any) – Passed to sympy.lambdify

Returns:

lambda – Takes concrete values returns concrete diagrams.

Return type:

callable

Examples

>>> from sympy.abc import phi, psi
>>> x, y, z = Ob('x'), Ob('y'), Ob('z')
>>> f, g = Box('f', x, y, data=phi), Box('g', y, z, data=psi)
>>> assert f.lambdify(psi)(42) == f
>>> assert (f >> g).lambdify(phi, psi)(42, 43)\
...     == Box('f', x, y, data=42) >> Box('g', y, z, data=43)
bubble(**params)[source]#

Returns a cat.Bubble with the diagram inside.

to_tree()[source]#

Encodes an arrow as a tree.

classmethod from_tree(tree)[source]#

Decodes a tree as an arrow.

bubble_factory#

alias of Bubble

sum#

alias of Sum