주 콘텐츠로 건너뛰기

Qiskit AI 기반 트랜스파일러 서비스 소개

예상 QPU 사용량: 없음 (참고: 이 튜토리얼은 트랜스파일에 초점을 맞추므로 작업을 실행하지 않습니다)

배경

**Qiskit AI 기반 트랜스파일러 서비스(QTS)**는 라우팅 및 합성 패스 모두에 머신 러닝 기반 최적화를 도입합니다. 이 AI 모드는 특히 대규모 Circuit과 복잡한 하드웨어 토폴로지에서 기존 트랜스파일의 한계를 극복하도록 설계되었습니다.

2025년 7월 기준으로, 트랜스파일러 서비스는 새로운 IBM Quantum® 플랫폼으로 마이그레이션되었으며 더 이상 이전 방식으로 사용할 수 없습니다. 트랜스파일러 서비스 상태에 관한 최신 업데이트는 트랜스파일러 서비스 문서를 참고하세요. AI 트랜스파일러는 표준 Qiskit 트랜스파일과 유사하게 로컬에서 계속 사용할 수 있습니다. generate_preset_pass_manager()generate_ai_pass_manager()로 교체하기만 하면 됩니다. 이 함수는 AI 기반 라우팅 및 합성 패스를 로컬 트랜스파일 워크플로우에 직접 통합하는 패스 매니저를 구성합니다.

AI 패스의 주요 기능

  • 라우팅 패스: AI 기반 라우팅은 특정 Circuit과 Backend에 따라 Qubit 경로를 동적으로 조정하여 과도한 SWAP Gate의 필요성을 줄입니다.

    • AIRouting: 레이아웃 선택 및 Circuit 라우팅
  • 합성 패스: AI 기술은 다중 Qubit Gate의 분해를 최적화하여 오류가 발생하기 쉬운 두 Qubit Gate의 수를 최소화합니다.

    • AICliffordSynthesis: Clifford Gate 합성
    • AILinearFunctionSynthesis: 선형 함수 Circuit 합성
    • AIPermutationSynthesis: 순열 Circuit 합성
    • AIPauliNetworkSynthesis: Pauli Network Circuit 합성 (Qiskit Transpiler Service에서만 사용 가능하며 로컬 환경에서는 지원되지 않음)
  • 기존 트랜스파일과의 비교: 표준 Qiskit Transpiler는 다양한 양자 Circuit을 효과적으로 처리할 수 있는 강력한 도구입니다. 그러나 Circuit의 규모가 커지거나 하드웨어 구성이 복잡해지면 AI 패스가 추가적인 최적화 이점을 제공할 수 있습니다. 라우팅 및 합성에 학습된 모델을 활용함으로써 QTS는 Circuit 레이아웃을 더욱 정교하게 조정하고 까다롭거나 대규모 양자 작업의 오버헤드를 줄입니다.

이 튜토리얼은 라우팅 패스와 합성 패스 모두를 사용하여 AI 모드를 평가하고, 기존 트랜스파일과의 결과를 비교하여 AI가 성능 향상을 제공하는 부분을 강조합니다.

사용 가능한 AI 패스에 대한 자세한 내용은 AI 패스 문서를 참고하세요.

양자 Circuit 트랜스파일에 AI를 사용하는 이유

양자 Circuit이 크기와 복잡성 면에서 성장함에 따라, 기존 트랜스파일 방법은 레이아웃을 최적화하고 Gate 수를 효율적으로 줄이는 데 어려움을 겪습니다. 특히 수백 개의 Qubit을 포함하는 대규모 Circuit은 장치 제약, 제한된 연결성 및 Qubit 오류율로 인해 라우팅 및 합성에 상당한 어려움을 부과합니다.

바로 이 부분에서 AI 기반 트랜스파일이 잠재적인 해결책을 제공합니다. 머신 러닝 기술을 활용하여 Qiskit의 AI 기반 Transpiler는 Qubit 라우팅 및 Gate 합성에 대해 더 스마트한 결정을 내릴 수 있어 대규모 양자 Circuit의 최적화가 향상됩니다.

간략한 벤치마킹 결과

Qiskit 대비 AI Transpiler 성능을 보여주는 그래프

