Arrow#
- class discopy.cat.Arrow(dom, cod, boxes, _scan=True)[source]#
Bases:
object
Defines an arrow in a free dagger category.
- Parameters:
- 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]
- 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:
- 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:
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, [])
- 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:
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)