Migrar de NoiseLearner a NoiseLearnerV3
Esta guía te explica paso a paso cómo realizar la migración de IBM Quantum® NoiseLearner a NoiseLearnerV3. Ambas
clases realizan experimentos que caracterizan los procesos de ruido basándose en un
modelo de ruido de Pauli-Lindblad, pero las entradas y
las salidas son ligeramente diferentes.
En segundo plano
La NoiseLearner
clase se creó para permitir a los usuarios llevar a cabo un aprendizaje explícito del ruido. El
modelo de ruido resultante puede pasarse a continuación a IBM Quantum Estimator para aplicar técnicas de mitigación de errores
como PEA y PEC.
NoiseLearner se diseñó para funcionar con Estimator, por lo que, implícitamente, emplea la misma
estrategia de búsqueda de capas que Estimator. Esta estrategia no se puede modificar; de lo contrario, las
medidas de mitigación posteriores no funcionarían correctamente.
A partir de la versión v0.47.0qiskit-ibm-runtime , hay una nueva
NoiseLearnerV3
clase que es compatible con el modelo de ejecución
primitivoExecutor y el dirigido.
Este nuevo modelo ofrece una experiencia de «caja blanca», ya que proporciona los elementos necesarios para plasmar la intención de diseño
en el lado del cliente, y una única primitiva del lado del servidor (Executor) procesa esos datos tal y como
se le indica, sin tomar ninguna decisión implícita en tu nombre. A diferencia del original NoiseLearner,
tú decides cómo estructurar tus circuitos cuando lo utilizasNoiseLearnerV3, y la clase simplemente toma como entrada una lista de instrucciones de circuitos empaquetadas
(por ejemplo, capas únicas).
NoiseLearnerV3 También admite el aprendizaje del ruido de medición. Para cada instrucción de la lista de entrada, ejecuta el
protocolo de aprendizaje de Pauli-Lindblad si la casilla contiene puertas de uno y dos qubits, y el protocolo
TREX
si la casilla contiene mediciones.
¿Deberías migrar?
NoiseLearner solo funciona con el código heredado del lado del servidor Estimator, y NoiseLearnerV3 solo funciona con
Executor y el código del lado del cliente Estimator. Debes migrar a NoiseLearnerV3 si estás utilizando
Executor o del lado del cliente Estimator. El código heredado del lado del servidor ha Estimator quedado obsoleto y ha sido sustituido por su equivalente del lado del cliente en v0.50.0qiskit-ibm-runtime .
Si utilizas la versión v0.50.0qiskit-ibm-runtime o posterior, lee primero la guía «Migración de Sampler y Estimator del lado del servidor al lado del cliente» para migrar a las primitivas del lado del cliente.
Pasos de migración
Paso 1: Modificar las importaciones
NoiseLearner:
from qiskit_ibm_runtime.noise_learner import NoiseLearnerNoiseLearnerV3:
from qiskit_ibm_runtime import NoiseLearnerV3Paso 2: Actualizar los datos de entrada
El método NoiseLearner``run() toma como argumento una lista de circuitos o PUB, mientras que el método NoiseLearnerV3``run() toma como argumento una lista de instrucciones, cada una de las cuales debe ser un objeto con anotación «twirling» que contenga BoxOp operaciones ISA.
Existen métodos prácticos para generar los recuadros anotados, dependiendo de la
primitiva que se vaya a utilizar.
NoiseLearner:
from qiskit_ibm_runtime.noise_learner import NoiseLearner
learner = NoiseLearner(mode=backend)
# `circuits_to_learn` is a list of ISA QuantumCircuit
learner_job = learner.run(circuits_to_learn)NoiseLearnerV3, al trabajar con el Estimador del lado del cliente:
Si tienes pensado utilizar el Estimator del lado del cliente para la ejecución de circuitos, puedes utilizar el find_unique_layers método de Estimator para crear recuadros (capas) anotados:
from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime import NoiseLearnerV3
pubs = [...] # Your PUBs
estimator = Estimator(backend)
estimator.options.resilience.pec_mitigation = True # or zne_mitigation + pea amplifier
# Identify the unique layers to learn.
layers = estimator.find_unique_layers(pubs)
# Learn the noise model for those layers (runs as a separate job).
learner = NoiseLearnerV3(backend)
learner_job = learner.run(layers)NoiseLearnerV3, al trabajar con Executor:
Si tienes pensado utilizar Executor para la ejecución de circuitos, te recomendamos que utilices la función generate_boxing_pass_manager de Samplomatic para crear cajas anotadas:
from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3
from samplomatic.transpiler import generate_boxing_pass_manager
from samplomatic.utils import find_unique_box_instructions
# Run the boxing pass manager to group instructions into annotated boxes.
# `isa_circuit` is an ISA QuantumCircuit.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)
boxed_circuit = boxing_pm.run(isa_circuit)
# Find unique boxed instructions.
unique_box_instructions = find_unique_box_instructions(boxed_circuit.data)
# Instantiate a NoiseLearnerV3 object and execute the noise learning program.
learner = NoiseLearnerV3(backend)
learner_job = learner.run(unique_box_instructions)Paso 3: Convertir las opciones
La mayoría de los campos NoiseLearnerOptions se asignan directamente a NoiseLearnerV3Options, salvo los siguientes:
max_layers_to_learn: ConNoiseLearnerV3, el número de capas que se van a entrenar depende del número de capas que se introduzcan.twirling_strategy: ConNoiseLearnerV3, la estrategia de giro viene determinada por la forma en que se agrupan y se anotan las instrucciones (como, por ejemplo, al utilizargenerate_boxing_pass_manager()).
NoiseLearner:
from qiskit_ibm_runtime.noise_learner import NoiseLearner
from qiskit_ibm_runtime.options import NoiseLearnerOptions
# Instantiate a NoiseLearnerOptions object
learner_options = NoiseLearnerOptions(
max_layers_to_learn=3, num_randomizations=32, twirling_strategy="all"
)
learner = NoiseLearner(mode=backend, options=learner_options)
learner_job = learner.run(circuits_to_learn)NoiseLearnerV3, al trabajar con el Estimador del lado del cliente:
Si tienes pensado utilizar el Estimador del lado del cliente para la ejecución de circuitos, puedes
configurar la opción «Estimador twirling.strategy »:
from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime import NoiseLearnerV3
from qiskit_ibm_runtime.options_models import NoiseLearnerV3Options
pubs = [...] # Your PUBs
estimator = Estimator(backend)
estimator.options.resilience.pec_mitigation = True # or zne_mitigation + pea amplifier
estimator.options.twirling.strategy = "all" # set twirling strategy here
# Identify the unique layers to learn.
layers = estimator.find_unique_layers(pubs)
# Instantiate a NoiseLearnerV3 object and execute the noise learning program
learner_options = NoiseLearnerV3Options(num_randomizations=32)
learner = NoiseLearnerV3(backend, options=learner_options)
# Learn just the first 3 layers.
learner_job = learner.run(layers[:3])NoiseLearnerV3, al trabajar con Executor:
Si tienes pensado utilizar Executor para la ejecución de circuitos, puedes pasar la opción twirling_strategy a la función generate_boxing_pass_manager.
Ten en cuenta que, en el caso de generate_boxing_pass_manager(), los valores twirling_strategy utilizan guiones bajos
("active_accum", "active_circuit"), mientras que los valores NoiseLearnerOptions.twirling_strategy de utilizan guiones ("active-accum", "active-circuit").
from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3
from qiskit_ibm_runtime.options_models import NoiseLearnerV3Options
from samplomatic.transpiler import generate_boxing_pass_manager
from samplomatic.utils import find_unique_box_instructions
# Run the boxing pass manager to group instructions into annotated boxes
# `isa_circuit` is an ISA QuantumCircuit
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
twirling_strategy="all", # twirling strategy can be specified here
inject_noise_targets="gates",
inject_noise_strategy="uniform_modification",
)
boxed_circuit = boxing_pm.run(isa_circuit)
# Find unique boxed instructions
unique_box_instructions = find_unique_box_instructions(boxed_circuit.data)
learner_options = NoiseLearnerV3Options(num_randomizations=32)
# Instantiate a NoiseLearnerV3 object and execute the noise learning program
learner = NoiseLearnerV3(backend, options=learner_options)
# Learn just the first 3 layers.
learner_job = learner.run(unique_box_instructions[:3])Paso 4: Revisa los resultados
Los resultados de y NoiseLearner contienen NoiseLearnerV3 información similar, pero están en formatos distintos. Actualiza tu código si comprueba la salida de forma explícita.
Asignación de atributos de resultados:
(learner_result es el resultado del trabajo del alumno)
Atributo | NoiseLearner | NoiseLearnerV3 |
|---|---|---|
| Tipo de resultado | NoiseLearnerResult | NoiseLearnerV3Results : un contenedor similar a una secuencia de NoiseLearnerV3Result |
| Número de capas entrenadas | len( learner_result.data ) | len(learner_result) |
| Datos de la primera capa | layer_error = learner_result.data[0] | noise_map = learner_result[0].to_pauli_lindblad_map() |
| Tipo de resultado de cada capa | LayerError (type(layer_error)) | PauliLindbladMap (type(noise_map)) |
| Generadores para el canal de error | layer_error.error.generators | noise_map.generators() |
| Índice de errores | layer_error.error.rates | noise_map.rates |
Paso 5: Introducir el modelo de ruido en una primitiva
NoiseLearner solo funciona con el código heredado del lado del servidor Estimator, y NoiseLearnerV3 solo funciona con y Executor el código del lado del cliente Estimator. La forma de especificar un modelo de ruido varía ligeramente en función de la primitiva que se utilice.
NoiseLearner, al trabajar con el Estimator heredado del lado del servidor:
from qiskit_ibm_runtime import Estimator as LegacyEstimator
learner_result = learner_job.result()
# Pass the noise model to the `estimator.options` attribute directly
estimator = LegacyEstimator(mode=backend)
estimator.options.resilience.layer_noise_model = learner_result
job = estimator.run(pubs)NoiseLearnerV3, al trabajar con el Estimador del lado del cliente:
Vuelve a utilizar el mismo Estimator que se utilizó en layers el paso 2. Los mapas de ruido devueltos por el
aprendiz se corresponden posicionalmente con esas capas, por lo que deben asignarse al estimador
del que proceden. La función PEA/PEC ya se había activado en ese dispositivo en el paso 2.
Ten en cuenta que, aunque NoiseLearnerV3 admite tanto el protocolo de Pauli-Lindblad como el de TREX, Estimator solo acepta modelos de ruido para capas de dos qubits aprendidos con el protocolo de Pauli-Lindblad.
learner_result = learner_job.result()
# Convert results to Pauli-Lindblad noise maps.
pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()
# Assign the learned noise maps so PEA/PEC uses them.
estimator.options.resilience.layer_noise_model = zip(layers, pauli_lindblad_maps)
# Now execute the target PUBs.
job = estimator.run(pubs)NoiseLearnerV3, al trabajar con Executor:
from qiskit_ibm_runtime import Executor
from qiskit_ibm_runtime.quantum_program import QuantumProgram
# Generate a quantum program
program = QuantumProgram(shots=1000)
# Convert the NoiseLearnerV3 result to a dictionary
learner_result = learner_job.result()
noise_maps = learner_result.to_dict(
instructions=unique_box_instructions, require_refs=False
)
# Append the samplex item and execute
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"pauli_lindblad_maps": noise_maps,
},
)
executor = Executor(backend)
executor_job = executor.run(program)Ejemplos completos
NoiseLearnerV3 y el Estimador del lado del cliente
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, NoiseLearnerV3
from qiskit_ibm_runtime.executor_estimator import Estimator
# 1. Account + backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# 2. Circuit + observable
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
observable = SparsePauliOp("ZZ")
# 3. Transpile to ISA
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
pubs = [(isa_circuit, isa_observable)]
# 4. Initialize Estimator with options
estimator = Estimator(backend)
estimator.options.resilience.pec_mitigation = True
# 5. Extract the unique boxed layers from PUBs
layers = estimator.find_unique_layers(pubs)
# 6. Learn the noise model for those layers
learner = NoiseLearnerV3(backend)
learner_job = learner.run(layers)
learner_result = learner_job.result()
# 7. Convert the result to Pauli-Lindblad maps and pass them to Estimator
pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()
estimator.options.resilience.layer_noise_model = zip(layers, pauli_lindblad_maps)
# 8. Execute the target PUBs
job = estimator.run(pubs)
result = job.result()NoiseLearnerV3 y albacea
from qiskit import QuantumCircuit
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, Executor, NoiseLearnerV3
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from samplomatic import build
from samplomatic.transpiler import generate_boxing_pass_manager
from samplomatic.utils import find_unique_box_instructions
# 1. Account + backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# 2. Circuit + observable
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
# 3. Transpile to ISA
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
# 4. Run the boxing pass manager to group instructions into annotated boxes
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)
boxed_circuit = boxing_pm.run(isa_circuit)
# 5. Find unique boxed instructions (layers)
unique_box_instructions = find_unique_box_instructions(boxed_circuit.data)
# 6. Learn the noise model for those layers
learner = NoiseLearnerV3(backend)
learner_job = learner.run(unique_box_instructions)
learner_result = learner_job.result()
# 7. Convert the NoiseLearnerV3 result to a dictionary
noise_maps = learner_result.to_dict(
instructions=unique_box_instructions, require_refs=False
)
# 8. Build the template circuit and samplex pair
template_circuit, samplex = build(boxed_circuit)
# 9. Prepare a quantum program
program = QuantumProgram(shots=1000)
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"pauli_lindblad_maps": noise_maps,
},
)
executor = Executor(backend)
job = executor.run(program)
result = job.result()