벤치마킹 테스트에서 AI Transpiler는 표준 Qiskit Transpiler에 비해 일관되게 더 얕고 품질이 높은 Circuit을 생성했습니다. 이 테스트에서는 [generate_preset_passmanager]로 구성된 Qiskit의 기본 패스 매니저 전략을 사용했습니다. 이 기본 전략은 종종 효과적이지만 더 크거나 복잡한 Circuit에서는 어려움을 겪을 수 있습니다. 반면에 AI 기반 패스는 IBM Quantum 하드웨어의 heavy-hex 토폴로지로 트랜스파일할 때 대규모 Circuit(100개 이상의 Qubit)에서 평균 24%의 두 Qubit Gate 수 감소와 36%의 Circuit 깊이 감소를 달성했습니다. 이 벤치마크에 대한 자세한 내용은 이 블로그를 참고하세요.

이 튜토리얼은 AI 패스의 주요 이점과 기존 방법과의 비교를 살펴봅니다.

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy pandas qiskit qiskit-ibm-runtime qiskit-ibm-transpiler
# This cell is hidden from users;
# it just disables a linting rule.
# ruff: noqa: F811

요구 사항

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

  • Qiskit SDK v1.0 이상, 시각화 지원 포함
  • Qiskit Runtime (pip install qiskit-ibm-runtime) v0.22 이상
  • AI 로컬 모드가 포함된 Qiskit IBM® Transpiler(pip install 'qiskit-ibm-transpiler[ai-local-mode]')

설정

from qiskit import QuantumCircuit
from qiskit.circuit.library import efficient_su2, PermutationGate
from qiskit.synthesis.qft import synth_qft_full
from qiskit.circuit.random import random_circuit, random_clifford_circuit
from qiskit.transpiler import generate_preset_pass_manager, CouplingMap
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_transpiler import generate_ai_pass_manager
from qiskit.synthesis.permutation import (
synth_permutation_depth_lnn_kms,
synth_permutation_basic,
)
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import time
import logging

seed = 42

# Used for generating permutation circuits in part two for comparison
def generate_permutation_circuit(width, pattern):
circuit = QuantumCircuit(width)
circuit.append(
PermutationGate(pattern=pattern),
qargs=range(width),
)
return circuit

# Creates a Bernstein-Vazirani circuit given the number of qubits
def create_bv_circuit(num_qubits):
qc = QuantumCircuit(num_qubits, num_qubits - 1)
qc.x(num_qubits - 1)
qc.h(qc.qubits)
for i in range(num_qubits - 1):
qc.cx(i, num_qubits - 1)
qc.h(qc.qubits[:-1])
return qc

# Transpile a circuit with a given pass manager and return metrics
def transpile_with_metrics(pass_manager, circuit):
start = time.time()
qc_out = pass_manager.run(circuit)
elapsed = time.time() - start

depth_2q = qc_out.depth(lambda x: x.operation.num_qubits == 2)
gate_count = qc_out.size()

return qc_out, {
"depth_2q": depth_2q,
"gate_count": gate_count,
"time_s": elapsed,
}

# Used for collecting metrics for part 3 of synthesis methods
def synth_transpile_with_metrics(qc, pm, pattern_id, method):
start = time.time()
qc = pm.run(qc)
elapsed = time.time() - start

return {
"Pattern": pattern_id,
"Method": method,
"Depth (2Q)": qc.depth(lambda x: x.operation.num_qubits == 2),
"Gates": qc.size(),
"Time (s)": elapsed,
}

# Ignore logs like "INFO:qiskit_ibm_transpiler.wrappers.ai_local_synthesis:Running Linear Functions AI synthesis on local mode"

logging.getLogger(
"qiskit_ibm_transpiler.wrappers.ai_local_synthesis"
).setLevel(logging.WARNING)

Part I. Qiskit 패턴

이제 Qiskit 패턴을 사용하여 간단한 양자 Circuit으로 AI Transpiler 서비스를 사용하는 방법을 살펴보겠습니다. 핵심은 표준 generate_preset_pass_manager() 대신 generate_ai_pass_manager()PassManager를 생성하는 것입니다.

Step 1: 고전적 입력을 양자 문제로 매핑

이 섹션에서는 efficient_su2 Circuit, 즉 널리 사용되는 하드웨어 효율적 ansatz에서 AI Transpiler를 테스트합니다. 이 Circuit은 변분 양자 알고리즘(예: VQE) 및 양자 머신 러닝 작업에 특히 관련이 있어 트랜스파일 성능 평가를 위한 이상적인 테스트 케이스입니다.

