주 콘텐츠로 건너뛰기
이 프로젝트는 베타 단계입니다. 버그를 발견하셨나요? GitHub 이슈 만들기. 질문이나 아이디어가 있으신가요? Discussions에서 질문하기 — 피드백을 기다립니다!
이 페이지의 번역 품질은 어떻습니까?

Estimator 입력 및 출력

패키지 버전

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

qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.47.0

이 페이지에서는 IBM Quantum® 컴퓨팅 자원에서 워크로드를 실행하는 IBM Quantum Estimator 프리미티브의 입력 및 출력에 대한 개요를 소개해요. Estimator는 Primitive Unified Bloc (PUB)이라는 데이터 구조를 사용하여 벡터화된 워크로드를 효율적으로 정의할 수 있게 해요. PUB는 Estimator 프리미티브의 run() 메서드에 입력으로 전달되며, 이 메서드가 정의된 워크로드를 Job으로 실행해요. Job이 완료되면 사용한 PUB 및 프리미티브에 지정한 런타임 옵션에 따라 달라지는 형식으로 결과가 반환돼요.

입력​

각 PUB는 다음 형식을 따릅니다:

(<single circuit>, <one or more observables>, <optional one or more parameter values>, <optional precision>),

선택적 parameter values는 리스트 또는 단일 매개변수일 수 있어요. observables와 parameter values의 요소는 Primitive 입력 및 출력 주제에서 설명하는 NumPy 브로드캐스팅 규칙에 따라 결합되며, 브로드캐스트된 형태의 각 요소에 대해 하나의 기댓값 추정치가 반환돼요.

정보

입력에 측정이 포함된 경우 이는 무시됩니다.

Estimator Primitive의 경우 PUB에는 최대 네 가지 값이 포함될 수 있습니다:

  • 하나 이상의 Parameter 객체를 포함할 수 있는 단일 QuantumCircuit
  • 추정할 기댓값을 지정하는 하나 이상의 Observable 목록으로, 배열로 정렬됩니다(예: 단일 Observable은 0차원 배열, Observable 목록은 1차원 배열 등). 데이터는 Pauli, SparsePauliOp, PauliList, str과 같은 ObservablesArrayLike 형식 중 하나로 제공될 수 있습니다.
    가환 Observable
    • 동일한 PUB 내의 가환 Observable은 이 메서드를 사용하여 그룹화됩니다.
    • 다른 PUB에 있는 가환 Observable은 동일한 Circuit을 가지더라도 동일한 측정을 사용하여 추정되지 않습니다. 각 PUB는 서로 다른 측정 기저를 나타내므로 각 PUB에 대해 별도의 측정이 필요합니다.
    • 가환 Observable이 동일한 측정을 사용하여 추정되도록 하려면 동일한 PUB 내에 그룹화하세요.
  • Circuit에 바인딩할 매개변수 값의 컬렉션. 이는 마지막 인덱스가 Circuit의 Parameter 객체에 해당하는 단일 배열 형식 객체로 지정하거나, Circuit에 Parameter 객체가 없는 경우 생략(또는 동등하게 None으로 설정)할 수 있습니다.
  • (선택적) 추정할 기댓값의 목표 정밀도

다음 코드는 Estimator 프리미티브에 대한 벡터화된 입력 예제 세트를 보여주며, 이를 단일 RuntimeJobV2 객체로 IBM® 백엔드에서 실행해요.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit.circuit import (
Parameter,
QuantumCircuit,
)
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp

from qiskit_ibm_runtime import QiskitRuntimeService

# Legacy server-side primitive before qiskit-ibm-runtime 0.50.0
# from qiskit_ibm_runtime import Estimator

# Client-side primitive introduced in qiskit-ibm-runtime 0.50.0
from qiskit_ibm_runtime.executor_estimator import Estimator

import numpy as np

# Instantiate runtime service and get
# the least busy backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

# Define a circuit with two parameters.
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.ry(Parameter("a"), 0)
circuit.rz(Parameter("b"), 0)
circuit.cx(0, 1)
circuit.h(0)

# Transpile the circuit
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
transpiled_circuit = pm.run(circuit)
layout = transpiled_circuit.layout

# Now define a sweep over parameter values, the last axis of dimension 2 is
# for the two parameters "a" and "b"
params = np.vstack(
[
np.linspace(-np.pi, np.pi, 100),
np.linspace(-4 * np.pi, 4 * np.pi, 100),
]
).T

