Saltar al contenido principal

Introducción práctica a los criterios de DiVincenzo con Qiskit 2

Introducción

El físico David DiVincenzo estableció cinco requisitos clave para cualquier implementación física de un ordenador cuántico, además de dos criterios adicionales para la comunicación cuántica. En este notebook, experimentarás cada criterio de DiVincenzo a través de demostraciones prácticas con Qiskit. En lugar de profundizar en la teoría, cada sección explica brevemente un criterio y luego ofrece ejercicios de código usando Qiskit 2. Podrás ejecutar circuitos en simuladores y dispositivos reales de IBM Quantum para explorar cada principio de manera práctica.

Los cinco criterios de DiVincenzo para la computación cuántica:

  1. Un sistema físico escalable con qubits bien caracterizados.
  2. Capacidad para inicializar los qubits a un estado fiducial simple (p. ej., |00…0〉).
  3. Tiempos de decoherencia largos (la coherencia del qubit debe ser mucho mayor que el tiempo de operación de las puertas).
  4. Un conjunto universal de puertas cuánticas (capaz de realizar operaciones unitarias arbitrarias).
  5. Capacidad de medición específica por qubit (leer el estado de cada qubit).

(DiVincenzo también describió dos criterios para la comunicación cuántica: la capacidad de interconvertir qubits estacionarios y "voladores", y de transmitir fielmente los qubits voladores entre ubicaciones. Los incluimos en una actividad recomendada al final de este notebook.)

Cada una de las siguientes secciones corresponde a un criterio. Usaremos Qiskit para ilustrar el concepto con código y experimentos interactivos que puedes probar. Por ejemplo, veremos cómo escalar el número de qubits y la profundidad del circuito afecta los resultados (Criterio 1), cómo reiniciar y preparar estados de qubits (Criterio 2), cómo medir qubits en simuladores frente a dispositivos reales (Criterio 4), cómo Qiskit compone puertas universales (Criterio 3), y cómo la coherencia finita (T₁, T₂) impacta en los cálculos (Criterio 5). Al final, tendrás una intuición más profunda de lo que significa cada criterio de DiVincenzo en la práctica y cómo Qiskit permite experimentar con ellos.

# Added by doQumentation — required packages for this notebook
!pip install -q numpy
# Install necessary packages
!pip install qiskit[visualization] qiskit-ibm-runtime qiskit-aer qiskit_ibm_runtime

1. Criterio 1 – Qubits escalables y bien caracterizados

Criterio 1: "Un sistema físico escalable con qubits bien caracterizados." Esto significa que necesitamos una plataforma de hardware cuántico donde podamos aumentar el número de qubits y seguir controlándolos de forma fiable. Las propiedades de cada qubit (niveles de energía, tasas de error, conectividad, etc.) deben ser bien conocidas. En esencia, queremos construir circuitos más grandes sin que el sistema se degrade. En la práctica, a medida que escalamos el número de qubits o la profundidad del circuito, los errores y la decoherencia se acumulan, por lo que demostrar escalabilidad también implica comprender cómo el aumento de tamaño afecta el rendimiento.

Objetivo de la demostración: Usar Qiskit para mostrar el efecto de escalar un circuito (en número de qubits o profundidad de puertas) sobre la fidelidad del resultado. Simularemos un escenario ideal frente a uno ruidoso para ver cómo un sistema más grande o un circuito más profundo sucumbe a la decoherencia y los errores.

Primero, construyamos un pequeño estado entrelazado (estado GHZ) en 3 qubits, y luego uno más grande en 5 qubits, como prueba simple de escalabilidad. Un estado GHZ de n qubits es 12(0...0+1...1)\frac{1}{\sqrt{2}}(|0...0\rangle + |1...1\rangle). En una simulación ideal, medir un GHZ de n qubits produce solo dos resultados (todos 0 o todos 1) con igual probabilidad. Compararemos la salida ideal con la salida ruidosa a medida que aumentamos n o la profundidad del circuito.

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import SamplerV2 as Sampler

# 3-qubit GHZ circuit
qc3 = QuantumCircuit(3, 3)
qc3.h(0)
qc3.cx(0, 1)
qc3.cx(1, 2)
qc3.measure([0, 1, 2], [0, 1, 2])