efficient_su2 Circuit은 단일 Qubit 회전과 CNOT 같은 엔탱글링 Gate의 교대 레이어로 구성됩니다. 이 레이어는 Gate 깊이를 관리 가능한 수준으로 유지하면서 양자 상태 공간을 유연하게 탐색할 수 있게 합니다. 이 Circuit을 최적화함으로써 Gate 수를 줄이고, 충실도를 높이며, 노이즈를 최소화하는 것을 목표로 합니다. 이는 AI Transpiler의 효율성을 테스트하기에 좋은 후보가 됩니다.

# For our transpilation, we will use a large circuit of 101 qubits
qc = efficient_su2(90, entanglement="circular", reps=1).decompose()

# Draw a smaller version of the circuit to get a visual representation
qc_small = efficient_su2(5, entanglement="circular", reps=1).decompose()
qc_small.draw(output="mpl")

이전 코드 셀의 출력

Step 2: 양자 하드웨어 실행을 위한 문제 최적화

Backend 선택

이 예시에서는 시뮬레이터가 아니며 최소 100개의 Qubit을 보유한 가장 여유 있는 운영 중인 IBM Quantum Backend를 선택합니다:

참고: 가장 여유 있는 Backend는 시간이 지남에 따라 변경될 수 있으므로 실행마다 다른 장치가 선택될 수 있습니다. 커플링 맵과 같은 장치별 속성은 트랜스파일된 Circuit에 차이를 초래할 수 있습니다.

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=100
)
cm = backend.coupling_map
print(f"Using backend: {backend.name}")
Using backend: ibm_torino

AI 및 기존 패스 매니저 생성

AI Transpiler의 효과를 평가하기 위해 두 번의 트랜스파일 실행을 수행합니다. 먼저 AI Transpiler를 사용하여 Circuit을 트랜스파일합니다. 그런 다음 AI Transpiler 없이 기존 방법을 사용하여 동일한 Circuit을 트랜스파일하여 비교를 실행합니다. 두 트랜스파일 프로세스 모두 선택한 Backend의 동일한 커플링 맵을 사용하고, 공정한 비교를 위해 최적화 레벨을 3으로 설정합니다.

이 두 방법 모두 Qiskit에서 Circuit을 트랜스파일하기 위한 PassManager 인스턴스를 생성하는 표준 접근 방식을 반영합니다.

pm_ai = generate_ai_pass_manager(
optimization_level=3,
ai_optimization_level=3,
coupling_map=cm,
include_ai_synthesis=True, # used for part 3 when comparing synthesis methods
)

pm_no_ai = generate_preset_pass_manager(
optimization_level=3,
coupling_map=cm,
seed_transpiler=seed, # note that the AI pass manager does not currently support seeding
)

Circuit을 트랜스파일하고 시간을 기록합니다.

# Transpile using standard (non-AI) pass manager
_, metrics_no_ai = transpile_with_metrics(pm_no_ai, qc)
print(
f"Standard transpilation: Depth (2q) {metrics_no_ai['depth_2q']}, "
f"Gate count {metrics_no_ai['gate_count']}, Time {metrics_no_ai['time_s']}"
)

# Transpile using AI pass manager
_, metrics_ai = transpile_with_metrics(pm_ai, qc)
print(
f"AI transpilation : Depth (2q) {metrics_ai['depth_2q']}, "
f"Gate count {metrics_ai['gate_count']}, Time {metrics_ai['time_s']}"
)
Standard transpilation: Depth (2q) 95, Gate count 458, Time 0.04650712013244629
AI transpilation : Depth (2q) 90, Gate count 456, Time 0.9342479705810547

이 테스트에서는 efficient_su2 Circuit에서 AI Transpiler와 표준 트랜스파일 방법의 성능을 비교합니다. AI Transpiler는 비슷한 Gate 수를 유지하면서 눈에 띄게 더 얕은 Circuit 깊이를 달성합니다.

  • Circuit 깊이: AI Transpiler는 더 낮은 두 Qubit 깊이를 가진 Circuit을 생성합니다. AI 패스는 Qubit 상호작용 패턴을 학습하고 규칙 기반 휴리스틱보다 하드웨어 연결성을 더 효과적으로 활용하여 깊이를 최적화하도록 훈련되어 있으므로 이는 예상된 결과입니다.

  • Gate 수: 총 Gate 수는 두 방법 사이에서 비슷하게 유지됩니다. 표준 SABRE 기반 트랜스파일은 Gate 오버헤드를 지배하는 SWAP 수를 명시적으로 최소화하기 때문에 이는 예상과 일치합니다. AI Transpiler는 대신 전체 깊이를 우선시하며 더 짧은 실행 경로를 위해 때로 몇 가지 추가 Gate를 교환할 수 있습니다.

  • 트랜스파일 시간: AI Transpiler는 표준 방법보다 실행 시간이 더 오래 걸립니다. 이는 라우팅 및 합성 중에 학습된 모델을 호출하는 추가적인 계산 비용 때문입니다. 반면 SABRE 기반 Transpiler는 Rust로 재작성되고 최적화된 후 크게 빨라져 대규모에서 매우 효율적인 휴리스틱 라우팅을 제공합니다.

