This tutorial demonstrates how to perform GST on a "leaky-qubit" described by a 3-level (instead of the desired 2-level) system.

In [1]:

```
import pygsti
import pygsti.construction as pc
import pygsti.modelpacks.legacy.std1Q_XYI as std1Q
import numpy as np
import scipy.linalg as sla
#import pickle
```

In [2]:

```
def to_3level_unitary(U_2level):
U_3level = np.zeros((3,3),complex)
U_3level[0:2,0:2] = U_2level
U_3level[2,2] = 1.0
return U_3level
def unitary_to_gmgate(U):
return pygsti.tools.change_basis(
pygsti.tools.unitary_to_process_mx(U), 'std','gm')
def state_to_gmvec(state):
pygsti.tools.stdmx_to_gmvec
Us = pygsti.tools.internalgates.get_standard_gatename_unitaries()
```

In [3]:

```
mdl_2level_ideal = std1Q.target_model()
```

In [4]:

```
rho0 = np.array( [[1,0,0],
[0,0,0],
[0,0,0]], complex)
E0 = rho0
E1 = np.array( [[0,0,0],
[0,1,0],
[0,0,1]], complex)
sslbls = pygsti.obj.StateSpaceLabels(['Qubit+Leakage'],[9])
mdl_3level_ideal = pygsti.obj.ExplicitOpModel(sslbls, 'gm')
mdl_3level_ideal['rho0'] = pygsti.tools.stdmx_to_gmvec(rho0)
mdl_3level_ideal['Mdefault'] = pygsti.obj.TPPOVM([('0',pygsti.tools.stdmx_to_gmvec(E0)),
('1',pygsti.tools.stdmx_to_gmvec(E1))])
mdl_3level_ideal['Gi'] = unitary_to_gmgate( to_3level_unitary(Us['Gi']))
mdl_3level_ideal['Gx'] = unitary_to_gmgate( to_3level_unitary(Us['Gxpi2']))
mdl_3level_ideal['Gy'] = unitary_to_gmgate( to_3level_unitary(Us['Gypi2']))
```

In [5]:

```
sigmaX = np.array([[0,1],[1,0]],complex)
rot = sla.expm(1j * 0.1 * sigmaX)
Uleakage = np.identity(3,complex)
Uleakage[1:3,1:3] = rot
leakageOp = unitary_to_gmgate(Uleakage)
#print(Uleakage)
#Guess of a model w/just unitary leakage
mdl_3level_guess = mdl_3level_ideal.copy()
mdl_3level_guess['Gi'] = np.dot(leakageOp, mdl_3level_guess['Gi'])
#mdl_3level_guess['Gx'] = np.dot(leakageOp, mdl_3level_guess['Gx'])
#mdl_3level_guess['Gy'] = np.dot(leakageOp, mdl_3level_guess['Gy'])
#Actual model used for data generation (some depolarization too)
mdl_3level_noisy = mdl_3level_ideal.depolarize(op_noise=0.005, spam_noise=0.01)
mdl_3level_noisy['Gi'] = np.dot(leakageOp, mdl_3level_noisy['Gi'])
#mdl_3level_noisy['Gx'] = np.dot(leakageOp, mdl_3level_noisy['Gx'])
#mdl_3level_noisy['Gy'] = np.dot(leakageOp, mdl_3level_noisy['Gy'])
```

In [6]:

```
#print(mdl_3level_guess)
```

In [7]:

```
# get sequences using expected model
generate_fiducials = False
if generate_fiducials:
prepfids, measfids = pygsti.algorithms.generate_fiducials(
mdl_3level_guess, omitIdentity=False, maxFidLength=4, verbosity=4)
pygsti.io.write_circuit_list("example_files/leakage_prepfids.txt", prepfids)
pygsti.io.write_circuit_list("example_files/leakage_measfids.txt", measfids)
```

In [8]:

```
prepfids = pygsti.io.load_circuit_list("example_files/leakage_prepfids.txt")
measfids = pygsti.io.load_circuit_list("example_files/leakage_measfids.txt")
germs = std1Q.germs
maxLengths = [1,]
expList = pc.make_lsgst_experiment_list(mdl_3level_noisy, prepfids, measfids, germs, maxLengths)
ds = pc.generate_fake_data(mdl_3level_noisy, expList, 1000, 'binomial', seed=1234)
```

In [9]:

```
results_2level = pygsti.do_stdpractice_gst(ds, mdl_2level_ideal, prepfids, measfids,
germs, maxLengths, modes="CPTP", verbosity=3)
results_3level = pygsti.do_stdpractice_gst(ds, mdl_3level_ideal, prepfids, measfids,
germs, maxLengths, modes="CPTP,True",
modelsToTest={'True': mdl_3level_noisy},
verbosity=4, advancedOptions={'all': {'tolerance': 1e-2}})
```

In [10]:

