pyGSTi 0.9.12.1__cp39-cp39-win_amd64.whl → 0.9.13__cp39-cp39-win_amd64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (221) hide show
  1. pyGSTi-0.9.13.dist-info/METADATA +197 -0
  2. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/RECORD +207 -217
  3. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/WHEEL +1 -1
  4. pygsti/_version.py +2 -2
  5. pygsti/algorithms/contract.py +1 -1
  6. pygsti/algorithms/core.py +42 -28
  7. pygsti/algorithms/fiducialselection.py +17 -8
  8. pygsti/algorithms/gaugeopt.py +2 -2
  9. pygsti/algorithms/germselection.py +87 -77
  10. pygsti/algorithms/mirroring.py +0 -388
  11. pygsti/algorithms/randomcircuit.py +165 -1333
  12. pygsti/algorithms/rbfit.py +0 -234
  13. pygsti/baseobjs/basis.py +94 -396
  14. pygsti/baseobjs/errorgenbasis.py +0 -132
  15. pygsti/baseobjs/errorgenspace.py +0 -10
  16. pygsti/baseobjs/label.py +52 -168
  17. pygsti/baseobjs/opcalc/fastopcalc.cp39-win_amd64.pyd +0 -0
  18. pygsti/baseobjs/opcalc/fastopcalc.pyx +2 -2
  19. pygsti/baseobjs/polynomial.py +13 -595
  20. pygsti/baseobjs/statespace.py +1 -0
  21. pygsti/circuits/__init__.py +1 -1
  22. pygsti/circuits/circuit.py +682 -505
  23. pygsti/circuits/circuitconstruction.py +0 -4
  24. pygsti/circuits/circuitlist.py +47 -5
  25. pygsti/circuits/circuitparser/__init__.py +8 -8
  26. pygsti/circuits/circuitparser/fastcircuitparser.cp39-win_amd64.pyd +0 -0
  27. pygsti/circuits/circuitstructure.py +3 -3
  28. pygsti/circuits/cloudcircuitconstruction.py +1 -1
  29. pygsti/data/datacomparator.py +2 -7
  30. pygsti/data/dataset.py +46 -44
  31. pygsti/data/hypothesistest.py +0 -7
  32. pygsti/drivers/bootstrap.py +0 -49
  33. pygsti/drivers/longsequence.py +2 -1
  34. pygsti/evotypes/basereps_cython.cp39-win_amd64.pyd +0 -0
  35. pygsti/evotypes/chp/opreps.py +0 -61
  36. pygsti/evotypes/chp/statereps.py +0 -32
  37. pygsti/evotypes/densitymx/effectcreps.cpp +9 -10
  38. pygsti/evotypes/densitymx/effectreps.cp39-win_amd64.pyd +0 -0
  39. pygsti/evotypes/densitymx/effectreps.pyx +1 -1
  40. pygsti/evotypes/densitymx/opreps.cp39-win_amd64.pyd +0 -0
  41. pygsti/evotypes/densitymx/opreps.pyx +2 -2
  42. pygsti/evotypes/densitymx/statereps.cp39-win_amd64.pyd +0 -0
  43. pygsti/evotypes/densitymx/statereps.pyx +1 -1
  44. pygsti/evotypes/densitymx_slow/effectreps.py +7 -23
  45. pygsti/evotypes/densitymx_slow/opreps.py +16 -23
  46. pygsti/evotypes/densitymx_slow/statereps.py +10 -3
  47. pygsti/evotypes/evotype.py +39 -2
  48. pygsti/evotypes/stabilizer/effectreps.cp39-win_amd64.pyd +0 -0
  49. pygsti/evotypes/stabilizer/effectreps.pyx +0 -4
  50. pygsti/evotypes/stabilizer/opreps.cp39-win_amd64.pyd +0 -0
  51. pygsti/evotypes/stabilizer/opreps.pyx +0 -4
  52. pygsti/evotypes/stabilizer/statereps.cp39-win_amd64.pyd +0 -0
  53. pygsti/evotypes/stabilizer/statereps.pyx +1 -5
  54. pygsti/evotypes/stabilizer/termreps.cp39-win_amd64.pyd +0 -0
  55. pygsti/evotypes/stabilizer/termreps.pyx +0 -7
  56. pygsti/evotypes/stabilizer_slow/effectreps.py +0 -22
  57. pygsti/evotypes/stabilizer_slow/opreps.py +0 -4
  58. pygsti/evotypes/stabilizer_slow/statereps.py +0 -4
  59. pygsti/evotypes/statevec/effectreps.cp39-win_amd64.pyd +0 -0
  60. pygsti/evotypes/statevec/effectreps.pyx +1 -1
  61. pygsti/evotypes/statevec/opreps.cp39-win_amd64.pyd +0 -0
  62. pygsti/evotypes/statevec/opreps.pyx +2 -2
  63. pygsti/evotypes/statevec/statereps.cp39-win_amd64.pyd +0 -0
  64. pygsti/evotypes/statevec/statereps.pyx +1 -1
  65. pygsti/evotypes/statevec/termreps.cp39-win_amd64.pyd +0 -0
  66. pygsti/evotypes/statevec/termreps.pyx +0 -7
  67. pygsti/evotypes/statevec_slow/effectreps.py +0 -3
  68. pygsti/evotypes/statevec_slow/opreps.py +0 -5
  69. pygsti/extras/__init__.py +0 -1
  70. pygsti/extras/drift/stabilityanalyzer.py +3 -1
  71. pygsti/extras/interpygate/__init__.py +12 -0
  72. pygsti/extras/interpygate/core.py +0 -36
  73. pygsti/extras/interpygate/process_tomography.py +44 -10
  74. pygsti/extras/rpe/rpeconstruction.py +0 -2
  75. pygsti/forwardsims/__init__.py +1 -0
  76. pygsti/forwardsims/forwardsim.py +14 -55
  77. pygsti/forwardsims/mapforwardsim.py +69 -18
  78. pygsti/forwardsims/mapforwardsim_calc_densitymx.cp39-win_amd64.pyd +0 -0
  79. pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx +65 -66
  80. pygsti/forwardsims/mapforwardsim_calc_generic.py +91 -13
  81. pygsti/forwardsims/matrixforwardsim.py +63 -15
  82. pygsti/forwardsims/termforwardsim.py +8 -110
  83. pygsti/forwardsims/termforwardsim_calc_stabilizer.cp39-win_amd64.pyd +0 -0
  84. pygsti/forwardsims/termforwardsim_calc_statevec.cp39-win_amd64.pyd +0 -0
  85. pygsti/forwardsims/termforwardsim_calc_statevec.pyx +0 -651
  86. pygsti/forwardsims/torchfwdsim.py +265 -0
  87. pygsti/forwardsims/weakforwardsim.py +2 -2
  88. pygsti/io/__init__.py +1 -2
  89. pygsti/io/mongodb.py +0 -2
  90. pygsti/io/stdinput.py +6 -22
  91. pygsti/layouts/copalayout.py +10 -12
  92. pygsti/layouts/distlayout.py +0 -40
  93. pygsti/layouts/maplayout.py +103 -25
  94. pygsti/layouts/matrixlayout.py +99 -60
  95. pygsti/layouts/prefixtable.py +1534 -52
  96. pygsti/layouts/termlayout.py +1 -1
  97. pygsti/modelmembers/instruments/instrument.py +3 -3
  98. pygsti/modelmembers/instruments/tpinstrument.py +2 -2
  99. pygsti/modelmembers/modelmember.py +0 -17
  100. pygsti/modelmembers/operations/__init__.py +2 -4
  101. pygsti/modelmembers/operations/affineshiftop.py +1 -0
  102. pygsti/modelmembers/operations/composederrorgen.py +1 -1
  103. pygsti/modelmembers/operations/composedop.py +1 -24
  104. pygsti/modelmembers/operations/denseop.py +5 -5
  105. pygsti/modelmembers/operations/eigpdenseop.py +2 -2
  106. pygsti/modelmembers/operations/embeddederrorgen.py +1 -1
  107. pygsti/modelmembers/operations/embeddedop.py +0 -1
  108. pygsti/modelmembers/operations/experrorgenop.py +2 -2
  109. pygsti/modelmembers/operations/fullarbitraryop.py +1 -0
  110. pygsti/modelmembers/operations/fullcptpop.py +2 -2
  111. pygsti/modelmembers/operations/fulltpop.py +28 -6
  112. pygsti/modelmembers/operations/fullunitaryop.py +5 -4
  113. pygsti/modelmembers/operations/lindbladcoefficients.py +93 -78
  114. pygsti/modelmembers/operations/lindbladerrorgen.py +268 -441
  115. pygsti/modelmembers/operations/linearop.py +7 -27
  116. pygsti/modelmembers/operations/opfactory.py +1 -1
  117. pygsti/modelmembers/operations/repeatedop.py +1 -24
  118. pygsti/modelmembers/operations/staticstdop.py +1 -1
  119. pygsti/modelmembers/povms/__init__.py +3 -3
  120. pygsti/modelmembers/povms/basepovm.py +7 -36
  121. pygsti/modelmembers/povms/complementeffect.py +4 -9
  122. pygsti/modelmembers/povms/composedeffect.py +0 -320
  123. pygsti/modelmembers/povms/computationaleffect.py +1 -1
  124. pygsti/modelmembers/povms/computationalpovm.py +3 -1
  125. pygsti/modelmembers/povms/effect.py +3 -5
  126. pygsti/modelmembers/povms/marginalizedpovm.py +0 -79
  127. pygsti/modelmembers/povms/tppovm.py +74 -2
  128. pygsti/modelmembers/states/__init__.py +2 -5
  129. pygsti/modelmembers/states/composedstate.py +0 -317
  130. pygsti/modelmembers/states/computationalstate.py +3 -3
  131. pygsti/modelmembers/states/cptpstate.py +4 -4
  132. pygsti/modelmembers/states/densestate.py +6 -4
  133. pygsti/modelmembers/states/fullpurestate.py +0 -24
  134. pygsti/modelmembers/states/purestate.py +1 -1
  135. pygsti/modelmembers/states/state.py +5 -6
  136. pygsti/modelmembers/states/tpstate.py +28 -10
  137. pygsti/modelmembers/term.py +3 -6
  138. pygsti/modelmembers/torchable.py +50 -0
  139. pygsti/modelpacks/_modelpack.py +1 -1
  140. pygsti/modelpacks/smq1Q_ZN.py +3 -1
  141. pygsti/modelpacks/smq2Q_XXYYII.py +2 -1
  142. pygsti/modelpacks/smq2Q_XY.py +3 -3
  143. pygsti/modelpacks/smq2Q_XYI.py +2 -2
  144. pygsti/modelpacks/smq2Q_XYICNOT.py +3 -3
  145. pygsti/modelpacks/smq2Q_XYICPHASE.py +3 -3
  146. pygsti/modelpacks/smq2Q_XYXX.py +1 -1
  147. pygsti/modelpacks/smq2Q_XYZICNOT.py +3 -3
  148. pygsti/modelpacks/smq2Q_XYZZ.py +1 -1
  149. pygsti/modelpacks/stdtarget.py +0 -121
  150. pygsti/models/cloudnoisemodel.py +1 -2
  151. pygsti/models/explicitcalc.py +3 -3
  152. pygsti/models/explicitmodel.py +3 -13
  153. pygsti/models/fogistore.py +5 -3
  154. pygsti/models/localnoisemodel.py +1 -2
  155. pygsti/models/memberdict.py +0 -12
  156. pygsti/models/model.py +800 -65
  157. pygsti/models/modelconstruction.py +4 -4
  158. pygsti/models/modelnoise.py +2 -2
  159. pygsti/models/modelparaminterposer.py +1 -1
  160. pygsti/models/oplessmodel.py +1 -1
  161. pygsti/models/qutrit.py +15 -14
  162. pygsti/objectivefns/objectivefns.py +73 -138
  163. pygsti/objectivefns/wildcardbudget.py +2 -7
  164. pygsti/optimize/__init__.py +1 -0
  165. pygsti/optimize/arraysinterface.py +28 -0
  166. pygsti/optimize/customcg.py +0 -12
  167. pygsti/optimize/customlm.py +129 -323
  168. pygsti/optimize/customsolve.py +2 -2
  169. pygsti/optimize/optimize.py +0 -84
  170. pygsti/optimize/simplerlm.py +841 -0
  171. pygsti/optimize/wildcardopt.py +19 -598
  172. pygsti/protocols/confidenceregionfactory.py +28 -14
  173. pygsti/protocols/estimate.py +31 -14
  174. pygsti/protocols/gst.py +142 -68
  175. pygsti/protocols/modeltest.py +6 -10
  176. pygsti/protocols/protocol.py +9 -37
  177. pygsti/protocols/rb.py +450 -79
  178. pygsti/protocols/treenode.py +8 -2
  179. pygsti/protocols/vb.py +108 -206
  180. pygsti/protocols/vbdataframe.py +1 -1
  181. pygsti/report/factory.py +0 -15
  182. pygsti/report/fogidiagram.py +1 -17
  183. pygsti/report/modelfunction.py +12 -3
  184. pygsti/report/mpl_colormaps.py +1 -1
  185. pygsti/report/plothelpers.py +8 -2
  186. pygsti/report/reportables.py +41 -37
  187. pygsti/report/templates/offline/pygsti_dashboard.css +6 -0
  188. pygsti/report/templates/offline/pygsti_dashboard.js +12 -0
  189. pygsti/report/workspace.py +2 -14
  190. pygsti/report/workspaceplots.py +326 -504
  191. pygsti/tools/basistools.py +9 -36
  192. pygsti/tools/edesigntools.py +124 -96
  193. pygsti/tools/fastcalc.cp39-win_amd64.pyd +0 -0
  194. pygsti/tools/fastcalc.pyx +35 -81
  195. pygsti/tools/internalgates.py +151 -15
  196. pygsti/tools/jamiolkowski.py +5 -5
  197. pygsti/tools/lindbladtools.py +19 -11
  198. pygsti/tools/listtools.py +0 -114
  199. pygsti/tools/matrixmod2.py +1 -1
  200. pygsti/tools/matrixtools.py +173 -339
  201. pygsti/tools/nameddict.py +1 -1
  202. pygsti/tools/optools.py +154 -88
  203. pygsti/tools/pdftools.py +0 -25
  204. pygsti/tools/rbtheory.py +3 -320
  205. pygsti/tools/slicetools.py +64 -12
  206. pyGSTi-0.9.12.1.dist-info/METADATA +0 -155
  207. pygsti/algorithms/directx.py +0 -711
  208. pygsti/evotypes/qibo/__init__.py +0 -33
  209. pygsti/evotypes/qibo/effectreps.py +0 -78
  210. pygsti/evotypes/qibo/opreps.py +0 -376
  211. pygsti/evotypes/qibo/povmreps.py +0 -98
  212. pygsti/evotypes/qibo/statereps.py +0 -174
  213. pygsti/extras/rb/__init__.py +0 -13
  214. pygsti/extras/rb/benchmarker.py +0 -957
  215. pygsti/extras/rb/dataset.py +0 -378
  216. pygsti/extras/rb/io.py +0 -814
  217. pygsti/extras/rb/simulate.py +0 -1020
  218. pygsti/io/legacyio.py +0 -385
  219. pygsti/modelmembers/povms/denseeffect.py +0 -142
  220. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/LICENSE +0 -0
  221. {pyGSTi-0.9.12.1.dist-info → pyGSTi-0.9.13.dist-info}/top_level.txt +0 -0
pygsti/protocols/rb.py CHANGED
@@ -10,6 +10,7 @@ RB Protocol objects
10
10
  # http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory.
11
11
  #***************************************************************************************************
12
12
 
13
+ from collections import defaultdict
13
14
  import numpy as _np
14
15
 
15
16
  from pygsti.protocols import protocol as _proto
@@ -65,6 +66,10 @@ class CliffordRBDesign(_vb.BenchmarkingDesign):
65
66
  the ideal output a circuit is randomized to a uniformly random bit-string. This setting is
66
67
  useful for, e.g., detecting leakage/loss/measurement-bias etc.
67
68
 
69
+ interleaved_circuit : Circuit, optional (default None)
70
+ Circuit to use in the constuction of an interleaved CRB experiment. When specified each
71
+ random clifford operation is interleaved with the specified circuit.
72
+
68
73
  citerations : int, optional
69
74
  Some of the Clifford compilation algorithms in pyGSTi (including the default algorithm) are
70
75
  randomized, and the lowest-cost circuit is chosen from all the circuit generated in the
@@ -111,7 +116,7 @@ class CliffordRBDesign(_vb.BenchmarkingDesign):
111
116
  """
112
117
 
113
118
  @classmethod
114
- def from_existing_circuits(cls, circuits_and_idealouts_by_depth, qubit_labels=None,
119
+ def from_existing_circuits(cls, data_by_depth, qubit_labels=None,
115
120
  randomizeout=False, citerations=20, compilerargs=(), interleaved_circuit=None,
116
121
  descriptor='A Clifford RB experiment', add_default_protocol=False):
117
122
  """
@@ -123,10 +128,12 @@ class CliffordRBDesign(_vb.BenchmarkingDesign):
123
128
 
124
129
  Parameters
125
130
  ----------
126
- circuits_and_idealouts_by_depth : dict
127
- A dictionary whose keys are integer depths and whose values are lists of `(circuit, ideal_outcome)`
128
- 2-tuples giving each RB circuit and its
129
- ideal (correct) outcome.
131
+ data_by_depth : dict
132
+ A dictionary whose keys are integer depths and whose values are lists of
133
+ `(circuit, ideal_outcome, num_native_gates)` tuples giving each RB circuit, its
134
+ ideal (correct) outcome, and (optionally) the number of native gates in the compiled Cliffords.
135
+ If only a 2-tuple is passed, i.e. number of native gates is not included,
136
+ the :meth:`average_gates_per_clifford()` function will not work.
130
137
 
131
138
  qubit_labels : list, optional
132
139
  If not None, a list of the qubits that the RB circuits are to be sampled for. This should
@@ -183,22 +190,27 @@ class CliffordRBDesign(_vb.BenchmarkingDesign):
183
190
  -------
184
191
  CliffordRBDesign
185
192
  """
186
- depths = sorted(list(circuits_and_idealouts_by_depth.keys()))
187
- circuit_lists = [[x[0] for x in circuits_and_idealouts_by_depth[d]] for d in depths]
188
- ideal_outs = [[x[1] for x in circuits_and_idealouts_by_depth[d]] for d in depths]
189
- circuits_per_depth = [len(circuits_and_idealouts_by_depth[d]) for d in depths]
193
+ depths = sorted(list(data_by_depth.keys()))
194
+ circuit_lists = [[x[0] for x in data_by_depth[d]] for d in depths]
195
+ ideal_outs = [[x[1] for x in data_by_depth[d]] for d in depths]
196
+ try:
197
+ native_gate_counts = [[x[2] for x in data_by_depth[d]] for d in depths]
198
+ except IndexError:
199
+ native_gate_counts = None
200
+ circuits_per_depth = [len(data_by_depth[d]) for d in depths]
190
201
  self = cls.__new__(cls)
191
202
  self._init_foundation(depths, circuit_lists, ideal_outs, circuits_per_depth, qubit_labels,
192
203
  randomizeout, citerations, compilerargs, descriptor, add_default_protocol,
193
- interleaved_circuit)
204
+ interleaved_circuit, native_gate_counts=native_gate_counts)
194
205
  return self
195
206
 
196
207
  def __init__(self, pspec, clifford_compilations, depths, circuits_per_depth, qubit_labels=None, randomizeout=False,
197
- interleaved_circuit=None, citerations=20, compilerargs=(), descriptor='A Clifford RB experiment',
198
- add_default_protocol=False, seed=None, verbosity=1, num_processes=1):
208
+ interleaved_circuit=None, citerations=20, compilerargs=(), exact_compilation_key=None,
209
+ descriptor='A Clifford RB experiment', add_default_protocol=False, seed=None, verbosity=1, num_processes=1):
199
210
  if qubit_labels is None: qubit_labels = tuple(pspec.qubit_labels)
200
211
  circuit_lists = []
201
212
  ideal_outs = []
213
+ native_gate_counts = []
202
214
 
203
215
  if seed is None:
204
216
  self.seed = _np.random.randint(1, 1e6) # Pick a random seed
@@ -214,26 +226,35 @@ class CliffordRBDesign(_vb.BenchmarkingDesign):
214
226
  args_list = [(pspec, clifford_compilations, l)] * circuits_per_depth
215
227
  kwargs_list = [dict(qubit_labels=qubit_labels, randomizeout=randomizeout, citerations=citerations,
216
228
  compilerargs=compilerargs, interleaved_circuit=interleaved_circuit,
217
- seed=lseed + i) for i in range(circuits_per_depth)]
229
+ seed=lseed + i, return_native_gate_counts=True, exact_compilation_key=exact_compilation_key)
230
+ for i in range(circuits_per_depth)]
218
231
  results = _tools.mptools.starmap_with_kwargs(_rc.create_clifford_rb_circuit, circuits_per_depth,
219
232
  num_processes, args_list, kwargs_list)
220
233
 
221
234
  circuits_at_depth = []
222
235
  idealouts_at_depth = []
223
- for c, iout in results:
236
+ native_gate_counts_at_depth = []
237
+ for c, iout, nng in results:
224
238
  circuits_at_depth.append(c)
225
239
  idealouts_at_depth.append((''.join(map(str, iout)),))
240
+ native_gate_counts_at_depth.append(nng)
226
241
 
227
242
  circuit_lists.append(circuits_at_depth)
228
243
  ideal_outs.append(idealouts_at_depth)
244
+ native_gate_counts.append(native_gate_counts_at_depth)
229
245
 
230
246
  self._init_foundation(depths, circuit_lists, ideal_outs, circuits_per_depth, qubit_labels,
231
247
  randomizeout, citerations, compilerargs, descriptor, add_default_protocol,
232
- interleaved_circuit)
248
+ interleaved_circuit, native_gate_counts=native_gate_counts)
233
249
 
234
250
  def _init_foundation(self, depths, circuit_lists, ideal_outs, circuits_per_depth, qubit_labels,
235
251
  randomizeout, citerations, compilerargs, descriptor, add_default_protocol,
236
- interleaved_circuit):
252
+ interleaved_circuit, native_gate_counts=None, exact_compilation_key=None):
253
+ self.native_gate_count_lists = native_gate_counts
254
+ if self.native_gate_count_lists is not None:
255
+ # If we have native gate information, pair this with circuit data so that we serialize/truncate properly
256
+ self.paired_with_circuit_attrs = ["native_gate_count_lists"]
257
+
237
258
  super().__init__(depths, circuit_lists, ideal_outs, qubit_labels, remove_duplicates=False)
238
259
  self.circuits_per_depth = circuits_per_depth
239
260
  self.randomizeout = randomizeout
@@ -241,12 +262,102 @@ class CliffordRBDesign(_vb.BenchmarkingDesign):
241
262
  self.compilerargs = compilerargs
242
263
  self.descriptor = descriptor
243
264
  self.interleaved_circuit = interleaved_circuit
265
+ self.exact_compilation_key = exact_compilation_key
244
266
  if add_default_protocol:
245
267
  if randomizeout:
246
268
  defaultfit = 'A-fixed'
247
269
  else:
248
270
  defaultfit = 'full'
249
271
  self.add_default_protocol(RB(name='RB', defaultfit=defaultfit))
272
+
273
+ #set some auxfile information for interleaved_circuit
274
+ self.auxfile_types['interleaved_circuit'] = 'circuit-str-json'
275
+
276
+ def average_native_gates_per_clifford_for_circuit(self, list_idx, circ_idx):
277
+ """The average number of native gates per Clifford for a specific circuit
278
+
279
+ Parameters
280
+ ----------
281
+ list_idx: int
282
+ The index of the circuit list (for a given depth)
283
+
284
+ circ_idx: int
285
+ The index of the circuit within the circuit list
286
+
287
+ Returns
288
+ -------
289
+ avg_gate_counts: dict
290
+ The average number of native gates, native 2Q gates, and native size
291
+ per Clifford as values with respective label keys
292
+ """
293
+ if self.native_gate_counts_lists is None:
294
+ raise ValueError("Native gate counts not available, cannot compute average gates per Clifford")
295
+
296
+ num_clifford_gates = self.depths[list_idx] + 1
297
+ avg_gate_counts = {}
298
+ for key, native_gate_count in self.native_gate_count_lists[list_idx][circ_idx].items():
299
+ avg_gate_counts[key.replace('native', 'avg_native_per_clifford')] = native_gate_count / num_clifford_gates
300
+
301
+ return avg_gate_counts
302
+
303
+ def average_native_gates_per_clifford_for_circuit_list(self, list_idx):
304
+ """The average number of gates per Clifford for a circuit list
305
+
306
+ This essentially gives the average number of native gates per Clifford
307
+ for a given depth (indexed by list index, not depth).
308
+
309
+ Parameters
310
+ ----------
311
+ list_idx: int
312
+ The index of the circuit list (for a given depth)
313
+
314
+ circ_idx: int
315
+ The index of the circuit within the circuit list
316
+
317
+ Returns
318
+ -------
319
+ float
320
+ The average number of native gates per Clifford
321
+ """
322
+ if self.native_gate_count_lists is None:
323
+ raise ValueError("Native gate counts not available, cannot compute average gates per Clifford")
324
+
325
+ gate_counts = defaultdict(int)
326
+ for native_gate_counts in self.native_gate_count_lists[list_idx]:
327
+ for k, v in native_gate_counts.items():
328
+ gate_counts[k] += v
329
+
330
+ num_clifford_gates = len(self.native_gate_count_lists[list_idx]) * (self.depths[list_idx] + 1)
331
+ avg_gate_counts = {}
332
+ for key, total_native_gate_counts in gate_counts.items():
333
+ avg_gate_counts[key.replace('native', 'avg_native_per_clifford')] = total_native_gate_counts / num_clifford_gates
334
+
335
+ return avg_gate_counts
336
+
337
+ def average_native_gates_per_clifford(self):
338
+ """The average number of native gates per Clifford for all circuits
339
+
340
+ Returns
341
+ -------
342
+ float
343
+ The average number of native gates per Clifford
344
+ """
345
+ if self.native_gate_count_lists is None:
346
+ raise ValueError("Number of native gates not available, cannot compute average gates per Clifford")
347
+
348
+ gate_counts = defaultdict(int)
349
+ num_clifford_gates = 0
350
+ for list_idx in range(len(self.depths)):
351
+ for native_gate_counts in self.native_gate_count_lists[list_idx]:
352
+ for k, v in native_gate_counts.items():
353
+ gate_counts[k] += v
354
+ num_clifford_gates += len(self.native_gate_count_lists[list_idx]) * (self.depths[list_idx] + 1)
355
+
356
+ avg_gate_counts = {}
357
+ for key, total_native_gate_counts in gate_counts.items():
358
+ avg_gate_counts[key.replace('native', 'avg_native_per_clifford')] = total_native_gate_counts / num_clifford_gates
359
+
360
+ return avg_gate_counts
250
361
 
251
362
  def map_qubit_labels(self, mapper):
252
363
  """
@@ -970,6 +1081,9 @@ class BinaryRBDesign(_vb.BenchmarkingDesign):
970
1081
  def _init_foundation(self, depths, circuit_lists, measurements, signs, circuits_per_depth, qubit_labels, layer_sampling,
971
1082
  sampler, samplerargs, addlocal, lsargs, descriptor,
972
1083
  add_default_protocol):
1084
+ # Pair these attributes with circuit data so that we serialize/truncate properly
1085
+ self.paired_with_circuit_attrs = ["measurements", "signs"]
1086
+
973
1087
  super().__init__(depths, circuit_lists, signs, qubit_labels, remove_duplicates=False)
974
1088
  self.measurements = measurements
975
1089
  self.signs = signs
@@ -986,11 +1100,185 @@ class BinaryRBDesign(_vb.BenchmarkingDesign):
986
1100
 
987
1101
  defaultfit = 'A-fixed'
988
1102
  self.add_default_protocol(RB(name='RB', defaultfit=defaultfit))
989
-
990
- self.auxfile_types['signs'] = 'json' # Makes sure that signs and measurements are saved seperately
991
- self.auxfile_types['measurements'] = 'json'
992
1103
 
993
1104
 
1105
+ class InterleavedRBDesign(_proto.CombinedExperimentDesign):
1106
+ """
1107
+ Experiment design for interleaved randomized benchmarking (IRB).
1108
+
1109
+ IRB encapsulates a pair of "Clifford randomized benchmarking" (CRB) experiments.
1110
+ One of these CRB designs is a 'standard' one, but the other interleaves some
1111
+ clifford gate of interest between each random clifford operation.
1112
+ The circuits created by this function will respect the connectivity and gate-set of the device encoded by
1113
+ `pspec` (see the :class:`QubitProcessorSpec` object docstring for how to construct the relevant `pspec`
1114
+ for a device).
1115
+
1116
+ Parameters
1117
+ ----------
1118
+ pspec : QubitProcessorSpec
1119
+ The QubitProcessorSpec for the device that the CRB experiment is being generated for, which defines the
1120
+ "native" gate-set and the connectivity of the device. The returned CRB circuits will be over the gates in
1121
+ `pspec`, and will respect the connectivity encoded by `pspec`.
1122
+
1123
+ clifford_compilations : dict
1124
+ A dictionary with the potential keys `'absolute'` and `'paulieq'` and corresponding class:`CompilationRules` values.
1125
+ These compilation rules specify how to compile the "native" gates of `pspec` into Clifford gates.
1126
+
1127
+ depths : list of ints
1128
+ The "CRB depths" of the circuit; a list of integers >= 0. The CRB length is the number of Cliffords in the
1129
+ circuit - 2 *before* each Clifford is compiled into the native gate-set.
1130
+
1131
+ circuits_per_depth : int
1132
+ The number of (possibly) different CRB circuits sampled at each length.
1133
+
1134
+ interleaved_circuit : Circuit
1135
+ Circuit to use in the constuction of the interleaved CRB experiment. This is the circuit
1136
+ whose error rate is to be estimated by the IRB experiment.
1137
+
1138
+ qubit_labels : list, optional
1139
+ If not None, a list of the qubits that the RB circuits are to be sampled for. This should
1140
+ be all or a subset of the qubits in the device specified by the QubitProcessorSpec `pspec`.
1141
+ If None, it is assumed that the RB circuit should be over all the qubits. Note that the
1142
+ ordering of this list is the order of the "wires" in the returned circuit, but is otherwise
1143
+ irrelevant. If desired, a circuit that explicitly idles on the other qubits can be obtained
1144
+ by using methods of the Circuit object.
1145
+
1146
+ randomizeout : bool, optional
1147
+ If False, the ideal output of the circuits (the "success" or "survival" outcome) is always
1148
+ the all-zeros bit string. This is probably considered to be the "standard" in CRB. If True,
1149
+ the ideal output a circuit is randomized to a uniformly random bit-string. This setting is
1150
+ useful for, e.g., detecting leakage/loss/measurement-bias etc.
1151
+
1152
+ citerations : int, optional
1153
+ Some of the Clifford compilation algorithms in pyGSTi (including the default algorithm) are
1154
+ randomized, and the lowest-cost circuit is chosen from all the circuit generated in the
1155
+ iterations of the algorithm. This is the number of iterations used. The time required to
1156
+ generate a CRB circuit is linear in `citerations * (CRB length + 2)`. Lower-depth / lower 2-qubit
1157
+ gate count compilations of the Cliffords are important in order to successfully implement
1158
+ CRB on more qubits.
1159
+
1160
+ compilerargs : list, optional
1161
+ A list of arguments that are handed to compile_clifford() function, which includes all the
1162
+ optional arguments of compile_clifford() *after* the `iterations` option (set by `citerations`).
1163
+ In order, this list should be values for:
1164
+
1165
+ * algorithm : str. A string that specifies the compilation algorithm. The default in
1166
+ compile_clifford() will always be whatever we consider to be the 'best' all-round
1167
+ algorithm.
1168
+ * aargs : list. A list of optional arguments for the particular compilation algorithm.
1169
+ * costfunction : 'str' or function. The cost-function from which the "best" compilation
1170
+ for a Clifford is chosen from all `citerations` compilations. The default costs a
1171
+ circuit as 10x the num. of 2-qubit gates in the circuit + 1x the depth of the circuit.
1172
+ * prefixpaulis : bool. Whether to prefix or append the Paulis on each Clifford.
1173
+ * paulirandomize : bool. Whether to follow each layer in the Clifford circuit with a
1174
+ random Pauli on each qubit (compiled into native gates). I.e., if this is True the
1175
+ native gates are Pauli-randomized. When True, this prevents any coherent errors adding
1176
+ (on average) inside the layers of each compiled Clifford, at the cost of increased
1177
+ circuit depth. Defaults to False.
1178
+
1179
+ For more information on these options, see the compile_clifford() docstring.
1180
+
1181
+ descriptor : str, optional
1182
+ A string describing the experiment generated, which will be stored in the returned
1183
+ dictionary.
1184
+
1185
+ add_default_protocol : bool, optional
1186
+ Whether to add a default RB protocol to the experiment design, which can be run
1187
+ later (once data is taken) by using a :class:`DefaultProtocolRunner` object.
1188
+
1189
+ seed : int, optional
1190
+ A seed to initialize the random number generator used for creating random clifford
1191
+ circuits. The first of the two subdesigns will use the specified seed directly,
1192
+ while the second will use seed+1.
1193
+
1194
+ verbosity : int, optional
1195
+ If > 0 the number of circuits generated so far is shown.
1196
+
1197
+ interleave : bool, optional
1198
+ Whether the circuits of the standard CRB and IRB sub designs should be interleaved to
1199
+ form the circuit ordering of this experiment design. E.g. when calling the `all_circuits_needing_data`
1200
+ attribute.
1201
+ """
1202
+
1203
+ def __init__(self, pspec, clifford_compilations, depths, circuits_per_depth, interleaved_circuit, qubit_labels=None, randomizeout=False,
1204
+ citerations=20, compilerargs=(), exact_compilation_key=None,
1205
+ descriptor='An Interleaved RB experiment', add_default_protocol=False, seed=None, verbosity=1, num_processes=1,
1206
+ interleave = False):
1207
+ #Farm out the construction of the experiment designs to CliffordRBDesign:
1208
+ print('Constructing Standard CRB Subdesign:')
1209
+ crb_subdesign = CliffordRBDesign(pspec, clifford_compilations, depths, circuits_per_depth, qubit_labels, randomizeout,
1210
+ None, citerations, compilerargs, exact_compilation_key,
1211
+ descriptor + ' (Standard)', add_default_protocol, seed, verbosity, num_processes)
1212
+ print('Constructing Interleaved CRB Subdesign:')
1213
+ icrb_subdesign = CliffordRBDesign(pspec, clifford_compilations, depths, circuits_per_depth, qubit_labels, randomizeout,
1214
+ interleaved_circuit, citerations, compilerargs, exact_compilation_key,
1215
+ descriptor + ' (Interleaved)', add_default_protocol, seed+1 if seed is not None else None,
1216
+ verbosity, num_processes)
1217
+
1218
+ self._init_foundation(crb_subdesign, icrb_subdesign, circuits_per_depth, interleaved_circuit, randomizeout,
1219
+ citerations, compilerargs, exact_compilation_key, interleave)
1220
+
1221
+ @classmethod
1222
+ def from_existing_designs(cls, crb_subdesign, icrb_subdesign, circuits_per_depth, interleaved_circuit, randomizeout=False,
1223
+ citerations=20, compilerargs=(), exact_compilation_key=None, interleave=False):
1224
+ self = cls.__new__(cls)
1225
+ self._init_foundation(self, crb_subdesign, icrb_subdesign, circuits_per_depth, interleaved_circuit, randomizeout,
1226
+ citerations, compilerargs, exact_compilation_key, interleave)
1227
+
1228
+ #helper method for reducing code duplication on different class constructors.
1229
+ def _init_foundation(self, crb_subdesign, icrb_subdesign, circuits_per_depth, interleaved_circuit, randomizeout,
1230
+ citerations, compilerargs, exact_compilation_key, interleave):
1231
+ super().__init__({'crb':crb_subdesign,
1232
+ 'icrb':icrb_subdesign}, interleave=interleave)
1233
+ self.circuits_per_depth = circuits_per_depth
1234
+ self.randomizeout = randomizeout
1235
+ self.citerations = citerations
1236
+ self.compilerargs = compilerargs
1237
+ self.interleaved_circuit = interleaved_circuit
1238
+ self.exact_compilation_key = exact_compilation_key
1239
+
1240
+ #set some auxfile information for serializing interleaved_circuit
1241
+ self.auxfile_types['interleaved_circuit'] = 'circuit-str-json'
1242
+
1243
+ def average_native_gates_per_clifford(self):
1244
+ """
1245
+ The average number of native gates per Clifford for all circuits
1246
+
1247
+ Returns
1248
+ -------
1249
+ tuple of floats
1250
+ A tuple of the average number of native gates per Clifford
1251
+ for the contained standard CRB design, and interleaved CRB design,
1252
+ respectively.
1253
+ """
1254
+ avg_gate_counts_crb = self['crb'].average_native_gates_per_clifford()
1255
+ avg_gate_counts_icrb = self['icrb'].average_native_gates_per_clifford()
1256
+
1257
+ return (avg_gate_counts_crb, avg_gate_counts_icrb)
1258
+
1259
+ def map_qubit_labels(self, mapper):
1260
+ """
1261
+ Creates a new experiment design whose circuits' qubit labels are updated according to a given mapping.
1262
+
1263
+ Parameters
1264
+ ----------
1265
+ mapper : dict or function
1266
+ A dictionary whose keys are the existing self.qubit_labels values
1267
+ and whose value are the new labels, or a function which takes a
1268
+ single (existing qubit-label) argument and returns a new qubit-label.
1269
+
1270
+ Returns
1271
+ -------
1272
+ InterleavedRBDesign
1273
+ """
1274
+
1275
+ mapped_crb_design = self['crb'].map_qubit_labels(mapper)
1276
+ mapped_icrb_design = self['icrb'].map_qubit_labels(mapper)
1277
+
1278
+ return InterleavedRBDesign.from_existing_designs(mapped_crb_design, mapped_icrb_design, self.circuits_per_depth,
1279
+ self.randomizeout, self.citerations, self.compilerargs, self.interleaved_circuit,
1280
+ self.exact_compilation_key)
1281
+
994
1282
  class RandomizedBenchmarking(_vb.SummaryStatistics):
995
1283
  """
996
1284
  The randomized benchmarking protocol.
@@ -998,55 +1286,10 @@ class RandomizedBenchmarking(_vb.SummaryStatistics):
998
1286
  This same analysis protocol is used for Clifford, Direct and Mirror RB.
999
1287
  The standard Mirror RB analysis is obtained by setting
1000
1288
  `datatype` = `adjusted_success_probabilities`.
1001
-
1002
- Parameters
1003
- ----------
1004
- datatype: 'success_probabilities', 'adjusted_success_probabilities', or 'energies', optional
1005
- The type of summary data to extract, average, and the fit to an exponential decay. If
1006
- 'success_probabilities' then the summary data for a circuit is the frequency that
1007
- the target bitstring is observed, i.e., the success probability of the circuit. If
1008
- 'adjusted_success_probabilties' then the summary data for a circuit is
1009
- S = sum_{k = 0}^n (-1/2)^k h_k where h_k is the frequency at which the output bitstring is
1010
- a Hamming distance of k from the target bitstring, and n is the number of qubits.
1011
- This datatype is used in Mirror RB, but can also be used in Clifford and Direct RB.
1012
- If 'energies', then the summary data is Pauli operator measurement results. This datatype is
1013
- only used for Binary RB.
1014
-
1015
- defaultfit: 'A-fixed' or 'full'
1016
- The summary data is fit to A + Bp^m with A fixed and with A as a fit parameter.
1017
- If 'A-fixed' then the default results displayed are those from fitting with A
1018
- fixed, and if 'full' then the default results displayed are those where A is a
1019
- fit parameter.
1020
-
1021
- asymptote : 'std' or float, optional
1022
- The summary data is fit to A + Bp^m with A fixed and with A has a fit parameter,
1023
- with the default results returned set by `defaultfit`. This argument specifies the
1024
- value used when 'A' is fixed. If left as 'std', then 'A' defaults to 1/2^n if
1025
- `datatype` is `success_probabilities` and to 1/4^n if `datatype` is
1026
- `adjusted_success_probabilities`.
1027
-
1028
- rtype : 'EI' or 'AGI', optional
1029
- The RB error rate definition convention. 'EI' results in RB error rates that are associated
1030
- with the entanglement infidelity, which is the error probability with stochastic Pauli errors.
1031
- 'AGI' results in RB error rates that are associated with the average gate infidelity.
1032
-
1033
- seed : list, optional
1034
- Seeds for the fit of B and p (A is seeded to the asymptote defined by `asympote`).
1035
-
1036
- bootstrap_samples : float, optional
1037
- The number of samples for generating bootstrapped error bars.
1038
-
1039
- depths: list or 'all'
1040
- If not 'all', a list of depths to use (data at other depths is discarded).
1041
-
1042
- name : str, optional
1043
- The name of this protocol, also used to (by default) name the
1044
- results produced by this protocol. If None, the class name will
1045
- be used.
1046
1289
  """
1047
1290
 
1048
1291
  def __init__(self, datatype='success_probabilities', defaultfit='full', asymptote='std', rtype='EI',
1049
- seed=(0.8, 0.95), bootstrap_samples=200, depths='all', square_mean_root=False, name=None):
1292
+ seed=(0.8, 0.95), bootstrap_samples=200, depths='all', name=None):
1050
1293
  """
1051
1294
  Initialize an RB protocol for analyzing RB data.
1052
1295
 
@@ -1109,7 +1352,6 @@ class RandomizedBenchmarking(_vb.SummaryStatistics):
1109
1352
  self.rtype = rtype
1110
1353
  self.datatype = datatype
1111
1354
  self.defaultfit = defaultfit
1112
- self.square_mean_root = square_mean_root
1113
1355
  if self.datatype == 'energies':
1114
1356
  self.energies = True
1115
1357
  else:
@@ -1143,8 +1385,6 @@ class RandomizedBenchmarking(_vb.SummaryStatistics):
1143
1385
  if self.datatype not in data.cache:
1144
1386
  summary_data_dict = self._compute_summary_statistics(data, energy = self.energies)
1145
1387
  data.cache.update(summary_data_dict)
1146
- #print('data cache updated')
1147
- #print(data.cache)
1148
1388
  src_data = data.cache[self.datatype]
1149
1389
  data_per_depth = src_data
1150
1390
 
@@ -1170,17 +1410,9 @@ class RandomizedBenchmarking(_vb.SummaryStatistics):
1170
1410
  adj_sps = []
1171
1411
  for depth in depths:
1172
1412
  percircuitdata = circuitdata_per_depth[depth]
1173
- #print(percircuitdata)
1174
- if self.square_mean_root:
1175
- #print(percircuitdata)
1176
- adj_sps.append(_np.nanmean(_np.sqrt(percircuitdata))**2)
1177
- #print(adj_sps)
1178
- else:
1179
- adj_sps.append(_np.nanmean(percircuitdata)) # average [adjusted] success probabilities or energies
1413
+ adj_sps.append(_np.nanmean(percircuitdata)) # average [adjusted] success probabilities or energies
1180
1414
 
1181
- #print(adj_sps)
1182
1415
  # Don't think this needs changed
1183
- #print(asymptote)
1184
1416
  full_fit_results, fixed_asym_fit_results = _rbfit.std_least_squares_fit(
1185
1417
  depths, adj_sps, nqubits, seed=self.seed, asymptote=asymptote,
1186
1418
  ftype='full+FA', rtype=self.rtype)
@@ -1200,10 +1432,8 @@ class RandomizedBenchmarking(_vb.SummaryStatistics):
1200
1432
  failcount_faf = 0
1201
1433
 
1202
1434
  #Store bootstrap "cache" dicts (containing summary keys) as a list under data.cache
1203
- #print(len(data.cache['bootstraps']))
1204
1435
  if 'bootstraps' not in data.cache or len(data.cache['bootstraps']) < self.bootstrap_samples:
1205
1436
  # TIM - finite counts always True here?
1206
- #print('adding bootstrap')
1207
1437
  self._add_bootstrap_qtys(data.cache, self.bootstrap_samples, finitecounts=True)
1208
1438
  bootstrap_caches = data.cache['bootstraps'] # if finitecounts else 'infbootstraps'
1209
1439
 
@@ -1397,6 +1627,147 @@ class RandomizedBenchmarkingResults(_proto.ProtocolResults):
1397
1627
  data = _proto.ProtocolData(self.data.edesign, self.data.dataset)
1398
1628
  cpy = RandomizedBenchmarkingResults(data, self.protocol, self.fits, self.depths, self.defaultfit)
1399
1629
  return cpy
1630
+
1631
+
1632
+ class InterleavedRandomizedBenchmarking(_proto.Protocol):
1633
+ """
1634
+ The interleaved randomized benchmarking protocol.
1635
+
1636
+ This object itself utilizes the RandomizedBenchmarking protocol to
1637
+ perform the analysis for the standard CRB and interleaved RB subexperiments
1638
+ that constitute the IRB process. As such, this class takes as input
1639
+ the subset of RandomizedBenchmarking's arguments relevant for CRB.
1640
+ """
1641
+
1642
+ def __init__(self, defaultfit='full', asymptote='std', rtype='EI', seed=(0.8, 0.95),
1643
+ bootstrap_samples=200, depths='all', name=None):
1644
+ """
1645
+ Initialize an RB protocol for analyzing RB data.
1646
+
1647
+ Parameters
1648
+ ----------
1649
+ defaultfit: 'A-fixed' or 'full'
1650
+ The summary data is fit to A + Bp^m with A fixed and with A as a fit parameter.
1651
+ If 'A-fixed' then the default results displayed are those from fitting with A
1652
+ fixed, and if 'full' then the default results displayed are those where A is a
1653
+ fit parameter.
1654
+
1655
+ asymptote : 'std' or float, optional
1656
+ The summary data is fit to A + Bp^m with A fixed and with A has a fit parameter,
1657
+ with the default results returned set by `defaultfit`. This argument specifies the
1658
+ value used when 'A' is fixed. If left as 'std', then 'A' defaults to 1/2^n if
1659
+ `datatype` is `success_probabilities` and to 1/4^n if `datatype` is
1660
+ `adjusted_success_probabilities`.
1661
+
1662
+ rtype : 'EI' or 'AGI', optional
1663
+ The RB error rate definition convention. 'EI' results in RB error rates that are associated
1664
+ with the entanglement infidelity, which is the error probability with stochastic Pauli errors.
1665
+ 'AGI' results in RB error rates that are associated with the average gate infidelity.
1666
+
1667
+ seed : list, optional
1668
+ Seeds for the fit of B and p (A is seeded to the asymptote defined by `asympote`).
1669
+
1670
+ bootstrap_samples : float, optional
1671
+ The number of samples for generating bootstrapped error bars.
1672
+
1673
+ depths: list or 'all'
1674
+ If not 'all', a list of depths to use (data at other depths is discarded).
1675
+
1676
+ name : str, optional
1677
+ The name of this protocol, also used to (by default) name the
1678
+ results produced by this protocol. If None, the class name will
1679
+ be used.
1680
+ """
1681
+ super().__init__(name)
1682
+ self.seed = seed
1683
+ self.depths = depths
1684
+ self.bootstrap_samples = bootstrap_samples
1685
+ self.asymptote = asymptote
1686
+ self.rtype = rtype
1687
+ self.datatype = 'success_probabilities'
1688
+ self.defaultfit = defaultfit
1689
+
1690
+ def run(self, data, memlimit=None, comm=None):
1691
+ """
1692
+ Run this protocol on `data`.
1693
+
1694
+ Parameters
1695
+ ----------
1696
+ data : ProtocolData
1697
+ The input data.
1698
+
1699
+ memlimit : int, optional
1700
+ A rough per-processor memory limit in bytes.
1701
+
1702
+ comm : mpi4py.MPI.Comm, optional
1703
+ When not ``None``, an MPI communicator used to run this protocol
1704
+ in parallel.
1705
+
1706
+ Returns
1707
+ -------
1708
+ RandomizedBenchmarkingResults
1709
+ """
1710
+ design = data.edesign
1711
+ assert(isinstance(design, InterleavedRBDesign)), 'This protocol can only be run on InterleavedRBDesign.'
1712
+ #initialize a RandomizedBenchmarking protocol to use as a helper
1713
+ #for performing analysis on the two subexperiments.
1714
+ rb_protocol = RandomizedBenchmarking('success_probabilities', self.defaultfit, self.asymptote, self.rtype,
1715
+ self.seed, self.bootstrap_samples, self.depths, name=None)
1716
+
1717
+ #run the RB protocol on both subdesigns.
1718
+ crb_results = rb_protocol.run(data['crb'])
1719
+ icrb_results = rb_protocol.run(data['icrb'])
1720
+
1721
+ nqubits = len(design.qubit_labels)
1722
+ #let the dimension depend on the value of rtype.
1723
+ dim = 2**nqubits
1724
+ if self.rtype == 'EI':
1725
+ dim_prefactor = (dim**2 -1)/(dim**2)
1726
+ elif self.rtype == 'AGI':
1727
+ dim_prefactor = (dim -1)/dim
1728
+ else:
1729
+ raise ValueError('Only EI and AGI type IRB numbers are currently implemented.')
1730
+
1731
+ irb_numbers = dict()
1732
+ irb_bounds = dict()
1733
+ #use the crb and icrb results to get the irb number and the bounds.
1734
+ for fit_key in crb_results.fits.keys():
1735
+ p_crb = crb_results.fits[fit_key].estimates['p']
1736
+ p_icrb = icrb_results.fits[fit_key].estimates['p']
1737
+ irb_numbers[fit_key] = dim_prefactor*(1-(p_icrb/p_crb))
1738
+ #Magesan paper gives the bounds as the minimum of two quantities.
1739
+ possible_bound_1 = dim_prefactor * (abs(p_crb - (p_icrb/p_crb)) + (1 - p_crb))
1740
+ possible_bound_2 = (2*(dim**2-1)*(1-p_crb))/(p_crb*dim**2) + (4*_np.sqrt(1-p_crb)*_np.sqrt(dim**2 - 1))/p_crb
1741
+ #The value of the possible_bound_2 coming directly from the Magesan paper should be in units of AGI.
1742
+ #So if we want EI use the standard dimensional conversion factor.
1743
+ if self.rtype == 'EI':
1744
+ possible_bound_2 = ((dim + 1)/dim)*possible_bound_2
1745
+ irb_bounds[fit_key] = min(possible_bound_1, possible_bound_2)
1746
+
1747
+ children = {'crb': _proto.ProtocolResultsDir(data['crb'], crb_results),
1748
+ 'icrb': _proto.ProtocolResultsDir(data['icrb'], icrb_results)}
1749
+
1750
+ irb_top_results = InterleavedRandomizedBenchmarkingResults(data, self, irb_numbers, irb_bounds)
1751
+
1752
+ return _proto.ProtocolResultsDir(data, irb_top_results, children = children)
1753
+
1754
+ class InterleavedRandomizedBenchmarkingResults(_proto.ProtocolResults):
1755
+ """
1756
+ Class for storing the results of an interleaved randomized benchmarking experiment.
1757
+ This subclasses off of ProtocolResultsDir as this class acts primarily as both a container
1758
+ class for holding the two subexperiment's results, as well as containing some specialized
1759
+ information regarding the IRB number estimates.
1760
+ """
1761
+
1762
+ def __init__(self, data, protocol, irb_numbers, irb_bounds):
1763
+ #msg = 'rb_subexperiment_results should be a dictionary with values corresponding to the'\
1764
+ # +' standard CRB and interleaved CRB subexperiments used in performing IRB.'
1765
+ #assert(isinstance(rb_subexperiment_results, dict)), msg
1766
+ #super().__init__(data, rb_subexperiment_results)
1767
+ super().__init__(data, protocol)
1768
+
1769
+ self.irb_numbers = irb_numbers
1770
+ self.irb_bounds = irb_bounds
1400
1771
 
1401
1772
 
1402
1773
  RB = RandomizedBenchmarking