이러한 결과는 하나의 Circuit에 기반한 것임을 명심하는 것이 중요합니다. AI Transpiler와 기존 방법을 포괄적으로 이해하려면 다양한 Circuit을 테스트해야 합니다. QTS의 성능은 최적화되는 Circuit의 유형에 따라 크게 달라질 수 있습니다. 더 광범위한 비교를 위해 위의 벤치마크를 참고하거나 블로그를 방문하세요.

Step 3: Qiskit 프리미티브를 사용한 실행

이 튜토리얼은 트랜스파일에 초점을 맞추고 있으므로, 양자 디바이스에서 실험을 실행하지 않습니다. 목표는 Step 2의 최적화를 활용하여 깊이(depth) 또는 게이트 수가 줄어든 트랜스파일된 Circuit을 얻는 것입니다.

Step 4: 결과를 원하는 고전 형식으로 후처리하여 반환

이 노트북에서는 실행이 없으므로 후처리할 결과도 없습니다.

파트 II. 트랜스파일된 Circuit 분석 및 벤치마킹

이 섹션에서는 트랜스파일된 Circuit을 분석하고 원본 버전과 더 상세하게 비교하는 방법을 보여줍니다. Circuit 깊이, 게이트 수, 트랜스파일 시간과 같은 지표에 집중하여 최적화의 효과를 평가합니다. 또한 다양한 Circuit 유형에 따라 결과가 어떻게 달라질 수 있는지 논의하고, 여러 시나리오에서 Transpiler의 전반적인 성능에 대한 통찰을 제공합니다.

# Circuits to benchmark
seed = 42
circuits = [
{
"name": "Random",
"qc": random_circuit(num_qubits=30, depth=10, seed=seed),
},
{
"name": "Clifford",
"qc": random_clifford_circuit(
num_qubits=40, num_gates=200, seed=seed
),
},
{
"name": "QFT",
"qc": synth_qft_full(num_qubits=20, do_swaps=False).decompose(),
},
{
"name": "BV",
"qc": create_bv_circuit(40),
},
]

results = []

# Run the transpilation for each circuit and store the results
for circuit in circuits:
qc_no_ai, metrics_no_ai = transpile_with_metrics(pm_no_ai, circuit["qc"])
qc_ai, metrics_ai = transpile_with_metrics(pm_ai, circuit["qc"])

print("Completed transpilation for", circuit["name"])

results.append(
{
"Circuit": circuit["name"],
"Depth 2Q (No AI)": metrics_no_ai["depth_2q"],
"Gate Count (No AI)": metrics_no_ai["gate_count"],
"Time (No AI)": metrics_no_ai["time_s"],
"Depth 2Q (AI)": metrics_ai["depth_2q"],
"Gate Count (AI)": metrics_ai["gate_count"],
"Time (AI)": metrics_ai["time_s"],
}
)

df = pd.DataFrame(results)
df
Completed transpilation for Random
Completed transpilation for Clifford
Completed transpilation for QFT
Completed transpilation for BV
Circuit  Depth 2Q (No AI)  Gate Count (No AI)  Time (No AI)  \
0 Random 37 221 0.039347
1 Clifford 36 232 0.036633
2 QFT 165 924 0.077458
3 BV 65 155 0.024993

Depth 2Q (AI) Gate Count (AI) Time (AI)
0 24 181 0.773718
1 43 267 1.097431
2 130 913 3.660771
3 70 155 0.345522

각 지표의 평균 감소율입니다. 양수는 개선, 음수는 저하를 나타냅니다.

# Average reduction from non-AI to AI transpilation as a percentage
avg_reduction_depth = (
(df["Depth 2Q (No AI)"] - df["Depth 2Q (AI)"]).mean()
/ df["Depth 2Q (No AI)"].mean()
* 100
)
avg_reduction_gates = (
(df["Gate Count (No AI)"] - df["Gate Count (AI)"]).mean()
/ df["Gate Count (No AI)"].mean()
* 100
)
avg_reduction_time = (
(df["Time (No AI)"] - df["Time (AI)"]).mean()
/ df["Time (No AI)"].mean()
* 100
)

