Eseguire la migrazione da NoiseLearner a NoiseLearnerV3
Questa guida illustra passo dopo passo la procedura di migrazione da IBM Quantum® NoiseLearner a NoiseLearnerV3. Entrambe le
classi eseguono esperimenti volti a caratterizzare i processi di rumore basati su un
modello di rumore di Pauli-Lindblad, ma gli input e gli
output sono leggermente diversi.
Sfondo
La NoiseLearner
classe è stata creata per consentire agli utenti di eseguire un apprendimento esplicito del rumore. Il modello di
rumore così ottenuto può quindi essere trasmesso a IBM Quantum Estimator per l'applicazione di tecniche di mitigazione degli errori
come PEA e PEC.
NoiseLearner è stato progettato per funzionare con Estimator, e pertanto utilizza implicitamente la stessa
strategia di individuazione dei livelli di Estimator. Questa strategia non può essere modificata; in caso contrario, le successive
misure di mitigazione non funzionerebbero correttamente.
A partire dalla versione v0.47.0qiskit-ibm-runtime , è disponibile una nuova
NoiseLearnerV3
classe compatibile con il modello di esecuzione
primitivoExecutor e con quello diretto.
Questo nuovo modello offre un'esperienza di tipo "white-box", fornendo gli elementi necessari per catturare l'intento di progettazione
lato client, mentre un'unica primitiva lato server (Executor) elabora tali input esattamente come
indicato — senza prendere alcuna decisione implicita per conto dell'utente. A differenza della versione originale NoiseLearner,
sei tu a decidere come strutturare i tuoi circuiti durante l'utilizzoNoiseLearnerV3, e la classe accetta semplicemente come input un elenco di istruzioni relative ai circuiti incapsulati
(ad esempio, livelli univoci).
NoiseLearnerV3 supporta anche l'apprendimento del rumore di misurazione. Per ogni istruzione presente nell'elenco di input, esegue il
protocollo di apprendimento di Pauli-Lindblad se la casella contiene porte a uno e due qubit, e il protocollo
TREX
se la casella contiene misurazioni.
Dovresti migrare?
NoiseLearner funziona solo con il codice lato server legacy Estimatore funziona NoiseLearnerV3 solo con
Executor e il codice lato client Estimator. È necessario effettuare la migrazione a NoiseLearnerV3 se si utilizza
Executor o il lato client Estimator. Il codice lato server legacy è Estimator stato deprecato e sostituito dall'equivalente lato client disponibile all'indirizzo v0.50.0qiskit-ibm-runtime .
Se utilizzi la versione v0.50.0qiskit-ibm-runtime o successive, leggi la guida "Migrazione da Sampler e Estimator lato server a lato client" per effettuare prima la migrazione alle primitive lato client.
Passi di migrazione
Passaggio 1: Modificare le importazioni
NoiseLearner:
from qiskit_ibm_runtime.noise_learner import NoiseLearnerNoiseLearnerV3:
from qiskit_ibm_runtime import NoiseLearnerV3Fase 2: Aggiornare i dati di input
Il metodo NoiseLearner``run() accetta un elenco di circuiti o PUB, mentre il metodo NoiseLearnerV3``run() accetta un elenco di istruzioni, ciascuna delle quali deve essere un oggetto annotato con twirling BoxOp contenente operazioni ISA.
Sono disponibili metodi pratici per generare i riquadri annotati, a seconda della
primitiva che si intende utilizzare.
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, quando si utilizza l'Estimator lato client:
Se si intende utilizzare Estimator lato client per l'esecuzione dei circuiti, è possibile utilizzare il metodo find_unique_layers di Estimator per creare riquadri annotati (livelli):
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, quando si utilizza Executor:
Se hai intenzione di utilizzare Executor per l'esecuzione dei circuiti, valuta la possibilità di utilizzare la funzione generate_boxing_pass_manager di Samplomatic per creare box annotati:
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)Fase 3: Convertire le opzioni
La maggior parte dei campi NoiseLearnerOptions corrisponde direttamente a NoiseLearnerV3Options, ad eccezione dei seguenti:
max_layers_to_learn: ConNoiseLearnerV3, il numero di livelli da addestrare dipende dal numero di livelli specificati.twirling_strategy: ConNoiseLearnerV3, la strategia di rotazione è definita dal modo in cui le istruzioni vengono raggruppate e annotate (ad esempio quando si utilizzagenerate_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, quando si utilizza l'Estimator lato client:
Se si intende utilizzare l'Estimator lato client per l'esecuzione dei circuiti, è possibile
impostare l'opzione Estimator 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, quando si utilizza Executor:
Se si intende utilizzare Executor per l'esecuzione dei circuiti, è possibile passare l'opzione twirling_strategy alla funzione generate_boxing_pass_manager.
Si noti che, nel caso di generate_boxing_pass_manager(), i valori twirling_strategy utilizzano il trattino basso
("active_accum", "active_circuit"), mentre i valori NoiseLearnerOptions.twirling_strategy di utilizzano il trattino ("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])Fase 4: Verificare i risultati
I risultati di e NoiseLearner NoiseLearnerV3 contengono informazioni simili, ma sono in formati diversi. Aggiorna il codice se verifica esplicitamente l'output.
Mappatura degli attributi dei risultati:
(learner_result è l'output del processo di apprendimento)
Attributo | NoiseLearner | NoiseLearnerV3 |
|---|---|---|
| Tipo di risultato | NoiseLearnerResult | NoiseLearnerV3Results, un contenitore simile a una sequenza di NoiseLearnerV3Result |
| Numero di livelli appresi | len( learner_result.data ) | len(learner_result) |
| Dati relativi al primo strato | layer_error = learner_result.data[0] | noise_map = learner_result[0].to_pauli_lindblad_map() |
| Tipo di risultato di ciascun livello | LayerError (type(layer_error)) | PauliLindbladMap (type(noise_map)) |
| Generatori per il canale di errore | layer_error.error.generators | noise_map.generators() |
| Frequenza errori | layer_error.error.rates | noise_map.rates |
Passaggio 5: Inserimento del modello di rumore in una primitiva
NoiseLearner funziona solo con il lato server Estimator legacy e funziona solo NoiseLearnerV3 con il lato client Executor``Estimator . Le modalità di definizione di un modello di rumore variano leggermente a seconda della primitiva utilizzata.
NoiseLearner, quando si utilizza la versione precedente di Estimator lato server:
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, quando si utilizza l'Estimator lato client:
Riutilizza lo stesso Estimator che hai utilizzato layers al punto 2. Le mappe di rumore restituite dal
modello di apprendimento sono allineate posizionalmente a tali livelli, pertanto devono essere assegnate allo stimatore
da cui provengono. La funzione PEA/PEC era già stata attivata su quel dispositivo al punto 2.
Si noti che, sebbene NoiseLearnerV3 supporti sia il protocollo Pauli-Lindblad che quello TREX, accetta Estimator solo modelli di rumore per livelli a due qubit appresi con il protocollo 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, quando si utilizza 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)Esempi completi
NoiseLearnerV3 e lo strumento di stima lato client
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 e esecutore testamentario
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()