{ "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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atVw8uRJ7NixAydOnICTkxOOHTsmdFlUhnGkUIKIiAhIJBKYmJgIXUqZJxKJMGTIENy/fx9t27bFwIED0aNHD4SFhQldGhF9hIFStYlEIgwdOhTBwcFo1KgRevbsia+++grR0dFCl0ZlEEcKJQgPD4eZmRkkEonQpZQb5ubm+O2333D48GHcuHEDjo6O2LJlC2cricoQBkoCAEtLSxw/fhy7d+/G6dOn4eTkhMOHDwtdFpUxHCmUgD0oi69Xr14ICQlB3759MXLkSHz++ed48uSJ0GURERgo6T2RSIRBgwYhODgYzZs3R58+ffDll1/yWniS40ihBKq+S05JGRoaYtu2bfjzzz/x9OlT1K1bF6tWrUJmZqbQpRGpNAZK+liVKlVw+PBh/Prrr/jrr7/g5OSEgwcPCl0WlQEcKZSATc2Vw93dHffu3cPIkSPx3XffoXnz5ggKChK6LCKVxUBJuRGJRPjyyy8RHByMli1bon///ujbt6+8hR6pJo4USsAlb+XR09PDmjVrcPnyZSQkJKBhw4ZYsGAB0tLShC6NSOUwUFJ+zM3N4evriwMHDuD8+fNwcnJi5w4VxpGihGQyGZe8S0GzZs0QEBCA6dOnY9GiRXB1dcX169eFLotIpXAvbyqISCRC//79ERISgs8//xwDBw5E79695e30SHUwUJbQmzdvkJaWxhnKUqCpqYnvv/8eN2/ehKamJpo1a4apU6ciOTlZ6NKIVAL38qbCMjU1xYEDB+Dr64srV67A0dERe/fu5WylCuFIUUJsal766tevj2vXruGHH37Azz//jLp168LPz0/osogqtOwgwEBJRdGnTx8EBwejY8eOGDRoEHr06IFXr14JXRZ9AhwpSig7UHLJu3Spqalh2rRpuHv3LqpWrYp27dph5MiRePv2rdClEVVIUqkUAAMlFZ2JiQn27duHI0eO4Pr163BycsLOnTs5W1nBcaQooex9vM3NzQWuRDXY29vj3Llz+Pnnn7F//344OjrixIkTQpdFVOEwUFJJ9ezZEyEhIejatSs8PDzQtWtX7opWgXGkKKGIiAjo6elBT09P6FJUhlgsxujRoxEcHIz69euje/fuGDhwIBvsEikRAyUpg5GREXbv3o3jx48jICAATk5O8PHx4WxlBcSRooR4h7dwrKys8Pvvv2PPnj34888/UadOHezbt48DFZES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jQ0OHDiAP/3pT1i5ciU8PT0RExMDFxcXzJs3z+yYPXr0wMaNGxEbG4srV65ArVZjz549GDNmjFDGwcEBx48fR2JiItLS0pCSkgKZTIbAwEDEx8eja9euAAAfV2MdxGLzfpwisQTu4fEo/b8k3PvxkHEtb88e8Bi3GDZuPiZlDbVVEEntILY39peUiEUY2t3NbNlFAEhJScHKlStN1vI+fPgwXnzxRZNy5eXlEIlEQqtrc7Zt24bjx48L79PT05Geng4AGDZsGAMlEVEbEhlaOhEeET0Vjh07hpEjR0IxbSXEXr0gtneCSCx57ONc/2QmnPq9BJeXIgAAdlIx/r14OHx/D6wt8fzzz0OpVCItLa3Fx3jQvXv3oNVqMWnSJNy9e/eh/VuJiOjh2IeSiAAAN9Pex41PZqCm8LfH/mzNrRwY6rSQDZkqbEuY2NeiMFlWVobz588jISGhxcdozKxZsyCXy/Hdd989vDARET0StlASdXIlJSX48ccfAQBf/ucGDt50hNiu5UEQAGJH98RbIwNao3qt7sKFCygqKgIAODk5YciQIVauERFRx8dASUQmUn/IxaqDl1CnN0Cnf/Tbg0QsglQsQsLEvpg+yO/hHyAioqcGAyURmbl+pxLvHMjEyavFkIhFzQbL+v0hAd2QGBZk0WNuIiLqmBgoiahJ2YX3sPtMLtKzipB7uxINbxYiGCctHxnojplD/BodzU1ERJ0DAyURPZIKbR00tytQU6eHrVQMlZujyQo4RETUeTFQEhEREZFFOG0QEREREVmEgZKIiIiILMJASUREREQWYaAkIiIiIoswUBIRERGRRRgoiYiIiMgiDJREREREZBEGSiIiIiKyCAMlEREREVmEgZKIiIiILMJASUREREQWYaAkIiIiIoswUBIRERGRRRgoiYiIiMgiDJREREREZBEGSiIiIiKyCAMlEREREVmEgZKIiIiILMJASUREREQWYaAkIiIiIoswUBIRERGRRRgoiYiIiMgiDJREREREZBEGSiIiIiKyCAMlEREREVmEgZKIiIiILMJASUREREQWYaAkIiIiIoswUBIRERGRRRgoiYiIiMgiDJREREREZBEGSiIiIiKyCAMlEREREVmEgZKIiIiILMJASUREREQWYaAkIiIiIoswUBIRERGRRf4fRvaV9Kju6F8AAAAASUVORK5CYII=", "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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", "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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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/Quantinuum/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", "\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", "\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.12.12" } }, "nbformat": 4, "nbformat_minor": 2 }