انتقل إلى المحتوى الرئيسي
هذا المشروع في مرحلة تجريبية. وجدت خطأ؟ افتح مشكلة على GitHub. لديك سؤال أو فكرة؟ اسأل في Discussions — نحب سماع ملاحظاتك!
كيف جودة الترجمة في هذه الصفحة؟

البداية السريعة


title: البداية السريعة description: دليل بداية سريعة لحزمة pauli-prop من إضافات Qiskit​

في هذا الدليل نستخدم حزمة pauli-prop لمحاكاة الديناميكا الزمنية لنموذج Ising المدفوع بـ 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 هو المجال المستعرض العام. سيتم تنفيذ تحليل Trotter من الرتبة الأولى للمؤثر المتطور زمنياً كدائرة كمية، UU، على مدى 2020 خطوة Trotter. سيتم تثبيت ثابت الاقتران، JJ، عند J=−π2J=-\frac{\pi}{2}، وتثبيت hh عند π6\frac{\pi}{6}. ستُنفَّذ تفاعلات ZZZZ باستخدام بوابات Clifford ‏(CXCX، SdgSdg، Y\sqrt{Y}).

ننفّذ التطور الزمني بطريقة Trotter كدائرة كمية ونستخدم π6\frac{\pi}{6} للدورانات غير Clifford حول المحور x. كلما ابتعدت هذه الزوايا عن زوايا Clifford (مثلاً θ=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 هو عدد السبينات.

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

_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "pauli_prop": "pauli-prop", "qiskit": "qiskit", "qiskit_aer": "qiskit-aer"}
_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")
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 of the previous code cell

حاكِ التطور الزمني للنظام باستخدام انتشار باولي​

بمجرد أن تصبح لدينا الدائرة، UU، والقابل للرصد، OO، يمكننا محاكاة النظام بسهولة في بضع خطوات:

  • افصل UU إلى جزأيه Clifford، CC، وغير Clifford، PP، بحيث U=PCU=PC باستخدام evolve_through_cliffords

  • انشر OO عبر PP، لينتج مؤثر جديد، O′O^\prime، باستخدام pauli_prop.propagate_through_circuit

  • طوّر O′O^\prime عبر جزء Clifford من الدائرة باستخدام دعم تطور Clifford المدمج في Qiskit

  • قرّب القيمة المتوقعة بالشكل ⟨0∣O′∣0⟩≈⟨0∣U†OU∣0⟩\langle0|O^\prime|0\rangle \approx \langle0|U^\dagger OU|0\rangle عن طريق جمع المعاملات في O′O^\prime المرتبطة بحدود باولي القطرية بالكامل (حدود باولي التي تحتوي على I أو Z فقط على كل الكيوبتات). تذكّر أن هذا تقريب لأننا حذفنا بعض الحدود من O′O^\prime أثناء نشره عبر الجزء غير Clifford من الدائرة.

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")
Text(0.5, 1.0, 'Simulating 20-step 1D Ising Model')

Output of the previous code cell