Ayudante para aprender sobre el ruido
El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos. Recomendamos utilizar estas versiones o versiones más recientes.
qiskit[all]~=2.5.2 qiskit-ibm-runtime~=0.47.0 samplomatic~=0.21.0
Las técnicas de mitigación de errores PEA y PEC utilizan ambas un componente de aprendizaje del ruido basado en un modelo de ruido de Pauli-Lindblad, que normalmente se gestiona durante la ejecución tras enviar uno o varios trabajos a través de qiskit-ibm-runtime sin ningún tipo de acceso local al modelo de ruido ajustado. Sin embargo, en qiskit-ibm-runtimev0.27.1 se han creado una NoiseLearner clase y otra NoiseLearnerOptions asociada para obtener los resultados de estos experimentos de aprendizaje con ruido. Estos resultados pueden almacenarse localmente como un NoiseLearnerResult y utilizarse como datos de entrada en experimentos posteriores. Esta página ofrece una descripción general de su uso y de las opciones disponibles.
Además, a partir de la versión qiskit-ibm-runtimev0.47.0, hay una nueva NoiseLearnerV3 clase que es compatible con el tipo primitivo Executor. Esta nueva versión, que también forma parte del modelo de ejecución dirigida, te permite especificar explícitamente las capas que deseas aprender.
NoiseLearner solo funciona con el « EstimatorV2 » del lado del servidor y NoiseLearnerV3 solo funciona con «Executor» y el nuevo «Estimator» del lado del cliente (introducido en qiskit-ibm-runtime v0.50.0 ).
NoiseLearnerV3
Visión general
Al igual que NoiseLearner, la NoiseLearnerV3 clase lleva a cabo experimentos que caracterizan los procesos de ruido basándose en un modelo de ruido de Pauli-Lindblad para uno o varios circuitos. Su run() método toma una lista de instrucciones, cada una de las cuales debe ser una estructura «twirled» anotada BoxOp que contenga operaciones ISA.
El resultado de un NoiseLearnerV3 trabajo contiene una lista de objetos NoiseLearnerV3Result , uno por cada instrucción de entrada. El siguiente código muestra cómo utilizar el programa auxiliar.
from qiskit import QuantumCircuit
from qiskit.transpiler import CouplingMap
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, Executor
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
# Build a circuit with two entangling layers
num_qubits = 27
edges = list(CouplingMap.from_line(num_qubits, bidirectional=False))
even_edges = edges[::2]
odd_edges = edges[1::2]
circuit = QuantumCircuit(num_qubits)
for pair in even_edges:
circuit.cx(pair[0], pair[1])
for pair in odd_edges:
circuit.cx(pair[0], pair[1])
# Choose a backend to run on
service = QiskitRuntimeService()
backend = service.least_busy()
# Transpile the circuit for execution
pm = generate_preset_pass_manager(backend=backend, optimization_level=3)
isa_circuit = pm.run(circuit)
# 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)
# Find unique boxed instructions
unique_box_instructions = find_unique_box_instructions(boxed_circuit.data)
print(f"Found {len(unique_box_instructions)} unique layers")
print(
f"Each instruction is of type {type(unique_box_instructions[0].operation)}"
)
print(
f"And has annotations: {unique_box_instructions[0].operation.annotations}"
)
# Instantiate a NoiseLearnerV3 object and execute the noise learning program
learner = NoiseLearnerV3(backend)
learner.options.shots_per_randomization = 128
learner.options.num_randomizations = 32
learner_job = learner.run(unique_box_instructions)
learner_result = learner_job.result()Output:
Found 3 unique layers
Each instruction is of type <class 'qiskit.circuit.controlflow.box.BoxOp'>
And has annotations: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r223A', modifier_ref='', site='after')]
El resultado de la operación es una lista de NoiseLearnerV3Result objetos, uno por cada conjunto de instrucciones entre corchetes. NoiseLearnerV3Result tiene un to_pauli_lindblad_map() método que devuelve un PauliLindbladMap objeto, el cual cuenta con métodos para extraer los generadores, las tasas de error y mucho más.
import numpy
print(
f"The Noise learner V3 result contains {len(learner_result)} entries"
f" and each has the following type:\n {type(learner_result[0])}\n"
)
noise_map = learner_result[0].to_pauli_lindblad_map()
print(
f"After converting to PauliLindbladMap, you can extract data "
f" on the generators for the error channel "
f"(truncated to 3): \n{noise_map.generators()[:3]}\n"
)
with numpy.printoptions(threshold=20):
print(
f"Along with the error rates "
f"(truncated to 3): \n{noise_map.rates[:3]}\n"
)Output:
The Noise learner V3 result contains 3 entries and each has the following type:
<class 'qiskit_ibm_runtime.results.noise_learner_v3.NoiseLearnerV3Result'>
After converting to PauliLindbladMap, you can extract data on the generators for the error channel (truncated to 3):
<QubitSparsePauliList with 3 elements on 27 qubits: [X_5, Y_5, Z_5]>
Along with the error rates (truncated to 3):
[2.3e-04 9.0e-05 1.1e-04]
Opciones de aprendizaje sobre ruido
NoiseLearnerV3 ofrece varias opciones, entre las que se incluyen el número de aleatorizaciones y la profundidad de los pares de capas, entre otras. Al igual que con los tipos primitivos, puedes especificar las opciones durante o después de instanciar el NoiseLearnerV3 objeto. El ejemplo de código anterior mostraba cómo configurar las opciones shots_per_randomization y num_randomizations . Consulte la documentación de la NoiseLearnerV3Options API para obtener información detallada.
Introducir un modelo de ruido en Executor
Executor sigue las intenciones de diseño especificadas en las anotaciones del circuito (en forma de samplex) y en las opciones. InjectNoise es la anotación que especifica dónde inyectar el ruido, y el pauli_lindblad_maps argumento samplex indica qué mapa de ruido se debe utilizar.
El circuito del ejemplo anterior pasa por el gestor de pasos de encajado, que agrupa las instrucciones en bloques anotados. Se incluye aquí el código correspondiente para facilitar la comprensión.
inject_noise_targets=”gates”especifica que se añadan lasInjectNoiseanotaciones a los recuadros que contienen elementos de entrelazamiento.inject_noise_strategy="uniform_modification"especifica que se asignen los mismosrefymodifier_refa todas las casillas equivalentes conInjectNoiseanotaciones.InjectNoise.refes un identificador único que se utiliza para asignar un modelo de ruido a esa casilla.InjectNoise.modifier_refpermite ajustar el modelo de ruido asignado a un cuadro mediante factores multiplicativos.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)El circuito del ejemplo anterior contiene tres recuadros, dos de los cuales contienen InjectNoise anotaciones con atributos diferentes ref (ya que no son equivalentes).
# box_circuit comes from the example above
for idx, instruction in enumerate(boxed_circuit):
# The `InjectNoise` annotation defines which boxes to inject noise.
print(f"Annotations of box #{idx}: {instruction.operation.annotations}\n")Output:
Annotations of box #0: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r223A', modifier_ref='r223A', site='after')]
Annotations of box #1: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r621A', modifier_ref='r621A', site='after')]
Annotations of box #2: [Twirl(group='pauli', dressing='right', decomposition='rzsx')]
El resultado del NoiseLearnerV3 trabajo debe convertirse en un diccionario antes de pasárselo a Executor. Las claves de este diccionario son los InjectNoise.ref atributos y los valores son los mapas de ruido correspondientes. Esta asignación indica a Executor qué modelos de ruido debe insertar y en qué lugar.
El siguiente código muestra cómo tomar el circuito y el NoiseLearnerV3 resultado del ejemplo anterior y pasarlos a Executor, que generará las variantes del circuito con los modelos de ruido inyectados y las ejecutará en el hardware.
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from samplomatic import build
# Generate a quantum program
program = QuantumProgram(shots=1000)
# Build the template circuit and samplex pair
template_circuit, samplex = build(boxed_circuit)
# Convert the NoiseLearnerV3 result to a dictionary
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)Uso de « NoiseLearnerV3 » con el Estimator del lado del cliente
El siguiente código muestra cómo utilizar el programa auxiliar con el nuevo Estimator 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()NoiseLearner
A partir de la v0.51.0, qiskit_ibm_runtime NoiseLearner ha quedado obsoleto. Consulta la guía «Migrar a NoiseLearnerV3 » para obtener instrucciones sobre cómo realizar la migración.
Visión general
En esta clase
NoiseLearnerse realizan experimentos que caracterizan los procesos de ruido basándose en un modelo de ruido de Pauli-Lindblad para uno (o más) circuitos. Cuenta con un métodorun()que ejecuta los experimentos de aprendizaje y toma como entrada una lista de circuitos o un PUB, y devuelve un objeto que contieneNoiseLearnerResultlos canales de ruido aprendidos y los metadatos sobre los trabajos enviados. A continuación se muestra un fragmento de código que ilustra cómo se utiliza el programa auxiliar.from qiskit import QuantumCircuit from qiskit.transpiler import CouplingMap from qiskit.transpiler import generate_preset_pass_manager from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 from qiskit_ibm_runtime.noise_learner import NoiseLearner from qiskit_ibm_runtime.options import ( NoiseLearnerOptions, ResilienceOptionsV2, EstimatorOptions, ) # Build a circuit with two entangling layers num_qubits = 27 edges = list(CouplingMap.from_line(num_qubits, bidirectional=False)) even_edges = edges[::2] odd_edges = edges[1::2] circuit = QuantumCircuit(num_qubits) for pair in even_edges: circuit.cx(pair[0], pair[1]) for pair in odd_edges: circuit.cx(pair[0], pair[1]) # Choose a backend to run on service = QiskitRuntimeService() backend = service.least_busy() # Transpile the circuit for execution pm = generate_preset_pass_manager(backend=backend, optimization_level=3) circuit_to_learn = pm.run(circuit) # Instantiate a NoiseLearner object and execute the noise learning program learner = NoiseLearner(mode=backend) job = learner.run([circuit_to_learn]) noise_model = job.result()El resultado
NoiseLearnerResult.dataes una lista de objetosLayerErrorque contienen el modelo de ruido para cada capa de entrelazamiento individual que pertenece a los circuitos de destino. Cada una almacenaLayerErrorla información de la capa, en forma de circuito y de un conjunto de etiquetas de qubits, juntoPauliLindbladErrorcon el modelo de ruido que se ha aprendido para esa capa concreta.import numpy print( f"Noise learner result contains {len(noise_model.data)} entries" f" and has the following type:\n {type(noise_model)}\n" ) print( f"Each element of `NoiseLearnerResult` then contains" f" an object of type:\n {type(noise_model.data[0])}\n" ) # Results are truncated with numpy.printoptions(threshold=200): print( f"And each of these `LayerError` objects possess" f" data on the generators for the error channel: \n" f"{noise_model.data[0].error.generators}\n" ) # Results are truncated with numpy.printoptions(threshold=200): print( f"Along with the error rates: \n{noise_model.data[0].error.rates}\n" )El atributo
LayerError.errordel resultado del aprendizaje del ruido contiene los generadores y las tasas de error del modelo Pauli Lindblad ajustado, que tiene la formadonde son los
LayerError.ratesy son los operadores de Pauli especificados enLayerError.generators.Opciones de aprendizaje sobre ruido
Puedes elegir entre varias opciones que introducir al instanciar un objeto
NoiseLearner. Estas opciones están encapsuladas en la claseqiskit_ibm_runtime.options.NoiseLearnerOptionse incluyen la posibilidad de especificar el número máximo de capas que se van a aprender, el número de aleatorizaciones y la estrategia de «twirling», entre otras. Consulta la documentación de la APINoiseLearnerOptionspara obtener información detallada.A continuación se muestra un ejemplo sencillo que ilustra cómo utilizar el
NoiseLearnerOptionsen unNoiseLearnerexperimento:# Build a GHZ circuit circuit = QuantumCircuit(10) circuit.h(0) circuit.cx(range(0, 9), range(1, 10)) # Choose a backend to run on service = QiskitRuntimeService() backend = service.least_busy() # Transpile the circuit for execution pm = generate_preset_pass_manager(backend=backend, optimization_level=3) circuit_to_run = pm.run(circuit_to_learn) # Instantiate a NoiseLearnerOptions object learner_options = NoiseLearnerOptions( max_layers_to_learn=3, num_randomizations=32, twirling_strategy="all" ) # Instantiate a NoiseLearner object and execute the noise learning program learner = NoiseLearner(mode=backend, options=learner_options) job = learner.run([circuit_to_run]) noise_model = job.result()Introducir modelo de ruido en una primitiva
El modelo de ruido aprendido en el circuito también puede utilizarse como entrada para la primitiva
EstimatorV2« IBM Quantum ». Esto se puede pasar a la primitiva de varias formas diferentes. Los tres ejemplos siguientes muestran cómo se puede pasar el modelo de ruido directamente alestimator.optionsatributo, utilizando unResilienceOptionsV2objeto antes de instanciar una primitiva Estimator y pasando un diccionario con el formato adecuado.# Option 1: Pass the noise model to the `estimator.options` attribute directly estimator = EstimatorV2(mode=backend) estimator.options.resilience.layer_noise_model = noise_model # Option 2: Specify options through a ResilienceOptionsV2 object resilience_options = ResilienceOptionsV2(layer_noise_model=noise_model) estimator_options = EstimatorOptions(resilience=resilience_options) estimator = EstimatorV2(mode=backend, options=estimator_options) # Option 3: Specify options by using a dictionary options_dict = { "resilience_level": 2, "resilience": {"layer_noise_model": noise_model}, } estimator = EstimatorV2(mode=backend, options=options_dict)Una vez que el modelo de ruido se ha pasado al
EstimatorV2objeto, este puede utilizarse para ejecutar cargas de trabajo y llevar a cabo la mitigación de errores con total normalidad.
Próximos pasos
- Consulta la referencia de la API « EstimatorOptions » y la referencia de la API « ResilienceOptionsV2 ».
- Obtén más información sobre las técnicas disponibles para la mitigación y la supresión de errores.
- Descubre cómo implementar la gestión del ruido en Estimator.