Lumaktaw sa pangunahing nilalaman
Ang proyektong ito ay nasa beta. Nakakita ng bug? Mag-bukas ng GitHub issue. May tanong o ideya? Magtanong sa Discussions — gusto naming marinig ang iyong feedback!
Gaano kaganda ang kalidad ng pagsasalin sa pahinang ito?

Mabilisang simula


title: Quickstart description: Isang quickstart na gabay para sa pauli-prop na Qiskit addons package​

Sa gabay na ito, gagamitin natin ang pauli-prop package para i-simulate nang classical ang time dynamics ng isang 10-qubit na kicked Ising model sa 1D spin chain.

Ihanda ang mga input para sa Pauli propagation​

Ang Hamiltonian na isinasaalang-alang ay:

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

kung saan ang J>0J>0 ay naglalarawan ng coupling ng mga magkatabing spin, i<ji<j, at ang hh ay ang global na transverse field. Ang first-order na Trotter decomposition ng time-evolved na operator ay ipapatupad bilang isang quantum circuit, UU, sa loob ng 2020 Trotter step. Ang coupling constant, JJ, ay ifi-fix sa J=−π2J=-\frac{\pi}{2}, at ang hh ay ifi-fix sa π6\frac{\pi}{6}. Ang mga interaksyong ZZZZ ay ipapatupad gamit ang mga Clifford gate (CXCX, SdgSdg, Y\sqrt{Y}).

Ipinapatupad natin ang Trotterized na time evolution bilang isang quantum circuit at gumagamit ng π6\frac{\pi}{6} para sa mga non-Clifford na rotation sa paligid ng x-axis. Habang lumalayo ang mga anggulong ito sa mga Clifford angle (halimbawa, θ=nπ2,n∈Z\theta=n\frac{\pi}{2}, n \in \mathbb{Z}), mas nagiging mahirap i-simulate ang sistema gamit ang mga Pauli propagation method.

Para sa pagpili ng observable, isinasaalang-alang natin ang average na single-site magnetization, 1N∑i=1N⟨zi⟩\frac{1}{N} \sum_{i=1}^{N} \langle z_i \rangle, kung saan ang NN ay ang bilang ng mga spin.

# 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

I-simulate ang time evolution ng sistema gamit ang Pauli propagation​

Kapag mayroon na tayong circuit, UU, at observable, OO, madali nating mai-simulate ang sistema sa ilang hakbang:

  • Hatiin ang UU sa Clifford na bahagi nito, CC, at non-Clifford na bahagi, PP, para ang U=PCU=PC, gamit ang evolve_through_cliffords

  • I-propagate ang OO sa pamamagitan ng PP, na magreresulta sa bagong operator, O′O^\prime, gamit ang pauli_prop.propagate_through_circuit

  • I-evolve ang O′O^\prime sa Clifford na bahagi ng circuit gamit ang suporta sa Clifford evolution na built-in sa Qiskit

  • Tantiyahin ang expectation value bilang ⟨0∣O′∣0⟩≈⟨0∣U†OU∣0⟩\langle0|O^\prime|0\rangle \approx \langle0|U^\dagger OU|0\rangle sa pamamagitan ng pagsasama-sama ng mga coefficient sa O′O^\prime na nauugnay sa mga fully-diagonal na Pauli term (mga Pauli term na naglalaman ng I o Z sa lahat ng qubit). Tandaan, isa itong approximation dahil nag-truncate tayo ng mga term mula sa O′O^\prime habang pina-propagate ito sa non-Clifford na bahagi ng circuit.

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())
)

Habang nagpapatakbo tayo ng mas malalaking kalkulasyon, mas nagiging tumpak ang mga approximation ng expectation value. Sa halimbawang ito, napupuno natin ang buong Pauli space sa humigit-kumulang 410≈1064^{10}\approx10^6, na makikita sa pagpapatag ng kurba sa pagitan ng huling dalawang punto.

Bagama't monotonic ang convergence na ipinapakita ng plot sa ibaba, karaniwang hindi monotonic ang convergence ng mga Pauli propagation simulation. Hindi kakaiba na makakita ng "bumpy" na behavior sa ganitong uri ng mga plot.

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