#!/usr/bin/env python # coding: utf-8 # # Algorithms: high-level interface # ## (Running GST using Driver Routines) # The `pygsti` package provides multiple levels of abstraction over the core Gate Set Tomography (GST) algorithms. This tutorial will show you how to work with `pygsti`'s highest level of abstraction, called "driver functions" to run GST algorithms with a minimial amount of effort. In order to run a GST algorithm there are 3 essential ingredients: 1) data specifing the experimental outcomes, 2) a desired, or "target", `GateSet`, and 3) multiple lists of gate sequences, specifying the gate sequences to use at each successive step in the GST optimization. There are currently only a few driver routines, which we'll cover in turn. Each driver function returns a single `pygsti.objects.Results` object, which contains the *single* input `DataSet` and one or more *estimates* (`pygsti.objects.Estimate` objects). # # [The abbreviation "LSGST" (lowercase in function names to follow Python naming conventions) stands for "Long Sequence Gate Set Tomography", and refers to the more powerful flavor of GST that utilizes long sequences to find gate set estimates. LSGST can be compared to Linear GST, or "LGST", which only uses short sequences and as a result provides much less accurate estimates.] # In[1]: from __future__ import print_function import pygsti # ### Setup # First, we set our desired "target gateset" to be the standard I, X, Y gate set that we've been using throughout the tutorials, and pull in the fiducial and germ sequences needed to generate the GST gate sequences. We also specify a list of maximum lengths. We'll analyze the simulated data generated in the data sets tutorial. # In[2]: from pygsti.construction import std1Q_XYI gs_target = std1Q_XYI.gs_target prep_fiducials, meas_fiducials = std1Q_XYI.prepStrs, std1Q_XYI.effectStrs germs = std1Q_XYI.germs maxLengths = [1,2,4,8,16,32] ds = pygsti.io.load_dataset("tutorial_files/Example_Dataset.txt", cache=True) # ## `do_long_sequence_gst` # This driver function finds what is logically a **single GST estimate** given a `DataSet`, a target `GateSet`, and other parameters. We say "logically" because the returned `Results` object may actually contain multiple related estimates in certain cases. Most important among the other parameters are the fiducial and germ sequences and list of maximum lengths needed to define a *standard* set of GST gate sequence lists. # In[3]: results = pygsti.do_long_sequence_gst(ds, gs_target, prep_fiducials, meas_fiducials, germs, maxLengths) # In[4]: # A summary of what's inside a Results object is obtained by printing it # (for more examples of how to use a Results object, see the Results tutorial) print(results) # ### Beyond the minimum # The above example supplies the minimal amount of information required to run the long-sequence GST algorithm. `do_long_sequence_gst` can be used in a variety of contexts and accepts additional (optional) arguments that affect the way the algorithm is run. Here we make several remarks regarding alternate or more advanced usage of `do_long_sequence_gst`. # # - For many of the arguments, you can supply either a filename or a python object (e.g. dataset, target gateset, gate string lists), so if you find yourself loading things from files just to pass them in as arguments, you're probabaly working too hard. # # - Typically we want to apply certain constraints to a GST optimization. As mentioned in the gate set tutorial, the space over which a gate-set estimation is carried out is dictated by the parameterization of the `targetGateset` argument. For example, to constrain a GST estimate to be trace-preserving, one should call `set_all_parameterizations("TP")` on the target `GateSet` before calling `do_long_sequence_gst`. # # - the `gaugeOptParams` argument specifies a dictionary of parameters ultimately to be passed to the `gaugeopt_to_target` function (which provides full documentation). By specifying an `itemWeights` argument we can set the ratio of the state preparation and measurement (SPAM) weighting to the gate weighting when performing a gauge optimization. In the example below, the gate parameters are weighted 1000 times more relative to the SPAM parameters. Mathematically this corresponds to a multiplicative factor of 0.001 preceding the sum-of-squared-difference terms corresponding to SPAM elements in the gateset. Typically it is good to weight the gates parameters more heavily since GST amplifies gate parameter errors via long gate sequences but cannot amplify SPAM parameter errors. If unsure, 0.001 is a good value to start with. For more details on the arguments of `gaugeopt_to_target`, see the previous tutorial on low-level algorithms. # # The below call illustrates all three of these. # In[5]: gs_target_TP = gs_target.copy() #make a copy so we don't change gs_target's parameterization, # since this could be confusing later... gs_target_TP.set_all_parameterizations("TP") #constrain GST estimate to TP results_TP = pygsti.do_long_sequence_gst("tutorial_files/Example_Dataset.txt", gs_target_TP, prep_fiducials, meas_fiducials, germs, maxLengths, gaugeOptParams={'itemWeights': {'gates': 1.0, 'spam': 0.001}}) # ## `do_long_sequence_gst_base` # This performs the same analysis as `do_long_sequence_gst` except it allows the user to fully specify the list of gate sequences as either a list of lists of `GateString` objects or a list of `GateStringStructure` objects (the latter allow the structured plotting of the sequences in report figures). In this example, we'll just generate a standard set of structures, but with some of the sequences randomly dropped (see later tutorials on gate string reduction). Note that like `do_long_sequence_gst`, `do_long_sequence_gst_base` is able to take filenames as arguments and accepts a `gaugeOptParams` argument for customizing the gauge optimization that is performed. # In[6]: #Create the same sequences but drop 50% of them randomly for each repeated-germ block. lsgst_structs = pygsti.construction.make_lsgst_structs(gs_target, prep_fiducials, meas_fiducials, germs, maxLengths, keepFraction=0.5, keepSeed=2018) results_reduced = pygsti.do_long_sequence_gst_base(ds, gs_target, lsgst_structs) # ## `do_std_practice_gst` # This driver function calls `do_long_sequence_gst` multiple times using typical variations in gauge optimization parameters and `GateSet` parameterization. This function provides a clean and simple interface to performing a "usual" set of GST analyses on a set of data. As such, it takes a single `DataSet`, similar gate-sequence-specifying parameters to `do_long_sequence_gst`, and a new `modes` argument which is a comma-separated list of "canned" GST analysis types (e.g. `"TP,CPTP"` will compute a Trace-Preserving estimate *and* a Completely-Positive & Trace-Preserving estimate). The currently available modes are: # - "full" : unconstrained gates (fully parameterized) # - "TP" : TP-constrained gates and state preparations # - "CPTP" : CPTP-constrained gates and TP-constrained state preparations # - "H+S" : Only Hamiltonian and Pauli stochastic errors allowed (CPTP) # - "S" : Only Pauli-stochastic errors allowed (CPTP) # - "Target" : use the target (ideal) gates as the estimate # # The gauge optimization(s) `do_std_practice_gst` performs are controlled by its `gaugeOptSuite` and `gaugeOptTarget` arguments. The former is can be either a string, specifying a standard "suite" of gauge optimizations, or a dictionary of dictionaries similar to the `gaugeOptParams` argument of `do_long_sequence_gst` (see docstring). The `gaugeOptTarget` argument may be set to a `GateSet` that is used as the target for gauge optimization, overriding the (typically ideal) target gates given by the `targetGateFilenameOrSet` argument. # In[7]: results_stdprac = pygsti.do_stdpractice_gst(ds, gs_target, prep_fiducials, meas_fiducials, germs, maxLengths, modes="TP,CPTP,Target") #uses the default suite of gauge-optimizations # In[8]: print("Estimates: ", ", ".join(results_stdprac.estimates.keys())) print("TP Estimate's gauge optimized gate sets: ", ", ".join(results_stdprac.estimates["TP"].goparameters.keys())) # Next, we'll perform the same analysis but with a **non-default standard suite of gauge optimizations** - this one toggles the SPAM penalty in addition to varying the spam weight (the default suite just varies the spam weight without any SPAM penalty) # In[9]: results_stdprac_nondefaultgo = pygsti.do_stdpractice_gst( ds, gs_target, prep_fiducials, meas_fiducials, germs, maxLengths, modes="TP,CPTP,Target", gaugeOptSuite="varySpam") # In[10]: print("Estimates: ", ", ".join(results_stdprac_nondefaultgo.estimates.keys())) print("TP Estimate's gauge optimized gate sets: ", ", ".join(results_stdprac_nondefaultgo.estimates["TP"].goparameters.keys())) # Finally, we'll demonstrate how to specify a fully custom set of gauge optimization parameters and how to use a separately-specified target gate set for gauge optimization. # In[11]: my_goparams = { 'itemWeights': {'gates': 1.0, 'spam': 0.001} } my_gaugeOptTarget = gs_target.depolarize(gate_noise=0.005, spam_noise=0.01) # a guess at what estimate should be results_stdprac_customgo = pygsti.do_stdpractice_gst( ds, gs_target, prep_fiducials, meas_fiducials, germs, maxLengths, modes="TP,CPTP,Target", gaugeOptSuite={ 'myGO': my_goparams }, gaugeOptTarget=my_gaugeOptTarget) # In[12]: print("Estimates: ", ", ".join(results_stdprac_customgo.estimates.keys())) print("TP Estimate's gauge optimized gate sets: ", ", ".join(results_stdprac_customgo.estimates["TP"].goparameters.keys())) # To finish up, we'll pickle the results for processing in subsequent tutorials. # In[13]: import pickle pickle.dump(results, open('tutorial_files/exampleResults.pkl',"wb")) pickle.dump(results_TP, open('tutorial_files/exampleResults_TP.pkl',"wb")) pickle.dump(results_reduced, open('tutorial_files/exampleResults_reduced.pkl',"wb")) pickle.dump(results_stdprac, open('tutorial_files/exampleResults_stdprac.pkl',"wb")) # In[ ]: