iqm-benchmarks 1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of iqm-benchmarks might be problematic. Click here for more details.

Files changed (42) hide show
  1. iqm/benchmarks/__init__.py +31 -0
  2. iqm/benchmarks/benchmark.py +109 -0
  3. iqm/benchmarks/benchmark_definition.py +264 -0
  4. iqm/benchmarks/benchmark_experiment.py +163 -0
  5. iqm/benchmarks/compressive_gst/__init__.py +20 -0
  6. iqm/benchmarks/compressive_gst/compressive_gst.py +1029 -0
  7. iqm/benchmarks/entanglement/__init__.py +18 -0
  8. iqm/benchmarks/entanglement/ghz.py +802 -0
  9. iqm/benchmarks/logging_config.py +29 -0
  10. iqm/benchmarks/optimization/__init__.py +18 -0
  11. iqm/benchmarks/optimization/qscore.py +719 -0
  12. iqm/benchmarks/quantum_volume/__init__.py +21 -0
  13. iqm/benchmarks/quantum_volume/clops.py +726 -0
  14. iqm/benchmarks/quantum_volume/quantum_volume.py +854 -0
  15. iqm/benchmarks/randomized_benchmarking/__init__.py +18 -0
  16. iqm/benchmarks/randomized_benchmarking/clifford_1q.pkl +0 -0
  17. iqm/benchmarks/randomized_benchmarking/clifford_2q.pkl +0 -0
  18. iqm/benchmarks/randomized_benchmarking/clifford_rb/__init__.py +19 -0
  19. iqm/benchmarks/randomized_benchmarking/clifford_rb/clifford_rb.py +386 -0
  20. iqm/benchmarks/randomized_benchmarking/interleaved_rb/__init__.py +19 -0
  21. iqm/benchmarks/randomized_benchmarking/interleaved_rb/interleaved_rb.py +555 -0
  22. iqm/benchmarks/randomized_benchmarking/mirror_rb/__init__.py +19 -0
  23. iqm/benchmarks/randomized_benchmarking/mirror_rb/mirror_rb.py +810 -0
  24. iqm/benchmarks/randomized_benchmarking/multi_lmfit.py +86 -0
  25. iqm/benchmarks/randomized_benchmarking/randomized_benchmarking_common.py +892 -0
  26. iqm/benchmarks/readout_mitigation.py +290 -0
  27. iqm/benchmarks/utils.py +521 -0
  28. iqm_benchmarks-1.3.dist-info/LICENSE +205 -0
  29. iqm_benchmarks-1.3.dist-info/METADATA +190 -0
  30. iqm_benchmarks-1.3.dist-info/RECORD +42 -0
  31. iqm_benchmarks-1.3.dist-info/WHEEL +5 -0
  32. iqm_benchmarks-1.3.dist-info/top_level.txt +2 -0
  33. mGST/LICENSE +21 -0
  34. mGST/README.md +54 -0
  35. mGST/additional_fns.py +962 -0
  36. mGST/algorithm.py +733 -0
  37. mGST/compatibility.py +238 -0
  38. mGST/low_level_jit.py +694 -0
  39. mGST/optimization.py +349 -0
  40. mGST/qiskit_interface.py +282 -0
  41. mGST/reporting/figure_gen.py +334 -0
  42. mGST/reporting/reporting.py +710 -0
