Saltar al contenido principal

Transición de fase de Nishimori

Estimación de uso: 3 minutos en un procesador Heron r2 (NOTA: Esto es solo una estimación. Su tiempo de ejecución podría variar.)

Contexto

Este tutorial demuestra cómo realizar una transición de fase de Nishimori en un procesador cuántico de IBM®. Este experimento fue descrito originalmente en Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits.

La transición de fase de Nishimori se refiere a la transición entre fases con orden de corto y largo alcance en el modelo de Ising con enlaces aleatorios. En una computadora cuántica, la fase con orden de largo alcance se manifiesta como un estado en el que los qubits están entrelazados a lo largo de todo el dispositivo. Este estado altamente entrelazado se prepara utilizando el protocolo de generación de entrelazamiento por medición (GEM, por sus siglas en inglés). Mediante el uso de mediciones a mitad de circuito, el protocolo GEM es capaz de entrelazar qubits a lo largo de todo el dispositivo utilizando circuitos de profundidad constante. Este tutorial utiliza la implementación del protocolo GEM del paquete de software GEM Suite.

Requisitos

Antes de comenzar este tutorial, asegúrate de tener instalado lo siguiente:

  • Qiskit SDK v1.0 o posterior, con soporte de visualización
  • Qiskit Runtime v0.22 o posterior ( pip install qiskit-ibm-runtime )
  • GEM Suite ( pip install gem-suite )

Configuración

# Added by doQumentation — required packages for this notebook
!pip install -q gem-suite matplotlib qiskit qiskit-ibm-runtime
import matplotlib.pyplot as plt

from collections import defaultdict

from qiskit_ibm_runtime import QiskitRuntimeService

from qiskit.transpiler import generate_preset_pass_manager

from gem_suite import PlaquetteLattice
from gem_suite.experiments import GemExperiment

Paso 1: Mapear entradas clásicas a un problema cuántico

El protocolo GEM opera sobre un procesador cuántico cuya conectividad de qubits se describe mediante una red (lattice). Los procesadores cuánticos actuales de IBM utilizan la red heavy hex. Los qubits del procesador se agrupan en plaquetas según la celda unitaria de la red a la que pertenecen. Dado que un qubit puede pertenecer a más de una celda unitaria, las plaquetas no son disjuntas. En la red heavy hex, una plaqueta contiene 12 qubits. Las plaquetas en sí también forman una red, donde dos plaquetas están conectadas si comparten algún qubit. En la red heavy hex, las plaquetas vecinas comparten 3 qubits.

En el paquete de software GEM Suite, la clase fundamental para implementar el protocolo GEM es PlaquetteLattice, que representa la red de plaquetas (la cual es distinta de la red heavy hex). Un PlaquetteLattice se puede inicializar a partir de un mapa de acoplamiento de qubits. Actualmente, solo se admiten mapas de acoplamiento heavy hex.

La siguiente celda de código inicializa una red de plaquetas a partir del mapa de acoplamiento de un procesador cuántico de IBM. La red de plaquetas no siempre abarca todo el hardware. Por ejemplo, ibm_torino tiene 133 qubits en total, pero la red de plaquetas más grande que cabe en el dispositivo utiliza solo 125 de ellos y comprende un total de 18 plaquetas. Lo mismo se puede observar en dispositivos de IBM Quantum® con diferentes cantidades de qubits.

# QiskitRuntimeService.save_account(channel="ibm_quantum", token="<YOUR_API_KEY>", overwrite=True, set_as_default=True)
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
plaquette_lattice = PlaquetteLattice.from_coupling_map(backend.coupling_map)

print(f"Number of qubits in backend: {backend.num_qubits}")
print(
f"Number of qubits in plaquette lattice: {len(list(plaquette_lattice.qubits()))}"
)
print(f"Number of plaquettes: {len(list(plaquette_lattice.plaquettes()))}")
Number of qubits in backend: 133
Number of qubits in plaquette lattice: 125
Number of plaquettes: 18

Puedes visualizar la red de plaquetas generando un diagrama de su representación en forma de grafo. En el diagrama, las plaquetas se representan mediante hexágonos etiquetados, y dos plaquetas están conectadas por una arista si comparten qubits.

plaquette_lattice.draw_plaquettes()

Output of the previous code cell

Puedes obtener información sobre plaquetas individuales, como los qubits que contienen, utilizando el método plaquettes.