```
pygsti.report.construct_standard_report(
{'two-level': results_2level, 'three-level': results_3level},
"Leakage Example Report"
).write_html('example_files/leakage_report')
```

In [11]:

```
#try a different basis:
gm_basis = pygsti.obj.Basis.cast('gm',9)
leakage_basis_mxs = [ np.sqrt(2)/3*(np.sqrt(3)*gm_basis[0] + 0.5*np.sqrt(6)*gm_basis[8]),
gm_basis[1], gm_basis[4], gm_basis[7],
gm_basis[2], gm_basis[3], gm_basis[5], gm_basis[6],
1/3*(np.sqrt(3)*gm_basis[0] - np.sqrt(6)*gm_basis[8]) ]
#for mx in leakage_basis_mxs:
# pygsti.tools.print_mx(mx)
check = np.zeros( (9,9), complex)
for i,m1 in enumerate(leakage_basis_mxs):
for j,m2 in enumerate(leakage_basis_mxs):
check[i,j] = np.trace(np.dot(m1,m2))
assert(np.allclose(check, np.identity(9,complex)))
leakage_basis = pygsti.obj.ExplicitBasis(leakage_basis_mxs, name="LeakageBasis",
longname="2+1 level leakage basis", real=True,
labels=['I','X','Y','Z','LX0','LX1','LY0','LY1','L'])
def changebasis_3level_model(mdl):
new_mdl = mdl.copy()
new_mdl.preps['rho0'] = pygsti.obj.FullSPAMVec(
pygsti.tools.change_basis(mdl.preps['rho0'].todense(), gm_basis, leakage_basis))
new_mdl.povms['Mdefault'] = pygsti.obj.UnconstrainedPOVM(
[('0', pygsti.tools.change_basis(mdl.povms['Mdefault']['0'].todense(), gm_basis, leakage_basis)),
('1', pygsti.tools.change_basis(mdl.povms['Mdefault']['1'].todense(), gm_basis, leakage_basis))])
for lbl,op in mdl.operations.items():
new_mdl.operations[lbl] = pygsti.obj.FullDenseOp(
pygsti.tools.change_basis(op.todense(), gm_basis, leakage_basis))
new_mdl.basis = leakage_basis
return new_mdl
def changebasis_3level_results(results):
new_results = results.copy()
for estlbl,est in results.estimates.items():
for mlbl,mdl in est.models.items():
if isinstance(mdl,(list,tuple)): #assume a list/tuple of models
new_results.estimates[estlbl].models[mlbl] = \
[ changebasis_3level_model(m) for m in mdl ]
else:
new_results.estimates[estlbl].models[mlbl] = changebasis_3level_model(mdl)
return new_results
```

In [12]:

```
results_3level_leakage_basis = changebasis_3level_results( results_3level )
```

In [13]:

```
pygsti.report.construct_standard_report(
{'two-level': results_2level, 'three-level': results_3level_leakage_basis},
"Leakage Example Report"
).write_html('example_files/leakage_report')
```

Open the report here

In [14]:

```
# use "kite" density-matrix structure
def to_2plus1_superop(superop_2level):
ret = np.zeros((5,5),'d')
ret[0:4,0:4] = superop_2level
ret[4,4] = 1.0 #leave leakage population where it is
return ret
#Tack on a single extra "0" for the 5-th dimension corresponding
# to the classical leakage level population.
rho0 = np.concatenate( (mdl_2level_ideal.preps['rho0'],[[0]]), axis=0)
E0 = np.concatenate( (mdl_2level_ideal.povms['Mdefault']['0'],[[0]]), axis=0)
E1 = np.concatenate( (mdl_2level_ideal.povms['Mdefault']['1'],[[0]]), axis=0)
sslbls = pygsti.obj.StateSpaceLabels([('Qubit',),('Leakage',)],[(4,),(1,)])
mdl_2plus1_ideal = pygsti.obj.ExplicitOpModel(sslbls, 'gm')
mdl_2plus1_ideal['rho0'] = rho0
mdl_2plus1_ideal['Mdefault'] = pygsti.obj.UnconstrainedPOVM([('0',E0),('1',E1)])
mdl_2plus1_ideal['Gi'] = to_2plus1_superop(mdl_2level_ideal['Gi'])
mdl_2plus1_ideal['Gx'] = to_2plus1_superop(mdl_2level_ideal['Gi'])
mdl_2plus1_ideal['Gy'] = to_2plus1_superop(mdl_2level_ideal['Gi'])
```

In [15]:

```
results_2plus1 = pygsti.do_long_sequence_gst(ds, mdl_2plus1_ideal, prepfids, measfids,
germs, maxLengths, verbosity=3,
advancedOptions={"starting point": "target"})
```

In [16]:

```
pygsti.report.construct_standard_report(
{'two-level': results_2level, 'three-level': results_3level_leakage_basis,
'two+one level': results_2plus1},
"Leakage Example Report"
).write_html('example_files/leakage_report', autosize='none')
```

Open the report here