@@ -0,0 +1,555 @@
1
+ # Copyright 2024 IQM Benchmarks developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Interleaved Clifford Randomized Benchmarking.
17
+ """
18
+
19
+ from time import strftime
20
+ from typing import Any, Dict, List, Literal, Optional, Sequence, Type
21
+
22
+ from matplotlib.figure import Figure
23
+ import numpy as np
24
+ from qiskit import QuantumCircuit
25
+ import xarray as xr
26
+
27
+ from iqm.benchmarks import AnalysisResult, Benchmark, RunResult
28
+ from iqm.benchmarks.benchmark import BenchmarkConfigurationBase
29
+ from iqm.benchmarks.benchmark_definition import add_counts_to_dataset
30
+ from iqm.benchmarks.logging_config import qcvv_logger
31
+ from iqm.benchmarks.randomized_benchmarking.randomized_benchmarking_common import (
32
+ exponential_rb,
33
+ fit_decay_lmfit,
34
+ generate_all_rb_circuits,
35
+ generate_fixed_depth_parallel_rb_circuits,
36
+ get_survival_probabilities,
37
+ import_native_gate_cliffords,
38
+ lmfit_minimizer,
39
+ plot_rb_decay,
40
+ submit_parallel_rb_job,
41
+ submit_sequential_rb_jobs,
42
+ survival_probabilities_parallel,
43
+ validate_irb_gate,
44
+ validate_rb_qubits,
45
+ )
46
+ from iqm.benchmarks.utils import retrieve_all_counts, retrieve_all_job_metadata, timeit, xrvariable_to_counts
47
+ from iqm.qiskit_iqm.iqm_backend import IQMBackendBase
48
+
49
+
50
+ # pylint: disable=too-many-statements, too-many-branches
51
+ def interleaved_rb_analysis(run: RunResult) -> AnalysisResult:
52
+ """Analysis function for an Interleaved RB experiment
53
+
54
+ Args:
55
+ run (RunResult): An interleaved RB experiment run for which analysis result is created
56
+ Returns:
57
+ AnalysisResult corresponding to Interleaved RB
58
+ """
59
+ dataset = run.dataset
60
+ observations: Dict[int, Any] = {}
61
+ plots: Dict[str, Figure] = {}
62
+
63
+ is_parallel_execution = dataset.attrs["parallel_execution"]
64
+ qubits_array = dataset.attrs["qubits_array"]
65
+ num_circuit_samples = dataset.attrs["num_circuit_samples"]
66
+ sequence_lengths = dataset.attrs["sequence_lengths"]
67
+
68
+ interleaved_gate = dataset.attrs["interleaved_gate"]
69
+ interleaved_gate_parameters = dataset.attrs["interleaved_gate_params"]
70
+
71
+ simultaneous_fit = dataset.attrs["simultaneous_fit"]
72
+
73
+ all_noisy_counts: Dict[str, Dict[str, Dict[int, List[Dict[str, int]]]]] = {}
74
+ fidelities: Dict[str, Dict[str, Dict[int, List[float]]]] = {
75
+ str(q): {rb_type: {} for rb_type in ["clifford", "interleaved"]} for q in qubits_array
76
+ }
77
+
78
+ if is_parallel_execution:
79
+ qcvv_logger.info(f"Post-processing parallel Interleaved RB for qubits {qubits_array}")
80
+ all_noisy_counts[str(qubits_array)] = {}
81
+ for rb_type in ["clifford", "interleaved"]:
82
+ all_noisy_counts[str(qubits_array)][rb_type] = {}
83
+ for depth in sequence_lengths:
84
+ identifier = f"{rb_type}_qubits_{str(qubits_array)}_depth_{str(depth)}"
85
+ all_noisy_counts[str(qubits_array)][rb_type][depth] = xrvariable_to_counts(
86
+ dataset, identifier, num_circuit_samples
87
+ )
88
+
89
+ # Retrieve the marginalized survival probabilities
90
+ all_survival_probabilities = survival_probabilities_parallel(
91
+ qubits_array, all_noisy_counts[str(qubits_array)][rb_type][depth]
92
+ )
93
+
94
+ # The marginalized survival probabilities will be arranged by qubit layouts
95
+ for qubits_str in all_survival_probabilities.keys():
96
+ fidelities[qubits_str][rb_type][depth] = all_survival_probabilities[qubits_str]
97
+ # Remaining analysis is the same regardless of whether execution was in parallel or sequential
98
+ qcvv_logger.info(f"Metrics for {rb_type.capitalize()} estimated successfully!")
99
+ else: # sequential
100
+ qcvv_logger.info(f"Post-processing sequential Interleaved RB for qubits {qubits_array}")
101
+
102
+ for q in qubits_array:
103
+ all_noisy_counts[str(q)] = {}
104
+ num_qubits = len(q)
105
+ fidelities[str(q)] = {}
106
+ for rb_type in ["clifford", "interleaved"]:
107
+ all_noisy_counts[str(q)][rb_type] = {}
108
+ fidelities[str(q)][rb_type] = {}
109
+ for depth in sequence_lengths:
110
+ identifier = f"{rb_type}_qubits_{str(q)}_depth_{str(depth)}"
111
+ all_noisy_counts[str(q)][rb_type][depth] = xrvariable_to_counts(
112
+ dataset, identifier, num_circuit_samples
113
+ )
114
+
115
+ qcvv_logger.info(f"Now on {rb_type.capitalize()} RB with qubits {q} and depth {depth}")
116
+ fidelities[str(q)][rb_type][depth] = get_survival_probabilities(
117
+ num_qubits, all_noisy_counts[str(q)][rb_type][depth]
118
+ )
119
+ # Remaining analysis is the same regardless of whether execution was in parallel or sequential
120
+
121
+ # All remaining (fitting & plotting) is done per qubit layout
122
+ for qubits_idx, qubits in enumerate(qubits_array):
123
+ dataset.attrs[str(qubits)] = {}
124
+ # Fit decays simultaneously
125
+ list_of_fidelities_clifford = list(fidelities[str(qubits)]["clifford"].values())
126
+ list_of_fidelities_interleaved = list(fidelities[str(qubits)]["interleaved"].values())
127
+ fit_data, fit_parameters = fit_decay_lmfit(
128
+ exponential_rb,
129
+ qubits,
130
+ [list_of_fidelities_clifford, list_of_fidelities_interleaved],
131
+ "interleaved",
132
+ simultaneous_fit,
133
+ )
134
+ rb_fit_results = lmfit_minimizer(fit_parameters, fit_data, sequence_lengths, exponential_rb)
135
+
136
+ processed_results = {}
137
+ for rb_type in ["interleaved", "clifford"]:
138
+ average_fidelities = {d: np.mean(fidelities[str(qubits)][rb_type][d]) for d in sequence_lengths}
139
+ stddevs_from_mean = {
140
+ d: np.std(fidelities[str(qubits)][rb_type][d]) / np.sqrt(num_circuit_samples) for d in sequence_lengths
141
+ }
142
+ popt = {
143
+ "amplitude": (
144
+ rb_fit_results.params["amplitude_1"]
145
+ if rb_type == "clifford"
146
+ else rb_fit_results.params["amplitude_2"]
147
+ ),
148
+ "offset": (
149
+ rb_fit_results.params["offset_1"] if rb_type == "clifford" else rb_fit_results.params["offset_2"]
150
+ ),
151
+ "decay_rate": (
152
+ rb_fit_results.params["p_rb"] if rb_type == "clifford" else rb_fit_results.params["p_irb"]
153
+ ),
154
+ }
155
+ fidelity = (
156
+ rb_fit_results.params["fidelity_per_clifford"]
157
+ if rb_type == "clifford"
158
+ else rb_fit_results.params["interleaved_fidelity"]
159
+ )
160
+
161
+ processed_results[rb_type] = {
162
+ "avg_gate_fidelity": {"value": fidelity.value, "uncertainty": fidelity.stderr},
163
+ "decay_rate": {"value": popt["decay_rate"].value, "uncertainty": popt["decay_rate"].stderr},
164
+ "fit_amplitude": {"value": popt["amplitude"].value, "uncertainty": popt["amplitude"].stderr},
165
+ "fit_offset": {"value": popt["offset"].value, "uncertainty": popt["offset"].stderr},
166
+ }
167
+
168
+ dataset.attrs[qubits_idx].update(
169
+ {
170
+ rb_type: {
171
+ "fidelities": fidelities[str(qubits)][rb_type],
172
+ "avg_fidelities_nominal_values": average_fidelities,
173
+ "avg_fidelities_stderr": stddevs_from_mean,
174
+ "fitting_method": str(rb_fit_results.method),
175
+ "num_function_evals": int(rb_fit_results.nfev),
176
+ "data_points": int(rb_fit_results.ndata),
177
+ "num_variables": int(rb_fit_results.nvarys),
178
+ "chi_square": float(rb_fit_results.chisqr),
179
+ "reduced_chi_square": float(rb_fit_results.redchi),
180
+ "Akaike_info_crit": float(rb_fit_results.aic),
181
+ "Bayesian_info_crit": float(rb_fit_results.bic),
182
+ }
183
+ }
184
+ )
185
+
186
+ observations.update({qubits_idx: processed_results})
187
+
188
+ # Generate decay plots
189
+ if interleaved_gate_parameters is None:
190
+ interleaved_gate_string = f"{interleaved_gate}"
191
+ else:
192
+ params_string = str(tuple(f"{x:.2f}" for x in interleaved_gate_parameters))
193
+ interleaved_gate_string = f"{interleaved_gate}{params_string}"
194
+
195
+ fig_name, fig = plot_rb_decay(
196
+ "irb",
197
+ [qubits],
198
+ dataset,
199
+ observations,
200
+ interleaved_gate=interleaved_gate_string,
201
+ )
202
+ plots[fig_name] = fig
203
+
204
+ # Rearrange observations
205
+ observations_refactored: Dict[int, Dict[str, Dict[str, float]]] = {}
206
+ for k, o in observations.items():
207
+ observations_refactored[k] = {}
208
+ for rb_type in o.keys():
209
+ observations_refactored[k].update({f"{k}_{rb_type}": v for k, v in o[rb_type].items()})
210
+
211
+ return AnalysisResult(dataset=dataset, observations=observations_refactored, plots=plots)
212
+
213
+
214
+ class InterleavedRandomizedBenchmarking(Benchmark):
215
+ """Interleaved RB estimates the average gate fidelity of a specific Clifford gate"""
216
+
217
+ analysis_function = staticmethod(interleaved_rb_analysis)
218
+
219
+ name: str = "clifford_rb"
220
+
221
+ def __init__(self, backend_arg: IQMBackendBase | str, configuration: "InterleavedRBConfiguration"):
222
+ """Construct the InterleavedRandomizedBenchmark class
223
+
224
+ Args:
225
+ backend_arg (IQMBackendBase | str): the backend to execute Clifford RB on
226
+ configuration (CliffordRBConfiguration): The Clifford RB configuration
227
+ """
228
+ super().__init__(backend_arg, configuration)
229
+
230
+ # EXPERIMENT
231
+ self.backend_configuration_name = backend_arg if isinstance(backend_arg, str) else backend_arg.name
232
+
233
+ self.qubits_array = configuration.qubits_array
234
+ self.sequence_lengths = configuration.sequence_lengths
235
+ self.num_circuit_samples = configuration.num_circuit_samples
236
+
237
+ self.parallel_execution = configuration.parallel_execution
238
+
239
+ self.interleaved_gate = configuration.interleaved_gate
240
+ self.interleaved_gate_params = configuration.interleaved_gate_params
241
+ self.simultaneous_fit = configuration.simultaneous_fit
242
+
243
+ self.session_timestamp = strftime("%Y%m%d-%H%M%S")
244
+ self.execution_timestamp = ""
245
+
246
+ def add_all_meta_to_dataset(self, dataset: xr.Dataset):
247
+ """Adds all configuration metadata and circuits to the dataset variable
248
+ Args:
249
+ dataset (xr.Dataset): The xarray dataset
250
+ """
251
+ dataset.attrs["session_timestamp"] = self.session_timestamp
252
+ dataset.attrs["execution_timestamp"] = self.execution_timestamp
253
+ dataset.attrs["backend_configuration_name"] = self.backend_configuration_name
254
+ dataset.attrs["backend_name"] = self.backend.name
255
+
256
+ for key, value in self.configuration:
257
+ if key == "benchmark": # Avoid saving the class object
258
+ dataset.attrs[key] = value.name
259
+ else:
260
+ dataset.attrs[key] = value
261
+ # Defined outside configuration - if any
262
+
263
+ @timeit
264
+ def add_all_circuits_to_dataset(self, dataset: xr.Dataset):
265
+ """Adds all generated circuits during execution to the dataset variable
266
+
267
+ Args:
268
+ dataset (xr.Dataset): The xarray dataset
269
+
270
+ Returns:
271
+
272
+ """
273
+ qcvv_logger.info("Adding all circuits to the dataset")
274
+ dataset.attrs["untranspiled_circuits"] = self.untranspiled_circuits
275
+ dataset.attrs["transpiled_circuits"] = self.transpiled_circuits
276
+
277
+ # pylint: disable=too-many-statements
278
+ def execute(self, backend: IQMBackendBase) -> xr.Dataset:
279
+ """Executes the benchmark"""
280
+
281
+ self.execution_timestamp = strftime("%Y%m%d-%H%M%S")
282
+ validate_rb_qubits(self.qubits_array, backend)
283
+
284
+ dataset = xr.Dataset()
285
+ self.add_all_meta_to_dataset(dataset)
286
+
287
+ clifford_1q_dict, clifford_2q_dict = import_native_gate_cliffords()
288
+
289
+ # Submit jobs for all qubit layouts
290
+ all_rb_jobs: Dict[str, List[Dict[str, Any]]] = {} # Label by Clifford or Interleaved
291
+ time_circuit_generation: Dict[str, float] = {}
292
+
293
+ # Initialize the variable to contain the circuits for each layout
294
+ self.untranspiled_circuits: Dict[str, Dict[int, List[QuantumCircuit]]] = {}
295
+ self.transpiled_circuits: Dict[str, Dict[int, List[QuantumCircuit]]] = {}
296
+
297
+ # Validate and get interleaved gate as a QC
298
+ interleaved_gate_qc = validate_irb_gate(
299
+ self.interleaved_gate, backend, gate_params=self.interleaved_gate_params
300
+ )
301
+
302
+ # Auxiliary dict from str(qubits) to indices
303
+ qubit_idx: Dict[str, Any] = {}
304
+
305
+ if self.parallel_execution:
306
+ all_rb_jobs["clifford"] = []
307
+ all_rb_jobs["interleaved"] = []
308
+ # Take the whole qubits_array and do RB in parallel on each qubits_array element
309
+ parallel_untranspiled_rb_circuits = {}
310
+ parallel_transpiled_rb_circuits = {}
311
+ parallel_untranspiled_interleaved_rb_circuits = {}
312
+ parallel_transpiled_interleaved_rb_circuits = {}
313
+ qcvv_logger.info(
314
+ f"Now executing parallel Interleaved RB on qubits {self.qubits_array}."
315
+ f" Will generate and submit all {self.num_circuit_samples} Interleaved and Clifford RB circuits"
316
+ f" for each depth {self.sequence_lengths}."
317
+ )
318
+
319
+ time_circuit_generation[str(self.qubits_array)] = 0
320
+
321
+ # Generate and submit all circuits
322
+ for seq_length in self.sequence_lengths:
323
+ # There are different ways of dealing with submission here:
324
+ # We'll generate Clifford circuits, then Interleaved circuits, for fixed depth
325
+ # Then we'll submit separate jobs but one right after the other, Clifford first
326
+ # Do for all sequence depths
327
+
328
+ qcvv_logger.info(f"Generating Clifford RB circuits of sequence length {seq_length}")
329
+ (
330
+ (parallel_untranspiled_rb_circuits[seq_length], parallel_transpiled_rb_circuits[seq_length]),
331
+ elapsed_time_untranspiled,
332
+ ) = generate_fixed_depth_parallel_rb_circuits(
333
+ self.qubits_array,
334
+ clifford_1q_dict,
335
+ clifford_2q_dict,
336
+ seq_length,
337
+ self.num_circuit_samples,
338
+ backend,
339
+ interleaved_gate=None,
340
+ )
341
+ qcvv_logger.info(f"Generating Interleaved RB circuits of sequence length {seq_length}")
342
+
343
+ (
344
+ (
345
+ parallel_untranspiled_interleaved_rb_circuits[seq_length],
346
+ parallel_transpiled_interleaved_rb_circuits[seq_length],
347
+ ),
348
+ elapsed_time_transpiled,
349
+ ) = generate_fixed_depth_parallel_rb_circuits(
350
+ self.qubits_array,
351
+ clifford_1q_dict,
352
+ clifford_2q_dict,
353
+ seq_length,
354
+ self.num_circuit_samples,
355
+ backend,
356
+ interleaved_gate=interleaved_gate_qc,
357
+ )
358
+
359
+ time_circuit_generation[str(self.qubits_array)] += elapsed_time_untranspiled + elapsed_time_transpiled
360
+
361
+ # Submit all
362
+ flat_qubits_array = [x for y in self.qubits_array for x in y]
363
+ sorted_transpiled_rb_qc_list = {tuple(flat_qubits_array): parallel_transpiled_rb_circuits[seq_length]}
364
+ sorted_transpiled_interleaved_rb_qc_list = {
365
+ tuple(flat_qubits_array): parallel_transpiled_interleaved_rb_circuits[seq_length]
366
+ }
367
+ all_rb_jobs["clifford"].append(
368
+ submit_parallel_rb_job(
369
+ backend,
370
+ self.qubits_array,
371
+ seq_length,
372
+ sorted_transpiled_rb_qc_list,
373
+ self.shots,
374
+ self.calset_id,
375
+ self.max_gates_per_batch,
376
+ )
377
+ )
378
+ all_rb_jobs["interleaved"].append(
379
+ submit_parallel_rb_job(
380
+ backend,
381
+ self.qubits_array,
382
+ seq_length,
383
+ sorted_transpiled_interleaved_rb_qc_list,
384
+ self.shots,
385
+ self.calset_id,
386
+ self.max_gates_per_batch,
387
+ )
388
+ )
389
+ qcvv_logger.info(f"Both jobs for sequence length {seq_length} submitted successfully!")
390
+
391
+ self.untranspiled_circuits[str(self.qubits_array)] = {
392
+ m: parallel_untranspiled_rb_circuits[m] for m in self.sequence_lengths
393
+ }
394
+ self.transpiled_circuits[str(self.qubits_array)] = {
395
+ m: parallel_transpiled_rb_circuits[m] for m in self.sequence_lengths
396
+ }
397
+ self.untranspiled_circuits[str(self.qubits_array) + "_interleaved"] = {
398
+ m: parallel_untranspiled_interleaved_rb_circuits[m] for m in self.sequence_lengths
399
+ }
400
+ self.transpiled_circuits[str(self.qubits_array) + "_interleaved"] = {
401
+ m: parallel_transpiled_interleaved_rb_circuits[m] for m in self.sequence_lengths
402
+ }
403
+
404
+ qubit_idx = {str(self.qubits_array): "parallel_all"}
405
+ dataset.attrs["parallel_all"] = {"qubits": self.qubits_array}
406
+ dataset.attrs.update({q_idx: {"qubits": q} for q_idx, q in enumerate(self.qubits_array)})
407
+ else:
408
+ rb_untranspiled_circuits: Dict[str, Dict[int, List[QuantumCircuit]]] = {}
409
+ rb_transpiled_circuits: Dict[str, Dict[int, List[QuantumCircuit]]] = {}
410
+ rb_untranspiled_interleaved_circuits: Dict[str, Dict[int, List[QuantumCircuit]]] = {}
411
+ rb_transpiled_interleaved_circuits: Dict[str, Dict[int, List[QuantumCircuit]]] = {}
412
+
413
+ all_rb_jobs["clifford"] = []
414
+ all_rb_jobs["interleaved"] = []
415
+
416
+ for qubits_idx, qubits in enumerate(self.qubits_array):
417
+ qubit_idx[str(qubits)] = qubits_idx
418
+ qcvv_logger.info(
419
+ f"Wxecuting sequential Clifford and Interleaved RB circuits on qubits {qubits}."
420
+ f" Will generate and submit all {self.num_circuit_samples} Clifford RB circuits"
421
+ f" for each depth {self.sequence_lengths}"
422
+ )
423
+ num_qubits = len(qubits)
424
+ rb_untranspiled_circuits[str(qubits)] = {}
425
+ rb_transpiled_circuits[str(qubits)] = {}
426
+ rb_untranspiled_interleaved_circuits[str(qubits)] = {}
427
+ rb_transpiled_interleaved_circuits[str(qubits)] = {}
428
+
429
+ if num_qubits == 1:
430
+ clifford_dict = clifford_1q_dict
431
+ else:
432
+ clifford_dict = clifford_2q_dict
433
+
434
+ ((rb_untranspiled_circuits[str(qubits)], rb_transpiled_circuits[str(qubits)]), t_clifford) = (
435
+ generate_all_rb_circuits(
436
+ qubits,
437
+ self.sequence_lengths,
438
+ clifford_dict,
439
+ self.num_circuit_samples,
440
+ backend,
441
+ interleaved_gate=None,
442
+ )
443
+ )
444
+ (
445
+ (
446
+ rb_untranspiled_interleaved_circuits[str(qubits)],
447
+ rb_transpiled_interleaved_circuits[str(qubits)],
448
+ ),
449
+ t_inter,
450
+ ) = generate_all_rb_circuits(
451
+ qubits,
452
+ self.sequence_lengths,
453
+ clifford_dict,
454
+ self.num_circuit_samples,
455
+ backend,
456
+ interleaved_gate=interleaved_gate_qc,
457
+ )
458
+
459
+ time_circuit_generation[str(qubits)] = t_clifford + t_inter
460
+
461
+ # Submit Clifford then Interleaved
462
+ all_rb_jobs["clifford"].extend(
463
+ submit_sequential_rb_jobs(
464
+ qubits,
465
+ rb_transpiled_circuits[str(qubits)],
466
+ self.shots,
467
+ backend,
468
+ self.calset_id,
469
+ max_gates_per_batch=self.max_gates_per_batch,
470
+ )
471
+ )
472
+ all_rb_jobs["interleaved"].extend(
473
+ submit_sequential_rb_jobs(
474
+ qubits,
475
+ rb_transpiled_interleaved_circuits[str(qubits)],
476
+ self.shots,
477
+ backend,
478
+ self.calset_id,
479
+ max_gates_per_batch=self.max_gates_per_batch,
480
+ )
481
+ )
482
+ qcvv_logger.info(
483
+ f"All jobs for qubits {qubits} and sequence lengths {self.sequence_lengths} submitted successfully!"
484
+ )
485
+
486
+ self.untranspiled_circuits[str(qubits)] = rb_untranspiled_circuits[str(qubits)]
487
+ self.transpiled_circuits[str(qubits)] = rb_transpiled_circuits[str(qubits)]
488
+ self.untranspiled_circuits[str(qubits) + "_interleaved"] = rb_untranspiled_interleaved_circuits[
489
+ str(qubits)
490
+ ]
491
+ self.transpiled_circuits[str(qubits) + "_interleaved"] = rb_transpiled_interleaved_circuits[str(qubits)]
492
+
493
+ dataset.attrs[qubits_idx] = {"qubits": qubits}
494
+
495
+ # Retrieve counts of jobs for all qubit layouts
496
+ all_job_metadata = {}
497
+ for rb_type in ["clifford", "interleaved"]:
498
+ for job_dict in all_rb_jobs[rb_type]:
499
+ qubits = job_dict["qubits"]
500
+ depth = job_dict["depth"]
501
+ # Retrieve counts
502
+ identifier = f"{rb_type}_qubits_{str(qubits)}_depth_{str(depth)}"
503
+ execution_results, time_retrieve = retrieve_all_counts(job_dict["jobs"], identifier)
504
+ # Retrieve all job meta data
505
+ all_job_metadata = retrieve_all_job_metadata(job_dict["jobs"])
506
+ # Export all to dataset
507
+ dataset.attrs[qubit_idx[str(qubits)]].update(
508
+ {
509
+ rb_type: {
510
+ f"depth_{str(depth)}": {
511
+ "time_circuit_generation": time_circuit_generation[str(qubits)],
512
+ "time_submit": job_dict["time_submit"],
513
+ "time_retrieve": time_retrieve,
514
+ "all_job_metadata": all_job_metadata,
515
+ },
516
+ }
517
+ }
518
+ )
519
+
520
+ qcvv_logger.info(f"Adding counts of qubits {qubits} and depth {depth} run to the dataset")
521
+ dataset, _ = add_counts_to_dataset(execution_results, identifier, dataset)
522
+
523
+ self.add_all_circuits_to_dataset(dataset)
524
+
525
+ qcvv_logger.info(f"Interleaved RB experiment concluded !")
526
+
527
+ return dataset
528
+
529
+
530
+ class InterleavedRBConfiguration(BenchmarkConfigurationBase):
531
+ """Interleaved RB configuration.
532
+ Attributes:
533
+ benchmark (Type[Benchmark]): InterleavedRandomizedBenchmarking.
534
+ qubits_array (Sequence[Sequence[int]]): The array of physical qubit labels with which to execute IRB.
535
+ sequence_lengths (Sequence[int]): The length of each random Clifford sequence.
536
+ num_circuit_samples (int): The number of circuit samples to generate.
537
+ shots (int): The number of measurement shots with which to execute each circuit sample.
538
+ parallel_execution(bool): Whether the benchmark is executed on all qubits in parallel or not.
539
+ * Default is False.
540
+ interleaved_gate (str): The name of the gate to interleave.
541
+ * Should be specified as a qiskit circuit library gate name, e.g., "YGate" or "CZGate".
542
+ interleaved_gate_params (Optional[Sequence[float]]): Any optional parameters entering the gate.
543
+ * Default is None.
544
+ simultaneous_fit (Sequence[Literal["amplitude", "offset"]]): Optional parameters to fit simultaneously.
545
+ * Default is ["amplitude", "offset"].
546
+ """
547
+
548
+ benchmark: Type[Benchmark] = InterleavedRandomizedBenchmarking
549
+ qubits_array: Sequence[Sequence[int]]
550
+ sequence_lengths: Sequence[int]
551
+ num_circuit_samples: int
552
+ parallel_execution: bool = False
553
+ interleaved_gate: str
554
+ interleaved_gate_params: Optional[Sequence[float]] = None
555
+ simultaneous_fit: Sequence[Literal["amplitude", "offset"]] = ["amplitude", "offset"]
@@ -0,0 +1,19 @@
1
+ # Copyright 2024 IQM Benchmarks developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Mirror RB reflects the fidelity of mirror circuits
17
+ """
18
+
19
+ from . import mirror_rb