Skip to main content
IBM Quantum Platform

실행자 브로드캐스팅

Executor 프라이머리비트에 제공된 데이터는 브로드캐스팅을 통해 다양한 형태로 배열될 수 있어 워크로드에 유연성을 제공합니다. 이 가이드에서는 Executor가 브로드캐스팅 세미언틱스를 사용하여 배열 입출력을 처리하는 방법을 설명합니다. 이러한 개념을 이해하면 매개변수 값을 효율적으로 훑어보고, 여러 구성을 결합하며, 반환된 데이터의 형태를 해석하는 데 도움이 될 것입니다.

Note

이 주제의 예제는 단독으로 실행할 수 없습니다. 이 문서에서는 사용자가 적절한 회로도를 정의하고, Samplomatic 패스 매니저를 사용하여 박스와 주석을 추가했으며, 필요에 따라 Samplomatic build 방식을 사용하여 각 코드 블록에 대한 템플릿 회로도와 샘플렉스를 확보했다고 가정합니다.


빠른 시작 예제

이 예시는 핵심 개념을 보여줍니다. 이 기능은 파라메트릭 회로와 다섯 가지 서로 다른 파라미터 구성을 생성합니다. 집행자는 다섯 가지 구성을 모두 실행하고, 각 양자 프로그램 항목의 고전적 레지스터마다 하나의 결과를 포함하도록 구성별로 정리된 데이터를 반환합니다.

이 가이드의 나머지 부분에서는 이 예시를 바탕으로 해당 기능이 어떻게 작동하는지, 그리고 Samplomatic 기반의 무작위화 및 입력 기능을 포함한 더 복잡한 스윕을 만드는 방법을 설명합니다.

import numpy as np
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

# A circuit with 2 parameters
# This circuit is used throughout the rest of this guide.
circuit = QuantumCircuit(4)
circuit.rx(Parameter("a"), 0)
circuit.rx(Parameter("b"), 1)
circuit.h(2)
circuit.cx(2, 3)
circuit.measure_all()

# 5 different parameter configurations (shape: 5 configurations × 2 parameters)
parameter_values = np.linspace(0, np.pi, 10).reshape(5, 2)

# Initialize the service and choose a backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

# Transpile to ISA circuit
preset_pass_manager = generate_preset_pass_manager(
    backend=backend,
    optimization_level=3,
)
isa_circuit = preset_pass_manager.run(circuit)

# This program is used throughout the rest of this guide.
program = QuantumProgram(shots=1024)
program.append_circuit_item(isa_circuit, circuit_arguments=parameter_values)

# initialize an Executor with default options
executor = Executor(mode=backend)

# Run and get results
result = executor.run(program).result()

# result is a list with one entry per program item
# result[0] is a dict mapping classical register names to data arrays
# Output bool arrays have shape (5, 1024, 4)
#   5 = number of parameter configurations
#   1024 = number of shots
#   4 = bits in the classical register
result[0]["meas"]

내재적 축과 외재적 축

방송 기능은 외적 축에만 적용됩니다. 내재적 축은 명시된 대로 항상 보존됩니다.

  • 내재 축 (가장 오른쪽): 데이터 유형에 따라 결정됩니다. (3,)예를 들어, 회로에 세 개의 매개변수가 있다면, 매개변수 값으로 세 개의 숫자가 필요하며, 이로 인해 의 본래 형태가 결정됩니다.

  • 외부 축 (가장 왼쪽): 스윕 치수. 이 설정은 실행할 구성의 수를 지정합니다.

입력 유형
본질적인 형태
전체 모양 예시
매개변수 값 (n개 매개변수)(명사)(5, 3) : 5가지 구성과 3가지 매개변수
스칼라 입력(예: 노이즈 스케일)()(4,) 네 가지 구성에 대하여
관측 가능 객체 (해당되는 경우)다양함관측 가능한 유형에 따라 다릅니다

두 개의 매개변수를 가진 회로를 가정하고, 이 매개변수 값과 잡음 배율을 변화시키며 4x3 에 제시된 구성 격자 전체를 훑어보고자 한다고 가정해 봅시다:

import numpy as np

# Parameter values: 4 configurations along axis 0, intrinsic shape (2,)
# Full shape: (4, 1, 2) - the "1" allows broadcasting with noise_scale
parameter_values = np.array([
    [[0.1, 0.2]],
    [[0.3, 0.4]],
    [[0.5, 0.6]],
    [[0.7, 0.8]],
])  # shape (4, 1, 2)

# Noise scale: 3 configurations, intrinsic shape () (scalar)
# Full shape: (3,)
noise_scale = np.array([0.8, 1.0, 1.2])  # shape (3,)

# Extrinsic shapes: (4, 1) and (3,) → broadcast to (4, 3)
# Result: 12 total configurations in a 4×3 grid
program.append_samplex_item(
    template_circuit,
    samplex=samplex,
    samplex_arguments={
        "parameter_values": parameter_values,
        "noise_scales.mod_ref1": noise_scale,
    },
)

