Migrează de la NoiseLearner la NoiseLearnerV3
Acest ghid te conduce prin migrarea de la IBM Quantum® NoiseLearner la NoiseLearnerV3. Ambele
clase efectuează experimente care caracterizează procesele de zgomot pe baza unui
model de zgomot Pauli-Lindblad, dar intrările și
ieșirile sunt ușor diferite.
Context
Clasa NoiseLearner
a fost creată pentru a permite utilizatorilor să efectueze învățarea explicită a zgomotului. Modelul de zgomot
rezultat poate fi apoi transmis către Estimator IBM Quantum pentru aplicarea tehnicilor de atenuare a erorilor
cum ar fi PEA și PEC.
NoiseLearner a fost proiectat să funcționeze cu Estimator, și prin urmare folosește implicit aceeași
strategie de găsire a straturilor ca Estimator. Această strategie nu poate fi schimbată; altfel, pașii
ulteriori de atenuare nu ar funcționa corect.
Începând cu qiskit-ibm-runtime v0.47.0, există o nouă clasă
NoiseLearnerV3
care este compatibilă cu primitiva Executor și cu
modelul de execuție direcționată.
Acest nou model oferă o experiență de tip cutie albă furnizând piesele pentru a captura intenția de design
pe partea de client, iar o singură primitivă server-side (Executor) procesează acele intrări exact așa cum
sunt direcționate — nu ia decizii implicite în numele tău. Spre deosebire de NoiseLearner original,
controlezi cum să îți stratifici circuitele atunci când folosești NoiseLearnerV3, iar clasa primește pur și simplu o listă de instrucțiuni de circuit încadrate
(de exemplu, straturi unice) ca intrare.
NoiseLearnerV3 suportă de asemenea învățarea zgomotului de măsurare. Pentru fiecare instrucțiune din lista de intrare, rulează
protocolul de învățare Pauli-Lindblad dacă cutia conține porți cu unul și doi qubiți, și
protocolul TREX
dacă cutia conține măsurători.
Ar trebui să migrezi?
NoiseLearner funcționează doar cu Estimator server-side vechi, iar NoiseLearnerV3 funcționează doar cu
Executor și Estimator client-side. Trebuie să migrezi la NoiseLearnerV3 dacă folosești
Executor sau Estimator client-side. Estimator server-side vechi este depreciat și înlocuit de echivalentul client-side în qiskit-ibm-runtime v0.50.0.
Dacă folosești qiskit-ibm-runtime v0.50.0 sau o versiune ulterioară, citește ghidul Migrează de la Sampler și Estimator server-side la client-side pentru a migra mai întâi la primitivele client-side.
Pașii de migrare
Pasul 1: Schimbă importurile
NoiseLearner:
from qiskit_ibm_runtime.noise_learner import NoiseLearner
NoiseLearnerV3:
from qiskit_ibm_runtime import NoiseLearnerV3
Pasul 2: Actualizează intrările
Metoda run() a lui NoiseLearner primește o listă de circuite sau PUB-uri, în timp ce metoda run() a lui NoiseLearnerV3 primește o listă de instrucțiuni, fiecare dintre acestea trebuind să fie un BoxOp adnotat cu twirling care conține operații ISA.
Sunt disponibile metode ajutătoare pentru generarea cutiilor adnotate, în funcție de
primitiva pe care intenționezi să o folosești.
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, atunci când lucrează cu Estimator client-side:
Dacă intenționezi să folosești Estimator client-side pentru execuția circuitului, poți folosi metoda find_unique_layers din Estimator pentru a crea cutii adnotate (straturi):
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, atunci când lucrează cu Executor:
Dacă intenționezi să folosești Executor pentru execuția circuitului, ia în considerare folosirea funcției generate_boxing_pass_manager din Samplomatic pentru a crea cutii adnotate:
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)
Pasul 3: Convertește opțiunile
Majoritatea câmpurilor NoiseLearnerOptions se mapează direct la NoiseLearnerV3Options, cu excepția următoarelor:
-
max_layers_to_learn: CuNoiseLearnerV3, numărul de straturi de învățat se bazează pe numărul de straturi transmise. -
twirling_strategy: CuNoiseLearnerV3, strategia de twirling este definită de modul în care instrucțiunile sunt încadrate și adnotate (cum ar fi atunci când se foloseștegenerate_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, atunci când lucrează cu Estimator client-side:
Dacă intenționezi să folosești Estimator client-side pentru execuția circuitului, poți
seta opțiunea twirling.strategy a Estimator:
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, atunci când lucrează cu Executor:
Dacă intenționezi să folosești Executor pentru execuția circuitului, poți transmite opțiunea twirling_strategy funcției generate_boxing_pass_manager.
Reține că, cu generate_boxing_pass_manager(), valorile twirling_strategy folosesc underscore-uri
("active_accum", "active_circuit"), în timp ce valorile NoiseLearnerOptions.twirling_strategy folosesc cratime ("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])
Pasul 4: Inspectează rezultatele
Ieșirile lui NoiseLearner și NoiseLearnerV3 conțin informații similare, dar în formate diferite. Actualizează-ți codul dacă inspectează explicit rezultatul.
Maparea atributelor rezultatului:
(learner_result este rezultatul jobului de învățare)
| Atribut | NoiseLearner | NoiseLearnerV3 |
|---|---|---|
| Tip de rezultat | NoiseLearnerResult | NoiseLearnerV3Results, un container de tip secvență de NoiseLearnerV3Result |
| Numărul de straturi învățate | len(learner_result.data) | len(learner_result) |
| Date pentru primul strat | layer_error = learner_result.data[0] | noise_map = learner_result[0].to_pauli_lindblad_map() |
| Tip de rezultat al fiecărui strat | LayerError (type(layer_error)) | PauliLindbladMap (type(noise_map)) |
| Generatori pentru canalul de eroare | layer_error.error.generators | noise_map.generators() |
| Rate de eroare | layer_error.error.rates | noise_map.rates |
Pasul 5: Introdu modelul de zgomot într-o primitivă
NoiseLearner funcționează doar cu Estimator server-side vechi, iar NoiseLearnerV3 funcționează doar cu Executor și Estimator client-side. Modul în care este specificat un model de zgomot variază ușor în funcție de primitiva utilizată.
NoiseLearner, atunci când lucrează cu Estimator server-side vechi:
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, atunci când lucrează cu Estimator client-side:
Refolosește același Estimator care a produs layers la pasul 2. Hărțile de zgomot returnate de
cel care învață sunt potrivite pozițional cu acele straturi, așa că trebuie atribuite Estimator-ului
de la care provin. PEA/PEC era deja activat pe acesta la pasul 2.
Reține că, deși NoiseLearnerV3 suportă atât protocolul Pauli-Lindblad, cât și protocolul TREX, Estimator acceptă doar modele de zgomot pentru straturile cu doi qubiți învățate cu protocolul 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, atunci când lucrează cu 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)
Exemple complete
NoiseLearnerV3 și Estimator client-side
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 și 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()