Saltar al contenido principal
Este proyecto está en fase beta. ¿Encontraste un error? Abre un issue en GitHub. ¿Tienes una pregunta o una idea? Pregunta en Discussions — ¡nos encantaría tu opinión!
¿Cómo es la calidad de la traducción en esta página?

Hardware

nota

Masao Tokunari y Tamiya Onodera (14 de junio de 2024)

Este curso está basado en un curso en vivo en la Universidad de Tokio.

El PDF de la clase de esta lección se dividió en dos partes. Descargar parte 1 y Descargar parte 2. Ten en cuenta que algunos fragmentos de código pueden estar desactualizados, ya que son imágenes estáticas.

1. Introducción​

Esta lección explora el hardware moderno de computación cuántica.

Comenzamos verificando algunas versiones e importando los paquetes relevantes.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
import statistics

from qiskit_ibm_runtime import QiskitRuntimeService

2. Backend y Target​

Qiskit ofrece una API para obtener tanto información estática como dinámica sobre un dispositivo cuántico. Utilizamos una instancia de Backend como interfaz con un dispositivo. Esta contiene una instancia de Target – un modelo abstracto de máquina que resume las propiedades esenciales, como la Instruction Set Architecture (ISA) y las propiedades y restricciones asociadas. Utilicemos estas instancias de Backend para obtener parte de la información que ves en la página de Compute resources de IBM Quantum® Platform. Primero, creamos una instancia de Backend para un dispositivo de nuestra elección. En el siguiente ejemplo utilizamos "ibm_kyoto", "ibm_kawasaki" o la máquina Eagle menos ocupada. Tu acceso a QPUs puede variar – ajusta 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.name
'ibm_strasbourg'

Comencemos con alguna 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}
"""
)
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 primero por tu cuenta – más abajo encontrarás un código de solución para comparar.

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 Mapa de acoplamiento​

Ahora dibujamos el mapa de acoplamiento del dispositivo. Como puedes ver, los nodos representan qubits numerados. Las aristas indican los pares a los que se puede aplicar directamente la puerta de entrelazamiento de 2 qubits. La topología se denomina "red Heavy-Hex".

# 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

Output of the previous code cell

3. Propiedades de los qubits​

El dispositivo Eagle tiene 127 qubits. Veamos las propiedades de algunos de ellos.

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)

Calculemos la mediana de los tiempos T1 de los qubits. Compara el resultado con lo que se muestra para el dispositivo en la 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 Ejercicio​

Calcula la mediana de los tiempos T2 de los qubits. Pruébalo primero por tu cuenta – más abajo encontrarás un código de solución para comparar.

# 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 Errores de puertas y de lectura​

Ahora nos centramos en los errores de puertas. Primero examinamos la estructura de datos de la instancia Target. Es un diccionario cuyas claves son nombres de operaciones.

target = backend.target
target.keys()
dict_keys(['measure', 'id', 'sx', 'delay', 'x', 'for_loop', 'rz', 'if_else', 'ecr', 'reset', 'switch_case'])

Los valores también son diccionarios. Veamos algunas entradas del diccionario de valores para la operación '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)

Hagamos lo mismo para las operaciones 'ecr' y '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)

Como se puede ver, los errores de lectura suelen ser mayores que los errores de las operaciones de 2 qubits, que a su vez suelen ser mayores que los de las operaciones de 1 qubit.

Ahora que entendemos las estructuras de datos, podemos calcular los errores medianos para las puertas 'sx' y 'ecr'. Compara nuevamente los resultados con los del dispositivo en 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. Apéndice​

Una característica especialmente popular de Qiskit es su capacidad de visualización. Incluye visualizadores de circuitos, visualizadores de estados y distribuciones, y un visualizador de Target. Los dos primeros ya los has utilizado en los Jupyter notebooks anteriores. Veamos ahora algunas funciones del visualizador de Target.

from qiskit.visualization import plot_gate_map

plot_gate_map(backend, font_size=14)

Output of the previous code cell

from qiskit.visualization import plot_error_map

plot_error_map(backend)

Output of the previous code cell

# Check Qiskit version
import qiskit

qiskit.__version__
'2.0.2'