Benchmark dynamic circuits with cut Bell pairs
Bruuk-Schatzung: 22 Sekunnen op een Heron r2 Perzesser (WOHRSCHAU: Dat is blots een Schatzung. Dien Looptiet kann anners ween.)
Background
Kwantenhardware is normalerwies op lokale Interaktschonen begrenzt, aver vööl Algorithmen bruukt dat, dat Qubits verschrankt warrt, de wied vun eenanner liggt oder Qubits op verscheden Perzessers. Dynamische Schaltkresen - dat sünd Schaltkresen mit Metungen un Feedforward binnen den Loop - sorgt darvör, dat wi de Begrenzen ümgahn künnt, dör dat wi Echttiet-Kommunikatschon bruukt, üm effektiv nich-lokale Kwantenoperatschonen to implementeren. Dormit künnt Metungsergebnissen vun een Deel vun den Schaltkreis (oder een QPU) bedingt Gates op een annern triggern, so dat wi Verschrankung över grote Distanzen teleportern künnt. Dat is de Basis vun lokale Operatschonen un klassische Kommunikatschon (LOCC) Schemas, wo wi verschrankte Ressurcentöstänn (Bell-Poren) verbruukt un Metungsergebnissen klassisch kommunizeert, üm wied vun eenanner liggen Qubits to verbinnen.
Een vielversprekend Bruuk vun LOCC is dat, virtuell Lang-Streck-CNOT-Gates dör Teleportatschon to realisern, as in dat long-range entanglement tutorial wiest. Anstatt een direkt Lang-Streck-CNOT (wat de Hardware-Konnektivitat villicht nich verlövt), maakt wi Bell-Poren un föhrt een teleportatschonsbaseert Gate-Implementerung dör. Allerdings hangt de Fidelitat vun sülke Operatschonen vun de Hardwareeigenschoppen af. Qubit-Dekohärenz binnen de nödige Vertreckung (während wi op Metungsergebnissen töövt) un klassische Kommunikatschonslatenz künnt den verschrankten Tostand verschlechtern. Bütendeem sünd Fehlers bi Metungen binnen den Loop sworer to korrgeern as Fehlers bi de Endmetungen, wiel se sik dör de bedingten Gates op denRest vun den Schaltkreis utbreet.
In dat Referenz-Experiment stellt de Autoren een Bell-Por-Fidelitats-Benchmark vör, üm ruuttofinn, welke Delen vun een Gerat am besten för LOCC-baseert Verschrankung schickt sünd. De Idee is dat, een lütten dynamischen Schaltkreis op jede Grupp vun veer verbunnen Qubits in den Perzesser to lopen laten. De Veer-Qubit-Schaltkreis maakt toeerst een Bell-Por op twee midden Qubits, un bruukt denn de as Ressurce, üm de twee Rand-Qubits dör LOCC to verschranken. Konkret warrt Qubits 1 un 2 lokaal in een unsneden Bell-Por prepareert (mit een Hadamard un CNOT), un denn verbruukt een Teleportatschonsrutine dat Bell-Por, üm Qubits 0 un 3 to verschranken. Qubits 1 un 2 warrt binnen de Utföhrung vun den Schaltkreis meten, un baseert op de Ergebnissen warrt Pauli-Korrekturen (een X op Qubit 3 un Z op Qubit 0) anwennt. Qubits 0 un 3 bliift denn an't Enn vun den Schaltkreis in een Bell-Tostand.
Üm de Qualitat vun dat End-Bell-Por to kwantifizeren, meet wi sien Stabilisatoren: konkret de Paritat in de -Basis () un in de -Basis (). För een perfekt Bell-Por sünd beeds düsse Verwachtenswerten +1. In de Praxis warrt Hardware-Ruuschen düsse Werten reduzeren. Dorüm wedderhoolt wi den Schaltkreis tweemal för jedes Qubit-Por: een Schaltkreis mitt Qubits 0 un 3 in de -Basis, un een annern mitt se in de -Basis. Ut de Resultaten kriegt wi een Schatzung vun un för dat Por vun Qubits. Wi bruukt den middeln kwadratischen Afwiek (MSE) vun düsse Stabilisatoren betagen op den idealen Wert (1) as eenfach Metrik vun de Verschrankungsfidelitat. Een lager MSE bedüdd, dat de twee Qubits een Bell-Tostand neger an't Ideale erreikt hebbt (högere Fidelitat), während een högere MSE mehr Fehlers anwiest. Dör dat wi dat Experiment över dat Gerat scannen künnt, künnt wi de Met-un-Feedforward-Fähigkeit vun verscheden Qubit-Gruppen benchmarken un de besten Poren vun Qubits för LOCC-Operatschonen identifizeren.
Düt Tutorial demonstreert dat Experiment op een IBM Quantum® Gerat, üm to wiesen, wo dynamische Schaltkresen bruukt warrt künnt, üm Verschrankung twischen wied vun eenanner liggen Qubits to erzeugen un to evaluern. Wi warrt all Veer-Qubit-linearen Keden op dat Gerat kartern, den Teleportatschonsschaltkreis op jede lopen laten, un denn de Verdelung vun de MSE-Werten visualisern. Düsse End-to-End-Perzedur wiest, wo wi Qiskit Runtime un dynamische Schaltkreisfunktschonen nutzen künnt, üm hardware-bewuste Entscheedungen för dat Snieen vun Schaltkresen oder dat Verdeeln vun Kwantenalgorithmen över een modulares System to drapen.
Requirements
Bevör du mit düt Tutorial anfängst, stell seeker, dat du Folgendes installeert hest:
- Qiskit SDK v2.0 oder never, mit visualization Ünnerstütten
- Qiskit Runtime v0.40 oder never (
pip install qiskit-ibm-runtime)
Setup
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
from qiskit.transpiler import generate_preset_pass_manager
import numpy as np
import matplotlib.pyplot as plt
def create_bell_stab(initial_layouts):
"""
Create a circuit for a 1D chain of qubits (number of qubits must be a multiple of 4),
where a middle Bell pair is consumed to create a Bell at the edge.
Takes as input a list of lists, where each element of the list is a
1D chain of physical qubits that is used as the initial_layout for the transpiled circuit.
Returns a list of length-2 tuples, each tuple contains a circuit to measure the ZZ stabilizer and
a circuit to measure the XX stabilizer of the edge Bell state.
"""
bell_circuits = []
for (
initial_layout
) in initial_layouts: # Iterate over chains of physical qubits
assert (
len(initial_layout) % 4 == 0
), f"The length of the chain must be a multiple of 4, len(inital_layout)={len(initial_layout)}"
num_pairs = len(initial_layout) // 4
bell_parallel = QuantumCircuit(4 * num_pairs, 4 * num_pairs)
for pair_idx in range(num_pairs):
(q0, q1, q2, q3) = (
pair_idx * 4,
pair_idx * 4 + 1,
pair_idx * 4 + 2,
pair_idx * 4 + 3,
)
(c0, c1) = pair_idx * 4, pair_idx * 4 + 3 # edge qubits
(ca0, ca1) = pair_idx * 4 + 1, pair_idx * 4 + 2 # middle qubits
bell_parallel.h(q0)
bell_parallel.h(q1)
bell_parallel.cx(q1, q2)
bell_parallel.cx(q0, q1)
bell_parallel.cx(q2, q3)
bell_parallel.h(q2)
# add barrier BEFORE measurements and add id in conditional
bell_parallel.barrier()
for pair_idx in range(num_pairs):
(q0, q1, q2, q3) = (
pair_idx * 4,
pair_idx * 4 + 1,
pair_idx * 4 + 2,
pair_idx * 4 + 3,
)
(ca0, ca1) = pair_idx * 4 + 1, pair_idx * 4 + 2 # middle qubits
bell_parallel.measure(q1, ca0)
bell_parallel.measure(q2, ca1)
# bell_parallel.barrier() #remove barrier after measurement
for pair_idx in range(num_pairs):
(q0, q1, q2, q3) = (
pair_idx * 4,
pair_idx * 4 + 1,
pair_idx * 4 + 2,
pair_idx * 4 + 3,
)
(ca0, ca1) = pair_idx * 4 + 1, pair_idx * 4 + 2 # middle qubits
with bell_parallel.if_test((ca0, 1)):
bell_parallel.x(q3)
with bell_parallel.if_test((ca1, 1)):
bell_parallel.z(q0)
bell_parallel.id(q0) # add id here for correct alignment
bell_zz = bell_parallel.copy()
bell_zz.barrier()
bell_xx = bell_parallel.copy()
bell_xx.barrier()
for pair_idx in range(num_pairs):
(q0, q1, q2, q3) = (
pair_idx * 4,
pair_idx * 4 + 1,
pair_idx * 4 + 2,
pair_idx * 4 + 3,
)
bell_xx.h(q0)
bell_xx.h(q3)
bell_xx.barrier()
for pair_idx in range(num_pairs):
(q0, q1, q2, q3) = (
pair_idx * 4,
pair_idx * 4 + 1,
pair_idx * 4 + 2,
pair_idx * 4 + 3,
)
(c0, c1) = pair_idx * 4, pair_idx * 4 + 3 # edge qubits
bell_zz.measure(q0, c0)
bell_zz.measure(q3, c1)
bell_xx.measure(q0, c0)
bell_xx.measure(q3, c1)
bell_circuits.append(bell_zz)
bell_circuits.append(bell_xx)
return bell_circuits
def get_mse(result, initial_layouts):
"""
given a result object and the initial layouts, returns a dict of layouts and their mse
"""
layout_mse = {}
for layout_idx, initial_layout in enumerate(initial_layouts):
layout_mse[tuple(initial_layout)] = {}
num_pairs = len(initial_layout) // 4
counts_zz = result[2 * layout_idx].data.c.get_counts()
total_shots = sum(counts_zz.values())
# Get ZZ expectation value
exp_zz_list = []
for pair_idx in range(num_pairs):
exp_zz = 0
for bitstr, shots in counts_zz.items():
bitstr = bitstr[::-1] # reverse order to big endian
b1, b0 = (
bitstr[pair_idx * 4],
bitstr[pair_idx * 4 + 3],
) # parse bitstring to get edge measurements for each 4-q chain
z_val0 = 1 if b0 == "0" else -1
z_val1 = 1 if b1 == "0" else -1
exp_zz += z_val0 * z_val1 * shots
exp_zz /= total_shots
exp_zz_list.append(exp_zz)
counts_xx = result[2 * layout_idx + 1].data.c.get_counts()
total_shots = sum(counts_xx.values())
# Get XX expectation value
exp_xx_list = []
for pair_idx in range(num_pairs):
exp_xx = 0
for bitstr, shots in counts_xx.items():
bitstr = bitstr[::-1] # reverse order to big endian
b1, b0 = (
bitstr[pair_idx * 4],
bitstr[pair_idx * 4 + 3],
) # parse bitstring to get edge measurements for each 4-q chain
x_val0 = 1 if b0 == "0" else -1
x_val1 = 1 if b1 == "0" else -1
exp_xx += x_val0 * x_val1 * shots
exp_xx /= total_shots
exp_xx_list.append(exp_xx)
mse_list = [
((exp_zz - 1) ** 2 + (exp_xx - 1) ** 2) / 2
for exp_zz, exp_xx in zip(exp_zz_list, exp_xx_list)
]
print(f"layout {initial_layout}")
for idx in range(num_pairs):
layout_mse[tuple(initial_layout)][
tuple(initial_layout[4 * idx : 4 * idx + 4])
] = mse_list[idx]
print(
f"qubits: {initial_layout[4*idx:4*idx+4]}, mse:, {round(mse_list[idx],4)}"
)
# print(f'exp_zz: {round(exp_zz_list[idx],4)}, exp_xx: {round(exp_xx_list[idx],4)}')
print(" ")
return layout_mse
def plot_mse_ecdfs(layouts_mse, combine_layouts=False):
"""
Plot CDF of MSE data for multiple layouts. Optionally combine all data in a single CDF
"""
if not combine_layouts:
for initial_layout, layouts in layouts_mse.items():
sorted_layouts = dict(
sorted(layouts.items(), key=lambda item: item[1])
) # sort layouts by mse
# get layouts and mses
layout_list = list(sorted_layouts.keys())
mse_list = np.asarray(list(sorted_layouts.values()))
# convert to numpy
x = np.array(mse_list)
y = np.arange(1, len(x) + 1) / len(x)
# Prepend (x[0], 0) to start CDF at zero
x = np.insert(x, 0, x[0])
y = np.insert(y, 0, 0)
# Create the plot
plt.plot(
x,
y,
marker="x",
linestyle="-",
label=f"qubits: {initial_layout}",
)
# add qubits labels for the edge pairs
for xi, yi, q in zip(x[1:], y[1:], layout_list):
plt.annotate(
[q[0], q[3]],
(xi, yi),
textcoords="offset points",
xytext=(5, -10),
ha="left",
fontsize=8,
)
elif combine_layouts:
all_layouts = {}
all_initial_layout = []
for (
initial_layout,
layouts,
) in layouts_mse.items(): # puts together all layout information
all_layouts.update(layouts)
all_initial_layout += initial_layout
sorted_layouts = dict(
sorted(all_layouts.items(), key=lambda item: item[1])
) # sort layouts by mse
# get layouts and mses
layout_list = list(sorted_layouts.keys())
mse_list = np.asarray(list(sorted_layouts.values()))
# convert to numpy
x = np.array(mse_list)
y = np.arange(1, len(x) + 1) / len(x)
# Prepend (x[0], 0) to start CDF at zero
x = np.insert(x, 0, x[0])
y = np.insert(y, 0, 0)
# Create the plot
plt.plot(
x,
y,
marker="x",
linestyle="-",
label=f"qubits: {sorted(list(set(all_initial_layout)))}",
)
# add qubit labels for the edge pairs
for xi, yi, q in zip(x[1:], y[1:], layout_list):
plt.annotate(
[q[0], q[3]],
(xi, yi),
textcoords="offset points",
xytext=(5, -10),
ha="left",
fontsize=8,
)
plt.xscale("log")
plt.xlabel("Mean squared error of ⟨ZZ⟩ and ⟨XX⟩")
plt.ylabel("Cumulative distribution function")
plt.title("CDF for different initial layouts")
plt.grid(alpha=0.3)
plt.show()
Step 1: Map classical inputs to a quantum problem
De eerst Schritt is dat, een Satz vun Kwantenschaltkresen to maken, üm all kandidaat Bell-Por-Links to benchmarken, de op de Topologie vun dat Gerat anpasst sünd. Wi dörchsöcht programmatsch de Gerat-Koppelungskoort för all linear verbunnen Keden vun veer Qubits. Jede sülke Kede (dör Qubit-Indizes tekent) deent as Testfall för den Verschrankung-Swapping-Schaltkreis. Dör dat wi all mööglichen Längde-4-Paden identifizeert, stellt wi maximale Decken för möögliche Grupperen vun Qubits seeker, de dat Protokoll realisern künnt.
service = QiskitRuntimeService()
backend = service.least_busy(operational=True)
Wi erzeugt düsse Keden, dör dat wi een Hölpfunktschon bruukt, de een gierige Sök op den Gerat-Graf dörvört. Se gifft "Striepen" vun veer Veer-Qubit-Keden torüch, de in 16-Qubit-Gruppen bündelt sünd (dynamische Schaltkresen begrenzt momentan de Grötte vun dat Metregister op 16 Qubits). Dat Bündeln verlövt uns, mehrere Veer-Qubit-Experimenten parallel op verscheden Delen vun den Chip to lopen laten un dat ganze Gerat effizient to bruken. Jede 16-Qubit-Striep enthöllt veer disjunkte Keden, dat bedüdd, dat keen Qubit binnen düsse Grupp wedder bruukt warrt. To'n Bispill künnt een Striep ut Keden , , un bestahn, all tosamen packt. Jedes Qubit, wat nich in een Striep entholln weer, warrt in de leftover Variable torüchgeven.
from itertools import chain
from collections import defaultdict
def stripes16_from_backend(backend):
"""
Creates stripes of 16 qubits, four non-overlapping four-qubit chains, that cover as much of
the coupling map as possible. Returns any unused qubits as leftovers.
"""
# get the undirected adjacency list
edges = backend.coupling_map.get_edges()
graph = defaultdict(set)
for u, v in edges:
graph[u].add(v)
graph[v].add(u)
qubits = sorted(graph) # all qubit indices that appear
# greedy search for 4-long linear chains (blocks) ────────────
used = set() # qubits already placed in a block
blocks = [] # each block is a four-qubit list
for q in qubits: # deterministic order for reproducibility
if q in used:
continue # already consumed by earlier block
# depth-first "straight" walk of length 3 without revisiting nodes
def extend(path):
if len(path) == 4:
return path
tip = path[-1]
for nbr in sorted(graph[tip]): # deterministic
if nbr not in path and nbr not in used:
maybe = extend(path + [nbr])
if maybe:
return maybe
return None
block = extend([q])
if block: # found a 4-node path
blocks.append(block)
used.update(block)
# bundle four four-qubit blocks into one 16-qubit stripe (max number of measurement compatible with if-else)
stripes = [
list(chain.from_iterable(blocks[i : i + 4]))
for i in range(0, len(blocks) // 4 * 4, 4) # full groups of four
]
leftovers = set(qubits) - set(chain.from_iterable(stripes))
return stripes, leftovers
initial_layouts, leftover = stripes16_from_backend(backend)
As nächstes konstrueert wi den Schaltkreis för jede 16-Qubit-Striep. De Rutine deit dat Folgende för jede Kede:
- Een midden Bell-Por preparern: Een Hadamard op Qubit 1 un een CNOT vun Qubit 1 na Qubit 2 anwennen. Dat verschrankt Qubits 1 un 2 (un maakt een Bell-Tostand).
- De Rand-Qubits verschranken: Een CNOT vun Qubit 0 na Qubit 1 un een CNOT vun Qubit 2 na Qubit 3 anwennen. Dat verbindt de anfänglich trennte Poren, so dat Qubits 0 un 3 na de nächsten Schritten verschrankt warrt. Een Hadamard op Qubit 2 warrt ook anwennt (dat, kombiniert mit de fröheren CNOTs, billt een Deel vun een Bell-Metung op Qubits 1 un 2). To düt Tietpunkt sünd Qubits 0 un 3 noch nich verschrankt, aver Qubits 1 un 2 sünd mit jem in een grötteren Veer-Qubit-Tostand verschrankt.
- Metungen binnen den Loop un Feedforward: Qubits 1 un 2 (de midden Qubits) warrt in de Berekeningsbasis meten, wat twee klassische Bits gifft. Baseert op düsse Metungsergebnissen wennt wi bedingte Operatschonen an: Wenn de Qubit-1-Metung (dat nömt wi Bit ) 1 is, wennt wi een -Gate op Qubit 3 an; wenn de Qubit-2-Metung () 1 is, wennt wi een -Gate op Qubit 0 an. Düsse bedingten Gates (realisiert dör dat Qiskit
if_test/if_elseKonstrukt) implementeert de standard Teleportatschonskorrekschonen. Se "maakt torüch" de tofälligen Pauli-Flips, de dör dat Projizeren vun Qubits 1 un 2 passeert, un stellt seeker, dat Qubits 0 un 3 in een bekannt Bell-Tostand ennt, unafhängig vun de Metungsergebnissen. Na düt Schritt schüllt Qubits 0 un 3 idealerwies in den Bell-Tostand verschrankt ween. - Bell-Por-Stabilisatoren meten: Wi deelt denn in twee Versionen vun den Schaltkreis. In de eerst Version meet wi den Stabilisator op Qubits 0 un 3. In de tweed Version meet wi den Stabilisator op düsse Qubits.
För jede Veer-Qubit-initial-Layout gifft de boven nömte Funktschon twee Schaltkresen torüch (een för , een för Stabilisatormetung). An't Enn vun düt Schritt hebbt wi een List vun Schaltkresen, de jede Veer-Qubit-Kede op dat Gerat deckt. Düsse Schaltkresen enthöllt Metungen binnen den Loop un bedingte (if/else) Operatschonen, wat de zentrale Anwiesungen vun den dynamischen Schaltkreis sünd.
circuits = create_bell_stab(initial_layouts)
circuits[-1].draw("mpl", fold=-1)

Step 2: Optimize the problem for quantum hardware execution
Bevör wi unse Schaltkresen op echt Hardware utföhrt, mööt wi se transpilern, üm to de physischen Begrenzen vun dat Gerat to passen. Transpileren warrt den abstrakten Schaltkreis op de physischen Qubits un Gate-Satz vun dat utsöchte Gerat mappen. Wieldat wi al spezifische physische Qubits för jede Kede utsöcht hebbt (dör dat wi een initial_layout för den Schaltkreisgenerator mitgeven hebbt), bruukt wi Transpiler optimization_level=0 mit dat feste Layout. Dat seggt Qiskit, dat dat keen Qubits wedder towiest oder swore Optimeren dörvört, de de Schaltkreisstruktur ännern künnt. Wi wüllt de Sequenz vun Operatschonen (besünners de bedingten Gates) genau so beholen, as angeven.
isa_circuits = []
for ind, init_layout in enumerate(initial_layouts):
pm = generate_preset_pass_manager(
optimization_level=0, backend=backend, initial_layout=init_layout
)
isa_circ = pm.run(circuits[ind * 2 : ind * 2 + 2])
isa_circuits.extend(isa_circ)
isa_circuits[1].draw("mpl", fold=-1, idle_wires=False)

Step 3: Execute using Qiskit primitives
Nu künnt wi dat Experiment op dat Kwantengerat lopen laten. Wi bruukt Qiskit Runtime un sien Sampler-Primitiv, üm de Charge vun Schaltkresen effizient uttofören.
sampler = Sampler(mode=backend)
sampler.options.environment.job_tags = ["cut-bell-pair-test"]
job = sampler.run(isa_circuits)
Step 4: Post-process and return result in the desired classical format
De letzt Schritt is dat, den middeln kwadratischen Afwiekmetrik (MSE) för jede testete Qubit-Grupp to berekenen un de Resultaten tosammentofaten. För jede Kede hebbt wi nu dat metene un . Wenn Qubits 0 un 3 perfekt in een Bell-Tostand verschrankt weren, würn wi verwachten, dat beeds vun düsse +1 sünd. Wi kwantifizeert den Afwiek mit den MSE:
Düsse Wert is 0 för een perfekt Bell-Por un stigt, as de verschrankte Tostand ruuschiger warrt (mit tofällige Resultaten, de een Verwachten üm 0 gifft, würr de MSE sik 1 negern). De Code berekent düssen MSE för jede Veer-Qubit-Grupp.
De Resultaten wiest een grote Spannwiet vun Verschrankungsqualitat över dat Gerat. Dat bestätigt de Entdecken vun dat Paper, dat dat över een Gröttentorden Variatschon in Bell-Tostandsfidelitat geven kann, afhängig dorvun, welke physische Qubits bruukt warrt. In praktische Begrippen bedüdd dat, dat bestimmte Regionen oder Links in den Chip veel beter dorin sünd, Metungen binnen den Loop un Feedforward-Operatschonen dörtoföhren as annere. Faktoren as Qubit-Utlesefehlers, Qubit-Levenstiet un Överspreken dragt wohrschienlich to düsse Ünnersch Eden bi. To'n Bispill, wenn een Kede een besünners ruuschig Utlesequbit enthöllt, künnt de Metung binnen den Loop untoseker ween, wat to een slecht Fidelitat för dat verschrankte Por föhrt (hoge MSE).
layouts_mse = get_mse(job.result(), initial_layouts)
layout [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
qubits: [0, 1, 2, 3], mse:, 0.0312
qubits: [4, 5, 6, 7], mse:, 0.0491
qubits: [8, 9, 10, 11], mse:, 0.0711
qubits: [12, 13, 14, 15], mse:, 0.0436
layout [16, 23, 22, 21, 17, 27, 26, 25, 18, 31, 30, 29, 19, 35, 34, 33]
qubits: [16, 23, 22, 21], mse:, 0.0197
qubits: [17, 27, 26, 25], mse:, 0.113
qubits: [18, 31, 30, 29], mse:, 0.0287
qubits: [19, 35, 34, 33], mse:, 0.0433
layout [36, 41, 42, 43, 37, 45, 46, 47, 38, 49, 50, 51, 39, 53, 54, 55]
qubits: [36, 41, 42, 43], mse:, 0.1645
qubits: [37, 45, 46, 47], mse:, 0.0409
qubits: [38, 49, 50, 51], mse:, 0.0519
qubits: [39, 53, 54, 55], mse:, 0.0829
layout [56, 63, 62, 61, 57, 67, 66, 65, 58, 71, 70, 69, 59, 75, 74, 73]
qubits: [56, 63, 62, 61], mse:, 0.8663
qubits: [57, 67, 66, 65], mse:, 0.0375
qubits: [58, 71, 70, 69], mse:, 0.0664
qubits: [59, 75, 74, 73], mse:, 0.0291
layout [76, 81, 82, 83, 77, 85, 86, 87, 78, 89, 90, 91, 79, 93, 94, 95]
qubits: [76, 81, 82, 83], mse:, 0.0598
qubits: [77, 85, 86, 87], mse:, 0.313
qubits: [78, 89, 90, 91], mse:, 0.0679
qubits: [79, 93, 94, 95], mse:, 0.0505
layout [96, 103, 102, 101, 97, 107, 106, 105, 98, 111, 110, 109, 99, 115, 114, 113]
qubits: [96, 103, 102, 101], mse:, 0.0302
qubits: [97, 107, 106, 105], mse:, 0.0384
qubits: [98, 111, 110, 109], mse:, 0.0375
qubits: [99, 115, 114, 113], mse:, 0.1051
layout [116, 121, 122, 123, 117, 125, 126, 127, 118, 129, 130, 131, 119, 133, 134, 135]
qubits: [116, 121, 122, 123], mse:, 0.1624
qubits: [117, 125, 126, 127], mse:, 0.7246
qubits: [118, 129, 130, 131], mse:, 0.5919
qubits: [119, 133, 134, 135], mse:, 0.5277
layout [136, 143, 142, 141, 137, 147, 146, 145, 138, 151, 150, 149, 139, 155, 154, 153]
qubits: [136, 143, 142, 141], mse:, 0.0383
qubits: [137, 147, 146, 145], mse:, 1.0187
qubits: [138, 151, 150, 149], mse:, 0.1531
qubits: [139, 155, 154, 153], mse:, 0.0471
To'n Sluss visualiseert wi de Gesamtperfermanz, dör dat wi de kumulative Verdeilingsfunktschon (CDF) vun de MSE-Werten för all Keden plotten. Dat CDF-Diagramm wiest de MSE-Schwelle op de x-Ass un de Fraktschon vun Qubit-Poren, de höchstens düsse MSE hebbt, op de y-Ass. Düsse Kurv fängt bi null an un negert sik eens, as de Schwelle wassen deit, üm all Datenpunkten to ümfaten. Een steile Opstieg bi een lage MSE würr anwiesen, dat veel Poren een hoge Fidelitat hebbt; een langsame Opstieg bedüdd, dat veel Poren grötere Fehlers hebbt. Wi annoteert dat CDF mit de Identitäten vun de besten Poren. In dat Diagramm entspricht jede Punkt in dat CDF een Veer-Qubit-Kede sien MSE, un wi tekent den Punkt mit dat Por vun Qubit-Indizes , de in düt Experiment verschrankt weren. Dat maakt dat eenfach, ruuttofinn, welke physische Qubit-Poren de beste Leisten hebbt (de Punkten ganz links op dat CDF).
plot_mse_ecdfs(layouts_mse, combine_layouts=True)