주 콘텐츠로 건너뛰기

IBM Circuit 함수를 이용한 오류 완화

참고

Qiskit Functions는 IBM Quantum® Premium Plan, Flex Plan, On-Prem (IBM Quantum Platform API 경유) Plan 사용자에게만 제공되는 실험적 기능입니다. 현재 미리 보기 릴리스 상태이며 변경될 수 있습니다.

사용 시간 예상: Eagle 프로세서 기준 약 26분 (참고: 이 값은 예상치이며, 실제 실행 시간은 다를 수 있습니다.)

이 튜토리얼에서는 IBM Circuit 함수를 사용하여 워크플로를 구성하고 실행하는 예제를 단계별로 살펴봅니다. 이 함수는 Primitive Unified Blocs (PUB)를 입력으로 받아 오류가 완화된 기댓값을 출력으로 반환합니다. 또한 자동화되고 맞춤화된 파이프라인을 제공하여 Circuit을 최적화하고 양자 하드웨어에서 실행할 수 있도록 하며, 연구자들이 알고리즘 및 응용 분야 탐색에 집중할 수 있게 합니다.

Qiskit Functions 소개 문서를 방문하여 개요를 확인하고, IBM Circuit 함수 시작 방법을 알아보세요.

배경

이 튜토리얼에서는 2D 횡자기장 이징 모델(transverse-field Ising model)에 대한 하드웨어 효율적인 Trotterized 시간 진화 Circuit을 구성하고 전체 자화(global magnetization)를 계산합니다. 이러한 Circuit은 응집 물질 물리학, 화학, 머신러닝 등 다양한 응용 분야에서 유용하게 활용됩니다. 이 모델의 구조에 대한 자세한 내용은 Nature 618, 500–505 (2023)을 참조하세요.

IBM Circuit 함수는 Qiskit Transpiler 서비스와 Qiskit Runtime Estimator의 기능을 결합하여 Circuit 실행을 위한 간소화된 인터페이스를 제공합니다. 이 함수는 단일 관리형 서비스 내에서 트랜스파일, 오류 억제, 오류 완화, Circuit 실행을 수행하므로, 패턴의 각 단계를 직접 구성하는 대신 문제를 Circuit에 매핑하는 데 집중할 수 있습니다.

요구 사항

이 튜토리얼을 시작하기 전에 다음 패키지가 설치되어 있는지 확인하세요:

  • Qiskit SDK v1.2 이상 (pip install qiskit)
  • Qiskit Runtime v0.28 이상 (pip install qiskit-ibm-runtime)
  • IBM Qiskit Functions Catalog 클라이언트 v0.0.0 이상 (pip install qiskit-ibm-catalog)
  • Qiskit Aer v0.15.0 이상 (pip install qiskit-aer)

설정

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-catalog qiskit-ibm-runtime rustworkx
import rustworkx
from collections import defaultdict
from numpy import pi, mean

from qiskit_ibm_runtime import QiskitRuntimeService

from qiskit_ibm_catalog import QiskitFunctionsCatalog

from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.quantum_info import SparsePauliOp

1단계: 고전적 입력을 양자 문제로 변환

  • 입력: 양자 Circuit을 생성하기 위한 매개변수
  • 출력: 추상 Circuit 및 관측량

Circuit 구성

구성할 Circuit은 2D 횡자기장 이징 모델에 대한 하드웨어 효율적인 Trotterized 시간 진화 Circuit입니다. 먼저 Backend를 선택합니다. 이 Backend의 속성(즉, 연결 맵)을 사용하여 양자 문제를 정의하고 하드웨어 효율성을 보장합니다.

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)

다음으로, Backend에서 연결 맵을 가져옵니다.

coupling_graph = backend.coupling_map.graph.to_undirected(multigraph=False)
layer_couplings = defaultdict(list)

Circuit의 레이어를 설계할 때 주의가 필요합니다. 연결 맵의 에지에 색상을 지정(즉, 분리된 에지를 그룹화)하고 그 색상을 활용하여 Circuit에 게이트를 더 효율적으로 배치합니다. 이를 통해 하드웨어에서 동시에 실행 가능한 게이트 레이어로 구성된 더 얕은 Circuit을 만들 수 있습니다.

edge_coloring = rustworkx.graph_bipartite_edge_color(coupling_graph)

for edge_idx, color in edge_coloring.items():
layer_couplings[color].append(
coupling_graph.get_edge_endpoints_by_index(edge_idx)
)
layer_couplings = [
sorted(layer_couplings[i]) for i in sorted(layer_couplings.keys())
]

다음으로, 위에서 구한 에지 색상을 사용하여 2D 횡자기장 이징 모델에 대한 하드웨어 효율적인 Trotterized 시간 진화 Circuit을 구현하는 간단한 헬퍼 함수를 작성합니다.

def construct_trotter_circuit(
num_qubits: int,
num_trotter_steps: int,
layer_couplings: list,
barrier: bool = True,
) -> QuantumCircuit:
theta, phi = Parameter("theta"), Parameter("phi")
circuit = QuantumCircuit(num_qubits)

for _ in range(num_trotter_steps):
circuit.rx(theta, range(num_qubits))
for layer in layer_couplings:
for edge in layer:
if edge[0] < num_qubits and edge[1] < num_qubits:
circuit.rzz(phi, edge[0], edge[1])
if barrier:
circuit.barrier()

return circuit

Qubit 수와 Trotter 단계 수를 선택한 후 Circuit을 구성합니다.

