주 콘텐츠로 건너뛰기

Qiskit Aer 프리미티브를 사용한 정확한 시뮬레이션 및 노이즈 시뮬레이션

패키지 버전

이 페이지의 코드는 다음 요구 사항을 사용하여 개발되었습니다. 이 버전 이상을 사용하길 권장합니다.

qiskit[all]~=2.5.2
qiskit-aer~=0.17

Exact simulation with Qiskit SDK primitives demonstrates how to use the reference primitives included with Qiskit to perform exact simulation of quantum circuits. Currently existing quantum processors suffer from errors, or noise, so the results of an exact simulation do not necessarily reflect the results you would expect when running circuits on real hardware. While the reference primitives in Qiskit do not support modeling noise, Qiskit Aer includes implementations of the primitives that do support modeling noise. Qiskit Aer is a high-performance quantum circuit simulator that you can use in place of the reference primitives for better performance and more features. It is part of the Qiskit Ecosystem. In this article, we demonstrate the use of Qiskit Aer primitives for exact and noisy simulation.

참고 사항
  • qiskit-aer v0.14 이상이 필요합니다.
  • Qiskit Aer 프리미티브는 프리미티브 인터페이스를 구현하지만, IBM Quantum 프리미티브와 동일한 옵션을 제공하지는 않습니다. 예를 들어, 복원력 수준(Resilience level)은 Qiskit Aer 프리미티브에서 사용할 수 없습니다.
  • Aer가 지원하는 시뮬레이션 방법 옵션에 대한 자세한 내용은 AerSimulator 문서를 참조하세요.

정확한 시뮬레이션과 노이즈 시뮬레이션을 탐색하기 위해 8개의 Qubit으로 예제 Circuit을 생성합니다.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit.circuit.library import efficient_su2

n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")

이전 코드 셀의 출력

이 Circuit에는 RyR_y 및 RzR_z Gate의 회전 각도를 나타내는 매개변수가 포함되어 있습니다. 이 Circuit을 시뮬레이션할 때는 이러한 매개변수에 대한 명시적인 값을 지정해야 합니다. 다음 셀에서는 이러한 매개변수에 대한 일부 값을 지정하고, Qiskit Aer의 Estimator 프리미티브를 사용하여 관측가능량(옵저버블) ZZ⋯ZZZ \cdots Z의 정확한 기댓값을 계산합니다.

from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import EstimatorV2 as Estimator

observable = SparsePauliOp("Z" * n_qubits)
params = [0.1] * circuit.num_parameters

exact_estimator = Estimator()
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value
0.8870140234256602

이제 모든 CX Gate에 2%의 탈분극 오류(depolarizing error)를 포함하는 노이즈 모델을 초기화해 보겠습니다. 실제로는 여기서 CX Gate인 2-Qubit Gate에서 발생하는 오류가 Circuit을 실행할 때 오류의 주요 원인입니다. Qiskit Aer에서 노이즈 모델 구성에 대한 개요는 노이즈 모델 구축을 참조하세요.

다음 셀에서는 이 노이즈 모델을 포함하는 Estimator를 구성하고 이를 사용하여 관측량의 기댓값을 계산합니다.

from qiskit_aer.noise import NoiseModel, depolarizing_error

noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)

noisy_estimator = Estimator(
options=dict(backend_options=dict(noise_model=noise_model))
)
job = noisy_estimator.run([pub])
result = job.result()
pub_result = result[0]
noisy_value = float(pub_result.data.evs)
noisy_value
0.7247404214143528

보면 알 수 있듯이, 노이즈가 있을 때의 기댓값은 올바른 값과 상당히 차이가 납니다. 실제로는 노이즈의 영향을 상쇄하기 위해 다양한 오류 완화 기술을 사용할 수 있지만, 이러한 기술에 대한 논의는 이 문서의 범위를 벗어납니다.

노이즈가 최종 결과에 어떻게 영향을 미치는지 대략적으로 이해하기 위해, 각 CX Gate에 2%의 탈분극 오류를 추가하는 노이즈 모델을 고려해 보겠습니다. 확률 pp의 탈분극 오류는 밀도 행렬 ρ\rho에 대해 다음과 같은 작용을 하는 양자 채널 EE로 정의됩니다.

E(ρ)=(1−p)ρ+pI2nE(\rho) = (1 - p) \rho + p\frac{I}{2^n}

여기서 nn은 Qubit의 수로, 이 경우 2입니다. 즉, 확률 pp로 상태가 완전히 혼합된 상태로 대체되고, 확률 1−p1 - p로 상태가 보존됩니다. 탈분극 채널의 mm번 적용 후 상태가 보존될 확률은 (1−p)m(1 - p)^m이 됩니다. 따라서 우리 Circuit의 CX Gate 수에 따라 시뮬레이션 끝에 올바른 상태를 유지할 확률이 기하급수적으로 감소할 것으로 예상됩니다.

Circuit에서 CX Gate의 수를 세고 (1−p)m(1 - p)^m을 계산해 보겠습니다. count_ops를 호출하여 Gate 이름을 횟수에 매핑하는 딕셔너리를 얻고 CX Gate에 대한 항목을 검색합니다.

cx_count = circuit.count_ops()["cx"]
(1 - cx_depolarizing_prob) ** cx_count
0.6542558123199923

이 값인 65%는 최종 상태가 올바를 확률에 대한 대략적인 추정값입니다. 시뮬레이션의 초기 상태를 고려하지 않기 때문에 보수적인 추정값입니다.

다음 코드 셀은 Qiskit Aer의 Sampler 프리미티브를 사용하여 노이즈가 있는 Circuit에서 샘플링하는 방법을 보여줍니다. Sampler 프리미티브로 실행하기 전에 Circuit에 측정을 추가해야 합니다.

from qiskit_aer.primitives import SamplerV2 as Sampler

measured_circuit = circuit.copy()
measured_circuit.measure_all()

noisy_sampler = Sampler(
options=dict(backend_options=dict(noise_model=noise_model))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params, 100)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
pub_result.data.meas.get_counts()
{'00000110': 1,
'11100000': 1,
'00000000': 59,
'11000000': 3,
'11110000': 1,
'00010100': 1,
'00100000': 2,
'00000011': 3,
'00110010': 1,
'00110101': 1,
'00000101': 1,
'11000010': 1,
'10000000': 4,
'00110000': 1,
'01000000': 2,
'00010000': 2,
'00000100': 2,
'01010000': 1,
'00001000': 2,
'00011110': 1,
'00001010': 1,
'01111000': 1,
'10100000': 1,
'01100000': 1,
'00001100': 2,
'00010110': 1,
'01001000': 1,
'00101000': 1,
'00000010': 1}

다음 단계​

권장 사항