Hardware
Masao Tokunari e Tamiya Onodera (14 giugno 2024)
Questo corso è basato su un corso tenuto in presenza all'Università di Tokyo.
Il PDF delle lezioni di questa sezione è stato suddiviso in due parti. Scarica la parte 1 e scarica la parte 2. Tieni presente che alcuni frammenti di codice potrebbero diventare obsoleti poiché si tratta di immagini statiche.
1. Introduzione
Questa lezione esplora l'hardware moderno per il calcolo quantistico.
Inizieremo verificando alcune versioni e importando i pacchetti necessari.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
import statistics
from qiskit_ibm_runtime import QiskitRuntimeService
2. Backend e Target
Qiskit fornisce un'API per ottenere informazioni, sia statiche che dinamiche, su un dispositivo quantistico. Si utilizza un'istanza Backend per interfacciarsi con un dispositivo; essa include un'istanza Target, un modello astratto della macchina che riassume le caratteristiche rilevanti, come l'architettura del set di istruzioni (ISA) e le proprietà o i vincoli associati. Utilizziamo queste istanze backend per ottenere alcune delle informazioni visibili nella pagina Compute resources su IBM Quantum® Platform. Per prima cosa, creiamo un'istanza backend per il dispositivo di interesse. Nel codice seguente, scegliamo "ibm_kyoto", "ibm_kawasaki" oppure la macchina Eagle meno occupata. L'accesso ai QPU potrebbe variare; aggiorna il nome del backend di conseguenza.
service = QiskitRuntimeService()
# backend = service.backend("ibm_kawasaki") # an Eagle, if you have access to ibm_kawasaki
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
) # Eagle
backend.name
'ibm_strasbourg'
Iniziamo con alcune informazioni di base (statiche) sul dispositivo.
print(
f"""
{backend.name}, {backend.num_qubits} qubits
processor type = {backend.processor_type}
basis gates = {backend.basis_gates}
"""
)
ibm_strasbourg, 127 qubits
processor type = {'family': 'Eagle', 'revision': 3}
basis gates = ['ecr', 'id', 'rz', 'sx', 'x']
2.1 Esercizio
Prova a ottenere le informazioni di base su un dispositivo Heron, "ibm_strasbourg". Fallo da solo, ma di seguito è stato aggiunto del codice per permetterti di verificare la tua soluzione.
a_heron = service.backend("ibm_strasbourg") # a Heron
# your code here
print(
f"""
{backend.name}, {a_heron.num_qubits} qubits
processor type = {a_heron.processor_type}
basis gates = {a_heron.basis_gates}
"""
)
ibm_strasbourg, 133 qubits
processor type = {'family': 'Heron', 'revision': '1'}
basis gates = ['cz', 'id', 'rz', 'sx', 'x']
2.2 Mappa di accoppiamento
Ora disegniamo la mappa di accoppiamento del dispositivo. Come puoi vedere, i nodi rappresentano i qubit, numerati progressivamente. Gli archi indicano le coppie su cui è possibile applicare direttamente il gate di entanglement a 2 qubit. La topologia è chiamata "heavy-hex lattice".
# This function requires that Graphviz is installed. If you need to install Graphviz you can refer to:
# https://graphviz.org/download/#executable-packages for instructions.
try:
fig = backend.coupling_map.draw()
except RuntimeError as ex:
print(ex)
fig

