pyGSTi 0.9.12.1__cp38-cp38-win_amd64.whl → 0.9.13__cp38-cp38-win_amd64.whl
Sign up to get free protection for your applications and to get access to all the features.
- pyGSTi-0.9.13.dist-info/METADATA +185 -0
- {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +207 -217
- {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/WHEEL +1 -1
- pygsti/_version.py +2 -2
- pygsti/algorithms/contract.py +1 -1
- pygsti/algorithms/core.py +42 -28
- pygsti/algorithms/fiducialselection.py +17 -8
- pygsti/algorithms/gaugeopt.py +2 -2
- pygsti/algorithms/germselection.py +87 -77
- pygsti/algorithms/mirroring.py +0 -388
- pygsti/algorithms/randomcircuit.py +165 -1333
- pygsti/algorithms/rbfit.py +0 -234
- pygsti/baseobjs/basis.py +94 -396
- pygsti/baseobjs/errorgenbasis.py +0 -132
- pygsti/baseobjs/errorgenspace.py +0 -10
- pygsti/baseobjs/label.py +52 -168
- pygsti/baseobjs/opcalc/fastopcalc.cp38-win_amd64.pyd +0 -0
- pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
- pygsti/baseobjs/polynomial.py +13 -595
- pygsti/baseobjs/statespace.py +1 -0
- pygsti/circuits/__init__.py +1 -1
- pygsti/circuits/circuit.py +682 -505
- pygsti/circuits/circuitconstruction.py +0 -4
- pygsti/circuits/circuitlist.py +47 -5
- pygsti/circuits/circuitparser/__init__.py +8 -8
- pygsti/circuits/circuitparser/fastcircuitparser.cp38-win_amd64.pyd +0 -0
- pygsti/circuits/circuitstructure.py +3 -3
- pygsti/circuits/cloudcircuitconstruction.py +1 -1
- pygsti/data/datacomparator.py +2 -7
- pygsti/data/dataset.py +46 -44
- pygsti/data/hypothesistest.py +0 -7
- pygsti/drivers/bootstrap.py +0 -49
- pygsti/drivers/longsequence.py +2 -1
- pygsti/evotypes/basereps_cython.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/chp/opreps.py +0 -61
- pygsti/evotypes/chp/statereps.py +0 -32
- pygsti/evotypes/densitymx/effectcreps.cpp +9 -10
- pygsti/evotypes/densitymx/effectreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/effectreps.pyx +1 -1
- pygsti/evotypes/densitymx/opreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/opreps.pyx +2 -2
- pygsti/evotypes/densitymx/statereps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/densitymx/statereps.pyx +1 -1
- pygsti/evotypes/densitymx_slow/effectreps.py +7 -23
- pygsti/evotypes/densitymx_slow/opreps.py +16 -23
- pygsti/evotypes/densitymx_slow/statereps.py +10 -3
- pygsti/evotypes/evotype.py +39 -2
- pygsti/evotypes/stabilizer/effectreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
- pygsti/evotypes/stabilizer/opreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/opreps.pyx +0 -4
- pygsti/evotypes/stabilizer/statereps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/statereps.pyx +1 -5
- pygsti/evotypes/stabilizer/termreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/stabilizer/termreps.pyx +0 -7
- pygsti/evotypes/stabilizer_slow/effectreps.py +0 -22
- pygsti/evotypes/stabilizer_slow/opreps.py +0 -4
- pygsti/evotypes/stabilizer_slow/statereps.py +0 -4
- pygsti/evotypes/statevec/effectreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/effectreps.pyx +1 -1
- pygsti/evotypes/statevec/opreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/opreps.pyx +2 -2
- pygsti/evotypes/statevec/statereps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/statereps.pyx +1 -1
- pygsti/evotypes/statevec/termreps.cp38-win_amd64.pyd +0 -0
- pygsti/evotypes/statevec/termreps.pyx +0 -7
- pygsti/evotypes/statevec_slow/effectreps.py +0 -3
- pygsti/evotypes/statevec_slow/opreps.py +0 -5
- pygsti/extras/__init__.py +0 -1
- pygsti/extras/drift/stabilityanalyzer.py +3 -1
- pygsti/extras/interpygate/__init__.py +12 -0
- pygsti/extras/interpygate/core.py +0 -36
- pygsti/extras/interpygate/process_tomography.py +44 -10
- pygsti/extras/rpe/rpeconstruction.py +0 -2
- pygsti/forwardsims/__init__.py +1 -0
- pygsti/forwardsims/forwardsim.py +14 -55
- pygsti/forwardsims/mapforwardsim.py +69 -18
- pygsti/forwardsims/mapforwardsim_calc_densitymx.cp38-win_amd64.pyd +0 -0
- pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx +65 -66
- pygsti/forwardsims/mapforwardsim_calc_generic.py +91 -13
- pygsti/forwardsims/matrixforwardsim.py +63 -15
- pygsti/forwardsims/termforwardsim.py +8 -110
- pygsti/forwardsims/termforwardsim_calc_stabilizer.cp38-win_amd64.pyd +0 -0
- pygsti/forwardsims/termforwardsim_calc_statevec.cp38-win_amd64.pyd +0 -0
- pygsti/forwardsims/termforwardsim_calc_statevec.pyx +0 -651
- pygsti/forwardsims/torchfwdsim.py +265 -0
- pygsti/forwardsims/weakforwardsim.py +2 -2
- pygsti/io/__init__.py +1 -2
- pygsti/io/mongodb.py +0 -2
- pygsti/io/stdinput.py +6 -22
- pygsti/layouts/copalayout.py +10 -12
- pygsti/layouts/distlayout.py +0 -40
- pygsti/layouts/maplayout.py +103 -25
- pygsti/layouts/matrixlayout.py +99 -60
- pygsti/layouts/prefixtable.py +1534 -52
- pygsti/layouts/termlayout.py +1 -1
- pygsti/modelmembers/instruments/instrument.py +3 -3
- pygsti/modelmembers/instruments/tpinstrument.py +2 -2
- pygsti/modelmembers/modelmember.py +0 -17
- pygsti/modelmembers/operations/__init__.py +2 -4
- pygsti/modelmembers/operations/affineshiftop.py +1 -0
- pygsti/modelmembers/operations/composederrorgen.py +1 -1
- pygsti/modelmembers/operations/composedop.py +1 -24
- pygsti/modelmembers/operations/denseop.py +5 -5
- pygsti/modelmembers/operations/eigpdenseop.py +2 -2
- pygsti/modelmembers/operations/embeddederrorgen.py +1 -1
- pygsti/modelmembers/operations/embeddedop.py +0 -1
- pygsti/modelmembers/operations/experrorgenop.py +2 -2
- pygsti/modelmembers/operations/fullarbitraryop.py +1 -0
- pygsti/modelmembers/operations/fullcptpop.py +2 -2
- pygsti/modelmembers/operations/fulltpop.py +28 -6
- pygsti/modelmembers/operations/fullunitaryop.py +5 -4
- pygsti/modelmembers/operations/lindbladcoefficients.py +93 -78
- pygsti/modelmembers/operations/lindbladerrorgen.py +268 -441
- pygsti/modelmembers/operations/linearop.py +7 -27
- pygsti/modelmembers/operations/opfactory.py +1 -1
- pygsti/modelmembers/operations/repeatedop.py +1 -24
- pygsti/modelmembers/operations/staticstdop.py +1 -1
- pygsti/modelmembers/povms/__init__.py +3 -3
- pygsti/modelmembers/povms/basepovm.py +7 -36
- pygsti/modelmembers/povms/complementeffect.py +4 -9
- pygsti/modelmembers/povms/composedeffect.py +0 -320
- pygsti/modelmembers/povms/computationaleffect.py +1 -1
- pygsti/modelmembers/povms/computationalpovm.py +3 -1
- pygsti/modelmembers/povms/effect.py +3 -5
- pygsti/modelmembers/povms/marginalizedpovm.py +0 -79
- pygsti/modelmembers/povms/tppovm.py +74 -2
- pygsti/modelmembers/states/__init__.py +2 -5
- pygsti/modelmembers/states/composedstate.py +0 -317
- pygsti/modelmembers/states/computationalstate.py +3 -3
- pygsti/modelmembers/states/cptpstate.py +4 -4
- pygsti/modelmembers/states/densestate.py +6 -4
- pygsti/modelmembers/states/fullpurestate.py +0 -24
- pygsti/modelmembers/states/purestate.py +1 -1
- pygsti/modelmembers/states/state.py +5 -6
- pygsti/modelmembers/states/tpstate.py +28 -10
- pygsti/modelmembers/term.py +3 -6
- pygsti/modelmembers/torchable.py +50 -0
- pygsti/modelpacks/_modelpack.py +1 -1
- pygsti/modelpacks/smq1Q_ZN.py +3 -1
- pygsti/modelpacks/smq2Q_XXYYII.py +2 -1
- pygsti/modelpacks/smq2Q_XY.py +3 -3
- pygsti/modelpacks/smq2Q_XYI.py +2 -2
- pygsti/modelpacks/smq2Q_XYICNOT.py +3 -3
- pygsti/modelpacks/smq2Q_XYICPHASE.py +3 -3
- pygsti/modelpacks/smq2Q_XYXX.py +1 -1
- pygsti/modelpacks/smq2Q_XYZICNOT.py +3 -3
- pygsti/modelpacks/smq2Q_XYZZ.py +1 -1
- pygsti/modelpacks/stdtarget.py +0 -121
- pygsti/models/cloudnoisemodel.py +1 -2
- pygsti/models/explicitcalc.py +3 -3
- pygsti/models/explicitmodel.py +3 -13
- pygsti/models/fogistore.py +5 -3
- pygsti/models/localnoisemodel.py +1 -2
- pygsti/models/memberdict.py +0 -12
- pygsti/models/model.py +800 -65
- pygsti/models/modelconstruction.py +4 -4
- pygsti/models/modelnoise.py +2 -2
- pygsti/models/modelparaminterposer.py +1 -1
- pygsti/models/oplessmodel.py +1 -1
- pygsti/models/qutrit.py +15 -14
- pygsti/objectivefns/objectivefns.py +73 -138
- pygsti/objectivefns/wildcardbudget.py +2 -7
- pygsti/optimize/__init__.py +1 -0
- pygsti/optimize/arraysinterface.py +28 -0
- pygsti/optimize/customcg.py +0 -12
- pygsti/optimize/customlm.py +129 -323
- pygsti/optimize/customsolve.py +2 -2
- pygsti/optimize/optimize.py +0 -84
- pygsti/optimize/simplerlm.py +841 -0
- pygsti/optimize/wildcardopt.py +19 -598
- pygsti/protocols/confidenceregionfactory.py +28 -14
- pygsti/protocols/estimate.py +31 -14
- pygsti/protocols/gst.py +142 -68
- pygsti/protocols/modeltest.py +6 -10
- pygsti/protocols/protocol.py +9 -37
- pygsti/protocols/rb.py +450 -79
- pygsti/protocols/treenode.py +8 -2
- pygsti/protocols/vb.py +108 -206
- pygsti/protocols/vbdataframe.py +1 -1
- pygsti/report/factory.py +0 -15
- pygsti/report/fogidiagram.py +1 -17
- pygsti/report/modelfunction.py +12 -3
- pygsti/report/mpl_colormaps.py +1 -1
- pygsti/report/plothelpers.py +8 -2
- pygsti/report/reportables.py +41 -37
- pygsti/report/templates/offline/pygsti_dashboard.css +6 -0
- pygsti/report/templates/offline/pygsti_dashboard.js +12 -0
- pygsti/report/workspace.py +2 -14
- pygsti/report/workspaceplots.py +326 -504
- pygsti/tools/basistools.py +9 -36
- pygsti/tools/edesigntools.py +124 -96
- pygsti/tools/fastcalc.cp38-win_amd64.pyd +0 -0
- pygsti/tools/fastcalc.pyx +35 -81
- pygsti/tools/internalgates.py +151 -15
- pygsti/tools/jamiolkowski.py +5 -5
- pygsti/tools/lindbladtools.py +19 -11
- pygsti/tools/listtools.py +0 -114
- pygsti/tools/matrixmod2.py +1 -1
- pygsti/tools/matrixtools.py +173 -339
- pygsti/tools/nameddict.py +1 -1
- pygsti/tools/optools.py +154 -88
- pygsti/tools/pdftools.py +0 -25
- pygsti/tools/rbtheory.py +3 -320
- pygsti/tools/slicetools.py +64 -12
- pyGSTi-0.9.12.1.dist-info/METADATA +0 -155
- pygsti/algorithms/directx.py +0 -711
- pygsti/evotypes/qibo/__init__.py +0 -33
- pygsti/evotypes/qibo/effectreps.py +0 -78
- pygsti/evotypes/qibo/opreps.py +0 -376
- pygsti/evotypes/qibo/povmreps.py +0 -98
- pygsti/evotypes/qibo/statereps.py +0 -174
- pygsti/extras/rb/__init__.py +0 -13
- pygsti/extras/rb/benchmarker.py +0 -957
- pygsti/extras/rb/dataset.py +0 -378
- pygsti/extras/rb/io.py +0 -814
- pygsti/extras/rb/simulate.py +0 -1020
- pygsti/io/legacyio.py +0 -385
- pygsti/modelmembers/povms/denseeffect.py +0 -142
- {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
- {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/top_level.txt +0 -0
pygsti/extras/rb/simulate.py
DELETED
@@ -1,1020 +0,0 @@
|
|
1
|
-
""" Clifford circuits with Pauli errors simulation functions """
|
2
|
-
#***************************************************************************************************
|
3
|
-
# Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
4
|
-
# Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights
|
5
|
-
# in this software.
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
7
|
-
# in compliance with the License. You may obtain a copy of the License at
|
8
|
-
# http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory.
|
9
|
-
#***************************************************************************************************
|
10
|
-
|
11
|
-
import os as _os
|
12
|
-
import time as _time
|
13
|
-
|
14
|
-
import numpy as _np
|
15
|
-
|
16
|
-
from pygsti.baseobjs.label import Label as _Lbl
|
17
|
-
from pygsti.data.dataset import DataSet as _DataSet
|
18
|
-
from pygsti.tools import symplectic as _symp
|
19
|
-
|
20
|
-
#from . import sample as _samp
|
21
|
-
_samp = None # MOVED - and this module is deprecated & broken now, so just set to None
|
22
|
-
|
23
|
-
|
24
|
-
def random_paulierror_in_chp(q):
|
25
|
-
"""
|
26
|
-
todo.
|
27
|
-
"""
|
28
|
-
i = _np.random.randint(0, 3)
|
29
|
-
|
30
|
-
if i == 0:
|
31
|
-
return ('p ' + str(q) + '\n') * 2
|
32
|
-
|
33
|
-
elif i == 1:
|
34
|
-
return 'h ' + str(q) + '\n' + ('p ' + str(q) + '\n') * 2 + 'h ' + str(q) + '\n'
|
35
|
-
|
36
|
-
else:
|
37
|
-
return ('p ' + str(q) + '\n') * 2 + 'h ' + str(q) + '\n' + ('p ' + str(q) + '\n') * 2 + 'h ' + str(q) + '\n'
|
38
|
-
|
39
|
-
|
40
|
-
def random_pauli_in_chp(q):
|
41
|
-
"""
|
42
|
-
todo.
|
43
|
-
"""
|
44
|
-
i = _np.random.randint(0, 4)
|
45
|
-
|
46
|
-
if i == 0:
|
47
|
-
return ''
|
48
|
-
|
49
|
-
elif i == 1:
|
50
|
-
return ('p ' + str(q) + '\n') * 2
|
51
|
-
|
52
|
-
elif i == 2:
|
53
|
-
return 'h ' + str(q) + '\n' + ('p ' + str(q) + '\n') * 2 + 'h ' + str(q) + '\n'
|
54
|
-
|
55
|
-
else:
|
56
|
-
return ('p ' + str(q) + '\n') * 2 + 'h ' + str(q) + '\n' + ('p ' + str(q) + '\n') * 2 + 'h ' + str(q) + '\n'
|
57
|
-
|
58
|
-
|
59
|
-
def stdgate_to_chp(gate, chpqubits):
|
60
|
-
"""
|
61
|
-
todo
|
62
|
-
Converts any of the standard Clifford gates to a chp string.
|
63
|
-
"""
|
64
|
-
gatestr = str(gate).split(':')
|
65
|
-
name = gatestr[0]
|
66
|
-
qubits = [chpqubits[q] for q in gatestr[1:]]
|
67
|
-
|
68
|
-
if name == 'Gi':
|
69
|
-
return ''
|
70
|
-
|
71
|
-
elif name == 'Gxpi':
|
72
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
73
|
-
s += ('p ' + str(qubits[0]) + '\n') * 2
|
74
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
75
|
-
return s
|
76
|
-
|
77
|
-
elif name == 'Gypi':
|
78
|
-
s = ('p ' + str(qubits[0]) + '\n') * 2
|
79
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
80
|
-
s += ('p ' + str(qubits[0]) + '\n') * 2
|
81
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
82
|
-
return s
|
83
|
-
|
84
|
-
elif name == 'Gzpi':
|
85
|
-
return ('p ' + str(qubits[0]) + '\n') * 2
|
86
|
-
|
87
|
-
elif name == 'Gxpi2':
|
88
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
89
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
90
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
91
|
-
return s
|
92
|
-
|
93
|
-
elif name == 'Gxmpi2':
|
94
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
95
|
-
s += ('p ' + str(qubits[0]) + '\n') * 3
|
96
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
97
|
-
return s
|
98
|
-
|
99
|
-
elif name == 'Gzpi2' or name == 'Gp':
|
100
|
-
return 'p ' + str(qubits[0]) + '\n'
|
101
|
-
|
102
|
-
elif name == 'Gzmpi2' or name == 'Gpdag':
|
103
|
-
return ('p ' + str(qubits[0]) + '\n') * 3
|
104
|
-
|
105
|
-
elif name == 'Gh':
|
106
|
-
return ('h ' + str(qubits[0]) + '\n')
|
107
|
-
|
108
|
-
elif name == 'Gc0':
|
109
|
-
return ''
|
110
|
-
|
111
|
-
elif name == 'Gc1':
|
112
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
113
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
114
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
115
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
116
|
-
return s
|
117
|
-
|
118
|
-
elif name == 'Gc2':
|
119
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
120
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
121
|
-
return s
|
122
|
-
|
123
|
-
elif name == 'Gc3':
|
124
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
125
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
126
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
127
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
128
|
-
return s
|
129
|
-
|
130
|
-
elif name == 'Gc4':
|
131
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
132
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
133
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
134
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
135
|
-
return s
|
136
|
-
|
137
|
-
elif name == 'Gc5':
|
138
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
139
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
140
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
141
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
142
|
-
return s
|
143
|
-
|
144
|
-
elif name == 'Gc6':
|
145
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
146
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
147
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
148
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
149
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
150
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
151
|
-
return s
|
152
|
-
|
153
|
-
elif name == 'Gc7':
|
154
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
155
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
156
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
157
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
158
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
159
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
160
|
-
return s
|
161
|
-
|
162
|
-
elif name == 'Gc8':
|
163
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
164
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
165
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
166
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
167
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
168
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
169
|
-
return s
|
170
|
-
|
171
|
-
elif name == 'Gc9':
|
172
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
173
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
174
|
-
return s
|
175
|
-
|
176
|
-
elif name == 'Gc10':
|
177
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
178
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
179
|
-
return s
|
180
|
-
|
181
|
-
elif name == 'Gc11':
|
182
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
183
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
184
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
185
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
186
|
-
return s
|
187
|
-
|
188
|
-
elif name == 'Gc12':
|
189
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
190
|
-
return s
|
191
|
-
|
192
|
-
elif name == 'Gc13':
|
193
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
194
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
195
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
196
|
-
return s
|
197
|
-
|
198
|
-
elif name == 'Gc14':
|
199
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
200
|
-
return s
|
201
|
-
|
202
|
-
elif name == 'Gc15':
|
203
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
204
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
205
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
206
|
-
return s
|
207
|
-
|
208
|
-
elif name == 'Gc16':
|
209
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
210
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
211
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
212
|
-
return s
|
213
|
-
|
214
|
-
elif name == 'Gc17':
|
215
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
216
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
217
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
218
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
219
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
220
|
-
return s
|
221
|
-
|
222
|
-
elif name == 'Gc18':
|
223
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
224
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
225
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
226
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
227
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
228
|
-
return s
|
229
|
-
|
230
|
-
elif name == 'Gc19':
|
231
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
232
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
233
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
234
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
235
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
236
|
-
return s
|
237
|
-
|
238
|
-
elif name == 'Gc20':
|
239
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
240
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
241
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
242
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
243
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
244
|
-
return s
|
245
|
-
|
246
|
-
elif name == 'Gc21':
|
247
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
248
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
249
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
250
|
-
return s
|
251
|
-
|
252
|
-
elif name == 'Gc22':
|
253
|
-
s = 'h ' + str(qubits[0]) + '\n'
|
254
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
255
|
-
s += 'h ' + str(qubits[0]) + '\n'
|
256
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
257
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
258
|
-
return s
|
259
|
-
|
260
|
-
elif name == 'Gc23':
|
261
|
-
s = 'p ' + str(qubits[0]) + '\n'
|
262
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
263
|
-
s += 'p ' + str(qubits[0]) + '\n'
|
264
|
-
return s
|
265
|
-
|
266
|
-
elif name == 'Gcnot':
|
267
|
-
return 'c ' + str(qubits[0]) + ' ' + str(qubits[1]) + '\n'
|
268
|
-
|
269
|
-
elif name == 'Gcphase':
|
270
|
-
s = 'h ' + str(qubits[1]) + '\n'
|
271
|
-
s += 'c ' + str(qubits[0]) + ' ' + str(qubits[1]) + '\n'
|
272
|
-
s = 'h ' + str(qubits[1]) + '\n'
|
273
|
-
return s
|
274
|
-
|
275
|
-
else:
|
276
|
-
raise ValueError("{} is an unknown gate! You must make your own `gateinchp` function!".format(gate))
|
277
|
-
|
278
|
-
|
279
|
-
class IndDepolErrorModel(object):
|
280
|
-
"""
|
281
|
-
todo
|
282
|
-
|
283
|
-
"""
|
284
|
-
|
285
|
-
def __init__(self, gate_errors, readout_errors):
|
286
|
-
"""
|
287
|
-
todo
|
288
|
-
|
289
|
-
"""
|
290
|
-
self.gate_errors = gate_errors
|
291
|
-
self.readout_errors = readout_errors
|
292
|
-
|
293
|
-
def layer_uniform_pauli_probability(self, layer, qubitorder):
|
294
|
-
"""
|
295
|
-
todo.
|
296
|
-
|
297
|
-
"""
|
298
|
-
if len(layer) > 0:
|
299
|
-
return 1 - _np.prod([1 - _np.array([4 * self.gate_errors[gate].get(q, 0) / 3
|
300
|
-
for q in qubitorder]) for gate in layer], axis=0)
|
301
|
-
else:
|
302
|
-
return _np.zeros(len(qubitorder), float)
|
303
|
-
|
304
|
-
def readout_uniform_pauli_probability(self, qubitorder):
|
305
|
-
"""
|
306
|
-
todo
|
307
|
-
|
308
|
-
"""
|
309
|
-
return 1 - _np.prod([1 - _np.array([4 * self.readout_errors[q1].get(q2, 0) / 3
|
310
|
-
for q2 in qubitorder]) for q1 in qubitorder], axis=0)
|
311
|
-
|
312
|
-
|
313
|
-
def depolarizing_errors_circuit_simulator(circuitlist, shots, errormodel, gate_to_chp=None,
|
314
|
-
aux_info_list=None, collision_action='keepseparate',
|
315
|
-
outdir='', perge_chp_files=True, returnds=True,
|
316
|
-
verbosity=1):
|
317
|
-
"""
|
318
|
-
todo.
|
319
|
-
|
320
|
-
"""
|
321
|
-
if returnds:
|
322
|
-
ds = _DataSet(collision_action=collision_action)
|
323
|
-
else:
|
324
|
-
ds = []
|
325
|
-
assert(_os.path.isfile("chp")), "This simulator uses the chp.c code.\n" + \
|
326
|
-
"It must be compiled to an executable called `chp` and situated in this folder!"
|
327
|
-
|
328
|
-
try:
|
329
|
-
_os.mkdir(outdir)
|
330
|
-
if perge_chp_files:
|
331
|
-
perge_dir = True
|
332
|
-
else:
|
333
|
-
perge_dir = False
|
334
|
-
except:
|
335
|
-
perge_dir = False
|
336
|
-
pass
|
337
|
-
|
338
|
-
time0 = _time.time()
|
339
|
-
|
340
|
-
if gate_to_chp is None: gate_to_chp = stdgate_to_chp
|
341
|
-
|
342
|
-
percentdone = 0
|
343
|
-
for cind, circuit in enumerate(circuitlist):
|
344
|
-
print(cind)
|
345
|
-
time1 = _time.time()
|
346
|
-
|
347
|
-
if verbosity > 0:
|
348
|
-
if verbosity > 1:
|
349
|
-
print("{0:.2f}".format(cind / len(circuitlist)), end=' ')
|
350
|
-
else:
|
351
|
-
if int(_np.floor(cind / len(circuitlist))) > percentdone:
|
352
|
-
percentdone += 1
|
353
|
-
print(" - Simulation {} percent complete.".format(percentdone))
|
354
|
-
|
355
|
-
n = circuit.num_lines
|
356
|
-
depth = circuit.depth
|
357
|
-
|
358
|
-
# Set up the CHP qubit labels: could be different CHP labels for each circuit.
|
359
|
-
aschpq = {label: str(i) for i, label in enumerate(circuit.line_labels)}
|
360
|
-
|
361
|
-
# A list containing the CHP string for each error-free circuit layer.
|
362
|
-
perfect_chpstrings = [''.join([gate_to_chp(gate, aschpq) for gate in circuit.layer(i)])
|
363
|
-
for i in range(depth)]
|
364
|
-
|
365
|
-
# Find the probability of error in each circuit layer.
|
366
|
-
errorprobs = [errormodel.layer_uniform_pauli_probability(circuit.layer(lind), circuit.line_labels)
|
367
|
-
for lind in range(circuit.depth)]
|
368
|
-
# Add measurement error at the end
|
369
|
-
errorprobs.append(errormodel.readout_uniform_pauli_probability(circuit.line_labels))
|
370
|
-
|
371
|
-
time2 = _time.time()
|
372
|
-
|
373
|
-
for sample in range(shots):
|
374
|
-
|
375
|
-
# Sample errors for the circuit. Note that if 1 then a uniformly random Pauli is sampled, so
|
376
|
-
# there is a 1/4 chance of no error even if this is 1. This is correct.
|
377
|
-
#print(errorprobs)
|
378
|
-
haserror = [_np.random.binomial(1, ep) for ep in errorprobs]
|
379
|
-
#for lind in range(depth):
|
380
|
-
# print('-', lind)
|
381
|
-
# print(haserror[lind])
|
382
|
-
# print([random_pauli_in_chp(q) for q in range(n) if haserror[lind][q] == 1])
|
383
|
-
# Construct the CHP string for each error layer.
|
384
|
-
error_chpstrings = [''.join([''] + [random_pauli_in_chp(q) for q in range(n) if haserror[lind][q] == 1])
|
385
|
-
for lind in range(depth)]
|
386
|
-
|
387
|
-
# Interleave the perfect and error CHP strings and then join.
|
388
|
-
chpstring = '#\n' + ''.join([val for pair in zip(perfect_chpstrings, error_chpstrings) for val in pair])
|
389
|
-
|
390
|
-
# Add the readout error
|
391
|
-
chpstring += ''.join([''] + [random_pauli_in_chp(q) for q in range(n) if haserror[depth][q] == 1])
|
392
|
-
|
393
|
-
# Add a measurement on all the qubits.
|
394
|
-
chpstring += '\n'.join(['m ' + aschpq[q] for q in circuit.line_labels]) + '\n'
|
395
|
-
#print(chpstring)
|
396
|
-
with open(outdir + "/circuit-{}-instance-{}.chp".format(cind, sample), 'w') as f:
|
397
|
-
f.write(chpstring)
|
398
|
-
|
399
|
-
# Run CHP on this file.
|
400
|
-
_os.system("./chp " + outdir + "/circuit-{}-instance-{}.chp > ".format(cind, sample)
|
401
|
-
+ outdir + "/circuit-{}-instance-{}-out.txt".format(cind, sample))
|
402
|
-
|
403
|
-
countdict = {}
|
404
|
-
for sample in range(shots):
|
405
|
-
|
406
|
-
with open(outdir + "/circuit-{}-instance-{}-out.txt".format(cind, sample), 'r') as f:
|
407
|
-
#print(cind,sample)
|
408
|
-
outasdict = {}
|
409
|
-
for i, line in enumerate(f):
|
410
|
-
if i > 3:
|
411
|
-
line = line.strip(' \n')
|
412
|
-
line = line.split(' ')
|
413
|
-
# todo : this assumes definite outcome circuits, so fix that
|
414
|
-
# by instead counting forward from the start of the line.
|
415
|
-
outasdict[circuit.line_labels[int(line[-2][:-1])]] = line[-1]
|
416
|
-
|
417
|
-
#print(outasdict)
|
418
|
-
bitstring = ''.join([outasdict[q] for q in circuit.line_labels])
|
419
|
-
|
420
|
-
if perge_chp_files:
|
421
|
-
_os.system("rm " + outdir + "/circuit-{}-instance-{}.chp".format(cind, sample))
|
422
|
-
_os.system("rm " + outdir + "/circuit-{}-instance-{}-out.txt".format(cind, sample))
|
423
|
-
|
424
|
-
try:
|
425
|
-
countdict[bitstring] += 1
|
426
|
-
except:
|
427
|
-
countdict[bitstring] = 1
|
428
|
-
|
429
|
-
if aux_info_list is not None:
|
430
|
-
aux = aux_info_list[cind]
|
431
|
-
else:
|
432
|
-
aux = None
|
433
|
-
|
434
|
-
if returnds:
|
435
|
-
ds.add_count_dict(circuit, countdict, record_zero_counts=False, aux=aux)
|
436
|
-
else:
|
437
|
-
ds.append(countdict)
|
438
|
-
|
439
|
-
time3 = _time.time()
|
440
|
-
|
441
|
-
if verbosity > 1:
|
442
|
-
print("({0:.2f}, {1:.2f})".format(time2 - time1, time3 - time2), end=', ')
|
443
|
-
print("Total time: {0:.2f})".format(time3 - time0))
|
444
|
-
|
445
|
-
if perge_dir:
|
446
|
-
_os.system("rmdir " + outdir)
|
447
|
-
|
448
|
-
return ds
|
449
|
-
|
450
|
-
|
451
|
-
def circuit_simulator_for_tensored_independent_pauli_errors(circuit, pspec, errormodel, counts,
|
452
|
-
alloutcomes=False, idle1q_placeholder='I'):
|
453
|
-
"""
|
454
|
-
A Clifford circuit simulator for an error model whereby each gate in the circuit induces independent Pauli
|
455
|
-
errors on some or all of the qubits, with user-specified error probabilities that can vary between gate
|
456
|
-
and between Pauli. State preparation and measurements errors are restricted to bit-flip errors on the output.
|
457
|
-
|
458
|
-
This simulator is a stochastic-unravelling simulator that uses an efficient-in-qubit-number representation
|
459
|
-
of the action of Clifford gates on Paulis. Specifically, it samples Pauli errors according to the error
|
460
|
-
statistics provided, and propogates them through the layers of Clifford gates in the circuit using the
|
461
|
-
conjugation action of the Cliffords on Paulis (as represented by 2n X 2n symplectic matrices for n qubits).
|
462
|
-
This is repeated for the number of counts (`counts`) requested. So, this function takes a time to run that
|
463
|
-
scales as (counts * n^2 * circuit depth). Therefore, this method will be slower than the pyGSTi density-matrix
|
464
|
-
simulators at low qubit number and high `counts`.
|
465
|
-
|
466
|
-
Parameters
|
467
|
-
----------
|
468
|
-
circuit : Circuit
|
469
|
-
The circuit to simulate. It should only contain gates that are also contained within the provided
|
470
|
-
QubitProcessorSpec `pspec` and are Clifford gates.
|
471
|
-
|
472
|
-
pspec : QubitProcessorSpec
|
473
|
-
The QubitProcessorSpec that defines the device. The Clifford model in QubitProcessorSpec should contain all of
|
474
|
-
the gates that are in the circuit.
|
475
|
-
|
476
|
-
errormodel : dict
|
477
|
-
A dictionary defining the error model. This errormodel should have keys that are Label objects (the
|
478
|
-
elements of the circuit). The values for a particular Label is an (n,4) numpy array of floats, that
|
479
|
-
encodes the errors caused by the gate specified by that Label. The (i,j) value in the array is the
|
480
|
-
probability that this gate is followed by Pauli i where Pauli 0 = identity, Pauli 1 = X, Pauli 2 = Y
|
481
|
-
and Pauli 3 = Z. So, if the arrray is [1.,0.,0.,0.] in every row then there is no errors, if it is
|
482
|
-
[1-p,p/3,p/3,p/3] in row j then there is equal probability of each Pauli error on qubit j with an
|
483
|
-
error probability of p.
|
484
|
-
|
485
|
-
Some simple error models can be auto-constructed using `create_locally_gate_independent_pauli_error_model()`
|
486
|
-
or create_iid_pauli_error_model()`.
|
487
|
-
|
488
|
-
counts : The number of counts, i.e., the number of repeats of the circuit that data should be generated for.
|
489
|
-
|
490
|
-
alloutcomes : bool, optional
|
491
|
-
If True then a dictionary is returned where the keys are all possible outcomes (i.e., all length n
|
492
|
-
bit strings) and the values are the counts for all of the outcomes. If False, then the returned
|
493
|
-
dictionary only contains keys for those outcomes that happen at least once.
|
494
|
-
|
495
|
-
TODO: docstring: idle1q_placeholder
|
496
|
-
|
497
|
-
Returns
|
498
|
-
-------
|
499
|
-
dict
|
500
|
-
A dictionary of simulated measurement outcome counts.
|
501
|
-
"""
|
502
|
-
n = circuit.number_of_lines
|
503
|
-
|
504
|
-
if set(circuit.line_labels) != set(pspec.qubit_labels):
|
505
|
-
assert(set(circuit.line_labels).issubset(set(pspec.qubit_labels)))
|
506
|
-
reduced_errormodel = errormodel.copy()
|
507
|
-
mask = _np.zeros(pspec.num_qubits, bool)
|
508
|
-
for i in range(pspec.num_qubits):
|
509
|
-
if pspec.qubit_labels[i] in circuit.line_labels:
|
510
|
-
mask[i] = True
|
511
|
-
for key in list(reduced_errormodel.keys()):
|
512
|
-
errormatrix = reduced_errormodel[key]
|
513
|
-
assert(_np.shape(errormatrix)[0] == pspec.num_qubits), "Format of `errormodel` incorrect!"
|
514
|
-
if len(_np.shape(errormatrix)) == 2:
|
515
|
-
reduced_errormodel[key] = errormatrix[mask, :]
|
516
|
-
elif len(_np.shape(errormatrix)) == 1:
|
517
|
-
reduced_errormodel[key] = errormatrix[mask]
|
518
|
-
else: raise ValueError("Format of `errormodel` incorrect!")
|
519
|
-
else:
|
520
|
-
reduced_errormodel = errormodel
|
521
|
-
|
522
|
-
results = {}
|
523
|
-
|
524
|
-
if alloutcomes:
|
525
|
-
for i in range(2**n):
|
526
|
-
result = tuple(_symp.int_to_bitstring(i, n))
|
527
|
-
results[result] = 0
|
528
|
-
|
529
|
-
for i in range(0, counts):
|
530
|
-
result = oneshot_circuit_simulator_for_tensored_independent_pauli_errors(
|
531
|
-
circuit, pspec, reduced_errormodel, idle1q_placeholder)
|
532
|
-
try: results[result] += 1
|
533
|
-
except: results[result] = 1
|
534
|
-
|
535
|
-
return results
|
536
|
-
|
537
|
-
|
538
|
-
def oneshot_circuit_simulator_for_tensored_independent_pauli_errors(circuit, pspec, errormodel, idle1q_placeholder='I'):
|
539
|
-
"""
|
540
|
-
Generates a single measurement result for the `circuit_simulator_for_tensored_independent_pauli_errors()`
|
541
|
-
simulator
|
542
|
-
|
543
|
-
Parameters
|
544
|
-
----------
|
545
|
-
circuit : Circuit
|
546
|
-
The circuit to simulate. It should only contain gates that are also contained within the provided
|
547
|
-
QubitProcessorSpec `pspec` and are Clifford gates.
|
548
|
-
|
549
|
-
pspec : QubitProcessorSpec
|
550
|
-
The QubitProcessorSpec that defines the device. The Clifford model in QubitProcessorSpec should contain all of
|
551
|
-
the gates that are in the circuit.
|
552
|
-
|
553
|
-
errormodel : dict
|
554
|
-
A dictionary defining the error model. This errormodel should have keys that are Label objects (the
|
555
|
-
elements of the circuit). The values for a particular Label is an (n,4) numpy array of floats, that
|
556
|
-
encodes the errors caused by the gate specified by that Label. The (i,j) value in the array is the
|
557
|
-
probability that this gate is followed by Pauli i where Pauli 0 = identity, Pauli 1 = X, Pauli 2 = Y
|
558
|
-
and Pauli 3 = Z. So, if the arrray is [1.,0.,0.,0.] in every row then there is no errors, if it is
|
559
|
-
[1-p,p/3,p/3,p/3] in row j then there is equal probability of each Pauli error on qubit j with an
|
560
|
-
error probability of p.
|
561
|
-
|
562
|
-
TODO: docstring: idle1q_placeholder
|
563
|
-
|
564
|
-
Returns
|
565
|
-
-------
|
566
|
-
tuple
|
567
|
-
A tuple of values that are 0 or 1, corresponding to the results of a z-measurement on all the qubits.
|
568
|
-
The ordering of this tuple corresponds to the ordering of the wires in the circuit.
|
569
|
-
"""
|
570
|
-
n = circuit.number_of_lines
|
571
|
-
depth = circuit.depth
|
572
|
-
sout, pout = _symp.prep_stabilizer_state(n, zvals=None)
|
573
|
-
srep = pspec.models['clifford'].compute_clifford_symplectic_reps()
|
574
|
-
I = _np.identity(2 * n, int)
|
575
|
-
|
576
|
-
for l in range(depth):
|
577
|
-
|
578
|
-
layer = circuit.layer_with_idles(l, idle_gate_name=idle1q_placeholder)
|
579
|
-
s, p = _symp.symplectic_rep_of_clifford_layer(layer, n, q_labels=circuit.line_labels, srep_dict=srep)
|
580
|
-
# Apply the perfect layer to the current state.
|
581
|
-
sout, pout = _symp.apply_clifford_to_stabilizer_state(s, p, sout, pout)
|
582
|
-
|
583
|
-
# Consider each gate in the layer, and apply Pauli errors with the relevant probs.
|
584
|
-
for gate in layer:
|
585
|
-
# Sample a pauli vector for the gate
|
586
|
-
gerror_p = _np.zeros(2 * n, int)
|
587
|
-
sampledvec = _np.array([list(_np.random.multinomial(1, pp)) for pp in errormodel[gate]])
|
588
|
-
# Z and Y both map X - > -X under conjugation, which is encoded with the upper half of
|
589
|
-
# the p vector being set to 2.
|
590
|
-
gerror_p[:n] = 2 * (sampledvec[:, 3] ^ sampledvec[:, 2])
|
591
|
-
# X and Y both map Z - > -Z under conjugation, which is encoded with the lower half of
|
592
|
-
# the p vector being set to 2.
|
593
|
-
gerror_p[n:] = 2 * (sampledvec[:, 1] ^ sampledvec[:, 2])
|
594
|
-
|
595
|
-
sout, pout = _symp.apply_clifford_to_stabilizer_state(I, gerror_p, sout, pout)
|
596
|
-
|
597
|
-
output = []
|
598
|
-
for q in range(n):
|
599
|
-
measurement_out = _symp.pauli_z_measurement(sout, pout, q)
|
600
|
-
# The probability of the '1' outcome
|
601
|
-
oneprob = measurement_out[1]
|
602
|
-
# Sample a bit with that probability to be 1.
|
603
|
-
bit = _np.random.binomial(1, oneprob)
|
604
|
-
output.append(bit)
|
605
|
-
|
606
|
-
# Add measurement errors, by bit-flipping with some probability
|
607
|
-
try:
|
608
|
-
measurement_errors = errormodel['measure']
|
609
|
-
except:
|
610
|
-
measurement_errors = [0 for i in range(n)]
|
611
|
-
|
612
|
-
add_to_outcome = _np.array([_np.random.binomial(1, p) for p in measurement_errors])
|
613
|
-
output = tuple(_np.array(output) ^ add_to_outcome)
|
614
|
-
outputasstring = ''
|
615
|
-
for s in output: outputasstring += str(s)
|
616
|
-
return outputasstring
|
617
|
-
|
618
|
-
|
619
|
-
def rb_with_pauli_errors(pspec, errormodel, lengths, k, counts, qubit_subset=None, filename=None, rbtype='DRB',
|
620
|
-
rbspec=None, returndata=True, appenddata=False, verbosity=0, idle1q_placeholder='I'):
|
621
|
-
"""
|
622
|
-
Simulates RB with Pauli errors. Can be used to simulated Clifford RB, direct RB and mirror RB. This
|
623
|
-
function:
|
624
|
-
|
625
|
-
1) Samples RB circuits
|
626
|
-
2) Simulates the RB circuit with the specified Pauli-errors error model
|
627
|
-
3) Records the summary RB data to file and/or returns this RB data.
|
628
|
-
|
629
|
-
Step 1 is implemented using the in-built RB samplers. For more information see rb.sample. Step 2
|
630
|
-
is implemented using the `circuit_simulator_for_tensored_independent_pauli_errors()` stochastic
|
631
|
-
errors circuit simulator. See that function for more details.
|
632
|
-
|
633
|
-
Parameters
|
634
|
-
----------
|
635
|
-
pspec : QubitProcessorSpec
|
636
|
-
The QubitProcessorSpec that defines the device.
|
637
|
-
|
638
|
-
errormodel : dict
|
639
|
-
A dictionary defining the error model. This errormodel should have keys that are Label objects
|
640
|
-
corresponding to the gates in `pspec`. The values for a particular Label is an (n,4) numpy array of
|
641
|
-
floats, that encodes the errors caused by the gate specified by that Label. The (i,j) value in the
|
642
|
-
array is the probability that this gate is followed by Pauli i where Pauli 0 = identity, Pauli 1 = X,
|
643
|
-
Pauli 2 = Y and Pauli 3 = Z. So, if the arrray is [1.,0.,0.,0.] in every row then there is no errors,
|
644
|
-
if it is [1-p,p/3,p/3,p/3] in row j then there is equal probability of each Pauli error on qubit j with an
|
645
|
-
error probability of p.
|
646
|
-
|
647
|
-
Some simple error models can be auto-constructed using `create_locally_gate_independent_pauli_error_model()`
|
648
|
-
or create_iid_pauli_error_model()`.
|
649
|
-
|
650
|
-
lengths : list
|
651
|
-
A list of the RB lengths to sample and simulate circuits at. E.g., for Clifford RB this is the number
|
652
|
-
of Cliffords in the uncompiled circuit - 2 (see `rb.sample.clifford_rb_circuit()`).
|
653
|
-
|
654
|
-
k : int
|
655
|
-
The number of circuits to sample and simulate at each RB length.
|
656
|
-
|
657
|
-
counts : int
|
658
|
-
The number of counts for each circuit.
|
659
|
-
|
660
|
-
qubit_subset : list
|
661
|
-
If not None, a list of qubit labels that the RB experiment should be over, that is a subset of the
|
662
|
-
qubits in `pspec`.
|
663
|
-
|
664
|
-
filename : str, optional
|
665
|
-
A filename for where to save the data (if None, the data is not saved to file).
|
666
|
-
|
667
|
-
rbtype : {'DRB', 'CRB', 'MRB'}
|
668
|
-
The RB type to simulate. 'DRB' corresponds to direct RB, 'CRB' corresponds to Clifford RB,
|
669
|
-
and 'MRB' corresponds to mirror RB.
|
670
|
-
|
671
|
-
rbspec : list, optional
|
672
|
-
Handed to the RB sampling function for all arguments after `pspec` and the RB lengths, which are the first
|
673
|
-
two arguments handed to the relevant function. See the relevant RB circuit sampling functions for details.
|
674
|
-
|
675
|
-
returndata : bool, optional
|
676
|
-
Whether to return the data
|
677
|
-
|
678
|
-
appenddata : bool, optional
|
679
|
-
If writing to file (i.e., `filename` is not None), whether to append the data to an already existing file
|
680
|
-
or to write over any existing file.
|
681
|
-
|
682
|
-
verbosity : int, optional
|
683
|
-
The amount of print-to-screen.
|
684
|
-
|
685
|
-
Returns
|
686
|
-
-------
|
687
|
-
None or RBSummaryDataset
|
688
|
-
If `returndata` an RBSummaryDataset containing the results. Else, None
|
689
|
-
|
690
|
-
"""
|
691
|
-
if rbspec is None:
|
692
|
-
rbspec = []
|
693
|
-
assert(rbtype == 'CRB' or rbtype == 'DRB' or rbtype == 'MRB'), "RB type not valid!"
|
694
|
-
|
695
|
-
if filename is not None:
|
696
|
-
if not appenddata:
|
697
|
-
with open(filename, 'w') as f:
|
698
|
-
f.write('# Results from a {} simulation\n'.format(rbtype))
|
699
|
-
f.write('# Number of qubits\n')
|
700
|
-
if qubit_subset is None: f.write(str(pspec.num_qubits))
|
701
|
-
else: f.write(str(len(qubit_subset)))
|
702
|
-
f.write('\n# RB length // Success counts // Total counts '
|
703
|
-
'// Circuit depth // Circuit two-qubit gate count\n')
|
704
|
-
|
705
|
-
n = pspec.num_qubits
|
706
|
-
lengthslist = []
|
707
|
-
scounts = []
|
708
|
-
cdepths = []
|
709
|
-
c2Qgcounts = []
|
710
|
-
|
711
|
-
for i in range(k):
|
712
|
-
|
713
|
-
if verbosity > 0:
|
714
|
-
print("- Sampling and simulating circuit {} of {} at each of {} lengths".format(i + 1, k, len(lengths)))
|
715
|
-
print(" - Number of circuits complete = ", end='')
|
716
|
-
|
717
|
-
for lind, l in enumerate(lengths):
|
718
|
-
|
719
|
-
lengthslist.append(l)
|
720
|
-
|
721
|
-
if rbtype == 'DRB':
|
722
|
-
c, idealout = _samp.direct_rb_circuit(pspec, l, qubit_subset, *rbspec)
|
723
|
-
elif rbtype == 'CRB':
|
724
|
-
c, idealout = _samp.clifford_rb_circuit(pspec, l, qubit_subset, *rbspec)
|
725
|
-
elif rbtype == 'MRB':
|
726
|
-
c, idealout = _samp.mirror_rb_circuit(pspec, l, qubit_subset, *rbspec)
|
727
|
-
|
728
|
-
#if verbosity > 0:
|
729
|
-
# print(" complete")
|
730
|
-
# print(" - Simulating circuit...",end='')
|
731
|
-
|
732
|
-
outcome = circuit_simulator_for_tensored_independent_pauli_errors(
|
733
|
-
c, pspec, errormodel, counts, alloutcomes=False, idle1q_placeholder=idle1q_placeholder)
|
734
|
-
#EGN: Hardcoded 'I' here. Could make this into an arg, but there's really
|
735
|
-
# no need for the user to modify this unless they use 'I' as a gate label.
|
736
|
-
if verbosity > 0: print(lind + 1, end=',')
|
737
|
-
|
738
|
-
# Add the number of success counts to the list
|
739
|
-
# scounts.append(outcome.get(idealout,0))
|
740
|
-
scounts.append(outcome.get(''.join(str(idealbit) for idealbit in idealout), 0))
|
741
|
-
cdepths.append(c.depth)
|
742
|
-
c2Qgcounts.append(c.two_q_gate_count())
|
743
|
-
|
744
|
-
# Write the data to file in each round.
|
745
|
-
if filename is not None:
|
746
|
-
with open(filename, 'a') as f:
|
747
|
-
f.write('{} {} {} {} {}\n'.format(l, scounts[-1], counts, cdepths[-1], c2Qgcounts[-1]))
|
748
|
-
|
749
|
-
if verbosity > 0: print('')
|
750
|
-
if returndata:
|
751
|
-
|
752
|
-
from . import results as _res
|
753
|
-
data = _res.RBSummaryDataset(n, lengthslist, success_counts=scounts, total_counts=counts,
|
754
|
-
circuit_depths=cdepths, circuit_twoQgate_counts=c2Qgcounts)
|
755
|
-
return data
|
756
|
-
|
757
|
-
|
758
|
-
def create_iid_pauli_error_model(pspec, one_qubit_gate_errorrate, two_qubit_gate_errorrate, idle_errorrate,
|
759
|
-
measurement_errorrate=0., ptype='uniform', idle1q_placeholder='I'):
|
760
|
-
"""
|
761
|
-
Returns a dictionary encoding a Pauli-stochastic error model whereby the errors are the same on all the
|
762
|
-
1-qubit gates, and the same on all 2-qubit gates. The probability of the 3 different Pauli errors on each
|
763
|
-
qubit is specified by `ptype` and can either be uniform, or always X, Y, or Z errors.
|
764
|
-
|
765
|
-
The dictionary returned is in the appropriate format for the
|
766
|
-
`circuit_simulator_for_tensored_independent_pauli_errors()` circuit simulator function.
|
767
|
-
|
768
|
-
Parameters
|
769
|
-
----------
|
770
|
-
pspec : QubitProcessorSpec
|
771
|
-
The QubitProcessorSpec that defines the device.
|
772
|
-
|
773
|
-
one_qubit_gate_errorrate : float
|
774
|
-
The 1-qubit gates error rate (the probability of a Pauli error on the target qubit) not including
|
775
|
-
idle gates.
|
776
|
-
|
777
|
-
two_qubit_gate_errorrate : float
|
778
|
-
The 2-qubit gates error rate (the total probability of a Pauli error on either qubit the gate acts
|
779
|
-
on -- each qubit has independent errors with equal probabilities).
|
780
|
-
|
781
|
-
idle_errorrate : float
|
782
|
-
The idle gates error rate.
|
783
|
-
|
784
|
-
measurement_errorrate : flip
|
785
|
-
The measurement error rate for all of the qubits. This is the probability that a qubits measurement
|
786
|
-
result is bit-flipped.
|
787
|
-
|
788
|
-
ptype : str, optional
|
789
|
-
Can be 'uniform', 'X', 'Y' or 'Z'. If 'uniform' then 3 Pauli errors are equally likely, if 'X', 'Y' or
|
790
|
-
'Z' then the errors are always Pauli X, Y or Z errors, respectively.
|
791
|
-
|
792
|
-
TODO: docstring idle1q_placeholder
|
793
|
-
|
794
|
-
Returns
|
795
|
-
-------
|
796
|
-
dict
|
797
|
-
An dict that encodes the error model described above in the format required for the simulator
|
798
|
-
`circuit_simulator_for_tensored_independent_pauli_errors()`.
|
799
|
-
|
800
|
-
"""
|
801
|
-
if ptype == 'uniform':
|
802
|
-
def error_row(er): return _np.array([1 - er, er / 3, er / 3, er / 3])
|
803
|
-
|
804
|
-
elif ptype == 'X':
|
805
|
-
def error_row(er): return _np.array([1 - er, er, 0., 0.])
|
806
|
-
|
807
|
-
elif ptype == 'Y':
|
808
|
-
def error_row(er): return _np.array([1 - er, 0., er, 0.])
|
809
|
-
|
810
|
-
elif ptype == 'Z':
|
811
|
-
def error_row(er): return _np.array([1 - er, 0., 0., er])
|
812
|
-
else:
|
813
|
-
raise ValueError("Error model type not understood! Set `ptype` to a valid option.")
|
814
|
-
|
815
|
-
perQ_twoQ_errorrate = 1 - (1 - two_qubit_gate_errorrate)**(1 / 2)
|
816
|
-
n = pspec.num_qubits
|
817
|
-
|
818
|
-
errormodel = {}
|
819
|
-
|
820
|
-
if idle1q_placeholder is not None:
|
821
|
-
#Added by EGN: special behavior needed when Model has
|
822
|
-
# an gate name used to designate a perfect 1-qubit idle op (used as placeholder).
|
823
|
-
# This translates to a set of "<gatename>:X" operation labels all w/idle_errorrate
|
824
|
-
idleLbl = idle1q_placeholder
|
825
|
-
for q in pspec.qubit_labels:
|
826
|
-
gl = _Lbl(idleLbl, q)
|
827
|
-
errormodel[gl] = _np.zeros((n, 4), float)
|
828
|
-
errormodel[gl][:, 0] = _np.ones(n, float)
|
829
|
-
errormodel[gl][pspec.qubit_labels.index(q), :] = error_row(idle_errorrate)
|
830
|
-
|
831
|
-
for gate in pspec.models['clifford'].primitive_op_labels:
|
832
|
-
errormodel[gate] = _np.zeros((n, 4), float)
|
833
|
-
errormodel[gate][:, 0] = _np.ones(n, float)
|
834
|
-
|
835
|
-
# If not a CNOT, it is a 1-qubit gate / idle.
|
836
|
-
if gate.num_qubits == 2:
|
837
|
-
q1 = gate.qubits[0]
|
838
|
-
q2 = gate.qubits[1]
|
839
|
-
er = perQ_twoQ_errorrate
|
840
|
-
errormodel[gate][pspec.qubit_labels.index(q1), :] = error_row(er)
|
841
|
-
errormodel[gate][pspec.qubit_labels.index(q2), :] = error_row(er)
|
842
|
-
|
843
|
-
elif gate.num_qubits == 1:
|
844
|
-
q = gate.qubits[0]
|
845
|
-
er = one_qubit_gate_errorrate
|
846
|
-
|
847
|
-
errormodel[gate][pspec.qubit_labels.index(q), :] = error_row(er)
|
848
|
-
|
849
|
-
else:
|
850
|
-
raise ValueError("The QubitProcessorSpec must only contain 1- and 2- qubit gates!")
|
851
|
-
|
852
|
-
errormodel['measure'] = _np.array([measurement_errorrate for q in range(n)])
|
853
|
-
|
854
|
-
return errormodel
|
855
|
-
|
856
|
-
|
857
|
-
def create_locally_gate_independent_pauli_error_model(pspec, gate_errorrate_dict, measurement_errorrate_dict=None,
|
858
|
-
ptype='uniform', idle1q_placeholder='I'):
|
859
|
-
"""
|
860
|
-
Returns a dictionary encoding a Pauli-stochastic error model whereby the errors are independent of the gates,
|
861
|
-
with a qubit subject to an error after a circuit layer with the probabilities specified by the dict
|
862
|
-
`gate_errorrate_dict`. The probability of the 3 different Pauli errors on each qubit is specified by
|
863
|
-
`ptype` and can either be uniform, or always X, Y, or Z errors.
|
864
|
-
|
865
|
-
The dictionary returned is in the appropriate format for the
|
866
|
-
`circuit_simulator_for_tensored_independent_pauli_errors()` circuit simulator function.
|
867
|
-
|
868
|
-
Parameters
|
869
|
-
----------
|
870
|
-
pspec : QubitProcessorSpec
|
871
|
-
The QubitProcessorSpec that defines the device.
|
872
|
-
|
873
|
-
gate_errorrate_dict : dict
|
874
|
-
A dict where the keys are elements of pspec.qubit_labels and the values are floats in [0,1].
|
875
|
-
The element for qubit with label `q` is the error probability for that qubit.
|
876
|
-
|
877
|
-
measurement_errorrate_dict : dict
|
878
|
-
A dict where the keys are elements of pspec.qubit_labels and the values are floats in [0,1].
|
879
|
-
The element for qubit with label `q` is the measurement bit-flip error probability for that qubit.
|
880
|
-
All qubits that do not have a measurement error rate specified are assumed to have perfect measurements.
|
881
|
-
|
882
|
-
ptype : str, optional
|
883
|
-
Can be 'uniform', 'X', 'Y' or 'Z'. If 'uniform' then 3 Pauli errors are equally likely, if 'X', 'Y' or
|
884
|
-
'Z' then the errors are always Pauli X, Y or Z errors, respectively.
|
885
|
-
|
886
|
-
TODO: docstring: idle1q_placeholder
|
887
|
-
|
888
|
-
Returns
|
889
|
-
-------
|
890
|
-
dict
|
891
|
-
An dict that encodes the error model described above in the format required for the simulator
|
892
|
-
`circuit_simulator_for_tensored_independent_pauli_errors()`.
|
893
|
-
|
894
|
-
"""
|
895
|
-
if measurement_errorrate_dict is None:
|
896
|
-
measurement_errorrate_dict = {}
|
897
|
-
if ptype == 'uniform':
|
898
|
-
def error_row(er): return _np.array([1 - er, er / 3, er / 3, er / 3])
|
899
|
-
|
900
|
-
elif ptype == 'X':
|
901
|
-
def error_row(er): return _np.array([1 - er, er, 0., 0.])
|
902
|
-
|
903
|
-
elif ptype == 'Y':
|
904
|
-
def error_row(er): return _np.array([1 - er, 0., er, 0.])
|
905
|
-
|
906
|
-
elif ptype == 'Z':
|
907
|
-
def error_row(er): return _np.array([1 - er, 0., 0., er])
|
908
|
-
else:
|
909
|
-
raise ValueError("Error model type not understood! Set `ptype` to a valid option.")
|
910
|
-
|
911
|
-
n = pspec.num_qubits
|
912
|
-
|
913
|
-
errormodel = {}
|
914
|
-
|
915
|
-
if idle1q_placeholder is not None:
|
916
|
-
#Added by EGN: special behavior needed when Model has
|
917
|
-
# an gate name used to designate a perfect 1-qubit idle op (used as placeholder).
|
918
|
-
# This translates to a set of "<gatename>:X" operation labels all w/appropriate errorrate
|
919
|
-
idleLbl = idle1q_placeholder
|
920
|
-
for q in pspec.qubit_labels:
|
921
|
-
gl = _Lbl(idleLbl, q)
|
922
|
-
er = gate_errorrate_dict[q]
|
923
|
-
errormodel[gl] = _np.zeros((n, 4), float)
|
924
|
-
errormodel[gl][:, 0] = _np.ones(n, float)
|
925
|
-
errormodel[gl][pspec.qubit_labels.index(q), :] = error_row(er)
|
926
|
-
|
927
|
-
for gate in pspec.models['clifford'].primitive_op_labels:
|
928
|
-
errormodel[gate] = _np.zeros((n, 4), float)
|
929
|
-
errormodel[gate][:, 0] = _np.ones(n, float)
|
930
|
-
|
931
|
-
for q in gate.qubits:
|
932
|
-
er = gate_errorrate_dict[q]
|
933
|
-
errormodel[gate][pspec.qubit_labels.index(q)] = error_row(er)
|
934
|
-
|
935
|
-
errormodel['measure'] = _np.array([measurement_errorrate_dict.get(q, 0.) for q in pspec.qubit_labels])
|
936
|
-
|
937
|
-
return errormodel
|
938
|
-
|
939
|
-
#
|
940
|
-
# TODO : DOES THIS NEED AND IDLE PLACEHOLDER?
|
941
|
-
#
|
942
|
-
|
943
|
-
|
944
|
-
def create_local_pauli_error_model(pspec, one_qubit_gate_errorrate_dict, two_qubit_gate_errorrate_dict,
|
945
|
-
measurement_errorrate_dict=None, ptype='uniform'):
|
946
|
-
"""
|
947
|
-
Returns a dictionary encoding a Pauli-stochastic error model whereby the errors caused by a gate act
|
948
|
-
only on the "target" qubits of the gate, all the 1-qubit gates on a qubit have the same error rate,
|
949
|
-
and all the 2-qubit gates on a qubit have the same error rate. The probability of the 3 different Pauli
|
950
|
-
errors on each qubit is specified by `ptype` and can either be uniform, or always X, Y, or Z errors.
|
951
|
-
|
952
|
-
The dictionary returned is in the appropriate format for the
|
953
|
-
`circuit_simulator_for_tensored_independent_pauli_errors()` circuit simulator function.
|
954
|
-
|
955
|
-
Parameters
|
956
|
-
----------
|
957
|
-
pspec : QubitProcessorSpec
|
958
|
-
The QubitProcessorSpec that defines the device.
|
959
|
-
|
960
|
-
one_qubit_gate_errorrate_dict : dict
|
961
|
-
A dict where the keys are elements of pspec.qubit_labels and the values are floats in [0,1].
|
962
|
-
The element for qubit with label `q` is the error probability for all 1-qubit gates on that qubit
|
963
|
-
|
964
|
-
two_qubit_gate_errorrate_dict : dict
|
965
|
-
A dict where the keys are 2-qubit gates in pspec and the values are floats in [0,1]. This is the
|
966
|
-
error probability for the 2-qubit gate, split evenly into independent Pauli errors on each of the
|
967
|
-
qubits the gate is intended to act on.
|
968
|
-
|
969
|
-
measurement_errorrate_dict : dict
|
970
|
-
A dict where the keys are elements of pspec.qubit_labels and the values are floats in [0,1].
|
971
|
-
The element for qubit with label `q` is the measurement bit-flip error probability for that qubit.
|
972
|
-
All qubits that do not have a measurement error rate specified are assumed to have perfect measurements.
|
973
|
-
|
974
|
-
|
975
|
-
ptype : str, optional
|
976
|
-
Can be 'uniform', 'X', 'Y' or 'Z'. If 'uniform' then 3 Pauli errors are equally likely, if 'X', 'Y' or
|
977
|
-
'Z' then the errors are always Pauli X, Y or Z errors, respectively.
|
978
|
-
|
979
|
-
Returns
|
980
|
-
-------
|
981
|
-
dict
|
982
|
-
An dict that encodes the error model described above in the format required for the simulator
|
983
|
-
`circuit_simulator_for_tensored_independent_pauli_errors()`.
|
984
|
-
|
985
|
-
"""
|
986
|
-
if measurement_errorrate_dict is None:
|
987
|
-
measurement_errorrate_dict = {}
|
988
|
-
if ptype == 'uniform':
|
989
|
-
def error_row(er): return _np.array([1 - er, er / 3, er / 3, er / 3])
|
990
|
-
|
991
|
-
elif ptype == 'X':
|
992
|
-
def error_row(er): return _np.array([1 - er, er, 0., 0.])
|
993
|
-
|
994
|
-
elif ptype == 'Y':
|
995
|
-
def error_row(er): return _np.array([1 - er, 0., er, 0.])
|
996
|
-
|
997
|
-
elif ptype == 'Z':
|
998
|
-
def error_row(er): return _np.array([1 - er, 0., 0., er])
|
999
|
-
else:
|
1000
|
-
raise ValueError("Error model type not understood! Set `ptype` to a valid option.")
|
1001
|
-
|
1002
|
-
n = pspec.num_qubits
|
1003
|
-
|
1004
|
-
errormodel = {}
|
1005
|
-
for gate in list(pspec.models['clifford'].primitive_op_labels):
|
1006
|
-
errormodel[gate] = _np.zeros((n, 4), float)
|
1007
|
-
errormodel[gate][:, 0] = _np.ones(n, float)
|
1008
|
-
|
1009
|
-
if gate.num_qubits == 1:
|
1010
|
-
er = one_qubit_gate_errorrate_dict[gate.qubits[0]]
|
1011
|
-
elif gate.num_qubits == 2:
|
1012
|
-
er = 1 - (1 - two_qubit_gate_errorrate_dict[gate])**(0.5)
|
1013
|
-
else: raise ValueError("Only 1- and 2-qubit gates supported!")
|
1014
|
-
|
1015
|
-
for q in gate.qubits:
|
1016
|
-
errormodel[gate][pspec.qubit_labels.index(q)] = error_row(er)
|
1017
|
-
|
1018
|
-
errormodel['measure'] = _np.array([measurement_errorrate_dict.get(q, 0.) for q in pspec.qubit_labels])
|
1019
|
-
|
1020
|
-
return errormodel
|