num_qubits = 100
num_trotter_steps = 2

circuit = construct_trotter_circuit(
num_qubits, num_trotter_steps, layer_couplings
)
circuit.draw("mpl", fold=-1)

이전 코드 셀의 출력

실행 품질을 벤치마킹하려면 이상적인 결과와 비교해야 합니다. 선택한 Circuit은 고전적인 브루트 포스 시뮬레이션으로는 계산할 수 없는 규모입니다. 따라서 Circuit의 모든 Rx 게이트 매개변수를 00으로, 모든 Rzz 게이트 매개변수를 π\pi로 고정합니다. 이렇게 하면 Circuit이 Clifford 형태가 되어 이상적인 시뮬레이션이 가능해지고, 비교를 위한 이상적인 결과를 얻을 수 있습니다. 이 경우 결과값은 1.0임을 알 수 있습니다.

parameters = [0, pi]

관측량 구성

먼저, NN-Qubit 문제에서 z^\hat{z} 방향의 전체 자화를 계산합니다: Mz=i=1NZi/NM_z = \sum_{i=1}^N \langle Z_i \rangle / N. 이를 위해 먼저 각 Qubit ii에 대한 단일 지점 자화 Zi\langle Z_i \rangle를 계산해야 하며, 이는 아래 코드에서 정의됩니다.

observables = []
for i in range(num_qubits):
obs = "I" * (i) + "Z" + "I" * (num_qubits - i - 1)
observables.append(SparsePauliOp(obs))

print(observables[0])
SparsePauliOp(['ZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j])

2단계 및 3단계: 양자 하드웨어 실행을 위한 문제 최적화 및 IBM Circuit 함수로 실행

  • 입력: 추상 Circuit 및 관측량
  • 출력: 완화된 기댓값

이제 추상 Circuit과 관측량을 IBM Circuit 함수에 전달할 수 있습니다. IBM Circuit 함수는 트랜스파일과 양자 하드웨어 실행을 처리하고 완화된 기댓값을 반환합니다. 먼저 IBM Qiskit Functions Catalog에서 함수를 불러옵니다.

catalog = QiskitFunctionsCatalog(
token="<YOUR_API_KEY>"
) # Use the 44-character API_KEY you created and saved from the IBM Quantum Platform Home dashboard
function = catalog.load("ibm/circuit-function")

IBM Circuit 함수는 pubs, backend_name 및 트랜스파일, 오류 완화 등을 구성하기 위한 선택적 입력을 받습니다. 추상 Circuit, 관측량, Circuit 매개변수로부터 pub을 생성합니다. Backend 이름은 문자열로 지정해야 합니다.

pubs = [(circuit, observables, parameters)]
backend_name = backend.name

트랜스파일, 오류 억제, 오류 완화를 위한 options도 구성할 수 있습니다. 지정하지 않으면 기본 설정이 사용됩니다. IBM Circuit 함수에는 Circuit 최적화 수준을 제어하는 optimization_level과 오류 억제 및 완화 수준을 지정하는 mitigation_level이라는 자주 사용되는 옵션이 제공됩니다. IBM Circuit 함수의 mitigation_levelQiskit Runtime Estimator에서 사용하는 resilience_level과는 다릅니다. 자주 사용되는 옵션 및 기타 고급 옵션에 대한 자세한 설명은 IBM Circuit 함수 문서를 방문하세요.

이 튜토리얼에서는 default_precision, optimization_level: 3, mitigation_level: 3을 설정합니다. 이렇게 하면 기본 레벨 1 설정에 더해 게이트 트월링과 확률적 오류 증폭(PEA)을 통한 제로 노이즈 외삽(ZNE)이 활성화됩니다.

options = {
"default_precision": 0.011,
"optimization_level": 3,
"mitigation_level": 3,
}

입력이 지정되면, 최적화 및 실행을 위해 IBM Circuit 함수에 작업을 제출합니다.

job = function.run(backend_name=backend_name, pubs=pubs, options=options)

4단계: 결과 후처리 및 원하는 고전적 형식으로 반환

  • 입력: IBM Circuit 함수의 실행 결과
  • 출력: 전체 자화

전체 자화 계산

함수 실행 결과는 Estimator와 동일한 형식을 갖습니다.

result = job.result()[0]

이 결과에서 완화된 기댓값과 완화되지 않은 기댓값을 가져옵니다. 이 기댓값들은 z^\hat{z} 방향의 단일 지점 자화를 나타냅니다. 이를 평균 내어 전체 자화를 구하고, 이 문제 인스턴스의 이상적인 값인 1.0과 비교합니다.

mitigated_expvals = result.data.evs
magnetization_mitigated = mean(mitigated_expvals)

print("mitigated:", magnetization_mitigated)

unmitigated_expvals = [
result.data.evs_extrapolated[i][0][1] for i in range(num_qubits)
]
magnetization_unmitigated = mean(unmitigated_expvals)

print("unmitigated:", magnetization_unmitigated)
mitigated: 0.9749883476088692
unmitigated: 0.7832977198447583

튜토리얼 설문조사

이 짧은 설문조사에 참여하여 튜토리얼에 대한 피드백을 남겨 주세요. 여러분의 의견은 콘텐츠 품질과 사용자 경험 개선에 도움이 됩니다.

설문조사 링크

Note: This survey is provided by IBM Quantum and relates to the original English content. To give feedback on doQumentation's website, translations, or code execution, please open a GitHub issue.