# 5-qubit GHZ circuit (scaling up the number of qubits)
qc5 = QuantumCircuit(5, 5)
qc5.h(0)
qc5.cx(0, range(1, 5)) # entangle qubit 0 with all others
qc5.measure(range(5), range(5))

# Transpile for a simulator backend
sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc3 = pm.run(qc3)
isa_qc5 = pm.run(qc5)

# Run ideal simulations (no noise)
sampler = Sampler(mode=sim_backend)

job3 = sampler.run([isa_qc3], shots=1024)
result3 = job3.result()
counts3 = result3[0].data.c.get_counts()

job5 = sampler.run([isa_qc5], shots=1024)
result5 = job5.result()
counts5 = result5[0].data.c.get_counts()

print("3-qubit GHZ counts (ideal):", counts3)
plot_histogram(counts3, legend=['3-qubit ideal'], figsize=(6,4))
3-qubit GHZ counts (ideal): {'000': 531, '111': 493}

Quantum circuit diagram

print("5-qubit GHZ counts (ideal):", counts5)
plot_histogram(counts5, legend=['5-qubit ideal'], figsize=(6,4))
5-qubit GHZ counts (ideal): {'11111': 535, '00000': 489}

Code output

Resultado esperado (caso ideal): El GHZ de 3 qubits produce idealmente alrededor de un 50% de 000 y un 50% de 111 en los conteos. El GHZ de 5 qubits produce ~50% de 00000 y 50% de 11111. No aparecen otras cadenas de bits porque el estado es idealmente totalmente coherente y entrelazado. Deberías ver dos barras altas en el histograma para cada circuito, correspondientes a los resultados de todos ceros y todos unos.

A continuación, veamos qué ocurre en un entorno ruidoso. Usaremos las capacidades de modelos de ruido de Qiskit Aer para imitar los errores de un dispositivo real. Por ejemplo, podemos tomar las propiedades de un backend de IBM para crear un modelo de ruido que incluya errores de puertas, tiempos de puerta finitos, relajación del qubit (T₁), desfasamiento (T₂) y errores de lectura. Aquí, usaremos un backend falso que representa el dispositivo IBM Quantum Brisbane para generar un modelo de ruido y volver a ejecutar los circuitos GHZ a través de él.

Ejercicio 1a: Simular con ruido

Completa el código siguiente para simular los circuitos GHZ en un simulador ruidoso basado en el backend FakeBrisbane. Esto te mostrará cómo el rendimiento se degrada a medida que el sistema escala en un entorno de ruido realista.

from qiskit_ibm_runtime.fake_provider import FakeBrisbane

# We will reuse the ideal circuits qc3 and qc5 and their results from the previous cell.

# --- YOUR CODE HERE ---

# 1. Create a fake backend for IBM Quantum Brisbane
###brisbane_backend = ...

# 2. Create a noisy AerSimulator from the fake backend's properties
###noisy_sim = ...

# 3. Transpile the circuits for the noisy simulator (this adapts them to the device's specific gates and connectivity)
###pm = ...

###isa_qc3_noisy = ...

###isa_qc5_noisy = ...

# 4. Run the noisy simulations using the Sampler and get the counts
###sampler = ...

###job3 = ...

###result3_noisy = ...

###counts3_noisy = ...

###job5 = ...

###result5_noisy = ...

###counts5_noisy = ...

# --- END YOUR CODE ---

# This part is done for you to print and plot the results:
print("3-qubit GHZ counts (noisy):", counts3_noisy)
plot_histogram(counts3_noisy, legend=['3-qubit noisy'], figsize=(6,4))
print("5-qubit GHZ counts (noisy):", counts5_noisy)
plot_histogram(counts5_noisy, legend=['5-qubit noisy'], figsize=(6,4))

Ejercicio 1b: Ejecutar en un ordenador cuántico real de IBM Quantum

El código siguiente ejecuta los circuitos GHZ en un ordenador cuántico real de IBM Quantum. Esto te mostrará cómo el rendimiento se degrada en un dispositivo real.

