iqm-benchmarks 2.42__py3-none-any.whl → 2.44__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/coherence/__init__.py +18 -0
- iqm/benchmarks/coherence/coherence.py +548 -0
- iqm/benchmarks/entanglement/ghz.py +3 -3
- iqm/benchmarks/entanglement/graph_states.py +21 -21
- iqm/benchmarks/quantum_volume/clops.py +2 -3
- iqm/benchmarks/randomized_benchmarking/eplg/eplg.py +23 -24
- iqm/benchmarks/utils.py +72 -8
- iqm/benchmarks/utils_plots.py +309 -65
- {iqm_benchmarks-2.42.dist-info → iqm_benchmarks-2.44.dist-info}/METADATA +1 -1
- {iqm_benchmarks-2.42.dist-info → iqm_benchmarks-2.44.dist-info}/RECORD +13 -11
- {iqm_benchmarks-2.42.dist-info → iqm_benchmarks-2.44.dist-info}/WHEEL +0 -0
- {iqm_benchmarks-2.42.dist-info → iqm_benchmarks-2.44.dist-info}/licenses/LICENSE +0 -0
- {iqm_benchmarks-2.42.dist-info → iqm_benchmarks-2.44.dist-info}/top_level.txt +0 -0
|
@@ -21,7 +21,6 @@ from math import floor, pi
|
|
|
21
21
|
from time import perf_counter, strftime
|
|
22
22
|
from typing import Any, Dict, List, Sequence, Tuple, Type
|
|
23
23
|
|
|
24
|
-
import matplotlib as mpl
|
|
25
24
|
from matplotlib.figure import Figure
|
|
26
25
|
import matplotlib.pyplot as plt
|
|
27
26
|
import numpy as np
|
|
@@ -178,8 +177,8 @@ def retrieve_clops_elapsed_times(job_meta: Dict[str, Dict[str, Any]]) -> Dict[st
|
|
|
178
177
|
# submit_i = datetime.strptime(x["submit_start"], job_time_format)
|
|
179
178
|
execution_f = datetime.strptime(x["execution_end"], job_time_format)
|
|
180
179
|
execution_i = datetime.strptime(x["execution_start"], job_time_format)
|
|
181
|
-
job_f = datetime.strptime(x["
|
|
182
|
-
job_i = datetime.strptime(x["
|
|
180
|
+
job_f = datetime.strptime(x["ready"], job_time_format)
|
|
181
|
+
job_i = datetime.strptime(x["received"], job_time_format)
|
|
183
182
|
|
|
184
183
|
all_job_elapsed[update][batch] = {
|
|
185
184
|
"job_total": job_f - job_i,
|
|
@@ -5,6 +5,7 @@ Error Per Layered Gate (EPLG).
|
|
|
5
5
|
from time import strftime
|
|
6
6
|
from typing import Dict, Optional, Sequence, Tuple, Type, cast
|
|
7
7
|
|
|
8
|
+
from matplotlib.colors import to_rgba
|
|
8
9
|
from matplotlib.figure import Figure
|
|
9
10
|
import matplotlib.pyplot as plt
|
|
10
11
|
import networkx as nx
|
|
@@ -76,38 +77,35 @@ def plot_layered_fidelities_graph(
|
|
|
76
77
|
fig = plt.figure()
|
|
77
78
|
ax = plt.axes()
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
else:
|
|
83
|
-
if num_qubits in (20, 7):
|
|
84
|
-
station = "garnet" if num_qubits == 20 else "deneb"
|
|
85
|
-
qubit_positions = GraphPositions.predefined_stations[station]
|
|
86
|
-
else:
|
|
87
|
-
graph_backend = backend_coupling_map.graph.to_undirected(multigraph=False)
|
|
88
|
-
qubit_positions = GraphPositions.create_positions(graph_backend)
|
|
89
|
-
else:
|
|
90
|
-
graph_backend = backend_coupling_map.graph.to_undirected(multigraph=False)
|
|
91
|
-
if num_qubits in (20, 7):
|
|
92
|
-
station = "garnet" if num_qubits == 20 else "deneb"
|
|
93
|
-
qubit_positions = GraphPositions.predefined_stations[station]
|
|
94
|
-
else:
|
|
95
|
-
qubit_positions = GraphPositions.create_positions(graph_backend)
|
|
80
|
+
qubit_positions = GraphPositions.get_positions(
|
|
81
|
+
station=station, graph=backend_coupling_map.graph.to_undirected(multigraph=False), num_qubits=num_qubits
|
|
82
|
+
)
|
|
96
83
|
|
|
97
84
|
# Normalize fidelity values to the range [0, 1] for color mapping
|
|
98
85
|
norm = plt.Normalize(vmin=cast(float, min(fidelity_values)), vmax=cast(float, max(fidelity_values)))
|
|
99
|
-
edge_colors = [
|
|
86
|
+
edge_colors = []
|
|
87
|
+
for edge in backend_coupling_map:
|
|
88
|
+
if edge in fidelity_edges:
|
|
89
|
+
edge_colors.append(cmap(norm(fidelity_edges[edge])))
|
|
90
|
+
elif (edge[1], edge[0]) in fidelity_edges:
|
|
91
|
+
edge_colors.append(cmap(norm(fidelity_edges[(edge[1], edge[0])])))
|
|
92
|
+
else:
|
|
93
|
+
edge_colors.append(to_rgba("lightgray"))
|
|
94
|
+
|
|
95
|
+
nodes = list(set(v for edge in backend_coupling_map for v in edge))
|
|
96
|
+
active_nodes = list(set(v for edge in qubit_pairs for v in edge))
|
|
97
|
+
node_colors = ["lightgray" if v not in active_nodes else "k" for v in nodes]
|
|
100
98
|
|
|
101
99
|
nx.draw_networkx(
|
|
102
100
|
rx_to_nx_graph(backend_coupling_map),
|
|
103
101
|
pos=qubit_positions,
|
|
104
|
-
nodelist=
|
|
105
|
-
|
|
102
|
+
nodelist=nodes,
|
|
103
|
+
edgelist=list(backend_coupling_map),
|
|
104
|
+
labels={x: qubit_names[x] for x in nodes},
|
|
106
105
|
font_size=6.5,
|
|
107
|
-
edgelist=qubit_pairs,
|
|
108
106
|
width=4.0,
|
|
109
107
|
edge_color=edge_colors,
|
|
110
|
-
node_color=
|
|
108
|
+
node_color=node_colors,
|
|
111
109
|
font_color="w",
|
|
112
110
|
ax=ax,
|
|
113
111
|
)
|
|
@@ -116,7 +114,7 @@ def plot_layered_fidelities_graph(
|
|
|
116
114
|
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
|
|
117
115
|
sm.set_array([])
|
|
118
116
|
cbar = fig.colorbar(sm, ax=ax, shrink=0.5, label="Layered Fidelity (%)", format="%.2f")
|
|
119
|
-
cbar.set_ticks(np.linspace(min(fidelity_values), max(fidelity_values), 5, endpoint=True))
|
|
117
|
+
cbar.set_ticks(tuple(np.linspace(min(fidelity_values), max(fidelity_values), 5, endpoint=True)))
|
|
120
118
|
|
|
121
119
|
station_string = "IQM Backend" if station is None else station.capitalize()
|
|
122
120
|
|
|
@@ -124,6 +122,7 @@ def plot_layered_fidelities_graph(
|
|
|
124
122
|
f"EPLG estimate: {eplg_estimate['value']:.2e} +/- {eplg_estimate['uncertainty']:.2e}\n" if eplg_estimate else ""
|
|
125
123
|
)
|
|
126
124
|
plt.title(f"Layered fidelities for qubit pairs in {station_string}\n" f"{eplg_string}{timestamp}")
|
|
125
|
+
plt.gca().invert_yaxis()
|
|
127
126
|
plt.close()
|
|
128
127
|
|
|
129
128
|
return fig_name, fig
|
|
@@ -190,8 +189,8 @@ def eplg_analysis(run: BenchmarkRunResult) -> BenchmarkAnalysisResult:
|
|
|
190
189
|
backend_num_qubits=backend_num_qubits,
|
|
191
190
|
edge_list=edges,
|
|
192
191
|
timestamp=timestamp,
|
|
193
|
-
disjoint_layers=disjoint_layers,
|
|
194
192
|
station=backend_configuration_name,
|
|
193
|
+
disjoint_layers=disjoint_layers,
|
|
195
194
|
qubit_names=qubit_names,
|
|
196
195
|
is_eplg=True,
|
|
197
196
|
)
|
iqm/benchmarks/utils.py
CHANGED
|
@@ -48,6 +48,9 @@ from iqm.qiskit_iqm.iqm_job import IQMJob
|
|
|
48
48
|
from iqm.qiskit_iqm.iqm_provider import IQMProvider
|
|
49
49
|
|
|
50
50
|
|
|
51
|
+
# pylint: disable=too-many-lines
|
|
52
|
+
|
|
53
|
+
|
|
51
54
|
def timeit(f):
|
|
52
55
|
"""Calculates the amount of time a function takes to execute.
|
|
53
56
|
|
|
@@ -283,12 +286,18 @@ def get_active_qubits(qc: QuantumCircuit) -> List[int]:
|
|
|
283
286
|
return list(active_qubits)
|
|
284
287
|
|
|
285
288
|
|
|
286
|
-
def extract_fidelities(cal_url: str) ->
|
|
289
|
+
def extract_fidelities(cal_url: str, all_metrics: bool = False) -> Union[
|
|
290
|
+
Tuple[List[List[int]], List[float], str, Dict[int, int]],
|
|
291
|
+
Tuple[List[List[int]], List[float], str, Dict[int, int], Dict[str, Dict[Union[int, Tuple[int, int]], float]]],
|
|
292
|
+
]:
|
|
287
293
|
"""Returns couplings and CZ-fidelities from calibration data URL
|
|
288
294
|
|
|
289
295
|
Args:
|
|
290
296
|
cal_url: str
|
|
291
297
|
The url under which the calibration data for the backend can be found
|
|
298
|
+
all_metrics: bool
|
|
299
|
+
If True, returns a dictionary with all metrics from the calibration data
|
|
300
|
+
Default is False
|
|
292
301
|
Returns:
|
|
293
302
|
list_couplings: List[List[int]]
|
|
294
303
|
A list of pairs, each of which is a qubit coupling for which the calibration
|
|
@@ -297,6 +306,13 @@ def extract_fidelities(cal_url: str) -> tuple[list[list[int]], list[float], str]
|
|
|
297
306
|
A list of CZ fidelities from the calibration url, ordered in the same way as list_couplings
|
|
298
307
|
topology: str
|
|
299
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
|
+
metrics_dict: Dict
|
|
313
|
+
Dictionary of all metrics (returned only if all_metrics=True)
|
|
314
|
+
Format: {metric_name: {qubit: value}} for single qubit metrics
|
|
315
|
+
Format: {metric_name: {(qubit_1, qubit_2): value}} for two qubit metrics
|
|
300
316
|
"""
|
|
301
317
|
headers = {"Accept": "application/json", "Authorization": "Bearer " + os.environ["IQM_TOKEN"]}
|
|
302
318
|
r = requests.get(cal_url, headers=headers, timeout=60)
|
|
@@ -304,6 +320,7 @@ def extract_fidelities(cal_url: str) -> tuple[list[list[int]], list[float], str]
|
|
|
304
320
|
cal_keys = {
|
|
305
321
|
el2["key"]: (i, j) for i, el1 in enumerate(calibration["calibrations"]) for j, el2 in enumerate(el1["metrics"])
|
|
306
322
|
}
|
|
323
|
+
resonator_names = ["COMPR", "COMP_R", "MPR1", "MPR_1"]
|
|
307
324
|
list_couplings = []
|
|
308
325
|
list_fids = []
|
|
309
326
|
if "double_move_gate_fidelity" in cal_keys.keys():
|
|
@@ -313,18 +330,65 @@ def extract_fidelities(cal_url: str) -> tuple[list[list[int]], list[float], str]
|
|
|
313
330
|
i, j = cal_keys["cz_gate_fidelity"]
|
|
314
331
|
topology = "crystal"
|
|
315
332
|
for item in calibration["calibrations"][i]["metrics"][j]["metrics"]:
|
|
316
|
-
qb1 =
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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])
|
|
322
344
|
list_fids.append(float(item["value"]))
|
|
323
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
|
+
|
|
370
|
+
# Enumerate all calibrated qubits starting from 0
|
|
324
371
|
qubit_mapping = {qubit: idx for idx, qubit in enumerate(calibrated_qubits)}
|
|
325
372
|
list_couplings = [[qubit_mapping[edge[0]], qubit_mapping[edge[1]]] for edge in list_couplings]
|
|
326
373
|
|
|
327
|
-
|
|
374
|
+
# Apply the qubit mapping to metrics_dict
|
|
375
|
+
remapped_metrics_dict = {}
|
|
376
|
+
for metric_key, metric_values in metrics_dict.items():
|
|
377
|
+
remapped_metrics_dict[metric_key] = {}
|
|
378
|
+
for key, value in metric_values.items():
|
|
379
|
+
if isinstance(key, tuple):
|
|
380
|
+
# Two-qubit metric
|
|
381
|
+
remapped_metrics_dict[metric_key][(qubit_mapping[key[0]], qubit_mapping[key[1]])] = value
|
|
382
|
+
else:
|
|
383
|
+
# Single-qubit metric
|
|
384
|
+
remapped_metrics_dict[metric_key][qubit_mapping[key]] = value
|
|
385
|
+
metrics_dict = remapped_metrics_dict
|
|
386
|
+
|
|
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
|
+
return list_couplings, list_fids, topology, qubit_mapping, metrics_dict
|
|
328
392
|
|
|
329
393
|
|
|
330
394
|
# pylint: disable=too-many-branches
|