{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"# Algorithms: low-level interface\n",
"Once we have data for GST, there are several *algorithms* we can run on it to produce tomographic estimates. Depending on the amount of data you have, and time available for running Gate Set Tomography, one algorithm may be preferable over the others. **What is typically thought of as \"standard GST\" is the iterative maximum-likelihood optimization implemented by `do_iterative_mlgst`** which uses a combination of minimum-$\\chi^2$ GST and maximum-likelihood GST.\n",
"\n",
"`pygsti` provides support for the following \"primary\" GST algorithms:\n",
"\n",
"* **Linear Gate Set Tomography (LGST)**: Uses short gate sequences to quickly compute a rough (low accuracy) estimate of a gate set by linear inversion.\n",
"\n",
"* **Extended Linear Gate Set Tomography (eLGST or EXLGST)**: Minimizes the sub-of-squared errors between independent LGST estimates and the estimates obtained from a single gate set to find a best-estimate gate set. This is typically done in an interative fashion, using LGST estimates for longer and longer sequences. \n",
"\n",
"* **Minimum-$\\chi^2$ Gate Set Tomography (MC2GST)**: Minimizes the $\\chi^{2}$ statistic of the data frequencies and gate set probabilities to find a best-estimate gate set. Typically done in an interative fashion, using successively larger sets of longer and longer gate sequences. \n",
"\n",
"* **Maximum-Likelihood Gate Set Tomography (MLGST)**: Maximizes the log-likelihood statistic of the data frequencies and gate set probabilities to find a best-estimate gate set. Typically done in an interative fashion similar to MC2GST. This maximum likelihood estimation (MLE) is very well-motivated from a statistics standpoint and should be the **most accurate among the algorithms**. \n",
"\n",
"If you're curious, the implementation of the algorithms for LGST, EXLGST, MC2GST, and MLGST may be found in the `pygsti.algorithms.core` module. In this tutorial, we'll show how to invoke each of these algorithms.\n",
"\n",
"Additionally, `pygsti` contains **gauge-optimization** algorithms. Because the outcome data (the input to the GST algorithms above) only determines a gate set up to some number of un-physical \"gauge\" degrees of freedom, it is often desirable to optimize the `GateSet` estimate obtained from a GST algorithm within the space of its gauge freedoms. This process is called \"gauge-optimization\" and the final part of this tutorial demonstrates how to gauge-optimize a gate set using various criteria."
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"## Primary GST Algorithms\n",
"The ingredients needed to as input to the \"primary\" GST algorithms are:\n",
"- a \"target\" `GateSet` which defines the desired gates. This gate set is used by LGST to specify the various gate, state preparation, POVM effect, and SPAM labels, as well as to provide an initial guess for the *gauge* degrees of freedom.\n",
"- a `DataSet` containing the data that GST attempts to fit using the probabilities generated by a single `GateSet`. This data set must at least contain the data for the gate sequences required by the algorithm that is chosen.\n",
"- for EXLGST, MC2GST, and MLGST, a list-of-lists of `GateString` objects, which specify which gate strings are used during each iteration of the algorithm (the length of the top-level list defines the number of interations). Note that which gate strings are included in these lists is different for EXLGST than it is for MC2GST and MLGST."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"from __future__ import print_function"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"import pygsti\n",
"import json"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading tutorial_files/Example_Dataset_LowCnts.txt: 100%\n",
"Writing cache file (to speed future loads): tutorial_files/Example_Dataset_LowCnts.txt.cache\n",
"Loaded target gateset with gate labels: odict_keys(['Gi', 'Gx', 'Gy'])\n",
"Loaded fiducial lists of lengths: (6, 6)\n",
"Loaded dataset of length: 3382\n"
]
}
],
"source": [
"#We'll use the standard I, X(pi/2), Y(pi/2) gate set that we generated data for in the DataSet tutorial\n",
"from pygsti.construction import std1Q_XYI\n",
"\n",
"gs_target = std1Q_XYI.gs_target\n",
"prep_fiducials = std1Q_XYI.prepStrs\n",
"meas_fiducials = std1Q_XYI.effectStrs\n",
"germs = std1Q_XYI.germs\n",
"\n",
"maxLengthList = [1,2,4,8,16] #for use in iterative algorithms\n",
"\n",
"ds = pygsti.io.load_dataset(\"tutorial_files/Example_Dataset.txt\", cache=True)\n",
"dsLowCounts = pygsti.io.load_dataset(\"tutorial_files/Example_Dataset_LowCnts.txt\", cache=True)\n",
"\n",
"depol_gateset = gs_target.depolarize(gate_noise=0.1)\n",
"\n",
"print(\"Loaded target gateset with gate labels: \", gs_target.gates.keys())\n",
"print(\"Loaded fiducial lists of lengths: \", (len(prep_fiducials),len(meas_fiducials)))\n",
"print(\"Loaded dataset of length: \", len(ds))"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"### Using LGST to get an initial estimate\n",
"\n",
"An important and distinguising property of the LGST algorithm is that it does *not* require an initial-guess `GateSet` as an input. It uses linear inversion and short sequences to obtain a rough gate set estimate. As such, it is very common to use the LGST estimate as the initial-guess starting point for more advanced forms of GST."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- LGST ---\n",
"Gauge optimization completed in 0.025496s.\n",
"--- Contract to CPTP (direct) ---\n",
"The closest legal point found was distance: 0.00018252137590788687\n"
]
}
],
"source": [
"#Run LGST to get an initial estimate for the gates in gs_target based on the data in ds\n",
"\n",
"#run LGST\n",
"gs_lgst = pygsti.do_lgst(ds, prep_fiducials, meas_fiducials, targetGateset=gs_target, verbosity=1)\n",
"\n",
"#Gauge optimize the result to match the target gateset\n",
"gs_lgst_after_gauge_opt = pygsti.gaugeopt_to_target(gs_lgst, gs_target, verbosity=1)\n",
"\n",
"#Contract the result to CPTP, guaranteeing that the gates are CPTP\n",
"gs_clgst = pygsti.contract(gs_lgst_after_gauge_opt, \"CPTP\", verbosity=1)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"rho0 = 0.7071 -0.0302 0.0396 0.7480\n",
"\n",
"\n",
"Mdefault = Unconstrained POVM with effect vectors:\n",
"0:\n",
" 0.73\n",
" 0\n",
" 0\n",
" 0.65\n",
"\n",
"1:\n",
" 0.69\n",
" 0\n",
" 0\n",
"-0.65\n",
"\n",
"\n",
"\n",
"Gi = \n",
" 1.0000 0 0 0\n",
" 0.0094 0.9238 0.0542 -0.0155\n",
" 0.0285 -0.0149 0.9021 0.0200\n",
" -0.0142 0.0280 0.0009 0.9057\n",
"\n",
"\n",
"Gx = \n",
" 1.0000 0 0 0\n",
" 0.0064 0.9053 0.0281 -0.0044\n",
" -0.0006 0.0215 -0.0471 -0.9983\n",
" -0.0692 -0.0056 0.8095 0.0090\n",
"\n",
"\n",
"Gy = \n",
" 1.0000 0 0 0\n",
" -0.0152 -0.0245 0.0379 0.9906\n",
" 0.0076 -0.0126 0.8876 -0.0257\n",
" -0.0771 -0.8084 -0.0476 0.0210\n",
"\n",
"\n",
"\n",
"\n"
]
}
],
"source": [
"print(gs_lgst)"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"### Extended LGST (eLGST or EXLGST)\n",
"EXLGST requires a list-of-lists of gate strings, one per iteration. The elements of these lists are typically repetitions of short \"germ\" strings such that the final strings does not exceed some maximum length. We created such lists in the gate string tutorial. Now, we just load these lists from the text files they were saved in."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true,
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Iterative eLGST: Iter 5 of 5 ; 43 gate strings ---: \n"
]
}
],
"source": [
"#Get rho and E specifiers, needed by LGST\n",
"elgstListOfLists = pygsti.construction.make_elgst_lists(gs_target, germs, maxLengthList)\n",
" \n",
"#run EXLGST. The result, gs_exlgst, is a GateSet containing the estimated quantities\n",
"gs_exlgst = pygsti.do_iterative_exlgst(ds, gs_clgst, prep_fiducials, meas_fiducials, elgstListOfLists,\n",
" targetGateset=gs_target, verbosity=2)"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"### Minimum-$\\chi^2$ GST (MC2GST)\n",
"MC2GST and MLGST also require a list-of-lists of gate strings, one per iteration. However, the elements of these lists are typically repetitions of short \"germ\" strings *sandwiched between fiducial strings* such that the repeated-germ part of the string does not exceed some maximum length. We created such lists in the gate string tutorial. Now, we just load these lists from the text files they were saved in."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true,
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Iterative MC2GST: Iter 1 of 5 92 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 40.9959 (92 data params - 44 model params = expected mean of 48; p-value = 0.752997)\n",
" Completed in 0.1s\n",
" Iteration 1 took 0.1s\n",
" \n",
"--- Iterative MC2GST: Iter 2 of 5 168 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 119.003 (168 data params - 44 model params = expected mean of 124; p-value = 0.609957)\n",
" Completed in 0.2s\n",
" Iteration 2 took 0.2s\n",
" \n",
"--- Iterative MC2GST: Iter 3 of 5 450 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 415.116 (450 data params - 44 model params = expected mean of 406; p-value = 0.366587)\n",
" Completed in 0.5s\n",
" Iteration 3 took 0.5s\n",
" \n",
"--- Iterative MC2GST: Iter 4 of 5 862 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 813.352 (862 data params - 44 model params = expected mean of 818; p-value = 0.539288)\n",
" Completed in 1.0s\n",
" Iteration 4 took 1.0s\n",
" \n",
"--- Iterative MC2GST: Iter 5 of 5 1282 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 1251.63 (1282 data params - 44 model params = expected mean of 1238; p-value = 0.387312)\n",
" Completed in 1.5s\n",
" Iteration 5 took 1.5s\n",
" \n",
"Iterative MC2GST Total Time: 3.3s\n"
]
}
],
"source": [
"#Get lists of gate strings for successive iterations of LSGST to use\n",
"lsgstListOfLists = pygsti.construction.make_lsgst_lists(gs_target, prep_fiducials, meas_fiducials, germs, maxLengthList)\n",
" \n",
"#run MC2GST. The result is a GateSet containing the estimated quantities\n",
"gs_mc2 = pygsti.do_iterative_mc2gst(ds, gs_clgst, lsgstListOfLists, verbosity=2)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"#Write the resulting EXLGST and MC2GST results to gate set text files for later reference.\n",
"pygsti.io.write_gateset(gs_exlgst, \"tutorial_files/Example_eLGST_Gateset.txt\",\"# Example result from running eLGST\")\n",
"pygsti.io.write_gateset(gs_mc2, \"tutorial_files/Example_MC2GST_Gateset.txt\",\"# Example result from running MC2GST\")"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Iterative MC2GST: Iter 1 of 5 92 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 47.3001 (92 data params - 44 model params = expected mean of 48; p-value = 0.501435)\n",
" Completed in 0.1s\n",
" Iteration 1 took 0.2s\n",
" \n",
"--- Iterative MC2GST: Iter 2 of 5 168 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 148.438 (168 data params - 44 model params = expected mean of 124; p-value = 0.0665627)\n",
" Completed in 0.3s\n",
" Iteration 2 took 0.3s\n",
" \n",
"--- Iterative MC2GST: Iter 3 of 5 450 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 438.226 (450 data params - 44 model params = expected mean of 406; p-value = 0.130175)\n",
" Completed in 0.5s\n",
" Iteration 3 took 0.6s\n",
" \n",
"--- Iterative MC2GST: Iter 4 of 5 862 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 836.618 (862 data params - 44 model params = expected mean of 818; p-value = 0.318)\n",
" Completed in 1.1s\n",
" Iteration 4 took 1.2s\n",
" \n",
"--- Iterative MC2GST: Iter 5 of 5 1282 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 1267.98 (1282 data params - 44 model params = expected mean of 1238; p-value = 0.270572)\n",
" Completed in 1.6s\n",
" Iteration 5 took 1.6s\n",
" \n",
"Iterative MC2GST Total Time: 3.8s\n"
]
}
],
"source": [
"#Run MC2GST again but use a DataSet with a lower number of counts \n",
"gs_mc2_lowcnts = pygsti.do_iterative_mc2gst(dsLowCounts, gs_clgst, lsgstListOfLists, verbosity=2)"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"### Maximum Likelihood GST (MLGST)\n",
"Executing MLGST is very similar to MC2GST: the same gate string lists can be used and calling syntax is nearly identitcal."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true,
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Iterative MLGST: Iter 1 of 5 92 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 40.9959 (92 data params - 44 model params = expected mean of 48; p-value = 0.752997)\n",
" Completed in 0.2s\n",
" 2*Delta(log(L)) = 41.1735\n",
" Iteration 1 took 0.2s\n",
" \n",
"--- Iterative MLGST: Iter 2 of 5 168 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 119.003 (168 data params - 44 model params = expected mean of 124; p-value = 0.609957)\n",
" Completed in 0.3s\n",
" 2*Delta(log(L)) = 119.399\n",
" Iteration 2 took 0.4s\n",
" \n",
"--- Iterative MLGST: Iter 3 of 5 450 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 415.116 (450 data params - 44 model params = expected mean of 406; p-value = 0.366587)\n",
" Completed in 0.6s\n",
" 2*Delta(log(L)) = 415.822\n",
" Iteration 3 took 1.0s\n",
" \n",
"--- Iterative MLGST: Iter 4 of 5 862 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 813.352 (862 data params - 44 model params = expected mean of 818; p-value = 0.539288)\n",
" Completed in 1.0s\n",
" 2*Delta(log(L)) = 815.138\n",
" Iteration 4 took 1.7s\n",
" \n",
"--- Iterative MLGST: Iter 5 of 5 1282 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 1251.63 (1282 data params - 44 model params = expected mean of 1238; p-value = 0.387312)\n",
" Completed in 1.9s\n",
" 2*Delta(log(L)) = 1254.02\n",
" Iteration 5 took 2.9s\n",
" \n",
" Switching to ML objective (last iteration)\n",
" --- MLGST ---\n",
" Maximum log(L) = 626.828 below upper bound of -2.13594e+06\n",
" 2*Delta(log(L)) = 1253.66 (1282 data params - 44 model params = expected mean of 1238; p-value = 0.371952)\n",
" Completed in 2.2s\n",
" 2*Delta(log(L)) = 1253.66\n",
" Final MLGST took 2.2s\n",
" \n",
"Iterative MLGST Total Time: 8.5s\n"
]
}
],
"source": [
"#run MLGST. The result is a GateSet containing the estimated quantities\n",
"gs_mle = pygsti.do_iterative_mlgst(ds, gs_clgst, lsgstListOfLists, verbosity=2)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true,
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--- Iterative MLGST: Iter 1 of 5 92 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 47.3001 (92 data params - 44 model params = expected mean of 48; p-value = 0.501435)\n",
" Completed in 0.1s\n",
" 2*Delta(log(L)) = 48.1797\n",
" Iteration 1 took 0.2s\n",
" \n",
"--- Iterative MLGST: Iter 2 of 5 168 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 148.438 (168 data params - 44 model params = expected mean of 124; p-value = 0.0665627)\n",
" Completed in 0.3s\n",
" 2*Delta(log(L)) = 152.737\n",
" Iteration 2 took 0.4s\n",
" \n",
"--- Iterative MLGST: Iter 3 of 5 450 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 438.226 (450 data params - 44 model params = expected mean of 406; p-value = 0.130175)\n",
" Completed in 0.5s\n",
" 2*Delta(log(L)) = 449.554\n",
" Iteration 3 took 0.8s\n",
" \n",
"--- Iterative MLGST: Iter 4 of 5 862 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 836.618 (862 data params - 44 model params = expected mean of 818; p-value = 0.318)\n",
" Completed in 1.2s\n",
" 2*Delta(log(L)) = 856.236\n",
" Iteration 4 took 1.8s\n",
" \n",
"--- Iterative MLGST: Iter 5 of 5 1282 gate strings ---: \n",
" --- Minimum Chi^2 GST ---\n",
" Sum of Chi^2 = 1267.98 (1282 data params - 44 model params = expected mean of 1238; p-value = 0.270572)\n",
" Completed in 1.9s\n",
" 2*Delta(log(L)) = 1296.65\n",
" Iteration 5 took 3.3s\n",
" \n",
" Switching to ML objective (last iteration)\n",
" --- MLGST ---\n",
" Maximum log(L) = 644.501 below upper bound of -106241\n",
" 2*Delta(log(L)) = 1289 (1282 data params - 44 model params = expected mean of 1238; p-value = 0.152777)\n",
" Completed in 2.0s\n",
" 2*Delta(log(L)) = 1289\n",
" Final MLGST took 2.0s\n",
" \n",
"Iterative MLGST Total Time: 8.6s\n"
]
}
],
"source": [
"#Run MLGST again but use a DataSet with a lower number of counts \n",
"gs_mle_lowcnts = pygsti.do_iterative_mlgst(dsLowCounts, gs_clgst, lsgstListOfLists, verbosity=2)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"deletable": true,
"editable": true
},
"source": [
"## Gauge Optimization\n",
"All gauge optimization algorithms perform essentially the same task - to find the gate set which optimizes some objective function from within the set or space of gate sets that are gauge-equivalent to some starting set. This is accomplished in `pygsti` using the following mechanism:\n",
"- one begins with an initial `GateSet`, call it `gs`, to be gauge-optimized.\n",
"- a `pygsti.objects.GaugeGroup` instance defines a parameterized group of allowable gauge transformations. This gauge group must be compatible with the `gs`'s parameterization, so that `gs.transform` (which calls `Gate.transform` and `SPAMVec.transform`) is able to process elements of the `GaugeGroup` (obtained via a call to `GaugeGroup.get_element(params)`). That is, the gauge transformation must map between gatesets with the *same* parameterization (that give by `gs`). Because of the close interplay between a gate set's parameterization and its allowed gauge transformations, `GateSet` objects can contain a `GaugeGroup` instance as their `default_gauge_group` member. In many circumstances, `gs.default_gauge_group` is set to the correct gauge group to use for a given `GateSet`.\n",
"- `pygsti.gaugeopt_custom(...)` takes an intial `GateSet`, an objective function, and a `GaugeGroup` (along with other optimization parameters) and returns a gauge-optimized `GateSet`. Note that if its `gauge_group` argument is left as `None`, then the gate set's default gauge group is used. And objective function which takes a single `GateSet` argument and returns a float can be supplied, giving the user a fair amount of flexiblity.\n",
"- since usually the objective function is one which compares the gate set being optimized to a fixed \"target\" gate set, `pygsti.gaugeopt_to_target(...)` is a routine able to perform these common types of gauge optimization. Instead of an objective function, `gaugeopt_to_target` takes a target `GateSet` and additional arguments (see below) from which it constructs a objective function and then calls `gaugeopt_custom`. It is essetially a convenience routine for constructing common gauge optimization objective functions. Relevant arguments which affect what objective function is used are:\n",
" - `targetGateset` : the `GateSet` to compare against - i.e., the one you want to gauge optimize toward. **Note that this doesn't have to be a set of ideal gates **- it can be any (imperfect) gate set that reflects your expectations about what the estimates should look like.\n",
" - `itemWeights` : a dictionary of weights allowing different gates and/or SPAM operations to be weighted differently when computing the objective function's value.\n",
" - `CPpenalty` : a prefactor multiplying the sum of all the negative Choi-matrix eigenvalues corresponding to each of the gates.\n",
" - `TPpenalty` : a prefactor multiplying the sum of absoulte-value differences between the first row of each gate matrix and `[1 0 ... 0 ]` and the discrpance between the first element of each state preparation vector and its expected value.\n",
" - `validSpamPenalty` : a prefactor multiplying penalty terms enforcing the non-negativity of state preparation eigenavlues and that POVM effect eigenvalues lie between 0 and 1.\n",
" - `gatesMetric` : how to compare corresponding gates in the gauge-optimized and target sets. `\"frobenius`\" uses the frobenius norm (weighted before taking the final sqrt), `\"fidelity\"` uses the *squared process infidelity* (squared to avoid negative-infidelity issues in non-TP gate sets), and `\"tracedist\"` uses the trace distance (weighted after computing the trace distance between corresponding gates).\n",
" - `spamMetric` : how to compare corresponding SPAM vectors. `\"frobenius\"` (the default) should be used here, as `\"fidelity\"` and `\"tracedist\"` compare the \"SPAM gates\" -- the outer product of state prep and POVM effect vectors -- which isn't a meaningful metric.\n",
" \n",
"The cell below demonstrates some of common usages of `gaugeopt_to_target`."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Default gauge group = \n",
"\n",
"gaugeopt_to_target output:\n",
" --- Gauge Optimization (ls method) ---\n",
"--- Outer Iter 0: norm_f = 0.091421, mu=0, |J|=7.24835\n",
"--- Outer Iter 1: norm_f = 0.0914134, mu=0.00171217, |J|=7.2468\n",
"--- Outer Iter 2: norm_f = 0.0914134, mu=0.000570723, |J|=7.24671\n",
" Least squares message = Both actual and predicted relative reductions in the sum of squares are at most 1e-08\n",
"Gauge optimization completed in 0.0260451s.\n",
"Final frobenius distance between gs_go7 and gs_target = 0.03903275393537098\n"
]
}
],
"source": [
"gs = gs_mle.copy() #we'll use the MLGST result from above as an example\n",
"gs_go1 = pygsti.gaugeopt_to_target(gs, gs_target) # optimization to the perfect target gates\n",
"gs_go2 = pygsti.gaugeopt_to_target(gs, depol_gateset) # optimization to a \"guess\" at what the estimate should be\n",
"gs_go3 = pygsti.gaugeopt_to_target(gs, gs_target, {'gates': 1.0, 'spam': 0.01}) \n",
" # weight the gates differently from the SPAM operations\n",
"gs_go4 = pygsti.gaugeopt_to_target(gs, gs_target, {'gates': 1.0, 'spam': 0.01, 'Gx': 10.0, 'E0': 0.001}) \n",
" # weight an individual gate/SPAM separately (note the specific gate/SPAM labels always override\n",
" # the more general 'gates' and 'spam' weight values). \n",
"gs_go5 = pygsti.gaugeopt_to_target(gs, gs_target, gatesMetric=\"tracedist\") #use trace distance instead of frobenius\n",
"\n",
"print(\"Default gauge group = \",type(gs.default_gauge_group)) # default is FullGaugeGroup\n",
"gs_go6 = pygsti.gaugeopt_to_target(gs, gs_target, gauge_group=pygsti.objects.UnitaryGaugeGroup(gs.dim, 'pp'))\n",
" #gauge optimize only over unitary gauge transformations\n",
"\n",
"print(\"\\ngaugeopt_to_target output:\")\n",
"gs_go7 = pygsti.gaugeopt_to_target(gs, gs_target, verbosity=3) # show output\n",
"print(\"Final frobenius distance between gs_go7 and gs_target = \", gs_go7.frobeniusdist(gs_target))"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"## Compare MLGST with MC2GST (after gauge optimization)\n",
"\n",
"Both MLGST and MC2GST use a $\\chi^{2}$ optimization procedure for all but the final iteration. For the last set of gatestrings (the last iteration), MLGST uses a maximum likelihood estimation. Below, we show how close the two estimates are to one another. Before making the comparison, however, we **optimize the gauge** so the estimated gates are as close to the target gates as the gauge degrees of freedom allow."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"# We optimize over the gate set gauge\n",
"gs_mle = pygsti.gaugeopt_to_target(gs_mle,depol_gateset)\n",
"gs_mle_lowcnts = pygsti.gaugeopt_to_target(gs_mle_lowcnts,depol_gateset)\n",
"gs_mc2 = pygsti.gaugeopt_to_target(gs_mc2,depol_gateset)\n",
"gs_mc2_lowcnts = pygsti.gaugeopt_to_target(gs_mc2_lowcnts,depol_gateset)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Frobenius diff btwn MLGST and datagen = 0.001986\n",
"Frobenius diff btwn MC2GST and datagen = 0.001987\n",
"Frobenius diff btwn MLGST and LGST = 0.012193\n",
"Frobenius diff btwn MLGST and MC2GST = 5.3e-05\n",
"Chi^2 ( MC2GST ) = 1251.6313\n",
"Chi^2 ( MLGST ) = 1251.9954\n",
"LogL ( MC2GST ) = -2136570.5208\n",
"LogL ( MLGST ) = -2136570.337\n"
]
}
],
"source": [
"print(\"Frobenius diff btwn MLGST and datagen = {0}\".format(round(gs_mle.frobeniusdist(depol_gateset), 6)))\n",
"print(\"Frobenius diff btwn MC2GST and datagen = {0}\".format(round(gs_mc2.frobeniusdist(depol_gateset), 6)))\n",
"print(\"Frobenius diff btwn MLGST and LGST = {0}\".format(round(gs_mle.frobeniusdist(gs_clgst), 6)))\n",
"print(\"Frobenius diff btwn MLGST and MC2GST = {0}\".format(round(gs_mle.frobeniusdist(gs_mc2), 6)))\n",
"print(\"Chi^2 ( MC2GST ) = {0}\".format(round(pygsti.chi2(gs_mc2, ds, lsgstListOfLists[-1]), 4)))\n",
"print(\"Chi^2 ( MLGST ) = {0}\".format(round(pygsti.chi2(gs_mle, ds, lsgstListOfLists[-1] ), 4)))\n",
"print(\"LogL ( MC2GST ) = {0}\".format(round(pygsti.logl(gs_mc2, ds, lsgstListOfLists[-1]), 4)))\n",
"print(\"LogL ( MLGST ) = {0}\".format(round(pygsti.logl(gs_mle, ds, lsgstListOfLists[-1]), 4)))"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"Notice that, as expected, the MC2GST estimate has a *slightly* lower $\\chi^{2}$ score than the MLGST estimate, and the MLGST estimate has a *slightly* higher loglikelihood than the MC2GST estimate. In addition, _both_ are close (in terms of the Frobenius difference) to the depolarized gateset. Which is good - it means GST is giving us estimates which are close to the _true_ gateset used to generate the data. Performing the same analysis with the low-count data shows larger differences between the two, which is expected since the $\\chi^2$ and loglikelihood statistics are more similar at large $N$, that is, for large numbers of samples."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"LOW COUNT DATA:\n",
"Frobenius diff btwn MLGST and datagen = 0.008493\n",
"Frobenius diff btwn MC2GST and datagen = 0.008537\n",
"Frobenius diff btwn MLGST and LGST = 0.015241\n",
"Frobenius diff btwn MLGST and MC2GST = 0.009214\n",
"Chi^2 ( MC2GST ) = 1267.9804\n",
"Chi^2 ( MLGST ) = 1275.6837\n",
"LogL ( MC2GST ) = -106889.6808\n",
"LogL ( MLGST ) = -106885.8592\n"
]
}
],
"source": [
"print(\"LOW COUNT DATA:\")\n",
"print(\"Frobenius diff btwn MLGST and datagen = {0}\".format(round(gs_mle_lowcnts.frobeniusdist(depol_gateset), 6)))\n",
"print(\"Frobenius diff btwn MC2GST and datagen = {0}\".format(round(gs_mc2_lowcnts.frobeniusdist(depol_gateset), 6)))\n",
"print(\"Frobenius diff btwn MLGST and LGST = {0}\".format(round(gs_mle_lowcnts.frobeniusdist(gs_clgst), 6)))\n",
"print(\"Frobenius diff btwn MLGST and MC2GST = {0}\".format(round(gs_mle_lowcnts.frobeniusdist(gs_mc2), 6)))\n",
"print(\"Chi^2 ( MC2GST ) = {0}\".format(round(pygsti.chi2(gs_mc2_lowcnts, dsLowCounts, lsgstListOfLists[-1]), 4)))\n",
"print(\"Chi^2 ( MLGST ) = {0}\".format(round(pygsti.chi2(gs_mle_lowcnts, dsLowCounts, lsgstListOfLists[-1] ), 4)))\n",
"print(\"LogL ( MC2GST ) = {0}\".format(round(pygsti.logl(gs_mc2_lowcnts, dsLowCounts, lsgstListOfLists[-1]), 4)))\n",
"print(\"LogL ( MLGST ) = {0}\".format(round(pygsti.logl(gs_mle_lowcnts, dsLowCounts, lsgstListOfLists[-1]), 4)))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"deletable": true,
"editable": true
},
"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.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 0
}