# Define three observables. The inner length-1 lists cause this array of
# observables to have shape (3, 1), rather than shape (3,) if they were
# omitted.
observables = [
[SparsePauliOp(["XX", "IY"], [0.5, 0.5])],
[SparsePauliOp("XX")],
[SparsePauliOp("IY")],
]
# Apply the same layout as the transpiled circuit.
observables = [
[observable.apply_layout(layout) for observable in observable_set]
for observable_set in observables
]

# Estimate the expectation value for all 300 combinations of observables
# and parameter values, where the pub result will have shape (3, 100).
#
# This shape is due to our array of parameter bindings having shape
# (100, 2), combined with our array of observables having shape (3, 1).
estimator_pub = (transpiled_circuit, observables, params)

# Instantiate the new Estimator object, then run the transpiled circuit
# using the set of parameters and observables.
estimator = Estimator(mode=backend)
job = estimator.run([estimator_pub])
result = job.result()

출력​

하나 이상의 PUB가 QPU로 전송되어 Job이 성공적으로 완료되면, 데이터는 RuntimeJobV2.result() 메서드를 호출하여 접근하는 PrimitiveResult 컨테이너 객체로 반환됩니다.

PrimitiveResult는 각 PUB의 실행 결과를 포함하는 PubResult 객체의 반복 가능한 목록을 포함합니다.

이 목록의 각 요소는 Primitive의 run() 메서드에 제출된 각 PUB에 해당합니다(예: 20개의 PUB와 함께 제출된 Job은 각 PUB에 해당하는 20개의 PubResult 객체 목록을 포함하는 PrimitiveResult 객체를 반환합니다).

Estimator Primitive의 각 PubResult는 최소한 기댓값 배열(PubResult.data.evs)과 관련 표준 편차(사용된 resilience_level에 따라 PubResult.data.stds 또는 PubResult.data.ensemble_standard_error)를 포함하지만, 지정된 오류 완화 옵션에 따라 더 많은 데이터를 포함할 수 있습니다.

각 PubResult 객체는 data와 metadata 속성을 모두 가집니다.

  • data 속성은 실제 측정값, 표준 편차 등을 포함하는 사용자 정의 DataBin입니다.
  • DataBin은 관련 PUB의 형태나 구조 및 Job을 제출하는 데 사용된 Primitive에서 지정한 오류 완화 옵션(예: ZNE 또는 PEC)에 따라 다양한 속성을 가집니다.
  • metadata 속성에는 사용된 런타임 및 오류 완화 옵션에 대한 정보가 포함됩니다(이 페이지의 결과 메타데이터 섹션에서 나중에 설명됩니다).

다음은 Estimator 출력에 대한 PrimitiveResult 데이터 구조의 시각적 개요입니다:

└── PrimitiveResult
├── PubResult[0]
│ ├── metadata
│ └── data ## In the form of a DataBin object
│ ├── evs
│ │ └── List of estimated expectation values in the shape
| | specified by the first pub
│ └── stds
│ └── List of calculated standard deviations in the
| same shape as above
├── PubResult[1]
| ├── metadata
| └── data ## In the form of a DataBin object
| ├── evs
| │ └── List of estimated expectation values in the shape
| | specified by the second pub
| └── stds
| └── List of calculated standard deviations in the
| same shape as above
├── ...
├── ...
└── ...

간단히 말해서, 단일 Job은 PrimitiveResult 객체를 반환하고 하나 이상의 PubResult 객체 목록을 포함합니다. 이 PubResult 객체들은 Job에 제출된 각 PUB의 측정 데이터를 저장합니다.

아래 코드 스니펫은 위에서 생성된 Job의 PrimitiveResult(및 관련 PubResult) 형식을 설명합니다.

print(
f"The result of the submitted job had {len(result)} "
f"PUBs and has a value:\n {result}\n"
)
print(
"The associated PubResult of this job has the following data bins:\n "
"{result[0].data}\n"
)
print(f"And this DataBin has attributes: {result[0].data.keys()}")
print(
"Recall that this shape is due to our array of parameter binding sets"
"having shape (100, 2), where 2 is the number of parameters in the "
"circuit, combined with our array of observables having shape (3, 1). \n"
)
with np.printoptions(threshold=200):
print(
"The expectation values measured from this PUB are: \n"
"{result[0].data.evs}\n"
)
The result of the submitted job had 1 PUBs and has a value:
PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(3, 100), dtype=float64>), stds=np.ndarray(<shape=(3, 100), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(3, 100), dtype=float64>), shape=(3, 100)), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})

