Idle tomography

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 for more details):

  • Hamiltonian: $F_i = H_i$ where $H_i : \rho \rightarrow -i[P_i,\rho]$
  • Stochastic: $F_i = S_i$ where $S_i : \rho \rightarrow P_i \rho P_i - \rho$
  • Affine: $F_i = A_i$ where $A_i : \rho \rightarrow \mathrm{Tr}(\rho_{target})P_i \otimes \rho_{non-target}$

Creating idle tomography circuits

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.

The function make_idle_tomography_list then creates a list of Circuit objects:

In [ ]:
import pygsti
from pygsti.extras import idletomography as idt

n_qubits = 4
maxLengths = [1,2,4,8]

mdl_target = pygsti.construction.build_localnoise_model(n_qubits, ["Gx","Gy","Gcnot"])
paulidicts = idt.determine_paulidicts(mdl_target)
listOfExperiments = idt.make_idle_tomography_list(n_qubits, maxLengths, paulidicts)
print(len(listOfExperiments), "idle tomography experiments for %d qubits" % n_qubits)

Generating some fake data

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 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.

In [ ]:
#Generate some data (takes ~5min w/10Q)
mdl_datagen = pygsti.construction.build_crosstalk_free_model(n_qubits, ["Gx","Gy","Gcnot"], 
                                                            {'idle': {'HX': 0.01, 'SX': 0.01}})
ds = pygsti.construction.generate_fake_data(mdl_datagen, listOfExperiments, 100000, seed=8675309)

Running idle tomography

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.

In [ ]:
#Run idle tomography (takes ~1.5min w/10Q)
results = idt.do_idle_tomography(n_qubits, ds, maxLengths, paulidicts)

Viewing the results

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.

In [ ]:
ws = pygsti.report.Workspace()
ws.init_notebook_mode(autodisplay=True)

Then we can display a table of the intrisic rates (the $\alpha_i$ corresponding the $F_i$ error rates as described above):

In [ ]:
ws.IdleTomographyIntrinsicErrorsTable(results)

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!)).

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.

In [ ]:
ws.IdleTomographyObservedRatesTable(results, threshold=0.01)

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:

In [ ]:
idt.create_idletomography_report(results, "../tutorial_files/IDTTestReport",
                                 "Test idle tomography example report", auto_open=True)