Pomocný program pro učení šumu
Package versions
Kód na této stránce byl vyvinut s použitím následujících požadavků. Doporučujeme používat tyto verze nebo novější.
qiskit[all]~=2.4.1
qiskit-ibm-runtime~=0.47.0
samplomatic~=0.18.0
Techniky pro potlačení chyb PEA a PEC využívají komponentu pro učení šumu založenou na Pauliho-Lindbladově modelu šumu, která je typicky spravována během spouštění po odeslání jedné nebo více úloh přes qiskit-ibm-runtime bez lokálního přístupu k natrénovanému modelu šumu. Nicméně od verze qiskit-ibm-runtime v0.27.1 byly vytvořeny třídy NoiseLearner a přidružená třída NoiseLearnerOptions, které umožňují získat výsledky těchto experimentů pro učení šumu. Tyto výsledky lze pak lokálně uložit jako NoiseLearnerResult a použít jako vstup v pozdějších experimentech. Tato stránka poskytuje přehled použití a dostupných možností.
Navíc od verze qiskit-ibm-runtime v0.47.0 existuje nová třída NoiseLearnerV3, která je kompatibilní s primitivem Executor. Tato nová verze, také součást modelu řízeného spouštění, ti dává možnost explicitně specifikovat vrstvy, které chceš naučit.
NoiseLearner pracuje pouze s EstimatorV2 a NoiseLearnerV3 pracuje pouze s Executor.
NoiseLearner
Přehled
Třída NoiseLearner provádí experimenty, které charakterizují procesy šumu na základě Pauliho-Lindbladova modelu šumu pro jeden nebo více Circuit. Disponuje metodou run(), která spustí experimenty pro učení a jako vstup přijímá buď seznam Circuit, nebo PUB, a vrací NoiseLearnerResult obsahující naučené kanály šumu a metadata o odeslaných úlohách. Níže je ukázka kódu demonstrující použití tohoto pomocného programu.
# 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()
Výsledný NoiseLearnerResult.data je seznam objektů LayerError obsahujících model šumu pro každou jednotlivou propletací vrstvu patřící k cílovým Circuit. Každý LayerError ukládá informace o vrstvě ve formě Circuit a sady označení qubit, společně s PauliLindbladError pro model šumu naučený pro danou vrstvu.
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 výsledku učení šumu obsahuje generátory a míry chyb natrénovaného Pauliho-Lindbladova modelu, který má tvar
kde jsou LayerError.rates a jsou Pauliho operátory specifikované v LayerError.generators.
Možnosti učení šumu
Při vytváření instance objektu NoiseLearner si můžeš vybrat z několika možností. Tyto možnosti jsou zapouzdřeny třídou qiskit_ibm_runtime.options.NoiseLearnerOptions a zahrnují možnost specifikovat maximální počet vrstev k naučení, počet randomizací a strategii twirling, a další. Podrobnější informace najdeš v dokumentaci API pro NoiseLearnerOptions.
Níže je jednoduchý příklad ukazující, jak použít NoiseLearnerOptions v experimentu s 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()
Předání modelu šumu jako vstup do primitivu
Model šumu naučený na obvod lze také použít jako vstup pro primitiv EstimatorV2 implementovaný v Qiskit Runtime. Lze ho předat primitivu několika různými způsoby. Následující tři příklady ukazují, jak lze předat model šumu přímo atributu estimator.options, použitím objektu ResilienceOptionsV2 před vytvořením instance primitivu Estimator, nebo předáním vhodně formátovaného slovníku.
# 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)
Po předání modelu šumu do objektu EstimatorV2 ho lze použít ke spouštění úloh a provádění potlačení chyb jako obvykle.
NoiseLearnerV3
Přehled
Podobně jako NoiseLearner provádí třída NoiseLearnerV3 experimenty, které charakterizují procesy šumu na základě Pauliho-Lindbladova modelu šumu pro jeden nebo více obvodů. Její metoda run() přijímá seznam instrukcí, z nichž každá musí být twirl-anotovaný BoxOp obsahující operace ISA.
Výsledek úlohy NoiseLearnerV3 obsahuje seznam objektů NoiseLearnerV3Result, jeden pro každou vstupní instrukci.
Následující kód ukazuje, jak použít tento pomocný 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')]
Výsledek úlohy je seznam objektů NoiseLearnerV3Result, jeden pro každou vstupní množinu boxovaných instrukcí. NoiseLearnerV3Result má metodu to_pauli_lindblad_map(), která vrací objekt PauliLindbladMap, jenž má metody pro extrakci generátorů, měr chyb a dalších dat.
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]
Možnosti učení šumu
NoiseLearnerV3 podporuje několik možností, včetně počtu randomizací a hloubky párů vrstev, mimo jiné. Podobně jako u primitivů můžeš možnosti specifikovat během vytváření instance objektu NoiseLearnerV3 nebo po něm. Předchozí příklad kódu ukázal, jak nastavit možnosti shots_per_randomization a num_randomizations. Podrobnější informace najdeš v dokumentaci API pro NoiseLearnerV3Options.
Předání modelu šumu jako vstup do Executor
Executor se řídí záměry návrhu specifikovanými v anotacích obvodů (ve formě samplexu) a možnostech. InjectNoise je anotace pro specifikaci místa injektování šumu a argument samplexu pauli_lindblad_maps specifikuje, který model šumu použít.
Obvod z předchozího příkladu prochází boxing pass managerem, který seskupuje instrukce do anotovaných boxů. Příslušný kód je zde přidán pro lepší pochopení.
inject_noise_targets="gates"specifikuje přidání anotacíInjectNoisedo boxů obsahujících provazovací operace.inject_noise_strategy="uniform_modification"specifikuje přiřazení stejnéhorefamodifier_refvšem ekvivalentním boxům s anotacemiInjectNoise.InjectNoise.refje jedinečný identifikátor používaný k přiřazení modelu šumu danému boxu.InjectNoise.modifier_refumožňuje škálování modelu šumu přiřazeného boxu multiplikativními faktory.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)
Obvod z předchozího příkladu obsahuje tři boxy, dva z nichž obsahují anotace InjectNoise s různými atributy ref (protože nejsou ekvivalentní).
# 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')]
Výsledek úlohy NoiseLearnerV3 musí být převeden na slovník před předáním do Executor. Klíče tohoto slovníku jsou atributy InjectNoise.ref a hodnoty jsou odpovídající modely šumu. Toto mapování říká Executor, které modely šumu injektovat a kam.
Následující kód ukazuje, jak vzít obvod a výsledek NoiseLearnerV3 z předchozího příkladu a předat je Executor, který vygeneruje varianty obvodu s injektovanými modely šumu a spustí je na hardwaru.
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)
Další kroky
- Prohlédni si referenci API pro EstimatorOptions a referenci API pro ResilienceOptionsV2.
- Dozvěz se více o technikách pro potlačení a eliminaci chyb dostupných přes Qiskit Runtime.
- Dozvěz se, jak implementovat správu šumu Estimator.
- Přečti si Migrace na primitivy V2.