# your_api_key = "deleteThisAndPasteYourAPIKeyHere"
# your_crn = "deleteThisAndPasteYourCRNHere"

# QiskitRuntimeService.save_account(
# channel="ibm_quantum_platform",
# token=your_api_key,
# instance=your_crn,
# name="fallfest-2025",
# )

# Check that the account has been saved properly
# service = QiskitRuntimeService(name="fallfest-2025")
# print(service.saved_accounts())

# We will reuse the ideal circuits qc3 and qc5 and their results from the previous cell.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService(name="fallfest-2025")
real_backend = service.least_busy(operational=True, simulator=False)
print("Running on " + real_backend.name)

pm = generate_preset_pass_manager(backend=real_backend, optimization_level=1)
isa_qc3r = pm.run(qc3)
isa_qc5r = pm.run(qc5)

sampler = Sampler(mode=real_backend)

job3r = sampler.run([isa_qc3r], shots=1024)
result3r = job3r.result()
counts3r = result3r[0].data.c.get_counts()

job5r = sampler.run([isa_qc5r], shots=1024)
result5r = job5r.result()
counts5r = result5r[0].data.c.get_counts()

print("3-qubit GHZ counts (real):", counts3r)
plot_histogram(counts3r, legend=['3-qubit real'], figsize=(6,4))
print("5-qubit GHZ counts (real):", counts5r)
plot_histogram(counts5r, legend=['5-qubit real'], figsize=(6,4))

Resultado esperado (ruidoso frente a ideal): Con ruido, ya sea simulado o en un dispositivo real, el estado GHZ es menos perfecto. Verás resultados adicionales más allá de todos ceros y todos unos. Para 3 qubits, en lugar de un 100% en 000/111, parte de la probabilidad se filtra hacia otras cadenas de bits (p. ej., 001, 010, etc.) debido a errores de puertas o decoherencia que voltea algunos qubits. Para 5 qubits, el efecto es aún más pronunciado; el circuito más grande (más qubits y puertas CNOT) acumula más error, por lo que los picos de todos ceros y todos unos son más bajos y aparecen muchos otros resultados. Esta tendencia ilustra el desafío de la escalabilidad: a medida que escalamos, mantener una alta fidelidad se vuelve más difícil sin corrección de errores.

Conclusión: Un ordenador cuántico escalable necesita preservar las correlaciones cuánticas a medida que el sistema crece. Nuestros ejemplos muestran cómo aumentar el número de qubits o la profundidad de las puertas provoca una caída en la fidelidad de los resultados cuando hay ruido. Los criterios restantes abordarán cómo mantener esos qubits bien comportados (bajo error, inicializables, etc.) a medida que escalamos.

2. Criterio 2 – Inicialización de qubits

Criterio 2: "La capacidad de inicializar el estado de los qubits a un estado fiducial simple, como |000…〉." Todos los qubits deben comenzar de forma fiable en un estado de referencia conocido (típicamente el estado base |0〉 para cada qubit). La inicialización es esencial para que los algoritmos comiencen con una pizarra en blanco. En la práctica, en los dispositivos cuánticos de IBM cada qubit se reinicia automáticamente a |0〉 al inicio de cada ejecución de circuito. Qiskit también proporciona instrucciones para reiniciar qubits o preparar estados personalizados durante un cálculo.

Objetivo de la demostración: Mostrar cómo inicializar qubits en Qiskit, tanto al inicio como en mitad del circuito. Demostraremos el uso de la instrucción reset y los métodos de preparación de estado.

Ejercicio 2: Preparar un estado específico

En el bloque de código siguiente, completa el QuantumCircuit para preparar el estado 10|10\rangle. Esto significa que el qubit 0 debe estar en el estado 0|0\rangle y el qubit 1 en el estado 1|1\rangle. Usa la puerta y la instrucción adecuadas para lograrlo.

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator

# Create a circuit to initialize qubits to |10> and verify by measurement
qc_init = QuantumCircuit(2, 2)

# --- YOUR CODE HERE ---

# 1. Set qubit 1 to the |1> state

# 2. Explicitly reset qubit 0 to the |0> state