print(f"Average reduction in depth: {avg_reduction_depth:.2f}%")
print(f"Average reduction in gate count: {avg_reduction_gates:.2f}%")
print(f"Average reduction in transpilation time: {avg_reduction_time:.2f}%")
Average reduction in depth: 11.88%
Average reduction in gate count: 1.04%
Average reduction in transpilation time: -3193.95%
fig, axs = plt.subplots(1, 3, figsize=(21, 6))
df.plot(
x="Circuit",
y=["Depth 2Q (No AI)", "Depth 2Q (AI)"],
kind="bar",
ax=axs[0],
)
axs[0].set_title("Circuit Depth Comparison")
axs[0].set_ylabel("Depth")
axs[0].set_xlabel("Circuit")
axs[0].tick_params(axis="x", rotation=45)
df.plot(
x="Circuit",
y=["Gate Count (No AI)", "Gate Count (AI)"],
kind="bar",
ax=axs[1],
)
axs[1].set_title("Gate Count Comparison")
axs[1].set_ylabel("Gate Count")
axs[1].set_xlabel("Circuit")
axs[1].tick_params(axis="x", rotation=45)
df.plot(x="Circuit", y=["Time (No AI)", "Time (AI)"], kind="bar", ax=axs[2])
axs[2].set_title("Time Comparison")
axs[2].set_ylabel("Time (seconds)")
axs[2].set_xlabel("Circuit")
axs[2].tick_params(axis="x", rotation=45)
fig.suptitle(
"Benchmarking AI transpilation vs Non-AI transpilation for various circuits"
)

plt.tight_layout()
plt.show()

이전 코드 셀의 출력

AI Transpiler의 성능은 최적화하는 Circuit의 유형에 따라 크게 달라집니다. 일부 경우에는 표준 Transpiler에 비해 Circuit 깊이와 게이트 수가 눈에 띄게 줄어듭니다. 그러나 이러한 개선은 종종 런타임이 크게 증가하는 대가를 치릅니다.

특정 유형의 Circuit에서는 AI Transpiler가 Circuit 깊이 측면에서 약간 더 나은 결과를 낼 수 있지만, 게이트 수 증가와 상당한 런타임 저하를 초래할 수도 있습니다. 이러한 관찰은 AI Transpiler의 이점이 모든 Circuit 유형에 균일하게 적용되지 않음을 시사합니다. 오히려, 효과는 Circuit의 특성에 따라 달라지므로 일부 사용 사례에 더 적합합니다.

AI 기반 트랜스파일을 언제 선택해야 할까요?

Qiskit의 AI 기반 Transpiler는 전통적인 트랜스파일 방법이 어려움을 겪는 시나리오, 특히 대규모의 복잡한 양자 Circuit에서 뛰어난 성능을 발휘합니다. 수백 개의 Qubit이 포함된 Circuit이나 복잡한 커플링 맵을 가진 하드웨어를 대상으로 하는 경우, AI Transpiler는 Circuit 깊이, 게이트 수, 런타임 효율성 측면에서 우수한 최적화를 제공합니다. 벤치마킹 테스트에서 AI Transpiler는 전통적인 방법보다 지속적으로 우수한 성능을 보여주며, 훨씬 더 얕은 Circuit과 적은 게이트 수를 달성했습니다. 이는 실제 양자 하드웨어에서 성능을 향상시키고 노이즈를 줄이는 데 중요합니다.

사용자는 다음과 같은 경우 AI 기반 트랜스파일을 고려해야 합니다:

  • 전통적인 방법으로는 규모를 효율적으로 처리하기 어려운 대형 Circuit.
  • 디바이스 연결성과 라우팅 문제가 발생하는 복잡한 하드웨어 토폴로지.
  • Circuit 깊이 줄이기와 피델리티 향상이 가장 중요한 성능 민감형 애플리케이션.

파트 III. AI 기반 순열 네트워크 합성 탐색

