Langkau ke kandungan utama

Pembantu pembelajaran hingar

Versi pakej

Kod pada halaman ini dibangunkan menggunakan keperluan berikut. Kami mengesyorkan menggunakan versi ini atau yang lebih baru.

qiskit[all]~=2.4.1
qiskit-ibm-runtime~=0.47.0
samplomatic~=0.18.0

Teknik pengurangan ralat PEA dan PEC kedua-duanya menggunakan komponen pembelajaran hingar berdasarkan model hingar Pauli-Lindblad, yang biasanya diuruskan semasa pelaksanaan selepas menyerahkan satu atau lebih kerja melalui qiskit-ibm-runtime tanpa sebarang akses tempatan kepada model hingar yang telah dipadankan. Walau bagaimanapun, mulai qiskit-ibm-runtime v0.27.1, kelas NoiseLearner dan NoiseLearnerOptions yang berkaitan telah dicipta untuk mendapatkan keputusan eksperimen pembelajaran hingar ini. Keputusan ini kemudiannya boleh disimpan secara tempatan sebagai NoiseLearnerResult dan digunakan sebagai input dalam eksperimen kemudian. Halaman ini memberikan gambaran keseluruhan penggunaannya dan pilihan yang tersedia.

Selain itu, bermula dengan qiskit-ibm-runtime v0.47.0, terdapat kelas NoiseLearnerV3 baharu yang serasi dengan primitif Executor. Versi baharu ini, juga sebahagian daripada model pelaksanaan terarah, memberi anda keupayaan untuk menentukan secara eksplisit lapisan yang ingin anda pelajari.

nota

NoiseLearner hanya berfungsi dengan EstimatorV2 dan NoiseLearnerV3 hanya berfungsi dengan Executor.

NoiseLearner

Gambaran keseluruhan

Kelas NoiseLearner melakukan eksperimen yang mencirikan proses hingar berdasarkan model hingar Pauli-Lindblad untuk satu (atau lebih) litar. Ia mempunyai kaedah run() yang melaksanakan eksperimen pembelajaran dan mengambil sebagai input sama ada senarai litar atau PUB, dan mengembalikan NoiseLearnerResult yang mengandungi saluran hingar yang dipelajari dan metadata tentang kerja yang diserahkan. Berikut adalah serpihan kod yang menunjukkan penggunaan program pembantu.

# 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 ialah senarai objek LayerError yang mengandungi model hingar untuk setiap lapisan penjalin individu yang tergolong dalam litar sasaran. Setiap LayerError menyimpan maklumat lapisan, dalam bentuk litar dan set label qubit, bersama-sama PauliLindbladError untuk model hingar yang telah dipelajari bagi lapisan yang diberikan.

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 bagi keputusan pembelajaran hingar mengandungi penjana dan kadar ralat model Pauli Lindblad yang dipadankan, yang mempunyai bentuk

Λ(ρ)=expjrj(PjρPjρ),\Lambda(\rho) = \exp{\sum_j r_j \left(P_j \rho P_j^\dagger - \rho\right)},

di mana rjr_j adalah LayerError.rates dan PjP_j adalah operator Pauli yang ditentukan dalam LayerError.generators.

Pilihan pembelajaran hingar

Anda boleh memilih antara beberapa pilihan untuk dimasukkan apabila anda membuat instance objek NoiseLearner. Pilihan-pilihan ini dirangkum oleh kelas qiskit_ibm_runtime.options.NoiseLearnerOptions dan termasuk keupayaan untuk menentukan lapisan maksimum untuk dipelajari, bilangan rawak, dan strategi twirling, antara lain. Rujuk dokumentasi API NoiseLearnerOptions untuk maklumat yang lebih terperinci.

Berikut adalah contoh mudah 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()

Masukkan model hingar ke dalam primitif

