{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# DisCoCat in lambeq" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "In the previous tutorial, we learnt the basics of :term:`monoidal categories ` and how to represent them in ``lambeq``. In this tutorial, we look at the `Distributional Compositional Categorical` model [CSC2010]_, which uses functors to map diagrams from the `rigid category `_ of `pregroup grammars <../string-diagrams.rst#Pregroup-grammars>`_ to vector space semantics.\n", "\n", ":download:`Download code <../_code/discocat.ipynb>`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pregroup grammars" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "`Pregroup grammar <../string-diagrams.rst#Pregroup-grammars>`_ is a grammatical formalism devised by Joachim Lambek in 1999 [Lam1999]_. In pregroups, each word is a morphism with type :math:`I \\to T` where :math:`I` is the monoidal unit and :math:`T` is a rigid type, referred to as the *pregroup type*. Here are some examples for pregroup type assignments:\n", "\n", "* a noun is given the base type :math:`n`.\n", "* an adjective consumes a noun on the noun's left to return another noun, so it is given the type :math:`n\\cdot n^l`.\n", "* a transitive verb consumes a noun on its left and another noun on its right to give a sentence, so is given the type :math:`n^r \\cdot s \\cdot n^l`.\n", "\n", "In the context of pregroups, the :term:`adjoints ` :math:`n^l` and :math:`n^r` can be thought of as the left and right inverses of a type :math:`n` respectively. In a pregroup derivation, the words are concatenated using the monoidal product :math:`\\otimes` and linked using :term:`cups `, which are special morphisms that exist in any :term:`rigid category`. A sentence is grammatically sound if its derivation has a single uncontracted sentence wire.\n", "\n", "In ``lambeq``, words are defined using the :py:class:`~lambeq.backend.grammar.Word` class. A :py:class:`~lambeq.backend.grammar.Word` is just a :py:class:`~lambeq.backend.grammar.Box` where the input type is fixed to be the monoidal unit :math:`I` (or ``Ty()``). A pregroup derivation diagram can be drawn using either the :py:meth:`.backend.grammar.Diagram.draw` method or the :py:func:`.backend.drawing.draw` function." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from lambeq.backend.drawing import draw\n", "from lambeq.backend.grammar import Cap, Cup, Id, Ty, Word\n", "\n", "\n", "n, s = Ty('n'), Ty('s')\n", "\n", "words = [\n", " Word('she', n),\n", " Word('goes', n.r @ s @ n.l),\n", " Word('home', n)\n", "]\n", "\n", "cups = Cup(n, n.r) @ Id(s) @ Cup(n.l, n)\n", "\n", "assert Id().tensor(*words) == words[0] @ words[1] @ words[2]\n", "assert Ty().tensor(*[n.r, s, n.l]) == n.r @ s @ n.l\n", "\n", "diagram = Id().tensor(*words) >> cups\n", "draw(diagram)" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ ".. note::\n", "\n", " In ``lambeq``, method :py:meth:`~lambeq.backend.grammar.Diagram.create_pregroup_diagram` provides an alternative, more compact way to create pregroup diagrams, by explicitly defining a list of :term:`cups ` and :term:`swaps `. For example, the above diagram can be also generated using the following code:\n", "\n", " .. code-block:: python\n", "\n", " from lambeq.backend.grammar import Diagram, Ty\n", "\n", " words = [Word('she', n), Word('goes', n.r @ s @ n.l), Word('home', n)]\n", " morphisms = [(Cup, 0, 1), (Cup, 3, 4)]\n", " diagram = Diagram.create_pregroup_diagram(words, morphisms)\n", " \n", " where the numbers in ``morphisms`` define the indices of the corresponding wires at the top of the diagram\n", " ``(n @ n.r @ s @ n.l @ n)``." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before normal form: she, goes, home, CUP, CUP\n", "After normal form: she, goes, CUP, home, CUP\n" ] }, { "data": { "image/png": "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FLVv397omACABsKefQBA0KupqdEzzzyjuLg4tWnTRtnZ2f7rioqKNGrUKLVs2VKtWrXSz372M/3lL3/xX5+dna0ePXro1VdfldPpVMuWLfUP//APqq6u1oIFC9SmTRslJCRo/vz5tX7mmTNnNG3aNLVu3VqtWrXSHXfcoT179jTVQw4o7dq1U1ZWlj7//HMdOHBAzz77rA4ePKhZs2Zp4MCBstlscjqduvvuu/Xss8/qjTfeUEFBgS5evGh0dENUVlZq7969evPNN/VP//RPGjlypJKSkhQbG6sBAwboscce0759+zR79mx5vV4VFhbqn//5nyn6AGAy7NkHAAS9FStW6KmnnlJ+fr62b9+uKVOmqH///ho6dKi/6G/ZskVVVVV69NFHdf/99ysvL89//0OHDmnjxo3atGmTDh06pHHjxunw4cNKSUnRli1btG3bNk2dOlUZGRlKT0+XJI0fP15RUVHauHGjbrrpJr3yyisaOnSoDh48aNBvITCkpKQoKytLWVlZunjxog4cOKCCggIVFhaqsLBQq1at0rFjxyRJYWFhSklJUUJCgmw2W51TXFxcnWWxsbEKC2s+L4+qqqp05swZlZaW1utUXFysgwcPqrKyUpJ08803y+12a8KECXK73XK73erSpYtatGhh8CMDADS25jPNAAAwiMfj0Zw5cyRJycnJWrJkiXJzcyVJhYWFOnLkiH+v5+uvv66uXbtq586d6tOnj6Tv3xnw6quvKiYmRqmpqbr99tt14MABbdiwQSEhIercubNeeOEFffjhh0pPT9fWrVu1Y8cOFRcX+0vXwoULlZOTozVr1qh3794G/BYCT0REhL/AXqq0tNT/dnWv16uSkhKVlpbq22+/rVWMq6urL7vemJiYy24ciI6OVmhoqMLCwn7035YtW6q8vFxVVVWqrq6+4r8/nK+oqKiV7fTp0yotLVVZWdllM4aGhio2NrbWhovExESlpqbqkUce8f9ebDZbg//eAQCBgbIPAAh6Ho+n1mWHw6Hi4mJ5vV61b9++1tubU1NTFRsbK6/X6y/7HTp0UExMjP82iYmJCg0NrfW1ZYmJiSouLpYk7dmzR+Xl5YqPj6/1c8+fP69Dhw5R9m+QzWbTwIEDNXDgwCvexufzqby8vFaxvtrp22+/VUVFRa2CfrnS/sP52267Tdu3b6+zIeBK56OiomSz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AmUfAAJcixYt9P7772vixIl68sknlZaWpo0bN1L6G0llZaXeffddde/eXb/4xS80depUbdy4UWFhYUZHAwA0smXLlmnevHl6+eWX1blzZy1fvlwVFRVGxzIln8+nTz75RBkZGZowYYL69u2rTz75RK1btzY6WsCg7AOACcTFxenll1/Wzp07ZbVaNWLECDkcDj388MN6//33Kf43qLKyUv/7v/+radOmqU2bNrr33nsVFxen3bt36ze/+Y1iY2ONjggAaAItWrTQL3/5S+3fv1/9+vXTQw89pNatW+tnP/uZ1qxZQ/G/QT6fT/n5+crMzNQtt9yifv36qaioSBs3btS6devUoUMHoyMGFHZDAICJ9OrVS9u3b9euXbu0evVqrV69WkuXLpXdbtdtt90mt9stj8cjt9utlJQUhYeHGx252bl48aIOHDigwsJC/2n79u06ffq0OnXqpIcffljjx49Xjx49eBshAAQpp9OptWvX6quvvvLP2/Hjx8tqteonP/mJ3G63/5Samiqr1Wp05GanpqZGhw8f9s/agoIC7dixQ8eOHVNCQoLGjh2r8ePHa9CgQQoNDTU6bkCy+Hw+n9EhAASevn37qmfPnhwFvpnz+XzatWuX1q1bp127dqmwsFB//vOfJX1/sKEuXbrU2gDQtWtXJSQkKDIy0uDkje/8+fMqLi7W3r17axX7/fv3q7KyUpJ08803y+12q1evXhozZgwFH0CTe/jhh/XZZ59px44dRkfBj/jqq6+0Zs0a5efnq7CwUIcPH5bP51NISIg6depUawOA2+2Ww+FQdHS06efKxYsXderUKXm93lrF/osvvvC/EyI+Pl5ut1s9evTQvffeS8FvIJR9ANeFsh+4Tp065S+4BQUFKiws1N69e1VeXu6/TWRkpGw2W71PcXFx/vNNuaHg/PnzKi0tverp9OnTl11+4cIF/3piYmLqvAhzu92y2WxN9lgA4HIo+4GrvLxcX3zxRa0NygUFBTp16pT/NuHh4dc0by89NeWGgosXL/7ovL3S/L30ow0tWrRQampqrR0Nbrdbbdq0Mf1GDyPwNn4ACDLx8fEaPHiwBg8e7F9WU1Ojr7/+Wl6vV6dOnbrs0D58+HCty999991l1//DhgKr1arQ0FCFhYUpNDS01vm/XXbLLbfoyJEjqqqqUnV1taqrq/3nL7fs3LlzdQr7paKiouq8KOrUqVOdZXa7XS6XS0lJSbzIAAA0qJYtWyo9PV3p6en+ZT6fTydOnNAXX3yh4uLiy87bb7/9Vnv37vVfvnRj/KV+2FDQsmXLes3a0NBQOZ1OHTt2rF6ztqqqSt99912dwn6piIiIOrO1ffv28ng8dXYKpKSkqFOnThzQtgnxmwYAKCQkRLfccotuueWWet/nhxcAVzqdP3/+si8kLveCwmq1KjY29kdfpPzwr9VqverejhYtWjTibwsAgOtjsVjkcDjkcDjqfZ/KykqdOXPmivO2rKzMP1evNnerqqpktVp10003XXXGXvpvixYtrjpvo6Ki2FjejFH2AQDXJTIy8ppfsAAAgGsTHh6u1q1b85VzuGZ89R4AAAAAACZD2QcAAAAAwGQo+wAAAAAAmAxlHwAAAAAAk6HsAwAAAABgMpR9AAAAAABMhrIPAAAAAIDJUPYBAAAAADAZyj4AAAAAACZD2QcAAAAAwGQo+wAAAAAAmAxlHwAAAAAAk6HsAwAAAABgMpR9AAAAAABMhrIPAAAAAIDJUPYBAAAAADAZyj4AAAAAACZD2QcAAAAAwGQo+wAAAAAAmAxlHwAAAAAAk6HsAwAAAABgMpR9AAAAAABMhrIPAAAAAIDJUPYBAAAAADAZyj4AAAAAACZD2QcAAAAAwGQo+wAAAAAAmAxlHwAAAAAAk6HsAwAAAABgMpR9AAAAAABMhrIPAAAAAIDJUPYBAAAAADAZyj4AAAAAACZD2QcAAAAAwGQo+wAAAAAAmAxlHwAAAAAAk6HsAwAAAABgMmFGBwAQmObPny+bzWZ0DAAATG369OkqLS01OgaAAGTx+Xw+o0MAAAAAAICGw9v4AQAAAAAwGco+AAAAAAAmQ9kHAAAAAMBkKPsAAAAAAJgMZR8AAAAAAJOh7AMAAAAAYDKUfQAAAAAATIayDwAAAACAyVD2AQAAAAAwGco+AAAAAAAmQ9kHAAAAAMBkKPsAAAAAAJgMZR8AAAAAAJOh7AMAAAAAYDKUfQAAAAAATIayDwAAAACAyVD2AQAAAAAwGco+AAAAAAAmQ9kHAAAAAMBkKPsAAAAAAJgMZR8AAAAAAJOh7AMAAAAAYDKUfQAAAAAATIayDwAAAACAyVD2AQAAAAAwGco+AAAAAAAmQ9kHAAAAAMBkKPsAAAAAAJgMZR8AAAAAAJP5P3ug+jQateJ/AAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from lambeq.backend.drawing import draw_equation\n", "\n", "# In the original diagram, words appear before the cups\n", "print('Before normal form:', ', '.join(map(str, diagram.boxes)))\n", "\n", "diagram_nf = diagram.normal_form()\n", "print('After normal form:', ', '.join(map(str, diagram_nf.boxes)))\n", "\n", "draw_equation(diagram, diagram_nf, symbol='->', figsize=(10, 4), draw_as_pregroup=False, foliated=True)" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "In the example above, the application of normal form to the diagram introduces a :term:`cup` before the word \"home\"." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functors" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Given :term:`monoidal categories ` :math:`\\mathcal{C}` and :math:`\\mathcal{D}`, a monoidal :term:`functor` :math:`F: \\mathcal{C} \\to \\mathcal{D}` satisfies the following properties:\n", "\n", "- monoidal structure of objects is preserved: :math:`F(A \\otimes B) = F(A) \\otimes F(B)`\n", "- :term:`adjoints ` are preserved: :math:`F(A^l) = F(A)^l`, :math:`F(A^r) = F(A)^r`\n", "- monoidal structure of morphism is preserved: :math:`F(g \\otimes f) = F(g) \\otimes F(f)`\n", "- compositonal structure of morphisms is preserved: :math:`F(g \\circ f) = F(g) \\circ F(f)`\n", "\n", "Put simply, a :term:`functor` is a structure-preserving transformation. In a free :term:`monoidal category`, applying a :term:`functor` to a diagram amounts to simply providing a mapping for each generating object and morphism. In ``lambeq``, a :term:`functor` is defined by passing mappings (dictionaries or functions) as arguments ``ob`` and ``ar`` to the :py:class:`~lambeq.backend.grammar.Functor` class.\n", "\n", ":term:`Functors ` are one of the most powerful concepts in category theory. In fact, the encoding, rewriting and parameterisation steps of ``lambeq``'s :ref:`pipeline ` are implemented individually as :term:`functors `, resulting in an overall functorial transformation from :term:`parse trees ` to :term:`tensor networks ` and :term:`circuits `. More specifically:\n", "\n", "- :py:class:`lambeq.CCGParser` uses a :term:`functor` to transform a biclosed CCG diagram to a pregroup diagram [YK2021]_.\n", "- :py:class:`lambeq.Rewriter` functorially transforms a pregroup diagram to a simpler pregroup diagram.\n", "- :py:class:`lambeq.TensorAnsatz` functorially transforms a pregroup diagram to a tensor diagram, which can be evaluated as a tensor network using NumPy, JAX or PyTorch.\n", "- :py:class:`lambeq.CircuitAnsatz` functorially transforms a pregroup diagram to a :term:`quantum circuit`, for evaluation on a quantum device.\n", "\n", "Below we present two examples of :term:`functors `, implemented in ``lambeq``." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example 1: \"Very\" functor" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "This :term:`functor` adds the word \"very\" in front of every adjective in a :term:`DisCoCat` diagram. \n", "Since the mapping is from a :py:class:`.grammar.Diagram` to another :py:class:`.grammar.Diagram`, a :py:class:`.grammar.Functor` should be used. Further, the word \"very\" modifies an adjective to return another adjective, so it should have type \n", ":math:`(n \\otimes n^l) \\otimes (n \\otimes n^l)^l = n \\otimes n^l \\otimes n^{ll} \\otimes n^l`." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from lambeq import BobcatParser\n", "parser = BobcatParser(verbose='suppress')" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/png": "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rF9++UWS9M4772j48OFKSkpy1qoBQJWEhITIx8fH4TfhuDKsWrXK6BJQAR8fH4WEhBhdBuBUhP3LdPbsWY0fP17x8fHKycnRpEmT1L9/f23fvr3W3DquJixevFgjR47Upk2btGXLFj3wwAOKiorS/fff7zCd1WpVv379FBUVpY0bN+q3336r8s8QapuK2qCwsFDTp09XixYtdOLECY0fP16JiYn64osvJEkHDx7UgAED9PDDD+uBBx7Qli1b6mS7dO3aVb/99pu2bdumjh076ptvvlFISIiSk5Pt03zzzTd64oknlJKSojvvvFNTpkzRXXfdpe+++05//etfFRwcrMTExFLL3rx5s4YNGyY/Pz/NnTu3SteXAABni4qKUlpamjIzMys132233aaEhAQ99NBDNVRZ3bF161bdf//9+vDDD9WoUSOjyzHczJkztXv3bi1ZssToUmqFLl26aMyYMbrnnnsqNV9ISIiioqJqqCqgdiLsX6aBAwc6vF64cKFCQ0O1a9euCq/GX9c1bNhQs2fPlsViUYsWLZSamqrZs2eXCvtffvml9u3bp+TkZIWHh0v6/T+tXr16GVF2taqoDUaMGGGfruRshk6dOiknJ0f16tXT/Pnzdc011+gf//iHJNnnf+GFF4xanSrx9/dX27ZtlZycrI4dOyo5OVnjxo3T1KlTlZOTo9OnT2vv3r3q3r27pkyZop49e+qZZ56RJDVv3ly7du3SSy+9VGbYDw0Nlaenp7y9ve3bDgDUBVFRUZUOFR4eHoqIiLDfDu5KdvbsWUlS69at6/R1l6pLSEiIfH192Tb+PxcXFzVs2JD2AC6BeQ89O8mePXt0zz33qGnTpvLz81Pjxo0lSRkZGcYWVsM6d+7scKX266+/Xnv27JHVanWYLj09XQ0bNnQIa9dee63T6qxJFbVBSkqK+vbtq6ioKNWvX1/du3eX9Md2kZaWpuuuu85heXX1dj3du3dXcnKybDab1q1bpwEDBigmJkbffvutvvnmG0VGRio6OlppaWnq0qWLw7xdunQpc7sBAAAAcHkI+5epb9++ysrK0ptvvqmNGzdq48aNksTtvq5g586dU+/eveXn56dly5Zp8+bN+uijjySZc7vo0aOHvv32W+3YscN+u6IePXooOTlZ33zzjb2jAwAAZ0lMTKzT1wWqbhdrj6SkJAUEBDitHqOxfeBKQdi/DCdPnlR6err+/ve/q2fPnoqJian0Pc7rqpJOjRLff/+9oqOjS92nvkWLFjp48KCOHz9uH7d582an1FjTymuD3bt36+TJk3r++efVtWtXtWzZUidOnHCYNiYmRps2bSo1f11U8rv92bNn24N9SdhPTk5Wjx49JP2+zuvXr3eYd/369WrevHmp7QYAAADA5SHsX4bAwEAFBwdrwYIF2rt3r9asWaPx48cbXZZTZGRkaPz48UpPT9e7776refPmaezYsaWm69Wrl6655hoNHz5cO3fu1Pr16/X3v/9dkhxOga+LymuDqKgoeXh4aN68edq/f78++eQTTZ8+3WHe0aNHa8+ePXr88ceVnp6u5cuX19krzQcGBio+Pl7Lli2zB/tu3bpp69at+umnn+wdABMmTNDq1as1ffp0/fTTT1q8eLFeffVVPfbYYwZWDwAAAJgTYf8yuLi4aMWKFUpJSVFsbKzGjRunl156yeiynGLYsGHKy8vTtddeq4cfflhjx47VAw88UGo6V1dXrVy5Ujk5OerUqZNGjRqlp59+WpLk5eXl7LKrVXltEBoaqqSkJL3//vtq1aqVnn/+ec2aNcth3qioKH3wwQdauXKl2rRpo9dff13PPvusQWty+bp37y6r1WoP+0FBQWrVqpXCw8PVokULSVL79u313nvvacWKFYqNjdWkSZM0bdq0Mi/OBwD4/SypRx55RH/7298UFBSk8PBwTZkyxeiyDEFbOKI9HNEeQNm4Gv9luuWWW7Rr1y6HcTabzaBqnOP826rNnz+/1PsHDhxweN2yZUt9++239tclp3I3a9asRupzhou1wT333FPqljAXbhcJCQlKSEhwGHffffdVX5FONGfOHM2ZM8dh3Pbt20tNN3DgwFJ3sDjfhdvOypUrL784AKjDFi9erPHjx2vjxo3asGGDEhMT1aVLF1Pc1aayaAtHtIcj2gMozfRh//333zfVbbt+/fXXy5r37bffrsZqLs3WrVvl6empBg0a6MSJE1qxYoWaNWtm/0335UhJSanyvBs2bJCvr+9lfX5tc+rUqSrPu2TJEtWrV6/6ijHYzz//bHQJAHDZ4uPjNXnyZElSdHS0Xn31Va1evfqKDDC0hSPawxHtAZRm2rDftGlTRURE2H8fbiYNGjRQdHR0pea58cYbtWDBAo0aNaqGqqq86qpl0KBB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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from lambeq.backend.drawing import draw_equation\n", "from lambeq.backend.grammar import Diagram, grammar, Functor\n", "\n", "# determiners have the same type as adjectives\n", "# but we shouldn't add 'very' behind them\n", "determiners = ['a', 'the', 'my', 'his', 'her', 'their']\n", "\n", "# type for an adjective\n", "adj = n @ n.l\n", "very = Word('very', adj @ adj.l)\n", "cups = Diagram.cups(adj.l, adj)\n", "\n", "def very_ob(_, ty):\n", " return ty\n", "\n", "def very_ar(_, box):\n", " if box != very:\n", " if box.name not in determiners:\n", " if box.cod == adj:\n", " return very @ box >> Id(adj) @ cups\n", " return box\n", "\n", "very_functor = Functor(grammar,\n", " ob=very_ob,\n", " ar=very_ar,)\n", "\n", "diagram = parser.sentence2diagram('a big bad wolf')\n", "new_diagram = very_functor(diagram)\n", "\n", "draw_equation(diagram, new_diagram, symbol='->', figsize=(10, 4))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example 2: Twist functor" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "In this :term:`functor`, :term:`cups ` and :term:`caps ` are treated specially and are not passed to the ``ar`` function; instead they are passed to :py:meth:`.grammar.Diagram.register_special_box` method.\n", "\n", "Here is an example of how to map a :term:`cup` to a custom diagram, such as a \"twisted\" :term:`cup`. Note that it is up to the user to ensure the new :term:`cups ` and :term:`caps ` satisfy the :term:`snake equations`." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAApQAAAChCAYAAAB55y8LAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAX0UlEQVR4nO3de1BU9/3/8deBBWQBQUQREPGGCApUtNbqKIwxamusRmMzbWOGoUUz0TpJJ2nqdGqNGcfvOMl4aUebW7GO1hiNmCYZkxgrWqshAS+AF4LxgkZGRaNG0HLZ/f3hsD9RIOIBzrL7fMyc4XB2Ofvej+t7X+eyZw2n0+kUAAAA8JB8rC4AAAAAnRuBEgAAAKYQKAEAAGAKgRIAAACmECgBAABgCoESAAAAphAoAQAAYAqBEgAAAKYQKAEAAGAKgRIAAACmECgBAABgCoESAAAAphAoAQAAYAqBEgAAAKYQKAEAAGAKgRIAAACmECgBAABgCoESAAAAphAoAQAAYIrN6gJaUl5ersrKSqvLcImIiFCfPn2sLqNduNtYA4AZ9Gt4Ind+XbttoCwvL1diYqKqq6utLsXFbrfr+PHjbvuP+bDccawBwAz6NTyRO7+u3TZQVlZWqrq6Whs2bFBiYqLV5ej48eN66qmnVFlZ6Zb/kGa421gDgBn0a3gid39du22gbJCYmKi0tDSry/AKjDUAdA70a7gbj/tQTl5engzD0LVr15q9z+LFi/WDH/ygw2oCvFVGRoaee+45q8sA0En07dtXK1eu9JrH9SSdKlAahtHitHjx4gdazwsvvKBdu3a1b7EAtG3bNr3yyitWlwGgg5jdiPzyyy81Z86cB7ovIdC9uP0h77tVVFS45jdv3qxFixaptLTUtSw4OFgFBQXfu57g4GAFBwe3S40A/r/w8HCrSwDQifTo0cPqEvCQOtUeyl69ermm0NBQGYbRaNndIbGwsFAjRoyQ3W7X6NGjGwXPew955+XlaeTIkQoKClJYWJjGjBmjs2fPduRTAzzS3Xsr1qxZo/j4eHXp0kWRkZF64oknrC0OQJvKzMzUnj17tGrVKteRw4iICL366quu+0yfPl1+fn66efOmJOn8+fMyDEMnT56U1Hivo9Pp1OLFi9WnTx8FBAQoOjpaCxYskHSnt5w9e1bPP/+867Ea7Nu3T2PHjlVgYKBiY2O1YMECVVVVuW6/dOmSpk6dqsDAQPXr108bN25s76HxCp0qULbGH//4R7322msqKCiQzWZTVlZWk/erq6vT9OnTlZ6erqKiIh04cEBz5sxp9OIEYE5BQYEWLFigJUuWqLS0VB9//LHGjRtndVkA2tCqVav04x//WNnZ2aqoqFBFRYVmz56tvLw8SXcC4n/+8x+FhYVp3759kqQ9e/YoJiZGAwcOvG997733nlasWKHXX39dZWVl2r59u5KTkyXdOZ2md+/eWrJkieuxJOnrr7/W5MmTNXPmTBUVFWnz5s3at2+f5s+f71pvZmamzp07p927d2vr1q1as2aNLl261M6j4/k61SHv1li6dKnS09MlSX/4wx80ZcoU3b59W126dGl0vxs3buj69et67LHHNGDAAEniUgxAGysvL1dQUJAee+wxhYSEKC4uTsOGDbO6LABtKDQ0VP7+/rLb7erVq5ckafz48crJyVF9fb1KSkrk7++vJ598Unl5eZo8ebLy8vJc79X3Ki8vV69evTRhwgT5+fmpT58+GjlypKQ7p9P4+voqJCTE9ViStGzZMv3qV79yHRmJj4/X6tWrlZ6errVr16q8vFw7duzQF198oR/+8IeSpLfffpv3/TbgsXsoU1JSXPNRUVGS1OQWSHh4uDIzMzVp0iRNnTpVq1atanSuJgDzHn30UcXFxal///6aPXu2Nm7cyIWZAS8wduxYfffddzp06JD27Nmj9PR0ZWRkuPZa7tmzRxkZGU3+7axZs3Tr1i31799f2dnZys3NVV1dXYuPd+TIEa1bt871WYng4GBNmjRJDodDp0+f1vHjx2Wz2TR8+HDX3wwePFhhYWFt9Iy9l8cGSj8/P9d8w+Frh8PR5H1zcnJ04MABjR49Wps3b9agQYP0+eefd0idgDcICQnRwYMHtWnTJkVFRWnRokVKTU1t8fJeADq/sLAwpaamKi8vzxUex40bp0OHDumrr75SWVlZs3soY2NjVVpaqjVr1igwMFDPPvusxo0bp9ra2mYf7+bNm5o7d64OHz7smo4cOaKysjLXUUi0D48NlK01bNgwLVy4UPv379fQoUP1z3/+0+qSAI9is9k0YcIELV++XEVFRTpz5oz+/e9/W10WgDbk7++v+vr6RsvS09O1e/du7d27VxkZGQoPD1diYqKWLl2qqKgoDRo0qNn1BQYGaurUqVq9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rVs35efna+LEicrKytKYMWO0fft23bp1y+rSOq1jx47ppZde0pAhQ3Ts2DHl5uZqzpw5VpcFoJN7/PHH9dlnn+ny5ctKS0vTvHnzdOjQIfZYPqSamhrt2LFDkyZN0qxZs5SWlqbCwkLFxsZaXRo8jFcESunOd5Fu2LBBeXl5qq2t1eOPP66ePXvql7/8pXJzc3Xz5k2rS3RrDodDJSUlevnllzVkyBANGTJEa9eu1Ysvvqhjx45p+vTpMgzD6jIBeIBHHnlER44c0bJly/TOO+8oLS1N8fHxWrhwoQoLC1VfX291iW7t1q1b2rFjh7KyshQZGamf/vSnOn/+vD744AO9//776tevn9UlwgN53XUo09PTVVBQoBMnTmjLli3asmWLNm3aJEnq37+/UlJSlJyc7JoGDhwom827hqmyslLFxcWNppKSElVVVSkkJETTpk3TsmXLNHHiRHXp0sXqcgF4IH9/f7344ot67rnntHv3br377rt644039H//938KDAxUUlJSo16dnJysyMhIr9qwdTgcOnXqlKtPFxUVqbi4WCdPnpTD4VB8fLzmzZunWbNmKSUlxavGBh3PcHIcQaWlpdq/f3+jAHXx4kVJUkBAgKtxDRgwQN26dWt2CggIsPiZNM/hcOjGjRv69ttv75uuXr2qS5cuqaSkRMXFxaqoqJB0p6Hf3bRTU1M1btw4QqQbyM7OVlFRkfLz860uxeP97Gc/kyT961//srgS1NbW6r///a8OHTrk6tVHjx51nb4UERGhlJQUDR06VFFRUc326tDQULc+f7C2tva+Hn3372fPnlVRUZGOHj2q6upqSVL37t0bhesf/ehHSk5OJkS6gS5duujVV1/V/PnzrS6lXXnXrrdmJCQkKCEhodGyy5cvN9riKy4u1qeffqqrV6+qpqamyfUEBgY2alrh4eH3NbLg4GD5+vrKZrM1+nnvMpvNJofDobq6OtXX17f4s6ampsmgePd0/fr1Jj+MZBiGQkNDFRERoaSkJGVlZbkaUnx8vPz8/NplzAGgtfz8/JSRkaGMjAzXsvr6en399deNdgh88sknunTpkq5du9bkuZeGYahr165N9uh7dxI01a+b+llbW/u9vbq+vl5VVVXf26+rqqqaff7dunVTTEyMkpOT9fOf/9x1VK1Xr16ER1iKQNmMHj16aPz48Ro/fnyj5U6n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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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OBzatGmT60U5RUVFkhofr3LNNde4/gfu3bt3hz5exWKxKDg4WMHBwef9jjXV1dXavn17o4H9zDPPuM4LFxwc7Dr4+4YbblD37t3d8SMA8HFOp1ObN2/WihUr9MEHH2j37t2Sfnp6OiEhQXa7XZMnT3bN5T59+nT4N1Sw2Wyy2WyKjY09r687fvy4vv3220Zz+YUXXnAd12+z2TRq1Cilp6crLS2Nt76F6XzuRTnFxcVatGiR3nnnHX333XeKiYnRjTfe6DptEMer/MTpdOrHH39sdNqgzMxMWSwWXX755br11lt10003dfhh7k14UY778aIcc3z33XdatGiRVq5cqf379ys6Olo33HCDRo8eLbvdrsTERN7x5V9OHdd/6rRB69atk9Pp1IQJE/TLX/5S//Ef/8HKZTviRTn/5jOFsqamRn/961/12GOPqXPnzrrppps0bdo0jR49mlLUSocOHdK7776rFStWaP369Ro9erSeffZZXXLJJWZH8wkUSvejULavuro6LVmyRI8++qiCgoI0ffp0paena9y4cZSiVjpy5Ijee+89rVixQmvXrtXw4cP13HPPacSIEWZH8wkUyn/ziSb1ww8/KCkpSfPnz9dvfvMb7dmzR0uXLtXYsWMpk+chKipKd911lz7//HOtX79eZWVlSklJ0cKFC82OBsDDHD16VMOGDdODDz6oW2+9Vbt379azzz6r1NRUyuR56N69u26//XatWbNGX375perq6nTZZZfpT3/6k9nR4GO8/hhKh8OhjIwMlZeXKzc3V0OGDDE7kldITU1Vbm6u5syZozlz5mjkyJEaM2aM2bEAeACn06k77rhD33//vbKzs5WcnGx2JK8wZswYZWdna968eXrkkUc0cuRITZw40exY8BFevzz3yiuv6B//+IdeffVVymQbCwgI0FNPPaVRo0bplltuafa0RQBwpuXLl2vVqlV66aWXKJNtzGq16k9/+pMmTpyomTNnnvXUSUBb8vpCmZOTo1GjRunKK680O4pXslqteuihh1RaWqoDBw6YHQeAB9iyZYuSk5N1ww03mB3FK/n5+ekPf/iDqqqqtG/fPrPjwEd4faHct2+fIiMjzY7h1aKjo1VRUeE6zRAAnM3+/ft572k3i46OVmVlpQ4fPmx2FPgIry+UUtN3okHb4oVNAM4Xc9m9mMtob/zGAQAAwBAK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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from lambeq.backend.grammar import Category, Ty, Layer, Diagram, Functor, Box, Cup, Cap, Swap\n", "\n", "\n", "twisted = Category('twisted')\n", "\n", "@twisted('Diagram')\n", "class TwistedDiagram(Diagram): ...\n", "\n", "@twisted('Ty')\n", "class TwistedTy(Ty): ...\n", "\n", "@twisted('Box')\n", "class TwistedBox(Box): ...\n", "\n", "@twisted('Layer')\n", "class TwistedLayer(Layer): ...\n", "\n", "class TwistedCup(Cup, TwistedBox): ...\n", "\n", "class TwistedCap(Cap, TwistedBox): ...\n", "\n", "@TwistedDiagram.register_special_box('swap')\n", "class TwistedSwap(Swap, TwistedBox): ...\n", "\n", "@TwistedDiagram.register_special_box('cap')\n", "def twisted_cap_factory(left, right, is_reversed=False):\n", " caps = TwistedCap(right, left, is_reversed=not is_reversed)\n", " swaps = TwistedSwap(right, left)\n", " return caps >> swaps\n", "\n", "@TwistedDiagram.register_special_box('cup')\n", "def twisted_cup_factory(left, right, is_reversed=False):\n", " swaps = TwistedSwap(left, right)\n", " cups = TwistedCup(right, left, is_reversed=not is_reversed)\n", " return swaps >> cups\n", "\n", "\n", "twist_functor = Functor(\n", " ob=lambda _, ty: TwistedTy(ty.name),\n", " ar=lambda func, box: TwistedBox(box.name, func(box.dom), func(box.cod)),\n", " target_category=twisted)\n", "\n", "diagram = parser.sentence2diagram('This is twisted')\n", "twisted_diagram = twist_functor(diagram)\n", "\n", "draw(diagram)\n", "draw(twisted_diagram)\n", "\n", "snake = Id(n) @ Cap(n.r, n) >> Cup(n, n.r).to_diagram() @ Id(n)\n", "draw_equation(twist_functor(snake), Id(n), figsize=(4, 2))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "TwistedDiagram.cups(n, n.r).draw(figsize=(2, 2))\n", "TwistedDiagram.caps(n.r, n).draw(figsize=(2, 2))" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ ".. note::\n", " \n", " Twisting the nested :term:`cups ` for \"is\" and \"twisted\" together is **not** a functorial operation, so it cannot be implemented using :py:class:`.grammar.Functor`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Classical DisCoCat: Tensor networks" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "The classical version of :term:`DisCoCat` sends diagrams in the :term:`category` of pregroup derivations to tensors in the :term:`category` of vector spaces **FVect**. **FVect** is a :term:`monoidal category` with vector spaces (e.g. :math:`\\mathbb{R}^2 \\otimes \\mathbb{R}^2`) as objects and linear maps between vector spaces as morphisms. It is in fact a :term:`compact closed category`, which is a special case of rigid categories where :math:`A^l = A^r = A^*`.\n", "\n", "Using the :py:mod:`lambeq.backend.tensor` module, you can define a free :term:`category` of vector spaces: objects are defined with the :py:class:`lambeq.backend.tensor.Dim` class and morphisms with the :py:class:`lambeq.backend.tensor.Box` class. Composite morphisms are constructed by freely combining the generating morphisms using the ``>>`` operator. This is similar to how :term:`rigid categories ` and :term:`monoidal categories ` are defined. The concrete value of the tensor is passed to the ``data`` attribute as an unshaped list; ``lambeq`` will reshape it later based on the input and output dimensions.\n", "\n", "It is worth noting that :py:class:`lambeq.backend.tensor.Diagram` delays the computation of tensor contractions until :py:meth:`.tensor.Diagram.eval` is called." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dim(1) @ Dim(2) @ Dim(3)=Dim(2, 3)\n" ] } ], "source": [ "import numpy as np\n", "from lambeq.backend.tensor import Box, Diagram, Dim, Id\n", "\n", "# Dim(1) is the unit object, so disappears when tensored with another Dim\n", "print(f'{Dim(1) @ Dim(2) @ Dim(3)=}')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "id_box.eval()=array([[1., 0.],\n", " [0., 1.]])\n" ] } ], "source": [ "id_box = Box('Id Box', Dim(2), Dim(2), data=[1,0,0,1])\n", "id_tensor = np.array([1, 0, 0, 1]).reshape((2, 2))\n", "\n", "# the actual values of id_box and id_tensor are equal\n", "assert (id_box.array == id_tensor).all()\n", "print(f'{id_box.eval()=}')" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "In the :term:`category` of vector spaces, :term:`cups `, :term:`caps ` and :term:`swaps ` take on concrete values as tensors." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1, 0, 0],\n", " [0, 1, 0],\n", " [0, 0, 1]])" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Diagram.cups(Dim(3), Dim(3)).eval(dtype=np.int64)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[[[1, 0],\n", " [0, 0]],\n", "\n", " [[0, 0],\n", " [1, 0]]],\n", "\n", "\n", " [[[0, 1],\n", " [0, 0]],\n", "\n", " [[0, 0],\n", " [0, 1]]]])" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Diagram.swap(Dim(2), Dim(2)).eval(dtype=np.int64)" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "To implement a :term:`functor` from :py:class:`.grammar.Diagram` to :py:class:`.tensor.Diagram`, use a :py:class:`.grammar.Functor` with ``target_category = lambeq.backend.tensor.tensor``, and with :py:class:`.tensor.Dim` and :py:class:`.tensor.Diagram` as ``cod``, respectively. In addition, :py:class:`.tensor.Diagram`\\ s can be instantiated with concrete values to be evaluated later using a custom tensor contractor. See the implementation of :py:class:`~lambeq.ansatz.tensor.TensorAnsatz` for an example." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\"This\" becomes\n", "[1. 1.]\n", "\"is\" becomes\n", "[[[[1. 1.]\n", " [1. 1.]]\n", "\n", " [[1. 1.]\n", " [1. 1.]]]\n", "\n", "\n", " [[[1. 1.]\n", " [1. 1.]]\n", "\n", " [[1. 1.]\n", " [1. 1.]]]]\n", "\"twisted\" becomes\n", "[[1. 1.]\n", " [1. 1.]]\n", "one_diagram = Diagram(dom=Dim(1), cod=Dim(2), layers=[Layer(left=Dim(1), box=[This; Dim(1) -> Dim(2)], right=Dim(1)), Layer(left=Dim(2), box=[is; Dim(1) -> Dim(2, 2, 2, 2)], right=Dim(1)), Layer(left=Dim(2, 2, 2, 2, 2), box=[twisted; Dim(1) -> Dim(2, 2)], right=Dim(1)), Layer(left=Dim(2, 2, 2, 2), box=[CUP; Dim(2, 2) -> Dim(1)], right=Dim(2)), Layer(left=Dim(2, 2, 2), box=[CUP; Dim(2, 2) -> Dim(1)], right=Dim(1)), Layer(left=Dim(1), box=[CUP; Dim(2, 2) -> Dim(1)], right=Dim(2))])\n" ] }, { "data": { "image/png": "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tXXotXXotXXotTXos3Wc2Ougfpd3R/roo4+a/Xv9+vVKTExUSUmJJk2aZFNVzkSvrUOvrUOvrUOvrUGfrePEXofsDOXdampqJEnx8fE2V+J89No69No69No69Noa9Nk6Tug1gVKS3+/XkiVLNGHCBI0cOdLuchyNXluHXluHXluHXluDPlvHKb0O2VPeTeXn56u8vFx79uyxuxTHo9fWodfWodfWodfWoM/WcUqvQz5QLlq0SB988IF2796tPn362F2Oo9Fr69Br69Br69Bra9Bn6zip1yEbKA3D0NNPP63t27ersLBQ/fv3t7skx6LX1qHX1qHX1qHX1qDP1nFir0M2UObn5+vNN9/Ujh075PV69Z///EeSFBsbq+joaJurcxZ6bR16bR16bR16bQ36bB0n9jpk35Szbt061dTUKDc3V8nJyYFly5YtdpfmOPTaOvTaOvTaOvTaGvTZOk7sdcjOUBqGYXcJIYNeW4deW4deW4deW4M+W8eJvQ7ZGUoAAAC0D8cHysTERGVlZam+vt7uUhzP7/dr3LhxdpcBoJPKyspSZGSk3WWEhLS0NKWkpNhdBhzE8YGyd+/e+uyzz7Rt2za7S3G0uro6bd26Vf/73//sLgVAJ+VyufTuu+/qypUrdpfiaLt27dLu3buVmJhodylwEMcHygkTJuixxx7Tk08+qaqqKrvLcSTDMPSb3/xG586d08qVK+0uB0AntWzZMtXX1ysvL8+RrzELBlevXtXcuXOVm5urmTNn2l0OHMTxgdLlcun111+X1+vVmDFjVFBQIL/fb3dZjnHixAlNnz5dr732mlatWqWhQ4faXRKATiolJUV/+ctftH37duXk5Ki0tNTukhzDMAy98847ysrKUl1dnTZs2KDw8HC7y4KDOD5QSlL37t114MABTZkyRfPnz9eECRP03nvv6ebNm3aX1mkdO3ZMzz//vEaMGKFjx45p+/btWrBggd1lAejkHn30UX366ae6fPmysrOzlZ+fr0OHDjFj+R3dvn1bO3fu1NSpUzVnzhxlZ2erpKREqampdpcGhwmJQClJycnJ2rhxowoLC1VfX69HH31UiYmJ+vnPf67t27frxo0bdpcY1Px+v8rLy/WHP/xBI0aM0IgRI7Ru3To999xzOnbsmGbNmiWXy2V3mQAc4Ic//KGOHDmilStX6q233lJ2drbS09O1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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import numpy as np\n", "from lambeq.backend.grammar import Functor\n", "from lambeq.backend import tensor\n", "\n", "\n", "def one_ob(_, ty):\n", " dims = [2] * len(ty)\n", " return Dim(*dims) # does Dim(2,2,..)\n", "\n", "def one_ar(_, box):\n", " dom = one_ob(_, box.dom)\n", " cod = one_ob(_, box.cod)\n", " box = Box(box.name, dom, cod, np.ones((dom @ cod).dim))\n", " print(f'\"{box}\" becomes')\n", " print(box.data)\n", " return box\n", "\n", "one_functor = Functor(\n", " target_category=tensor.tensor,\n", " ob=one_ob, ar=one_ar,\n", ")\n", "one_diagram = one_functor(diagram)\n", "print(f'{one_diagram = }')\n", "one_diagram.draw()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Quantum DisCoCat: Quantum circuits" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "The quantum version of :term:`DisCoCat` sends diagrams in the :term:`category` of pregroup derivations to :term:`circuits ` in the category of Hilbert spaces **FHilb**. This is a :term:`compact closed ` monoidal category with Hilbert spaces (e.g. :math:`\\mathbb{C}^{2^n}`) as objects and unitary maps between Hilbert spaces as morphisms.\n", "\n", "The :py:mod:`lambeq.backend.quantum` module is a framework for the free :term:`category` of :term:`quantum circuits `: objects are generated using the :py:class:`.quantum.Ty` class and morphisms by using the available :term:`quantum gates ` which are subclasses of :py:class:`.quantum.Box`. In ``lambeq``, rotation values range from :math:`0` to :math:`1` rather than from :math:`0` to :math:`2\\pi`. The circuit can then either be evaluated using tensor contraction with the :py:meth:`~lambeq.backend.quantum.Diagram.eval` method, or exported to :term:`pytket` using the :meth:`~lambeq.backend.quantum.Diagram.to_tk` method, which supports multiple hardware backends." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "tk.Circuit(4).CX(1, 2).X(3).CX(0, 1).CX(2, 3).Rz(0.2, 0).Rz(0.4, 1).Rz(0.6, 2).Rz(0.8, 3)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from lambeq.backend.quantum import CX, Id, qubit, Rz, X\n", "\n", "\n", "circuit = Id(4)\n", "circuit >>= Id(1) @ CX @ X\n", "circuit >>= CX @ CX\n", "circuit >>= Rz(0.1) @ Rz(0.2) @ Rz(0.3) @ Rz(0.4)\n", "\n", "same_circuit = (Id(4).CX(1, 2).X(3).CX(0, 1).CX(2, 3)\n", " .Rz(0.1, 0).Rz(0.2, 1).Rz(0.3, 2).Rz(0.4, 3))\n", "assert circuit == same_circuit\n", "\n", "circuit.draw(draw_type_labels=False)\n", "circuit.to_tk()" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "To apply multi-qubit :term:`gates ` to non-consecutive :term:`qubits `, use :term:`swaps ` to permute the wires, apply the :term:`gate `, then unpermute the wires. These :term:`swaps ` are only logical swaps and do not result in more gates when converted to :term:`tket` format." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "tk.Circuit(3).CX(2, 0)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from lambeq.backend.quantum import Diagram as Circuit, SWAP\n", "\n", "# to apply a CNOT on qubits 2 and 0:\n", "circuit1 = Id(3)\n", "circuit1 >>= SWAP @ Id(1)\n", "circuit1 >>= Id(1) @ SWAP\n", "circuit1 >>= Id(1) @ CX\n", "circuit1 >>= Id(1) @ SWAP\n", "circuit1 >>= SWAP @ Id(1)\n", "\n", "# or you can do\n", "perm = Circuit.permutation(circuit1.dom, [2, 0, 1])\n", "circuit2 = perm[::-1] >> Id(1) @ CX >> perm\n", "\n", "assert circuit1 == circuit2\n", "circuit1.draw(figsize=(3, 3), draw_type_labels=False)\n", "\n", "# no swaps introduced when converting to tket\n", "circuit1.to_tk()" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "We also have long-ranged controlled gates." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAUAAAADcCAYAAAABQ3gmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAAASLElEQVR4nO3da0xcZQKH8f8wtCCFWiutqBVr8Aa0yFATix92bdKsNuBCYoofHLUG6g1jrFfUGo27trpW3d1IWVnrlpRmV/jSpmO9tElNSCqpwpSMBW80LdUWFC8tA6WW4eyHZiaLXSrMnNMZfJ9fMkk5M3PeF6Y8nJlz5ozLsixLAGCgpHhPAADihQACMBYBBGAsAgjAWAQQgLEIIABjEUAAxiKAAIxFAAEYiwACMBYBBGAsAgjAWAQQgLEIIABjEUAAxiKAAIxFAAEYiwACMBYBBGAsAgjAWAQQgLEIIABjEUAAxiKAAIxFAAEYy7EAnjx5Us3NzTp06JBTQyCBDA8Pq7m5WYcPH473VHAWDA4Oqrm5WX19ffGeSkwcC+DQ0JAqKirU2trq1BBIIEePHlVFRYXa29vjPRWcBd99950qKioUCATiPZWY8BQYgLEIIABjEUAAxiKAAIxFAAEYiwACMBYBBGAsAgjAWAQQgLEIIABjEUAAxiKAAIxFAAEYiwACMBYBBGAsAgjAWAQQgLEIIABjEUAAxiKAAIxFAAEYiwACMBYBBGAsAgjAWAQQgLEIIABjEUAAxiKAAIxFAAEYiwACMBYBBGAsAgjAWAQQgLEIIABjEUAAxiKAAIxFAAEYiwACMBYBBGCs5HhPAIAzenp61N/f78i6Dx8+LEn68ssvNXv2bEfGkKTMzExlZ2c7tn7HAmhZlhYvXqxp06Y5NQQSSPjxTk7mb2oi6OnpUW5uroaGhhwd5/7773d0/Wlpaerq6nIsgo79b3W5XGptbdXJkyedGgIJJPx4j4yMxHsqkNTf36+hoSE1NjYqNzc33tOJSldXl7xer/r7+6deAAHEX25uroqKiuI9jYTFThAAxiKAAIzlWAAHBgYkSV988YUCgUDkawBIFLYH0O/3q6qqSjk5OZKk1atXq6CgQHPmzFFVVZX27t1r95AAEBXbAhgMBlVeXq6ioiI1NDTo559/HnP9iRMn1NDQII/Ho/Lycg0ODto1NABExZYABoNBLVmyRD6fT5LGPRQivNzn8+mGG25QMBi0Y3gADvr+++81d+5cHThwwNFx3nvvPRUWFmp0dNTRcf6XLQH0er3y+/0KhUITun0oFJLf75fX67VjeADjePbZZ+VyueRyuTRt2jRddtllevzxxzU8PDzhdbzwwgsqKyvT/PnzI8t6enpUUlKitLQ0zZ07V4899tivHgM6f/78yFzClxdffDFy/U033aRp06Zp8+bNk/4+oxXzcYB+v19bt26d9P1CoZC2bt2qvXv3qrCwMNZpABjHTTfdpH/96186efKk2tradOedd8rlcumll1761fsODQ1pw4YNev/99yPLQqGQSkpKlJWVpd27d+vIkSO64447NG3aNK1Zs+aM63v++ee1cuXKyNcZGRljrl+xYoX+/ve/6/bbb5/kdxmdmLcAa2tro377U3Jysmpra2OdAoAzSElJUVZWli655BKVl5dr6dKl2rFjhyTpueeeO22rzOVyaePGjZKk7du3KyUlRYsXL46s74MPPlBnZ6caGxtVWFioZcuW6U9/+pNqa2tPe+3/lzIyMpSVlRW5zJgxY8z1N998sz755BN1d3fb+0MYR0wBHBgYUGNjY9RvfxoZGVFjYyOHyABnyaeffqrdu3dr+vTpkqRHH31UR44ciVzWrVuntLQ0XXvttZKklpYWLVq0aMw6PvroIy1cuFAXXHBBZNmNN96oY8eOad++fWcc/8UXX9T5558vj8ejl19++bR2ZGdn64ILLlBLS4sd3+6viukp8IEDB3TixImYJjA8PKxnnnlmzA8TU094h1Zzc7MCgUCcZ4P/3RLz+XxKT0/XyMiITpw4oaSkJL3++uuSpPT0dKWnp0uSWltbtXr1ajU0NGjBggWSpIMHD+qiiy4as+7e3t7Tfl/DX/f29o47pwcffFBFRUWaPXu2du/erSeffFJHjhzRq6++OuZ2F110kQ4ePKiCgoIov/uJiymAdu3FbWho4CwiU1x4z92WLVsiWxeInyuvvDLy7yVLlqiurk6Dg4N67bXXlJycrFtuuWXM7Xt6elReXq5HH31UFRUVkeXHjx9XamqqLXN6+OGHI/8uKCjQ9OnTdc8992jt2rVKSUmJXHfOOec4fhabsJiqE/7LEauWlpbIXxxMTX19fcrKytLmzZtVWloa7+kYr729PfLUdcaMGbr88sslSW+99ZauueYabdiw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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from lambeq.backend.quantum import Controlled, Rz, X\n", "\n", "(Controlled(Rz(0.5), distance=2) >> Controlled(X, distance=-2)).draw(figsize=(3, 2), draw_type_labels=False)\n", "Controlled(Controlled(X), distance=2).draw(figsize=(3, 2), draw_type_labels=False)" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "So far, our :term:`circuits ` have been \"pure\" circuits, consisting of unitaries. Pure circuits can be evaluated locally to return a unitary ``numpy`` array. Circuits containing :py:class:`~lambeq.backend.quantum.Discard`\\ s and :py:class:`~lambeq.backend.quantum.Measure`\\ s are considered \"mixed\", and return non-unitary ``numpy`` arrays when evaluated, as they are classical-quantum maps (for more details, see Chapter 5 in [HV2013]_)." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j]]\n", "\n", "[[[1.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j]]\n", "\n", " [[0.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j]]]\n", "\n", "[1. 0.]\n", "\n", "[1.+0.j 0.+0.j]\n", "\n" ] } ], "source": [ "from lambeq.backend.quantum import Discard, Measure, Ket, Bra\n", "\n", "\n", "print(f'{Discard().eval()}\\n')\n", "print(f'{Measure().eval()}\\n')\n", "print(f'{Ket(0).eval()}\\n')\n", "# circuits that have measurements in them are no longer unitary\n", "print(f'{(Ket(0) >> Measure()).eval()}\\n')" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Pure :term:`circuits ` can be coerced to evaluate into a classical-quantum map representation by setting ``mixed=True``." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[[[[[[[1.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]],\n", "\n", "\n", "\n", " [[[[0.+0.j, 1.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]]],\n", "\n", "\n", "\n", "\n", " [[[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 1.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]],\n", "\n", "\n", "\n", " [[[[0.+0.j, 0.+0.j],\n", " [1.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]]]],\n", "\n", "\n", "\n", "\n", "\n", " [[[[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[1.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]],\n", "\n", "\n", "\n", " [[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 1.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]]],\n", "\n", "\n", "\n", "\n", " [[[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 1.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]],\n", "\n", "\n", "\n", " [[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [1.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]]]]],\n", "\n", "\n", "\n", "\n", "\n", "\n", " [[[[[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[1.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]],\n", "\n", "\n", "\n", " [[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 1.+0.j],\n", " [0.+0.j, 0.+0.j]]]]],\n", "\n", "\n", "\n", "\n", " [[[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 1.+0.j]]]],\n", "\n", "\n", "\n", " [[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [1.+0.j, 0.+0.j]]]]]],\n", "\n", "\n", "\n", "\n", "\n", " [[[[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[1.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]],\n", "\n", "\n", "\n", " [[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 1.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]]],\n", "\n", "\n", "\n", "\n", " [[[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 1.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]],\n", "\n", "\n", "\n", " [[[[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]],\n", "\n", "\n", " [[[0.+0.j, 0.+0.j],\n", " [1.+0.j, 0.+0.j]],\n", "\n", " [[0.+0.j, 0.+0.j],\n", " [0.+0.j, 0.+0.j]]]]]]]])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "CX.eval(mixed=True)" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Note that the tensor order of classical-quantum maps is doubled, compared to that of pure quantum circuits:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(2, 2, 2, 2)\n", "(2, 2, 2, 2, 2, 2, 2, 2)\n" ] } ], "source": [ "print(CX.eval().shape)\n", "print(CX.eval(mixed=True).shape)" ] }, { "cell_type": "raw", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "We can implement a :term:`functor` from :term:`string diagrams ` to :term:`quantum circuits ` like so." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "image/png": "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cOAAfvzxR3R2dkKhUGDMmDG45ZZbMGvWLKSkpPAVvwMxBBANEs4cAs7X0tKCH374wdoAiouL8cMPP6C9vR0AEBERgaSkJCQkJCA8PBxhYWHWRavVylw9XYq2tjYcO3bMulRVVVnv88rKSgCAu7s74uPjrQGw6z739vaWuXpxMAQQDRKuFAJ6YzKZUFZWZhMMfvzxR5w4ccLmfP7+/hgxYoRNMAgLC7MeFxISwu8dOFhnZydqampw7NgxGI1Gm2bfddypU6dsLjN8+HDruz5dDT82Npb3lcwYAogGCVcPAX3p6OhAdXV1j0bTvQE1NDTYXEan08HPzw++vr7W5fy/+zpOp9NBqRzc/zglSRLOnDmDhoYGNDQ04PTp09b13v4+/7impiab7fn4+PQazLrCWUhICDw8PGS6tnQh/IYFETk1d3d3REZGIjIyss/zNDc3W4NBdXV1r03tyJEjNse1tLT0uT2NRgN3d/delwuddv6iUqmgVCqhVCqhUCj6PFQoFLBYLLBYLJAkqddDi8UCs9mMjo6OXpezZ8/2eVpv5+2LVqvtEZBCQ0MxduxY63F+fn4ICQmxNnqdTndF9zHJhyGAiFyet7c34uLiEBcXd8mXOXv2LBobG3uEhaampktuph0dHWhtbcXp06d7Pc1sNts08b4avEqlgiRJfQaFrnWVSnXBQOLr63tJ4USj0cDHx6fHOyI+Pj7QaDQOvKfI2TAEEJGQNBoN9Ho99Hq93KUQyWZwf/BFREREfWIIICIiEhRDABERkaAYAoiIiATFEEBERCQohgAiIiJBMQQQEREJiiGAiIhIUAwBREREgmIIICIiEhRDABERkaAYAoiIiATFEEBERCQohgAiIiJBMQQQEREJiiGAiIhIUAwBREREgmIIICIiEhRDABERkaAYAoiIiATFEEBERCQohgAiIiJBMQQQEREJiiGAiIhIUAwBREREgmIIICIiEhRDABERkaAYAoiIiATFEEBERCQohgAiIiJBMQQQEREJiiGAiIhIUAwBREREgmIIICIiEhRDABERkaAYAoiIiATFEEBERCQohgAiIiJBMQQQEREJiiGAiIhIUAwBREREgmIIICIiEhRDABERkaAYAoiIiATFEEBERCQohgAiIiJBKSRJkuQugoiu3O7du+Hm5oZrr71W7lKIyEUwBBAREQmKHwcQEREJiiGAiIhIUAwBREREgmIIICIiEhRDABERkaAYAoiIiATFEEBERCQohgAiIiJBMQQQEREJiiGAiIhIUAwBREREgmIIICIiEhRDABERkaAYAoiIiATFEEBERCQohgAiIiJBMQQQEREJiiGAiIhIUAwBREREgmIIICIiEhRDABERkaAYAoiIiATFEEBERCQohgAiIiJBMQQQEREJ6v8BQFBgrt43SOUAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAzMAAAMzCAYAAACSq0y2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAABzhUlEQVR4nO3deVyVZeL///cBRAXULAotUdOspHLDpZoWdZzMnKTFGddMxrC03TJZFERla9E2Q9NKGzV0rNGmPi1qWE2aC6ZNhS1mKpoYZSKoKHD9/ugn3whQVM65uQ6v5+PBH973de7r3XmcuHmfc5/7chljjAAAAADAMj5OBwAAAACA00GZAQAAAGAlygwAAAAAK1FmAAAAAFiJMgMAAADASpQZAAAAAFaizAAAAACwEmUGAAAAgJUoMwAAAACsRJkBAAAAYCXKDAAAAAArUWYAAAAAWIkyAwAAAMBKlBkAAAAAVqLMAAAAALASZQYAAACAlSgzAAAAAKxEmQEAAABgJcoMAAAAACtRZgAAAABYiTIDAAAAwEqUGQAAAABWoswAAAAAsBJlBgAAAICVKDMAAAAArESZAQAAAGAlygwAAAAAK1FmAAAAAFiJMgMAAADASpQZAAAAAFaizAAAAACwEmUGAAAAgJUoMwAAAACsRJkBAAAAYCXKDAAAAAArUWYAAAAAWIkyAwAAAMBKlBkAAAAAVqLMAAAAALASZQYAAACAlSgzAAAAAKxEmQEAAABgJcoMAAAAACtRZgAAAABYiTIDAAAAwEqUGQAAAABWoswAAAAAsBJlBgAAAICVKDMAAAAArESZAQAAAGAlygwAAAAAK1FmAAAAAFiJMgMAAADASpQZAAAAAFaizAAAAACwEmUGAAAAgJUoMwAAAACsRJkBAAAAYCXKDAAAAAArUWYAAAAAWIkyAwAAAMBKlBkAAAAAVqLMAAAAALASZQYAAACAlSgzAAAAAKxEmQEAAABgJcoMAAAAACtRZgAAAABYiTIDAAAAwEqUGQAAAABWoswAAAAAsBJlBgAAAICVKDMAAAAArESZAQAAAGClOltm8vLyNHjwYC1fvtzpKEC1FBcXa9SoUXrhhRecjuJ1PvzwQw0aNEjbtm1zOorXiY2NVWxsrNMxvM62bds0aNAgffTRR05HAarl4MGDGjp0qF577TWno3idZcuWafDgwcrLy3M6iiNcxhjjdAgnjBs3TjNmzFBoaKi++eYbNWjQwOlIwAnNmTNHo0ePVoMGDfTtt9+qRYsWTkfyCqWlpQoPD9fmzZs1ZMgQLVq0yOlIXuO///2vrr32WknSxx9/rGuuucbhRN5jyJAhysjIUOfOnbVx40b5+NTZ9yZhiSlTpighIUHBwcHatm2bGjdu7HQkr3DkyBFdfPHF2rVrl8aNG6ennnrK6UgeVyd/++3cuVMzZ87UiBEjtGfPHqWnpzsdCTihw4cPa/Lkybr55psVGBioKVOmOB3JayxZskSbN2/WP/7xD7322mvavHmz05G8gjFG0dHR6ty5szp16qTo6GjV0ffOatxnn32mjIwM/eMf/9Bnn32mf/3rX05HAk7op59+0pNPPqkhQ4aooKBA06dPdzqS13jhhRe0Z88ejRgxQjNnztTOnTudjuR5pg6KjIw05557rjl48KCJiooy55xzjjlw4IDTsYAqPf7448bPz898++23Zvr06cbX19ds3brV6VjWO3r0qGnbtq25+eabzbFjx8zFF19s+vXr53Qsr/Cf//zHSDLvvvuueeedd4wk89ZbbzkdyyvceOON5uKLLzbHjh0zf/3rX81FF11kjh496nQsoEoPP/ywadSokfnpp5/M+PHjTVBQkMnNzXU6lvV+/fVXc84555jRo0eb/Px8c+6555p//OMfTsfyuDpXZr788kvj4+Njnn32WWOMMTk5OaZBgwZm0qRJDicDKrd//37TtGlTM2bMGGOMMYcPHzahoaFm4MCBDiez3wsvvGBcLpf5/PPPjTHGLFmyxEgyq1evdjiZ3YqLi83ll19uevbsaUpLS01paam5/vrrzRVXXGGKi4udjme1zMxMI8n861//MsYY8/nnnxuXy2XS09MdTgZU7ocffjD+/v5mypQpxhhjfv75Z9OkSRPzwAMPOJzMfhMnTjQNGjQwOTk5xhhjnnnmGePj42O+/PJLh5N5Vp0rM7fccotp3bq1KSoqKtv22GOPmcDAQLN3714HkwGVi4mJMQEBAWbPnj1l21555RUjyaxfv97BZHYrKCgwzZo1MyNGjCjbVlpaasLDw82VV15pSktLHUxnt1dffdVIMp9++mnZtrVr1xpJ5p///KeDyexWWlpqevToYbp27Vru9XnHHXeYZs2amcLCQgfTAZUbOXKkOe+888zBgwfLtiUn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uIEDByo0NLROv1kEoG6gzOCE1q1bp7/97W/l3kVdvny5IiIiyv798ccfq2vXric91oEDB3T22WeX29a9e3fl5OTohx9+qLHMtmnUqJEmTpyoV155RVu3bq2w/+jRo8rKylKfPn3Ktvn4+KhPnz5au3ZthfHPPfec8vLyNGXKFLfmBv7oxRdfrPb3s1wul+bMmePmRHbLz8/XwoULFRkZqSNHjqiwsLDs59ChQ2Xjfr/9+E9RUZEiIyO1aNEibtsMwKv5OR3ACW+99ZaCgoLKbfvj5RD4TZs2bdS/f3+lpKRowoQJkn77JOall14qG7Njx46TlpklS5Zow4YNmj17drnt559/ftkxWrduXbPhLXLPPfdoxowZiouL0+uvv15uX15enkpKShQSElJue0hISIXys3//fqWmpuruu+9WmzZt3J4b+L2lS5dW+3dpSUmJnn76aX333XduTmWv/fv3q6ioSImJiSf85PaPvxv+6IcffuBTWgBeq06WmV69elX46H3dunV8WbIS5557rgYOHKh7771XGzZsUKtWreTv76+mTZuWjTl8+LAaNGhQ5TEyMzMVGRmpOXPm6LLLLiu3r2HDhpJU7l3Guqh+/fqaMmWK7rzzTq1fv17du3c/reOkpaWVffkf8LQDBw6c0vgjR47oxx9/dFMa+53q81mVU7nLJADYpk6WmcDAQF100UXltnHtdtWCgoIUERGhhQsX6sILL9SQIUPK7Q8ODtb+/fsrfeyHH36om2++WTNmzKh0TZpffvlF0m+lqa4bNmyYHn/8cUVHR2vVqlVll+sEBwfL19dXubm55cbn5uaqWbNmZf/evXu3nnnmGT366KMnfacWcIcmTZpoz5491R5/0UUX6YMPPnBjIrtt2bJFnTp1UmZmprp161Zu3zfffFN2Q4Dc3FwFBgZWePyGDRvUq1evsrtMAoA34jszqJZhw4YpIyNDb7/9tm666aZy+zp37qyvvvqqwmNWr16t/v37Ky0tTaNHj670uF988YXq1atX4RObusjX11fJycnKzMzUihUryrb7+/srPDxcq1atKttWWlqqVatW6aqrrirbNmXKFAUGBurRRx/1aG7guIEDB1Z52+A/8vX1PeUvtdc1F154oRo2bKg1a9YoMDCw3E9AQEDZuD/uO/7zySefqGHDhnX6El4A3o8yg2rp27evSkpKdMkl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AAB1zc6dO5WXl3faj//pp5/UvHlz7dy5U5s2bTqjLMHBwWrZsuUZHaM2OdPntqZ40/NaWlqqv/3tb/rmm2/O6Dgul0tPPfWU5s6de0bHee6559SzZ88zOga8B2UGAAAP2rlzp9q3b69Dhw6d8bGioqLO+BgBAQHKzs72ij+8a/K5PVPe9LwePHhQ77//voKDgxUREeFYjh9//FFLlizRf//7X8oMylBmAADwoLy8PB06dEgLFixQ+/btHc2SnZ2t4cOHKy8vzyv+6K4tz623Pa9NmjTRo48+qpSUFD3yyCMKDQ11JMfo0aMVHBysBx54wJH5UTtRZgAAcED79u3VpUsXp2N4JZ7bmjdu3DjNnDlTkydP1ksvveTx+b/++mu9/PLLevLJJ9W4cWOPz4/aixsAAAAA4IQaNWqkiRMnat68ecrOzvb4/BMnTtQFF1yge+65x+Nzo3ajzAAAAOCk7r77boWGhmrixIkenXfDhg1aunSpEhMT1aBBA4/OjdqPMgMAAICTql+/vqZMmaI33nhD69at89i8sbGxCgsL0x133OGxOWEPygwAAACqZdiwYbr88ssVHR0tY4zb51u5cqVWrlyp5ORk+fr6un0+2IcyAwAAgGrx9fVVcnKyVq9erRUrVrh1LmOMoqOjdeWVV2rAgAFunQv2oswAAACg2v7617/qT3/6k6Kjo1VaWuq2eV5//XVlZWUpNTVVLpfLbfPAbpQZAABQ5zz77LMaMWKE0zGs5HK5lJqaqs8++0z/+te/3DJHcXGx4uLi1K9fP11//fVumQPegTIDAADqFGOMli5dqvnz50v6bQ2TZs2a6eDBg9U+RnR0tO6//353Raz1rrnmGvXv318TJ07UsWPHavz4r7zyir755hslJyfX+LHhXSgzAABYYuTIkbrlllsqbF+9erVcLpd+/fVXj2ey0erVq3X99deXXboUExOj+++/X40aNSrbHxERoebNmyswMFCdOnXSwoULyx3j0Ucf1fz58/X99997PH9tkZycrG3btunll18+6diZM2eqdevWatCggXr06KH169dXOfbw4cOaPHmyhgwZok6dOtVgYngjygwAAKhTFixYUHaJ2c6dO/XWW29p5MiRZfvXrFmjDh066PXXX9fnn3+uyMhIjRgxQm+99VbZmODgYPXt21fp6emejl9rdOjQQcOGDVNiYqIO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2LGj+vbtq3379lUYW1paqpiYGF1zzTW66aab3BXd4ygzAACgzjh8+LB2796tdu3aSZKWLFmijh076oILLigbExsbq6lTp+rqq69W27Zt9eCDD+rGG2/UG2+8Ue5YN998szIyMjyaH3VDu3btdNdddyk5OVkHDhyoctz06dMVFRWlyMhIhYWFadasWQoICNDLL79cYeySJUu0efNmpaamln0q6Q0oMwAAwCutW7dOf/vb35SWlla2bfny5YqIiCj798cff6yuXbue9FgHDhzQ2WefXW5b9+7dlZOTox9++KHGMgPHxcfH6/Dhw3riiScq3X/06FFlZWWpT58+Zdt8fHzUp08frV27tsLYiRMn6uabb9af/vQnt+b2NMoMAKDGvfXWWwoKCir3069fP6djoY5p06aN+vfvX+5d6iVLlmjw4MFl/96xY4fOP//8Ex5nyZIl2rBhgyIjI8ttP/64HTt21GBq4Dfnn3++HnzwQc2YMUN79+6tsD8vL08lJSUKCQkptz0kJKTC+Jdeeknff/+9kpKS3JrZCZQZAECN69WrlzZv3lzuZ+7cuU7HQh1z7rnnauDAgcrJydGGDRu0b98++fv7q2nTpmVjDh8+rAYNGlR5jMzMTEVGRmrOnDm67LLLyu1r2LChJOnQoUPu+Q9AnffYY4/J399f06ZNO+1jFBYWasqUKRo+fLiuuOKKGkxXO/g5HQAA4H0CAwN10UUXlduWk5PjUBrUZUFBQYqIiNDChQt14YUXVrgdbXBwsPbv31/pYz/88EPdfPPNmjFjRqVr0vzyyy+SfitNgDs0bdpUMTExiouL08MPP6y2bduW7QsODpavr69yc3PLPSY3N1fNmjUr+/czzzyjn3/+WVOmTPFYbk/ikxkAAODVhg0bpoyMDL399tsV7uLUuXNnffXVVxUes3r1avXv319paWkaPXp0pcf94osvVK9evQqf2AA16b777tN5552n+Pj4ctv9/f0VHh6uVatWlW0rLS3VqlWrdNVVV0mSfv75Z6WlpWnMmDFq3bq1J2N7DGUGAAB4tb59+6qkpESXXHKJ6tWrV2Hf2rVrVVJSUrYtMzNT/fv31wMPPKDbb79de/fu1d69e8s+iTnu448/1rXXXlt2uRngDgEBAUpISNCiRYu0efPmcvvGjRunOXPmaP78+crOztaYMWNUWFhY9v2utLQ0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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from lambeq.backend.grammar import Functor\n", "from lambeq.backend.quantum import quantum, Id\n", "\n", "\n", "def cnot_ob(_, ty):\n", " # this implicitly maps all rigid types to 1 qubit\n", " return qubit ** len(ty)\n", "\n", "def cnot_ar(_, box):\n", " dom = len(box.dom)\n", " cod = len(box.cod)\n", " width = max(dom, cod)\n", " circuit = Id(width)\n", " for i in range(width - 1):\n", " circuit >>= Id(i) @ CX.to_diagram() @ Id(width - i - 2)\n", "\n", " # Add Bras (post-selection) and Kets (states)\n", " # to get a circuit with the right amount of\n", " # input and output wires\n", " if cod <= dom:\n", " circuit >>= Id(cod) @ Bra(*[0]*(dom - cod)).to_diagram()\n", " else:\n", " circuit = Id(dom) @ Ket(*[0]*(cod - dom)).to_diagram() >> circuit\n", " return circuit\n", "\n", "cnot_functor = Functor(target_category=quantum, ob=cnot_ob, ar=cnot_ar)\n", "diagram.draw(figsize=(5, 2))\n", "cnot_functor(diagram).draw(figsize=(8, 8), draw_type_labels=False)" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 4 }