# Get a list of the plaquettes
plaquettes = list(plaquette_lattice.plaquettes())
# Display information about plaquette 0
plaquettes[0]
PyPlaquette(index=0, qubits=[0, 1, 2, 3, 4, 15, 16, 19, 20, 21, 22, 23], neighbors=[3, 1])

También puede generar un diagrama de los qubits subyacentes que forman la red de plaquetas.

plaquette_lattice.draw_qubits()

Output of the previous code cell

Además de las etiquetas de los qubits y las aristas que indican qué qubits están conectados, el diagrama contiene tres elementos adicionales de información relevantes para el protocolo GEM:

  • Cada qubit está sombreado (gris) o sin sombrear. Los qubits sombreados son qubits de "sitio" que representan los sitios del modelo de Ising, y los qubits sin sombrear son qubits de "enlaza" utilizados para mediar las interacciones entre los qubits de sitio.
  • Cada qubit de sitio está etiquetado como (A) o (B), indicando uno de los dos roles que un qubit de sitio puede desempeñar en el protocolo GEM (los roles se explican más adelante).
  • Cada arista está coloreada usando uno de seis colores, particionando así las aristas en seis grupos. Esta partición determina cómo se pueden paralelizar las compuertas de dos qubits, así como diferentes patrones de programación que probablemente incurran en diferentes cantidades de error en un procesador cuántico ruidoso. Dado que las aristas de un grupo son disjuntas, una capa de compuertas de dos qubits puede aplicarse simultáneamente sobre esas aristas. De hecho, es posible dividir los seis colores en tres grupos de dos colores de manera que la unión de cada grupo de dos colores sigue siendo disjunta. Por lo tanto, solo se necesitan tres capas de compuertas de dos qubits para activar todas las aristas. Existen 12 formas de particionar los seis colores de esta manera, y cada una de estas particiones produce un programa de 3 capas de compuertas diferente.

Ahora que ha creado una red de plaquetas, el siguiente paso es inicializar un objeto GemExperiment, pasando tanto la red de plaquetas como el backend en el que pretende ejecutar el experimento. La clase GemExperiment gestiona la implementación real del protocolo GEM, incluyendo la generación de circuitos, el envío de trabajos y el análisis de los datos. La siguiente celda de código inicializa la clase del experimento restringiendo la red de plaquetas a solo dos de las plaquetas (21 qubits), reduciendo el tamaño del experimento para asegurar que el ruido del hardware no domine la señal.

gem_exp = GemExperiment(plaquette_lattice.filter([9, 12]), backend=backend)

# visualize the plaquette lattice after filtering
plaquette_lattice.filter([9, 12]).draw_qubits()

Output of the previous code cell

Un circuito del protocolo GEM se construye siguiendo estos pasos:

  1. Preparar el estado +|+\rangle en todos los qubits aplicando una compuerta Hadamard a cada qubit.
  2. Aplicar una compuerta RZZR_{ZZ} entre cada par de qubits conectados. Esto se puede lograr usando 3 capas de compuertas. Cada compuerta RZZR_{ZZ} actúa sobre un qubit de sitio y un qubit de enlace. Si el qubit de sitio está etiquetado como (B), entonces el ángulo se fija en π2\frac{\pi}{2}. Si el qubit de sitio está etiquetado como (A), entonces se permite que el ángulo varíe, produciendo diferentes circuitos. Por defecto, el rango de ángulos se establece en 21 puntos igualmente espaciados entre 00 y π2\frac{\pi}{2}, inclusive.
  3. Medir cada qubit de enlace en la base de Pauli XX. Dado que los qubits se miden en la base de Pauli ZZ, esto se puede lograr aplicando una compuerta Hadamard antes de medir el qubit.

Ten en cuenta que el artículo citado en la introducción de este tutorial utiliza una convención diferente para el ángulo RZZR_{ZZ}, que difiere de la convención utilizada en este tutorial por un factor de 2.

En el paso 3, solo se miden los qubits de enlace. Para entender en qué estado permanecen los qubits de sitio, es instructivo considerar el caso en que el ángulo RZZR_{ZZ} aplicado a los qubits de sitio (A) en el paso 2 es igual a π2\frac{\pi}{2}. En este caso, los qubits de sitio quedan en un estado altamente entrelazado similar al estado GHZ,

