{ "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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Sxf4+/sjMDAQRkZG2Lx5M2xsbDSNbh/m5OQEf39/nDp1Ch07dsTmzZuRnZ2NsLAwzWsCAwMRGxuLUaNGQS6Xw8XFBYWFhTh//jyio6ORlpaG9u3bP3Zebt7xSABAWU5lHfdTElF84yKAqvNy845G4N7xnVUan9c0L7dz584ICAjAsmXLUFZWhv79+2P//v04evQoIiIiqjQ1V/fhDAsLq/GGGzVzc3N8+umnePvttzF+/Hi4ubnh6NGjCA8Px5IlS9C2bdtaPiERERHVhoFSD3Tq1AlJSUlYsGABIiIikJ+fj06dOkEmk2luQDExMcG+ffswc+ZMLFiwALa2tggICIBEIoGfn1+1ffbq1QurV69GYGAg/vjjD3Tr1g27du2Cm5ub5jUWFhY4cuQIQkJCEBUVhW3btsHKygpOTk4IDg5GmzaV1xx1/ruVhlhc83Wc946GV3lceO57zdcPB0pVWTEAEYxaV56+V8/LrekOy6VLl0IikWDdunXYsmULevXqhfDwcEyZMqXK69SzbO3s7Gr+5j5k5syZMDExwfLlyxEbGwsHBwd8+eWXmDNnzmPfS0RERI/G0Yv0WIcPH8bQoUNhP34BxHa9ITZrDZG4fqMPASBr67swtuoAG68gAICpsRg/vOuqVe+3CRMmIC0tDb/88kuD9/FvBQUFKCkpwWuvvYZ79+6xDyUREdFj8BpKqrPMqE9xY9VUlGb/Ve/3KkuKUHrrKqyHTNM894lHH63CpEqlwuHDh7F48eIG76Mm3t7esLGxwYkTJ3S6XyIiopaKK5T0WHfv3sWvv/4KANj/2w3EZlpqPcM7UPok3h7aUxfl6dy5c+dw69YtAEDr1q3x0ksvCVwRERGRfmOgpHqLPHWd83KJiIhIg4GSGiT9TlG95+UO6dme83KJiIhaIAZK0grn5RIREREDJekM5+USEREZJgZKIiIiItIK2wYRERERkVYYKImIiIhIKwyURERERKQVBkoiIiIi0goDJRERERFphYGSiIiIiLTCQElEREREWmGgJCIiIiKtMFASERERkVYYKImIiIhIKwyURERERKQVBkoiIiIi0goDJRERERFphYGSiIiIiLTCQElEREREWmGgJCIiIiKtMFASERERkVYYKImIiIhIKwyURERERKQVBkoiIiIi0goDJRERERFphYGSiIiIiLTCQElEREREWmGgJCIiIiKtMFASERERkVYYKImIiIhIKwyURERERKQVBkoiIiIi0goDJRERERFphYGSiIiIiLTCQElEREREWmGgJCIiIiKtMFASERERkVYYKImIiIhIKwyURERERKQVBkoiIiIi0goDJRERERFp5f8BJkgahdmk60QAAAAASUVORK5CYII=", "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.11.2" } }, "nbformat": 4, "nbformat_minor": 2 }