Arrow#

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

Bases: Composable[Ob]

An arrow is a tuple of composable boxes inside with a pair of objects dom and cod as domain and codomain.

Parameters:
  • inside (tuple[Box, ...]) – The tuple of boxes inside an arrow.

  • dom (T) – The domain of an arrow, i.e. its input.

  • cod (T) – The codomain of an arrow, i.e. output

  • _scan (bool) – Whether to check composition.

Summary

id([dom])

The identity arrow with the empty tuple inside, called with Id.

then(*others)

Sequential composition, called with >> and <<.

dagger()

Contravariant involution, called with [::-1].

bubble(**params)

Unary operator on homsets.

Tip

For code clarity, it is recommended not to initialise arrows directly but to use Arrow.id() and Arrow.then() instead. For example:

>>> x, y, z = map(Ob, "xyz")
>>> f, g = Box('f', x, y), Box('g', y, z)
>>> arrow = Arrow.id(x).then(f, g)  # Do this...
>>> arrow_ = Arrow((f, g), x, z)    # ...rather than that!
>>> assert arrow == arrow_

Note

Arrows can be indexed and sliced using square brackets. Indexing behaves like that of strings, i.e. when we index an arrow we get an arrow back.

>>> assert (f >> g)[0] == f and (f >> g)[1] == g
>>> assert f[:0] == Arrow.id(f.dom)
>>> assert f[1:] == Arrow.id(f.cod)

Note

If dom or cod are not instances of ty_factory, they are automatically cast. This means one can use e.g. int instead of Ob, see monoidal.PRO.

ty_factory#

alias of Ob

classmethod id(dom=None)[source]#

The identity arrow with the empty tuple inside, called with Id.

Parameters:

dom (Ob | None) – The domain (and codomain) of the identity.

Return type:

Arrow

Note

If dom is not provided, we use the default value of ty_factory.

Example

>>> assert Arrow.id() == Id() == Id(Ob())
>>> assert Arrow.id('x') == Id('x') == Id(Ob('x'))
then(*others)[source]#

Sequential composition, called with >> and <<.

Parameters:

others (Arrow) – The other arrows to compose.

Raises:

AxiomError – Whenever self and others do not compose.

Return type:

Arrow

dagger()[source]#

Contravariant involution, called with [::-1].

Return type:

Arrow

classmethod zero(dom, cod)[source]#

Return the empty sum with a given domain and codomain.

Parameters:
  • dom – The domain of the empty sum.

  • cod – The codomain of the empty sum.

bubble(**params)[source]#

Unary operator on homsets.

Return type:

Bubble

property free_symbols: set[sympy.Symbol]#

The free sympy symbols in an arrow.

Example

>>> 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]})
>>> diagram = (f >> g).bubble() + Id(x)
>>> assert diagram.free_symbols == {phi, psi}
subs(*args)[source]#

Substitute a variable by an expression.

Parameters:
  • var (sympy.Symbol) – The subtituted variable.

  • expr (sympy.Expr) – The substituting expression.

Return type:

Arrow

Tip

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

Example

>>> 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]#

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

Parameters:
  • symbols (sympy.Symbol) – The inputs of the function.

  • kwargs – Passed to sympy.lambdify.

Return type:

Callable

Example

>>> 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)
to_tree()[source]#

Serialise a DisCoPy arrow, see discopy.utils.dumps().

Example

>>> from pprint import PrettyPrinter
>>> pprint = PrettyPrinter(indent=4, width=70, sort_dicts=False).pprint
>>> f = Box('f', 'x', 'y', data=42)
>>> pprint((f >> f[::-1]).to_tree())
{   'factory': 'cat.Arrow',
    'inside': [   {   'factory': 'cat.Box',
                      'name': 'f',
                      'dom': {'factory': 'cat.Ob', 'name': 'x'},
                      'cod': {'factory': 'cat.Ob', 'name': 'y'},
                      'data': 42},
                  {   'factory': 'cat.Box',
                      'name': 'f',
                      'dom': {'factory': 'cat.Ob', 'name': 'y'},
                      'cod': {'factory': 'cat.Ob', 'name': 'x'},
                      'is_dagger': True,
                      'data': 42}],
    'dom': {'factory': 'cat.Ob', 'name': 'x'},
    'cod': {'factory': 'cat.Ob', 'name': 'x'}}
Return type:

dict

classmethod from_tree(tree)[source]#

Decode a serialised DisCoPy arrow, see discopy.utils.loads().

Parameters:

tree (dict) – DisCoPy serialisation.

Return type:

Arrow

Example

>>> f = Box('f', 'x', 'y', data=42)
>>> assert Arrow.from_tree((f >> f[::-1]).to_tree()) == f >> f[::-1]
bubble_factory#

alias of Bubble

factory#

alias of Arrow

sum_factory#

alias of Sum