Pornire rapidă
title: Pornire rapidă description: Un ghid de pornire rapidă pentru pachetul de addon-uri Qiskit pauli-prop
În acest ghid folosim pachetul pauli-prop pentru a simula clasic dinamica în timp a unui model Ising cu lovituri (kicked Ising) cu 10 qubiți pe un lanț de spini 1D.
Pregătește datele de intrare pentru propagarea Pauli
Hamiltonianul considerat este:
unde descrie cuplajul dintre spinii vecini cei mai apropiați, , iar este câmpul transversal global. O descompunere Trotter de ordinul întâi a operatorului evoluat în timp va fi implementată ca un circuit cuantic, , pe parcursul a de pași Trotter. Constanta de cuplaj, , va fi fixată la , iar va fi fixat la . Interacțiunile vor fi implementate folosind porți Clifford (, , ).
Implementăm evoluția în timp Trotterizată ca un circuit cuantic și folosim pentru rotațiile non-Clifford în jurul axei x. Cu cât aceste unghiuri sunt mai departe de unghiurile Clifford (de exemplu, ), cu atât sistemul va fi mai greu de simulat prin metodele de propagare Pauli.
Ca observabilă, considerăm magnetizarea medie pe un singur situs, , unde este numărul de spini.
# 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)
Simulează evoluția în timp a sistemului cu propagare Pauli
Odată ce avem circuitul, , și observabila, , putem simula ușor sistemul în câțiva pași:
-
Separă în partea sa Clifford, , și partea non-Clifford, , astfel încât , folosind
evolve_through_cliffords -
Propagă prin , rezultând un nou operator, , folosind
pauli_prop.propagate_through_circuit -
Evoluează prin partea Clifford a circuitului folosind suportul pentru evoluție Clifford integrat în Qiskit
-
Aproximează valoarea de așteptare ca prin însumarea coeficienților din asociați termenilor Pauli complet diagonali (termeni Pauli care conțin fie
I, fieZpe toți qubiții). Reține că aceasta este o aproximare, deoarece am trunchiat termeni din în timp ce l-am propagat prin partea non-Clifford a circuitului.
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())
)
Pe măsură ce rulăm calcule mai mari, aproximările valorii de așteptare devin mai precise. În acest exemplu saturăm întregul spațiu Pauli în jurul valorii , ceea ce se reflectă în aplatizarea curbei între ultimele două puncte.
Deși graficul de mai jos arată o convergență monotonă, simulările cu propagare Pauli nu converg în general monoton. Nu este neobișnuit să vezi un comportament „neregulat” în astfel de grafice.
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')

