Helper pembelajaran noise
Versi paket
Kode di halaman ini dikembangkan menggunakan persyaratan berikut. Kami merekomendasikan menggunakan versi ini atau yang lebih baru.
qiskit[all]~=2.4.1
qiskit-ibm-runtime~=0.47.0
samplomatic~=0.18.0
Teknik mitigasi error PEA dan PEC keduanya menggunakan komponen pembelajaran noise berdasarkan model noise Pauli-Lindblad, yang biasanya dikelola selama eksekusi setelah mengirimkan satu atau lebih job melalui qiskit-ibm-runtime tanpa akses lokal ke model noise yang telah difit. Namun, sejak qiskit-ibm-runtime v0.27.1, kelas NoiseLearner beserta NoiseLearnerOptions telah dibuat untuk mendapatkan hasil eksperimen pembelajaran noise ini. Hasilnya kemudian bisa disimpan secara lokal sebagai NoiseLearnerResult dan digunakan sebagai input dalam eksperimen berikutnya. Halaman ini memberikan gambaran umum tentang penggunaannya dan opsi-opsi yang tersedia.
Selain itu, mulai dari qiskit-ibm-runtime v0.47.0, ada kelas NoiseLearnerV3 baru yang kompatibel dengan primitive Executor. Versi baru ini, yang juga merupakan bagian dari model eksekusi terarah, memberi kamu kemampuan untuk secara eksplisit menentukan lapisan yang ingin dipelajari.
NoiseLearner hanya berfungsi dengan EstimatorV2 dan NoiseLearnerV3 hanya berfungsi dengan Executor.
NoiseLearner
Gambaran umum
Kelas NoiseLearner melakukan eksperimen yang mengkarakterisasi proses noise berdasarkan model noise Pauli-Lindblad untuk satu (atau lebih) Circuit. Kelas ini memiliki metode run() yang mengeksekusi eksperimen pembelajaran dan menerima input berupa daftar Circuit atau sebuah PUB, serta mengembalikan NoiseLearnerResult yang berisi kanal noise yang telah dipelajari beserta metadata tentang job yang dikirimkan. Berikut adalah cuplikan kode yang menunjukkan penggunaan program helper ini.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime samplomatic
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()
NoiseLearnerResult.data yang dihasilkan adalah daftar objek LayerError yang berisi model noise untuk setiap lapisan entangling individual yang termasuk dalam Circuit target. Setiap LayerError menyimpan informasi lapisan dalam bentuk Circuit dan sekumpulan label qubit, bersama dengan PauliLindbladError untuk model noise yang telah dipelajari untuk lapisan tersebut.
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"
)
Noise learner result contains 2 entries and has the following type:
<class 'qiskit_ibm_runtime.utils.noise_learner_result.NoiseLearnerResult'>
Each element of `NoiseLearnerResult` then contains an object of type:
<class 'qiskit_ibm_runtime.utils.noise_learner_result.LayerError'>
And each of these `LayerError` objects possess data on the generators for the error channel:
['IIIIIIIIIIIIIIIIIIIIIIIIIIX', 'IIIIIIIIIIIIIIIIIIIIIIIIIIY',
'IIIIIIIIIIIIIIIIIIIIIIIIIIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIXI',
'IIIIIIIIIIIIIIIIIIIIIIIIIXX', 'IIIIIIIIIIIIIIIIIIIIIIIIIXY',
'IIIIIIIIIIIIIIIIIIIIIIIIIXZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIYI',
'IIIIIIIIIIIIIIIIIIIIIIIIIYX', 'IIIIIIIIIIIIIIIIIIIIIIIIIYY',
'IIIIIIIIIIIIIIIIIIIIIIIIIYZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIZI',
'IIIIIIIIIIIIIIIIIIIIIIIIIZX', 'IIIIIIIIIIIIIIIIIIIIIIIIIZY',
'IIIIIIIIIIIIIIIIIIIIIIIIIZZ', 'IIIIIIIIIIIIIIIIIIIIIIIIXII',
'IIIIIIIIIIIIIIIIIIIIIIIIXIX', 'IIIIIIIIIIIIIIIIIIIIIIIIXIY',
'IIIIIIIIIIIIIIIIIIIIIIIIXIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIYII',
'IIIIIIIIIIIIIIIIIIIIIIIIYIX', 'IIIIIIIIIIIIIIIIIIIIIIIIYIY',
'IIIIIIIIIIIIIIIIIIIIIIIIYIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIZII',
'IIIIIIIIIIIIIIIIIIIIIIIIZIX', 'IIIIIIIIIIIIIIIIIIIIIIIIZIY',
'IIIIIIIIIIIIIIIIIIIIIIIIZIZ', 'IIIIIIIIIIIIIIIIIIIIIIIXIII',
'IIIIIIIIIIIIIIIIIIIIIIIYIII', 'IIIIIIIIIIIIIIIIIIIIIIIZIII',
'IIIIIIIIIIIIIIIIIIIIIIXIIII', 'IIIIIIIIIIIIIIIIIIIIIIXXIII',
'IIIIIIIIIIIIIIIIIIIIIIXYIII', 'IIIIIIIIIIIIIIIIIIIIIIXZIII',
'IIIIIIIIIIIIIIIIIIIIIIYIIII', 'IIIIIIIIIIIIIIIIIIIIIIYXIII',
'IIIIIIIIIIIIIIIIIIIIIIYYIII', 'IIIIIIIIIIIIIIIIIIIIIIYZIII',
'IIIIIIIIIIIIIIIIIIIIIIZIIII', 'IIIIIIIIIIIIIIIIIIIIIIZXIII',
'IIIIIIIIIIIIIIIIIIIIIIZYIII', 'IIIIIIIIIIIIIIIIIIIIIIZZIII',
'IIIIIIIIIIIIIIIIIIIIIXIIIII', 'IIIIIIIIIIIIIIIIIIIIIXXIIII',
'IIIIIIIIIIIIIIIIIIIIIXYIIII', 'IIIIIIIIIIIIIIIIIIIIIXZIIII',
'IIIIIIIIIIIIIIIIIIIIIYIIIII', 'IIIIIIIIIIIIIIIIIIIIIYXIIII',
'IIIIIIIIIIIIIIIIIIIIIYYIIII', 'IIIIIIIIIIIIIIIIIIIIIYZIIII',
'IIIIIIIIIIIIIIIIIIIIIZIIIII', 'IIIIIIIIIIIIIIIIIIIIIZXIIII',
'IIIIIIIIIIIIIIIIIIIIIZYIIII', 'IIIIIIIIIIIIIIIIIIIIIZZIIII',
'IIIIIIIIIIIIIIIIIIIIXIIIIII', 'IIIIIIIIIIIIIIIIIIIIXXIIIII',
'IIIIIIIIIIIIIIIIIIIIXYIIIII', 'IIIIIIIIIIIIIIIIIIIIXZIIIII',
'IIIIIIIIIIIIIIIIIIIIYIIIIII', 'IIIIIIIIIIIIIIIIIIIIYXIIIII',
'IIIIIIIIIIIIIIIIIIIIYYIIIII', 'IIIIIIIIIIIIIIIIIIIIYZIIIII',
'IIIIIIIIIIIIIIIIIIIIZIIIIII', 'IIIIIIIIIIIIIIIIIIIIZXIIIII',
'IIIIIIIIIIIIIIIIIIIIZYIIIII', 'IIIIIIIIIIIIIIIIIIIIZZIIIII',
'IIIIIIIIIIIIIIIIIIIXIIIIIII', 'IIIIIIIIIIIIIIIIIIIXXIIIIII',
'IIIIIIIIIIIIIIIIIIIXYIIIIII', 'IIIIIIIIIIIIIIIIIIIXZIIIIII',
'IIIIIIIIIIIIIIIIIIIYIIIIIII', 'IIIIIIIIIIIIIIIIIIIYXIIIIII',
'IIIIIIIIIIIIIIIIIIIYYIIIIII', 'IIIIIIIIIIIIIIIIIIIYZIIIIII', ...]
Along with the error rates:
[5.9e-04 5.3e-04 5.7e-04 ... 0.0e+00 1.0e-05 0.0e+00]
Atribut LayerError.error dari hasil pembelajaran noise berisi generator dan laju error dari model Pauli Lindblad yang telah difit, yang memiliki bentuk
di mana adalah LayerError.rates dan adalah operator Pauli yang ditentukan dalam LayerError.generators.
Opsi pembelajaran noise
Kamu bisa memilih di antara beberapa opsi saat membuat instance objek NoiseLearner. Opsi-opsi ini dirangkum oleh kelas qiskit_ibm_runtime.options.NoiseLearnerOptions dan mencakup kemampuan untuk menentukan jumlah maksimum lapisan yang akan dipelajari, jumlah randomisasi, dan strategi twirling, di antara opsi lainnya. Lihat dokumentasi API NoiseLearnerOptions untuk informasi lebih detail.
Berikut adalah contoh sederhana yang menunjukkan cara menggunakan NoiseLearnerOptions dalam eksperimen NoiseLearner:
# 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()
Memasukkan model noise ke primitive
Model noise yang dipelajari dari Circuit juga bisa digunakan sebagai input ke primitive EstimatorV2 yang diimplementasikan dalam Qiskit Runtime. Model ini bisa dimasukkan ke dalam primitive dengan beberapa cara berbeda. Tiga contoh berikutnya menunjukkan cara memasukkan model noise ke atribut estimator.options secara langsung, menggunakan objek ResilienceOptionsV2 sebelum membuat instance Estimator primitive, dan dengan memasukkan dictionary berformat yang sesuai.
# Pass the noise model to the `estimator.options` attribute directly
estimator = EstimatorV2(mode=backend)
estimator.options.resilience.layer_noise_model = noise_model
# 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)
# Specify options by using a dictionary
options_dict = {
"resilience_level": 2,
"resilience": {"layer_noise_model": noise_model},
}
estimator = EstimatorV2(mode=backend, options=options_dict)
Setelah model noise dimasukkan ke objek EstimatorV2, model tersebut bisa digunakan untuk menjalankan workload dan melakukan mitigasi error seperti biasa.
NoiseLearnerV3
Gambaran umum
Mirip dengan NoiseLearner, kelas NoiseLearnerV3 melakukan eksperimen yang mengkarakterisasi proses noise berdasarkan model noise Pauli-Lindblad untuk satu atau lebih Circuit. Metode run()-nya menerima daftar instruksi, di mana setiap instruksi harus berupa BoxOp beranotasi twirl yang berisi operasi ISA.
Hasil job NoiseLearnerV3 berisi daftar objek NoiseLearnerV3Result, satu untuk setiap instruksi input.
Kode berikut menunjukkan cara menggunakan program helper ini.
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()
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='r789B', modifier_ref='', site='before')]
Hasil job adalah daftar objek NoiseLearnerV3Result, satu untuk setiap set instruksi berkotak yang menjadi input. NoiseLearnerV3Result memiliki metode to_pauli_lindblad_map() yang mengembalikan objek PauliLindbladMap, yang memiliki metode untuk mengekstrak generator, laju error, dan lainnya.
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"
)
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_0, Y_0, Z_0]>
Along with the error rates (truncated to 3):
[0.00026 0.00032 0.00023]
Opsi pembelajaran noise
NoiseLearnerV3 mendukung beberapa opsi, termasuk jumlah randomisasi dan kedalaman pasangan lapisan, di antara opsi lainnya. Mirip dengan primitive, kamu bisa menentukan opsi saat atau setelah membuat instance objek NoiseLearnerV3. Contoh kode sebelumnya menunjukkan cara menetapkan opsi shots_per_randomization dan num_randomizations. Lihat dokumentasi API NoiseLearnerV3Options untuk informasi lebih detail.
Memasukkan model noise ke Executor
Executor mengikuti maksud desain yang ditentukan dalam anotasi Circuit (dalam bentuk samplex) dan opsi. InjectNoise adalah anotasi untuk menentukan di mana noise akan diinjeksi, dan argumen samplex pauli_lindblad_maps menentukan peta noise mana yang akan digunakan.
Circuit dalam contoh sebelumnya dijalankan melalui boxing pass manager, yang mengelompokkan instruksi ke dalam kotak beranotasi. Kode yang relevan ditambahkan di sini untuk kemudahan pemahaman.
inject_noise_targets="gates"menentukan untuk menambahkan anotasiInjectNoiseke kotak yang berisi entangler.inject_noise_strategy="uniform_modification"menentukan untuk menetapkanrefdanmodifier_refyang sama ke semua kotak setara dengan anotasiInjectNoise.InjectNoise.refadalah pengenal unik yang digunakan untuk menetapkan model noise ke kotak tersebut.InjectNoise.modifier_refmemungkinkan penskalaan model noise yang ditetapkan ke suatu kotak dengan faktor perkalian.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)
Circuit dari contoh sebelumnya berisi tiga kotak, dua di antaranya mengandung anotasi InjectNoise dengan atribut ref yang berbeda (karena tidak setara).
# 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")
Annotations of box #0: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r789B', modifier_ref='r789B', site='before')]
Annotations of box #1: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r054B', modifier_ref='r054B', site='before')]
Annotations of box #2: [Twirl(group='pauli', dressing='right', decomposition='rzsx')]
Hasil job NoiseLearnerV3 harus dikonversi ke dictionary sebelum diteruskan ke Executor. Kunci dictionary ini adalah atribut InjectNoise.ref dan nilainya adalah peta noise yang sesuai. Pemetaan ini memberi tahu Executor model noise mana yang akan diinjeksi di mana.
Kode berikut menunjukkan cara mengambil Circuit dan hasil NoiseLearnerV3 dari contoh sebelumnya dan meneruskannya ke Executor, yang akan menghasilkan varian Circuit dengan model noise yang diinjeksikan dan mengeksekusinya di 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)
Langkah selanjutnya
- Tinjau referensi API EstimatorOptions dan referensi API ResilienceOptionsV2.
- Pelajari lebih lanjut tentang teknik mitigasi dan penekanan error yang tersedia melalui Qiskit Runtime.
- Pelajari cara mengimplementasikan manajemen noise Estimator.
- Baca Migrasi ke V2 primitives.