Lewati ke konten utama
Proyek ini masih dalam tahap beta. Menemukan bug? Buat isu GitHub. Punya pertanyaan atau ide? Tanya di Discussions — kami sangat menghargai masukan kamu!
Bagaimana kualitas terjemahan di halaman ini?

Pakai Lp-norm yang berbeda untuk pemotongan suku Pauli

Catatan: Sebelum membaca panduan ini, sebaiknya baca dulu panduan Truncate Pauli terms, yang menjelaskan pemangkasan suku Pauli berbobot rendah yang sudah tertanam di metode backpropagate berdasarkan TruncationErrorBudget yang ditentukan. Di panduan ini, kamu akan belajar tentang argumen kata kunci backpropagate, yaitu p_norm, yang bisa dipakai untuk mengubah norma Lp yang digunakan untuk memperkirakan error akibat suku Pauli yang dipangkas.

Membangun contoh circuit​

Panduan ini memakai contoh circuit yang sama seperti di panduan Truncate Pauli terms:

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

_needed = {"matplotlib": "matplotlib", "qiskit": "qiskit", "qiskit_addon_obp": "qiskit-addon-obp", "qiskit_addon_utils": "qiskit-addon-utils", "rustworkx": "rustworkx"}
_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 rustworkx.generators
from qiskit.synthesis import LieTrotter
from qiskit_addon_utils.problem_generators import (
PauliOrderStrategy,
generate_time_evolution_circuit,
generate_xyz_hamiltonian,
)
from qiskit_addon_utils.slicing import combine_slices, slice_by_gate_types

# Generate a linear chain of 10 qubits
num_qubits = 10
linear_chain = rustworkx.generators.path_graph(num_qubits)

# Use an arbitrary XY model
hamiltonian = generate_xyz_hamiltonian(
linear_chain,
coupling_constants=(0.05, 0.02, 0.0),
ext_magnetic_field=(0.02, 0.08, 0.0),
pauli_order_strategy=PauliOrderStrategy.InteractionThenColor,
)
# Evolve for some time
circuit = generate_time_evolution_circuit(
hamiltonian, synthesis=LieTrotter(reps=3), time=2.0
)
# slice the circuit by gate type
slices = slice_by_gate_types(circuit)

# For visualization purposes only, recombine the slices with barriers between them and draw the resulting circuit
combine_slices(slices, include_barriers=True).draw("mpl", fold=50, scale=0.6)

Output of the previous code cell

Definisikan observable untuk magnetisasi total:

from qiskit.quantum_info import SparsePauliOp

obs = SparsePauliOp.from_sparse_list(
[("Z", [i], 1.0) for i in range(num_qubits)], num_qubits=num_qubits
)

Sebagai acuan, hitung nilai ekspektasi yang tepat:

from qiskit.primitives import StatevectorEstimator

estimator = StatevectorEstimator()
job = estimator.run([(circuit, obs)])
res = job.result()
exact_exp = res[0].data.evs
print(exact_exp)
9.318197859862146

Gunakan norma L1​

Secara default, dan seperti yang sudah kamu lihat di panduan Truncate Pauli terms, p_norm=1, artinya error diperkirakan sebagai:

∣⟨ψ∣Δ∣ψ⟩∣≤∑P∈T∣cP∣|\langle\psi|\Delta|\psi\rangle| \leq \sum_{P\in\mathcal{T}} |c_P|

dengan ψ\psi adalah state kuantum, Δ\Delta adalah selisih sebenarnya antara observable yang tepat dan yang sudah dipangkas (yang tidak diketahui), T\mathcal{T} adalah himpunan suku Pauli yang dipangkas, dan cPc_P adalah koefisien suku Pauli. Ketidaksamaan ini adalah batas atas yang ketat secara matematis tapi sangat longgar di sebagian besar skenario. Panduan ini melakukan backpropagation pada enam slice dari contoh circuit, dengan error konstan per slice sebesar 0.001. Nilai ini dipahami sebagai budget dalam p_norm yang diberikan.

from qiskit_addon_obp.utils.truncating import setup_budget

l1_truncation_error_budget = setup_budget(max_error_per_slice=0.001, p_norm=1)
print(l1_truncation_error_budget)
TruncationErrorBudget(per_slice_budget=[0.001], max_error_total=inf, p_norm=1)
from qiskit_addon_obp import backpropagate

max_slices = 6
l1_bp_obs, l1_remaining_slices, l1_metadata = backpropagate(
obs,
slices[-max_slices:],
truncation_error_budget=l1_truncation_error_budget,
)
l1_reduced_circuit = combine_slices(
slices[:-max_slices] + l1_remaining_slices
)
print(
f"Backpropagated {max_slices - len(l1_remaining_slices)} circuit slices."
)
print(
f"New observable contains {len(l1_bp_obs)} terms and {len(l1_bp_obs.group_commuting(qubit_wise=True))} commuting groups."
)
Backpropagated 6 circuit slices.
New observable contains 116 terms and 10 commuting groups.