순열 네트워크는 양자 컴퓨팅, 특히 제한된 토폴로지로 인해 제약을 받는 시스템에서 매우 중요합니다. 이러한 네트워크는 제한된 연결성을 가진 하드웨어에서 전전 연결(all-to-all connectivity)을 모방하기 위해 Qubit을 동적으로 스왑하여 장거리 상호작용을 가능하게 합니다. 이러한 변환은 상호작용이 종종 최근접 이웃을 초과하는 근미래 디바이스에서 복잡한 양자 알고리즘을 구현하는 데 필수적입니다.

이 섹션에서는 Qiskit의 AI 기반 Transpiler에 대한 매력적인 사용 사례로서 순열 네트워크의 합성을 강조합니다. 구체적으로, AIPermutationSynthesis 패스는 AI 기반 최적화를 활용하여 Qubit 순열 작업을 위한 효율적인 Circuit을 생성합니다. 반면, 일반적인 합성 방식은 특히 밀집된 Qubit 상호작용이 있거나 완전한 연결성을 달성하려는 시나리오에서 게이트 수와 Circuit 깊이 간의 균형을 맞추기 어려울 수 있습니다.

Qiskit 패턴 예제를 통해 Qubit 집합에 대한 전전 연결을 달성하기 위한 순열 네트워크 합성을 살펴볼 것입니다. Qiskit의 표준 합성 방법과 AIPermutationSynthesis의 성능을 비교합니다. 이 예제는 AI Transpiler가 어떻게 더 낮은 Circuit 깊이와 게이트 수를 위해 최적화하는지 보여주며, 실제 양자 워크플로에서의 장점을 강조합니다. AI 합성 패스를 활성화하기 위해 include_ai_synthesis 파라미터를 True로 설정하여 generate_ai_pass_manager() 함수를 사용합니다.

Step 1: 고전적 입력을 양자 문제로 매핑

고전적 순열 문제를 양자 컴퓨터에서 표현하기 위해 먼저 양자 Circuit의 구조를 정의합니다. 이 예제에서는:

  1. 양자 Circuit 초기화: 사용할 Backend의 Qubit 수(27개)에 맞춰 27개의 Qubit을 할당합니다.

  2. 순열 적용: 재현성을 위해 고정 시드를 사용하여 10개의 무작위 순열 패턴(pattern_1부터 pattern_10)을 생성합니다. 각 순열 패턴은 별도의 양자 Circuit(qc_1부터 qc_10)에 적용됩니다.

  3. Circuit 분해: 각 순열 연산은 대상 양자 하드웨어와 호환되는 네이티브 게이트 집합으로 분해됩니다. 분해된 각 Circuit의 깊이와 2큐비트 게이트(비로컬 게이트) 수를 분석합니다.

결과는 양자 디바이스에서 고전적 순열 문제를 표현하는 복잡성에 대한 통찰을 제공하며, 다양한 순열 패턴에 필요한 리소스를 보여줍니다.

# Parameters
width = 27
num_circuits = 10

# Set random seed
np.random.seed(seed)

# Generate random patterns and circuits
patterns = [
np.random.permutation(width).tolist() for _ in range(num_circuits)
]
circuits = {
f"qc_{i}": generate_permutation_circuit(width, pattern)
for i, pattern in enumerate(patterns, start=1)
}

# Display one of the circuits
circuits["qc_1"].decompose(reps=3).draw(output="mpl", fold=-1)

이전 코드 셀의 출력

Step 2: Optimize problem for quantum hardware execution

이 단계에서는 AI 합성 패스를 사용하여 최적화를 진행합니다.

AI 합성 패스의 경우, PassManager는 Backend의 커플링 맵만 필요합니다. 그러나 모든 커플링 맵이 호환되는 것은 아닙니다. AIPermutationSynthesis 패스가 학습된 커플링 맵만 사용할 수 있습니다. 현재 AIPermutationSynthesis 패스는 65, 33, 27 큐비트 크기의 블록을 지원합니다. 이 예제에서는 27-큐비트 QPU를 사용합니다.

비교를 위해, Qiskit의 일반적인 순열 합성 방법과 AI 합성의 성능을 평가할 것입니다. 다음 방법들을 포함합니다:

  • synth_permutation_depth_lnn_kms: 이 방법은 Kutin, Moulton, Smithline (KMS) 알고리즘을 사용하여 선형 최근접 이웃(LNN) 아키텍처에 대한 순열 Circuit을 합성합니다. SWAP Gate 기준으로 측정했을 때 최대 nn 깊이와 최대 n(n1)/2n(n-1)/2 크기의 Circuit을 보장합니다.

  • synth_permutation_basic: 이는 연결성 제약이나 특정 아키텍처에 대한 최적화 없이 순열 Circuit을 합성하는 간단한 구현입니다. 더 고급 방법과의 성능 비교를 위한 기준선 역할을 합니다.

