Aprende el modelo de ruido de una puerta
Este tutorial muestra cómo aprender un modelo de ruido para una puerta unitaria con un protocolo de aprendizaje estándar accesible mediante las funciones de protocolo de alto nivel prepare_vanilla_program() y process_vanilla_result().
-
Definir la puerta
-
Configurar la simulación local
-
Preparar el programa cuántico
-
Ejecutar el programa cuántico
-
Leer los resultados
Los circuitos siguientes se simulan localmente, por lo que este recorrido no necesita credenciales de IBM Quantum®. Para ejecutarlo en un dispositivo real:
-
Paso 1: reemplaza
FakeMarrakeshpor un backend real. -
Paso 2: pasa ese backend como modo del executor y elimina las opciones del simulador.
1. Definir la puerta
La puerta es un BoxOp que contiene una capa con twirling de seis puertas CZ disjuntas.
from qiskit.circuit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeMarrakesh
from samplomatic import InjectNoise, Tag, Twirl
backend = FakeMarrakesh()
cz_pairs = [(91, 92), (93, 94), (95, 99), (98, 111), (112, 113), (114, 115)]
circuit = QuantumCircuit(backend.num_qubits)
with circuit.box([Twirl(), Tag("cz_gate"), InjectNoise("cz_gate")]):
for pair in cz_pairs:
circuit.cz(*pair)
from qiskit_ibm_runtime import QiskitRuntimeService
backend = QiskitRuntimeService().backend("ibm_marrakesh")
2. Configurar la simulación local
Los índices de Pauli dentro de cada mapa son locales a la puerta, en orden ascendente de qubit físico:
cz_qubits = sorted({qubit for pair in cz_pairs for qubit in pair})
local = {qubit: index for index, qubit in enumerate(cz_qubits)}
local
{91: 0,
92: 1,
93: 2,
94: 3,
95: 4,
98: 5,
99: 6,
111: 7,
112: 8,
113: 9,
114: 10,
115: 11}
Define el ruido con un término ZZ correlacionado y un término XX más débil en cada par CZ, además de un término Z de un solo qubit en todas partes; la medición recibe un término de inversión de bit por qubit.
from qiskit.quantum_info import PauliLindbladMap
num_qubits = len(cz_qubits)
cz_noise = PauliLindbladMap.from_sparse_list(
[("ZZ", [local[a], local[b]], 8e-4) for a, b in cz_pairs]
+ [("XX", [local[a], local[b]], 4e-4) for a, b in cz_pairs]
+ [("Z", [index], 3e-4) for index in range(num_qubits)],
num_qubits=num_qubits,
)
readout_noise = PauliLindbladMap.from_sparse_list(
[("X", [index], 5e-3) for index in range(num_qubits)], num_qubits=num_qubits
)
Construye una caja para que la medición aprenda.
measurement = QuantumCircuit(backend.num_qubits, num_qubits)
with measurement.box([Twirl(), Tag("readout"), InjectNoise("readout")]):
for clbit, qubit in enumerate(cz_qubits):
measurement.measure(qubit, clbit)
Cada entrada de layer_noise_model empareja una de esas cajas con el mapa que se le aplica. Usa el método de simulación de estabilizadores y establece seed_simulator para que los datos simulados sean reproducibles.
from qiskit_aer import AerSimulator
from qiskit_ibm_runtime import Executor
executor = Executor(
mode=AerSimulator(method="stabilizer"),
options={
"simulator": {
"layer_noise_model": [
(circuit[0], cz_noise),
(measurement[0], readout_noise),
],
"seed_simulator": 1234,
}
},
)
executor = Executor(mode=backend)
3. Prepara el programa cuántico
Usa prepare_vanilla_program() para construir el programa cuántico que contiene los experimentos de aprendizaje.
from qiskit_noise_learning.protocols import prepare_vanilla_program
program = prepare_vanilla_program(
backend,
[circuit[0], measurement[0]],
fragment_depths=[2, 16, 64, 128],
num_randomizations=50,
shots_per_randomization=20,
)
print(f"Number of template circuits: {len(program.items)}")
Number of template circuits: 5
4. Ejecuta el programa cuántico
Envía el programa cuántico. Este paso es el mismo tanto si el ejecutor apunta a un simulador como a un dispositivo real.
result = executor.run(program).result()
5. Lee los resultados
Procesa el resultado con process_vanilla_result().
from qiskit_noise_learning.protocols import process_vanilla_result
noise_maps, gate_names, fit = process_vanilla_result(result)
Grafica los decaimientos de fidelidad por par de qubits: tanto los datos como el ajuste exponencial.
fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
exponential_fit=True,
)