This tutorial discusses the creation of Circuit
objects for use with Gate Set Tomography (GST). If you're not sure what a Circuit
is, you might want to read through the tutorial on circuits first.
While pyGSTi allows one to create arbitrary lists of circuits, the GST algorithms have been designed to work well with circuits that have a particular structure. At the beginning and the end of each string are "preparation fiducial" and "measurement fiducial" circuits (or "sequences"), respectively, whose purpose is to extend the native preparation and measurment operations to informationally complete sets. In between the fiducial sequences is a "germ" sequence, or just "germ", that is repeated some number of times. The purpose of the repeated-germ sequence is to amplify one or more particular types of errors. By considering an entire set of germs (called an "amplificationally complete" set), all possible types of errors are amplified, giving the GST algorithms high sensitivity to all errors. The longer the sequences, that is, the more repetitions of the germs, the higher the sensitivity.
While this may seem to imply that one should just to incredibly long sequences, there are several caveats.
In practice, well-chosen lists of operation sequences can be formed as follows. First, we defne an increasing sequence of maximum-lengths, usually powers of 2, e.g. [1,2,4,8,16,...]
, which terminates with the longest useful sequence length. Secondly, we select preparation- and measurement-fiducial Circuit
lists, and a list of germ circuits. These lists are chosen such that the fiducial sequences result in informationally complete preparations and measurements, and the germs are amplificationally complete. For each maximum-length $L$, the set of all
preparation_fiducial + repeated_germ + measurement_fiducial
sequences, where preparation_fiducial
ranges over all preparation fiducials, measurement_fiducial
ranges over all measurement fiducials, and repeated_germ
ranges over all the germs repeated such that the length of repeated_germ
does not exceed $L$. To further increase the robustness of the numerics, the circuit list corresponding to $L$ will also contain all of the sequences from earlier (lower) values of $L$. This procedure thus creates a list of operation sequences for each $L$ that are designed for use by pyGSTi's "long-sequence" GST algorithms.
The fiducial and germ lists are obtained by pyGSTi's "fiducial selection" and "germ selection" algorithms, which are explained in more detail in the tutorial on fiducial and germ selection. This this tutorial we'll be using one of pyGSTi's "standard" models (see the standard module tutorial), for which fiducial and germ sequences are pre-computed:
import pygsti
from pygsti.construction import std1Q_XY #import the standard X(pi/2), Y(pi/2) model info
prep_fiducials = std1Q_XY.prepStrs
meas_fiducials = std1Q_XY.effectStrs
germs = std1Q_XY.germs
print("Prep fiducials:\n", prep_fiducials)
print("Meas fiducials:\n", meas_fiducials)
print("Germs:\n",germs)
Prep fiducials: [Circuit({}), Circuit(Gx), Circuit(Gy), Circuit(GxGx), Circuit(GxGxGx), Circuit(GyGyGy)] Meas fiducials: [Circuit({}), Circuit(Gx), Circuit(Gy), Circuit(GxGx), Circuit(GxGxGx), Circuit(GyGyGy)] Germs: [Circuit(Gx), Circuit(Gy), Circuit(GxGy), Circuit(GxGxGy), Circuit(GxGyGy), Circuit(GxGxGyGxGyGy)]
We can now construct a the lists of sequences used by a long-sequence GST algorithm by defining a list of maximum lenghts and calling make_lsgst_lists
:
maxLengths = [1,2,4]
lsgst_lists = pygsti.construction.make_lsgst_lists(['Gx','Gy'], prep_fiducials, meas_fiducials, germs, maxLengths)
#Print the result. Note that larger L lists also contain all the elements of lower-L lists.
# Note also that germs which are length 4 only show up in the L=4 list, and there are only "repeated" once.
for i,lst in enumerate(lsgst_lists):
print("\nList %d (max-length L=%d): %d Circuits" % (i,maxLengths[i],len(lst)))
print('\n'.join([c.str for c in lst])) # Note: use ".str" to get a *single-line* string representation
List 0 (max-length L=1): 56 Circuits {} Gx Gy GxGx GxGxGx GyGyGy GxGy GxGxGxGx GxGyGyGy GyGx GyGy GyGxGx GyGxGxGx GyGyGyGy GxGxGy GxGxGxGxGx GxGxGyGyGy GxGxGxGy GxGxGxGxGxGx GxGxGxGyGyGy GyGyGyGx GyGyGyGxGx GyGyGyGxGxGx GyGyGyGyGyGy Gy(Gx)Gy Gy(Gx)GxGxGx Gy(Gx)GyGyGy GxGxGx(Gx)Gy GxGxGx(Gx)GxGxGx GxGxGx(Gx)GyGyGy GyGyGy(Gx)Gy GyGyGy(Gx)GxGxGx GyGyGy(Gx)GyGyGy Gx(Gy)Gx Gx(Gy)Gy Gx(Gy)GxGx Gx(Gy)GxGxGx Gx(Gy)GyGyGy Gy(Gy)Gx Gy(Gy)GxGx Gy(Gy)GxGxGx Gy(Gy)GyGyGy GxGx(Gy)Gx GxGx(Gy)Gy GxGx(Gy)GxGx GxGx(Gy)GxGxGx GxGx(Gy)GyGyGy GxGxGx(Gy)Gx GxGxGx(Gy)Gy GxGxGx(Gy)GxGx GxGxGx(Gy)GxGxGx GxGxGx(Gy)GyGyGy GyGyGy(Gy)Gx GyGyGy(Gy)GxGx GyGyGy(Gy)GxGxGx GyGyGy(Gy)GyGyGy List 1 (max-length L=2): 96 Circuits {} Gx Gy GxGx GxGxGx GyGyGy GxGy GxGxGxGx GxGyGyGy GyGx GyGy GyGxGx GyGxGxGx GyGyGyGy GxGxGy GxGxGxGxGx GxGxGyGyGy GxGxGxGy GxGxGxGxGxGx GxGxGxGyGyGy GyGyGyGx GyGyGyGxGx GyGyGyGxGxGx GyGyGyGyGyGy Gy(Gx)Gy Gy(Gx)GxGxGx Gy(Gx)GyGyGy GxGxGx(Gx)Gy GxGxGx(Gx)GxGxGx GxGxGx(Gx)GyGyGy GyGyGy(Gx)Gy GyGyGy(Gx)GxGxGx GyGyGy(Gx)GyGyGy Gx(Gy)Gx Gx(Gy)Gy Gx(Gy)GxGx Gx(Gy)GxGxGx Gx(Gy)GyGyGy Gy(Gy)Gx Gy(Gy)GxGx Gy(Gy)GxGxGx Gy(Gy)GyGyGy GxGx(Gy)Gx GxGx(Gy)Gy GxGx(Gy)GxGx GxGx(Gy)GxGxGx GxGx(Gy)GyGyGy GxGxGx(Gy)Gx GxGxGx(Gy)Gy GxGxGx(Gy)GxGx GxGxGx(Gy)GxGxGx GxGxGx(Gy)GyGyGy GyGyGy(Gy)Gx GyGyGy(Gy)GxGx GyGyGy(Gy)GxGxGx GyGyGy(Gy)GyGyGy Gy(Gx)^2Gy Gy(Gx)^2GxGxGx Gy(Gx)^2GyGyGy GxGxGx(Gx)^2Gy GxGxGx(Gx)^2GxGxGx GxGxGx(Gx)^2GyGyGy GyGyGy(Gx)^2Gy GyGyGy(Gx)^2GxGxGx GyGyGy(Gx)^2GyGyGy Gx(Gy)^2Gx Gx(Gy)^2GxGx Gx(Gy)^2GxGxGx Gx(Gy)^2GyGyGy GxGx(Gy)^2Gx GxGx(Gy)^2GxGx GxGx(Gy)^2GxGxGx GxGx(Gy)^2GyGyGy GxGxGx(Gy)^2Gx GxGxGx(Gy)^2GxGx GxGxGx(Gy)^2GxGxGx GxGxGx(Gy)^2GyGyGy GyGyGy(Gy)^2Gx GyGyGy(Gy)^2GxGx GyGyGy(Gy)^2GxGxGx GyGyGy(Gy)^2GyGyGy Gy(GxGy)Gx Gy(GxGy)Gy Gy(GxGy)GxGx Gy(GxGy)GxGxGx Gy(GxGy)GyGyGy GxGxGx(GxGy)Gx GxGxGx(GxGy)Gy GxGxGx(GxGy)GxGx GxGxGx(GxGy)GxGxGx GxGxGx(GxGy)GyGyGy GyGyGy(GxGy)Gx GyGyGy(GxGy)Gy GyGyGy(GxGy)GxGx GyGyGy(GxGy)GxGxGx GyGyGy(GxGy)GyGyGy List 2 (max-length L=4): 189 Circuits {} Gx Gy GxGx GxGxGx GyGyGy GxGy GxGxGxGx GxGyGyGy GyGx GyGy GyGxGx GyGxGxGx GyGyGyGy GxGxGy GxGxGxGxGx GxGxGyGyGy GxGxGxGy GxGxGxGxGxGx GxGxGxGyGyGy GyGyGyGx GyGyGyGxGx GyGyGyGxGxGx GyGyGyGyGyGy Gy(Gx)Gy Gy(Gx)GxGxGx Gy(Gx)GyGyGy GxGxGx(Gx)Gy GxGxGx(Gx)GxGxGx GxGxGx(Gx)GyGyGy GyGyGy(Gx)Gy GyGyGy(Gx)GxGxGx GyGyGy(Gx)GyGyGy Gx(Gy)Gx Gx(Gy)Gy Gx(Gy)GxGx Gx(Gy)GxGxGx Gx(Gy)GyGyGy Gy(Gy)Gx Gy(Gy)GxGx Gy(Gy)GxGxGx Gy(Gy)GyGyGy GxGx(Gy)Gx GxGx(Gy)Gy GxGx(Gy)GxGx GxGx(Gy)GxGxGx GxGx(Gy)GyGyGy GxGxGx(Gy)Gx GxGxGx(Gy)Gy GxGxGx(Gy)GxGx GxGxGx(Gy)GxGxGx GxGxGx(Gy)GyGyGy GyGyGy(Gy)Gx GyGyGy(Gy)GxGx GyGyGy(Gy)GxGxGx GyGyGy(Gy)GyGyGy Gy(Gx)^2Gy Gy(Gx)^2GxGxGx Gy(Gx)^2GyGyGy GxGxGx(Gx)^2Gy GxGxGx(Gx)^2GxGxGx GxGxGx(Gx)^2GyGyGy GyGyGy(Gx)^2Gy GyGyGy(Gx)^2GxGxGx GyGyGy(Gx)^2GyGyGy Gx(Gy)^2Gx Gx(Gy)^2GxGx Gx(Gy)^2GxGxGx Gx(Gy)^2GyGyGy GxGx(Gy)^2Gx GxGx(Gy)^2GxGx GxGx(Gy)^2GxGxGx GxGx(Gy)^2GyGyGy GxGxGx(Gy)^2Gx GxGxGx(Gy)^2GxGx GxGxGx(Gy)^2GxGxGx GxGxGx(Gy)^2GyGyGy GyGyGy(Gy)^2Gx GyGyGy(Gy)^2GxGx GyGyGy(Gy)^2GxGxGx GyGyGy(Gy)^2GyGyGy Gy(GxGy)Gx Gy(GxGy)Gy Gy(GxGy)GxGx Gy(GxGy)GxGxGx Gy(GxGy)GyGyGy GxGxGx(GxGy)Gx GxGxGx(GxGy)Gy GxGxGx(GxGy)GxGx GxGxGx(GxGy)GxGxGx GxGxGx(GxGy)GyGyGy GyGyGy(GxGy)Gx GyGyGy(GxGy)Gy GyGyGy(GxGy)GxGx GyGyGy(GxGy)GxGxGx GyGyGy(GxGy)GyGyGy Gy(Gx)^4Gy Gy(Gx)^4GxGx Gy(Gx)^4GxGxGx Gy(Gx)^4GyGyGy GxGx(Gx)^4Gy GxGx(Gx)^4GxGxGx GxGx(Gx)^4GyGyGy GxGxGx(Gx)^4Gy GxGxGx(Gx)^4GxGxGx GxGxGx(Gx)^4GyGyGy GyGyGy(Gx)^4Gy GyGyGy(Gx)^4GxGx GyGyGy(Gx)^4GxGxGx GyGyGy(Gx)^4GyGyGy Gx(Gy)^4Gx Gx(Gy)^4GxGx Gx(Gy)^4GxGxGx Gx(Gy)^4GyGyGy GxGx(Gy)^4Gx GxGx(Gy)^4GxGx GxGx(Gy)^4GxGxGx GxGx(Gy)^4GyGyGy GxGxGx(Gy)^4Gx GxGxGx(Gy)^4GxGx GxGxGx(Gy)^4GxGxGx GxGxGx(Gy)^4GyGyGy GyGyGy(Gy)^4Gx GyGyGy(Gy)^4GxGx GyGyGy(Gy)^4GxGxGx GyGyGy(Gy)^4GyGyGy (GxGy)^2 (GxGy)^2Gx (GxGy)^2Gy (GxGy)^2GxGx (GxGy)^2GxGxGx (GxGy)^2GyGyGy Gx(GxGy)^2 Gx(GxGy)^2Gx Gx(GxGy)^2Gy Gx(GxGy)^2GxGx Gx(GxGy)^2GxGxGx Gx(GxGy)^2GyGyGy Gy(GxGy)^2 Gy(GxGy)^2Gx Gy(GxGy)^2Gy Gy(GxGy)^2GxGx Gy(GxGy)^2GxGxGx Gy(GxGy)^2GyGyGy GxGx(GxGy)^2 GxGx(GxGy)^2Gx GxGx(GxGy)^2Gy GxGx(GxGy)^2GxGx GxGx(GxGy)^2GxGxGx GxGx(GxGy)^2GyGyGy GxGxGx(GxGy)^2 GxGxGx(GxGy)^2Gx GxGxGx(GxGy)^2Gy GxGxGx(GxGy)^2GxGx GxGxGx(GxGy)^2GxGxGx GxGxGx(GxGy)^2GyGyGy GyGyGy(GxGy)^2 GyGyGy(GxGy)^2Gx GyGyGy(GxGy)^2Gy GyGyGy(GxGy)^2GxGx GyGyGy(GxGy)^2GxGxGx GyGyGy(GxGy)^2GyGyGy Gy(GxGxGy)Gx Gy(GxGxGy)Gy Gy(GxGxGy)GxGx Gy(GxGxGy)GxGxGx Gy(GxGxGy)GyGyGy GxGxGx(GxGxGy)Gx GxGxGx(GxGxGy)Gy GxGxGx(GxGxGy)GxGx GxGxGx(GxGxGy)GxGxGx GxGxGx(GxGxGy)GyGyGy GyGyGy(GxGxGy)Gx GyGyGy(GxGxGy)Gy GyGyGy(GxGxGy)GxGx GyGyGy(GxGxGy)GxGxGx GyGyGy(GxGxGy)GyGyGy Gy(GxGyGy)Gx Gy(GxGyGy)GxGx Gy(GxGyGy)GxGxGx Gy(GxGyGy)GyGyGy GxGxGx(GxGyGy)Gx GxGxGx(GxGyGy)GxGx GxGxGx(GxGyGy)GxGxGx GxGxGx(GxGyGy)GyGyGy GyGyGy(GxGyGy)Gx GyGyGy(GxGyGy)GxGx GyGyGy(GxGyGy)GxGxGx GyGyGy(GxGyGy)GyGyGy
While a list-of-lists such as lsgst_lists
is all that is needed by the core long-sequence GST algorithms, one can also construct, in similar fashion, a list of pygsti.objects.CircuitStructure
objects. These objects mimic a list of Circuits
in many ways, but retain the structure of each circuit so that per-circuit quantities may later be plotted according to their decomposition into fiducials, germ, and $L$. The allstrs
member of a CircuitStructure
allows access to the underlying list of Circuit
objects. We'll demonstrate this when we get to plotting. For now, just think of this as a slightly richer way to generate the circuits needed by a GST algorithm that facilitates post-processing and analysis.
#Note: same arguments as make_lsgst_lists
lsgst_structs = pygsti.construction.make_lsgst_structs(['Gx','Gy'], prep_fiducials, meas_fiducials, germs, maxLengths)
print(type(lsgst_structs[0]))
for i,struct in enumerate(lsgst_structs):
print("Struct %d (L=%d) has %d strings" % (i,maxLengths[i],len(struct.allstrs)))
<class 'pygsti.objects.circuitstructure.LsGermsStructure'> Struct 0 (L=1) has 56 strings Struct 1 (L=2) has 96 strings Struct 2 (L=4) has 189 strings
If you're taking data, not running a GST algorithm, then you just want a single list of all the circuits that the GST algorithm will need. Since most of the time the lists are nested, that is, all of the lower-$L$ (shorter) circuits appear in the higher-$L$ (longer) circuits, the final element of lsgst_lists
is often the list of required experiments. However, in advanced usages this is not always the case, and so there is a dedicated function, make_lsgst_experiment_list
which performs this constrution:
#Note: same arguments as make_lsgst_lists
lsgst_experiment_list = pygsti.construction.make_lsgst_experiment_list(['Gx','Gy'], prep_fiducials,
meas_fiducials, germs, maxLengths)
print("%d experiments to do..." % len(lsgst_experiment_list))
189 experiments to do...
As a final full-fledged example we demonstrate the use of pyGSTi's more general Circuit
creation and processing functions to create the lists of LSGST circuits. The following example functions are very similar to pygsti.construction.make_lsgst_lists
except we assume that the preparation and measurement fiducial sequences are the same.
import pygsti.construction as pc
def my_make_lsgst_lists(gateLabels, fiducialList, germList, maxLengthList):
singleOps = pc.circuit_list([(g,) for g in gateLabels])
lgstStrings = pc.list_lgst_circuits(fiducialList, fiducialList, gateLabels)
lsgst_list = pc.circuit_list([ () ]) #running list of all strings so far
if maxLengthList[0] == 0:
lsgst_listOfLists = [ lgstStrings ]
maxLengthList = maxLengthList[1:]
else: lsgst_listOfLists = [ ]
for maxLen in maxLengthList:
lsgst_list += pc.create_circuit_list("f0+R(germ,N)+f1", f0=fiducialList,
f1=fiducialList, germ=germList, N=maxLen,
R=pc.repeat_with_max_length,
order=('germ','f0','f1'))
lsgst_listOfLists.append( pygsti.remove_duplicates(lgstStrings + lsgst_list) )
print("%d LSGST sets w/lengths" % len(lsgst_listOfLists), list(map(len,lsgst_listOfLists)))
return lsgst_listOfLists
my_lsgst_lists = my_make_lsgst_lists(['Gx','Gy'], prep_fiducials, germs, maxLengths)
print('\n'.join(['%d strings' % len(l) for l in my_lsgst_lists]))
3 LSGST sets w/lengths [56, 96, 189] 56 strings 96 strings 189 strings