GHZ=0000+1111.\lvert \text{GHZ} \rangle = \lvert 00 \cdots 00 \rangle + \lvert 11 \cdots 11 \rangle.

Debido a la aleatoriedad en los resultados de medición, el estado real de los qubits de sitio podría ser un estado diferente con orden de largo alcance, por ejemplo, 00110+11001\lvert 00110 \rangle + \lvert 11001 \rangle. Sin embargo, el estado GHZ se puede recuperar aplicando una operación de decodificación basada en los resultados de medición. Cuando el ángulo RZZR_{ZZ} se reduce desde π2\frac{\pi}{2}, el orden de largo alcance aún se puede recuperar hasta un ángulo crítico, que en ausencia de ruido es aproximadamente 0.3π0.3 \pi. Por debajo de este ángulo, el estado resultante ya no exhibe entrelazamiento de largo alcance. Esta transición entre la presencia y la ausencia de orden de largo alcance es la transición de fase de Nishimori.

En la descripción anterior, los qubits de sitio se dejaron sin medir, y la operación de decodificación puede realizarse aplicando compuertas cuánticas. En el experimento tal como se implementa en GEM Suite, que es el que sigue este tutorial, los qubits de sitio sí se miden, y la operación de decodificación se aplica en un paso de posprocesamiento clásico.

En la descripción anterior, la operación de decodificación puede realizarse aplicando compuertas cuánticas a los qubits de sitio para recuperar el estado cuántico. Sin embargo, si el objetivo es medir inmediatamente el estado, por ejemplo, con fines de caracterización, entonces los qubits de sitio se miden junto con los qubits de enlace, y la operación de decodificación puede aplicarse en un paso de posprocesamiento clásico. Así es como se implementa el experimento en GEM Suite, que es el que sigue este tutorial.

Además de depender del ángulo RZZR_{ZZ} en el paso 2, que por defecto recorre 21 valores, el circuito del protocolo GEM también depende del patrón de programación utilizado para implementar las 3 capas de compuertas RZZR_{ZZ}. Como se discutió previamente, existen 12 de estos patrones de programación. Por lo tanto, el número total de circuitos en el experimento es 21×12=25221 \times 12 = 252.

Los circuitos del experimento se pueden generar utilizando el método circuits de la clase GemExperiment.

circuits = gem_exp.circuits()
print(f"Total number of circuits: {len(circuits)}")
Total number of circuits: 252

Para los propósitos de este tutorial, es suficiente considerar un solo patrón de programación. La siguiente celda de código restringe el experimento al primer patrón de programación. Como resultado, el experimento tiene solo 21 circuitos, uno para cada ángulo RZZR_{ZZ} recorrido.

# Restrict experiment to the first scheduling pattern
gem_exp.set_experiment_options(schedule_idx=0)

# There are less circuits now
circuits = gem_exp.circuits()
print(f"Total number of circuits: {len(circuits)}")

# Print the RZZ angles swept over
print(f"RZZ angles:\n{gem_exp.parameters()}")
Total number of circuits: 21
RZZ angles:
[0. 0.07853982 0.15707963 0.23561945 0.31415927 0.39269908
0.4712389 0.54977871 0.62831853 0.70685835 0.78539816 0.86393798
0.9424778 1.02101761 1.09955743 1.17809725 1.25663706 1.33517688
1.41371669 1.49225651 1.57079633]

La siguiente celda de código dibuja un diagrama del circuito en el índice 5. Para reducir el tamaño del diagrama, se eliminan las compuertas de medición al final del circuito.

# Get the circuit at index 5
circuit = circuits[5]
# Remove the final measurements to ease visualization
circuit.remove_final_measurements()
# Draw the circuit
circuit.draw("mpl", fold=-1, scale=0.5)

Output of the previous code cell

Paso 2: Optimizar el problema para la ejecución en hardware cuántico

La transpilación de circuitos cuánticos para su ejecución en hardware generalmente involucra varias etapas. Típicamente, las etapas que conllevan mayor costo computacional son la elección de la disposición de qubits, el enrutamiento de las compuertas de dos qubits para ajustarse a la conectividad del hardware, y la optimización del circuito para minimizar el conteo y la profundidad de compuertas. En el protocolo GEM, las etapas de disposición y enrutamiento son innecesarias porque la conectividad del hardware ya está incorporada en el diseño del protocolo. Los circuitos ya tienen una disposición de qubits, y las compuertas de dos qubits ya están mapeadas sobre conexiones nativas. Además, para preservar la estructura del circuito a medida que varía el ángulo RZZR_{ZZ}, solo se debe realizar una optimización de circuito muy básica.

