Přeskočit na hlavní obsah

Migrace z NoiseLearner na NoiseLearnerV3

Tento průvodce tě provede migrací z IBM Quantum® NoiseLearner na NoiseLearnerV3. Obě třídy provádějí experimenty, které charakterizují šumové procesy na základě Pauliho-Lindbladova modelu šumu, ale vstupy a výstupy jsou mírně odlišné.

Kontext​

Třída NoiseLearner byla vytvořena, aby uživatelům umožnila provádět explicitní učení šumu. Výsledný model šumu pak lze předat IBM Quantum Estimator pro aplikaci technik zmírnění chyb, jako jsou PEA a PEC.

NoiseLearner byl navržen pro práci s Estimator, a proto implicitně používá stejnou strategii hledání vrstev jako Estimator. Tuto strategii nelze změnit; jinak by následné kroky zmírnění nefungovaly správně.

Počínaje qiskit-ibm-runtime v0.47.0 existuje nová třída NoiseLearnerV3, která je kompatibilní s primitivem Executor a modelem řízeného spouštění. Tento nový model poskytuje zkušenost typu white-box tím, že poskytuje prvky pro zachycení záměru návrhu na straně klienta, a jediné serverové primitivum (Executor) zpracovává tyto vstupy přesně tak, jak je nasměrováno — nedělá za tebe žádná implicitní rozhodnutí. Na rozdíl od původního NoiseLearner, kontroluješ, jak rozvrstvit své obvody, když používáš NoiseLearnerV3, a třída jednoduše přijímá seznam zabalených instrukcí obvodu (například jedinečných vrstev) jako svůj vstup.

NoiseLearnerV3 také podporuje učení šumu měření. Pro každou instrukci ve vstupním seznamu spouští protokol učení Pauliho-Lindblad, pokud box obsahuje jedno- a dvouqubitová hradla, a protokol TREX, pokud box obsahuje měření.

Máš migrovat?​

NoiseLearner funguje pouze se starším serverovým Estimator a NoiseLearnerV3 funguje pouze s Executor a klientským Estimator. Musíš migrovat na NoiseLearnerV3, pokud používáš Executor nebo klientský Estimator. Starší serverový Estimator je zastaralý a nahrazen klientským ekvivalentem v qiskit-ibm-runtime v0.50.0.

poznámka

Pokud používáš qiskit-ibm-runtime v0.50.0 nebo novější, nejprve si přečti průvodce Migrace ze serverového na klientský Sampler a Estimator, abys migroval na klientská primitiva.

Kroky migrace​

Krok 1: Změň importy​

NoiseLearner:

from qiskit_ibm_runtime.noise_learner import NoiseLearner

NoiseLearnerV3:

from qiskit_ibm_runtime import NoiseLearnerV3

Krok 2: Aktualizuj vstupy​

Metoda run() třídy NoiseLearner přijímá seznam obvodů nebo PUB, zatímco metoda run() třídy NoiseLearnerV3 přijímá seznam instrukcí, z nichž každá musí být anotovaný twirlingem BoxOp obsahující operace ISA. K dispozici jsou pomocné metody pro generování anotovaných boxů, v závislosti na tom, které primitivum plánuješ použít.

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, při práci s klientským Estimatorem:

Pokud plánuješ použít klientský Estimator pro spouštění obvodů, můžeš použít metodu find_unique_layers z Estimatoru k vytvoření anotovaných boxů (vrstev):

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, při práci s Executorem:

Pokud plánuješ použít Executor pro spouštění obvodů, zvaž použití funkce generate_boxing_pass_manager z Samplomatic k vytvoření anotovaných boxů:

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)

Krok 3: Převeď možnosti​

Většina polí NoiseLearnerOptions se mapuje přímo na NoiseLearnerV3Options, kromě následujících:

  • max_layers_to_learn: S NoiseLearnerV3 je počet vrstev k naučení založen na počtu předaných vrstev.

  • twirling_strategy: S NoiseLearnerV3 je strategie twirlingu definována tím, jak jsou instrukce zabaleny a anotovány (například při použití generate_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, při práci s klientským Estimatorem:

Pokud plánuješ použít klientský Estimator pro spouštění obvodů, můžeš nastavit možnost Estimatoru 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, při práci s Executorem:

Pokud plánuješ použít Executor pro spouštění obvodů, můžeš předat možnost twirling_strategy funkci generate_boxing_pass_manager.

Všimni si, že s generate_boxing_pass_manager() hodnoty twirling_strategy používají podtržítka ("active_accum", "active_circuit"), zatímco hodnoty NoiseLearnerOptions.twirling_strategy používají spojovníky ("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])

Krok 4: Zkontroluj výsledky​

Výstupy NoiseLearner a NoiseLearnerV3 obsahují podobné informace, ale v odlišných formátech. Aktualizuj svůj kód, pokud výstup explicitně zkoumá.

Mapování atributů výsledku:

(learner_result je výstup úlohy learneru)

AtributNoiseLearnerNoiseLearnerV3
Typ výsledkuNoiseLearnerResultNoiseLearnerV3Results, kontejner podobný sekvenci obsahující NoiseLearnerV3Result
Počet naučených vrstevlen(learner_result.data)len(learner_result)
Data pro první vrstvulayer_error = learner_result.data[0]noise_map = learner_result[0].to_pauli_lindblad_map()
Typ výsledku každé vrstvyLayerError (type(layer_error))PauliLindbladMap (type(noise_map))
Generátory chybového kanálulayer_error.error.generatorsnoise_map.generators()
Chybovostlayer_error.error.ratesnoise_map.rates

Krok 5: Vstup modelu šumu do primitiva​

NoiseLearner funguje pouze se starším serverovým Estimator a NoiseLearnerV3 funguje pouze s Executor a klientským Estimator. Způsob, jakým je model šumu specifikován, se mírně liší podle toho, které primitivum se používá.

NoiseLearner, při práci se starším serverovým Estimatorem:

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, při práci s klientským Estimatorem:

Znovu použij stejný Estimator, který vytvořil layers v kroku 2. Mapy šumu vrácené learnerem jsou pozičně přiřazeny k těmto vrstvám, takže musí být přiřazeny Estimatoru, od kterého pocházejí. PEA/PEC na něm bylo již povoleno v kroku 2.

Všimni si, že zatímco NoiseLearnerV3 podporuje jak protokol Pauli-Lindblad, tak TREX, Estimator přijímá pouze modely šumu pro dvouqubitové vrstvy naučené protokolem 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, při práci s Executorem:

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)

Kompletní příklady​

NoiseLearnerV3 a Estimator na straně klienta​

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 a Executor​

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()

Reference​