Hardware del sistema
Masao Tokunari y Tamiya Onodera (14 de junio de 2024)
Este curso se basa en un curso presencial impartido en la Universidad de Tokio.
El pdf de esta lección está dividido en dos partes. Descargue la parte 1 y descargue la parte 2. Tenga en cuenta que algunos fragmentos de código podrían quedar obsoletos, ya que se trata de imágenes estáticas.
1. Introducción
Esta lección explora el hardware moderno de la computación cuántica.
Empezaremos verificando algunas versiones e importando algunos paquetes relevantes.
import statistics
from qiskit_ibm_runtime import QiskitRuntimeService2. Backend y objetivo
Qiskit proporciona una API para obtener la información, tanto estática como dinámica, sobre un dispositivo cuántico. Utilizamos una instancia Backend para interactuar con un dispositivo, que incluye una instancia Target, un modelo abstracto de máquina que resume las características pertinentes, como su arquitectura de conjunto de instrucciones (ISA) y cualquier propiedad o restricción asociada a ella. Utilicemos estas instancias backend para obtener parte de la información que se ve en la página Recursos informáticos en IBM Quantum® Platform. En primer lugar, creamos una instancia de backend para un dispositivo de interés. A continuación, elegimos "ibm_kyoto", "ibm_kawasaki" o la máquina Eagle menos ocupada. Su acceso a las QPU puede diferir; actualice el nombre del backend en consecuencia.
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.nameOutput:
'ibm_strasbourg'
Empezamos con información básica (estática) sobre el dispositivo.
print(
f"""
{backend.name}, {backend.num_qubits} qubits
processor type = {backend.processor_type}
basis gates = {backend.basis_gates}
"""
)Output:
ibm_strasbourg, 127 qubits
processor type = {'family': 'Eagle', 'revision': 3}
basis gates = ['ecr', 'id', 'rz', 'sx', 'x']
2.1 Ejercicio
Intenta obtener la información básica sobre un dispositivo Heron, "ibm_strasbourg". Pruébalo por tu cuenta, pero a continuación se ha añadido un código para que lo compruebes tú mismo.
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}
"""
)Output:
ibm_strasbourg, 133 qubits
processor type = {'family': 'Heron', 'revision': '1'}
basis gates = ['cz', 'id', 'rz', 'sx', 'x']
2.2 Mapa de acoplamiento
Ahora dibujamos el mapa de acoplamiento del dispositivo. Como puedes ver, los nodos son qubits que están numerados. Los bordes indican los pares a los que se puede aplicar directamente la puerta de enredo de 2 qubits. La topología se denomina "celosía de hexágonos pesados".
# 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)
figOutput:
3. Propiedades del qubit
El dispositivo Eagle tiene 127 qubits. Obtengamos las propiedades de algunos de ellos.
for qn in range(backend.num_qubits):
if qn >= 5:
break
print(f"{qn}: {backend.qubit_properties(qn)}")Output:
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)
Calculemos la mediana de los tiempos T1 de los qubits. Compare el resultado con el mostrado para el dispositivo en 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"Output:
'Median T1: 285.43 μs'
3.1 Ejercicio
Pease calcular la mediana de T2 tiempos de los qubits. Pruébalo por tu cuenta, pero a continuación se ha añadido un código para que lo compruebes tú mismo.
# 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"Output:
'Median T2: 173.10 μs'
3.2 Errores de puerta y lectura
Pasemos ahora a los errores de puerta. Para empezar, estudiamos la estructura de datos de la instancia objetivo. Es un diccionario cuyas claves son los nombres de las operaciones.
target = backend.target
target.keys()Output:
dict_keys(['measure', 'id', 'sx', 'delay', 'x', 'for_loop', 'rz', 'if_else', 'ecr', 'reset', 'switch_case'])
Sus valores también son diccionarios. Veamos algunos de los elementos del valor (diccionario) para la operación "sx".
for i, qq in enumerate(target["sx"]):
if i >= 5:
break
print(i, qq, target["sx"][qq])Output:
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)
Hagamos lo mismo con las operaciones "ecr" y "measure".
for i, edge in enumerate(target["ecr"]):
if i >= 5:
break
print(i, edge, target["ecr"][edge])Output:
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])Output:
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)
Como puede verse, los errores de lectura tienden a ser mayores que los de la operación de 2 qubits, que a su vez tienden a ser mayores que los de la operación de 1 qubit.
Una vez comprendidas las estructuras de datos, estamos preparados para calcular los errores medios de las puertas 'sx' y 'ecr'. De nuevo, compare los resultados con los mostrados para el dispositivo en la plataforma IBM Quantum.
sx_errors = [inst_prop.error for inst_prop in target["sx"].values()]
f"Median SX error: {(statistics.median(sx_errors)):.3e}"Output:
'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}"Output:
'Median ECR error: 6.895e-03'
4. Apéndice
Una de las características más populares de Qiskit es su capacidad de visualización. Incluye visualizadores de circuitos, de estados y de distribución, y de objetivos. Ya has utilizado los dos primeros en los cuadernos jupyter anteriores. Utilicemos algunas capacidades del visualizador de destino.
from qiskit.visualization import plot_gate_map
plot_gate_map(backend, font_size=14)Output:
from qiskit.visualization import plot_error_map
plot_error_map(backend)Output:
# Check Qiskit version
import qiskit
qiskit.__version__Output:
'2.0.2'