Skip to main content
IBM Quantum Platform


title: "빠른 시작" description: "pauli-prop Qiskit 애드온 패키지를 위한 빠른 시작 가이드"

빠른 시작

이 가이드에서는 pauli-prop 패키지를 사용하여 1D 스핀 사슬 상의 10-큐비트 킥 이징 모델의 시간적 동역학을 고전적으로 시뮬레이션합니다.


파울리 전파를 위한 입력값을 준비합니다

고려되는 해밀토니안은 다음과 같습니다:

H=−J∑⟨i,j⟩ZiZj+h∑iXiH = -J\sum\limits_{\langle i,j \rangle} Z_iZ_j + h\sum\limits_iX_i

여기서 J>0J>0 는 가장 가까운 이웃 스핀 간의 결합을 나타내며, i<ji<j 이고, hh 는 전역 횡자기장이다. 시간에 따라 변화하는 연산자에 대한 1차 트로터 분해는 2020 의 트로터 단계를 거쳐 양자 회로 UU 로 구현될 것이다. 결합 상수 JJ 는 J=−π2J=-\frac{\pi}{2} 로 고정되며, hh 는 π6\frac{\pi}{6} 로 고정됩니다. ZZZZ 상호작용은 클리포드 게이트( CXCX, SdgSdg, Y\sqrt{Y} )를 사용하여 구현될 것입니다.

우리는 트로터화(Trotterized)된 시간 진화를 양자 회로로 구현하고, x축을 중심으로 한 비클리포드 회전에 대해 π6\frac{\pi}{6} 를 사용합니다. 이러한 각도가 클리포드 각도(예: θ=nπ2,n∈Z\theta=n\frac{\pi}{2}, n \in \mathbb{Z} )에서 멀어질수록, 파울리 전파법을 사용하여 해당 시스템을 시뮬레이션하는 것이 더 어려워집니다.

관측량으로, 평균 단일 위치 자화량인 1N∑i=1N⟨zi⟩\frac{1}{N} \sum_{i=1}^{N} \langle z_i \rangle 를 고려하며, 여기서 NN 는 스핀의 개수이다.

import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import CouplingMap

num_qubits = 10
coupling_map = CouplingMap.from_line(num_qubits, bidirectional=False)

# Num Trotter steps
num_steps = 20
theta_rx = np.pi / 6

# Average single-site magnetization
observable = (
    SparsePauliOp(
        [
            "I" * iq + "Z" + "I" * (num_qubits - iq - 1)
            for iq in range(num_qubits)
        ]
    )
    / num_qubits
)

# Create the Trotter circuit
num_qubits = 10
num_steps = 20
theta_rx = np.pi / 6
circuit = QuantumCircuit(num_qubits)
edges = CouplingMap.from_line(num_qubits, bidirectional=False).get_edges()
for _ in range(num_steps):
    circuit.rx(theta_rx, [i for i in range(num_qubits)])
    for edge in edges:
        circuit.sdg(edge)
        circuit.ry(np.pi / 2, edge[1])
        circuit.cx(edge[0], edge[1])
        circuit.ry(-np.pi / 2, edge[1])
circuit.draw("mpl", fold=-1)

Output:

Output of the previous code cell

파울리 전파를 사용하여 시스템의 시간적 변화를 시뮬레이션한다

회로( UU )와 관측 가능 변수( OO )가 준비되면, 몇 단계만 거치면 시스템을 쉽게 시뮬레이션할 수 있습니다:

  • UU 를 클리포드 부분( CC )과 비클리포드 부분( PP )으로 분리하되, U=PCU=PC 가 성립하도록 하되, 다음을 사용한다. evolve_through_cliffords
  • OO 를 PP 를 통해 전개하면, 다음을 사용하여 새로운 연산자 O′O^\prime 가 생성됩니다. pauli_prop.propagate_through_circuit
  • Qiskit에 내장된 클리포드 진화 지원 기능을 사용하여 회로의 클리포드 부분을 통해 O′O^\prime 를 진화시킵니다
  • O′O^\prime 에 포함된, 완전히 대각선인 파울리 항(모든 큐비트에 Z I 또는 중 하나가 포함된 파울리 항)과 관련된 계수들을 합산하여, 기대값을 ⟨0∣O′∣0⟩≈⟨0∣U†OU∣0⟩\langle0|O^\prime|0\rangle \approx \langle0|U^\dagger OU|0\rangle 로 근사합니다. 이 계산은 회로의 비클리포드 부분으로 전파하는 과정에서 O′O^\prime 의 항들을 생략했기 때문에 근사값이라는 점을 기억하십시오.
import time

from pauli_prop import evolve_through_cliffords, propagate_through_circuit

cliff, non_cliff = evolve_through_cliffords(circuit)

max_terms_list = [10**i for i in range(8)]
approx_evs = []
durations = []
for max_terms in max_terms_list:
    st = time.perf_counter()
    evolved_obs = propagate_through_circuit(
        observable, non_cliff, max_terms=max_terms, atol=1e-12, frame="h"
    )[0]
    evolved_obs.paulis = evolved_obs.paulis.evolve(cliff, frame="h")
    durations.append(time.perf_counter() - st)
    approx_evs.append(
        float(evolved_obs.coeffs[~evolved_obs.paulis.x.any(axis=1)].sum())
    )

계산 규모가 커질수록 기대값 근사치의 정확도는 높아집니다. 이 예시에서는 약 410≈1064^{10}\approx10^6 에서 전체 파울리 공간이 포화 상태에 이르며, 이는 마지막 두 점 사이에서 곡선이 평평해지는 것으로 나타납니다.

아래 그래프에서는 단조 수렴이 나타나지만, 파울리 전파 시뮬레이션은 일반적으로 단조적으로 수렴하지 않습니다. 이러한 유형의 그래프에서 “울퉁불퉁한” 양상을 보이는 것은 드문 일이 아닙니다.

import matplotlib.pyplot as plt
from qiskit_aer import AerSimulator

sim_circ = circuit.copy()
sim_circ.save_statevector()
backend = AerSimulator(method="statevector")
psi = backend.run(sim_circ).result().data()["statevector"]
exact_ev = psi.expectation_value(observable)

ax1 = plt.gca()
ax1.plot(max_terms_list, approx_evs, marker="o", label="Approximate")
ax1.axhline(exact_ev, linestyle="--", color="green", label="Exact")
ax1.set_xscale("log")
ax1.set_xlabel("# terms kept")
ax1.set_ylabel(r"$\frac{1}{N} \sum_{i=1}^{N} \langle z_i \rangle$")

ax2 = ax1.twinx()
ax2.plot(
    max_terms_list, durations, marker=".", label="Runtime", color="orange"
)
ax2.set_ylabel("Runtime (s)", color="orange")
ax2.set_yscale("log")

handles1, labels1 = ax1.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(handles1 + handles2, labels1 + labels2, loc="lower right")

plt.title(f"Simulating {num_steps}-step 1D Ising Model")

Output:

Text(0.5, 1.0, 'Simulating 20-step 1D Ising Model')
Output of the previous code cell
이 페이지가 도움이 되었습니까?
GitHub에서 버그, 오타를 보고하거나 컨텐츠를 요청하십시오.