Gunakan norma Lp yang berbeza untuk pemangkasan sebutan Pauli
Nota: Sebelum membaca panduan ini, anda harus membaca panduan Truncate Pauli terms, yang menerangkan pemangkasan sebutan Pauli berpemberat rendah yang terbina dalam kaedah backpropagate berdasarkan TruncationErrorBudget yang ditetapkan.
Dalam panduan ini, anda akan mempelajari tentang argumen kata kunci backpropagate, p_norm, yang boleh digunakan untuk menukar norma Lp yang digunakan bagi menganggar ralat yang timbul daripada sebutan Pauli yang dipangkas.
Bina litar contoh
Panduan ini menggunakan litar contoh yang sama seperti dalam 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)

Tentukan observable untuk jumlah kemagnetan:
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 rujukan, hitung nilai jangkaan 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 lalai, dan seperti yang telah anda lihat dalam panduan Truncate Pauli terms, p_norm=1, yang bermaksud ralat dianggarkan sebagai:
dengan ialah keadaan kuantum, ialah perbezaan sebenar antara observable yang tepat dan yang dipangkas (yang tidak diketahui), ialah set sebutan Pauli yang dipangkas, dan ialah pekali sebutan Pauli.
Ketaksamaan ini ialah had atas yang tegar tetapi sangat longgar untuk kebanyakan senario.
Panduan ini melakukan perambatan balik enam hirisan litar contoh, menggunakan ralat malar bagi setiap hirisan sebanyak 0.001. Nilai ini harus difahami sebagai bajet 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.
Kini kita boleh mengira nilai jangkaan observable yang dirambat balik, serta ralat berbanding rujukan 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
Akhir sekali, kita boleh memplot ralat yang timbul semasa perambatan balik setiap hirisan, serta ralat terkumpul. Ralat terkumpul ialah jumlah ralat hirisan. Kita dapat melihat bahawa ralat terkumpul ialah had atas yang sangat longgar bagi ralat sebenar.
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])

Gunakan norma L2
Boleh dihujahkan bahawa norma L2 ialah anggaran yang lebih baik bagi ralat yang timbul berbanding norma L1. Ini kerana kita boleh menganggap keadaan kuantum diambil daripada ensemble rawak Haar, dan dalam hal ini ralat yang timbul mengikut taburan dengan min yang lenyap dan varians yang boleh dihadkan secara anggaran oleh norma L2:
Walaupun had ini tidak tegar, ia hanya akan dilanggar dalam kes patologi.
Sekali lagi kita merambat balik enam hirisan litar contoh, menggunakan ralat maksimum bagi setiap hirisan sebanyak 0.001 (kali ini, ditafsirkan 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 mengira nilai jangkaan observable yang dirambat balik dan ralat berbanding rujukan 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 ralat yang timbul bagi setiap hirisan dan ralat terkumpul menghasilkan gambaran yang serupa seperti sebelum ini.
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])

Perhatikan bahawa ralat terkumpul sekali lagi ialah jumlah ralat setiap hirisan. Ini ialah had longgar yang lain disebabkan ketaksamaan Minkowski, kerana kita perlu mengira had ini secara rekursif:
dengan subskrip baharu menunjukkan lelaran hirisan semasa, menjadikan ralat sebenar pada lelaran perambatan balik , ralat pemangkasan yang dianggarkan daripada lelaran , dan set sebutan Pauli yang dipangkas pada lelaran .