Qiskit SDK 의 기본 요소로 정확한 시뮬레이션
이 페이지의 코드는 다음 요구 사항을 사용하여 개발되었습니다. 다음 버전 이상을 사용하는 것이 좋습니다.
qiskit[all]~=2.5.2
Qiskit SDK 의 참조 프리미티브는 국소 상태 벡터 시뮬레이션을 수행합니다. 이러한 시뮬레이션은 디바이스 노이즈를 모델링하는 데는 적합하지 않지만, 보다 고급 시뮬레이션 기법( Qiskit Aer 사용 )을 탐구하거나 실제 디바이스에서 실행( IBM Quantum 기본 요소 )하기 전에 알고리즘을 신속하게 프로토타이핑하는 데 유용합니다.
추정기 프리미티브는 회로의 기대값을 계산할 수 있고, 샘플러 프리미티브는 회로의 출력 분포에서 샘플링할 수 있습니다 을 샘플링할 수 있습니다.
다음 섹션에서는 참조 프리미티브를 사용하여 워크플로를 로컬에서 실행하는 방법을 보여드립니다.
참조 추정기를 사용하십시오
로컬 상태 벡터 시뮬레이터에서 실행되는 qiskit.primitives 의 EstimatorV2 참조 구현은 시뮬레이터에서 실행되는 참조 구현은 StatevectorEstimator 클래스입니다. 회로, 관측값, 파라미터를 입력으로 받아 로컬에서 계산된 기대값을 반환할 수 있습니다.
다음 코드는 이후 예제에서 사용될 입력 데이터를 준비합니다. 관측 가능 객체의 예상 입력 유형은
입니다 qiskit.quantum_info.SparsePauliOp. 참고로
예제의 회로는 매개변수화되어 있지만, 매개변수화되지 않은 회로에서도 Estimator를 실행할 수 있습니다.
추정기로 전달되는 모든 회로에는 측정값이 포함되어서는 안 됩니다.
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
# circuit for which you want to obtain the expected value
circuit = QuantumCircuit(2)
circuit.ry(Parameter("theta"), 0)
circuit.h(0)
circuit.cx(0, 1)
circuit.draw("mpl", style="iqp")Output:
from qiskit.quantum_info import SparsePauliOp
import numpy as np
# observable(s) whose expected values you want to compute
observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1])
# value(s) for the circuit parameter(s)
parameter_values = [[0], [np.pi / 6], [np.pi / 2]]IBM Quantum 의 프리미티브 워크플로에서는 회로와 관측값을 QPU에서 지원하는 명령어만 사용하도록 변환해야 합니다(이를 ‘명령어 집합 아키텍처(ISA) 회로 및 관측값’이라고 합니다). 참조 프리미티브는 로컬 상태 벡터 시뮬레이션에 의존하기 때문에 여전히 추상 명령어를 수용하지만, 회로를 트랜스파일링하는 것이 회로 최적화 측면에서 여전히 이점이 있을 수 있다.
# Generate a pass manager without providing a backend
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)추정기 초기화
인스턴스화 qiskit.primitives.StatevectorEstimator.
from qiskit.primitives import StatevectorEstimator
estimator = StatevectorEstimator()달려서 결과를 얻어라
이 예제에서는 하나의 회로( QuantumCircuit)와 하나의 관찰 가능.
메서드를 호출하여 추정을 실행하면 StatevectorEstimator.run 메서드를 호출하여 추정을 실행합니다 PrimitiveJob 객체의 인스턴스를 반환하는 메서드를 호출하여 추정을 실행합니다. 작업에서 결과를 가져올 수 있습니다( qiskit.primitives.PrimitiveResult 객체) 메서드를 사용하여 qiskit.primitives.PrimitiveJob.result 메서드를 사용하여 작업의 결과를 가져올 수 있습니다.
job = estimator.run([(circuit, observable, parameter_values)])
result = job.result()
print(f" > Result class: {type(result)}")Output:
> Result class: <class 'qiskit.primitives.containers.primitive_result.PrimitiveResult'>
결과로부터 기대값을 얻으십시오
원시 함수 결과는 객체 PubResult 배열을 출력하며, 배열의 각 요소는 데이터에 회로-관측 가능성 조합( PUB ) 내 모든 회로-관측 가능성 조합에 대응하는 평가 결과 배열을 포함하는 객체입니다 PubResult .
첫 번째(이 경우 유일한) 회로 평가에 대한 기대값과 메타데이터를 검색하려면 평가에 액세스해야 합니다 dataPUB 에 액세스해야 합니다:
print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")Output:
> Expectation value: [4. 3.73205081 2. ]
> Metadata: {'target_precision': 0.0, 'circuit_metadata': {}}
세트 추정기 실행 옵션 설정
기본적으로 참조 추정기는 다음을 기반으로 정확한 상태 벡터 계산을 수행합니다 quantum_info.Statevector 클래스를 기반으로 정확한 상태벡터 계산을 수행합니다.
그러나 샘플링 오버헤드("샷 노이즈"라고도 함)의 효과를 도입하기 위해 이를 수정할 수 있습니다.
추정기는 원시 구현이 목표로 삼아야 하는 오차 막대를 표현하는 precision 인수를 받아들입니다 프리미티브 구현이 기대값 추정을 위해 목표로 삼아야 하는 오차 막대를 표현하는 인수를 받습니다. 이는 샘플링 오버헤드이며 .run() 메서드에만 정의되어 있습니다. 이렇게 하면 PUB 수준까지 옵션을 미세 조정할 수 있습니다.
# Estimate expectation values for two PUBs, both with 0.05 precision.
precise_job = estimator.run(
[(circuit, observable, parameter_values)], precision=0.05
)전체 예제는 ‘Estimator 예제’ 페이지를 참조하십시오.
참조 샘플러를 사용하십시오
qiskit.primitives 에서 SamplerV2 의 참조 구현은 StatevectorSampler 클래스입니다. 회로와 파라미터를 입력으로 받아 출력 확률 분포에서 샘플링한 결과를 출력 상태의 준확률 분포로 반환합니다.
다음 코드는 이후 예제에서 사용될 입력 데이터를 준비합니다. 참고로 이 예제들은 매개변수가 지정된 단일 회로를 실행하지만, 매개변수가 지정되지 않은 회로에서도 Sampler를 실행할 수 있습니다.
from qiskit import QuantumCircuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw("mpl", style="iqp")Output:
샘플러로 전달되는 모든 양자 회로에는 측정값이 포함되어야 합니다.
IBM Quantum 의 프리미티브 워크플로에서는 회로를 QPU에서 지원하는 명령어만 사용하도록 변환해야 합니다(이를 ISA 회로라고 합니다). 참조 프리미티브는 로컬 상태 벡터 시뮬레이션에 의존하기 때문에 여전히 추상 명령어를 수용하지만, 회로를 트랜스파일링하는 것이 회로 최적화 측면에서 여전히 이점이 있을 수 있다.
# Generate a pass manager without providing a backend
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(qc)초기화 SamplerV2
인스턴스화 qiskit.primitives.StatevectorSampler:
from qiskit.primitives import StatevectorSampler
sampler = StatevectorSampler()달려서 결과를 얻어라
# execute 1 circuit with Sampler
job = sampler.run([circuit])
pub_result = job.result()[0]
print(f" > Result class: {type(pub_result)}")Output:
> Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>
프리미티브는 여러 개의 PUB를 입력으로 받아들이고, 각각 PUB 자체의 결과를 가져옵니다. 따라서 다양한 매개변수/관찰 가능한 조합으로 여러 회로를 실행하고 PUB 결과를 검색할 수 있습니다:
from qiskit.transpiler import generate_preset_pass_manager
# create two circuits
circuit1 = circuit.copy()
circuit2 = circuit.copy()
# transpile circuits
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit1 = pm.run(circuit1)
isa_circuit2 = pm.run(circuit2)
# execute 2 circuits using Sampler
job = sampler.run([(isa_circuit1), (isa_circuit2)])
pub_result_1 = job.result()[0]
pub_result_2 = job.result()[1]
print(f" > Result class: {type(pub_result)}")Output:
> Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>
확률 분포 또는 측정 결과를 얻다
측정 결과 샘플은 비트 문자열 또는 카운트로 반환됩니다. 비트스트링은 측정 결과를 보여주며, 측정된 샷 순서를 유지합니다. 샘플러 결과 오브젝트는 동적 회로와의 호환성을 위해 입력 회로의 클래식 레지스터 이름을 기준으로 데이터를 구성합니다.
클래식 레지스터의 기본 이름은 "meas" 입니다. 이 이름은 나중에 측정 비트스트링에 액세스할 때 사용됩니다.
# Define quantum circuit with 2 qubits
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw()Output:
┌───┐ ░ ┌─┐
q_0: ┤ H ├──■───░─┤M├───
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├─░──╫─┤M├
└───┘ ░ ║ └╥┘
meas: 2/══════════════╩══╩═
0 1
# Transpile circuit
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(circuit)
# Run using Sampler
result = sampler.run([circuit]).result()
# Access result data for PUB 0
data_pub = result[0].data
# Access bitstring for the classical register "meas"
bitstrings = data_pub.meas.get_bitstrings()
print(f"The number of bitstrings is: {len(bitstrings)}")
# Get counts for the classical register "meas"
counts = data_pub.meas.get_counts()
print(f"The counts are: {counts}")Output:
The number of bitstrings is: 1024
The counts are: {'11': 537, '00': 487}
실행 옵션 변경
기본적으로 레퍼런스 샘플러는 정확한 상태 벡터 계산을 수행합니다 quantum_info.Statevector 클래스를 기반으로 정확한 상태벡터 계산을 수행합니다.
그러나 샘플링 오버헤드("샷 노이즈"라고도 함)의 효과를 도입하기 위해 이를 수정할 수 있습니다. 이 오버헤드를 관리하기 위해 샘플러 인터페이스는 PUB 수준에서 정의할 수 있는 shots 인수를 허용합니다.
이 예에서는 두 개의 회로를 정의했다고 가정합니다.
# Sample two circuits at 128 shots each.
sampler.run([isa_circuit1, isa_circuit2], shots=128)
# Sample two circuits at different amounts of shots. The "None"s are necessary
# as placeholders
# for the lack of parameter values in this example.
sampler.run([(isa_circuit1, None, 123), (isa_circuit2, None, 456)])Output:
<qiskit.primitives.primitive_job.PrimitiveJob at 0x7f2cb0255950>
전체 예제는 샘플러 예제 페이지를 참조하십시오.
다음 단계
- 더 큰 회로를 처리할 수 있는 고성능 시뮬레이션이나 노이즈 모델을 시뮬레이션에 통합하려면 키스킷 에어 프리미티브를 사용한 정확하고 노이즈가 많은 시뮬레이션을 참조하세요.
- 퀀텀 컴포저를 시뮬레이션에 사용하는 방법을 알아보려면 IBM 퀀텀 컴포저 가이드를 참조하세요.
- 키스킷 추정기 API 레퍼런스를 읽어보세요.
- 키스킷 샘플러 API 레퍼런스를 읽어보세요.