Lumaktaw sa pangunahing nilalaman

Noise learning helper

Mga bersyon ng package

Ang code sa pahinang ito ay ginawa gamit ang mga sumusunod na requirements. Inirerekomenda naming gamitin ang mga bersyong ito o mas bago pa.

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

Ang mga teknik sa error mitigation na PEA at PEC ay parehong gumagamit ng noise learning component na batay sa isang Pauli-Lindblad noise model, na karaniwang pinamamahalaan sa panahon ng pagpapatupad pagkatapos mag-submit ng isa o higit pang mga trabaho sa pamamagitan ng qiskit-ibm-runtime nang walang lokal na access sa fitted noise model. Gayunpaman, mula sa qiskit-ibm-runtime v0.27.1, isang NoiseLearner at kaugnay na NoiseLearnerOptions na klase ang nilikha para makuha ang mga resulta ng mga noise learning experiment na ito. Ang mga resultang ito ay maaaring i-store nang lokal bilang isang NoiseLearnerResult at gamitin bilang input sa mga susunod na eksperimento. Ibinibigay ng pahinang ito ang pangkalahatang-ideya ng paggamit nito at ng mga kaugnay na opsyon na makukuha.

Bukod dito, simula sa qiskit-ibm-runtime v0.47.0, may bagong klase na NoiseLearnerV3 na katugma sa Executor primitive. Ang bagong bersyong ito, na bahagi rin ng directed execution model, ay nagbibigay sa iyo ng kakayahang tahasang tukuyin ang mga layer na nais mong matutunan.

tala

NoiseLearner ay gumagana lamang sa EstimatorV2 at NoiseLearnerV3 ay gumagana lamang sa Executor.

NoiseLearner

Pangkalahatang-ideya

Ang NoiseLearner na klase ay nagsasagawa ng mga eksperimento na nagtatasa ng mga proseso ng ingay batay sa isang Pauli-Lindblad noise model para sa isa (o higit pa) na mga circuit. Mayroon itong run() na pamamaraan na nagpapatakbo ng mga learning experiment at tumatanggap bilang input ng alinman sa isang listahan ng mga circuit o isang PUB, at nagbabalik ng NoiseLearnerResult na naglalaman ng mga natutunang noise channel at metadata tungkol sa mga isinumiteng trabaho. Sa ibaba ay isang code snippet na nagpapakita ng paggamit ng helper program.

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

Ang resultang NoiseLearnerResult.data ay isang listahan ng mga LayerError na object na naglalaman ng noise model para sa bawat indibidwal na entangling layer na kabilang sa target na circuit(s). Bawat LayerError ay nag-iimbak ng impormasyon ng layer, sa anyo ng isang circuit at isang set ng mga qubit label, kasama ang PauliLindbladError para sa noise model na natuto para sa ibinigay na layer.

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]

Ang LayerError.error na katangian ng noise learning result ay naglalaman ng mga generator at error rate ng fitted na Pauli Lindblad model, na may ganitong anyo

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

kung saan ang rjr_j ay ang LayerError.rates at ang PjP_j ay ang mga Pauli operator na tinukoy sa LayerError.generators.

Mga opsyon sa noise learning

Maaari kang pumili mula sa ilang opsyon na ilalagay kapag nag-instantiate ka ng NoiseLearner na object. Ang mga opsyong ito ay naka-encapsulate ng qiskit_ibm_runtime.options.NoiseLearnerOptions na klase at kasama ang kakayahang tukuyin ang maximum na mga layer na matututunan, bilang ng mga randomization, at ang twirling strategy, bukod sa iba pa. Sumangguni sa dokumentasyon ng API ng NoiseLearnerOptions para sa detalyadong impormasyon.

Ang sumusunod ay isang simpleng halimbawa ng kung paano gamitin ang NoiseLearnerOptions sa isang NoiseLearner na eksperimento:

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

Ipasok ang noise model sa isang primitive

Ang noise model na natuto sa circuit ay maaari ring gamitin bilang input sa EstimatorV2 primitive na ipinatupad sa Qiskit Runtime. Ito ay maaaring ipasa sa primitive sa ilang iba't ibang paraan. Ang susunod na tatlong halimbawa ay nagpapakita kung paano mo maipapasa ang noise model sa estimator.options na katangian nang direkta, sa pamamagitan ng paggamit ng isang ResilienceOptionsV2 na object bago mag-instantiate ng Estimator primitive, at sa pamamagitan ng pagpasa ng isang naaangkop na na-format na dictionary.

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