Sekarang kita bisa menghitung nilai ekspektasi dari observable hasil backpropagation, beserta error terhadap acuan yang tepat:

estimator = StatevectorEstimator()
job = estimator.run([(l1_reduced_circuit, l1_bp_obs)])
res = job.result()
l1_exp = res[0].data.evs
l1_error = exact_exp - l1_exp
print(l1_exp, l1_error)
9.317869899338842 0.00032796052330397174

Terakhir, kita bisa memplot error yang muncul selama backpropagation tiap slice, beserta error akumulasinya. Error akumulasi adalah jumlah dari error tiap slice. Kita bisa lihat bahwa error akumulasi merupakan batas atas yang sangat longgar terhadap error sebenarnya.

from matplotlib import pyplot as plt
from qiskit_addon_obp.utils.visualization import (
plot_accumulated_error,
plot_slice_errors,
)

fig, axes = plt.subplots(1, 2, figsize=(14, 5))
axes[1].plot([6], [l1_error], "x", color="red", label="actual error")
plot_slice_errors(l1_metadata, axes[0])
plot_accumulated_error(l1_metadata, axes[1])

Output of the previous code cell

Gunakan norma L2​

Bisa dibilang norma L2 adalah pendekatan yang lebih baik untuk error yang muncul dibanding norma L1. Sebabnya, kita bisa mengasumsikan state kuantum ∣ψ⟩|\psi\rangle diambil dari ensemble acak Haar, yang dalam hal ini error yang muncul mengikuti distribusi dengan rata-rata nol dan varians yang kira-kira bisa dibatasi oleh norma L2:

∣⟨ψ∣Δ∣ψ⟩∣≲(∑P∈T∣cP∣2)1/2|\langle\psi|\Delta|\psi\rangle| \lesssim \left( \sum_{P\in\mathcal{T}} |c_P|^2 \right)^{1/2}

Meski batas ini tidak ketat secara matematis, batas ini hanya akan dilanggar pada kasus patologis. Kita kembali melakukan backpropagation pada enam slice dari contoh circuit, dengan error maksimum per slice sebesar 0.001 (kali ini diartikan pada norma L2).

l2_truncation_error_budget = setup_budget(max_error_per_slice=0.001, p_norm=2)
print(l2_truncation_error_budget)
TruncationErrorBudget(per_slice_budget=[0.001], max_error_total=inf, p_norm=2)
max_slices = 6
l2_bp_obs, l2_remaining_slices, l2_metadata = backpropagate(
obs,
slices[-max_slices:],
truncation_error_budget=l2_truncation_error_budget,
)
l2_reduced_circuit = combine_slices(
slices[:-max_slices] + l2_remaining_slices
)
print(
f"Backpropagated {max_slices - len(l2_remaining_slices)} circuit slices."
)
print(
f"New observable contains {len(l2_bp_obs)} terms and {len(l2_bp_obs.group_commuting(qubit_wise=True))} commuting groups."
)
Backpropagated 6 circuit slices.
New observable contains 84 terms and 6 commuting groups.

Sekali lagi, kita hitung nilai ekspektasi dari observable hasil backpropagation dan error terhadap acuan yang tepat:

estimator = StatevectorEstimator()
job = estimator.run([(l2_reduced_circuit, l2_bp_obs)])
res = job.result()
l2_exp = res[0].data.evs
l2_error = exact_exp - l2_exp
print(l2_exp, l2_error)
9.317829770853422 0.00036808900872387085

Memplot error yang muncul per slice dan error akumulasi menghasilkan gambaran yang mirip seperti sebelumnya.

fig, axes = plt.subplots(1, 2, figsize=(14, 5))
axes[1].plot([6], [l2_error], "x", color="red", label="actual error")
plot_slice_errors(l2_metadata, axes[0])
plot_accumulated_error(l2_metadata, axes[1])

Output of the previous code cell

Perhatikan bahwa error akumulasi lagi-lagi adalah jumlah dari error tiap slice. Ini adalah batas longgar lainnya akibat ketidaksamaan Minkowski, karena kita harus menghitung batas ini secara rekursif:

∣⟨ψ∣Δi∣ψ⟩∣≤∣⟨ψ∣Δ~i−1∣ψ⟩∣+(∑P∈Ti∣cP∣2)1/2=∣⟨ψ∣Δ~i∣ψ⟩∣|\langle\psi|\Delta_{i}|\psi\rangle| \leq |\langle\psi|\tilde{\Delta}_{i-1}|\psi\rangle| + \left( \sum_{P\in\mathcal{T_i}} |c_P|^2 \right)^{1/2} = |\langle\psi|\tilde{\Delta}_{i}|\psi\rangle|

dengan subskrip baru ii menunjukkan iterasi slice saat ini, sehingga Δi\Delta_i adalah error sebenarnya pada iterasi backpropagation ii, Δ~i−1\tilde{\Delta}_{i-1} adalah error pemangkasan hasil pendekatan dari iterasi i−1i-1, dan Ti\mathcal{T}_i adalah himpunan suku Pauli yang dipangkas pada iterasi ii.