{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "2f5c3ad4", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T19:01:27.510577Z", "iopub.status.busy": "2024-03-26T19:01:27.510208Z", "iopub.status.idle": "2024-03-26T19:01:27.512758Z", "shell.execute_reply": "2024-03-26T19:01:27.512400Z" }, "nbsphinx": "hidden" }, "outputs": [], "source": [ "# Copyright 2024 Keysight Technologies Inc." ] }, { "cell_type": "raw", "id": "7cc8ed15", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "\n", "Advanced Qudit Framework\n", "========================\n", "This tutorial outlines the mathematical framework needed to do computations with\n", "qudits and outlines how users can use this framework within |True-Q|.\n", "\n", "The Weyl-Heisenberg Group\n", "-------------------------\n", "The Weyl-Heisenberg group is a generalization of the Pauli group to\n", ":math:`d`\\-dimensional systems and has operators analogous to the Pauli :math:`X` and\n", ":math:`Z` operators, which are referred to as \"shift\" (:math:`X`\\) and \"clock\"\n", "(:math:`Z`\\) operators. In cases where the dimension is unclear, we will denote the\n", ":math:`d`\\-dimensional shift (clock) matrix as :math:`X_d` (:math:`Z_d`\\).\n", "\n", "These operators are defined to be,\n", "\n", ".. math::\n", " X &= \\sum_{a\\in\\mathbb{Z}_d}\\ket{a \\oplus 1}\\bra{a}\\\\\n", " Z &= \\sum_{a\\in\\mathbb{Z}_d}\\textrm{exp}(2\\pi i a/d)\\ket{a}\\bra{a},\n", "\n", "where :math:`\\oplus` denotes addition modulo :math:`d`\\. When :math:`d=2`\\,\n", "these operators are the familiar Pauli :math:`X` and :math:`Z` operators. Their\n", "actions,\n", "\n", ".. math::\n", " X\\ket{a} &= \\ket{a+1}\\\\\n", " Z\\ket{a} &= \\textrm{exp}(2\\pi i a/d)\\ket{a},\n", "\n", "where :math:`a\\in\\mathbb{Z}_d` and operations act according to modular\n", "arithmetic, for example for 3-dimensional qudits (aka *qutrits*),\n", ":math:`X\\ket{2}=\\ket{0}`\\.\n", "\n", "Often, we specify elements of the Weyl-Heisenberg group (Weyl operators) by the powers\n", "of the clock and shift operators acting on a qudit along with an integer :math:`k`\n", "which specifies the phase. For a single-qudit system, a Weyl operator can be written\n", "as :math:`\\omega(k)X^xZ^z`\\, where\n", "\n", ".. math::\n", " \\omega(k) =\\begin{cases}\n", " \\textrm{exp}(\\pi i(2k+x\\cdot z\\%2)/2) & d=2 \\\\\n", " \\textrm{exp}(2\\pi ik/d) & d>2\n", " \\end{cases}\n", "\n", "Then, the powers and phase which specify that Weyl operator are :math:`(x, z)\\in\n", "\\mathbb{Z}_d^2` and :math:`k` respectively.\n", "\n", "|\n", "\n", ".. dropdown:: **Advanced note**: Expectation values of Weyl operators\n", "\n", " For :math:`d>2`\\, the Weyl operators are unitary but not Hermitian. This means\n", " that they can still be used to describe the evolution of quantum systems.\n", " However, the expectation of a Weyl operator :math:`W` for a system in the state\n", " :math:`\\rho`\\, that is, :math:`\\mathrm{Tr}(W^\\dagger \\rho)`\\, may be\n", " complex-valued, i.e. takes the form :math:`r*\\textrm{exp}(i\\phi)`\\. When\n", " :math:`\\rho` is expected to be an eigenstate of :math:`W` (e.g.\n", " :math:`|0\\rangle` for :math:`W = Z`\\)\\, then any other eigenstates are error\n", " states. The phase, :math:`\\phi'`\\, of a measured expectation value,\n", " :math:`r'*\\textrm{exp}[i(\\phi+\\phi')]`\\, relative to the ideal phase,\n", " :math:`r*\\textrm{exp}(i\\phi)`\\, indicates that the error states were not\n", " observed with equal frequencies.\n", "\n", " As the Weyl operators form a trace-orthogonal operator basis with respect to the\n", " Hilbert-Schmidt inner product, any state :math:`\\rho` can be expanded as\n", " :math:`\\sum_W \\frac{p_W(\\rho)}{d^n} W` where\n", " :math:`p_W(\\rho) = \\mathrm{Tr}(W^\\dagger \\rho)` and :math:`n` is the number of\n", " qudits. The expectation value :math:`\\mathrm{Tr}(W^\\dagger \\rho)` is thus the\n", " :math:`W` component of :math:`\\rho`\\.\n", "\n", "\n", "Defining Weyl Operators in |True-Q|\n", "-----------------------------------\n", "\n", "A :math:`n`\\-qudit Weyl operator can be expressed as an element\n", ":math:`w\\in\\mathbb{Z}_d^{2n}` and an integer specifying the phase, where the first\n", "(last) :math:`n` entries of :math:`w` are the powers of the shift (clock) operators\n", "acting on each of the first (last) :math:`n` qudits. For example, the 3-qudit Weyl\n", "operator :math:`X\\otimes X^2\\otimes Z` can be specified by :math:`1,2,0,0,0,1` with\n", ":math:`k=0`. To initialize a Weyl operator from a string in |True-Q|\\, we specify the\n", "action of the operator on each individual qudit sequentially, separated by a ``W``.\n", "For example, the operator :math:`X\\otimes X^2\\otimes Z` given above would be specified\n", "by ``W10W20W01`` as" ] }, { "cell_type": "code", "execution_count": 2, "id": "211abe04", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T19:01:27.514594Z", "iopub.status.busy": "2024-03-26T19:01:27.514326Z", "iopub.status.idle": "2024-03-26T19:01:29.763094Z", "shell.execute_reply": "2024-03-26T19:01:29.762622Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2 0 0 0 1]]\n" ] } ], "source": [ "import numpy as np\n", "import trueq.math as tqm\n", "\n", "# create a three-qutrit Weyls object which stores the example given above\n", "weyl = tqm.Weyls(\"W10W20W01\", 3)\n", "\n", "# we can access the powers as follows:\n", "print(weyl.powers)" ] }, { "cell_type": "raw", "id": "80075837", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "The second argument in the constructor specifies the dimension of the qudits. If the\n", "global dimension has been specified by ``tq.settings.set_dim(3)``, these methods will\n", "use the specified dimension automatically. To instantiate a\n", ":py:class:`~trueq.math.weyl.Weyls` object with multiple Weyl operators, we separate\n", "the operators by a ``_`` character. In this notation, all operators must act on the\n", "same number of qudits. For example, for the pair :math:`\\{Z\\otimes XZ^2,\n", "X^2\\otimes XZ\\}`\\, we can run" ] }, { "cell_type": "code", "execution_count": 3, "id": "91d9a94b", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T19:01:29.765600Z", "iopub.status.busy": "2024-03-26T19:01:29.764981Z", "iopub.status.idle": "2024-03-26T19:01:29.779895Z", "shell.execute_reply": "2024-03-26T19:01:29.779493Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "
True-Q formatting will not be loaded without trusting this\n", "notebook or rerunning the affected cells. Notebooks can be marked as trusted by clicking\n", "\"File -> Trust Notebook\".
\n", "\n", "\n", "\n", "
\n", "
\n", "
Type:
\n", "
  • Weyls
\n", "\n", "
Dim:
\n", "
  • 3
\n", "
\n", "
\n", " \n", "
Powers:
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "
X0X1Z0Z1
00112
12101
\n", "
\n", "
\n" ], "text/plain": [ "Weyls('W01W12_W20W11', dim=3)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tqm.Weyls(\"W01W12_W20W11\", 3)" ] }, { "cell_type": "raw", "id": "469dd758", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ ".. note::\n", " In the example above, we stored Weyl operators as\n", " :py:class:`~trueq.math.weyl.Weyls` objects. |True-Q| has several classes for\n", " storing Weyl operators which are used in different contexts. The\n", " :py:class:`~trueq.math.weyl.Weyls` class does not store phases, and is used, for\n", " example, to specify targeted errors for error diagnostic protocols such as\n", " :doc:`../../guides/error_diagnostics/cb`\\. Some of |True-Q|\\'s classes for Weyl\n", " operators account for phases and some do not. If you are unsure which is relevant\n", " for your use-case, consult the API references.\n", "\n", "\n", "The Clifford Group on Qudits\n", "----------------------------\n", "The :math:`n`\\-qudit Clifford group is defined to be the group of unitary operators\n", "that map each :math:`n`\\-qudit Weyl operator to a phase multiple of an\n", ":math:`n`\\-qudit Weyl operator under conjugation. This coincides with the definition\n", "of the :math:`n`\\-qubit Clifford group with respect to the Pauli group. We can specify\n", "elements of the :math:`d`\\-dimensional Clifford group by their unique action on a\n", "basis of the Weyl-Heisenberg group. |True-Q| follows the convention of specifying the\n", "mapping of the Weyl basis described by the rows of an identity matrix, that is the set\n", ":math:`\\{X_1, X_2,...,X_n, Z_1,Z_2,...,Z_n\\}`\\.\n", "\n", "A :py:class:`~trueq.math.weyl.Clifford` object then stores the outcome of applying the\n", "corresponding Clifford operator to each of those basis elements. For example, a\n", "generalized Hadamard (or Fourier) gate on 2 qudits maps the basis elements\n", ":math:`XI\\rightarrow ZI`\\, :math:`IX\\rightarrow IZ`\\, :math:`ZI\\rightarrow X^{d-1}I`\\,\n", "and :math:`IZ\\rightarrow IX^{d-1}`\\, and would therefore be stored as the ordered list\n", ":math:`\\{ZI,\\: IZ,\\: X^{d-1}I,\\: IX^{d-1}\\}`\\. We can instantiate a\n", ":py:class:`~trueq.math.weyl.Clifford` object which stores a Hadamard as\n", "\n", "instantiate a 2-qudit Hadamard gate with dimension 3" ] }, { "cell_type": "code", "execution_count": 4, "id": "cc9b3a92", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T19:01:29.781849Z", "iopub.status.busy": "2024-03-26T19:01:29.781541Z", "iopub.status.idle": "2024-03-26T19:01:29.783999Z", "shell.execute_reply": "2024-03-26T19:01:29.783596Z" } }, "outputs": [], "source": [ "hadamard = tqm.Clifford(\"W01W00_W00W01_W20W00_W00W20\", [0, 0, 0, 0], 3)" ] }, { "cell_type": "raw", "id": "c193f355", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "The second argument provides the phases on the basis elements after the Clifford is\n", "applied. |True-Q| has :py:class:`~trueq.math.weyl.Clifford` constructors for\n", "generalized versions of the Hadamard (:py:meth:`~trueq.math.weyl.Clifford.fourier`),\n", "controlled-X (:py:meth:`~trueq.math.weyl.Clifford.cx`) and controlled-Z\n", "(:py:meth:`~trueq.math.weyl.Clifford.cz`) gates." ] }, { "cell_type": "code", "execution_count": 5, "id": "9fd90044", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T19:01:29.785845Z", "iopub.status.busy": "2024-03-26T19:01:29.785574Z", "iopub.status.idle": "2024-03-26T19:01:29.787849Z", "shell.execute_reply": "2024-03-26T19:01:29.787457Z" } }, "outputs": [], "source": [ "built_in_h = tqm.Clifford.fourier(3)" ] }, { "cell_type": "raw", "id": "f560ab8f", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "We can retrieve the unitary matrix representation of a\n", ":py:class:`~trueq.math.weyl.Clifford` by calling\n", ":py:meth:`~trueq.math.weyl.Clifford.mat`\\. Let's use the matrices to check if these\n", "constructions are equivalent:" ] }, { "cell_type": "code", "execution_count": 6, "id": "1c54549f", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T19:01:29.789618Z", "iopub.status.busy": "2024-03-26T19:01:29.789350Z", "iopub.status.idle": "2024-03-26T19:01:29.792872Z", "shell.execute_reply": "2024-03-26T19:01:29.792461Z" } }, "outputs": [ { "data": { "text/plain": [ "array([[ True, True, True, True, True, True, True, True, True],\n", " [ True, True, True, True, True, True, True, True, True],\n", " [ True, True, True, True, True, True, True, True, True],\n", " [ True, True, True, True, True, True, True, True, True],\n", " [ True, True, True, True, True, True, True, True, True],\n", " [ True, True, True, True, True, True, True, True, True],\n", " [ True, True, True, True, True, True, True, True, True],\n", " [ True, True, True, True, True, True, True, True, True],\n", " [ True, True, True, True, True, True, True, True, True]])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.isclose(hadamard.mat, np.kron(built_in_h.mat, built_in_h.mat))" ] }, { "cell_type": "raw", "id": "2db9021e", "metadata": { "raw_mimetype": "text/restructuredtext" }, "source": [ "Some users may desire to incorporate random Cliffords in their circuits. For\n", "convenience, we provide the :py:meth:`~trueq.math.weyl.Clifford.random` function that\n", "can construct a random Clifford as follows:" ] }, { "cell_type": "code", "execution_count": 7, "id": "60621784", "metadata": { "execution": { "iopub.execute_input": "2024-03-26T19:01:29.794770Z", "iopub.status.busy": "2024-03-26T19:01:29.794481Z", "iopub.status.idle": "2024-03-26T19:01:29.797688Z", "shell.execute_reply": "2024-03-26T19:01:29.797295Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "
True-Q formatting will not be loaded without trusting this\n", "notebook or rerunning the affected cells. Notebooks can be marked as trusted by clicking\n", "\"File -> Trust Notebook\".
\n", "\n", "\n", "\n", "
\n", "
\n", "
Type:
\n", "
  • Clifford
\n", "\n", "
Dim:
\n", "
  • 3
\n", "
\n", "
\n", " \n", "
Generator images:
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "
X0X1Z0Z1ph.
im(X0)00202
im(X1)00222
im(Z0)12211
im(Z1)01100
\n", "
\n", "
\n" ], "text/plain": [ "Clifford('W02W00_W02W02_W12W21_W01W10', [2, 2, 1, 0], dim=3)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# construct a random Clifford on 2 qutrits\n", "tqm.Clifford.random(2, 3)" ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "raw_mimetype,nbsphinx,-all", "main_language": "python", "notebook_metadata_filter": "-all", "text_representation": { "extension": ".py", "format_name": "percent" } }, "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.8.10" } }, "nbformat": 4, "nbformat_minor": 5 }