Pagkatapos mailagay ang noise model sa EstimatorV2 na object, maaari na itong gamitin para magpatakbo ng mga workload at magsagawa ng error mitigation gaya ng karaniwan.

NoiseLearnerV3

Pangkalahatang-ideya

Katulad ng NoiseLearner, ang NoiseLearnerV3 na klase ay nagsasagawa ng mga eksperimento na nagtatasa ng mga proseso ng ingay batay sa isang Pauli-Lindblad noise model para sa isa o higit pang mga circuit. Ang run() na pamamaraan nito ay tumatanggap ng listahan ng mga instruction, na bawat isa ay dapat na twirled-annotated BoxOp na naglalaman ng mga operasyon ng ISA.

Ang resulta ng isang NoiseLearnerV3 na trabaho ay naglalaman ng listahan ng mga NoiseLearnerV3Result na object, isa para sa bawat input na instruction. Ipinapakita ng sumusunod na code kung paano gamitin ang helper program.

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

Ang resulta ng trabaho ay isang listahan ng mga NoiseLearnerV3Result na object, isa para sa bawat input na boxed set ng mga instruction. Ang NoiseLearnerV3Result ay may to_pauli_lindblad_map() na pamamaraan na nagbabalik ng isang PauliLindbladMap na object, na may mga pamamaraan para kunin ang mga generator, error rate, at iba pa.

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]

Mga opsyon sa noise learning

Sinusuportahan ng NoiseLearnerV3 ang ilang opsyon, kasama ang bilang ng mga randomization at layer pair depth, bukod sa iba pa. Katulad ng mga primitive, maaari mong tukuyin ang mga opsyon sa panahon ng o pagkatapos mag-instantiate ng NoiseLearnerV3 na object. Ipinapakita ng nakaraang halimbawa ng code kung paano itakda ang shots_per_randomization at num_randomizations na opsyon. Sumangguni sa dokumentasyon ng API ng NoiseLearnerV3Options para sa detalyadong impormasyon.

Ipasok ang noise model sa Executor

Sinusunod ng Executor ang mga layunin ng disenyo na tinukoy sa mga anotasyon ng circuit (sa anyo ng samplex) at mga opsyon. Ang InjectNoise ay ang anotasyon para tukuyin kung saan mag-i-inject ng ingay, at ang pauli_lindblad_maps na samplex argument ay tumutukoy kung aling noise map ang gagamitin.

Ang circuit sa nakaraang halimbawa ay tumatakbo sa pamamagitan ng boxing pass manager, na nagpogroup ng mga instruction sa mga annotated box. Ang kaugnay na code ay idinagdag dito para sa kaginhawaan ng pag-unawa.

  • Ang inject_noise_targets="gates" ay tumutukoy na idagdag ang mga InjectNoise na anotasyon sa mga box na naglalaman ng mga entangler.
  • Ang inject_noise_strategy="uniform_modification" ay tumutukoy na magtakda ng parehong ref at modifier_ref sa lahat ng katumbas na box na may mga InjectNoise na anotasyon.
    • Ang InjectNoise.ref ay isang natatanging identifier na ginagamit para mag-assign ng noise model sa box na iyon.
    • Ang InjectNoise.modifier_ref ay nagbibigay-daan sa pag-scale ng noise model na itinalaga sa isang box sa pamamagitan ng mga multiplicative factor.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)

Ang circuit mula sa nakaraang halimbawa ay naglalaman ng tatlong box, dalawa sa mga ito ay may mga InjectNoise na anotasyon na may iba't ibang ref na katangian (dahil hindi sila katumbas).

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

Ang resulta ng NoiseLearnerV3 na trabaho ay dapat i-convert sa isang dictionary bago mailagay sa Executor. Ang mga key ng dictionary na ito ay ang mga InjectNoise.ref na katangian at ang mga value ay ang mga kaugnay na noise map. Ang mapping na ito ay nagsasabi sa Executor kung aling mga noise model ang i-i-inject at saan.

Ipinapakita ng sumusunod na code kung paano kunin ang circuit at ang NoiseLearnerV3 na resulta mula sa nakaraang halimbawa at ipasa ang mga ito sa Executor, na magge-generate ng mga variant ng circuit na may mga na-inject na noise model at ipapatakbo ang mga ito sa 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)

Mga susunod na hakbang

Mga rekomendasyon