이러한 각 방법은 순열 네트워크를 합성하는 서로 다른 접근 방식을 나타내며, AI 기반 방법에 대한 포괄적인 벤치마크를 제공합니다.

Qiskit의 합성 방법에 대한 자세한 내용은 Qiskit API 문서를 참조하세요. 27-큐비트 QPU를 나타내는 커플링 맵을 정의합니다.

coupling_map = [
[1, 0],
[2, 1],
[3, 2],
[3, 5],
[4, 1],
[6, 7],
[7, 4],
[7, 10],
[8, 5],
[8, 9],
[8, 11],
[11, 14],
[12, 10],
[12, 13],
[12, 15],
[13, 14],
[16, 14],
[17, 18],
[18, 15],
[18, 21],
[19, 16],
[19, 22],
[20, 19],
[21, 23],
[23, 24],
[25, 22],
[25, 24],
[26, 25],
]
CouplingMap(coupling_map).draw()

이전 코드 셀의 출력

AI 합성 패스와 일반 합성 방법을 사용하여 각 순열 Circuit을 트랜스파일합니다.

results = []
pm_no_ai_synth = generate_preset_pass_manager(
coupling_map=cm,
optimization_level=1, # set to 1 since we are using the synthesis methods
)

# Transpile and analyze all circuits
for i, (qc_name, qc) in enumerate(circuits.items(), start=1):
pattern = patterns[i - 1] # Get the corresponding pattern

qc_depth_lnn_kms = synth_permutation_depth_lnn_kms(pattern)
qc_basic = synth_permutation_basic(pattern)

# AI synthesis
results.append(
synth_transpile_with_metrics(
qc.decompose(reps=3),
pm_ai,
qc_name,
"AI",
)
)

# Depth-LNN-KMS Method
results.append(
synth_transpile_with_metrics(
qc_depth_lnn_kms.decompose(reps=3),
pm_no_ai_synth,
qc_name,
"Depth-LNN-KMS",
)
)

# Basic Method
results.append(
synth_transpile_with_metrics(
qc_basic.decompose(reps=3),
pm_no_ai_synth,
qc_name,
"Basic",
)
)

results_df = pd.DataFrame(results)

트랜스파일 후 각 Circuit의 지표(깊이, Gate 수, 시간)를 기록합니다.

# Calculate averages for each metric
average_metrics = results_df.groupby("Method")[
["Depth (2Q)", "Gates", "Time (s)"]
].mean()
average_metrics = average_metrics.round(3) # Round to two decimal places
print("\n=== Average Metrics ===")
print(average_metrics)

# Identify the best non-AI method based on least average depth
non_ai_methods = [
method for method in results_df["Method"].unique() if method != "AI"
]
best_non_ai_method = average_metrics.loc[non_ai_methods][
"Depth (2Q)"
].idxmin()
print(
f"\nBest Non-AI Method (based on least average depth): {best_non_ai_method}"
)

# Compare AI to the best non-AI method
ai_metrics = average_metrics.loc["AI"]
best_non_ai_metrics = average_metrics.loc[best_non_ai_method]

comparison = {
"Metric": ["Depth (2Q)", "Gates", "Time (s)"],
"AI": [
ai_metrics["Depth (2Q)"],
ai_metrics["Gates"],
ai_metrics["Time (s)"],
],
best_non_ai_method: [
best_non_ai_metrics["Depth (2Q)"],
best_non_ai_metrics["Gates"],
best_non_ai_metrics["Time (s)"],
],
"Improvement (AI vs Best Non-AI)": [
ai_metrics["Depth (2Q)"] - best_non_ai_metrics["Depth (2Q)"],
ai_metrics["Gates"] - best_non_ai_metrics["Gates"],
ai_metrics["Time (s)"] - best_non_ai_metrics["Time (s)"],
],
}

comparison_df = pd.DataFrame(comparison)
print("\n=== Comparison of AI vs Best Non-AI Method ===")
comparison_df
=== Average Metrics ===
Depth (2Q) Gates Time (s)
Method
AI 23.9 82.8 0.248
Basic 29.8 91.0 0.012
Depth-LNN-KMS 70.8 531.6 0.017

Best Non-AI Method (based on least average depth): Basic

