from __future__ import print_function
#Import relevant modules.
import pygsti
import numpy as _np
from pygsti.algorithms import fiducialselection as FS
import matplotlib.pyplot as plt
%matplotlib inline
import time
In this notebook, we'll demonstrate how to select preparation and measurement fiducials for a standard two-qubit gate set. By "standard", we mean that a) measurements are made in the computational (Z) basis (and state prep is |00>), and b) gate set consists of independent X pi/2 and Y pi/2 gates on each qubit. Presumably there will be additional entangling gates available; however, we do not want (or need) such gates in our fiducial gate strings. (Two-qubit operations will typically be of lower fidelity, so it is "safer" to use single-qubit operations for fiducials.)
#Build the gate set. As mentioned above, no entangling operation is included; these results will be general for
#any two-qubit gate set that has access to the Gix, Giy, Gxi, and Gyi gates
#(and prepares in the state |00> and performs measurements in the computational basis).
gs_target = pygsti.construction.build_gateset( [4], [('Q0','Q1')],['Gix','Giy','Gxi','Gyi'],
["X(pi/2,Q1)", "Y(pi/2,Q1)", "X(pi/2,Q0)", "Y(pi/2,Q0)"],
prepLabels = ["rho0"], prepExpressions = ["0"],
effectLabels = ["E0","E1","E2"], effectExpressions = ["0","1","2"],
spamdefs={'upup': (0,0), 'updn': (0,1), 'dnup': (0,2), 'dndn': (0,-1) },
basis="pp")
#Let's try to pick out a fiducial set.
#First, we generate a candidate set which we'll attempt to prune.
#We could look at all gate strings of up to a fixed length (using pygsti.construction.list_all_gatestrings),
#but that grows quite rapidly.
#Instead, we'll look at the tensor product of the standard 1-qubit fiducial set with itself.
#This product set we define below.
#{} x 1q fid list
emptyList = pygsti.construction.gatestring_list([
(),
('Gix',),
('Gix','Gix'),
('Gix','Gix','Gix'),
('Giy',),
('Giy','Giy','Giy')
])
#Gx x 1q fid list
XList = pygsti.construction.gatestring_list([
('Gxi',),
('Gxi','Gix',),
('Gxi','Gix','Gix'),
('Gxi','Gix','Gix','Gix'),
('Gxi','Giy',),
('Gxi','Giy','Giy','Giy')
])
#GxGx x 1q fid list
XXList = pygsti.construction.gatestring_list([
('Gxi','Gxi'),
('Gxi','Gxi','Gix',),
('Gxi','Gxi','Gix','Gix'),
('Gxi','Gxi','Gix','Gix','Gix'),
('Gxi','Gxi','Giy',),
('Gxi','Gxi','Giy','Giy','Giy')
])
#GxGxGx x 1q fid list
XXXList = pygsti.construction.gatestring_list([
('Gxi','Gxi','Gxi'),
('Gxi','Gxi','Gxi','Gix',),
('Gxi','Gxi','Gxi','Gix','Gix'),
('Gxi','Gxi','Gxi','Gix','Gix','Gix'),
('Gxi','Gxi','Gxi','Giy',),
('Gxi','Gxi','Gxi','Giy','Giy','Giy')
])
#Gy x 1q fid list
YList = pygsti.construction.gatestring_list([
('Gyi',),
('Gyi','Gix',),
('Gyi','Gix','Gix'),
('Gyi','Gix','Gix','Gix'),
('Gyi','Giy',),
('Gyi','Giy','Giy','Giy')
])
#Gy x 1q fid list
YYYList = pygsti.construction.gatestring_list([
('Gyi','Gyi'),
('Gyi','Gyi','Gyi','Gix',),
('Gyi','Gyi','Gyi','Gix','Gix'),
('Gyi','Gyi','Gyi','Gix','Gix','Gix'),
('Gyi','Gyi','Gyi','Giy',),
('Gyi','Gyi','Gyi','Giy','Giy','Giy')
])
testFidList = emptyList + XList + XXList + XXXList + YList + YYYList
#Don't worry if the optimize_integer_fiducials_slack function below throws a divide by zero warning;
#this just means one of the tested cases was *really* bad.
#We know that we should be able to find a prep fiducial set that has no more than 16 elements,
#so if we are finding sets that are larger than that, we can always increase slackFrac or fixedSlack
start = time.time()
prepFidList1_all = FS.optimize_integer_fiducials_slack(gs_target,testFidList,prepOrMeas='prep',initialWeights=None,
scoreFunc='all',slackFrac=.275)
end = time.time()
print('')
print("Fiducial selection completed in", end-start, "seconds.")
print("\n".join(map(str,sorted(prepFidList1_all,key=len))))
Complete initial fiducial set succeeds. Now searching for best fiducial set. Starting fiducial set optimization. Lower score is better. score = 1468.8 weights = [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 1 1 1 1 0 0 1 1 1 1] L1(weights) = 16 Final fiducial set succeeds. Fiducial selection completed in 0.23148202896118164 seconds. {} GyiGiy GxiGxiGiy GyiGixGix GxiGxiGxiGix GxiGxiGxiGiy GyiGixGixGix GyiGiyGiyGiy GyiGyiGyiGiy GxiGxiGixGixGix GxiGxiGiyGiyGiy GxiGxiGxiGixGix GyiGyiGyiGixGix GxiGxiGxiGixGixGix GyiGyiGyiGixGixGix GyiGyiGyiGiyGiyGiy
#We know that we should be able to find a prep fiducial set that has no more than 16 elements,
#so if we are finding sets that are larger than that, we can always increase slackFrac or fixedSlack
start = time.time()
prepFidList1_worst = FS.optimize_integer_fiducials_slack(gs_target,testFidList,prepOrMeas='prep',initialWeights=None,
scoreFunc='worst',slackFrac=.275)
end = time.time()
print('')
print("Fiducial selection completed in", end-start, "seconds.")
print("\n".join(map(str,sorted(prepFidList1_worst,key=len))))
Complete initial fiducial set succeeds. Now searching for best fiducial set. Starting fiducial set optimization. Lower score is better. score = 249.001323854 weights = [1 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0] L1(weights) = 16 Final fiducial set succeeds. Fiducial selection completed in 0.2091379165649414 seconds. {} Giy GyiGyi GixGixGix GxiGxiGix GxiGxiGxi GyiGixGix GyiGixGixGix GyiGiyGiyGiy GyiGyiGyiGix GyiGyiGyiGiy GxiGxiGiyGiyGiy GxiGxiGxiGixGix GyiGyiGyiGixGix GxiGxiGxiGixGixGix GxiGxiGxiGiyGiyGiy
#We know that there might exist a fiducial measurement set with as few as 6 elements (as 6*3=18>16).
#However, repeated attempts to find one to date have failed. We can reliably identify fiducial measurement sets
#with only 9 elements, so 9 should be considered an upper bound. (If you do find a set with fewer than 9 elements,
#the pyGSTi team would love to hear from you!)
start = time.time()
measFidList1_all = FS.optimize_integer_fiducials_slack(gs_target,testFidList,prepOrMeas='meas',initialWeights=None,
scoreFunc='all',slackFrac=1)
end = time.time()
print('')
print("Fiducial selection completed in", end-start, "seconds.")
print("\n".join(map(str,sorted(measFidList1_all,key=len))))
Complete initial fiducial set succeeds. Now searching for best fiducial set. Starting fiducial set optimization. Lower score is better. score = 316.130180659 weights = [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 0 1] L1(weights) = 9 Final fiducial set succeeds. Fiducial selection completed in 0.3222181797027588 seconds. {} GxiGxiGxiGiy GyiGyiGyiGix GxiGxiGixGixGix GxiGxiGiyGiyGiy GxiGxiGxiGixGix GyiGyiGyiGixGix GxiGxiGxiGixGixGix GyiGyiGyiGiyGiyGiy
#Let's try the same as above, but with "worst" instead of "all" as the scoreFunc.
start = time.time()
measFidList1_worst = FS.optimize_integer_fiducials_slack(gs_target,testFidList,prepOrMeas='meas',initialWeights=None,
scoreFunc='worst',slackFrac=1)
end = time.time()
print('')
print("Fiducial selection completed in", end-start, "seconds.")
print("\n".join(map(str,sorted(measFidList1_worst,key=len))))
Complete initial fiducial set succeeds. Now searching for best fiducial set. Starting fiducial set optimization. Lower score is better. score = 48.4574110103 weights = [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0] L1(weights) = 9 Final fiducial set succeeds. Fiducial selection completed in 0.314039945602417 seconds. {} GxiGxiGxiGix GyiGyiGyiGiy GxiGxiGixGixGix GxiGxiGiyGiyGiy GxiGxiGxiGixGix GyiGyiGyiGixGix GxiGxiGxiGiyGiyGiy GyiGyiGyiGixGixGix
FS.test_fiducial_list(gs_target, prepFidList1_all,'prep', scoreFunc='all', returnAll=True)
(True, [0.035777874246103326, 0.094384513594891764, 0.12472064408483972, 0.18406325009774369, 0.21922359359558477, 0.24878825006702784, 0.32992842070695388, 0.49999999999999961, 0.60106985528731904, 0.8952780966140732, 1.0000000000000002, 1.2601374932937572, 1.5082401339544393, 1.9793250220729006, 2.280776406404414, 4.7382864459799485], Score: 1152.0000000000025, N: 16)
print("prep fid_all spectrum:\n", FS.test_fiducial_list(gs_target, prepFidList1_all, 'prep',
returnAll=True)[1])
print("prep fid_all 'all-score':", FS.compute_composite_score(gs_target, prepFidList1_all, 'prep',
scoreFunc='all').score)
print("prep fid_all 'worst-score':", FS.compute_composite_score(gs_target, prepFidList1_all, 'prep',
scoreFunc='worst').score)
prep fid_all spectrum: [0.035777874246103757, 0.094384513594892402, 0.12472064408484011, 0.18406325009774313, 0.21922359359558505, 0.24878825006702732, 0.32992842070695388, 0.5, 0.60106985528731915, 0.89527809661407276, 1.0, 1.2601374932937566, 1.5082401339544393, 1.9793250220729006, 2.2807764064044158, 4.7382864459799485] prep fid_all 'all-score': 1152.0 prep fid_all 'worst-score': 447.20376314
print("prep fid_worst spectrum:\n", FS.test_fiducial_list(gs_target, prepFidList1_worst, 'prep',
returnAll=True)[1])
print("prep fid_worst 'all-score':", FS.compute_composite_score(gs_target, prepFidList1_worst, 'prep',
scoreFunc='all').score)
print("prep fid_worst 'worst-score':", FS.compute_composite_score(gs_target, prepFidList1_worst, 'prep',
scoreFunc='worst').score)
prep fid_worst spectrum: [0.081927275262132032, 0.11388855211719048, 0.1320152782977117, 0.1951852156926718, 0.27205660994856667, 0.29289321881345226, 0.49999999999999944, 0.49999999999999967, 0.50000000000000011, 0.65555661468669424, 0.91892639567648526, 1.114993642934855, 1.7071067811865468, 2.1841101287185047, 2.1951284422577562, 4.6362118444074252] prep fid_worst 'all-score': 832.0 prep fid_worst 'worst-score': 195.295155964
#Interestingly, using the option "worst" instead of "all" yields a better scoring fiducial set, by both the "worst"
#and "all".
print("prep meas_all spectrum:\n", FS.test_fiducial_list(gs_target, measFidList1_all, 'meas',
returnAll=True)[1])
print("prep meas_all 'all-score':", FS.compute_composite_score(gs_target, measFidList1_all, 'meas',
scoreFunc='all').score)
print("prep meas_all 'worst-score':", FS.compute_composite_score(gs_target, measFidList1_all, 'meas',
scoreFunc='worst').score)
prep meas_all spectrum: [0.3714602085566765, 0.50000000000000056, 0.56368584497043994, 0.64534972638934507, 0.71248175049995766, 0.71922359359558552, 0.744102543127522, 0.74999999999999989, 0.75000000000000011, 1.9166803725509385, 2.0000000000000022, 2.1610191647597001, 2.5209138803963618, 2.7710731135452389, 2.780776406404418, 7.0932333952038285] prep meas_all 'all-score': 158.065090329 prep meas_all 'worst-score': 24.2287055051
print("prep meas_worst spectrum:\n", FS.test_fiducial_list(gs_target, measFidList1_worst, 'meas',
returnAll=True)[1])
print("prep meas_worst 'all-score':", FS.compute_composite_score(gs_target, measFidList1_worst, 'meas',
scoreFunc='all').score)
print("prep meas_worst 'worst-score':", FS.compute_composite_score(gs_target, measFidList1_worst, 'meas',
scoreFunc='worst').score)
prep meas_worst spectrum: [0.3714602085566765, 0.50000000000000056, 0.56368584497044039, 0.64534972638934496, 0.71248175049995877, 0.71922359359558552, 0.74410254312752211, 0.74999999999999978, 0.75000000000000089, 1.9166803725509376, 2.0000000000000022, 2.1610191647597015, 2.52091388039636, 2.7710731135452402, 2.780776406404418, 7.093233395203832] prep meas_worst 'all-score': 158.065090329 prep meas_worst 'worst-score': 24.2287055051
for i in range(len(measFidList1_all)):
print(sorted(measFidList1_all,key=len)[i], '\t', sorted(measFidList1_worst,key=len)[i], '\t', sorted(measFidList1_all,key=len)[i] == sorted(measFidList1_worst,key=len)[i])
{} {} True GxiGxiGxiGiy GxiGxiGxiGix False GyiGyiGyiGix GyiGyiGyiGiy False GxiGxiGixGixGix GxiGxiGixGixGix True GxiGxiGiyGiyGiy GxiGxiGiyGiyGiy True GxiGxiGxiGixGix GxiGxiGxiGixGix True GyiGyiGyiGixGix GyiGyiGyiGixGix True GxiGxiGxiGixGixGix GxiGxiGxiGiyGiyGiy False GyiGyiGyiGiyGiyGiy GyiGyiGyiGixGixGix False
#We have the same scores for "all" and "worst" for measurement fiducials, even though the fiducial sets themselves
#are not quite the same.
#Lastly, let's see if we can find a minimal set of measurement fiducials (size 6), using the same input set as before.
start = time.time()
measFidList1_all_force6 = FS.optimize_integer_fiducials_slack(gs_target,testFidList,prepOrMeas='meas',initialWeights=None,fixedNum=6,
scoreFunc='all',slackFrac=1)
end = time.time()
print('')
print("Fiducial selection completed in", end-start, "seconds.")
print("\n".join(map(str,sorted(measFidList1_worst,key=len))))
Complete initial fiducial set succeeds. Now searching for best fiducial set. Starting fiducial set optimization. Lower score is better. Output set is required to be of size6 Total number of fiducial sets to be checked is324632.0
WARNING: If this is very large, you may wish to abort.
Switching! Switching! Switching! Switching! Fiducial selection completed in 103.61686706542969 seconds. {} GxiGxiGxiGix GyiGyiGyiGiy GxiGxiGixGixGix GxiGxiGiyGiyGiy GxiGxiGxiGixGix GyiGyiGyiGixGix GxiGxiGxiGiyGiyGiy GyiGyiGyiGixGixGix
FS.test_fiducial_list(gs_target,measFidList1_all_force6,'meas',scoreFunc='all',returnAll=True)
(False, [0.0, 2.4995843092626328e-16, 2.7770928464217906e-16, 3.8492813519304379e-16, 0.42672875571022356, 0.4934886775389975, 0.6563680176830814, 0.67679045677623229, 0.74999999999999989, 1.0000000000000004, 1.0000000000000013, 1.4193625622157191, 1.7710921857106274, 2.1291505505848565, 2.645811040896072, 5.0312077528842014], Score: 78.11868131868127, N: 12)
#Sadly, this did not work! However, one could try different input sets (or increasing fixedNum to 7 or 8, which would
#still be better than 9.)