The associated PubResult of this job has the following data bins:
{result[0].data}

And this DataBin has attributes: dict_keys(['evs', 'stds', 'ensemble_standard_error'])
Recall that this shape is due to our array of parameter binding setshaving shape (100, 2), where 2 is the number of parameters in the circuit, combined with our array of observables having shape (3, 1).

The expectation values measured from this PUB are:
{result[0].data.evs}

Estimator Primitive의 오류 계산 방법​

입력 PUB에서 전달된 Observable의 평균 추정치(DataBin의 evs 필드) 외에도, Estimator는 해당 기댓값과 관련된 오류 추정치도 제공하려고 시도해요. 모든 Estimator 쿼리는 각 기댓값에 대한 평균의 표준 오차와 유사한 양으로 stds 필드를 채우지만, 일부 오류 완화 옵션은 ensemble_standard_error와 같은 추가 정보를 생성해요.

단일 Observable O\mathcal{O}를 고려해 보세요. ZNE가 없는 경우, Estimator 실행의 각 샷은 기댓값 ⟨O⟩\langle \mathcal{O} \rangle의 점 추정치를 제공한다고 생각할 수 있습니다. 점별 추정치가 벡터 Os에 있는 경우, ensemble_standard_error에서 반환된 값은 다음과 같습니다(여기서 σO\sigma_{\mathcal{O}}는 기댓값의 표준 편차 추정치이고 NshotsN_{shots}는 샷 수입니다):

σONshots,\frac{ \sigma_{\mathcal{O}} }{ \sqrt{N_{shots}} },

이는 모든 샷을 단일 앙상블의 일부로 처리해요. Gate 트월링(twirling.enable_gates = True)을 요청한 경우, ⟨O⟩\langle \mathcal{O} \rangle의 점별 추정치를 공통 트월을 공유하는 집합으로 묶을 수 있어요. 이 추정치 집합을 O_twirls라고 하면, num_randomizations(트월 수)개가 있어요. 그러면 stds는 O_twirls의 평균의 표준 오차로:

σONtwirls,\frac{ \sigma_{\mathcal{O}} }{ \sqrt{N_{twirls}} },

여기서 σO\sigma_{\mathcal{O}}는 O_twirls의 표준 편차이고 NtwirlsN_{twirls}는 트월 수입니다. 트월링을 활성화하지 않으면 stds와 ensemble_standard_error는 동일합니다.

ZNE를 활성화하면 위에서 설명한 stds는 외삽기 모델에 대한 비선형 회귀에서 가중치가 됩니다. 이 경우 stds에 최종적으로 반환되는 것은 노이즈 계수 0에서 평가된 적합 모델의 불확실도입니다. 적합이 좋지 않거나 적합의 불확실도가 크면 보고된 stds가 매우 커질 수 있습니다. ZNE가 활성화된 경우 직접 외삽할 수 있도록 pub_result.data.evs_noise_factors와 pub_result.data.stds_noise_factors도 채워집니다.

결과 메타데이터​

실행 결과 외에도, PrimitiveResult와 PubResult 객체 모두 제출된 Job에 대한 메타데이터 속성을 포함합니다. 제출된 모든 PUB에 대한 정보(사용 가능한 다양한 런타임 옵션 등)를 포함하는 메타데이터는 PrimitiveResult.metatada에서 찾을 수 있으며, 각 PUB에 특정한 메타데이터는 PubResult.metadata에서 찾을 수 있습니다.

클라이언트 측 Estimator는 워크로드를 Executor 작업으로 제출합니다. 기본 Executor 결과의 메타데이터에는 실행 구간이라는 실행 타이밍 정보가 포함되어 있으며, PrimitiveResult.metadata의 "executor" 키 아래에서 확인할 수 있습니다.

참고

메타데이터 필드에서 Primitive 구현은 자신과 관련된 실행에 대한 모든 정보를 반환할 수 있으며, 기본 Primitive에 의해 보장되는 키-값 쌍은 없습니다. 따라서 반환된 메타데이터는 다른 Primitive 구현에서 다를 수 있습니다.