=== Comparison of AI vs Best Non-AI Method ===
Metric      AI   Basic  Improvement (AI vs Best Non-AI)
0 Depth (2Q) 23.900 29.800 -5.900
1 Gates 82.800 91.000 -8.200
2 Time (s) 0.248 0.012 0.236

결과는 AI Transpiler가 이 무작위 순열 Circuit 세트에 대해 다른 모든 Qiskit 합성 방법보다 우수한 성능을 보임을 보여줍니다. 주요 결과는 다음과 같습니다:

  1. 깊이: AI Transpiler는 가장 낮은 평균 깊이를 달성하여 Circuit 레이아웃 최적화가 우수함을 나타냅니다.
  2. Gate 수: 다른 방법에 비해 Gate 수를 크게 줄여 실행 신뢰도와 효율성을 향상시킵니다.
  3. 트랜스파일 시간: 이 규모에서 모든 방법이 매우 빠르게 실행되어 실용적으로 사용할 수 있습니다. 그러나 AI Transpiler는 사용되는 AI 모델의 복잡성으로 인해 전통적인 방법에 비해 런타임이 눈에 띄게 증가합니다.

이 결과는 AI Transpiler가 이 벤치마크에서 가장 효과적인 방법임을 확인시켜 주며, 특히 깊이와 Gate 수 최적화에서 뛰어납니다. AI 합성 패스와 일반 합성 방법의 성능을 비교하기 위해 결과를 시각화합니다.

methods = results_df["Method"].unique()

fig, axs = plt.subplots(1, 3, figsize=(18, 5))

# Pivot the DataFrame and reorder columns to ensure AI is first
pivot_depth = results_df.pivot(
index="Pattern", columns="Method", values="Depth (2Q)"
)[["AI", "Depth-LNN-KMS", "Basic"]]
pivot_gates = results_df.pivot(
index="Pattern", columns="Method", values="Gates"
)[["AI", "Depth-LNN-KMS", "Basic"]]
pivot_time = results_df.pivot(
index="Pattern", columns="Method", values="Time (s)"
)[["AI", "Depth-LNN-KMS", "Basic"]]

pivot_depth.plot(kind="bar", ax=axs[0], legend=False)
axs[0].set_title("Circuit Depth Comparison")
axs[0].set_ylabel("Depth")
axs[0].set_xlabel("Pattern")
axs[0].tick_params(axis="x", rotation=45)
pivot_gates.plot(kind="bar", ax=axs[1], legend=False)
axs[1].set_title("2Q Gate Count Comparison")
axs[1].set_ylabel("Number of 2Q Gates")
axs[1].set_xlabel("Pattern")
axs[1].tick_params(axis="x", rotation=45)
pivot_time.plot(
kind="bar", ax=axs[2], legend=True, title="Legend"
) # Show legend on the last plot
axs[2].set_title("Time Comparison")
axs[2].set_ylabel("Time (seconds)")
axs[2].set_xlabel("Pattern")
axs[2].tick_params(axis="x", rotation=45)
fig.suptitle(
"Benchmarking AI Synthesis Methods vs Non-AI Synthesis Methods For Random Permutations Circuits",
fontsize=16,
y=1,
)

plt.tight_layout()
plt.show()

이전 코드 셀의 출력

이 그래프는 서로 다른 합성 방법 간에 각 Circuit(qc_1부터 qc_10까지)의 개별 결과를 보여줍니다:

이 결과는 순열 Circuit에 대한 AI Transpiler의 효과를 강조하지만, 그 한계도 중요하게 고려해야 합니다. AI 합성 방법은 현재 특정 커플링 맵에서만 사용 가능하여 더 넓은 적용 가능성을 제한할 수 있습니다. 이 제약은 다른 시나리오에서의 사용을 평가할 때 고려해야 합니다.

전반적으로, AI Transpiler는 이러한 특정 Circuit에 대해 깊이와 Gate 수 최적화에서 유망한 개선을 보여주며, 동시에 비슷한 트랜스파일 시간을 유지합니다.

Step 3: Execute using Qiskit primitives

이 튜토리얼은 트랜스파일에 초점을 맞추고 있으므로, 양자 장치에서 실험을 실행하지 않습니다. 목표는 Step 2의 최적화를 활용하여 깊이 또는 Gate 수가 감소된 트랜스파일된 Circuit을 얻는 것입니다.

Step 4: Post-process and return result in desired classical format

이 노트북에는 실행이 없으므로 후처리할 결과도 없습니다.

튜토리얼 설문조사

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

설문조사 링크

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.