ข้ามไปยังเนื้อหาหลัก
โครงการนี้อยู่ในช่วงเบต้า พบข้อผิดพลาด? สร้าง GitHub Issue มีคำถามหรือไอเดีย? ถามใน Discussions — ยินดีรับฟังความคิดเห็น!
คุณภาพการแปลในหน้านี้เป็นอย่างไร?

ใช้ Lp-norm ที่ต่างกันสำหรับการตัดพจน์ Pauli

หมายเหตุ: ก่อนอ่านคู่มือนี้ ควรอ่านคู่มือ Truncate Pauli terms ก่อน ซึ่งอธิบายการตัดทอนเทอม Pauli ที่มีน้ำหนักต่ำที่ติดตั้งอยู่ในเมธอด backpropagate โดยอิงตาม TruncationErrorBudget ที่กำหนด ในคู่มือนี้ คุณจะได้เรียนรู้เกี่ยวกับ keyword argument ของ backpropagate ชื่อ p_norm ซึ่งใช้เปลี่ยน Lp-norm ที่ใช้ประมาณค่าความคลาดเคลื่อนที่เกิดจากเทอม Pauli ที่ถูกตัดทอนได้

สร้างวงจรตัวอย่าง​

คู่มือนี้ใช้วงจรตัวอย่างเดียวกับในคู่มือ 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

กำหนด observable สำหรับแมกนีไทเซชันรวม:

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
)

เพื่อใช้อ้างอิง ให้คำนวณค่าคาดหมายที่แน่นอน:

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

ใช้ L1 norm​

โดยค่าเริ่มต้น และอย่างที่คุณเคยเห็นแล้วในคู่มือ Truncate Pauli terms ค่า p_norm=1 ซึ่งหมายความว่าความคลาดเคลื่อนถูกประมาณเป็น:

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

โดยที่ ψ\psi คือสถานะควอนตัม, Δ\Delta คือผลต่างจริงระหว่าง observable ที่แน่นอนกับที่ถูกตัดทอน (ซึ่งไม่ทราบค่า), T\mathcal{T} คือเซตของเทอม Pauli ที่ถูกตัดทอน และ cPc_P คือสัมประสิทธิ์ของเทอม Pauli อสมการนี้เป็นขอบเขตบนที่เข้มงวดแต่หลวมมากในสถานการณ์ส่วนใหญ่ คู่มือนี้ทำ backpropagate ให้ 6 slice ของวงจรตัวอย่าง โดยใช้ความคลาดเคลื่อนคงที่ต่อ slice เท่ากับ 0.001 ค่านี้ควรเข้าใจว่าเป็นงบประมาณภายใต้ p_norm ที่กำหนด

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.

ตอนนี้เราคำนวณค่าคาดหมายของ observable ที่ผ่านการ backpropagate รวมถึงความคลาดเคลื่อนเมื่อเทียบกับค่าอ้างอิงที่แน่นอนได้:

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

สุดท้าย เราพลอตความคลาดเคลื่อนที่เกิดขึ้นระหว่างการ backpropagate ของแต่ละ slice รวมถึงความคลาดเคลื่อนสะสมได้ ความคลาดเคลื่อนสะสมคือผลรวมของความคลาดเคลื่อนของแต่ละ slice จะเห็นว่าความคลาดเคลื่อนสะสมเป็นขอบเขตบนที่หลวมมากของความคลาดเคลื่อนจริง

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

ใช้ L2 norm​

อาจกล่าวได้ว่า L2 norm เป็นค่าประมาณของความคลาดเคลื่อนที่เกิดขึ้นได้ดีกว่า L1 norm เพราะเราสามารถสมมติว่าสถานะควอนตัม ∣ψ⟩|\psi\rangle ถูกสุ่มมาจาก Haar random ensemble ซึ่งในกรณีนั้นความคลาดเคลื่อนที่เกิดขึ้นจะมีการแจกแจงที่ค่าเฉลี่ยหายไป และมีความแปรปรวนที่ถูกจำกัดขอบเขตโดยประมาณได้ด้วย L2 norm:

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

แม้ขอบเขตนี้จะไม่เข้มงวด แต่จะถูกละเมิดเฉพาะในกรณีที่ผิดปกติเท่านั้น เราทำ backpropagate 6 slice ของวงจรตัวอย่างอีกครั้ง โดยใช้ความคลาดเคลื่อนสูงสุดต่อ slice เท่ากับ 0.001 (คราวนี้ตีความบน L2 norm)

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.

เราคำนวณค่าคาดหมายของ observable ที่ผ่านการ backpropagate และความคลาดเคลื่อนเมื่อเทียบกับค่าอ้างอิงที่แน่นอนอีกครั้ง:

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

การพลอตความคลาดเคลื่อนที่เกิดขึ้นต่อ slice และความคลาดเคลื่อนสะสมให้ภาพที่คล้ายกับก่อนหน้านี้

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

สังเกตว่าความคลาดเคลื่อนสะสมคือผลรวมของความคลาดเคลื่อนของแต่ละ slice อีกครั้ง นี่เป็นอีกขอบเขตที่หลวมเนื่องจากอสมการ Minkowski เพราะเราต้องคำนวณขอบเขตนี้แบบเวียนเกิด:

∣⟨ψ∣Δ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|

โดยที่ตัวห้อยใหม่ ii ระบุรอบการวนซ้ำของ slice ปัจจุบัน ทำให้ Δi\Delta_i เป็นความคลาดเคลื่อนจริงที่รอบ backpropagation ที่ ii, Δ~i−1\tilde{\Delta}_{i-1} เป็นความคลาดเคลื่อนจากการตัดทอนโดยประมาณจากรอบ i−1i-1 และ Ti\mathcal{T}_i เป็นเซตของเทอม Pauli ที่ถูกตัดทอนในรอบ ii