소음 학습 도우미
이 페이지의 코드는 다음 요구 사항을 사용하여 개발되었습니다. 다음 버전 이상을 사용하는 것이 좋습니다.
qiskit[all]~=2.5.2 qiskit-ibm-runtime~=0.47.0 samplomatic~=0.21.0
오류 완화 기법인 PEA와 PEC는 모두 파울리-린드블라드(Pauli-Lindblad) 노이즈 모델을 기반으로 한 노이즈 학습 구성 요소를 활용하며, 이는 일반적으로 하나 이상의 작업을 제출한 후 실행 중에 관리되는데, 이때 qiskit-ibm-runtime 피팅된 노이즈 모델에 대한 로컬 액세스 권한은 전혀 부여되지 않습니다. 그러나 qiskit-ibm-runtimev0.27.1 를 기준으로, 이러한 노이즈 학습 실험 결과를 얻기 위해 및 관련 NoiseLearnerOptions 클래스가 NoiseLearner 생성되었습니다. 이러한 결과는 로컬에 파일로 NoiseLearnerResult 저장하여 추후 실험에서 입력 데이터로 활용할 수 있습니다. 이 페이지에서는 해당 기능의 사용법과 관련 옵션에 대한 개요를 제공합니다.
또한, qiskit-ibm-runtimev0.47.0 부터 Executor 기본 유형과 호환되는 새로운 NoiseLearnerV3 클래스가 추가되었습니다. 이 새로운 버전은 지시형 실행 모델의 일부이기도 하며, 학습하고자 하는 레이어를 명시적으로 지정할 수 있는 기능을 제공합니다.
NoiseLearner EstimatorV2 에서만 작동하며, NoiseLearnerV3 Executor에서만 작동합니다.
NoiseLearner
개요
이 NoiseLearner 수업에서는 하나(또는 그 이상)의 회로에 대해 파울리-린드블라드 잡음 모델을 기반으로 잡음 과정을 규명하는 실험을 수행합니다. 이 클래스는 학습 실험을 실행하는 run() 메서드를 갖추고 있으며, 회로 목록이나 PUB 를 입력으로 받아, 학습된 노이즈 채널과 제출된 작업에 대한 메타데이터를 포함하는 NoiseLearnerResult 객체를 반환합니다. 다음은 헬퍼 프로그램의 사용법을 보여주는 코드 예시입니다.
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()그 결과로 생성된 것은 대상 회로에 속하는 각 얽힘 계층에 대한 노이즈 모델을 포함하는 LayerError 객체들의 목록입니다 NoiseLearnerResult.data . 각 레이어는 회로와 큐비트 레이블 집합의 형태로 레이어 정보를 저장하며 LayerError , 주어진 레이어에 대해 PauliLindbladError 학습된 노이즈 모델 정보도 함께 저장합니다.
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"
)Output:
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',
'IIIIIIIIIIIIIIIIIIIIIIIIXXI', 'IIIIIIIIIIIIIIIIIIIIIIIIXYI',
'IIIIIIIIIIIIIIIIIIIIIIIIXZI', 'IIIIIIIIIIIIIIIIIIIIIIIIYII',
'IIIIIIIIIIIIIIIIIIIIIIIIYXI', 'IIIIIIIIIIIIIIIIIIIIIIIIYYI',
'IIIIIIIIIIIIIIIIIIIIIIIIYZI', 'IIIIIIIIIIIIIIIIIIIIIIIIZII',
'IIIIIIIIIIIIIIIIIIIIIIIIZXI', 'IIIIIIIIIIIIIIIIIIIIIIIIZYI',
'IIIIIIIIIIIIIIIIIIIIIIIIZZI', 'IIIIIIIIIIIIIIIIIIIIIIIXIII',
'IIIIIIIIIIIIIIIIIIIIIIIXXII', 'IIIIIIIIIIIIIIIIIIIIIIIXYII',
'IIIIIIIIIIIIIIIIIIIIIIIXZII', 'IIIIIIIIIIIIIIIIIIIIIIIYIII',
'IIIIIIIIIIIIIIIIIIIIIIIYXII', 'IIIIIIIIIIIIIIIIIIIIIIIYYII',
'IIIIIIIIIIIIIIIIIIIIIIIYZII', 'IIIIIIIIIIIIIIIIIIIIIIIZIII',
'IIIIIIIIIIIIIIIIIIIIIIIZXII', 'IIIIIIIIIIIIIIIIIIIIIIIZYII',
'IIIIIIIIIIIIIIIIIIIIIIIZZII', 'IIIIIIIIIIIIIIIIIIIIIIXIIII',
'IIIIIIIIIIIIIIIIIIIIIIXXIII', 'IIIIIIIIIIIIIIIIIIIIIIXYIII',
'IIIIIIIIIIIIIIIIIIIIIIXZIII', 'IIIIIIIIIIIIIIIIIIIIIIYIIII',
'IIIIIIIIIIIIIIIIIIIIIIYXIII', 'IIIIIIIIIIIIIIIIIIIIIIYYIII',
'IIIIIIIIIIIIIIIIIIIIIIYZIII', 'IIIIIIIIIIIIIIIIIIIIIIZIIII',
'IIIIIIIIIIIIIIIIIIIIIIZXIII', 'IIIIIIIIIIIIIIIIIIIIIIZYIII',
'IIIIIIIIIIIIIIIIIIIIIIZZIII', 'IIIIIIIIIIIIIIIIIIIIIXIIIII',
'IIIIIIIIIIIIIIIIIIIIIXIIIIX', 'IIIIIIIIIIIIIIIIIIIIIXIIIIY',
'IIIIIIIIIIIIIIIIIIIIIXIIIIZ', 'IIIIIIIIIIIIIIIIIIIIIYIIIII',
'IIIIIIIIIIIIIIIIIIIIIYIIIIX', 'IIIIIIIIIIIIIIIIIIIIIYIIIIY',
'IIIIIIIIIIIIIIIIIIIIIYIIIIZ', 'IIIIIIIIIIIIIIIIIIIIIZIIIII',
'IIIIIIIIIIIIIIIIIIIIIZIIIIX', 'IIIIIIIIIIIIIIIIIIIIIZIIIIY',
'IIIIIIIIIIIIIIIIIIIIIZIIIIZ', 'IIIIIIIIIIIIIIIIIIIIXIIIIII',
'IIIIIIIIIIIIIIIIIIIIXIXIIII', 'IIIIIIIIIIIIIIIIIIIIXIYIIII',
'IIIIIIIIIIIIIIIIIIIIXIZIIII', 'IIIIIIIIIIIIIIIIIIIIYIIIIII',
'IIIIIIIIIIIIIIIIIIIIYIXIIII', 'IIIIIIIIIIIIIIIIIIIIYIYIIII',
'IIIIIIIIIIIIIIIIIIIIYIZIIII', 'IIIIIIIIIIIIIIIIIIIIZIIIIII',
'IIIIIIIIIIIIIIIIIIIIZIXIIII', 'IIIIIIIIIIIIIIIIIIIIZIYIIII', ...]
Along with the error rates:
[0.00037 0.00043 0.00032 ... 0.00031 0.00035 0.00017]
노이즈 학습 결과의 LayerError.error 속성에는 적합된 폴리 린드블래드 모델의 생성자와 오류율이 포함되어 있으며, 다음과 같은 형식을 갖습니다
여기서 은 LayerError.rates 과 은 LayerError.generators 에 지정된 폴리 연산자입니다.
소음 학습 옵션
객체를 NoiseLearner 생성할 때 여러 입력 옵션 중에서 선택할 수 있습니다. 이러한 옵션들은 클래스에 qiskit_ibm_runtime.options.NoiseLearnerOptions 포함되어 있으며, 학습할 최대 레이어 수, 무작위화 횟수, 트위링 전략 등을 지정할 수 있는 기능을 포함합니다. 자세한 내용은 API 문서를 NoiseLearnerOptions 참조하십시오.
다음은 실험에서 NoiseLearner 를 NoiseLearnerOptions 사용하는 방법을 보여주는 간단한 예시입니다:
# 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()노이즈 모델을 프리미티브에 입력
회로에서 학습된 노이즈 모델은 IBM QuantumEstimatorV2 프라이머리트의 입력으로도 사용할 수 있습니다. 이는 몇 가지 다른 방법으로 기본형에 전달될 수 있습니다. 다음 세 가지 예제는 노이즈 모델을 estimator.options 속성에 직접 전달하는 방법, Estimator 프리미티브를 인스턴스화하기 전에 ResilienceOptionsV2 객체를 사용하는 방법, 그리고 적절한 형식으로 구성된 딕셔너리를 전달하는 방법을 보여줍니다.
# 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)노이즈 모델이 객체에 EstimatorV2 전달되면, 이를 사용하여 평소와 같이 워크로드를 실행하고 오류 완화 작업을 수행할 수 있습니다.
NoiseLearnerV3
개요
NoiseLearner와 마찬가지로, 이 NoiseLearnerV3 클래스는 하나 이상의 회로에 대해 파울리-린드블라드 잡음 모델을 기반으로 잡음 과정을 규명하는 실험을 수행합니다. 이 run() 메서드는 명령어 목록을 인수로 받으며, 각 명령어는 ISA 연산을 포함하는 트위얼드 주석이 BoxOp 달린 객체여야 합니다.
작업의 NoiseLearnerV3 결과에는 각 입력 명령어마다 하나씩, 총 개수의 NoiseLearnerV3Result 객체 목록이 포함됩니다.
다음 코드는 헬퍼 프로그램을 사용하는 방법을 보여줍니다.
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()Output:
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='r223A', modifier_ref='', site='after')]
작업 결과는 객체들의 NoiseLearnerV3Result 목록으로, 입력된 각 명령어 집합마다 하나의 객체가 포함됩니다. NoiseLearnerV3Result 에는 객체를 PauliLindbladMap 반환하는 메서드가 to_pauli_lindblad_map() 있으며, 이 객체에는 생성기, 오류율 등을 추출하는 메서드들이 포함되어 있습니다.
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"
)Output:
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_5, Y_5, Z_5]>
Along with the error rates (truncated to 3):
[2.3e-04 9.0e-05 1.1e-04]
소음 학습 옵션
NoiseLearnerV3 무작위화 횟수 및 레이어 쌍의 깊이 등 여러 가지 옵션을 지원합니다. 기본 유형과 마찬가지로, 객체를 NoiseLearnerV3 생성하는 도중이나 생성 후에 옵션을 지정할 수 있습니다. 앞서 소개한 코드 예제에서는 및 num_randomizations shots_per_randomization 옵션을 설정하는 방법을 보여주었습니다. 자세한 내용은 API 문서를 NoiseLearnerV3Options 참조하십시오.
Executor에 노이즈 모델을 입력합니다
Executor는 회로 어노테이션(samplex 형식) 및 옵션에 명시된 설계 의도를 따릅니다. InjectNoise 는 노이즈를 삽입할 위치를 지정하는 주석이며, samplex 인수는 pauli_lindblad_maps 사용할 노이즈 맵을 지정합니다.
앞의 예제에서 소개된 회로는 박싱 패스 관리자를 통해 실행되며, 이 관리자는 명령어를 주석이 달린 박스 단위로 묶습니다. 이해를 돕기 위해 관련 코드를 여기에 추가합니다.
inject_noise_targets=”gates”얽힘 생성자가 포함된 상자에 주석을InjectNoise추가하도록 지정합니다.inject_noise_strategy="uniform_modification"... 주석이 달린InjectNoise모든 동등한 상자에 동일한ref와modifier_ref를 할당하도록 지정합니다.InjectNoise.ref해당 상자에 소음 모델을 할당하는 데 사용되는 고유 식별자입니다.InjectNoise.modifier_ref상자에 할당된 노이즈 모델을 곱셈 계수를 사용하여 조정할 수 있습니다.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=False,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)이전 예제의 회로에는 세 개의 상자가 포함되어 있으며, 그중 두 개에는 서로 다른 ref 속성을 가진 주석이 포함되어 InjectNoise 있습니다(두 상자가 서로 동일하지 않기 때문입니다).
# 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")Output:
Annotations of box #0: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r223A', modifier_ref='r223A', site='after')]
Annotations of box #1: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r621A', modifier_ref='r621A', site='after')]
Annotations of box #2: [Twirl(group='pauli', dressing='right', decomposition='rzsx')]
작업의 NoiseLearnerV3 결과는 Executor로 전달되기 전에 사전(dictionary) 형식으로 변환되어야 합니다. 이 사전의 키는 속성이며, 값은 해당 InjectNoise.ref 속성에 대응하는 노이즈 맵입니다. 이 매핑은 Executor에게 어떤 노이즈 모델을 어디에 주입해야 하는지 알려줍니다.
다음 코드는 이전 예제의 회로와 결과를 NoiseLearnerV3 가져와 Executor에 전달하는 방법을 보여줍니다. Executor는 주입된 노이즈 모델을 적용한 회로 변형을 생성하고 이를 하드웨어에서 실행합니다.
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)다음 단계
- EstimatorOptions API 참조 및 ResilienceOptionsV2 API 참조를 검토하세요.
- 사용 가능한 오류 완화 및 억제 기법에 대해 자세히 알아보세요.
- 에스티메이터 노이즈 관리 기능을 구현하는 방법을 알아보세요.