{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "ea8ca980", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T18:56:57.457870Z", "iopub.status.busy": "2024-03-26T18:56:57.457582Z", "iopub.status.idle": "2024-03-26T18:56:57.460187Z", "shell.execute_reply": "2024-03-26T18:56:57.459770Z" }, "nbsphinx": "hidden" }, "outputs": [], "source": [ "# Copyright 2024 Keysight Technologies Inc." ] }, { "cell_type": "raw", "id": "527bbd75", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Example: Advanced Custom Compilers\n", "==================================\n", "\n", "This example builds on the :doc:`custom` example and explores several more\n", ":py:class:`~trueq.compilation.base.Pass` options for the\n", ":py:class:`~trueq.compilation.Compiler` that allow us to implement very complex\n", "compilation instructions in a simple and readable fashion.\n", "\n", "|True-Q|\\'s compilation tools work by applying an ordered list of built-in\n", "and/or user-specified :py:class:`~trueq.compilation.base.Pass` objects to a circuit in\n", "order. A :py:class:`~trueq.compilation.base.Pass` defines rules for how to decompose,\n", "replace, or remove a :py:class:`~trueq.Gate` (or more generally, an\n", ":py:class:`~trueq.Operation`\\), while possibly also adding or removing\n", ":py:class:`~trueq.Cycle`\\s.\n", "\n", ".. note::\n", "\n", " You can find an exhaustive list of all available\n", " :py:class:`~trueq.compilation.base.Pass` options in the\n", " :py:class:`~trueq.compilation.Compiler` API reference.\n", "\n", "Let's go through a concrete example. We start by defining a custom gateset through\n", "a :py:class:`~trueq.Config` object and then develop a highly customized compiler\n", "with a total of 15 passes that takes an example circuit and compiles it to our\n", "chosen gateset with a series of additional configuration options.\n", "\n", "We restrict our gateset to consist only of a single-qubit :math:`X` and :math:`Z` gate\n", "and use the :math:`CX` gate as our native entangling gate:" ] }, { "cell_type": "code", "execution_count": 2, "id": "5b3b721a", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T18:56:57.462119Z", "iopub.status.busy": "2024-03-26T18:56:57.461799Z", "iopub.status.idle": "2024-03-26T18:56:59.718222Z", "shell.execute_reply": "2024-03-26T18:56:59.717699Z" } }, "outputs": [], "source": [ "import trueq as tq\n", "import trueq.compilation as tqc\n", "\n", "config = tq.Config.from_yaml(\n", " \"\"\"\n", " Mode: ZXZ\n", " Dimension: 2\n", " Gates:\n", " - X(theta):\n", " Hamiltonian:\n", " - [X, theta]\n", " - Z(phi):\n", " Hamiltonian:\n", " - [Z, phi]\n", " - CX:\n", " Matrix:\n", " - [1.0, 0.0, 0.0, 0.0]\n", " - [0.0, 1.0, 0.0, 0.0]\n", " - [0.0, 0.0, 0.0, 1.0]\n", " - [0.0, 0.0, 1.0, 0.0]\n", " Involving:\n", " (0, 1): 2\n", " (1, 2): 0\n", " \"\"\"\n", ")" ] }, { "cell_type": "raw", "id": "256ad5ce", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Here, we also impose a restriction on single-qubit operations\n", "during the entangling gates (see our :doc:`configuration_example` example for more\n", "information on :py:class:`~trueq.Config` definitions).\n", "\n", "Using this ``config`` object, we now define our compiler as follows:" ] }, { "cell_type": "code", "execution_count": 3, "id": "c516c6ff", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T18:56:59.720737Z", "iopub.status.busy": "2024-03-26T18:56:59.720493Z", "iopub.status.idle": "2024-03-26T18:56:59.725499Z", "shell.execute_reply": "2024-03-26T18:56:59.725059Z" } }, "outputs": [], "source": [ "custom_passes = [\n", " tqc.CycleReplacement(\n", " target=tq.Cycle({(0, 1): tq.Gate.cz}),\n", " replacement=3 * [tq.Cycle({(0, 1): tq.Gate.cz})],\n", " ),\n", " tqc.Merge(max_sys=2),\n", " tqc.Native2Q(factories=config.factories, mode=\"ZXZ\"),\n", " tqc.Merge(max_sys=1),\n", " tqc.Native1Q(factories=config.factories, mode=\"ZXZ\"),\n", " tqc.RemoveId(),\n", " tqc.Justify(),\n", " tqc.InvolvingRestrictions(factories=config.factories),\n", " tqc.MarkCycles(),\n", " tqc.Justify(),\n", " tqc.CycleReplacement(\n", " target=tq.Cycle({(1, 2): tq.Gate.cx}),\n", " replacement=tq.Cycle({(1, 2): tq.Gate.cz, 0: tq.Gate.id}, marker=2),\n", " ),\n", " tqc.Native2Q(factories=config.factories, mode=\"ZXZ\"),\n", " tqc.Merge(max_sys=2, marker=2),\n", " tqc.RemoveId(marker=2),\n", " tqc.Merge(max_sys=1),\n", "]\n", "\n", "# now define a compiler which executes those passes in order\n", "custom_compiler = tqc.Compiler(passes=custom_passes)" ] }, { "cell_type": "raw", "id": "a7206855", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "We will see the effect of each pass in due time, but first notice that some passes\n", "are applied twice, for example the :py:class:`~trueq.compilation.Justify` pass is\n", "applied as both the 7th pass and 10th pass.\n", "\n", "This emphasizes the fact that the passes that are given to a\n", ":py:class:`~trueq.compilation.Compiler` are applied sequentially and that the order in\n", "which they appear in the list matters. To see this more explicitly, and to\n", "understand to effect of each pass that appears in ``custom_passes``, let's decompose\n", "the action of ``custom_compiler`` to show what what happens for every pass.\n", "\n", "First, let's define an example circuit:" ] }, { "cell_type": "code", "execution_count": 4, "id": "bfdb85be", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T18:56:59.727335Z", "iopub.status.busy": "2024-03-26T18:56:59.727174Z", "iopub.status.idle": "2024-03-26T18:56:59.751043Z", "shell.execute_reply": "2024-03-26T18:56:59.750613Z" }, "lines_to_next_cell": 0 }, "outputs": [ { "data": { "text/html": [ "
" ], "text/plain": [ "DisplayWrapper(