Швидкий старт
title: Швидкий старт description: Посібник зі швидкого старту для пакета pauli-prop з Qiskit addons
У цьому посібнику ми використовуємо пакет pauli-prop, щоб класично змоделювати часову динаміку 10-кубітної моделі Ізінга з імпульсним збудженням на одновимірному ланцюжку спінів.
Підготуй вхідні дані для Pauli propagation
Розглядається такий гамільтоніан:
де описує зв'язок між найближчими сусідніми спінами, , а — глобальне поперечне поле. Тротерівський розклад першого порядку оператора часової еволюції буде реалізовано як квантову схему, , на тротерівських кроках. Константу зв'язку, , буде зафіксовано як , а — як . Взаємодії буде реалізовано за допомогою гейтів Кліффорда (, , ).
Ми реалізуємо тротеризовану часову еволюцію як квантову схему та використовуємо для не-кліффордових обертань навколо осі x. Чим далі ці кути від кутів Кліффорда (наприклад, ), тим складніше буде змоделювати систему методами Pauli propagation.
Як спостережувану ми обираємо середню намагніченість на одному вузлі, , де — кількість спінів.
# 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)
Змоделюй часову еволюцію системи за допомогою Pauli propagation
Коли в нас є схема, , і спостережувана, , ми можемо легко змоделювати систему за кілька кроків:
-
Розділи на кліффордову, , і не-кліффордову, , частини так, щоб , за допомогою
evolve_through_cliffords -
Поширюй крізь , отримуючи новий оператор, , за допомогою
pauli_prop.propagate_through_circuit -
Еволюціонуй крізь кліффордову частину схеми за допомогою підтримки еволюції Кліффорда, вбудованої в Qiskit
-
Наближено оціни математичне сподівання як , підсумувавши коефіцієнти в , пов'язані з повністю діагональними паулівськими доданками (паулівські доданки, що містять на всіх кубітах лише
IабоZ). Пам'ятай, що це наближення, адже ми відкидали доданки з , поширюючи його крізь не-кліффордову частину схеми.
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())
)
Коли ми запускаємо більші обчислення, наближення математичного сподівання стають точнішими. У цьому прикладі ми насичуємо повний паулівський простір приблизно на , що відображається в вирівнюванні кривої між двома останніми точками.
Хоча графік нижче показує монотонну збіжність, симуляції Pauli propagation загалом збігаються немонотонно. Бачити «нерівну» поведінку на таких графіках — звичайна річ.
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')