# Print out the results metadata
print("The metadata of the PrimitiveResult is:")
for key, val in result.metadata.items():
print(f"'{key}' : {val},")

print("\nThe metadata of the PubResult result is:")
for key, val in result[0].metadata.items():
print(f"'{key}' : {val},")
The metadata of the PrimitiveResult is:
'dynamical_decoupling' : {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'},
'twirling' : {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'},
'resilience' : {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False},
'version' : 2,

The metadata of the PubResult result is:
'shots' : 4096,
'target_precision' : 0.015625,
'circuit_metadata' : {},
'resilience' : {},
'num_randomizations' : 32,

실행 구간 보기​

클라이언트 측 Estimator는 Executor 작업으로 실행되며, 이 작업은 QPU에서 청크 단위로 작업을 실행합니다. 각 청크의 타이밍은 ChunkSpan 객체의 리스트인 result.metadata["executor"].chunk_timing에 있습니다. 각 ChunkSpan에는 start 및 stop 타임스탬프와 parts 리스트가 있으며, 각 part는 항목 인덱스(idx_item)와 해당 항목에서 이 청크에 실행된 구성의 수(size)를 나타냅니다.

idx_item은 Estimator가 사용자의 PUB로부터 만드는 Executor 프로그램에서 항목의 인덱스입니다. Estimator는 오류 완화 옵션에 따라 프로그램 항목을 추가할 수 있으므로 PUB 인덱스와 반드시 일치하지는 않습니다. 예를 들어 TREX가 활성화되면 측정 오류 캘리브레이션 Circuit을 추가합니다.

타이밍을 시각화하려면 다음 예제와 같이 리스트를 draw_chunk_timings에 전달하세요.

청크 타임스탬프의 의미, 플롯을 읽는 방법, 청크 사이에 간격이 나타날 수 있는 이유는 Executor 입력 및 출력 가이드의 실행 구간 보기를 참조하세요.

from qiskit_ibm_runtime.visualization import draw_chunk_timings

# Note the "executor" key: the timing comes from the underlying Executor job
chunk_timing = result.metadata["executor"].chunk_timing

for idx, span in enumerate(chunk_timing):
duration = (span.stop - span.start).total_seconds()
print(f"Chunk {idx}: {span.start} to {span.stop} ({duration:.3f} s)")
for part in span.parts:
print(f" Item {part.idx_item}: {part.size} configurations")

fig = draw_chunk_timings(chunk_timing, names="Estimator job")

# Uncomment the following line to display the figure
# fig.show(renderer="notebook")

# Save to a file
# fig.write_html("chunk_timings.html")
Chunk 0: 2026-11-06 01:39:01.509471+00:00 to 2026-11-06 01:39:35.171288+00:00 (33.662 s)
Item 0: 800 configurations
Item 1: 4 configurations
Chunk 1: 2026-11-06 01:39:48.299074+00:00 to 2026-11-06 01:40:21.826190+00:00 (33.527 s)
Item 0: 800 configurations
Item 1: 4 configurations
Chunk 2: 2026-11-06 01:40:22.855454+00:00 to 2026-11-06 01:40:53.781896+00:00 (30.926 s)
Item 0: 800 configurations
Item 1: 4 configurations
Chunk 3: 2026-11-06 01:40:54.993867+00:00 to 2026-11-06 01:41:26.068319+00:00 (31.074 s)
Item 0: 800 configurations
Item 1: 4 configurations
Chunk 4: 2026-11-06 01:41:41.019968+00:00 to 2026-11-06 01:42:15.956573+00:00 (34.937 s)
Item 0: 800 configurations
Item 1: 4 configurations
Chunk 5: 2026-11-06 01:42:47.834717+00:00 to 2026-11-06 01:43:21.436255+00:00 (33.602 s)
Item 0: 800 configurations
Item 1: 4 configurations
Chunk 6: 2026-11-06 01:43:22.698235+00:00 to 2026-11-06 01:43:53.647547+00:00 (30.949 s)
Item 0: 800 configurations
Item 1: 4 configurations
Chunk 7: 2026-11-06 01:43:54.710995+00:00 to 2026-11-06 01:44:25.762574+00:00 (31.052 s)
Item 0: 800 configurations
Item 1: 4 configurations