모양은 다음과 같습니다:

입력
전체 모양
외형
본질적인 형태
parameter_values(4, 1, 2)(4, 1)(2,)
noise_scale(3,)(3,)()
브로드캐스트없음(4, 3)없음

출력 배열의 형상

출력 배열도 동일한 외재적/내재적 패턴을 따릅니다:

  • 외부 형상: 모든 입력의 브로드캐스트 형상과 일치함
  • 내재적 형태: 출력 유형에 따라 결정됨

가장 일반적인 출력 형식은 측정값에서 얻은 비트열 데이터로, 이는 부울 값의 배열 형태로 구성됩니다:

출력 유형
본질적인 형태
설명
고전적 등록 데이터(발사 횟수, 크레그 크기)측정 결과의 비트스트링 데이터

(4, 3)``(3,)외부 형상이 (4, 1) 와 인 입력을 제공하면, 브로드캐스트된 외부 형상은 입니다. 다음 코드는 1024개의 샷과 4비트 클래식 레지스터( Quickstart 예제에서 정의된 대로)를 사용하는 회로를 활용합니다:

# Input extrinsic shapes: (4, 1) and (3,) → (4, 3)
# Output for classical register "meas":
#   extrinsic: (4, 3)
#   intrinsic: (1024, 4)  - shots × bits
#   full shape: (4, 3, 1024, 4)

result = executor.run(program).result()
meas_data = result[0]["meas"]  # result[0] for first program item
print(meas_data.shape)  # (4, 3, 1024, 4)

# Access a specific configuration
config_2_1 = meas_data[2, 1, :, :]  # shape (1024, 4)
Note

각 구성은 양자 프로그램에 지정된 전체 샷 수만큼 실행됩니다. 샷은 구성별로 구분되지 않습니다. 예를 들어, 1024회의 테스트를 요청하고 10개의 구성이 있는 경우, 각 구성마다 1024회의 테스트가 실행됩니다(총 10,240회의 테스트가 실행됨).


무작위 배정 및 매개변수 shape

샘플렉스를 사용할 때, 외형(extrinsic shape)의 각 요소는 독립적인 회로 실행에 해당합니다. 일반적으로 샘플렉스는 각 실행에 무작위성(예: 게이트 트위링)을 도입하므로, 명시적으로 다중 무작위화를 요청하지 않더라도 각 요소는 무작위적인 구현을 받게 됩니다.

shape 매개변수를 사용하면 항목의 외형적 형태를 확장할 수 있으며, 이는 동일한 구성을 여러 번 무작위화하는 데 특화된 축을 효과적으로 추가하는 것과 같습니다. samplex_arguments. 파일에 내포된 형식으로 방송 가능해야 합니다. 가 를 초과하는 축에서는 shape 암시적 형상에 따라 추가적인 독립적 무작위화가 열거됩니다.

명시적인 무작위화 축 없음

(를 생략하거나 shape 입력 도형에 맞게 설정하면) 입력 구성마다 한 번씩 실행됩니다. 각 실행은 여전히 샘플렉스에 의해 무작위화되지만, 단 하나의 무작위 실현만으로는 여러 번의 무작위화를 평균화함으로써 얻는 이점을 누릴 수 없습니다.

Note

twirling=True만약 와 같은 간단한 플래그로 트와일링을 활성화하는 데 익숙하다면, Executor에서는 후처리 루틴이 여러 번의 무작위화 결과를 평균화하여 그 이점을 얻을 수 있도록 하기 위해 인수를shape 사용하여 여러 번의 무작위화를 명시적으로 요청해야 한다는 점에 유의하십시오. 단일 무작위화(를 생략했을 때의 shape 기본값)는 무작위 게이트를 적용하지만, 일반적으로 무작위화 없이 기본 회로를 실행하는 것보다 더 나은 이점을 제공하지 않습니다.

다음 예제는 기본 동작을 보여줍니다:

program.append_samplex_item(
    template_circuit,
    samplex=samplex,
    samplex_arguments={
        "parameter_values": np.random.rand(10, 2),  # extrinsic (10,)
    },
    # shape defaults to (10,) - one randomized execution per config
)
# Output shape for "meas": (10, num_shots, creg_size)

단일 무작위 배정 축

구성당 여러 번의 무작위 배정을 실행하려면 축을 추가하여 도형을 확장하십시오. 예를 들어, 다음 코드는 10가지 매개변수 구성 각각에 대해 20회의 무작위 시뮬레이션을 실행합니다:

program.append_samplex_item(
    template_circuit,
    samplex=samplex,
    samplex_arguments={
        "parameter_values": np.random.rand(10, 2),  # extrinsic (10,)
    },
    shape=(20, 10),  # 20 randomizations × 10 configurations
)
# Output shape for "meas": (20, 10, num_shots, creg_size)

