iqm-benchmarks 2.54__py3-none-any.whl → 2.55__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.
- iqm/benchmarks/benchmark.py +2 -0
- iqm/benchmarks/benchmark_definition.py +10 -5
- iqm/benchmarks/entanglement/ghz.py +56 -46
- iqm/benchmarks/quantum_volume/clops.py +19 -9
- iqm/benchmarks/quantum_volume/quantum_volume.py +14 -74
- iqm/benchmarks/randomized_benchmarking/eplg/eplg.py +10 -6
- iqm/benchmarks/utils.py +121 -72
- iqm/benchmarks/utils_plots.py +81 -35
- {iqm_benchmarks-2.54.dist-info → iqm_benchmarks-2.55.dist-info}/METADATA +1 -1
- {iqm_benchmarks-2.54.dist-info → iqm_benchmarks-2.55.dist-info}/RECORD +13 -13
- {iqm_benchmarks-2.54.dist-info → iqm_benchmarks-2.55.dist-info}/WHEEL +1 -1
- {iqm_benchmarks-2.54.dist-info → iqm_benchmarks-2.55.dist-info}/licenses/LICENSE +0 -0
- {iqm_benchmarks-2.54.dist-info → iqm_benchmarks-2.55.dist-info}/top_level.txt +0 -0
iqm/benchmarks/benchmark.py
CHANGED
|
@@ -109,10 +109,12 @@ class BenchmarkConfigurationBase(BaseModel):
|
|
|
109
109
|
|
|
110
110
|
benchmark: Type[BenchmarkBase]
|
|
111
111
|
shots: int = 2**8
|
|
112
|
+
quantum_computer: str | None = None
|
|
112
113
|
max_gates_per_batch: Optional[int] = None
|
|
113
114
|
max_circuits_per_batch: Optional[int] = None
|
|
114
115
|
calset_id: Optional[str] = None
|
|
115
116
|
routing_method: Literal["basic", "lookahead", "stochastic", "sabre", "none"] = "sabre"
|
|
116
117
|
physical_layout: Literal["fixed", "batching"] = "fixed"
|
|
117
118
|
use_dd: Optional[bool] = False
|
|
119
|
+
active_reset_cycles: int | None = None
|
|
118
120
|
dd_strategy: Optional[DDStrategy] = None
|
|
@@ -254,11 +254,16 @@ class Benchmark(ABC):
|
|
|
254
254
|
qcvv_logger.warning(
|
|
255
255
|
f"Beware that activating dynamical decoupling will change fidelities, error models and their interpretation."
|
|
256
256
|
)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
)
|
|
257
|
+
dd_mode = DDMode.ENABLED
|
|
258
|
+
|
|
260
259
|
else:
|
|
261
|
-
|
|
260
|
+
dd_mode = DDMode.DISABLED
|
|
261
|
+
|
|
262
|
+
self.circuit_compilation_options = CircuitCompilationOptions(
|
|
263
|
+
dd_mode=dd_mode,
|
|
264
|
+
dd_strategy=self.configuration.dd_strategy,
|
|
265
|
+
active_reset_cycles=self.configuration.active_reset_cycles
|
|
266
|
+
)
|
|
262
267
|
|
|
263
268
|
@classmethod
|
|
264
269
|
@abstractmethod
|
|
@@ -294,7 +299,7 @@ class Benchmark(ABC):
|
|
|
294
299
|
"""
|
|
295
300
|
backend_for_execute = copy.copy(self.backend)
|
|
296
301
|
backend_for_execute.run = functools.partial(
|
|
297
|
-
self.backend.run
|
|
302
|
+
self.backend.run
|
|
298
303
|
) # type: ignore
|
|
299
304
|
dataset = self.execute(backend_for_execute)
|
|
300
305
|
run = BenchmarkRunResult(dataset, self.circuits)
|
|
@@ -19,6 +19,7 @@ GHZ state benchmark
|
|
|
19
19
|
from itertools import chain
|
|
20
20
|
from time import strftime
|
|
21
21
|
from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, cast
|
|
22
|
+
import warnings
|
|
22
23
|
|
|
23
24
|
from matplotlib.figure import Figure
|
|
24
25
|
import matplotlib.pyplot as plt
|
|
@@ -27,7 +28,6 @@ from networkx import Graph, all_pairs_shortest_path, is_connected, minimum_spann
|
|
|
27
28
|
import numpy as np
|
|
28
29
|
from qiskit import ClassicalRegister, QuantumRegister
|
|
29
30
|
from qiskit.quantum_info import random_clifford
|
|
30
|
-
from qiskit.transpiler import CouplingMap
|
|
31
31
|
from qiskit_aer import Aer
|
|
32
32
|
from scipy.spatial.distance import hamming
|
|
33
33
|
import xarray as xr
|
|
@@ -45,7 +45,7 @@ from iqm.benchmarks.circuit_containers import BenchmarkCircuit, CircuitGroup, Ci
|
|
|
45
45
|
from iqm.benchmarks.logging_config import qcvv_logger
|
|
46
46
|
from iqm.benchmarks.readout_mitigation import apply_readout_error_mitigation
|
|
47
47
|
from iqm.benchmarks.utils import (
|
|
48
|
-
|
|
48
|
+
extract_fidelities_unified,
|
|
49
49
|
perform_backend_transpilation,
|
|
50
50
|
reduce_to_active_qubits,
|
|
51
51
|
retrieve_all_counts,
|
|
@@ -309,7 +309,7 @@ def generate_ghz_log_cruz(num_qubits: int) -> QuantumCircuit:
|
|
|
309
309
|
|
|
310
310
|
|
|
311
311
|
def generate_ghz_star_optimal(
|
|
312
|
-
qubit_layout: List[int],
|
|
312
|
+
qubit_layout: List[int], iqm_server_url: str, backend: IQMBackendBase, quantum_computer: str, inv: bool = False,
|
|
313
313
|
) -> QuantumCircuit:
|
|
314
314
|
"""
|
|
315
315
|
Generates the circuit for creating a GHZ state by maximizing the number of CZ gates between a pair of MOVE gates.
|
|
@@ -317,10 +317,12 @@ def generate_ghz_star_optimal(
|
|
|
317
317
|
Args:
|
|
318
318
|
qubit_layout: List[int]
|
|
319
319
|
The layout of qubits for the GHZ state.
|
|
320
|
-
|
|
321
|
-
The
|
|
320
|
+
iqm_server_url: str
|
|
321
|
+
The IQM server URL for extracting fidelities.
|
|
322
322
|
backend: IQMBackendBase
|
|
323
323
|
The backend to be used for the quantum circuit.
|
|
324
|
+
quantum_computer: str
|
|
325
|
+
The name of the quantum computer to be used for calbration data, i.e. "garnet", "emerald", ...
|
|
324
326
|
inv: bool
|
|
325
327
|
Whether to generate the inverse circuit.
|
|
326
328
|
|
|
@@ -330,49 +332,48 @@ def generate_ghz_star_optimal(
|
|
|
330
332
|
num_qubits = len(qubit_layout)
|
|
331
333
|
|
|
332
334
|
# Initialize quantum and classical registers
|
|
333
|
-
comp_r = QuantumRegister(1, "comp_r") # Computational resonator
|
|
334
335
|
q = QuantumRegister(backend.num_qubits, "q") # Qubits
|
|
335
336
|
c = ClassicalRegister(num_qubits, "c")
|
|
336
|
-
qc = QuantumCircuit(
|
|
337
|
-
|
|
338
|
-
cal_data =
|
|
337
|
+
qc = QuantumCircuit(q, c, name="GHZ_star_optimal")
|
|
338
|
+
# Extract calibration data
|
|
339
|
+
cal_data = extract_fidelities_unified(iqm_server_url, backend, quantum_computer)
|
|
339
340
|
# Determine the best move qubit
|
|
340
|
-
|
|
341
|
+
double_move_fidelities = {k[0]: v for k, v in list(cal_data[-1]["double_move_gate_fidelity"].items())[::2]}
|
|
342
|
+
move_dict = {q: double_move_fidelities[q + 1] for q in qubit_layout} ## +1 to match qubit indexing in cal data
|
|
343
|
+
# move_dict = {q + 1: cal_data[1][q] for q in qubit_layout} ## +1 to match qubit indexing in cal data
|
|
341
344
|
best_move = max(move_dict, key=move_dict.get)
|
|
342
345
|
|
|
343
|
-
T2 = cal_data[-1]["
|
|
344
|
-
t2_dict = {qubit
|
|
346
|
+
T2 = cal_data[-1]["t2_time"]
|
|
347
|
+
t2_dict = {qubit: T2[qubit + 1] for qubit in qubit_layout} ## +1 to match qubit indexing in cal data
|
|
345
348
|
cz_order = dict(sorted(t2_dict.items(), key=lambda item: item[1], reverse=True))
|
|
346
349
|
qubits_to_measure = list(cz_order.keys())
|
|
347
350
|
cz_order.pop(best_move)
|
|
348
351
|
|
|
349
352
|
# Construct the quantum circuit
|
|
350
|
-
qc.
|
|
351
|
-
qc.
|
|
353
|
+
qc.r(np.pi/2, 3*np.pi/2, best_move)
|
|
354
|
+
qc.barrier(best_move)
|
|
352
355
|
for qubit in cz_order.keys():
|
|
353
|
-
qc.
|
|
354
|
-
qc.
|
|
355
|
-
|
|
356
|
+
qc.barrier(qubit)
|
|
357
|
+
qc.r(np.pi/2, 3*np.pi/2, qubit)
|
|
358
|
+
qc.cz(best_move, qubit)
|
|
359
|
+
qc.r(np.pi/2, 5*np.pi/2, qubit)
|
|
360
|
+
qc.barrier(qubit)
|
|
356
361
|
qc.barrier()
|
|
357
362
|
qc.measure(sorted(qubits_to_measure), list(range(num_qubits)))
|
|
358
|
-
|
|
363
|
+
qcvv_logger.info(f"Best MOVE qubit selected: {best_move} with double MOVE fidelity {move_dict[best_move]:.4f} and T2 time {t2_dict[best_move]:.2f} us.")
|
|
359
364
|
if inv:
|
|
360
|
-
comp_r = QuantumRegister(1, "comp_r") # Computational resonator
|
|
361
365
|
q = QuantumRegister(backend.num_qubits, "q") # Qubits
|
|
362
366
|
c = ClassicalRegister(num_qubits, "c")
|
|
363
|
-
qc = QuantumCircuit(
|
|
364
|
-
|
|
365
|
-
qc.move(best_move, 0)
|
|
367
|
+
qc = QuantumCircuit(q, c, name="GHZ_star_optimal_inv")
|
|
366
368
|
for qubit in reversed(cz_order.keys()):
|
|
367
|
-
qc.
|
|
368
|
-
qc.
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
369
|
+
qc.barrier(qubit)
|
|
370
|
+
qc.r(np.pi/2, 5*np.pi/2, qubit)
|
|
371
|
+
qc.cz(best_move, qubit)
|
|
372
|
+
qc.r(np.pi/2, 3*np.pi/2, qubit)
|
|
373
|
+
qc.barrier(qubit)
|
|
374
|
+
qc.r(np.pi/2, 3*np.pi/2, best_move)
|
|
373
375
|
return qc
|
|
374
376
|
|
|
375
|
-
|
|
376
377
|
def generate_ghz_star(num_qubits: int) -> QuantumCircuit:
|
|
377
378
|
"""
|
|
378
379
|
Generates the circuit for creating a GHZ state by maximizing the number of CZ gates between a pair of MOVE gates.
|
|
@@ -456,7 +457,7 @@ def generate_ghz_spanning_tree(
|
|
|
456
457
|
|
|
457
458
|
|
|
458
459
|
def get_edges(
|
|
459
|
-
coupling_map:
|
|
460
|
+
coupling_map: list[tuple[int]],
|
|
460
461
|
qubit_layout: List[int],
|
|
461
462
|
edges_cal: Optional[List[List[int]]] = None,
|
|
462
463
|
fidelities_cal: Optional[List[float]] = None,
|
|
@@ -482,7 +483,7 @@ def get_edges(
|
|
|
482
483
|
for idx, edge in enumerate(coupling_map):
|
|
483
484
|
if edge[0] in qubit_layout and edge[1] in qubit_layout:
|
|
484
485
|
if not set(edge) in edges_patch:
|
|
485
|
-
edges_patch.append(
|
|
486
|
+
edges_patch.append(edge)
|
|
486
487
|
|
|
487
488
|
if fidelities_cal is not None and edges_cal is not None:
|
|
488
489
|
fidelities_cal = list(
|
|
@@ -491,9 +492,15 @@ def get_edges(
|
|
|
491
492
|
fidelities_patch = []
|
|
492
493
|
for edge in edges_patch:
|
|
493
494
|
for idx, edge_2 in enumerate(edges_cal):
|
|
494
|
-
if edge == set(edge_2):
|
|
495
|
+
if set(edge) == set(edge_2):
|
|
495
496
|
fidelities_patch.append(fidelities_cal[idx])
|
|
496
|
-
|
|
497
|
+
if len(fidelities_patch) != len(edges_patch):
|
|
498
|
+
warnings.warn(
|
|
499
|
+
f"Not all calibration fidelities were found for the selected qubit layout {qubit_layout}, using unweighted graph for circuit creation."
|
|
500
|
+
)
|
|
501
|
+
weights = np.ones(len(edges_patch))
|
|
502
|
+
else:
|
|
503
|
+
weights = -np.log(np.array(fidelities_patch))
|
|
497
504
|
else:
|
|
498
505
|
weights = np.ones(len(edges_patch))
|
|
499
506
|
graph = Graph()
|
|
@@ -646,7 +653,8 @@ class GHZBenchmark(Benchmark):
|
|
|
646
653
|
self.num_RMs = configuration.num_RMs
|
|
647
654
|
self.rem = configuration.rem
|
|
648
655
|
self.mit_shots = configuration.mit_shots
|
|
649
|
-
self.
|
|
656
|
+
self.iqm_server_url = configuration.iqm_server_url
|
|
657
|
+
self.quantum_computer = configuration.quantum_computer
|
|
650
658
|
self.timestamp = strftime("%Y%m%d-%H%M%S")
|
|
651
659
|
self.execution_timestamp = ""
|
|
652
660
|
|
|
@@ -689,8 +697,13 @@ class GHZBenchmark(Benchmark):
|
|
|
689
697
|
qcvv_logger.warning(
|
|
690
698
|
f"The current backend is a star architecture for which a suboptimal state generation routine is chosen. Consider setting state_generation_routine={routine}."
|
|
691
699
|
)
|
|
692
|
-
if self.
|
|
693
|
-
edges_cal, fidelities_cal, _, _ =
|
|
700
|
+
if self.iqm_server_url is not None:
|
|
701
|
+
edges_cal, fidelities_cal, _, _, _ = extract_fidelities_unified(self.iqm_server_url, self.backend, self.quantum_computer)
|
|
702
|
+
# Replace fidelities >= 1.0 with median of fidelities < 1.0
|
|
703
|
+
valid_fidelities = [f for f in fidelities_cal if f < 1.0]
|
|
704
|
+
if valid_fidelities:
|
|
705
|
+
median_fidelity = np.median(valid_fidelities)
|
|
706
|
+
fidelities_cal = [f if f < 1.0 else median_fidelity for f in fidelities_cal]
|
|
694
707
|
graph = get_edges(self.backend.coupling_map, qubit_layout, edges_cal, fidelities_cal)
|
|
695
708
|
else:
|
|
696
709
|
graph = get_edges(self.backend.coupling_map, qubit_layout)
|
|
@@ -718,15 +731,14 @@ class GHZBenchmark(Benchmark):
|
|
|
718
731
|
)
|
|
719
732
|
final_ghz = ghz_native_transpiled
|
|
720
733
|
elif routine == "star_optimal":
|
|
721
|
-
if self.
|
|
722
|
-
raise ValueError("
|
|
723
|
-
|
|
734
|
+
if self.iqm_server_url is None or self.quantum_computer is None:
|
|
735
|
+
raise ValueError("IQM server url and quantum_computer argument must be provided "
|
|
736
|
+
"for 'star_optimal' routine.")
|
|
737
|
+
ghz = generate_ghz_star_optimal(qubit_layout, self.iqm_server_url, self.backend, self.quantum_computer)
|
|
724
738
|
circuit_group.add_circuit(ghz)
|
|
725
739
|
ghz_native_transpiled = transpile_to_IQM(
|
|
726
740
|
ghz,
|
|
727
741
|
self.backend,
|
|
728
|
-
existing_moves_handling=True,
|
|
729
|
-
perform_move_routing=False,
|
|
730
742
|
optimize_single_qubits=self.optimize_sqg,
|
|
731
743
|
optimization_level=self.qiskit_optim_level,
|
|
732
744
|
)
|
|
@@ -775,7 +787,7 @@ class GHZBenchmark(Benchmark):
|
|
|
775
787
|
qc.remove_final_measurements()
|
|
776
788
|
phases = [np.pi * i / (qubit_count + 1) for i in range(2 * qubit_count + 2)]
|
|
777
789
|
if self.state_generation_routine == "star_optimal":
|
|
778
|
-
qc_inv = generate_ghz_star_optimal(qubit_layout, self.
|
|
790
|
+
qc_inv = generate_ghz_star_optimal(qubit_layout, self.iqm_server_url, self.backend, self.quantum_computer, inv=True)
|
|
779
791
|
for phase in phases:
|
|
780
792
|
qc_phase = qc.copy()
|
|
781
793
|
qc_phase.barrier()
|
|
@@ -804,8 +816,6 @@ class GHZBenchmark(Benchmark):
|
|
|
804
816
|
transpile_to_IQM(
|
|
805
817
|
ghz,
|
|
806
818
|
self.backend,
|
|
807
|
-
existing_moves_handling=True,
|
|
808
|
-
perform_move_routing=False,
|
|
809
819
|
optimize_single_qubits=self.optimize_sqg,
|
|
810
820
|
optimization_level=self.qiskit_optim_level,
|
|
811
821
|
)
|
|
@@ -1026,7 +1036,7 @@ class GHZConfiguration(BenchmarkConfigurationBase):
|
|
|
1026
1036
|
* Default: True
|
|
1027
1037
|
mit_shots (int): Total number of shots for readout error mitigation
|
|
1028
1038
|
* Default: 1000
|
|
1029
|
-
|
|
1039
|
+
iqm_server_url (Optional[str]): Optional iqm server URL where the calibration data for the selected backend can be retrieved from
|
|
1030
1040
|
The calibration data is used for the "tree" state generation routine to prioritize couplings with high
|
|
1031
1041
|
CZ fidelity.
|
|
1032
1042
|
* Default: None
|
|
@@ -1043,4 +1053,4 @@ class GHZConfiguration(BenchmarkConfigurationBase):
|
|
|
1043
1053
|
num_RMs: Optional[int] = 100
|
|
1044
1054
|
rem: bool = True
|
|
1045
1055
|
mit_shots: int = 1_000
|
|
1046
|
-
|
|
1056
|
+
iqm_server_url: Optional[str] = None
|
|
@@ -170,15 +170,23 @@ def retrieve_clops_elapsed_times(job_meta: Dict[str, Dict[str, Any]]) -> Dict[st
|
|
|
170
170
|
# ["timestamps"] might be empty if backend is a simulator
|
|
171
171
|
if job_meta[update][batch]["timestamps"] is not None:
|
|
172
172
|
x = job_meta[update][batch]["timestamps"]
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
173
|
+
|
|
174
|
+
# Check if timestamps need parsing or are already datetime objects
|
|
175
|
+
if isinstance(x["compilation_ended"], str):
|
|
176
|
+
job_time_format = "%Y-%m-%dT%H:%M:%S.%f%z"
|
|
177
|
+
compile_f = datetime.strptime(x["compilation_ended"], job_time_format)
|
|
178
|
+
compile_i = datetime.strptime(x["compilation_started"], job_time_format)
|
|
179
|
+
execution_f = datetime.strptime(x["execution_ended"], job_time_format)
|
|
180
|
+
execution_i = datetime.strptime(x["execution_started"], job_time_format)
|
|
181
|
+
job_f = datetime.strptime(x["ready"], job_time_format)
|
|
182
|
+
job_i = datetime.strptime(x["received"], job_time_format)
|
|
183
|
+
else:
|
|
184
|
+
compile_f = x["compilation_ended"]
|
|
185
|
+
compile_i = x["compilation_started"]
|
|
186
|
+
execution_f = x["execution_ended"]
|
|
187
|
+
execution_i = x["execution_started"]
|
|
188
|
+
job_f = x["ready"]
|
|
189
|
+
job_i = x["received"]
|
|
182
190
|
|
|
183
191
|
all_job_elapsed[update][batch] = {
|
|
184
192
|
"job_total": job_f - job_i,
|
|
@@ -187,6 +195,7 @@ def retrieve_clops_elapsed_times(job_meta: Dict[str, Dict[str, Any]]) -> Dict[st
|
|
|
187
195
|
"execution_total": execution_f - execution_i,
|
|
188
196
|
}
|
|
189
197
|
|
|
198
|
+
|
|
190
199
|
# Save the keys, will be needed later
|
|
191
200
|
totals_keys = all_job_elapsed[update][batch].keys()
|
|
192
201
|
|
|
@@ -574,6 +583,7 @@ class CLOPSBenchmark(Benchmark):
|
|
|
574
583
|
# Retrieve and save all job metadata
|
|
575
584
|
all_job_metadata = retrieve_all_job_metadata(all_jobs)
|
|
576
585
|
self.job_meta_per_update["update_" + str(update + 1)] = all_job_metadata
|
|
586
|
+
self.all_jobs = all_jobs
|
|
577
587
|
|
|
578
588
|
return time_parameter_assign, time_submit, time_retrieve
|
|
579
589
|
|
|
@@ -470,6 +470,7 @@ class QuantumVolumeBenchmark(Benchmark):
|
|
|
470
470
|
|
|
471
471
|
self.qiskit_optim_level = configuration.qiskit_optim_level
|
|
472
472
|
self.optimize_sqg = configuration.optimize_sqg
|
|
473
|
+
self.approximation_degree = configuration.approximation_degree
|
|
473
474
|
|
|
474
475
|
self.rem = configuration.rem
|
|
475
476
|
self.mit_shots = configuration.mit_shots
|
|
@@ -529,65 +530,6 @@ class QuantumVolumeBenchmark(Benchmark):
|
|
|
529
530
|
}
|
|
530
531
|
dataset.attrs[key] = dictionary
|
|
531
532
|
|
|
532
|
-
# def get_mapomatic_average_qv_scores(self) -> List[List[int]]:
|
|
533
|
-
# """Estimate the average mapomatic scores for N quantum volume circuit samples
|
|
534
|
-
# Returns:
|
|
535
|
-
# List[List[object]]: the mapomatic layout scores sorted from the smallest mean*(1+std/sqrt(N)) cost score
|
|
536
|
-
# """
|
|
537
|
-
# qv_circ_samples = self.mapomatic_qv_samples
|
|
538
|
-
#
|
|
539
|
-
# # Get calibration data once
|
|
540
|
-
# token = input("Trying to access IQM calibration data\nEnter your IQM token (without quote marks): ")
|
|
541
|
-
# calibration_data = get_calibration_fidelities(self.backend.architecture.name, token)
|
|
542
|
-
#
|
|
543
|
-
# qcvv_logger.info(
|
|
544
|
-
# "Evaluating matching layouts for QV",
|
|
545
|
-
# )
|
|
546
|
-
#
|
|
547
|
-
# all_scores: Dict[Tuple, List[float]] = {}
|
|
548
|
-
# for mapomatic_qv_sample in range(qv_circ_samples):
|
|
549
|
-
# qcvv_logger.info(
|
|
550
|
-
# f"Estimating layout costs for QV circuit sample {mapomatic_qv_sample+1}"
|
|
551
|
-
# )
|
|
552
|
-
# # Generate a representative quantum circuit sample
|
|
553
|
-
# qv_circ = get_circuit("quantum_volume", self.mapomatic_num_qubits)
|
|
554
|
-
# # Get all matching layouts
|
|
555
|
-
# layouts = matching_layouts(
|
|
556
|
-
# qv_circ,
|
|
557
|
-
# self.backend,
|
|
558
|
-
# self.backend.coupling_map,
|
|
559
|
-
# self.qiskit_optim_level,
|
|
560
|
-
# )
|
|
561
|
-
# # Evaluate all layouts
|
|
562
|
-
# scores = evaluate_costs(
|
|
563
|
-
# layouts,
|
|
564
|
-
# qv_circ,
|
|
565
|
-
# self.backend,
|
|
566
|
-
# calibration_data,
|
|
567
|
-
# self.qiskit_optim_level,
|
|
568
|
-
# )
|
|
569
|
-
# for score in scores:
|
|
570
|
-
# all_scores.setdefault(tuple(cast(list[int], score[0])), []).extend([cast(float, score[1])])
|
|
571
|
-
# qv_circ.clear()
|
|
572
|
-
#
|
|
573
|
-
# # Consider mean and std of the cost scores as mean*(1+std/sqrt(N))
|
|
574
|
-
# all_scores_mean_plus_std = {
|
|
575
|
-
# s_k: np.mean(s_v) * (1 + np.std(s_v) / np.sqrt(qv_circ_samples)) for s_k, s_v in all_scores.items()
|
|
576
|
-
# }
|
|
577
|
-
# # Turn into an array ([[tuple_layout0, score0], [tuple_layout1,score1], ... ])
|
|
578
|
-
# sorted_scores_mean_plus_std = list(sorted(all_scores_mean_plus_std.items(), key=lambda y: y[1]))
|
|
579
|
-
# # Return indices to list type for layouts ([[list_layout0, score0], [list_layout1,score1], ... ])
|
|
580
|
-
# layout_meanscore = [[list(s[0]), s[1]] for s in sorted_scores_mean_plus_std]
|
|
581
|
-
#
|
|
582
|
-
# mapomatic_qv_layouts = [x[0] for x in layout_meanscore[: self.mapomatic_num_layouts]]
|
|
583
|
-
# mapomatic_qv_costs = [x[1] for x in layout_meanscore[: self.mapomatic_num_layouts]]
|
|
584
|
-
#
|
|
585
|
-
# qcvv_logger.info(
|
|
586
|
-
# f"Will execute QV on layouts {mapomatic_qv_layouts}, of mapomatic average costs {mapomatic_qv_costs}"
|
|
587
|
-
# )
|
|
588
|
-
#
|
|
589
|
-
# return mapomatic_qv_layouts
|
|
590
|
-
|
|
591
533
|
@staticmethod
|
|
592
534
|
def generate_single_circuit(
|
|
593
535
|
num_qubits: int,
|
|
@@ -755,6 +697,7 @@ class QuantumVolumeBenchmark(Benchmark):
|
|
|
755
697
|
qiskit_optim_level=self.qiskit_optim_level,
|
|
756
698
|
optimize_sqg=self.optimize_sqg,
|
|
757
699
|
routing_method=self.routing_method,
|
|
700
|
+
approximation_degree=self.approximation_degree,
|
|
758
701
|
)
|
|
759
702
|
# Batching
|
|
760
703
|
sorted_transpiled_qc_list: Dict[Tuple[int, ...], List[QuantumCircuit]] = {}
|
|
@@ -845,27 +788,23 @@ class QuantumVolumeConfiguration(BenchmarkConfigurationBase):
|
|
|
845
788
|
Attributes:
|
|
846
789
|
benchmark (Type[Benchmark]): QuantumVolumeBenchmark
|
|
847
790
|
num_circuits (int): The number of circuits to use.
|
|
848
|
-
|
|
791
|
+
Should be at least 100 for a meaningful QV experiment.
|
|
849
792
|
num_sigmas (int): The number of sample standard deviations to consider with for the threshold criteria.
|
|
850
|
-
|
|
793
|
+
Default by consensus is 2
|
|
851
794
|
choose_qubits_routine (Literal["custom"]): The routine to select qubit layouts.
|
|
852
|
-
|
|
795
|
+
Default is "custom".
|
|
853
796
|
custom_qubits_array (Optional[Sequence[Sequence[int]]]): The physical qubit layouts to perform the benchmark on.
|
|
854
|
-
|
|
797
|
+
Default is [[0, 2]].
|
|
855
798
|
qiskit_optim_level (int): The Qiskit transpilation optimization level.
|
|
856
|
-
|
|
799
|
+
Default is 3.
|
|
857
800
|
optimize_sqg (bool): Whether Single Qubit Gate Optimization is performed upon transpilation.
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
- "batching": Considers the full coupling map of the backend and circuit execution is batched per final layout.
|
|
864
|
-
* Default is "fixed"
|
|
865
|
-
rem (bool): Whether Readout Error Mitigation is applied in post-processing. When set to True, both results (readout-unmitigated and -mitigated) are produced.
|
|
866
|
-
- Default is True.
|
|
801
|
+
Default is True.
|
|
802
|
+
approximation_degree (float): The target fidelity to which arbitrary two qubit gates are approximated.
|
|
803
|
+
rem (bool): Whether Readout Error Mitigation is applied in post-processing. When set to True, both results
|
|
804
|
+
(readout-unmitigated and -mitigated) are produced.
|
|
805
|
+
Default is True.
|
|
867
806
|
mit_shots (int): The measurement shots to use for readout calibration.
|
|
868
|
-
|
|
807
|
+
Default is 1_000.
|
|
869
808
|
"""
|
|
870
809
|
|
|
871
810
|
benchmark: Type[Benchmark] = QuantumVolumeBenchmark
|
|
@@ -875,5 +814,6 @@ class QuantumVolumeConfiguration(BenchmarkConfigurationBase):
|
|
|
875
814
|
custom_qubits_array: Sequence[Sequence[int]]
|
|
876
815
|
qiskit_optim_level: int = 3
|
|
877
816
|
optimize_sqg: bool = True
|
|
817
|
+
approximation_degree: float = 1.0
|
|
878
818
|
rem: bool = True
|
|
879
819
|
mit_shots: int = 1_000
|
|
@@ -245,7 +245,8 @@ class EPLGBenchmark(Benchmark):
|
|
|
245
245
|
self.chain_length = configuration.chain_length
|
|
246
246
|
self.chain_path_samples = configuration.chain_path_samples
|
|
247
247
|
self.num_disjoint_layers = configuration.num_disjoint_layers
|
|
248
|
-
self.
|
|
248
|
+
self.iqm_server_url = configuration.iqm_server_url
|
|
249
|
+
self.quantum_computer = configuration.quantum_computer
|
|
249
250
|
self.max_hamiltonian_path_tries = configuration.max_hamiltonian_path_tries
|
|
250
251
|
|
|
251
252
|
def add_all_meta_to_dataset(self, dataset: xr.Dataset):
|
|
@@ -298,8 +299,8 @@ class EPLGBenchmark(Benchmark):
|
|
|
298
299
|
raise ValueError("The number of chain path samples must be a positive integer.")
|
|
299
300
|
|
|
300
301
|
# Check calibration URL - this is a temporary solution, normally the backend should be enough to specify this
|
|
301
|
-
if self.
|
|
302
|
-
raise ValueError("The
|
|
302
|
+
if self.iqm_server_url is None:
|
|
303
|
+
raise ValueError("The IQM server URL must be specified if custom qubits array is not specified.")
|
|
303
304
|
|
|
304
305
|
if self.num_disjoint_layers is None:
|
|
305
306
|
self.num_disjoint_layers = 2
|
|
@@ -332,11 +333,14 @@ class EPLGBenchmark(Benchmark):
|
|
|
332
333
|
self.validate_random_chain_inputs()
|
|
333
334
|
num_qubits = cast(int, self.chain_length)
|
|
334
335
|
qcvv_logger.info("Generating linear chain path")
|
|
336
|
+
if self.iqm_server_url is None or self.quantum_computer is None:
|
|
337
|
+
raise ValueError("IQM server URL and quantum computer name must be specified for random chain evaluation.")
|
|
335
338
|
h_path_costs = evaluate_hamiltonian_paths(
|
|
336
339
|
self.chain_length,
|
|
337
340
|
self.chain_path_samples,
|
|
338
341
|
self.backend,
|
|
339
|
-
self.
|
|
342
|
+
self.iqm_server_url,
|
|
343
|
+
self.quantum_computer,
|
|
340
344
|
self.max_hamiltonian_path_tries,
|
|
341
345
|
)
|
|
342
346
|
qcvv_logger.info("Extracting the path that maximizes total 2Q calibration fidelity")
|
|
@@ -391,7 +395,7 @@ class EPLGConfiguration(BenchmarkConfigurationBase):
|
|
|
391
395
|
* Default is None: assigns 2 disjoint layers (arbitrary).
|
|
392
396
|
max_hamiltonian_path_tries (Optional[int]): The maximum number of tries to find a Hamiltonian path.
|
|
393
397
|
* Default is None: assigns 10 tries (arbitrary).
|
|
394
|
-
|
|
398
|
+
iqm_server_url (Optional[str]): The URL of the IQM station to retrieve calibration data from.
|
|
395
399
|
* It must be specified if custom_qubits_array is not specified.
|
|
396
400
|
* Default is None - raises an error if custom_qubits_array is not specified.
|
|
397
401
|
|
|
@@ -405,4 +409,4 @@ class EPLGConfiguration(BenchmarkConfigurationBase):
|
|
|
405
409
|
chain_path_samples: Optional[int] = None
|
|
406
410
|
num_disjoint_layers: Optional[int] = None
|
|
407
411
|
max_hamiltonian_path_tries: Optional[int] = None
|
|
408
|
-
|
|
412
|
+
iqm_server_url: Optional[str] = None
|
iqm/benchmarks/utils.py
CHANGED
|
@@ -16,11 +16,13 @@
|
|
|
16
16
|
General utility functions
|
|
17
17
|
"""
|
|
18
18
|
from collections import defaultdict
|
|
19
|
+
from enum import Enum
|
|
19
20
|
from functools import wraps
|
|
20
21
|
import itertools
|
|
21
22
|
from math import floor
|
|
22
23
|
import os
|
|
23
24
|
import random
|
|
25
|
+
import re
|
|
24
26
|
from time import time
|
|
25
27
|
from typing import Any, Dict, Iterable, List, Literal, Optional, Sequence, Set, Tuple, Union, cast
|
|
26
28
|
import warnings
|
|
@@ -38,6 +40,7 @@ import requests
|
|
|
38
40
|
import xarray as xr
|
|
39
41
|
|
|
40
42
|
from iqm.benchmarks.logging_config import qcvv_logger
|
|
43
|
+
from iqm.iqm_client import IQMClient
|
|
41
44
|
from iqm.iqm_client.models import CircuitCompilationOptions
|
|
42
45
|
from iqm.qiskit_iqm import IQMCircuit as QuantumCircuit
|
|
43
46
|
from iqm.qiskit_iqm import IQMFakeDeneb, optimize_single_qubit_gates, transpile_to_IQM
|
|
@@ -286,11 +289,23 @@ def get_active_qubits(qc: QuantumCircuit) -> List[int]:
|
|
|
286
289
|
return list(active_qubits)
|
|
287
290
|
|
|
288
291
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
"""
|
|
292
|
+
class ObservationType(Enum):
|
|
293
|
+
"""Enumeration representing relevant keys to fetch for each operation in the observations."""
|
|
294
|
+
|
|
295
|
+
CZ = "cz"
|
|
296
|
+
CLIFFORD = ("cz", "clifford")
|
|
297
|
+
SQG = "prx"
|
|
298
|
+
READOUT = ("measure_fidelity", ".fidelity")
|
|
299
|
+
READOUT_QNDNESS = ("measure", "qndness", ".fidelity")
|
|
300
|
+
DOUBLE_MOVE = "move"
|
|
301
|
+
T1 = ("t1", "QB")
|
|
302
|
+
T2 = ("t2", "QB")
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def extract_fidelities_unified(
|
|
306
|
+
iqm_server_url: str, backend: IQMBackendBase, quantum_computer: str
|
|
307
|
+
) -> tuple[list[list[int]], list[float], str, dict[Any, int], dict[str, dict[int | tuple[int, int], float]]]:
|
|
308
|
+
"""Returns couplings and CZ-fidelities from calibration data URL for external station API
|
|
294
309
|
|
|
295
310
|
Args:
|
|
296
311
|
cal_url: str
|
|
@@ -304,73 +319,93 @@ def extract_fidelities(cal_url: str, all_metrics: bool = False) -> Union[
|
|
|
304
319
|
data contains a fidelity.
|
|
305
320
|
list_fids: List[float]
|
|
306
321
|
A list of CZ fidelities from the calibration url, ordered in the same way as list_couplings
|
|
307
|
-
topology: str
|
|
308
|
-
Name of the chip topology layout, currently either "star" or "crystal"
|
|
309
|
-
qubit_mapping: Dict[int, int]
|
|
310
|
-
Enumerating all calibrated qubits starting from 0. For instance if on a 5 qubit chip the qubits 2, 3 are calibrated,
|
|
311
|
-
the mapping will be {2: 0, 3: 1}.
|
|
312
322
|
metrics_dict: Dict
|
|
313
323
|
Dictionary of all metrics (returned only if all_metrics=True)
|
|
314
324
|
Format: {metric_name: {qubit: value}} for single qubit metrics
|
|
315
325
|
Format: {metric_name: {(qubit_1, qubit_2): value}} for two qubit metrics
|
|
316
326
|
"""
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
|
|
327
|
+
# Create dictionaries to map key names to their corresponding metrics
|
|
328
|
+
cz_fidelity: Dict[Union[int, Tuple[int, int]], float] = {}
|
|
329
|
+
single_qubit_fidelity: Dict[int, float] = {}
|
|
330
|
+
readout_fidelity: Dict[int, float] = {}
|
|
331
|
+
t1: Dict[int, float] = {}
|
|
332
|
+
t2: Dict[int, float] = {}
|
|
333
|
+
move_fidelity: Dict[Tuple[int, int], float] = {}
|
|
334
|
+
quality_metric_set = IQMClient(iqm_server_url, quantum_computer=quantum_computer).get_quality_metric_set()
|
|
335
|
+
calibration_metrics = quality_metric_set.observations
|
|
336
|
+
|
|
324
337
|
list_couplings = []
|
|
325
338
|
list_fids = []
|
|
326
|
-
|
|
327
|
-
|
|
339
|
+
gates_info: Dict[str, Dict[str, Any]] = {}
|
|
340
|
+
for gate in backend.architecture.gates.keys():
|
|
341
|
+
gates_info[gate] = {
|
|
342
|
+
x: backend.architecture.gates[gate].implementations[x].loci
|
|
343
|
+
for x in backend.architecture.gates[gate].implementations.keys()
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if backend.has_resonators():
|
|
328
347
|
topology = "star"
|
|
329
348
|
else:
|
|
330
|
-
i, j = cal_keys["cz_gate_fidelity"]
|
|
331
349
|
topology = "crystal"
|
|
332
|
-
for item in calibration["calibrations"][i]["metrics"][j]["metrics"]:
|
|
333
|
-
qb1 = (
|
|
334
|
-
int(item["locus"][0][2:])
|
|
335
|
-
if not any(resonator in item["locus"][0] for resonator in resonator_names)
|
|
336
|
-
else 0
|
|
337
|
-
)
|
|
338
|
-
qb2 = (
|
|
339
|
-
int(item["locus"][1][2:])
|
|
340
|
-
if not any(resonator in item["locus"][1] for resonator in resonator_names)
|
|
341
|
-
else 0
|
|
342
|
-
)
|
|
343
|
-
list_couplings.append([qb1, qb2])
|
|
344
|
-
list_fids.append(float(item["value"]))
|
|
345
|
-
calibrated_qubits = set(np.array(list_couplings).reshape(-1))
|
|
346
|
-
|
|
347
|
-
# Process all metrics if all_metrics is True
|
|
348
|
-
metrics_dict: Dict[str, Dict[Union[int, Tuple[int, int]], float]] = {}
|
|
349
|
-
for metric_key, (i, j) in cal_keys.items():
|
|
350
|
-
metric_data = calibration["calibrations"][i]["metrics"][j]["metrics"]
|
|
351
|
-
metrics_dict[metric_key] = {}
|
|
352
|
-
|
|
353
|
-
for item in metric_data:
|
|
354
|
-
# Determine if it's a single or two-qubit metric
|
|
355
|
-
if "component" in item:
|
|
356
|
-
# Single qubit metric
|
|
357
|
-
component = item["component"]
|
|
358
|
-
if not any(resonator in component for resonator in resonator_names):
|
|
359
|
-
qb = int(component[2:])
|
|
360
|
-
metrics_dict[metric_key][qb] = float(item["value"])
|
|
361
|
-
calibrated_qubits.add(qb) # Add qubits that have a single qubit metric
|
|
362
|
-
if "locus" in item and len(item["locus"]) == 2:
|
|
363
|
-
# Two qubit metric
|
|
364
|
-
locus = item["locus"]
|
|
365
|
-
if not (any(resonator in locus[0] for resonator in resonator_names) or any(resonator in locus[1] for resonator in resonator_names)):
|
|
366
|
-
qb1 = int(locus[0][2:])
|
|
367
|
-
qb2 = int(locus[1][2:])
|
|
368
|
-
metrics_dict[metric_key][(qb1, qb2)] = float(item["value"])
|
|
369
350
|
|
|
351
|
+
# Iterate over the calibration metrics
|
|
352
|
+
for metrics in calibration_metrics:
|
|
353
|
+
dut_field = metrics.dut_field
|
|
354
|
+
values = metrics.value
|
|
355
|
+
if all(obs in dut_field for obs in ObservationType.READOUT.value):
|
|
356
|
+
qubit_index = int(dut_field.split("QB")[1].split(".")[0])
|
|
357
|
+
readout_fidelity[qubit_index] = values
|
|
358
|
+
elif ObservationType.SQG.value in dut_field and any(
|
|
359
|
+
x in dut_field for x in gates_info[ObservationType.SQG.value]
|
|
360
|
+
):
|
|
361
|
+
qubit_index = int(dut_field.split("QB")[1].split(".")[0])
|
|
362
|
+
single_qubit_fidelity[qubit_index] = values
|
|
363
|
+
elif all(obs in dut_field for obs in ObservationType.T1.value):
|
|
364
|
+
qubit_index = int(dut_field.split("QB")[1].split(".")[0])
|
|
365
|
+
t1[qubit_index] = values * 10**6
|
|
366
|
+
elif all(obs in dut_field for obs in ObservationType.T2.value):
|
|
367
|
+
qubit_index = int(dut_field.split("QB")[1].split(".")[0])
|
|
368
|
+
t2[qubit_index] = values * 10**6
|
|
369
|
+
elif ObservationType.DOUBLE_MOVE.value in dut_field and any(
|
|
370
|
+
x in dut_field for x in gates_info[ObservationType.DOUBLE_MOVE.value]
|
|
371
|
+
):
|
|
372
|
+
qb_matches = re.findall(r"QB\d+", dut_field)
|
|
373
|
+
qbx = int(qb_matches[0].split("QB")[1])
|
|
374
|
+
move_fidelity[(qbx, 0)] = values
|
|
375
|
+
move_fidelity[(0, qbx)] = values
|
|
376
|
+
elif (
|
|
377
|
+
ObservationType.CZ.value in dut_field
|
|
378
|
+
and any(x in dut_field for x in gates_info[ObservationType.CZ.value])
|
|
379
|
+
and backend.has_resonators()
|
|
380
|
+
):
|
|
381
|
+
qb_matches = re.findall(r"QB\d+", dut_field)
|
|
382
|
+
qbx = int(qb_matches[0].split("QB")[1])
|
|
383
|
+
list_couplings.append([qbx, 0])
|
|
384
|
+
list_fids.append(values)
|
|
385
|
+
cz_fidelity[(qbx, 0)] = values
|
|
386
|
+
cz_fidelity[(0, qbx)] = values
|
|
387
|
+
elif ObservationType.CZ.value in dut_field and any(
|
|
388
|
+
x in dut_field for x in gates_info[ObservationType.CZ.value]
|
|
389
|
+
):
|
|
390
|
+
qb_matches = re.findall(r"QB\d+", dut_field)
|
|
391
|
+
qbx, qby = int(qb_matches[0].split("QB")[1]), int(qb_matches[1].split("QB")[1])
|
|
392
|
+
cz_fidelity[(qbx, qby)] = values
|
|
393
|
+
cz_fidelity[(qby, qbx)] = values
|
|
394
|
+
list_couplings.append([qbx, qby])
|
|
395
|
+
list_fids.append(values)
|
|
396
|
+
|
|
397
|
+
metrics_dict: Dict[str, Dict[Union[int, Tuple[int, int]], float]] = {
|
|
398
|
+
"cz_gate_fidelity": cz_fidelity,
|
|
399
|
+
"fidelity_1qb_gates_averaged": single_qubit_fidelity,
|
|
400
|
+
"single_shot_readout_fidelity": readout_fidelity,
|
|
401
|
+
"t1_time": t1,
|
|
402
|
+
"t2_time": t2,
|
|
403
|
+
"double_move_gate_fidelity": move_fidelity,
|
|
404
|
+
}
|
|
370
405
|
# Enumerate all calibrated qubits starting from 0
|
|
406
|
+
calibrated_qubits = set(np.array(list_couplings).reshape(-1))
|
|
371
407
|
qubit_mapping = {qubit: idx for idx, qubit in enumerate(calibrated_qubits)}
|
|
372
408
|
list_couplings = [[qubit_mapping[edge[0]], qubit_mapping[edge[1]]] for edge in list_couplings]
|
|
373
|
-
|
|
374
409
|
# Apply the qubit mapping to metrics_dict
|
|
375
410
|
remapped_metrics_dict = {}
|
|
376
411
|
for metric_key, metric_values in metrics_dict.items():
|
|
@@ -384,10 +419,6 @@ def extract_fidelities(cal_url: str, all_metrics: bool = False) -> Union[
|
|
|
384
419
|
remapped_metrics_dict[metric_key][qubit_mapping[key]] = value
|
|
385
420
|
metrics_dict = remapped_metrics_dict
|
|
386
421
|
|
|
387
|
-
# If all_metrics is False, only return everything related to CZ fidelites
|
|
388
|
-
if not all_metrics:
|
|
389
|
-
return list_couplings, list_fids, topology, qubit_mapping
|
|
390
|
-
|
|
391
422
|
return list_couplings, list_fids, topology, qubit_mapping, metrics_dict
|
|
392
423
|
|
|
393
424
|
|
|
@@ -606,6 +637,7 @@ def perform_backend_transpilation(
|
|
|
606
637
|
optimize_sqg: bool = False,
|
|
607
638
|
drop_final_rz: bool = True,
|
|
608
639
|
routing_method: Optional[str] = "sabre",
|
|
640
|
+
approximation_degree: float = 1.0,
|
|
609
641
|
) -> List[QuantumCircuit]:
|
|
610
642
|
"""
|
|
611
643
|
Transpile a list of circuits to backend specifications.
|
|
@@ -620,6 +652,7 @@ def perform_backend_transpilation(
|
|
|
620
652
|
optimize_sqg (bool): Whether SQG optimization is performed taking into account virtual Z.
|
|
621
653
|
drop_final_rz (bool): Whether the SQG optimizer drops a final RZ gate.
|
|
622
654
|
routing_method (Optional[str]): The routing method employed by Qiskit's transpilation pass.
|
|
655
|
+
approximation_degree (int): The target fidelity to which arbitrary two qubit gates are approximated.
|
|
623
656
|
|
|
624
657
|
Returns:
|
|
625
658
|
List[QuantumCircuit]: A list of transpiled quantum circuits.
|
|
@@ -641,6 +674,7 @@ def perform_backend_transpilation(
|
|
|
641
674
|
optimize_single_qubits=optimize_sqg,
|
|
642
675
|
remove_final_rzs=drop_final_rz,
|
|
643
676
|
coupling_map=coupling_map_red,
|
|
677
|
+
approximation_degree=approximation_degree,
|
|
644
678
|
# initial_layout=qubits if aux_qc is None else None,
|
|
645
679
|
)
|
|
646
680
|
else:
|
|
@@ -651,6 +685,7 @@ def perform_backend_transpilation(
|
|
|
651
685
|
optimization_level=qiskit_optim_level,
|
|
652
686
|
initial_layout=qubits if aux_qc is None else None,
|
|
653
687
|
routing_method=routing_method,
|
|
688
|
+
approximation_degree=approximation_degree,
|
|
654
689
|
)
|
|
655
690
|
if aux_qc is not None:
|
|
656
691
|
transpiled = aux_qc.compose(transpiled, qubits=qubits, clbits=list(range(qc.num_clbits)))
|
|
@@ -797,31 +832,45 @@ def retrieve_all_counts(iqm_jobs: List[IQMJob], identifier: Optional[str] = None
|
|
|
797
832
|
|
|
798
833
|
|
|
799
834
|
def retrieve_all_job_metadata(
|
|
800
|
-
iqm_jobs:
|
|
801
|
-
) ->
|
|
802
|
-
"""Retrieve the
|
|
835
|
+
iqm_jobs: list[IQMJob],
|
|
836
|
+
) -> dict[str, dict[str, Any]]:
|
|
837
|
+
"""Retrieve the metadata from a list of Job objects.
|
|
838
|
+
|
|
803
839
|
Args:
|
|
804
|
-
iqm_jobs List[IQMJob]
|
|
840
|
+
iqm_jobs : List[IQMJob]
|
|
841
|
+
The list of IQMJob objects.
|
|
805
842
|
|
|
806
843
|
Returns:
|
|
807
844
|
Dict[str, Dict[str, Any]]: Relevant metadata of all the IQMJob objects.
|
|
845
|
+
|
|
808
846
|
"""
|
|
809
847
|
all_meta = {}
|
|
810
|
-
|
|
811
848
|
for index, j in enumerate(iqm_jobs):
|
|
812
849
|
all_attributes_j = dir(j)
|
|
850
|
+
if not hasattr(j, "_iqm_job"):
|
|
851
|
+
shots = j.metadata["shots"] if "shots" in j.metadata.keys() else None
|
|
852
|
+
timestamps = j.metadata["timestamps"] if "timestamps" in j.metadata.keys() else None
|
|
853
|
+
else:
|
|
854
|
+
job_parameters = j._iqm_job._parameters
|
|
855
|
+
if job_parameters is not None:
|
|
856
|
+
shots = job_parameters.shots if "shots" in job_parameters.__dict__.keys() else None
|
|
857
|
+
else:
|
|
858
|
+
raise ValueError("Job parameters return None, cannot retrieve shots information.")
|
|
859
|
+
timestamps = {}
|
|
860
|
+
for entry in j._iqm_job.data.timeline:
|
|
861
|
+
timestamps.update({entry.status: entry.timestamp})
|
|
813
862
|
all_meta.update(
|
|
814
863
|
{
|
|
815
864
|
"batch_job_"
|
|
816
865
|
+ str(index + 1): {
|
|
817
866
|
"job_id": j.job_id() if "job_id" in all_attributes_j else None,
|
|
818
|
-
"backend": j.backend().name if "backend" in all_attributes_j else None,
|
|
819
|
-
"status": j.status().value if "status" in all_attributes_j else None,
|
|
867
|
+
"backend": (j.backend().name if "backend" in all_attributes_j else None),
|
|
868
|
+
"status": (j.status().value if "status" in all_attributes_j else None),
|
|
820
869
|
"circuits_in_batch": (
|
|
821
|
-
len(cast(
|
|
870
|
+
len(cast(list, j.circuit_metadata)) if "circuit_metadata" in all_attributes_j else None
|
|
822
871
|
),
|
|
823
|
-
"shots":
|
|
824
|
-
"timestamps":
|
|
872
|
+
"shots": shots,
|
|
873
|
+
"timestamps": timestamps,
|
|
825
874
|
}
|
|
826
875
|
}
|
|
827
876
|
)
|
iqm/benchmarks/utils_plots.py
CHANGED
|
@@ -25,11 +25,11 @@ import matplotlib.pyplot as plt
|
|
|
25
25
|
import networkx as nx
|
|
26
26
|
import numpy as np
|
|
27
27
|
from qiskit.transpiler import CouplingMap
|
|
28
|
-
import requests
|
|
29
28
|
from rustworkx import PyGraph, spring_layout, visualization # pylint: disable=no-name-in-module
|
|
30
29
|
|
|
30
|
+
from iqm.benchmarks.entanglement.ghz import get_cx_map, get_edges
|
|
31
31
|
from iqm.benchmarks.logging_config import qcvv_logger
|
|
32
|
-
from iqm.benchmarks.utils import
|
|
32
|
+
from iqm.benchmarks.utils import extract_fidelities_unified, get_iqm_backend, random_hamiltonian_path
|
|
33
33
|
from iqm.qiskit_iqm.iqm_backend import IQMBackendBase
|
|
34
34
|
|
|
35
35
|
|
|
@@ -189,6 +189,10 @@ class GraphPositions:
|
|
|
189
189
|
"iqmfakedeneb": deneb_positions,
|
|
190
190
|
"emerald": emerald_positions,
|
|
191
191
|
"sirius": sirius_positions,
|
|
192
|
+
"crystal54": emerald_positions,
|
|
193
|
+
"crystal20": garnet_positions,
|
|
194
|
+
"star": sirius_positions,
|
|
195
|
+
"star24": sirius_positions,
|
|
192
196
|
}
|
|
193
197
|
|
|
194
198
|
@staticmethod
|
|
@@ -359,6 +363,7 @@ def evaluate_hamiltonian_paths(
|
|
|
359
363
|
path_samples: int,
|
|
360
364
|
backend_arg: str | IQMBackendBase,
|
|
361
365
|
url: str,
|
|
366
|
+
quantum_computer: str,
|
|
362
367
|
max_tries: int = 10,
|
|
363
368
|
) -> Dict[int, List[Tuple[int, int]]]:
|
|
364
369
|
"""Evaluates Hamiltonian paths according to the product of 2Q gate fidelities on the corresponding edges of the backend graph.
|
|
@@ -400,32 +405,23 @@ def evaluate_hamiltonian_paths(
|
|
|
400
405
|
|
|
401
406
|
# Get scores for all paths
|
|
402
407
|
# Retrieve fidelity data
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
headers = {"Accept": "application/json", "Authorization": "Bearer " + os.environ["IQM_TOKEN"]}
|
|
406
|
-
r = requests.get(url, headers=headers, timeout=60)
|
|
407
|
-
calibration = r.json()
|
|
408
|
-
|
|
409
|
-
for iq in calibration["calibrations"][0]["metrics"][0]["metrics"]:
|
|
410
|
-
temp = list(iq.values())
|
|
411
|
-
two_qubit_fidelity[str(temp[0])] = temp[1]
|
|
412
|
-
two_qubit_fidelity[str([temp[0][1], temp[0][0]])] = temp[1]
|
|
413
|
-
|
|
408
|
+
cal_data = extract_fidelities_unified(url, backend, quantum_computer=quantum_computer)
|
|
409
|
+
two_qubit_fidelity = cal_data[-1]["cz_gate_fidelity"]
|
|
414
410
|
# Rate all the paths
|
|
415
411
|
path_costs = {} # keys are costs, values are edge paths
|
|
416
412
|
for h_path in all_paths:
|
|
417
413
|
total_cost = 1
|
|
418
414
|
for edge in h_path:
|
|
419
415
|
if len(edge) == 2:
|
|
420
|
-
total_cost *= two_qubit_fidelity[
|
|
421
|
-
str([backend.index_to_qubit_name(edge[0]), backend.index_to_qubit_name(edge[1])])
|
|
422
|
-
]
|
|
416
|
+
total_cost *= two_qubit_fidelity[edge]
|
|
423
417
|
path_costs[total_cost] = h_path
|
|
424
418
|
|
|
425
419
|
return path_costs
|
|
426
420
|
|
|
427
421
|
|
|
428
|
-
def calculate_node_radii(
|
|
422
|
+
def calculate_node_radii(
|
|
423
|
+
metric_dict: Dict[str, Dict[int, float]], qubit_nodes: List[int], sq_metric: str
|
|
424
|
+
) -> np.ndarray:
|
|
429
425
|
"""Calculate node radii based on the specified single qubit metric. For the coherence metric, the fidelity is calculated as the idling fidelity of a single qubit gate duration.
|
|
430
426
|
|
|
431
427
|
Args:
|
|
@@ -443,9 +439,7 @@ def calculate_node_radii(metric_dict: Dict[str, Dict[int, float]], qubit_nodes:
|
|
|
443
439
|
if sq_metric == "fidelity":
|
|
444
440
|
radii = -np.log(np.array([metric_dict["fidelity_1qb_gates_averaged"][node] for node in qubit_nodes]))
|
|
445
441
|
if "fidelity_1qb_gates_averaged" not in metric_dict:
|
|
446
|
-
raise ValueError(
|
|
447
|
-
"The metric 'fidelity_1qb_gates_averaged' is not available in the backend metrics."
|
|
448
|
-
)
|
|
442
|
+
raise ValueError("The metric 'fidelity_1qb_gates_averaged' is not available in the backend metrics.")
|
|
449
443
|
elif sq_metric == "coherence":
|
|
450
444
|
if "t1_time" not in metric_dict or "t2_time" not in metric_dict:
|
|
451
445
|
raise ValueError(
|
|
@@ -458,9 +452,7 @@ def calculate_node_radii(metric_dict: Dict[str, Dict[int, float]], qubit_nodes:
|
|
|
458
452
|
radii = -np.log(idle_fidelities)
|
|
459
453
|
elif sq_metric == "readout":
|
|
460
454
|
if "single_shot_readout_fidelity" not in metric_dict:
|
|
461
|
-
raise ValueError(
|
|
462
|
-
"The metric 'single_shot_readout_fidelity' is both available in the backend metrics."
|
|
463
|
-
)
|
|
455
|
+
raise ValueError("The metric 'single_shot_readout_fidelity' is both available in the backend metrics.")
|
|
464
456
|
readout_fidelities = [metric_dict["single_shot_readout_fidelity"][node] for node in qubit_nodes]
|
|
465
457
|
radii = -np.log(readout_fidelities)
|
|
466
458
|
else:
|
|
@@ -469,11 +461,14 @@ def calculate_node_radii(metric_dict: Dict[str, Dict[int, float]], qubit_nodes:
|
|
|
469
461
|
)
|
|
470
462
|
return radii
|
|
471
463
|
|
|
464
|
+
|
|
472
465
|
def plot_layout_fidelity_graph(
|
|
473
|
-
|
|
466
|
+
iqm_server_url: str,
|
|
467
|
+
backend: IQMBackendBase,
|
|
474
468
|
qubit_layouts: Optional[list[list[int]]] = None,
|
|
475
|
-
|
|
469
|
+
quantum_computer: Optional[str] = None,
|
|
476
470
|
sq_metric: Optional[str] = "coherence",
|
|
471
|
+
show_ghz_path: bool = False,
|
|
477
472
|
):
|
|
478
473
|
"""Plot a graph showing the quantum chip layout with fidelity information.
|
|
479
474
|
|
|
@@ -482,33 +477,61 @@ def plot_layout_fidelity_graph(
|
|
|
482
477
|
(thinner edges mean better fidelity) and selected qubits are highlighted in orange.
|
|
483
478
|
|
|
484
479
|
Args:
|
|
485
|
-
|
|
480
|
+
iqm_server_url: URL to retrieve calibration data from.
|
|
481
|
+
backend: IQM backend instance.
|
|
486
482
|
qubit_layouts: List of qubit layouts where each layout is a list of qubit indices
|
|
487
|
-
|
|
483
|
+
quantum_computer: Name of the quantum computing station to use predefined positions for.
|
|
488
484
|
If None, positions will be generated algorithmically.
|
|
489
485
|
sq_metric: Optional single qubit metric to use for the visualization, can be either "fidelity", "coherence",
|
|
490
486
|
or "readout".
|
|
487
|
+
show_ghz_path: Whether to highlight the edges that are part of the GHZ state creation tree path.
|
|
491
488
|
|
|
492
489
|
Returns:
|
|
493
490
|
matplotlib.figure.Figure: The generated figure object containing the graph visualization
|
|
494
491
|
"""
|
|
495
492
|
# pylint: disable=unbalanced-tuple-unpacking, disable=too-many-statements
|
|
496
|
-
|
|
493
|
+
|
|
494
|
+
edges_cal, fidelities_cal, topology, qubit_mapping, metric_dict = extract_fidelities_unified(
|
|
495
|
+
iqm_server_url, backend, quantum_computer
|
|
496
|
+
)
|
|
497
|
+
|
|
497
498
|
if topology == "star":
|
|
498
499
|
idx_to_qubit = {idx: qubit for qubit, idx in qubit_mapping.items()}
|
|
500
|
+
qubit_to_idx = qubit_mapping
|
|
499
501
|
qubit_nodes = list(idx_to_qubit.keys())[1:]
|
|
500
502
|
fig, ax = plt.subplots(figsize=(len(qubit_nodes), 3))
|
|
501
503
|
else:
|
|
502
504
|
# For other topologies, qubits are indexed starting from 0 as per the Qiskit convention
|
|
503
505
|
idx_to_qubit = {idx: qubit - 1 for qubit, idx in qubit_mapping.items()}
|
|
506
|
+
qubit_to_idx = {qubit - 1: idx for qubit, idx in qubit_mapping.items()}
|
|
504
507
|
qubit_nodes = list(idx_to_qubit.keys())
|
|
505
508
|
fig, ax = plt.subplots(figsize=(1.5 * np.sqrt(len(qubit_nodes)), 1.5 * np.sqrt(len(qubit_nodes))))
|
|
506
509
|
|
|
510
|
+
# Filter out any edges that are not in the backend's coupling map
|
|
511
|
+
fidelities_cal = [
|
|
512
|
+
fidelity
|
|
513
|
+
for edge, fidelity in zip(edges_cal, fidelities_cal, strict=True)
|
|
514
|
+
if (edge[0], edge[1]) in backend.coupling_map or (edge[1], edge[0]) in backend.coupling_map
|
|
515
|
+
]
|
|
516
|
+
edges_cal = [edge for edge in edges_cal if (edge[0], edge[1])
|
|
517
|
+
in backend.coupling_map or (edge[1], edge[0]) in backend.coupling_map]
|
|
518
|
+
|
|
507
519
|
weights = -np.log(np.array(fidelities_cal))
|
|
508
520
|
calibrated_nodes = list(idx_to_qubit.keys())
|
|
509
521
|
|
|
522
|
+
if show_ghz_path and qubit_layouts is not None and any(len(layout) >= 2 for layout in qubit_layouts):
|
|
523
|
+
valid_fidelities = [f for f in fidelities_cal if f < 1.0]
|
|
524
|
+
if valid_fidelities:
|
|
525
|
+
median_fidelity = np.median(valid_fidelities)
|
|
526
|
+
fidelities_cal = [f if f < 1.0 else median_fidelity for f in fidelities_cal]
|
|
527
|
+
from iqm.benchmarks.entanglement.ghz import generate_ghz_spanning_tree, get_cx_map, get_edges
|
|
528
|
+
|
|
529
|
+
graph = get_edges(backend.coupling_map, qubit_layouts[0], edges_cal, fidelities_cal)
|
|
530
|
+
cx_map = get_cx_map(qubit_layouts[0], graph)
|
|
531
|
+
print(f"Edge map:", cx_map)
|
|
532
|
+
|
|
510
533
|
# Define qubit positions in plot
|
|
511
|
-
qubit_positions = GraphPositions.get_positions(station=
|
|
534
|
+
qubit_positions = GraphPositions.get_positions(station=quantum_computer, graph=None, num_qubits=len(calibrated_nodes))
|
|
512
535
|
|
|
513
536
|
graph = PyGraph()
|
|
514
537
|
nodes = list(set(qubit_positions.keys()))
|
|
@@ -520,24 +543,47 @@ def plot_layout_fidelity_graph(
|
|
|
520
543
|
else:
|
|
521
544
|
graph.add_edge(idx_to_qubit[edge[0]], idx_to_qubit[edge[1]], weight)
|
|
522
545
|
|
|
523
|
-
# Draw the main graph
|
|
546
|
+
# # Draw the main graph
|
|
524
547
|
visualization.mpl_draw(
|
|
525
548
|
graph,
|
|
526
549
|
ax=ax,
|
|
527
550
|
with_labels=True,
|
|
528
551
|
node_color="none", # No node color since we're using circles
|
|
529
552
|
pos=qubit_positions,
|
|
530
|
-
labels=lambda node: node,
|
|
553
|
+
labels=lambda node: str(qubit_to_idx[node]) if node in qubit_to_idx else "",
|
|
531
554
|
font_color="white",
|
|
532
|
-
|
|
533
|
-
)
|
|
555
|
+
edge_color="white",
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
# Draw edges manually with custom styles and colors
|
|
559
|
+
graph_edge_pairs = [list(edge) for edge in graph.edge_list()]
|
|
560
|
+
for _, (edge, weight) in enumerate(zip(graph_edge_pairs, graph.edges(), strict=True)):
|
|
561
|
+
x1, y1 = qubit_positions[edge[0]]
|
|
562
|
+
x2, y2 = qubit_positions[edge[1]]
|
|
563
|
+
|
|
564
|
+
# Define edge properties (customize these as needed)
|
|
565
|
+
edge_width = weight / np.max(list(graph.edges())) * 10 + 0.1
|
|
566
|
+
edge_color = "black"
|
|
567
|
+
edge_style = "solid"
|
|
568
|
+
|
|
569
|
+
# Highlight edges with zero weight (wrong calibration)
|
|
570
|
+
if weight == 0:
|
|
571
|
+
edge_width = 1
|
|
572
|
+
edge_style = "dashed"
|
|
573
|
+
# Highlight edges that are part of the GHZ path
|
|
574
|
+
if show_ghz_path and qubit_layouts is not None and any(len(layout) >= 2 for layout in qubit_layouts):
|
|
575
|
+
mapped_edge = [qubit_to_idx[edge[0]], qubit_to_idx[edge[1]]]
|
|
576
|
+
if mapped_edge in cx_map or list(reversed(mapped_edge)) in cx_map:
|
|
577
|
+
edge_color = "red"
|
|
578
|
+
|
|
579
|
+
ax.plot([x1, x2], [y1, y2], color=edge_color, linewidth=edge_width, linestyle=edge_style, zorder=1)
|
|
534
580
|
|
|
535
581
|
# Draw nodes as circles with varying radii given by the single qubit metric
|
|
536
582
|
radii = calculate_node_radii(metric_dict, qubit_nodes, sq_metric)
|
|
537
583
|
node_colors = ["darkgray" for _ in range(len(nodes))]
|
|
538
584
|
if qubit_layouts is not None:
|
|
539
585
|
for qb in {qb for layout in qubit_layouts for qb in layout}:
|
|
540
|
-
node_colors[qb] = "orange"
|
|
586
|
+
node_colors[idx_to_qubit[qb]] = "orange"
|
|
541
587
|
max_radius = 0.12 + np.max(radii) / np.max(radii) / 2.5
|
|
542
588
|
|
|
543
589
|
for idx, node in enumerate(qubit_nodes):
|
|
@@ -548,7 +594,7 @@ def plot_layout_fidelity_graph(
|
|
|
548
594
|
|
|
549
595
|
# Add edge labels using matplotlib's annotate
|
|
550
596
|
# for idx, edge in enumerate(edges_cal):
|
|
551
|
-
for edge, weight in zip(list(graph.
|
|
597
|
+
for edge, weight in zip(graph_edge_pairs, list(graph.edges()), strict=True):
|
|
552
598
|
x1, y1 = qubit_positions[edge[0]]
|
|
553
599
|
x2, y2 = qubit_positions[edge[1]]
|
|
554
600
|
x = (x1 + x2) / 2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iqm-benchmarks
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.55
|
|
4
4
|
Summary: A package for implementation of Quantum Characterization, Verification and Validation (QCVV) techniques on IQM's hardware at gate level abstraction
|
|
5
5
|
Author-email: IQM Finland Oy <developers@meetiqm.com>, Adrian Auer <adrian.auer@meetiqm.com>, Raphael Brieger <raphael.brieger@meetiqm.com>, Alessio Calzona <alessio.calzona@meetiqm.com>, Pedro Figueroa Romero <pedro.romero@meetiqm.com>, Amin Hosseinkhani <amin.hosseinkhani@meetiqm.com>, Miikka Koistinen <miikka@meetiqm.com>, Nadia Milazzo <nadia.milazzo@meetiqm.com>, Vicente Pina Canelles <vicente.pina@meetiqm.com>, Aniket Rath <aniket.rath@meetiqm.com>, Jami Rönkkö <jami@meetiqm.com>, Stefan Seegerer <stefan.seegerer@meetiqm.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/iqm-finland/iqm-benchmarks
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
iqm/benchmarks/__init__.py,sha256=-drZ_whue067Tu4I9RxBCqrrzu38Tm5Kqf9jHTftUPk,3070
|
|
2
|
-
iqm/benchmarks/benchmark.py,sha256=
|
|
3
|
-
iqm/benchmarks/benchmark_definition.py,sha256=
|
|
2
|
+
iqm/benchmarks/benchmark.py,sha256=w5dexVB9G9KKSBgMMIlZP1OA7AMp_ZmeMPOVfhGcK0A,5055
|
|
3
|
+
iqm/benchmarks/benchmark_definition.py,sha256=_fvMCGP2b6OjtQwfO8_FSXy1FJRvYc3nNgEe3sjlq28,11332
|
|
4
4
|
iqm/benchmarks/circuit_containers.py,sha256=anEtZEsodYqOX-34oZRmuKGeEpp_VfgG5045Mz4-4hI,7562
|
|
5
5
|
iqm/benchmarks/logging_config.py,sha256=U7olP5Kr75AcLJqNODf9VBhJLVqIvA4AYR6J39D5rww,1052
|
|
6
6
|
iqm/benchmarks/readout_mitigation.py,sha256=Q2SOGWTNgmklOYkNxepAaSaXlxSj0QQyymYY1bOkT8A,11756
|
|
7
|
-
iqm/benchmarks/utils.py,sha256=
|
|
8
|
-
iqm/benchmarks/utils_plots.py,sha256=
|
|
7
|
+
iqm/benchmarks/utils.py,sha256=yCTWo0lGMg82DK1fkUICEntzF0aocJktMfcY231pUxg,46114
|
|
8
|
+
iqm/benchmarks/utils_plots.py,sha256=Ei7_dsp94q652UMq5CszxoPCfJ1TNo6A7t-wSAAdpP8,26805
|
|
9
9
|
iqm/benchmarks/utils_shadows.py,sha256=e77PV_uaAO5m_woox9lAzompKAvFeDJ-0AKJrNJ7NFg,9728
|
|
10
10
|
iqm/benchmarks/coherence/__init__.py,sha256=yeyhk-_Lp8IbJ-f5lQj0HP5Q1HSKK_FzuXHazotUrVY,704
|
|
11
11
|
iqm/benchmarks/coherence/coherence.py,sha256=RvbOxV2sJpAyr_bXqjBfSjk9v8XjRN-nrkK8w7RyfH0,21596
|
|
@@ -13,13 +13,13 @@ iqm/benchmarks/compressive_gst/__init__.py,sha256=LneifgYXtcwo2jcXo7GdUEHL6_peip
|
|
|
13
13
|
iqm/benchmarks/compressive_gst/compressive_gst.py,sha256=_thQfc9qmIJqAcS3Kg4ITEYl8Ofi8xgC_oZotrmyzVk,28484
|
|
14
14
|
iqm/benchmarks/compressive_gst/gst_analysis.py,sha256=H6EQGbpI_sig69Jy6hflg6alMTtjB0t9tHftygzA2YA,41240
|
|
15
15
|
iqm/benchmarks/entanglement/__init__.py,sha256=sHVVToRWRCz0LSntk1rQaoSNNeyZLPoiTjUKWZWrk1E,778
|
|
16
|
-
iqm/benchmarks/entanglement/ghz.py,sha256=
|
|
16
|
+
iqm/benchmarks/entanglement/ghz.py,sha256=Tq7gPqOgS8WWywgp-1Jlu2ZgeTYEJNSiSxH2S8_D66E,47379
|
|
17
17
|
iqm/benchmarks/entanglement/graph_states.py,sha256=6qACedd3UXpiowXc9GW4QhSwO-CzHXnBA3dIC6nCIbE,62788
|
|
18
18
|
iqm/benchmarks/optimization/__init__.py,sha256=_ajW_OibYLCtzU5AUv5c2zuuVYn8ZNeZUcUUSIGt51M,747
|
|
19
19
|
iqm/benchmarks/optimization/qscore.py,sha256=7JJIVrJvmec77kSdwM4YkwJJoNBCT-LuZ7Ay8JMZ7Nc,46847
|
|
20
20
|
iqm/benchmarks/quantum_volume/__init__.py,sha256=i-Q4SpDWELBw7frXnxm1j4wJRcxbIyrS5uEK_v06YHo,951
|
|
21
|
-
iqm/benchmarks/quantum_volume/clops.py,sha256=
|
|
22
|
-
iqm/benchmarks/quantum_volume/quantum_volume.py,sha256=
|
|
21
|
+
iqm/benchmarks/quantum_volume/clops.py,sha256=HwO0bTRfDZrDtINLNtbXCIMqlqqFhsb6kmyma1gsDJU,31562
|
|
22
|
+
iqm/benchmarks/quantum_volume/quantum_volume.py,sha256=zKaD4ze3Msblo9tIxMmP8l_huq9mfDNukIJhSL72QYo,33576
|
|
23
23
|
iqm/benchmarks/randomized_benchmarking/__init__.py,sha256=IkKo-7zUChxZZd3my_csQCJfJfZNsV3-JTvdG8uqys4,734
|
|
24
24
|
iqm/benchmarks/randomized_benchmarking/clifford_1q.pkl,sha256=yrmSJqhv7Lb1yqiqU9-2baqTljJPNmTUPQR-AH6GGfc,7800
|
|
25
25
|
iqm/benchmarks/randomized_benchmarking/clifford_2q.pkl,sha256=mJQLubWPOb-DbmFi4oKYJqAMW_Yyo3eJjRjLGl9Sqmo,10282247
|
|
@@ -30,12 +30,12 @@ iqm/benchmarks/randomized_benchmarking/clifford_rb/clifford_rb.py,sha256=1BOYA9x
|
|
|
30
30
|
iqm/benchmarks/randomized_benchmarking/direct_rb/__init__.py,sha256=lCIIeWMFZHnMUUEUTjUBvrhhUur6uBTHIVkxFBSfHC4,681
|
|
31
31
|
iqm/benchmarks/randomized_benchmarking/direct_rb/direct_rb.py,sha256=X4MVojCcv1KabopKql4-58sNXP_q0WcFZBeUbDTY83w,49399
|
|
32
32
|
iqm/benchmarks/randomized_benchmarking/eplg/__init__.py,sha256=1MeGZTErElXJypQV2rQf7hwqLLvIp_JNVbwNhaP5vyI,696
|
|
33
|
-
iqm/benchmarks/randomized_benchmarking/eplg/eplg.py,sha256=
|
|
33
|
+
iqm/benchmarks/randomized_benchmarking/eplg/eplg.py,sha256=kmet3yxF1bl1spKf-UrHqHxyEQhRnM7954oRmUKJrX8,17332
|
|
34
34
|
iqm/benchmarks/randomized_benchmarking/interleaved_rb/__init__.py,sha256=sq6MgN_hwlpkOj10vyCU4e6eKSX-oLcF2L9na6W2Gt4,681
|
|
35
35
|
iqm/benchmarks/randomized_benchmarking/interleaved_rb/interleaved_rb.py,sha256=OHoAWajCE48dRDInwQUT8VvtzKad0ExefdqvZFTaYzs,28918
|
|
36
36
|
iqm/benchmarks/randomized_benchmarking/mirror_rb/__init__.py,sha256=jRKbivWCZ3xdO1k0sx-ygC3s5DUkGSModd975PoAtcg,692
|
|
37
37
|
iqm/benchmarks/randomized_benchmarking/mirror_rb/mirror_rb.py,sha256=ijieNymik3BeEUpXS-m64mtgdHz9iAFELuLooHeZY0E,33252
|
|
38
|
-
iqm_benchmarks-2.
|
|
38
|
+
iqm_benchmarks-2.55.dist-info/licenses/LICENSE,sha256=2Ncb40-hqkTil78RPv3-YiJfKaJ8te9USJgliKqIdSY,11558
|
|
39
39
|
mGST/LICENSE,sha256=TtHNq55cUcbglb7uhVudeBLUh_qPdUoAEvU0BBwFz-k,1098
|
|
40
40
|
mGST/README.md,sha256=v_5kw253csHF4-RfE-44KqFmBXIsSMRmOtN0AUPrRxE,5050
|
|
41
41
|
mGST/additional_fns.py,sha256=MV0Pm5ap59IjhT_E3QhsZyM7lXOF1RZ9SD11zoaf43A,31781
|
|
@@ -46,7 +46,7 @@ mGST/optimization.py,sha256=x9tJ9wMQ5aONWpNpBMVtK0rwE6DRcOU33htNgrt0tx4,11015
|
|
|
46
46
|
mGST/qiskit_interface.py,sha256=uCdn-Q9CXI2f4FQSxGUy8GmmzQhr9NhCOFb2VPj0gTs,10061
|
|
47
47
|
mGST/reporting/figure_gen.py,sha256=xFPAHx1Trdqz7swn0kRqwc_jbRaNxhG9Nvx0jeitooo,25847
|
|
48
48
|
mGST/reporting/reporting.py,sha256=Wss1-zFsMEhzrrXKfP-RICau80ezjDIzcN555KhSehc,34160
|
|
49
|
-
iqm_benchmarks-2.
|
|
50
|
-
iqm_benchmarks-2.
|
|
51
|
-
iqm_benchmarks-2.
|
|
52
|
-
iqm_benchmarks-2.
|
|
49
|
+
iqm_benchmarks-2.55.dist-info/METADATA,sha256=ZkaOMyHFWMsU0fPFyG2qMu1L8fnAcQ5oUeT_It0dxOQ,11009
|
|
50
|
+
iqm_benchmarks-2.55.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
51
|
+
iqm_benchmarks-2.55.dist-info/top_level.txt,sha256=3G23Z-1LGf-IOzTCUl6QwWqiQ3USz25Zt90Ihq192to,9
|
|
52
|
+
iqm_benchmarks-2.55.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|