def tensor(self, *others): """ Returns the horizontal composition of 'self' with a diagram 'other'. This method is called using the binary operator `@`: >>> x, y, z, w = Ty('x'), Ty('y'), Ty('z'), Ty('w') >>> f0, f1 = Box('f0', x, y), Box('f1', z, w) >>> assert f0 @ f1 == f0.tensor(f1) == f0 @ Id(z) >> Id(y) @ f1 Parameters ---------- other : :class:`Diagram` Returns ------- diagram : :class:`Diagram` the tensor of 'self' and 'other'. """ if not others: return self if len(others) > 1: return self.tensor(others[0]).tensor(*others[1:]) other = others[0] if not isinstance(other, Diagram): raise TypeError(messages.type_err(Diagram, other)) dom, cod = self.dom @ other.dom, self.cod @ other.cod boxes = self.boxes + other.boxes offsets = self.offsets + [n + len(self.cod) for n in other.offsets] layers = cat.Id(dom) for left, box, right in self.layers: layers = layers >> Layer(left, box, right @ other.dom) for left, box, right in other.layers: layers = layers >> Layer(self.cod @ left, box, right) return Diagram(dom, cod, boxes, offsets, layers=layers)
def __init__(self, dom, cod, boxes, offsets, layers=None): if not isinstance(dom, Ty): raise TypeError(messages.type_err(Ty, dom)) if not isinstance(cod, Ty): raise TypeError(messages.type_err(Ty, cod)) if len(boxes) != len(offsets): raise ValueError(messages.boxes_and_offsets_must_have_same_len()) if layers is None: layers = cat.Id(dom) for box, off in zip(boxes, offsets): if not isinstance(box, Diagram): raise TypeError(messages.type_err(Diagram, box)) if not isinstance(off, int): raise TypeError(messages.type_err(int, off)) left = layers.cod[:off] if layers else dom[:off] right = layers.cod[off + len(box.dom):]\ if layers else dom[off + len(box.dom):] layers = layers >> Layer(left, box, right) layers = layers >> cat.Id(cod) self._layers, self._offsets = layers, tuple(offsets) super().__init__(dom, cod, boxes, _scan=False)
def tensor(self, other=None, *rest): """ Returns the horizontal composition of 'self' with a diagram 'other'. This method is called using the binary operator `@`: >>> x, y, z, w = Ty('x'), Ty('y'), Ty('z'), Ty('w') >>> f0, f1 = Box('f0', x, y), Box('f1', z, w) >>> assert f0 @ f1 == f0.tensor(f1) == f0 @ Id(z) >> Id(y) @ f1 >>> (f0 @ f1).draw( ... figsize=(2, 2), ... path='docs/_static/imgs/monoidal/tensor-example.png') .. image:: ../_static/imgs/monoidal/tensor-example.png :align: center Parameters ---------- other : :class:`Diagram` Returns ------- diagram : :class:`Diagram` the tensor of 'self' and 'other'. """ if other is None: return self if rest: return self.tensor(other).tensor(*rest) if isinstance(other, Sum): return self.sum([self]).tensor(other) if not isinstance(other, Diagram): raise TypeError(messages.type_err(Diagram, other)) dom, cod = self.dom @ other.dom, self.cod @ other.cod boxes = self.boxes + other.boxes offsets = self.offsets + [n + len(self.cod) for n in other.offsets] layers = cat.Id(dom) for left, box, right in self.layers: layers = layers >> Layer(left, box, right @ other.dom) for left, box, right in other.layers: layers = layers >> Layer(self.cod @ left, box, right) return self.upgrade(Diagram(dom, cod, boxes, offsets, layers=layers))
def __init__(self, dom): monoidal.Id.__init__(self, dom) Diagram.__init__(self, dom, dom, [], [], layers=cat.Id(dom))
def __init__(self, t): super().__init__(t, t, [], [], layers=cat.Id(t))
def __init__(self, dom=Dim()): rigid.Id.__init__(self, dom) Diagram.__init__(self, dom, dom, [], [], layers=cat.Id(dom))
def __init__(self, dom=Ty()): cat.Id.__init__(self, dom) Diagram.__init__(self, dom, dom, [], [], layers=cat.Id(dom))
def __init__(self, x): super().__init__(x, x, [], [], layers=cat.Id(x))
def __str__(self): return ("{} @ ".format(cat.Id(self._left)) if self._left else "")\ + str(self._box)\ + (" @ {}".format(cat.Id(self._right)) if self._right else "")