Sari la conținutul principal
Acest proiect este în versiune beta. Ai găsit o eroare? Deschide un issue pe GitHub. Ai o întrebare sau o idee? Întreabă în Discussions — ne-ar plăcea să aflăm părerea ta!
Cum este calitatea traducerii pe această pagină?

Folosește diferite norme Lp pentru trunchierea termenilor Pauli

Notă: Înainte de a citi acest ghid, ar trebui să citești ghidul Truncate Pauli terms, care descrie trunchierea termenilor Pauli de pondere mică, integrată în metoda backpropagate pe baza unui TruncationErrorBudget specificat. În acest ghid vei învăța despre argumentul cuvânt-cheie p_norm al metodei backpropagate, care poate fi folosit pentru a schimba norma Lp utilizată la estimarea erorii introduse de termenii Pauli trunchiați.

Construiește un circuit exemplu​

Acest ghid folosește același circuit exemplu ca ghidul 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

Definește o observabilă pentru magnetizarea 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
)

Pentru referință, calculează valoarea de așteptare exactă:

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

Folosește norma L1​

Implicit, și așa cum ai văzut deja în ghidul Truncate Pauli terms, p_norm=1, ceea ce înseamnă că eroarea este estimată astfel:

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

unde ψ\psi este starea cuantică, Δ\Delta este diferența reală dintre observabila exactă și cea trunchiată (care este necunoscută), T\mathcal{T} este mulțimea termenilor Pauli care au fost trunchiați, iar cPc_P este coeficientul termenului Pauli. Această inegalitate este o margine superioară riguroasă, dar foarte largă în majoritatea scenariilor. Acest ghid aplică backpropagation pe șase felii ale circuitului exemplu, folosind o eroare constantă de 0.001 pe felie. Această valoare trebuie înțeleasă ca bugetul în cadrul p_norm dat.

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.

Acum putem calcula valoarea de așteptare a observabilei retropropagate, precum și eroarea față de referința exactă:

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

În final, putem reprezenta grafic eroarea introdusă în timpul retropropagării fiecărei felii, precum și eroarea acumulată. Eroarea acumulată este suma erorilor feliilor. Putem vedea că eroarea acumulată este o margine superioară foarte largă a erorii reale.

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

Folosește norma L2​

Se poate argumenta că norma L2 aproximează mai bine eroarea introdusă decât norma L1. Aceasta deoarece putem presupune că starea cuantică ∣ψ⟩|\psi\rangle este extrasă dintr-un ansamblu aleatoriu Haar, caz în care eroarea introdusă urmează o distribuție cu media nulă și o varianță care poate fi aproximativ mărginită de 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}

Deși marginea nu este riguroasă, ea va fi încălcată doar în cazuri patologice. Retropropagăm din nou șase felii ale circuitului exemplu, folosind o eroare maximă de 0.001 pe felie (de data aceasta, interpretată în 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.

Din nou, calculăm valoarea de așteptare a observabilei retropropagate și eroarea față de referința exactă:

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

Reprezentarea grafică a erorilor introduse pe felie și a erorii acumulate produce o imagine similară cu cea de dinainte.

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

Reține că eroarea acumulată este din nou suma erorilor feliilor individuale. Aceasta este o altă margine largă, din cauza inegalității Minkowski, deoarece trebuie să calculăm această margine recursiv:

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

unde noul indice ii indică iterația curentă a feliei, făcând din Δi\Delta_i eroarea reală la iterația de retropropagare ii, din Δ~i−1\tilde{\Delta}_{i-1} eroarea de trunchiere aproximată din iterația i−1i-1, iar din Ti\mathcal{T}_i mulțimea termenilor Pauli trunchiați la iterația ii.