{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Idle tomography\n", "This tutorial demonstrates how to run idle tomography on a multi-qubits system. Idle tomography is a protocol which characterizes the errors present in an idle operation using data from a small number of intuitive circuits. If $\\tilde{I}$ is the noisy idle operation being characterized and we write $\\tilde{I} = e^{\\Lambda}$, where we call $\\Lambda$ the *error generator* of $\\tilde{I}$, and we express $\\Lambda$ as a sum of terms, $\\Lambda = \\sum_i \\alpha_i F_i$, then idle tomography estimates the $\\alpha_i$ for some set of $F_i$. The $F_i$ are specific generators for well-known errors (e.g. rotations or stochastic errors), the $\\alpha_i$ can roughly be interpreted as the error *rates* corresponding to the well-known error types. The three classes of $F_i$ that pyGSTi's implementation of idle tomography estimates are (see the Lindblad operator section of the [tutorial on operators](../objects/advanced/Operators.ipynb) for more details):\n", "\n", "- **Hamiltonian**: $F_i = H_i$ where $H_i : \\rho \\rightarrow -i[P_i,\\rho]$\n", "- **Stochastic**: $F_i = S_i$ where $S_i : \\rho \\rightarrow P_i \\rho P_i - \\rho$\n", "- **Affine**: $F_i = A_i$ where $A_i : \\rho \\rightarrow \\mathrm{Tr}(\\rho_{target})P_i \\otimes \\rho_{non-target}$\n", "\n", "\n", "## Creating idle tomography circuits\n", "\n", "To run idle tomography in pyGSTi you start by getting a list of the circuits you need to run. This is done by specifying, similarly to in gate set tomography (GST), a target gate set (or model) along with a sequence of maximum-lengths. The model is used to construct fiducial sequences that rotate a prepared qubit (ideally) onto each of the antipodal points on the Bloch sphere (this is done automatically by `determine_paulidicts`). The maximum lengths determing how many successive idle operations to perform. Similar to GST, repeating the idle is used to amplify errors. In idle tomography, repeating the idle is useful as long as the errors are small enough that the higher-than-first-order errors are still small in the repeated gate.\n", "\n", "The function `make_idle_tomography_list` then creates a list of `Circuit` objects:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pygsti\n", "from pygsti.extras import idletomography as idt\n", "\n", "nQubits = 4\n", "maxLengths = [1,2,4,8]\n", "\n", "mdl_target = pygsti.construction.build_localnoise_model(nQubits, [\"Gx\",\"Gy\",\"Gcnot\"])\n", "paulidicts = idt.determine_paulidicts(mdl_target)\n", "listOfExperiments = idt.make_idle_tomography_list(nQubits, maxLengths, paulidicts)\n", "print(len(listOfExperiments), \"idle tomography experiments for %d qubits\" % nQubits)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Generating some fake data\n", "For this example, we'll need to generate some simulated data. We just create a crosstalk-free model with weight-1 Hamiltonian and Stochastic $X$ errors on all the qubits using the `build_crosstalk_free_model` function. (See the [implicit model tutorial](../objects/ImplicitModel.ipynb) for more details on building crosstalk-free models.) Data can then be generated by simulating this model using `generate_fake_data`. Note that the number of samples is quite high ($10^5$) - the current implementation of idle tomography in pyGSTi is suboptimal and requires more samples than are actually needed to achieve a given output accuracy, and this will be improved in future pyGSTi releases." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "#Generate some data (takes ~5min w/10Q)\n", "mdl_datagen = pygsti.construction.build_crosstalk_free_model(nQubits, [\"Gx\",\"Gy\",\"Gcnot\"], \n", " {'idle': {'HX': 0.01, 'SX': 0.01}})\n", "ds = pygsti.construction.generate_fake_data(mdl_datagen, listOfExperiments, 100000, seed=8675309)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Running idle tomography\n", "Now that we have some data, we can run idle tomography using the `do_idle_tomography` function, which takes the data, and number of qubits, the \"Pauli dictionaries\" which describe how to prepare and measure along the Bloch sphere axes, and the same list of maximum lengths used to generate the circuit list. This yields a `IdleTomographyResults` object which holds all the relevant idle tomography outputs." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "#Run idle tomography (takes ~1.5min w/10Q)\n", "results = idt.do_idle_tomography(nQubits, ds, maxLengths, paulidicts)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Viewing the results\n", "That's basically it - now all we need to do is visualize the results. Lets begin by creating a pyGSTi `Workspace` object to display plots inline." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "ws = pygsti.report.Workspace()\n", "ws.init_notebook_mode(autodisplay=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we can display a table of the intrisic rates (the $\\alpha_i$ corresponding the $F_i$ error rates as described above):" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "ws.IdleTomographyIntrinsicErrorsTable(results)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that idle tomography has identified the errors we placed in `mdl_datagen` (up to some dimensional factors that we need to describe and standardize, e.g. the stochasic error rates different from those of `mdl_datagen` by a factor of 2 (TODO!)).\n", " \n", "We can also plot the \"extrinsic\" error rates - those that show the raw data arranged into \"rays\" corresponding to a fixed state preparation and measurement basis where only the number of intervening idles is changed. These plots help give an intuitive picture of where idle tomography is getting the intrinsic rates from (see the second column of the table). The `threshold` argument, when a floating point number, specifies the percentage of the total plots to show, starting with the largest extrinsic rate and descending." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "ws.IdleTomographyObservedRatesTable(results, threshold=0.01)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, if you'd like to see these same plots in an HTML report that you can send to your friends, you just need to call `create_idletomography_report`:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "idt.create_idletomography_report(results, \"../tutorial_files/IDTTestReport\",\n", " \"Test idle tomography example report\", auto_open=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "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.7.0" } }, "nbformat": 4, "nbformat_minor": 2 }