Model hingar yang dipelajari pada litar juga boleh digunakan sebagai input kepada primitif EstimatorV2 yang dilaksanakan dalam Qiskit Runtime. Ini boleh dihantar ke dalam primitif dengan beberapa cara yang berbeza. Tiga contoh seterusnya menunjukkan cara anda boleh menghantar model hingar ke atribut estimator.options secara langsung, menggunakan objek ResilienceOptionsV2 sebelum membuat instance primitif Estimator, dan dengan menghantar kamus berformat bersesuaian.

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

Selepas model hingar dimasukkan ke dalam objek EstimatorV2, ia boleh digunakan untuk menjalankan beban kerja dan melakukan pengurangan ralat seperti biasa.

NoiseLearnerV3

Gambaran keseluruhan

Sama seperti NoiseLearner, kelas NoiseLearnerV3 melakukan eksperimen yang mencirikan proses hingar berdasarkan model hingar Pauli-Lindblad untuk satu atau lebih litar. Kaedah run()-nya mengambil senarai arahan, yang masing-masing mestilah BoxOp beranotasi twirled yang mengandungi operasi ISA.

Keputusan kerja NoiseLearnerV3 mengandungi senarai objek NoiseLearnerV3Result, satu untuk setiap arahan input. Kod berikut menunjukkan cara menggunakan program pembantu.

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')]

Keputusan kerja ialah senarai objek NoiseLearnerV3Result, satu untuk setiap set arahan berkotak input. NoiseLearnerV3Result mempunyai kaedah to_pauli_lindblad_map() yang mengembalikan objek PauliLindbladMap, yang mempunyai kaedah untuk mengekstrak penjana, kadar ralat, dan lain-lain.

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]

Pilihan pembelajaran hingar

NoiseLearnerV3 menyokong beberapa pilihan, termasuk bilangan rawak dan kedalaman pasangan lapisan, antara lain. Sama seperti primitif, anda boleh menentukan pilihan semasa atau selepas membuat instance objek NoiseLearnerV3. Contoh kod sebelumnya menunjukkan cara menetapkan pilihan shots_per_randomization dan num_randomizations. Rujuk dokumentasi API NoiseLearnerV3Options untuk maklumat yang lebih terperinci.

Masukkan model hingar ke Executor

Executor mengikut niat reka bentuk yang ditentukan dalam anotasi litar (dalam bentuk samplex) dan pilihan. InjectNoise ialah anotasi untuk menentukan di mana hendak menyuntik hingar, dan argumen samplex pauli_lindblad_maps menentukan peta hingar yang hendak digunakan.

Litar dalam contoh sebelumnya dijalankan melalui pengurus laluan pemboksan, yang mengumpulkan arahan ke dalam kotak beranotasi. Kod yang berkaitan ditambah di sini untuk kemudahan pemahaman.

  • inject_noise_targets="gates" menentukan untuk menambah anotasi InjectNoise pada kotak yang mengandungi penjalin.
  • inject_noise_strategy="uniform_modification" menentukan untuk menetapkan ref dan modifier_ref yang sama kepada semua kotak setara dengan anotasi InjectNoise.
    • InjectNoise.ref ialah pengecam unik yang digunakan untuk menetapkan model hingar kepada kotak tersebut.
    • InjectNoise.modifier_ref membenarkan pengskalaan model hingar yang ditetapkan kepada kotak dengan faktor pendaraban.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)

Litar daripada contoh sebelumnya mengandungi tiga kotak, dua daripadanya mengandungi anotasi InjectNoise dengan atribut ref yang berbeza (kerana ia 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')]

Keputusan kerja NoiseLearnerV3 mesti ditukar kepada kamus sebelum dihantar ke Executor. Kunci kamus ini ialah atribut InjectNoise.ref dan nilainya ialah peta hingar yang berkaitan. Pemetaan ini memberitahu Executor model hingar mana yang hendak disuntik di mana.

Kod berikut menunjukkan cara mengambil litar dan keputusan NoiseLearnerV3 daripada contoh sebelumnya dan menghantar mereka ke Executor, yang akan menjana varian litar dengan model hingar yang disuntik dan melaksanakannya pada perkakasan.

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 seterusnya

Cadangan