{
"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"
],
"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"
],
"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
}