# --- END YOUR CODE ---

qc_init.measure([0, 1], [0, 1])
qc_init.draw('mpl')
# Run the circuit and check the outcome
sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_init = pm.run(qc_init)

sampler = Sampler(mode=sim_backend)

job = sampler.run([isa_qc_init], shots=1024)
result = job.result()
counts = result[0].data.c.get_counts()

print("Outcome of |10> state measured in Z-basis:", counts)
plot_histogram(counts)

Deberías ver 10 (binario para qubit1=1, qubit0=0) con una probabilidad del 100% en la simulación, lo que significa que el qubit 1 se preparó correctamente en |1〉 y el qubit 0 en |0〉.

Ahora, para una preparación de estado más general, Qiskit permite la inicialización a estados arbitrarios usando el método initialize. Por ejemplo, preparemos un qubit en el estado +=(0+1)/2|+\rangle = (|0\rangle+|1\rangle)/\sqrt{2}, que es un estado de superposición, y un par de qubits en el estado de Bell (00+11)/2(|00\rangle+|11\rangle)/\sqrt{2}:

import numpy as np

# Initialize a single qubit in |+> state and measure in Z-basis
qc_plus = QuantumCircuit(1, 1)
state_plus = [1/np.sqrt(2), 1/np.sqrt(2)] # amplitude for |0> and |1>
qc_plus.initialize(state_plus, 0)
qc_plus.measure(0, 0)

# Initialize two qubits in a Bell state manually
qc_bell = QuantumCircuit(2, 2)
bell_state = [1/np.sqrt(2), 0, 0, 1/np.sqrt(2)] # amplitudes for |00>,|01>,|10>,|11>
qc_bell.initialize(bell_state, [0, 1])
qc_bell.measure([0, 1], [0, 1])

# Transpile and run the initialization circuits
isa_qc_plus = pm.run(qc_plus)
job_plus = sampler.run([isa_qc_plus], shots=1024)
result_plus = job_plus.result()
counts_plus = result_plus[0].data.c.get_counts()

print("Outcome of |+> state measured in Z-basis:", counts_plus)

isa_qc_bell = pm.run(qc_bell)
job_bell = sampler.run([isa_qc_bell], shots=1024)
result_bell = job_bell.result()
counts_bell = result_bell[0].data.c.get_counts()

print("Outcome of Bell state measured in Z-basis:", counts_bell)
Outcome of |+> state measured in Z-basis: {'1': 499, '0': 525}
Outcome of Bell state measured in Z-basis: {'00': 508, '11': 516}

Resultados esperados: El estado |+〉 de un solo qubit, al medirse, producirá 0 y 1 con una probabilidad aproximada del 50% cada uno. La medición del estado de Bell debería dar aproximadamente un 50% de 00 y un 50% de 11. Si observas estos resultados, se confirma que la inicialización a esos estados fue exitosa.

Inicialización en mitad del circuito: El reset de Qiskit se puede usar en el medio de un circuito para reinicializar un qubit a |0〉 en tiempo real. Por ejemplo, en los códigos de corrección de errores o en los algoritmos iterativos, a menudo se mide un qubit y luego se reinicia para reutilizarlo. La operación reset es determinista; descarta cualquier estado existente y lleva el qubit al estado base.

Ejemplo en dispositivo: En hardware como ibmq_brisbane (127 qubits) o cualquier dispositivo de IBM, todos los qubits comienzan en |0〉 por defecto cuando se ejecuta un trabajo. Si necesitas un estado inicial diferente, aplicarías puertas al principio (como hicimos con X para obtener |1〉). La reinicialización continua (para la corrección de errores cuánticos) es un tema de investigación activa porque realizarla rápidamente es un desafío. Afortunadamente, para el uso básico, la capacidad de comenzar desde cero en |0…0〉 está disponible y hemos demostrado cómo lograr también otros estados iniciales deseados.

3. Criterio 3 – Tiempo de Coherencia Largo (Decoherencia vs Tiempo de Compuerta)