여러 무작위 배정 축

무작위 배정을 다차원 격자 형태로 구성할 수 있습니다. 이는 구조화된 분석에 유용하며, 예를 들어 무작위 배정을 유형별로 분류하거나 통계 처리를 위해 그룹화하는 데 활용할 수 있습니다.

(2, 14, 10)여기서 입력의 외재적 형상은 (10,) 요청된 형상으로 브로드캐스팅되며, 0축과 1축은 독립적인 무작위 변수로 채워집니다.

program.append_samplex_item(
    template_circuit,
    samplex=samplex,
    samplex_arguments={
        "parameter_values": np.random.rand(10, 2),  # extrinsic (10,)
    },
    # 2×14=28 randomizations per configuration, 10 configurations
    # Or you could set shape=(28, 10) for the same effect
    shape=(2, 14, 10),  
)
# Output shape for "meas": (2, 14, 10, num_shots, creg_size)

입력 형상과 상호작용하는 방식 shape

shape 매개변수는 입력 외재적 형상에서 브로드캐스팅이 가능해야 합니다. 이는 다음을 의미합니다.

  • shapesize-1 치수를 가진 도형은 해당 치수에 맞춰 확장될 수 있습니다.
  • shape입력 형식은.을 기준으로 오른쪽에서 정렬되어야 합니다.
  • 입력 치수를 초과하는 축들은 shape 무작위 배열을 나열합니다.

다음 표의 마지막 행에서 볼 수 있듯이, size-1 차원을 포함할 수 있으며 shape , 이 차원들은 입력 차원에 맞춰 확장됩니다.

예:

외부 입력
형태
결과
(10,)(10,)10가지 구성, 각 구성당 1회 무작위 배정
(10,)(5, 10)10가지 구성, 각 구성당 5가지 무작위 배정
(10,)(2, 3, 10)10가지 구성, 각 구성당 2×3=6가지 무작위 배정
(4, 1)(4, 5)4가지 구성, 각 구성당 5회 무작위 배정
(4, 3)(2, 4, 3)4×3=12가지 조합, 각 조합당 2가지 무작위 배정
(4, 3)(2, 1, 3)4×3=12가지 조합, 각 조합당 2가지 무작위 배정 (1은 4로 확장됨)

결과로 이동

무작위화 축을 사용하면 특정 무작위화/매개변수 조합을 지정할 수 있습니다:

# Using shape=(2, 14, 10) with input extrinsic shape (10,), and 
# 1024 shots and 4 classical registers.
result = executor.run(program).result()
meas_data = result[0]["meas"]  # shape (2, 14, 10, 1024, 4)

# Get all shots for randomization (0, 7) and parameter config 3
specific = meas_data[0, 7, 3, :, :]  # shape (1024, 4)

# Average over all randomizations for parameter config 5 on bit 2
averaged = meas_data[:, :, 5, :, 2].mean(axis=(0, 1))

흔히 나타나는 패턴

단일 매개변수 스윕

다른 매개변수는 고정된 상태로 유지하면서 특정 매개변수를 훑어보려면 다음과 같은 코드를 사용하세요:

# Circuit has 2 parameters, sweep first one over 20 values
sweep_values = np.linspace(0, 2*np.pi, 20)

parameter_values = np.column_stack([
    sweep_values,
    np.full(20, 0.5),
])  # shape (20, 2)

2D 그리드 스윕 생성

세 가지 매개변수를 기반으로 그리드를 생성하려면:

# Sweep param 0 over 10 values, param 1 over 8 values, param 2 fixed
p0 = np.linspace(0, np.pi, 10)[:, np.newaxis, np.newaxis]  # (10, 1, 1)
p1 = np.linspace(0, np.pi, 8)[np.newaxis, :, np.newaxis]   # (1, 8, 1)
p2 = np.array([[[0.5]]])                                   # (1, 1, 1)

parameter_values = np.broadcast_arrays(p0, p1, p2)
parameter_values = np.stack(parameter_values, axis=-1).squeeze()  # (10, 8, 3)

# Extrinsic shape: (10, 8), intrinsic shape: (3,)

여러 입력 결합하기

내재적 형상이 서로 다른 입력들을 결합할 때는, 외재적 치수를 size-1 축을 사용하여 정렬하십시오:

# 4 parameter configurations, 3 noise scales → 4×3 = 12 total configurations
parameter_values = np.random.rand(4, 1, 2)  # extrinsic (4, 1), intrinsic (2,)
noise_scale = np.array([0.8, 1.0, 1.2])     # extrinsic (3,), intrinsic ()

# Broadcasted extrinsic shape: (4, 3)

다음 단계

권장사항
이 페이지가 도움이 되었습니까?
GitHub에서 버그, 오타를 보고하거나 컨텐츠를 요청하십시오.