La clase GemExperiment transpila los circuitos de forma transparente al ejecutar el experimento. Las etapas de disposición y enrutamiento ya están anuladas por defecto para no hacer nada, y la optimización de circuitos se realiza a un nivel que solo optimiza compuertas de un solo qubit. Sin embargo, puede anular o pasar opciones adicionales utilizando el método set_transpile_options. Para fines de visualización, la siguiente celda de código transpila manualmente el circuito mostrado previamente y dibuja el circuito transpilado.

# Demonstrate setting transpile options
gem_exp.set_transpile_options(
optimization_level=1 # This is the default optimization level
)
pass_manager = generate_preset_pass_manager(
backend=backend,
initial_layout=list(gem_exp.physical_qubits),
**dict(gem_exp.transpile_options),
)
transpiled = pass_manager.run(circuit)
transpiled.draw("mpl", idle_wires=False, fold=-1, scale=0.5)

Output of the previous code cell

Paso 3: Ejecutar utilizando primitivas de Qiskit

Para ejecutar los circuitos del protocolo GEM en el hardware, llama al método run del objeto GemExperiment. Puede especificar el número de shots que desea muestrear de cada circuito. El método run devuelve un objeto ExperimentData que debe guardar en una variable. Ten en cuenta que el método run solo envía los trabajos sin esperar a que terminen, por lo que es una llamada no bloqueante.

exp_data = gem_exp.run(shots=10_000)

Para esperar los resultados, llama al método block_for_results del objeto ExperimentData. Esta llamada hará que el intérprete se detenga hasta que los trabajos hayan finalizado.

exp_data.block_for_results()
ExperimentData(GemExperiment, d0d5880a-34c1-4aab-a7b6-c4f58516bc03, job_ids=['cwg12ptmptp00082khhg'], metadata=<5 items>, figure_names=['two_point_correlation.svg', 'normalized_variance.svg', 'plaquette_ops.svg', 'bond_ops.svg'])

Paso 4: Posprocesar y devolver el resultado en el formato clásico deseado

A un ángulo RZZR_{ZZ} de π2\frac{\pi}{2}, el estado decodificado sería el estado GHZ en ausencia de ruido. El orden de largo alcance del estado GHZ se puede visualizar graficando la magnetización de las cadenas de bits medidas. La magnetización MM se define como la suma de los operadores de Pauli ZZ de un solo qubit,

M=j=1NZj,M = \sum_{j=1}^N Z_j,

donde NN es el número de qubits de sitio. Su valor para una cadena de bits es igual a la diferencia entre el número de ceros y el número de unos. Medir el estado GHZ produce el estado de todos ceros o el estado de todos unos con igual probabilidad, por lo que la magnetización sería +N+N la mitad de las veces y N-N la otra mitad. En presencia de errores debidos al ruido, también aparecerían otros valores, pero si el ruido no es demasiado grande, la distribución seguiría estando concentrada cerca de +N+N y N-N.

Para las cadenas de bits sin procesar antes de la decodificación, la distribución de la magnetización sería equivalente a la de cadenas de bits uniformemente aleatorias, en ausencia de ruido.

La siguiente celda de código grafica la magnetización de las cadenas de bits sin procesar y las cadenas de bits decodificadas al ángulo RZZR_{ZZ} de π2\frac{\pi}{2}.

def magnetization_distribution(
counts_dict: dict[str, int],
) -> dict[str, float]:
"""Compute magnetization distribution from counts dictionary."""
# Construct dictionary from magnetization to count
mag_dist = defaultdict(float)
for bitstring, count in counts_dict.items():
mag = bitstring.count("0") - bitstring.count("1")
mag_dist[mag] += count
# Normalize
shots = sum(counts_dict.values())
for mag in mag_dist:
mag_dist[mag] /= shots
return mag_dist