Criterio 3: "Tiempos de decoherencia relevantes largos, mucho más largos que el tiempo de operación de la compuerta." Esto aborda la necesidad de que los qubits mantengan su estado cuántico el tiempo suficiente para realizar las operaciones necesarias. Cada qubit tiene un tiempo T₁ (tiempo de relajación de energía, con qué rapidez |1〉 decae a |0〉) y un tiempo T₂ (tiempo de desfase, con qué rapidez se pierde la coherencia de fase relativa). Para que una computadora cuántica funcione, estas escalas de tiempo deben superar ampliamente la duración de las operaciones de compuerta.

Objetivo de la Demo: Investigar la coherencia de los qubits en Qiskit mostrando cómo la decoherencia impacta los resultados del circuito a medida que crece la longitud de ejecución. Usaremos un backend falso con tiempos T1/T2 conocidos para simular este efecto.

Para demostrar el impacto de la coherencia finita, simularemos un experimento de decaimiento T1. Prepararemos un qubit en el estado |1〉, esperaremos un tiempo usando una instrucción delay, y luego mediremos. Esperamos que la probabilidad de medir |1〉 disminuya a medida que aumenta el retardo.

# This part is done for you. We are creating a list of circuits,
# each with a different delay time.

time_delays_ns = [0, 50000, 100000, 150000, 200000, 250000, 300000] # delay durations in ns

decay_expts = []
for delay in time_delays_ns:
qc = QuantumCircuit(1, 1)
qc.x(0) # initialize qubit to |1>
if delay > 0:
qc.delay(delay, 0, unit='ns') # wait 'delay' nanoseconds
qc.measure(0, 0)
decay_expts.append(qc)

decay_expts[1].draw('mpl') # Visualize one of the circuits

Quantum circuit diagram

Ejercicio 3: Simular un Experimento de Decaimiento T1

Ahora, usa un simulador ruidoso basado en FakeVigo (que tiene tiempos T1 de ~50-100 µs) para ejecutar estos circuitos. El simulador aplicará automáticamente los errores T1/T2 durante las instrucciones delay. Transpila los circuitos para este backend y ejecútalos.

from qiskit_ibm_runtime.fake_provider import FakeVigoV2 as FakeVigo
from qiskit_aer import AerSimulator

# --- YOUR CODE HERE ---

# 1. Create a noisy simulator from the FakeVigo backend
###sim_vigo = ...

# 2. Transpile the list of circuits for this simulator
###pm = ...

###isa_decay_expts = ...

# 3. Use the Sampler to run all the transpiled circuits in a single job
###sampler = ...

###job = ...

###result = ...

# --- END YOUR CODE ---

# This part is done for you to analyze and print the results.
for idx, (delay, qc) in enumerate(zip(time_delays_ns, isa_decay_expts)):
counts = result[idx].data.c.get_counts()
p1 = counts.get('1', 0) / 1000 # Assuming 1000 shots
print(f"Delay {delay} ns: P(qubit=1) = {p1:.3f}")

4. Criterio 4 – Conjunto Universal de Compuertas Cuánticas

Criterio 4: "Un conjunto 'universal' de compuertas cuánticas." Esto significa que nuestro hardware debe permitirnos realizar cualquier cómputo cuántico componiendo un conjunto finito de compuertas básicas. En la computación clásica, NAND es universal; en cuántica, hay muchas opciones de conjuntos de compuertas universales (p. ej. {H, T, CNOT} o las compuertas nativas de una máquina determinada). Los dispositivos IBM, por ejemplo, tienen un conjunto de operaciones nativas como rotaciones arbitrarias de un solo qubit y CNOTs entre ciertos qubits, que juntas son universales. El trabajo de Qiskit es a menudo compilar compuertas de alto nivel en estas compuertas base.

Objetivo de la Demo: Ilustrar la universalidad de las compuertas mostrando cómo Qiskit descompone compuertas. Tomaremos una compuerta no nativa (como una compuerta Toffoli de 3 qubits, CCX) y veremos cómo se descompone en las compuertas base del dispositivo. Esto demuestra que el conjunto de compuertas proporcionado es efectivamente universal – puede producir la operación más compleja.

