البداية السريعة
title: البداية السريعة description: دليل بداية سريعة لحزمة pauli-prop من إضافات Qiskit
في هذا الدليل نستخدم حزمة pauli-prop لمحاكاة الديناميكا الزمنية لنموذج Ising المدفوع بـ 10 كيوبت على سلسلة سبين أحادية البعد بشكل كلاسيكي.
جهّز المدخلات لانتشار باولي
الهاميلتونيان المعتمد هو:
حيث يصف الاقتران بين السبينات المتجاورة، ، و هو المجال المستعرض العام. سيتم تنفيذ تحليل Trotter من الرتبة الأولى للمؤثر المتطور زمنياً كدائرة كمية، ، على مدى خطوة Trotter. سيتم تثبيت ثابت الاقتران، ، عند ، وتثبيت عند . ستُنفَّذ تفاعلات باستخدام بوابات Clifford (، ، ).
ننفّذ التطور الزمني بطريقة Trotter كدائرة كمية ونستخدم للدورانات غير Clifford حول المحور x. كلما ابتعدت هذه الزوايا عن زوايا Clifford (مثلاً )، صارت محاكاة النظام أصعب على طرق انتشار باولي.
بالنسبة لاختيار القابل للرصد، نعتمد متوسط المغنطة في موقع واحد، ، حيث هو عدد السبينات.
# 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)
حاكِ التطور الزمني للنظام باستخدام انتشار باولي
بمجرد أن تصبح لدينا الدائرة، ، والقابل للرصد، ، يمكننا محاكاة النظام بسهولة في بضع خطوات:
-
افصل إلى جزأيه Clifford، ، وغير Clifford، ، بحيث باستخدام
evolve_through_cliffords -
انشر عبر ، لينتج مؤثر جديد، ، باستخدام
pauli_prop.propagate_through_circuit -
طوّر عبر جزء Clifford من الدائرة باستخدام دعم تطور Clifford المدمج في Qiskit
-
قرّب القيمة المتوقعة بالشكل عن طريق جمع المعاملات في المرتبطة بحدود باولي القطرية بالكامل (حدود باولي التي تحتوي على
IأوZفقط على كل الكيوبتات). تذكّر أن هذا تقريب لأننا حذفنا بعض الحدود من أثناء نشره عبر الجزء غير 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())
)
كلما أجرينا حسابات أكبر، صارت تقريبات القيمة المتوقعة أدق. في هذا المثال، نملأ فضاء باولي بالكامل عند حوالي ، وهو ما ينعكس في تسطّح المنحنى بين النقطتين الأخيرتين.
رغم أن الرسم أدناه يُظهر تقارباً رتيباً، فإن محاكاات انتشار باولي لا تتقارب رتيباً بشكل عام. ليس من غير المعتاد رؤية سلوك "متعرج" في هذه الأنواع من الرسوم.
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')

