{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Qubit mapping and routing\n", "\n", "**Download this notebook - {nb-download}`mapping_example.ipynb`**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this tutorial we will show how the problem of mapping from logical quantum circuits to physically permitted circuits is solved automatically in TKET. The basic examples require only the installation of pytket, ```pip install pytket```." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is a wide variety of different blueprints for realising quantum computers, including the well known superconducting and ion trap devices. Different devices come with different constraints, such as a limited primitive gate set for universal quantum computing. Often this limited gate set accommodates an additional constraint, that two-qubit gates can not be executed between all pairs of qubits." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In software, typically this constraint is presented as a \"connectivity\" graph where vertices connected by an edge represents pairs of physical qubits which two-qubit gates can be executed on. As programmers usually write logical quantum circuits with no sense of architecture (or may want to run their circuit on a range of hardware with different connectivity constraints), most quantum software development kits offer the means to automatically solve this constraint. One common way is to automatically add logical ```SWAP``` gates to a Circuit, changing the position of logical qubits on physical qubits until a two-qubit gate can be realised. This is an active area of research in quantum computing and a problem we discuss in our paper \"On The Qubit Routing Problem\" - arXiv:1902.08091." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In TKET this constraint is represented by the ```Architecture``` class. An Architecture object requires a coupling map to be created, a list of pairs of qubits which defines where two-qubit primitives may be executed. A coupling map can be produced naively by the integer indexing of nodes and edges in some architecture." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from pytket.architecture import Architecture\n", "from pytket.circuit import Node" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import networkx as nx\n", "from typing import List, Union, Tuple" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def draw_graph(coupling_map: List[Union[Tuple[int, int], Tuple[Node, Node]]]):\n", " coupling_graph = nx.Graph(coupling_map)\n", " nx.draw(coupling_graph, labels={node: node for node in coupling_graph.nodes()})" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "simple_coupling_map = [(0, 1), (1, 2), (2, 3)]\n", "simple_architecture = Architecture(simple_coupling_map)\n", "draw_graph(simple_coupling_map)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively we could use the `Node` class to assign our nodes - you will see why this can be helpful later. Lets create an Architecture with an identical graph:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "node_0 = Node(\"e0\", 0)\n", "node_1 = Node(\"e1\", 1)\n", "node_2 = Node(\"e2\", 2)\n", "node_3 = Node(\"e3\", 3)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "id_coupling_map = [(node_0, node_1), (node_1, node_2), (node_2, node_3)]\n", "id_architecture = Architecture(id_coupling_map)\n", "draw_graph(id_coupling_map)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also create an ID with an arbitrary-dimensional index. Let us make a 2x2x2 cube:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "node_000 = Node(\"cube\", [0, 0, 0])\n", "node_001 = Node(\"cube\", [0, 0, 1])\n", "node_010 = Node(\"cube\", [0, 1, 0])\n", "node_011 = Node(\"cube\", [0, 1, 1])\n", "node_100 = Node(\"cube\", [1, 0, 0])\n", "node_101 = Node(\"cube\", [1, 0, 1])\n", "node_110 = Node(\"cube\", [1, 1, 0])\n", "node_111 = Node(\"cube\", [1, 1, 1])" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "cube_coupling_map = [\n", " (node_000, node_001),\n", " (node_000, node_010),\n", " (node_010, node_011),\n", " (node_001, node_011),\n", " (node_000, node_100),\n", " (node_001, node_101),\n", " (node_010, node_110),\n", " (node_011, node_111),\n", " (node_100, node_101),\n", " (node_100, node_110),\n", " (node_110, node_111),\n", " (node_101, node_111),\n", "]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/png": "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grW1NQ4fPoyUlBTs3bu3XCc3bdo0hISEVPq+YKDk4YI1a9Zg7ty5cHNzwzvvvIOUlBSEh4fjyy+/RIsWLSr9LTUcbdu2RVpaGj777DPs3bsXjx49Qtu2bfHee+8pH8LR1dVFdHQ0vLy88Nlnn8HCwgLe3t5o3rw5pk2bVq7N0ld4LlmyBFeuXEGnTp2wf/9+vPPOO8p1DA0NcerUKfj5+eHgwYPYs2cPjI2N0a1bN6xatQrNmpU8df12T3NUfIpYIj8lvMxnycVnc10+f6wpiv4BIIJ20+bKZf89zkqtW7cOzZs3x86dOxEaGoquXbsiPDwcH374YZn1njwpeWKodEqhqkRFRZU52c3MzFRO3dWuXTv07du3sp8SaRwWlKQ21L2TK/Va22a4riWC7D+FpSqdnLaWCHavtkQXs7KTo9dFJ+fl5QVdXV1s3LgRsbGxaN++Pb7++mssWLDghb+lhsPS0rLSK/ul+vXrV+ET2f89aXn+hQLDhg2rss2mTZvCz89POWtARdq1KDneUSSFTJoPrSZNIdJ6dgLVYdn/qtxGqX9u/gLD7nbQbdkeQOXHGVByl8THxwc+Pj5VtpmcnAxra+syf4dUJjQ09KWuZEokEjx9+rTCJ82JNIVIUdMJ/ogamaSkJAwePBjBYfuxNlOOIh3DMp3cy8rZvRA6xmYwHfOs49LX0cKJhU5oX9qRVtO4ceOQlZUFsVhco99X5PHjxygoKMCoUaOQn5/Pp7yp3pQea6UspnwN/dZdq9WGvECKm1s+RJtpgdBtVVJQqnqcKRQKmJubIzw8/IWFc3V4e3tj8+bNAAAjIyPlCSKRJuEVSqJqmjHZHUDNO7nCe3+ilcuiMstXj+ytUieXlJSE8PDwF69cDZMnT0ZMTAwAoHfv3rXaNlFVXn/9dRw/fhyJV+4h+PSf0G3RttptaOkbosOSw2WWqXKcASWzLZROI1abvLy84OrqCuDZ/J9EmoZXKIle0sOHD3H+/Hnl5wsFLbH1tOqvZFsyrDvmDu6icju17eLFi8rOs2nTprC1tRU4ETVGWxOv4quE31+84guo63FG1FCwoCRSQUR6Nr6I/RXFckW5MZVV0dYSQUdLhNUje8PduvwDAkT0DI8zIvXHgpJIRTf/luLT6J+Rcu0+tCt4WOd5pd87dmkFvzGvqXT7jagx4XFGpN5YUBLVkqu5j7E3LRuJv99D9gMpnj+wRCiZTHlwNzNMsrWs8ClTInoxHmdE6okFJVEdkBQUI+uBBIXFcujpaKFjS6Myb+YgItXxOCNSHywoiYiIiEglfPUiEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREamEBSURERERqYQFJRERERGphAUlEREREank/wFpRbLv0zSOjQAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "cube_architecture = Architecture(cube_coupling_map)\n", "draw_graph(cube_coupling_map)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To avoid that tedium though we could just use our SquareGrid Architecture:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "from pytket.architecture import SquareGrid" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/png": "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foyXXnqp1jElEgkOHDiAjz76CF999RWKioowcOBAbNmypdqbnYgaE7bqlGvKrTpEzQ0D5Z+GDh2Ks2fPVtrm5eWFl19+udK2mq58VffekCFDVFfVnvb3O4UrevT+rnv37igrK6v2vddee031lJ6a2Nraqq4CTtp0Cieu50KuUMK4n2uVfQ0694VB5761jgmFHPLCPAiSFmjR0giDu7ZF93YmNd4F/bSkpCQIgoDFi6ufqnqao6Pjc/We5efnIzU1FaGhobXXD6BNmzb49ttv8e233z5zH6VSidzcXFU/GFFjwFadctrWqkPUmPFf0Z+Kiooq3b2dnp6OAwcOYMqUKSJWpXlfjLaFy5qjaj/Pu/iPi/j9q4lo2W0gLCcE4YvRL7YI+OHDhzF+/HiNLh6elJSETp064b333tPYmHl5ec9choVITGzV0b5WnafHSEsrfxRlREQEjh8vbwtQ94lHROpgoPxT165dMXXqVHTt2hW3bt3CN998Az09vRoX9G2KLM0MESSzxsKfztd5jDbO/4LiSfmUtaSlKZbLrGFp9nzN7xW+/PLLOh//WTw8PODh4aHRMY2NjVU9aQDw6quvanR8orpiq045bWrVeXqMCt99953qvxkoSUyCsj7WsWiCfH19cfjwYWRnZ0NfX1/1RIn+/fuLXVq9WH84HasS1H8U2EeuPTHLqfoF4Imo4Xl5eSEtLa3aPsim6ulWnbrK3rYQUMhh8c7SSq06EdPsav/wnw4cOABPT0+kpqZqbHYlPz8fZmZmCA0NfeYDFeri/v37UCgUsLCwwKxZsyrdTEVUH3iF8k+bN28Wu4QG5efUA+bG+gjYl4YyhfKFTtQSHQG6OgKWy6wxbqBV7R8gonrBVp0Xoy2tOkD5rFteXl7tOxJpCK9QarnM+4VYHHUex67eg0RHqPGEXfG+fXdzfDHa9oWnuYlIszp06FClVae4uBgpKSnVPva1KdtxJkOtVp3i7KuVWnXWzBjVrL8QHz16FKWlpQAAS0tLrl5B9Y6BkgAA6Tn52HYqA4ev3EFGbiGe/qEQUH4npNOr7eAjtUL3diZilUlET2GrTt2wVYdI8xgoqYqC4jLczC1ASZkCero66NLWiMtqEFGjsONMBlt1iBohBkoiImpS2KpD1PgwUBIRUZPEVh2ixoOBkoiImjy26hCJi4GSiIiIiNSiI3YBRERERNS0MVASERERkVoYKImIiIhILQyURERERKQWBkoiIiIiUgsDJRERERGphYGSiIiIiNTCQElEREREamGgJCIiIiK1MFASERERkVoYKImIiIhILQyURERERKQWBkoiIiIiUgsDJRERERGphYGSiIiIiNTCQElEREREamGgJCIiIiK1MFASERERkVoYKImIiIhILQyURERERKQWBkoiIiIiUgsDJRERERGphYGSiIiIiNTCQElEREREamGgJCIiIiK1MFASERERkVoYKImIiIhILQyURERERKQWBkoiIiIiUgsDJRERERGphYGSiIiIiNTCQElEREREamGgJCIiIiK1MFASERERkVoYKImIiIhILQyURERERKQWBkoiIiIiUsv/B3u6VeCxy4aSAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "alternative_cube_architecture = SquareGrid(2, 2, 2)\n", "draw_graph(alternative_cube_architecture.coupling)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The current range of quantum computers are commonly referred to as Noisy-Intermediate-Scale-Quantum devices i.e. NISQ devices. The impact of noise is a primary concern during compilation and incentivizes producing physically permitted circuits that have a minimal number of gates. For this reason benchmarking in this area is often completed by comparing the final number of two-qubit (or particularly SWAP gates) in compiled circuits." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However it is important to remember that adding logical SWAP gates to minimise gate count is not the only way this constraint can be met, with large scale architecture-aware synthesis methods and fidelity aware methods amongst other approaches producing viable physically permitted circuits. It is likely that no SINGLE approach is better for all circuits, but the ability to use different approaches where best fitted will give the best results during compilation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Producing physically valid circuits is completed via the `MappingManager` class, which aims to accommodate a wide range of approaches." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "from pytket.mapping import MappingManager" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `MappingManager` object requires an `Architecture` object at construction." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "mapping_manager = MappingManager(id_architecture)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All mapping is done through the `MappingManager.route_circuit` method. The `MappingManager.route_circuit` method has two arguments, the first a Circuit to be routed (which is mutated), the second a `List[RoutingMethodCircuit]` object that defines how the mapping is completed." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Later we will look at defining our own `RoutingMethodCircuit` objects, but initially lets consider one thats already available." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "from pytket.mapping import LexiLabellingMethod, LexiRouteRoutingMethod" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "lexi_label = LexiLabellingMethod()\n", "lexi_route = LexiRouteRoutingMethod(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `lexi_route` object here is of little use outside `MappingManager`. Note that it takes a lookahead parameter, which will affect the performance of the method, defining the number of two-qubit gates it considers when finding `SWAP` gates to add." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "from pytket import Circuit, OpType\n", "from pytket.circuit import display" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also look at which logical qubits are interacting." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "from pytket.utils import Graph" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Qubit connectivity\n", "\n", "\n", "\n", "q[0]\n", "\n", "q[0]\n", "\n", "\n", "\n", "q[1]\n", "\n", "q[1]\n", "\n", "\n", "\n", "q[0]--q[1]\n", "\n", "\n", "\n", "\n", "q[2]\n", "\n", "q[2]\n", "\n", "\n", "\n", "q[0]--q[2]\n", "\n", "\n", "\n", "\n", "q[3]\n", "\n", "q[3]\n", "\n", "\n", "\n", "q[0]--q[3]\n", "\n", "\n", "\n", "\n", "q[1]--q[2]\n", "\n", "\n", "\n", "\n", "q[1]--q[3]\n", "\n", "\n", "\n", "\n", "q[2]--q[3]\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Graph(c).get_qubit_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By running the `MappingManager.route_circuit` method on our circuit `c` with the `LexiLabellingMethod` and `LexiRouteRoutingMethod` objects as an argument, qubits in `c` with some physical requirements will be relabelled and the qubit graph modified (by the addition of SWAP gates and relabelling some CX as BRIDGE gates) such that the qubit graph is isomorphic to some subgraph of the full architecture." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "mapping_manager.route_circuit(c, [lexi_label, lexi_route])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The graph:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Qubit connectivity\n", "\n", "\n", "\n", "e1[1]\n", "\n", "e1[1]\n", "\n", "\n", "\n", "e0[0]\n", "\n", "e0[0]\n", "\n", "\n", "\n", "e1[1]--e0[0]\n", "\n", "\n", "\n", "\n", "e2[2]\n", "\n", "e2[2]\n", "\n", "\n", "\n", "e1[1]--e2[2]\n", "\n", "\n", "\n", "\n", "e3[3]\n", "\n", "e3[3]\n", "\n", "\n", "\n", "e2[2]--e3[3]\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Graph(c).get_qubit_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The resulting circuit may also change if we reduce the lookahead parameter." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "mapping_manager.route_circuit(c, [lexi_label, LexiRouteRoutingMethod(1)])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also pass multiple `RoutingMethod` options for Routing in a ranked List. Each `RoutingMethod` option has a function for checking whether it can usefully modify a subcircuit at a stage in Routing. To choose, each method in the List is checked in order until one returns True. This will be discussed more later." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can aid the mapping procedure by relabelling qubits in advance. This can be completed using the `Placement` class." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "from pytket.placement import Placement, LinePlacement, GraphPlacement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The default ```Placement``` assigns logical qubits to physical qubits as they are encountered during routing. ```LinePlacement``` uses a strategy described in https://arxiv.org/abs/1902.08091. ```GraphPlacement``` is described in Section 7.1 of https://arxiv.org/abs/2003.10611. Lets look at how we can use the ```LinePlacement``` class.`" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "line_placement = LinePlacement(id_architecture)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "line_placement.place(c)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that one qubit remains unplaced in this example. `LexiRouteRoutingMethod` will dynamically assign it during mapping." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Different placements will lead to different selections of SWAP gates being added. However each different routed circuit will preserve the original unitary action of the full circuit while respecting connectivity constraints." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "mapping_manager.route_circuit(c, [lexi_label, lexi_route])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The graph:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Qubit connectivity\n", "\n", "\n", "\n", "e0[0]\n", "\n", "e0[0]\n", "\n", "\n", "\n", "e1[1]\n", "\n", "e1[1]\n", "\n", "\n", "\n", "e0[0]--e1[1]\n", "\n", "\n", "\n", "\n", "e2[2]\n", "\n", "e2[2]\n", "\n", "\n", "\n", "e0[0]--e2[2]\n", "\n", "\n", "\n", "\n", "e1[1]--e2[2]\n", "\n", "\n", "\n", "\n", "e3[3]\n", "\n", "e3[3]\n", "\n", "\n", "\n", "e2[2]--e3[3]\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Graph(c).get_qubit_graph()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However, small changes to the depth of lookahead or the original assignment of `Architecture` `Node` can greatly affect the resulting physical circuit for the `LexiRouteRoutingMethod` method. Considering this variance, it should be possible to easily throw additional computational resources at the problem if necessary, which is something TKET is leaning towards with the ability to define custom `RoutingCircuitMethod` objects." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To define a new `RoutingMethodCircuit` method though, we first need to understand how it is used in `MappingManager` and routing. The `MappingManager.route_circuit` method treats the global problem of mapping to physical circuits as many sequential sub-problems. Consider the following problem." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "from pytket import Circuit" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "from pytket.placement import place_with_map" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "cluster_13\n", "\n", "CX\n", "\n", "\n", "cluster_14\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(9, 0)->(13, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 0)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 1)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(11, 0)->(14, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 1)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(12, 1)->(13, 1)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(13, 0)->(14, 1)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ = Circuit(4).CX(0, 1).CX(1, 2).CX(0, 2).CX(0, 3).CX(2, 3).CX(1, 3).CX(0, 1)\n", "naive_map = {\n", " circ.qubits[0]: node_0,\n", " circ.qubits[1]: node_1,\n", " circ.qubits[2]: node_2,\n", " circ.qubits[3]: node_3,\n", "}\n", "place_with_map(circ, naive_map)\n", "Graph(circ).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So what happens when we run the following?" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "cluster_13\n", "\n", "CX\n", "\n", "\n", "cluster_14\n", "\n", "SWAP\n", "\n", "\n", "cluster_15\n", "\n", "SWAP\n", "\n", "\n", "cluster_16\n", "\n", "BRIDGE\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(15, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(6, 0)->(15, 0)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(14, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(14, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 0)->(14, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 0)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(10, 1)->(15, 1)\n", "\n", "\n", "\n", "\n", "\n", "(16, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 0)->(16, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 1)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(12, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(16, 2)\n", "\n", "2\n", "\n", "\n", "\n", "(12, 1)->(16, 2)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(13, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(13, 1)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(16, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(14, 0)->(16, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 0)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(16, 0)->(13, 1)\n", "\n", "\n", "\n", "\n", "\n", "(16, 1)->(13, 0)\n", "\n", "\n", "\n", "\n", "\n", "(16, 2)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mapping_manager.route_circuit(circ, [lexi_route])\n", "Graph(circ).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sequential mapping typically works by partitioning the circuit into two, a first partition comprising a connected subcircuit that is physically permitted, a second partition that is not. Therefore, the first thing `MappingManager.route_circuit` does is find this partition for the passed circuit, by iterating through gates in the circuit." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will construct the partitions ourselves for illustrative purposes. Lets assume we are routing for the four qubit line architecture (qubits are connected to adjacent indices) \"simple_architecture\" we constructed earlier." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(6, 0)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(8, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 1)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_first_partition = Circuit(4).CX(0, 1).CX(1, 2)\n", "place_with_map(circ_first_partition, naive_map)\n", "Graph(circ_first_partition).get_DAG()" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(2, 0)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(9, 0)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(10, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 0)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_second_partition = Circuit(4).CX(0, 2).CX(0, 3).CX(2, 3).CX(1, 3).CX(0, 1)\n", "place_with_map(circ_second_partition, naive_map)\n", "Graph(circ_second_partition).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that there are gates in the second partition that would be physically permitted, if they were not dependent on other gates that are not." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The next step is to modify the second partition circuit to move it closer being physically permitted. Here the `LexiRouteRoutingMethod` as before will either insert a SWAP gate at the start of the partition, or will substitute a CX gate in the first slice of the partition with a BRIDGE gate." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The option taken by `LexiRouteRoutingethod(1)` is to insert a SWAP gate between the first two nodes of the architecture, swapping their logical states. How does this change the second partition circuit?" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "SWAP\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "cluster_13\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(9, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(9, 1)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 0)->(13, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(10, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(11, 1)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(12, 0)->(13, 1)\n", "\n", "\n", "\n", "\n", "\n", "(12, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_second_partition = (\n", " Circuit(4).SWAP(0, 1).CX(1, 2).CX(1, 3).CX(2, 3).CX(0, 3).CX(1, 0)\n", ")\n", "place_with_map(circ_second_partition, naive_map)\n", "Graph(circ_second_partition).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Leaving the full circuit as:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "SWAP\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "cluster_12\n", "\n", "CX\n", "\n", "\n", "cluster_13\n", "\n", "CX\n", "\n", "\n", "cluster_14\n", "\n", "CX\n", "\n", "\n", "cluster_15\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(12, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(12, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 0)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(14, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 0)->(14, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 1)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(12, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(11, 0)->(12, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(11, 1)->(13, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(12, 0)->(15, 0)\n", "\n", "\n", "\n", "\n", "\n", "(13, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(12, 1)->(13, 1)\n", "\n", "\n", "\n", "\n", "\n", "(13, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(13, 1)->(14, 1)\n", "\n", "\n", "\n", "\n", "\n", "(15, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(14, 0)->(15, 1)\n", "\n", "\n", "\n", "\n", "\n", "(14, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(15, 1)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "full_circuit = (\n", " Circuit(4).CX(0, 1).CX(1, 2).SWAP(0, 1).CX(1, 2).CX(1, 3).CX(2, 3).CX(0, 3).CX(1, 0)\n", ")\n", "place_with_map(full_circuit, naive_map)\n", "Graph(full_circuit).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After a modification is made the partition is updated." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first partition:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "SWAP\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(2, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(6, 0)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 1)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 0)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(10, 1)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_first_partition = Circuit(4).CX(0, 1).CX(1, 2).SWAP(0, 1).CX(1, 2)\n", "place_with_map(circ_first_partition, naive_map)\n", "Graph(circ_first_partition).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The second partition:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CX\n", "\n", "\n", "cluster_9\n", "\n", "CX\n", "\n", "\n", "cluster_10\n", "\n", "CX\n", "\n", "\n", "cluster_11\n", "\n", "CX\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(10, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(10, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(2, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(9, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(4, 0)->(9, 0)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(6, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(11, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(8, 0)->(11, 0)\n", "\n", "\n", "\n", "\n", "\n", "(9, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(8, 1)->(9, 1)\n", "\n", "\n", "\n", "\n", "\n", "(9, 0)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(9, 1)->(10, 1)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(10, 0)->(11, 1)\n", "\n", "\n", "\n", "\n", "\n", "(10, 1)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(11, 1)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "circ_second_partition = Circuit(4).CX(1, 3).CX(2, 3).CX(0, 3).CX(1, 0)\n", "place_with_map(circ_second_partition, naive_map)\n", "Graph(circ_second_partition).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This pattern of modification and updating the partition is repeated until the partition has reached the end of the circuit, i.e. the back side of the partition has no gates in it. Also note that the process of updating the partition has been simplified for this example with \"physically permitted\" encapsulating two-qubit gate constraints only - in the future we expect other arity gates to provide constraints that need to be met. Also note that any modification to the second circuit can willfully modify the qubit labelling and a token swapping network will be automatically added to conform to the new labelling." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now enough about how `MappingManager` works to add our own `RoutingMethodCircuit`. While `LexiRouteRoutingMethod` is implemented in c++ TKET, giving it some advantages, via lambda functions we can define our own `RoutingMethodCircuit` in python." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A python defined `RoutingMethodCircuit` requires three arguments. The first is a function that given a Circuit (the circuit after the partition) and an Architecture, returns a bool (determining whether the new circuit should be substituted in a full routing process), a new Circuit (a modification of the original circuit such as an added SWAP) a Dict between qubits reflecting any relabelling done in the method, and a Dict between qubits giving any implicit permutation of qubits (such as by adding a SWAP). For some clarity (we will write an example later), lets look at an example function declaration." ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "from typing import Dict" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "def route_subcircuit_func(\n", " circuit: Circuit, architecture: Architecture\n", ") -> Tuple[bool, Circuit, Dict[Node, Node], Dict[Node, Node]]:\n", " return ()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first return is a bool which detemrines if a given `RoutingMethodCircuit` is suitable for providing a solution at a given partition. `MappingManager.route_circuit` accepts a List of of `RoutingMethod` defining how solutions are found. At the point the partition circuit is modified, the circuit is passed to `RoutingMethodCircuit.routing_method` which additionally to finding a subcircuit substitution, should determine whether it can or can't helpfully modify the partition boundary circuit, and return True if it can. The first `RoutingMethodCircuit` to return True is then used for modification - meaning the ordering of List elements is important." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The third argument sets the maximum number of gates given in the passed Circuit and the fourth argument sets the maximum depth in the passed Circuit." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`LexiRouteRoutingMethod` will always return True, because it can always find some helpful SWAP to insert, and it can dynamically assign logical to physical qubits. Given this, lets construct a more specialised modification - an architecture-aware decomposition of a distance-2 CRy gate. Lets write our function type declarations for each method:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "def distance2_CRy_decomp(\n", " circuit: Circuit, architecture: Architecture\n", ") -> Tuple[bool, Circuit, Dict[Node, Node], Dict[Node, Node]]:\n", " return (False, Circuit(), {}, {})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Where do we start? Lets define a simple scope for our solution: for a single gate in the passed circuit (the circuit after the partition) that has OpType CRy, if the two qubits it's acting on are at distance 2 on the architecture, decompose the gate using BRIDGE gates." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first restriction is to only have a single gate from the first slice - we can achieve this by setting both the maximum depth and size parameters to 1." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The second restriction is for the gate to have OpType CRy and for the qubits to be at distance 2 - we can check this restriction in a `distance2_CRy_check` method." ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "def distance2_CRy_check(circuit: Circuit, architecture: Architecture) -> bool:\n", " if circuit.n_gates != 1:\n", " raise ValueError(\n", " \"Circuit for CRy check should only have 1 gate, please change parameters of method declaration.\"\n", " )\n", " command = circuit.get_commands()[0]\n", " if command.op.type == OpType.CRy:\n", " # Architecture stores qubits under `Node` identifier\n", " n0 = Node(command.qubits[0].reg_name, command.qubits[0].index)\n", " n1 = Node(command.qubits[1].reg_name, command.qubits[1].index)\n", " # qubits could not be placed in circuit, so check before finding distance\n", " if n0 in architecture.nodes and n1 in architecture.nodes:\n", " # means we can run the decomposition\n", " if architecture.get_distance(n0, n1) == 2:\n", " return True\n", " return False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `distance2_CRy_check` confirms whether the required restrictions are respected. Given this, if the `distance2_CRy_decomp` method is called we know where to add the decomposition." ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "def distance2_CRy_decomp(\n", " circuit: Circuit, architecture: Architecture\n", ") -> Tuple[bool, Circuit, Dict[Node, Node], Dict[Node, Node]]:\n", " worthwhile_substitution = distance2_CRy_check(circuit, architecture)\n", " if worthwhile_substitution == False:\n", " return (False, Circuit(), {}, {})\n", " command = circuit.get_commands()[0]\n", " qubits = command.qubits\n", " # Architecture stores qubits under `Node` identifier\n", " n0 = Node(qubits[0].reg_name, qubits[0].index)\n", " n1 = Node(qubits[1].reg_name, qubits[1].index)\n", "\n", " # need to find connecting node for decomposition\n", " adjacent_nodes_0 = architecture.get_adjacent_nodes(n0)\n", " adjacent_nodes_1 = architecture.get_adjacent_nodes(n1)\n", " connecting_nodes = adjacent_nodes_0.intersection(adjacent_nodes_1)\n", " if len(connecting_nodes) == 0:\n", " raise ValueError(\"Qubits for distance-2 CRy decomp are not at distance 2.\")\n", " connecting_node = connecting_nodes.pop()\n", " c = Circuit()\n", "\n", " # the \"relabelling map\" empty, and the permutation map is qubit to qubit, so add here\n", " permutation_map = dict()\n", " for q in circuit.qubits:\n", " permutation_map[q] = q\n", " c.add_qubit(q)\n", " # rotation, can assume only parameter as CRy\n", " angle = command.op.params[0]\n", " c.Ry(angle, qubits[1])\n", " # distance-2 CX decomp\n", " c.CX(qubits[0], connecting_node).CX(connecting_node, qubits[1])\n", " c.CX(qubits[0], connecting_node).CX(connecting_node, qubits[1])\n", " # rotation\n", " c.Ry(-1 * angle, qubits[1])\n", " # distance-2 CX decomp\n", " c.CX(qubits[0], connecting_node).CX(connecting_node, qubits[1])\n", " c.CX(qubits[0], connecting_node).CX(connecting_node, qubits[1])\n", "\n", " # the \"relabelling map\" is just qubit to qubit\n", " return (True, c, {}, permutation_map)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before turning this into a `RoutingMethod` we can try it ourselves." ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "Circuit\n", "\n", "\n", "cluster_q_inputs\n", "\n", "\n", "\n", "cluster_q_outputs\n", "\n", "\n", "\n", "cluster_8\n", "\n", "CRy(0.6)\n", "\n", "\n", "\n", "(0, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(8, 0)\n", "\n", "0\n", "\n", "\n", "\n", "(0, 0)->(8, 0)\n", "\n", "\n", "\n", "\n", "\n", "(2, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(3, 0)\n", "\n", "e1[1]\n", "\n", "\n", "\n", "(2, 0)->(3, 0)\n", "\n", "\n", "\n", "\n", "\n", "(4, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(8, 1)\n", "\n", "1\n", "\n", "\n", "\n", "(4, 0)->(8, 1)\n", "\n", "\n", "\n", "\n", "\n", "(6, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(7, 0)\n", "\n", "e3[3]\n", "\n", "\n", "\n", "(6, 0)->(7, 0)\n", "\n", "\n", "\n", "\n", "\n", "(1, 0)\n", "\n", "e0[0]\n", "\n", "\n", "\n", "(5, 0)\n", "\n", "e2[2]\n", "\n", "\n", "\n", "(8, 0)->(1, 0)\n", "\n", "\n", "\n", "\n", "\n", "(8, 1)->(5, 0)\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "test_c = Circuit(4)\n", "test_c.CRy(0.6, 0, 2)\n", "place_with_map(test_c, naive_map)\n", "Graph(test_c).get_DAG()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we can see, our circuit has one CRy gate at distance two away." ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "print(distance2_CRy_check(test_c, id_architecture))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our method returns True, as expected! We should also test cases where it returns errors or False." ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n" ] } ], "source": [ "test_c_false = Circuit(4)\n", "test_c_false.CRy(0.4, 0, 1)\n", "place_with_map(test_c_false, naive_map)\n", "print(distance2_CRy_check(test_c_false, id_architecture))" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error reached!\n" ] } ], "source": [ "test_c_error = Circuit(4)\n", "test_c_error.CRy(0.6, 0, 2)\n", "test_c_error.CRy(0.4, 0, 1)\n", "place_with_map(test_c_error, naive_map)\n", "try:\n", " distance2_CRy_check(test_c_error, id_architecture)\n", "except ValueError:\n", " print(\"Error reached!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Does the decomposition work?" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "test_c = Circuit(4)\n", "test_c.CRy(0.6, 0, 2)\n", "place_with_map(test_c, naive_map)\n", "decomp = distance2_CRy_decomp(test_c, id_architecture)\n", "display.render_circuit_jupyter(decomp[1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Great! Our check function and decomposition method are both working. Lets wrap them into a `RoutingMethodCircuit` and try them out." ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "from pytket.mapping import RoutingMethodCircuit" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "cry_rmc = RoutingMethodCircuit(distance2_CRy_decomp, 1, 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use our original `MappingManager` object as it is defined for the same architecture. Lets try it out on a range of circumstances." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we pass it a full CX circuit without `LexiRouteRoutingMethod`, we should find that `MappingManager` throws an error, as none of the passed methods can route for the given circuit." ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error reached!\n" ] } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "place_with_map(c, naive_map)\n", "try:\n", " mapping_manager.route_circuit(c, [cry_rmc])\n", "except RuntimeError:\n", " print(\"Error reached!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, we can add `LexiRouteRoutingMethod` on top:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "place_with_map(c, naive_map)\n", "mapping_manager.route_circuit(c, [cry_rmc, LexiRouteRoutingMethod(10)])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However as there are no CRy gates our new method is unused. We can add one:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CRy(0.6, 0, 2)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "mapping_manager.route_circuit(c, [lexi_label, cry_rmc, LexiRouteRoutingMethod(10)])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This time we can see our decomposition! If we reorder the methods though `LexiRouteRoutingMethod` is checked first (and returns True), so our new method is unused. The order is important!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, lets see what happens if the gate is not at the right distance initially." ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = (\n", " Circuit(4)\n", " .CRy(0.6, 0, 3)\n", " .CX(0, 1)\n", " .CX(1, 2)\n", " .CX(0, 2)\n", " .CX(0, 3)\n", " .CX(2, 3)\n", " .CX(1, 3)\n", " .CX(0, 1)\n", " .measure_all()\n", ")\n", "mapping_manager.route_circuit(c, [lexi_label, cry_rmc, LexiRouteRoutingMethod(10)])\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Above a SWAP gate is inserted by `LexiRouteRoutingMethod` before anything else." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For anyone interested, a simple extension exercise could be to extend this to additionally work for distance-2 CRx and CRz. Alternatively one could improve on the method itself - this approach always decomposes a CRy at distance-2, but is this a good idea?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Also note that higher performance solutions are coded straight into the TKET c++ codebase. This provides advantages, including that Circuit construction and substitution is unnecessary (as with python) as the circuit can be directly modified, however the ability to produce prototypes at the python level is very helpful. If you have a great python implementation but are finding some runtime bottlenecks, why not try implementing it straight into TKET (the code is open source at https://github.com/CQCL/tket)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Besides the `LexiRouteRoutingMethod()` and the `LexiLabellingMethod()` there are other routing methods in pytket, such as the `AASRouteRoutingMethod()` and the corresponding `AASLabellingMethod()`, which are used to route phase-polynomial boxes using architecture-aware synthesis. Usually circuits contain non-phase-polynomial operations as well, so it is a good idea to combine them with the `LexiRouteRoutingMethod()`, as in the following example:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [], "source": [ "from pytket.mapping import AASRouteRoutingMethod, AASLabellingMethod\n", "from pytket.circuit import PhasePolyBox, Qubit\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n", " \n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "c = Circuit(3, 3)\n", "n_qb = 3\n", "qubit_indices = {Qubit(0): 0, Qubit(1): 1, Qubit(2): 2}\n", "phase_polynomial = {(True, False, True): 0.333, (False, False, True): 0.05}\n", "linear_transformation = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])\n", "p_box = PhasePolyBox(n_qb, qubit_indices, phase_polynomial, linear_transformation)\n", "c.add_phasepolybox(p_box, [0, 1, 2])\n", "c.CX(0, 1).CX(0, 2).CX(1, 2)\n", "display.render_circuit_jupyter(c)\n", "nodes = [Node(\"test\", 0), Node(\"test\", 1), Node(\"test\", 2)]\n", "arch = Architecture([[nodes[0], nodes[1]], [nodes[1], nodes[2]]])\n", "mm = MappingManager(arch)\n", "mm.route_circuit(\n", " c,\n", " [\n", " AASRouteRoutingMethod(1),\n", " LexiLabellingMethod(),\n", " LexiRouteRoutingMethod(),\n", " AASLabellingMethod(),\n", " ],\n", ")\n", "display.render_circuit_jupyter(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case the order of the methods is not very relevant, because in each step of the routing only one of the methods is suitable. In the first part of the circuit the mapping is done without inserting swaps by the AAS method; in the second part one swap gate is added to the circuit." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.2" } }, "nbformat": 4, "nbformat_minor": 2 }