Example #1
0
 def tensor(self, *others):
     if len(others) != 1:
         return monoidal.Diagram.tensor(self, *others)
     other, = others
     f = rigid.Box('f', Ty('c00', 'q00', 'q00'), Ty('c10', 'q10', 'q10'))
     g = rigid.Box('g', Ty('c01', 'q01', 'q01'), Ty('c11', 'q11', 'q11'))
     above = Diagram.id(f.dom[:1] @ g.dom[:1] @ f.dom[1:2])\
         @ Diagram.swap(g.dom[1:2], f.dom[2:]) @ Diagram.id(g.dom[2:])\
         >> Diagram.id(f.dom[:1]) @ Diagram.swap(g.dom[:1], f.dom[1:])\
         @ Diagram.id(g.dom[1:])
     below =\
         Diagram.id(f.cod[:1]) @ Diagram.swap(f.cod[1:], g.cod[:1])\
         @ Diagram.id(g.cod[1:])\
         >> Diagram.id(f.cod[:1] @ g.cod[:1] @ f.cod[1:2])\
         @ Diagram.swap(f.cod[2:], g.cod[1:2]) @ Diagram.id(g.cod[2:])
     diagram2tensor = tensor.Functor(ob={
         Ty("{}{}{}".format(a, b, c)):
         z.__getattribute__(y).__getattribute__(x)
         for a, x in zip(['c', 'q'], ['classical', 'quantum'])
         for b, y in zip([0, 1], ['dom', 'cod'])
         for c, z in zip([0, 1], [self, other])
     },
                                     ar={
                                         f: self.utensor.array,
                                         g: other.utensor.array
                                     })
     return CQMap(self.dom @ other.dom,
                  self.cod @ other.cod,
                  utensor=diagram2tensor(above >> f @ g >> below))
Example #2
0
    def downgrade(self):
        """
        Downgrade hypergraph diagram to :class:`discopy.rigid.Diagram`.

        Examples
        --------
        >>> x = Ty('x')
        >>> v = Box('v', Ty(), x @ x)
        >>> print((v >> Swap(x, x) >> v[::-1]).downgrade())
        v >> Swap(x, x) >> v[::-1]
        >>> print((Id(x) @ Swap(x, x) >> v[::-1] @ Id(x)).downgrade())
        Id(x) @ Swap(x, x) >> v[::-1] @ Id(x)
        """
        diagram = self.make_progressive()
        graph = Graph()
        graph.add_nodes_from(diagram.ports)
        graph.add_edges_from([(diagram.ports[i], diagram.ports[j])
                              for i, j in enumerate(diagram.bijection)])
        graph.add_nodes_from([
            Node("box",
                 depth=depth,
                 box=box if isinstance(box, rigid.Box) else rigid.Box(
                     box.name,
                     box.dom,
                     box.cod,
                     _dagger=box.is_dagger,
                     data=box.data)) for depth, box in enumerate(diagram.boxes)
        ])
        graph.add_nodes_from([
            Node("box",
                 depth=len(diagram.boxes) + i,
                 box=rigid.Spider(0, 0, diagram.spider_types[s]))
            for i, s in enumerate(diagram.scalar_spiders)
        ])
        return drawing.nx2diagram(graph, rigid.Ty, rigid.Id)
Example #3
0
 def tensor(self, *others):
     if len(others) != 1:
         return monoidal.Diagram.tensor(self, *others)
     f = rigid.Box('f', Ty('c00', 'q00', 'q00'), Ty('c10', 'q10', 'q10'))
     g = rigid.Box('g', Ty('c01', 'q01', 'q01'), Ty('c11', 'q11', 'q11'))
     ob = {Ty("{}{}{}".format(a, b, c)):
           z.__getattribute__(y).__getattribute__(x)
           for a, x in zip(['c', 'q'], ['classical', 'quantum'])
           for b, y in zip([0, 1], ['dom', 'cod'])
           for c, z in zip([0, 1], [self, others[0]])}
     ar = {f: self.array, g: others[0].array}
     permute_above = Diagram.id(f.dom[:1] @ g.dom[:1] @ f.dom[1:2])\
         @ Diagram.swap(g.dom[1:2], f.dom[2:]) @ Diagram.id(g.dom[2:])\
         >> Diagram.id(f.dom[:1]) @ Diagram.swap(g.dom[:1], f.dom[1:])\
         @ Diagram.id(g.dom[1:])
     permute_below =\
         Diagram.id(f.cod[:1]) @ Diagram.swap(f.cod[1:], g.cod[:1])\
         @ Diagram.id(g.cod[1:])\
         >> Diagram.id(f.cod[:1] @ g.cod[:1] @ f.cod[1:2])\
         @ Diagram.swap(f.cod[2:], g.cod[1:2]) @ Diagram.id(g.cod[2:])
     F = TensorFunctor(ob, ar)
     array = F(permute_above >> f @ g >> permute_below).array
     dom, cod = self.dom @ others[0].dom, self.cod @ others[0].cod
     return CQMap(dom, cod, array)
Example #4
0
            return self.ob_factory.tensor(
                *[self(diagram[i:i + 1]) for i in range(len(diagram))])
        if isinstance(diagram, Curry):
            n_wires = len(
                self(getattr(diagram.cod,
                             'left' if diagram.left else 'right')))
            return self.ar_factory.curry(self(diagram.diagram), n_wires,
                                         diagram.left)
        for cls, method in [(FA, 'fa'), (BA, 'ba')]:
            if isinstance(diagram, cls):
                return getattr(self.ar_factory, method)(self(diagram.dom[:1]),
                                                        self(diagram.dom[1:]))
        for cls, method in [(FC, 'fc')]:
            if isinstance(diagram, cls):
                left, right = diagram.dom[:1].left, diagram.dom[1:].right
                middle = diagram.dom[:1].right
                return getattr(self.ar_factory, method)(self(left),
                                                        self(middle),
                                                        self(right))
        return super().__call__(diagram)


biclosed2rigid_ob = Functor(ob=lambda x: rigid.Ty(x[0].name),
                            ar={},
                            ob_factory=rigid.Ty)
biclosed2rigid = Functor(ob=biclosed2rigid_ob,
                         ar=lambda f: rigid.Box(f.name, biclosed2rigid_ob(
                             f.dom), biclosed2rigid_ob(f.cod)),
                         ob_factory=rigid.Ty,
                         ar_factory=rigid.Diagram)