{ "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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UGXLzMwEANStW7fE3+ddu3YVGNGNjo5GdHQ0AMDa2pqFkoioDImUpV34jogqpYiICHh4eGBT8B/4NlqBPF0jiMTFz6sszt01I2DSqhvMuo1RvWagK4ZsmjtszEu3V7dEIkF8fDzOnz9fqs8XJSsrC8+ePcPkyZMRGhqqKq1ERPT2OEJJREUa6zMcAGA1ajUM6jZ9p8/mProDZX4OTF2GFnh94cCWpS6TSqUSERER2Lp1a6k+X5x58+bhxx9/BAAYG/PJcyKi0uAIJREV8OTJE1y6dEn19V85Flh3KlHt887s9R4medipfZ6yduPGDdW8VF1dXXTt2lXYQEREWoiFkohKtONCAubvv458hbLAnMqS6IhF0BWLsHBgSwxvb1vyB4iISCuxUBLRW7mbmo0v91zFyZsp0HntYZ3XvXzfza4Wlg5xKPVtbiIi0g4slET0TuIeZmBbVALCbyQj4XE2Xv0BIsKLRcs9mtXBCBfbQk9zExFR5cRCSUSllpWTj/jHWcjNV0BfV4yGFsbcAYeIqApioSQiIiIitXDrRSIiIiJSCwslEREREamFhZKIiIiI1MJCSURERERqYaEkIiIiIrWwUBIRERGRWlgoiYiIiEgtLJREREREpBYWSiIiIiJSCwslEREREamFhZKIiIiI1MJCSURERERqYaEkIiIiIrWwUBIRERGRWlgoiYiIiEgtLJREREREpBYWSiIiIiJSCwslEREREamFhZKIiIiI1MJCSURERERqYaEkIiIiIrWwUBIRERGRWlgoiYiIiEgtLJREREREpBYWSiIiIiJSCwslEREREamFhZKIiIiI1MJCSURERERqYaEkIiIiIrWwUBIRERGRWlgoiYiIiEgtLJREREREpBYWSiIiIiJSCwslEREREamFhZKIiIiI1MJCSURERERqYaEkIiIiIrX8H7kfevBnsD5uAAAAAElFTkSuQmCC", "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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8krcNRdQKmA/fIG6qxI6QVzyC9+wceNGzJ49G3fv3tXZhfBvv/0GZ2dnnDhxoswrYBRHpVIhKSkJjx49QteuXbFmzRrMnDlTJ2MTlYXe3qHs378/du/ejcTERJiamuK9997D8uXLa1SYBIBRPZrgRXo21kbcLvcYpg3yr6ZnSVrjc/eSr6yrM0tLS3h5eQldBlEh7KqUTVXtqrz33ns6C5NAfmu8uCcmEVUmvb1DqW/2XH2IRcdikadUlenN2tBABCMDEZYMdcZHPZqU/AIiqhDsqpSePnVV8vLyNFa5aNWqlcbjf4kqCwOlHnmUnAH/wzdxIf4FDA1E7wyWBfvfb2GH5cM6oLFtyYsGE1HFGTduHKKiogp1Vbp27Sp0aToXHHVHq65KAX3oqhBVFQyUeujOn6+w68pDRN1+hodJGRprv4mQv7yGe6t68OnZROPb3ERElYVdFaLqhYFSz73OzsP9pNfIyVPCxMgAjnUtYGGqt1NriagKYVeFqPpgoCQioiqNXRWiqo+BkoiIqg12VYiqJgZKIiIiItKKXj7Lm4iIiIh0h4GSiIiIiLTCQElEREREWmGgJCIiIiKtMFASERERkVYYKImIiIhIKwyURERERKQVBkoiIiIi0goDJRERERFphYGSiIiIiLTCQElEREREWmGgJCIiIiKtMFASERERkVYYKImIiIhIKwyURERERKQVBkoiIiIi0goDJRERERFphYGSiIiIiLTCQElEREREWmGgJCIiIiKtMFASERERkVYYKImIiIhIKwyURERERKQVBkoiIiIi0goDJRERERFphYGSiIiIiLTCQElEREREWmGgJCIiIiKtMFASERERkVYYKImIiIhIKwyURERERKQVBkoiIiIi0goDJRERERFphYGSiIiIiLTCQElEREREWmGgJCIiIiKtMFASERERkVb+H2fCmOi8V/mAAAAAAElFTkSuQmCC", "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 }