Primero, veamos cuáles son las compuertas base de un backend IBM típico. Consultaremos la configuración de un dispositivo (o su versión falsa). Por ejemplo, las compuertas base de ibmq_brisbane: Deberías observar que la probabilidad P(qubit=1) disminuye a medida que aumenta el tiempo de retardo, siguiendo una curva de decaimiento exponencial característica de la relajación T1. Esto demuestra directamente cómo el tiempo de coherencia finito conduce a errores computacionales si el circuito se ejecuta durante demasiado tiempo.

Impacto en los algoritmos: Si intentas un algoritmo más largo (con muchas compuertas secuenciales), el tiempo total de ejecución podría acercarse o superar T2, causando que el estado pierda coherencia antes del final. Por eso mejorar los tiempos de coherencia y hacer las compuertas más rápidas son dos de los objetivos más críticos en la investigación de hardware cuántico.

from qiskit_ibm_runtime.fake_provider import FakeBrisbane
fake_brisbane = FakeBrisbane()
print("Basis gates for ibmq_brisbane:", fake_brisbane.configuration().basis_gates)
Basis gates for ibmq_brisbane: ['ecr', 'id', 'rz', 'sx', 'x']

Esto podría generar algo como ['id', 'rz', 'sx', 'x', 'ecr']. Estas son las operaciones primitivas que el hardware soporta de forma nativa (Identidad/sin operación, rotación RZ, compuerta sqrt(X), compuerta X y X controlada). Cualquier otra compuerta debe componerse a partir de estas. Se sabe que este conjunto es universal para la computación cuántica (esencialmente rotaciones de un solo qubit más una compuerta de dos qubits de entrelazamiento forman un conjunto universal).

Ahora, tomemos una compuerta Toffoli (CCX) como caso de prueba. CCX invierte un qubit objetivo solo si dos qubits de control son ambos 1. No es una compuerta nativa en el hardware de IBM. Qiskit proporciona una instrucción ccx, pero internamente la descompondrá.

Ejercicio 4: Descomponer una Compuerta Toffoli

Completa el código a continuación para construir un circuito con una compuerta Toffoli (CCX) y luego usa Qiskit para descomponerla en las compuertas base nativas del backend FakeBrisbane.

from qiskit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeBrisbane

# The fake_brisbane backend from the previous cell is reused here.

# --- YOUR CODE HERE ---

# 1. Create a circuit that can accommodate a Toffoli gate
###qc_toffoli = ...

# Apply a CCX gate with controls on qubits 0, 1 and target on qubit 2

# 2. Transpile the circuit to the fake Brisbane backend
###pm = ...

###isa_qc_toffoli = ...

# --- END YOUR CODE ---

print("Toffoli circuit before decomposition:")
print(qc_toffoli)

print("\nToffoli circuit after transpiling to Brisbane basis:")
# The .draw() method will now show the decomposed circuit
print(isa_qc_toffoli.draw(fold=120))

En la salida transpilada, deberías ver el CCX reemplazado por una secuencia de compuertas más básicas como rz, sx y ecr. Esto prueba que las compuertas nativas son suficientes para expresar el Toffoli.

Universalidad en la práctica: El ejercicio anterior muestra que una compuerta compleja de 3 qubits fue construida a partir de otras más simples. En general, cualquier unitario de múltiples qubits puede componerse a partir de compuertas de 1 y 2 qubits. El transpilador es un componente crucial de cualquier pila de software cuántico, ya que tiende el puente entre los algoritmos abstractos que queremos ejecutar y las operaciones físicas que un dispositivo cuántico específico puede realizar realmente.

Ejemplo en dispositivo: El dispositivo ibmq_brisbane usa la arquitectura Eagle con las compuertas base mostradas arriba. Eso significa que cualquier algoritmo enviado a esas máquinas será convertido en secuencias de esas operaciones. Este criterio es esencialmente sobre controlabilidad; tenemos suficientes palancas de control para realizar cualquier operación necesaria en nuestros qubits.

5. Criterio 5 – Medición de Qubits