3. Proprietà dei qubit
Il dispositivo Eagle ha 127 qubit. Otteniamo le proprietà di alcuni di essi.
for qn in range(backend.num_qubits):
if qn >= 5:
break
print(f"{qn}: {backend.qubit_properties(qn)}")
0: QubitProperties(t1=0.000183686508736532, t2=0.00023613944465408068, frequency=4832100227.116953)
1: QubitProperties(t1=0.00048794378526038294, t2=9.007098375327869e-05, frequency=4736264354.075363)
2: QubitProperties(t1=0.00021247781834456527, t2=7.81037910324034e-05, frequency=4859349851.150393)
3: QubitProperties(t1=0.0002936462084765663, t2=0.00011400214529510604, frequency=4679749549.503852)
4: QubitProperties(t1=0.00044229440258559125, t2=0.0003181648356339447, frequency=4845872064.050596)
Calcoliamo la mediana dei tempi T1 dei qubit. Confronta il risultato con quello mostrato per il dispositivo su IBM Quantum Platform.
t1s = [backend.qubit_properties(qq).t1 for qq in range(backend.num_qubits)]
f"Median T1: {(statistics.median(t1s)*10**6):.2f} \u03bcs"
'Median T1: 285.43 μs'
3.1 Esercizio
Calcola la mediana dei tempi T2 dei qubit. Fallo da solo, ma di seguito è stato aggiunto del codice per permetterti di verificare la tua soluzione.
# Your code here
t2s = [backend.qubit_properties(qq).t2 for qq in range(backend.num_qubits)]
f"Median T2: {(statistics.median(t2s)*10**6):.2f} \u03bcs"
'Median T2: 173.10 μs'
3.2 Errori di gate e di lettura
Passiamo ora agli errori di gate. Per iniziare, studiamo la struttura dati dell'istanza target. Si tratta di un dizionario le cui chiavi sono i nomi delle operazioni.
target = backend.target
target.keys()
dict_keys(['measure', 'id', 'sx', 'delay', 'x', 'for_loop', 'rz', 'if_else', 'ecr', 'reset', 'switch_case'])
Anche i valori sono dizionari. Esaminiamo alcuni degli elementi del valore (dizionario) per l'operazione 'sx'.
for i, qq in enumerate(target["sx"]):
if i >= 5:
break
print(i, qq, target["sx"][qq])
0 (0,) InstructionProperties(duration=6e-08, error=0.0007401311759115297)
1 (1,) InstructionProperties(duration=6e-08, error=0.0003163759907528654)
2 (2,) InstructionProperties(duration=6e-08, error=0.0003183859004638003)
3 (3,) InstructionProperties(duration=6e-08, error=0.00042235914178831863)
4 (4,) InstructionProperties(duration=6e-08, error=0.011163151923589715)
Facciamo lo stesso per le operazioni 'ecr' e 'measure'.
for i, edge in enumerate(target["ecr"]):
if i >= 5:
break
print(i, edge, target["ecr"][edge])
0 (0, 14) InstructionProperties(duration=6.6e-07, error=0.01486295709788732)
1 (1, 0) InstructionProperties(duration=6.6e-07, error=0.015201590794522601)
2 (2, 1) InstructionProperties(duration=6.6e-07, error=0.00697838102630724)
3 (2, 3) InstructionProperties(duration=6.6e-07, error=0.008075067943986797)
4 (3, 4) InstructionProperties(duration=6.6e-07, error=0.0630164507876913)
for i, qq in enumerate(target["measure"]):
if i >= 5:
break
print(i, qq, target["measure"][qq])
0 (0,) InstructionProperties(duration=1.6e-06, error=0.0078125)
1 (1,) InstructionProperties(duration=1.6e-06, error=0.155029296875)
2 (2,) InstructionProperties(duration=1.6e-06, error=0.057373046875)
3 (3,) InstructionProperties(duration=1.6e-06, error=0.02880859375)
4 (4,) InstructionProperties(duration=1.6e-06, error=0.01318359375)
Come puoi vedere, gli errori di lettura tendono ad essere maggiori di quelli delle operazioni a 2 qubit, che a loro volta tendono ad essere maggiori di quelli delle operazioni a 1 qubit.
Dopo aver compreso le strutture dati, siamo pronti a calcolare gli errori mediani per i gate 'sx' e 'ecr'. Ancora una volta, confronta i risultati con quelli mostrati per il dispositivo su IBM Quantum Platform.
sx_errors = [inst_prop.error for inst_prop in target["sx"].values()]
f"Median SX error: {(statistics.median(sx_errors)):.3e}"
'Median SX error: 2.277e-04'
ecr_errors = [inst_prop.error for inst_prop in target["ecr"].values()]
f"Median ECR error: {(statistics.median(ecr_errors)):.3e}"
'Median ECR error: 6.895e-03'
4. Appendice
Una funzionalità molto apprezzata di Qiskit è la sua capacità di visualizzazione. Include visualizzatori per circuito, stati, distribuzioni e target. Hai già utilizzato i primi due nei notebook Jupyter precedenti. Usiamo ora alcune funzionalità del visualizzatore di target.
from qiskit.visualization import plot_gate_map
plot_gate_map(backend, font_size=14)

from qiskit.visualization import plot_error_map
plot_error_map(backend)

# Check Qiskit version
import qiskit
qiskit.__version__
'2.0.2'