집행자 예시
이 페이지의 코드는 다음 요구 사항을 바탕으로 개발되었습니다. 이 버전 이상을 사용하시기를 권장합니다.
qiskit[all]~=2.5.2 qiskit-ibm-runtime~=0.47.0 samplomatic~=0.21.0
이 섹션의 예제는 Executor 기본 객체를 사용하는 몇 가지 일반적인 방법을 보여줍니다. 이 예제를 실행하기 전에, ‘Qiskit 및 Executor 설치’ 퀵스타트 가이드의 지침을 따르십시오.
시작하기 전에
samplex이 페이지의 일부 코드 예제에서는 Samplomatic 패키지의 일부인 를 사용합니다. 따라서, 해당 코드 블록을 실행하기 전에 다음 코드 블록에 표시된 대로 Samplomatic을 설치해야 합니다. 자세한 내용은 Samplomatic 문서를 참조하십시오.
pip install samplomatic
# For visualization support, include the visualization dependencies.
# pip install samplomatic[vis]예: 매개변수화 회로
이 예제는 매개변수가 있는 회로 항목을 추가하는 방법과 samplex 항목을 추가하는 방법을 보여줍니다. 다음과 같은 단계로 구성됩니다:
- 회로 설정: 대상 회로를 생성하고 트랜스파일합니다.
- 샘플렉스 준비: 게이트와 측정값을 주석이 달린 상자로 묶고, 회로 템플릿과 샘플렉스 쌍을 생성합니다.
- 실행: 회로 항목과 샘플렉스 항목을 추가하고, 이를
QuantumProgram단일 작업으로 실행합니다.
회로 구성하기
3큐비트 GHZ 상태를 준비하고, 큐비트를 파울리-Z 축을 중심으로 회전시킨 다음, 계산 기저에서 큐비트를 측정한다.
from qiskit.circuit import Parameter, QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService, Executor
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from qiskit.transpiler import generate_preset_pass_manager
import numpy as np
from samplomatic import build
from samplomatic.transpiler import generate_boxing_pass_manager
# Generate the circuit
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.h(1)
circuit.cz(0, 1)
circuit.h(1)
circuit.h(2)
circuit.cz(1, 2)
circuit.h(2)
circuit.rz(Parameter("theta"), 0)
circuit.rz(Parameter("phi"), 1)
circuit.rz(Parameter("lam"), 2)
circuit.measure_all()백엔드를 지정하고, QPU에서 지원하는 명령어만 사용하도록 회로를 트랜스파일링합니다(이를 명령어 집합 아키텍처(ISA) 회로라고 합니다).
# Initialize the service and choose a backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# Transpile the circuit to ISA
preset_pass_manager = generate_preset_pass_manager(
backend=backend, optimization_level=3
)
isa_circuit = preset_pass_manager.run(circuit)샘플렉스 준비하기
편의 함수와 generate_boxing_pass_manager 그 트위링 매개변수를 사용하여 두 큐비트 게이트와 측정 연산을 상자로 묶고 트위링 주석을 적용합니다.
boxing_pm = generate_boxing_pass_manager(
# Add gate twirling
enable_gates=True,
# Add measurement twirling
enable_measures=True,
)
boxed_circuit = boxing_pm.run(isa_circuit)메서드를 build 사용하여 템플릿 회로와 샘플렉스를 생성합니다.
# Build the template circuit and the samplex
template_circuit, samplex = build(boxed_circuit)서킷 운동 수행하기
Executor는 객체를 실행합니다 QuantumProgram . 각각에는 QuantumProgram 여러 개의 항목이 포함될 수 있습니다. 이 예제에서는 실행할 회로 항목과 샘플렉스 항목을 추가합니다. 자세한 내용은 Executor 입력 및 출력을 참조하십시오.
첫 번째 단계는 빈 프로그램을 초기화하고, 각 항목의 모든 구성에 대해 샷을 1024 요청하는 것입니다.
# Generate a quantum program
program = QuantumProgram(shots=1024)QuantumProgram회로 항목을 에 추가하십시오. 이 회로 항목은 ISA 회로와 10세트의 매개변수 값으로 구성되어 있습니다.
# Append the circuit and the parameter values to the program
program.append_circuit_item(
isa_circuit,
circuit_arguments=np.random.rand(10, 3), # 10 sets of parameter values
)다음 인수를 사용하여 samplex 항목을 에 QuantumProgram 추가하십시오:
- 템플릿 회로와 해당
build함수에 의해 생성된 샘플렉스 - 원본 회로의 매개변수 값 10가지
- 수행할 무작위 배정 횟수
# Append the template circuit and samplex as a samplex item
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"parameter_values": np.random.rand(
10, 3
), # 10 sets of parameter values
},
shape=(2, 14, 10),
)Executor 작업 실행
# initialize an Executor with default options
executor = Executor(mode=backend)
# Submit the job
job = executor.run(program)
# Retrieve the result
result = job.result()각 작업에 대한 결과를 가져옵니다.
# Access the results of the classical register of task #0, the CircuitItem
result_0 = result[0]["meas"]
# Access the results of the classical register of task #1, the SamplexItem
result_1 = result[1]["meas"]예시: PEC 수행
이 예제는 샘플렉스(Samplex) 항목을 사용하여 오차 완화를 위한 확률적 오차 상쇄( PEC )를 수행하는 방법을 보여줍니다.
10개의 큐비트와 두 개의 서로 다른 CX 게이트 층으로 구성된 회로의 대칭 버전을 생각해 보자. 주요 업무는 다음과 같습니다:
- 회전을 곁들여 회로를 수행하세요.
- 논문 “노이즈가 있는 양자 프로세서에서 스파스 파울리-린드블라드 모델을 이용한 확률적 오차 보정(Probabilistic error cancellation with sparse Pauli-Lindblad models on noisy quantum processors) ”에 제시된 바와 같이, PEC 보정 기법을 적용하여 회로를 실행하십시오.
이 프로세스는 다음과 같은 단계로 구성됩니다:
- 설정: 대상 회로를 생성하고 각 연산 단계를 상자로 묶습니다.
- 학습: PEC를 통해 완화하고자 하는 명령어의 노이즈를 학습합니다.
- 실행: 백엔드에서 회로를 실행합니다.
- 분석: 결과를 후처리하고 분석합니다.
비교를 위해 이 미러 회로를 두 번 실행해 보겠습니다. 한 번은 파울리 회전만 적용한 경우이고, 다른 한 번은 PEC 완화 효과를 적용한 경우입니다.
이 예제의 실행 시간은 Heron r2 프로세서 기준 약 10분 정도 소요됩니다.
회로 구성하기
백엔드를 선택하고 10큐비트 회로를 준비하십시오.
from qiskit_ibm_runtime import QiskitRuntimeService, Executor
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.transpiler import generate_preset_pass_manager
from samplomatic.transpiler import generate_boxing_pass_manager
from samplomatic import build
# Initialize the service and choose a backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# Prepare a circuit
num_qubits = 10
num_layers = 10
qubits = list(range(num_qubits))
circuit = QuantumCircuit(num_qubits)
for layer_idx in range(num_layers):
circuit.rx(Parameter(f"theta_{layer_idx}"), qubits)
for i in range(num_qubits // 2):
circuit.cz(qubits[2 * i], qubits[2 * i + 1])
circuit.rx(Parameter(f"phi_{layer_idx}"), qubits)
for i in range(num_qubits // 2 - 1):
circuit.cz(qubits[2 * i] + 1, qubits[2 * i + 1] + 1)
circuit.draw("mpl", scale=0.35, fold=100)Output:
이 회로와 그 역회로를 결합하여 대칭 회로를 만듭니다.
mirror_circuit = circuit.compose(circuit.inverse())
mirror_circuit.measure_all()
mirror_circuit.draw("mpl", scale=0.35, fold=100)Output:
몇 가지 매개변수 값을 설정합니다:
import numpy as np
parameter_values = np.random.rand(mirror_circuit.num_parameters)패스 매니저를 사용하여 회로를 ISA 회로로 변환하십시오.
preset_pass_manager = generate_preset_pass_manager(
backend=backend,
optimization_level=3,
)
isa_circuit = preset_pass_manager.run(mirror_circuit)다음으로, 게이트와 측정값을 주석이 달린 상자로 묶으세요. 이 작업을 수동으로 수행하거나, 편의를 위해 Samplomatic의 함수를 generate_boxing_pass_manager 사용할 수 있습니다. 첫 번째 회로에는 회전 효과만 적용되므로 주석만 추가하면 Twirl 됩니다. 두 번째 회로는 PEC 완화 기능이 완전히 활성화된 상태에서 실행되며, 및 InjectNoise 주석이 모두 Twirl 필요합니다.
# Pass manager used to create twirled-annotated boxes.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=True,
)
mirror_circuit_twirl = boxing_pm.run(isa_circuit)
# Pass manager used to create a new boxed circuit with
# both Twirl and InjectNoise annotations.
boxing_pm = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=True,
inject_noise_targets="gates", # no measurement mitigation
inject_noise_strategy="uniform_modification",
)
mirror_circuit_pec = boxing_pm.run(isa_circuit)소리를 익히세요
InjectNoise노이즈 학습 실험 횟수를 최소화하려면, 두 번째 회로( 에 주석이 달린 상자가 있는 회로)에서 고유한 명령어를 식별하십시오. 고유성을 정의할 때, 다음 두 조건이 모두 충족될 경우 두 박스 명령어는 서로 동일합니다:
- 단일 큐비트 게이트 수준까지는 두 내용의 내용이 동일합니다.
- 그들의
Twirl주석은 동일합니다(그 외의 주석은 모두 무시됩니다).
이를 통해 세 가지 고유한 지침, 즉 홀수 및 짝수 게이트 상자와 최종 측정 상자가 도출됩니다.
from samplomatic.utils import find_unique_box_instructions
unique_box_instructions = find_unique_box_instructions(
mirror_circuit_pec.data
)
assert len(unique_box_instructions) == 3NoiseLearnerV3를 초기화하고, 옵션을 설정하여 학습 매개변수를 선택한 다음, 노이즈 학습 작업을 실행합니다.
from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3
learner = NoiseLearnerV3(backend)
learner.options.shots_per_randomization = 128
learner.options.num_randomizations = 32
learner.options.layer_pair_depths = [0, 1, 2, 4, 16, 32]
learner_job = learner.run(unique_box_instructions)
learner_job.job_id()
learner_result = learner_job.result()메서드를 result.to_dict 사용하여 samplex에서 요구하는 객체로 변환합니다 result .
noise_maps = learner_result.to_dict(
instructions=unique_box_instructions, require_refs=False
)서킷 운동 수행하기
Executor 객체를 실행합니다 QuantumProgram . 각각에는 QuantumProgram 여러 항목이 포함될 수 있으며, 이 항목들은 프로그램에 추가됩니다. 각 항목은 프로그램이 수행해야 할 작업입니다.
빈 프로그램을 초기화하고, 각 항목의 모든 구성에 대해 샷을 1000 요청합니다.
from qiskit_ibm_runtime.quantum_program import QuantumProgram
# Initialize an empty QuantumProgram
program = QuantumProgram(shots=1000)다음으로, 템플릿 회로와 samplex를 mirror_circuit_twirl 작성하여 프로그램에 추가하십시오. 또한 samplex에서 무작위 배정을 요청하십시오 900 . 즉, 샘플렉스는 여러 세트의 매개변수를 생성하며 900 , 각 세트는 QPU에서 (샷 수만큼) 실행됩니다 1000 .
이것이 이 프로그램의 첫 번째 작업입니다(결과 0).
template_twirl, samplex_twirl = build(mirror_circuit_twirl)
program.append_samplex_item(
template_twirl,
samplex=samplex_twirl,
samplex_arguments={"parameter_values": parameter_values},
shape=(900,),
)mirror_circuit_pec마찬가지로, 를 위해 구축된 템플릿 회로와 samplex를 추가하고, 개의 무작위화를 요청합니다 900 . 이것은 이 프로그램의 두 번째 과제입니다(결과 1).
template_pec, samplex_pec = build(mirror_circuit_pec)
program.append_samplex_item(
template_pec,
samplex=samplex_pec,
samplex_arguments={
"parameter_values": parameter_values,
"pauli_lindblad_maps": noise_maps,
"noise_scales": {
ref: -1.0 for ref in noise_maps
}, # Set the scales to -1 for PEC
},
shape=(900,),
)작업을 가져와 Executor 제출합니다.
from qiskit_ibm_runtime.executor import Executor
executor = Executor(backend)
executor_job = executor.run(program)
executor_job.job_id()
executor_results = executor_job.result()
executor_results
twirl_result = executor_results[0]
print(f"Twirl result keys:\n {list(twirl_result.keys())}\n")
print(f"Shape of results: {twirl_result['meas'].shape}")
pec_result = executor_results[1]
print(f"PEC result keys:\n {list(pec_result.keys())}\n")
print(f"Shape of results: {pec_result['meas'].shape}")Output:
Twirl result keys:
['meas', 'measurement_flips.meas']
Shape of results: (900, 1000, 10)
PEC result keys:
['meas', 'measurement_flips.meas', 'pauli_signs']
Shape of results: (900, 1000, 10)
결과 분석
마지막으로, 결과를 후처리하여 10개의 활성 큐비트 각각에 작용하는 단일 큐비트 파울리-Z 연산자의 기대값을 추정한다(기대값: 1.0).
# Undo measurement twirling
twirl_result_unflipped = (
twirl_result["meas"] ^ twirl_result["measurement_flips.meas"]
)
# Calculate the expectation values of single-qubit Z operators
exp_vals = 1 - 2 * twirl_result_unflipped.mean(axis=1).mean(axis=0)
for qubit, val in enumerate(exp_vals):
print(f"Qubit {qubit} -> {np.round(val, 2)}")Output:
Qubit 0 -> 0.71
Qubit 1 -> 0.72
Qubit 2 -> 0.7
Qubit 3 -> 0.68
Qubit 4 -> 0.65
Qubit 5 -> 0.64
Qubit 6 -> 0.62
Qubit 7 -> 0.66
Qubit 8 -> 0.69
Qubit 9 -> 0.75
# Undo measurement twirling
pec_result_unflipped = (
pec_result["meas"] ^ pec_result["measurement_flips.meas"]
)
# Calculate the signs for PEC mitigation
signs = np.prod((-1) ** pec_result["pauli_signs"], axis=-1)
signs = signs.reshape((signs.shape[0], 1))
# Calculate the expectation values of single-qubit Z operators as required by
# PEC mitigation
exp_vals = 1 - (2 * pec_result_unflipped.mean(axis=1) * signs).mean(axis=0)
for qubit, val in enumerate(exp_vals):
print(f"Qubit {qubit} -> {np.round(val, 2)}")Output:
Qubit 0 -> 0.98
Qubit 1 -> 1.0
Qubit 2 -> 0.99
Qubit 3 -> 0.97
Qubit 4 -> 0.97
Qubit 5 -> 0.97
Qubit 6 -> 0.96
Qubit 7 -> 0.97
Qubit 8 -> 0.97
Qubit 9 -> 0.98
다음 단계
- 방송 개요를 확인해 주세요.
- Executor 옵션 사용 방법을 알아보세요.
- 지시형 실행 모델을 이해한다.
- Samplomatic 설명서를 확인해 보세요.
- ‘음영 처리된 라이트콘을 이용한 확률적 오류 취소’ 튜토리얼에서 지향적 실행 모델을 사용할 때 다양한 오류 완화 기법을 결합하는 방법에 대해 알아보세요.