Criterio 5: "Una capacidad de medición específica por qubit." El estado de cada qubit debe ser medible (típicamente en la base computacional, |0〉 o |1〉). En otras palabras, después de ejecutar un circuito cuántico, necesitamos leer cada qubit como un bit clásico 0/1. Este criterio trata sobre tener detectores confiables para cada qubit y poder seleccionar qué qubits medir.

Objetivo de la Demo: Mostrar cómo realizar mediciones en Qiskit en simuladores y dispositivos reales, y destacar las diferencias (como el ruido de medición). Mediremos algunos qubits en varios estados y examinaremos los resultados. También demostraremos cómo pueden aparecer errores de lectura comparando los resultados del simulador frente al hardware.

Primero, un ejemplo de medición simple:

qc_measure = QuantumCircuit(2, 2)
qc_measure.x(0) # qubit 0 -> |1>, qubit 1 stays |0>
qc_measure.measure([0, 1], [0, 1])
qc_measure.draw('mpl')

Quantum circuit diagram

sim_backend = AerSimulator()
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_measure = pm.run(qc_measure)
job = sampler.run([isa_qc_measure], shots=1000)
result = job.result()
counts = result[0].data.c.get_counts()

print("Simulator measurement counts:", counts)
Simulator measurement counts: {'01': 1000}

Esperamos 1000 cuentas de 01 en el simulador. Ahora, veamos el error de medición en acción simulándolo. Podemos agregar un error de lectura a nuestro simulador Aer. Qiskit Aer nos permite definir un ReadoutError y adjuntarlo a los qubits en un modelo de ruido.

Ejercicio 5: Simular Error de Lectura

Completa el código para definir un modelo de error de lectura simple donde cada qubit tiene un 2% de probabilidad de ser medido incorrectamente (un 0 se lee como 1, o un 1 como 0). Luego, ejecuta el circuito de medición con este modelo de ruido.

from qiskit_aer.noise import NoiseModel, ReadoutError

# --- YOUR CODE HERE ---

# 1. Define a 2% readout error for each single qubit.
# The format is a list of lists of probabilities: [[P(0|0), P(1|0)], [P(0|1), P(1|1)]]
# P(A|B) is the probability of measuring A given the state was |B>.
###ro_error = ...

# 2. Create a new noise model
###noise_model_ro = ...

# 3. Add the readout error to all qubits in the noise model
... # Hint: Use the add_all_qubit_readout_error method

# --- END YOUR CODE ---

sim_backend.set_options(noise_model=noise_model_ro)
pm = generate_preset_pass_manager(backend=sim_backend, optimization_level=1)
isa_qc_measure = pm.run(qc_measure)

# Run the measurement circuit with readout noise
sampler = Sampler(mode=sim_backend)

job = sampler.run([isa_qc_measure], shots=1024)
result = job.result()
counts = result[0].data.c.get_counts()

print("Simulation with 2% readout error:", counts)

Esta salida simulada mostrará algunas cuentas erróneas (como 11, 00, 10) similares a las que podría producir el hardware real, demostrando el impacto de una medición imperfecta.

Ejemplo en dispositivo: En un dispositivo real como ibmq_brisbane, podrías ejecutar el mismo circuito y probablemente verías cuentas similares, distintas de cero, para los resultados incorrectos. Los datos de calibración del dispositivo listan un error de lectura para cada qubit. Poder apuntar y leer qubits específicos es crucial, y entender sus características de error es clave para obtener resultados significativos. La ejecución en un dispositivo real fue demostrada en el Ejercicio 1b: Ejecutar en una computadora IBM Quantum real.

Criterios de Comunicación Cuántica (Qubits Voladores)

DiVincenzo también enumeró dos criterios específicos para la comunicación cuántica, importantes para construir una computadora cuántica en red:

  1. Capacidad de interconvertir qubits estacionarios y voladores. (P. ej., mapear un qubit en un procesador a un fotón que pueda viajar.)
  2. Capacidad de transmitir fielmente qubits voladores entre ubicaciones. (P. ej., enviar un fotón qubit a través de una fibra sin perder información cuántica.)