# Get counts dictionaries with and without decoding
data = exp_data.data()
# Get the last data point, which is at the angle for the GHZ state
raw_counts = data[-1]["counts"]
# Without decoding
site_indices = [
i for i, q in enumerate(gem_exp.plaquettes.qubits()) if q.role == "Site"
]
site_raw_counts = defaultdict(int)
for key, val in raw_counts.items():
site_str = "".join(key[-1 - i] for i in site_indices)
site_raw_counts[site_str] += val
# With decoding
_, site_decoded_counts = gem_exp.plaquettes.decode_outcomes(
raw_counts, return_counts=True
)

# Compute magnetization distribution
raw_magnetization = magnetization_distribution(site_raw_counts)
decoded_magnetization = magnetization_distribution(site_decoded_counts)

# Plot
plt.bar(*zip(*raw_magnetization.items()), label="raw")
plt.bar(*zip(*decoded_magnetization.items()), label="decoded", width=0.3)
plt.legend()
plt.xlabel("Magnetization")
plt.ylabel("Frequency")
plt.title("Magnetization distribution with and without decoding")
Text(0.5, 1.0, 'Magnetization distribution with and without decoding')

Output of the previous code cell

Para caracterizar el orden de largo alcance de manera más rigurosa, puede examinar la correlación promedio de dos puntos ff, definida como

f=1N2(M2M2).f = \frac{1}{N^2} \left(\langle M^2 \rangle - \langle M \rangle ^2\right).

Un valor más alto indica un mayor grado de entrelazamiento. La clase GemExperiment calcula automáticamente este valor para las cadenas de bits decodificadas como parte del procesamiento de los datos experimentales. Almacena una figura que es accesible a través del método figure de la clase de datos del experimento. En este caso, el nombre de la figura es two_point_correlation.

exp_data.figure("two_point_correlation")

Output of the previous code cell

Para determinar el punto crítico de la transición de fase de Nishimori, puede observar la varianza normalizada de M2/NM^2 / N, definida como

g=1N3(M4M22),g = \frac{1}{N^3} \left(\langle M^4 \rangle - \langle M^2 \rangle^2\right),

que cuantifica la cantidad de fluctuación en la magnetización al cuadrado. Este valor se maximiza en el punto crítico de la transición de fase de Nishimori. En ausencia de ruido, el punto crítico ocurre aproximadamente en 0.3π0.3 \pi. En presencia de ruido, el punto crítico se desplaza hacia arriba, pero la transición de fase aún se observa siempre que el punto crítico ocurra por debajo de 0.5π0.5 \pi.

exp_data.figure("normalized_variance")

Output of the previous code cell

Escalar el experimento

Las siguientes celdas de código ejecutan el experimento para seis plaquetas (49 qubits) y las 12 plaquetas completas (125 qubits) y grafican la varianza normalizada. A medida que el experimento se escala a tamaños mayores, la mayor cantidad de ruido desplaza el punto crítico hacia la derecha.

gem_exp = GemExperiment(
plaquette_lattice.filter(range(3, 9)), backend=backend
)
gem_exp.set_experiment_options(schedule_idx=0)
exp_data = gem_exp.run(shots=10_000)
exp_data.block_for_results()
exp_data.figure("normalized_variance")

Output of the previous code cell

gem_exp = GemExperiment(plaquette_lattice, backend=backend)
gem_exp.set_experiment_options(schedule_idx=0)
exp_data = gem_exp.run(shots=10_000)
exp_data.block_for_results()
exp_data.figure("normalized_variance")

Output of the previous code cell

Conclusión

En este tutorial, realizaste una transición de fase de Nishimori en un procesador cuántico utilizando el protocolo GEM. Las métricas que examinó durante el posprocesamiento, en particular la correlación de dos puntos y la varianza normalizada, sirven como referencias de la capacidad del dispositivo para generar estados entrelazados de largo alcance. Estas referencias extienden la utilidad del protocolo GEM más allá de explorar física interesante. Como parte del protocolo, entrelazaste qubits a lo largo de todo el dispositivo utilizando circuitos de profundidad constante. Esta hazaña solo es posible gracias al uso de mediciones a mitad de circuito por parte del protocolo. En este experimento, el estado entrelazado fue medido inmediatamente, pero una vía interesante para explorar sería continuar utilizando el estado en procesamiento cuántico adicional.

Encuesta del tutorial

Por favor, complete esta breve encuesta para proporcionar comentarios sobre este tutorial. Sus opiniones nos ayudarán a mejorar nuestras ofertas de contenido y la experiencia del usuario.

Enlaza a la encuesta