Estos están más allá del uso estándar de Qiskit porque Qiskit trata principalmente con qubits estacionarios en un chip. Sin embargo, podemos ilustrar el concepto de estos criterios con un ejemplo simple: la teleportación cuántica. La teleportación muestra cómo convertir el estado de un qubit estacionario en información transportada por un par entrelazado (la parte "voladora") y comunicación clásica, que luego se usa para reconstruir el estado en otro qubit estacionario en otro lugar.

El módulo de Teleportación Cuántica de Qiskit en Classrooms por la Dra. Katie McCormick te guiará a través de uno de los protocolos más fascinantes de la información cuántica: la teleportación cuántica, donde un estado cuántico (un qubit) se envía de Alice a Bob usando entrelazamiento y solo dos bits clásicos. Aprenderás el procedimiento completo de teleportación paso a paso: cómo preparar el par Bell entrelazado, realizar una medición en la base de Bell del lado de Alice, transmitir los resultados clásicos y aplicar la compuerta cuántica correcta en el qubit de Bob para recuperar perfectamente el estado original. En el camino, explorarás por qué teleportar la información de un qubit no viola el teorema de no clonación ni supera la velocidad de la luz. A través de ejercicios prácticos usando hardware o simuladores de IBM Quantum, obtendrás una comprensión práctica de la medición, el entrelazamiento y el control de avance en acción.

Al dominar la teleportación cuántica, comprenderás cómo codificar, transmitir y recuperar información cuántica entre nodos distintos, sentando las bases para redes cuánticas, sistemas de repetidores, esquemas de comunicación segura y computación cuántica modular escalable. Cómo se relaciona con los criterios 6 y 7: En una red cuántica real, el par entrelazado compartido se crearía distribuyendo qubits "voladores" (como fotones) entre las ubicaciones de Alice y Bob (Criterio 7: transmisión fiel). El protocolo de teleportación en sí mismo sirve entonces como una forma de mapear el estado del qubit estacionario de Alice en su mitad del par entrelazado, efectivamente 'enviándolo' a Bob (Criterio 6: interconversión). Qiskit nos permite simular la lógica del protocolo perfectamente, proporcionando un modelo conceptual de cómo se cumplen estos criterios en las arquitecturas de comunicación.

Conclusión y Resumen

Hemos diseñado una serie de ejercicios centrados en código para ilustrar los criterios de DiVincenzo usando Qiskit. A través de estos ejemplos prácticos, exploraste cómo una plataforma real de computación cuántica cumple cada requisito:

  • Escalabilidad: construir circuitos con más qubits y comprender el escalado del ruido.
  • Inicialización: usar resets y preparación de estados para comenzar cómputos de manera confiable en estados conocidos.
  • Compuertas Universales: transpilar operaciones complejas a las compuertas base de una máquina, probando que podemos realizar cualquier cómputo.
  • Medición: leer qubits y manejar errores de lectura realistas.
  • Coherencia: ver el efecto del T₁, T₂ finito en la fidelidad del algoritmo y la necesidad de que las operaciones sean rápidas en relación con la decoherencia.

Para mayor completitud, también tocamos los aspectos de comunicación cuántica a través del módulo de Teleportación Cuántica de Qiskit en Classrooms, vinculando los dos últimos criterios (qubits voladores).

Finalmente, vale la pena señalar cómo estos criterios se unen en una computadora cuántica real como la de IBM. Un dispositivo como ibmq_brisbane tiene 127 qubits superconductores (Criterio 1), cada uno comenzando en |0〉 (Criterio 2), con conjunto de compuertas calibrado y compiladores para la universalidad (Criterio 4), resonadores de lectura por microondas para cada qubit (Criterio 5), y tiempos de coherencia del orden de cientos de microsegundos frente a operaciones en nanosegundos (Criterio 3). Para experimentos de redes cuánticas, IBM y otros están explorando la transducción de microondas a óptico para qubits voladores, y el entrelazamiento de qubits distantes (Criterios 6 y 7); esas son áreas de investigación activa.

Al completar los ejercicios de este notebook, no solo has visto las definiciones de los criterios de DiVincenzo, sino que los has tocado a través del código; construyendo intuición sobre lo que cada requisito significa para el hardware y los algoritmos cuánticos reales. Siéntete libre de extender estos experimentos, ¡y feliz computación cuántica!