Operator backpropagation (OBP) untuk estimasi nilai ekspektasi
Estimasi penggunaan: 4 menit pada prosesor Heron r3 (CATATAN: Ini hanya estimasi. Waktu berjalan kamu bisa berbeda.)
Hasil pembelajaran
Setelah menyelesaikan tutorial ini, pengguna diharapkan memahami:
- Cara menggunakan
qiskit-addon-obpuntuk mengurangi kedalaman Circuit kuantum dengan biaya berupa peningkatan jumlah eksekusi Circuit - Cara menggunakan
qiskit-addon-utilsuntuk membangun Hamiltonian XYZ dan Circuit evolusi waktunya
Prasyarat
Kami menyarankan pengguna sudah familiar dengan topik-topik berikut sebelum menjalankan tutorial ini:
- Menggunakan primitif Estimator untuk menghitung nilai ekspektasi dari suatu observable
Latar Belakang
Operator backpropagation adalah teknik yang melibatkan penyerapan operasi dari akhir Circuit kuantum ke dalam observable yang diukur, sehingga secara umum mengurangi kedalaman Circuit dengan biaya berupa tambahan suku pada observable. Tujuannya adalah untuk membackpropagasi sebanyak mungkin Circuit tanpa membiarkan observable tumbuh terlalu besar. Implementasi berbasis Qiskit tersedia di addon OBP Qiskit. Baca dokumentasi terkait untuk informasi lebih lanjut.
Perhatikan contoh Circuit yang di dalamnya observable akan diukur, di mana adalah Pauli dan adalah koefisien. Mari kita notasikan Circuit tersebut sebagai uniter tunggal , yang secara logis dapat dibagi menjadi seperti yang ditunjukkan pada gambar di bawah.

Operator backpropagation menyerap uniter ke dalam observable dengan mengevolusinya sebagai . Dengan kata lain, sebagian komputasi dilakukan secara klasikal melalui evolusi observable dari ke . Masalah semula kini dapat diformulasikan ulang sebagai pengukuran observable untuk Circuit baru yang memiliki kedalaman lebih rendah dengan uniter .
Uniter direpresentasikan sebagai sejumlah irisan . Ada beberapa cara untuk mendefinisikan sebuah irisan. Misalnya, pada Circuit contoh di atas, setiap lapisan dan setiap lapisan Gate dapat dianggap sebagai irisan individual. Backpropagation melibatkan kalkulasi secara klasikal. Setiap irisan dapat direpresentasikan sebagai , di mana adalah Pauli -Qubit dan adalah skalar. Mudah untuk diverifikasi bahwa
Pada contoh di atas, jika , maka kita perlu menjalankan dua Circuit kuantum, alih-alih satu, untuk menghitung nilai ekspektasi. Oleh karena itu, backpropagation dapat meningkatkan jumlah suku dalam observable, sehingga berpotensi meningkatkan jumlah eksekusi Circuit. Salah satu cara untuk memungkinkan backpropagation lebih dalam ke Circuit, sambil mencegah operator tumbuh terlalu besar, adalah dengan memangkas suku-suku yang memiliki koefisien kecil, daripada menambahkannya ke operator. Misalnya, pada contoh di atas, seseorang dapat memilih untuk memangkas suku yang melibatkan selama cukup kecil. Memangkas suku dapat menghasilkan lebih sedikit Circuit kuantum yang perlu dieksekusi, namun hal ini menghasilkan beberapa kesalahan dalam kalkulasi nilai ekspektasi akhir yang sebanding dengan besarnya koefisien suku-suku yang dipangkas.
Persyaratan
Sebelum memulai tutorial ini, pastikan kamu telah menginstal hal-hal berikut:
- Qiskit SDK v2.0 atau lebih baru, dengan dukungan visualisasi
- Qiskit Runtime v0.22 atau lebih baru (
pip install qiskit-ibm-runtime) - OBP Qiskit addon 0.3 atau lebih baru (
pip install qiskit-addon-obp) - Qiskit addon utils 0.3 atau lebih baru (
pip install qiskit-addon-utils)
Pengaturan
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-addon-obp qiskit-addon-utils qiskit-ibm-runtime rustworkx
import numpy as np
import matplotlib.pyplot as plt
from qiskit.primitives import StatevectorEstimator
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import CouplingMap
from qiskit.synthesis import LieTrotter
from qiskit_addon_utils.problem_generators import generate_xyz_hamiltonian
from qiskit_addon_utils.problem_generators import (
generate_time_evolution_circuit,
)
from qiskit_addon_utils.slicing import slice_by_depth, combine_slices
from qiskit_addon_obp.utils.simplify import OperatorBudget
from qiskit_addon_obp import backpropagate
from qiskit_addon_obp.utils.truncating import setup_budget
from rustworkx.visualization import graphviz_draw
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorV2, EstimatorOptions
Contoh simulator skala kecil
Tutorial ini mengimplementasikan pola Qiskit untuk mensimulasikan dinamika kuantum rantai spin Heisenberg menggunakan addon OBP Qiskit. Perlu dicatat bahwa pada simulator tanpa derau, nilai ekspektasi yang diperoleh dengan dan tanpa backpropagation akan sama.
Langkah 1: Petakan input klasikal ke masalah kuantum
Petakan evolusi waktu model kuantum Heisenberg ke eksperimen kuantum
Pertama, kita akan menggunakan fungsi generate_xyz_hamiltonian dari qiskit-addon-utils untuk menghasilkan Hamiltonian seperti Heisenberg pada graf konektivitas tertentu. Graf ini bisa berupa rustworkx.PyGraph atau CouplingMap. Berikut ini, kita akan menggunakan CouplingMap rantai linier dari 10 qubit.
num_qubits = 10
layout = [(i - 1, i) for i in range(1, num_qubits)]
# Instantiate a CouplingMap object
coupling_map = CouplingMap(layout)
graphviz_draw(coupling_map.graph, method="circo")
Selanjutnya, kita membuat operator Pauli yang memodelkan Hamiltonian Heisenberg XYZ:
di mana adalah graf dari coupling map. Untuk tutorial ini, kita menggunakan masing-masing sebesar , dan masing-masing sebesar .
# Get a qubit operator describing the Heisenberg XYZ model
hamiltonian = generate_xyz_hamiltonian(
coupling_map,
coupling_constants=(np.pi / 8, np.pi / 4, np.pi / 2),
ext_magnetic_field=(np.pi / 3, np.pi / 6, np.pi / 9),
)
print(hamiltonian)
SparsePauliOp(['IIIIIIIXXI', 'IIIIIIIYYI', 'IIIIIIIZZI', 'IIIIIXXIII', 'IIIIIYYIII', 'IIIIIZZIII', 'IIIXXIIIII', 'IIIYYIIIII', 'IIIZZIIIII', 'IXXIIIIIII', 'IYYIIIIIII', 'IZZIIIIIII', 'IIIIIIIIXX', 'IIIIIIIIYY', 'IIIIIIIIZZ', 'IIIIIIXXII', 'IIIIIIYYII', 'IIIIIIZZII', 'IIIIXXIIII', 'IIIIYYIIII', 'IIIIZZIIII', 'IIXXIIIIII', 'IIYYIIIIII', 'IIZZIIIIII', 'XXIIIIIIII', 'YYIIIIIIII', 'ZZIIIIIIII', 'IIIIIIIIIX', 'IIIIIIIIIY', 'IIIIIIIIIZ', 'IIIIIIIIXI', 'IIIIIIIIYI', 'IIIIIIIIZI', 'IIIIIIIXII', 'IIIIIIIYII', 'IIIIIIIZII', 'IIIIIIXIII', 'IIIIIIYIII', 'IIIIIIZIII', 'IIIIIXIIII', 'IIIIIYIIII', 'IIIIIZIIII', 'IIIIXIIIII', 'IIIIYIIIII', 'IIIIZIIIII', 'IIIXIIIIII', 'IIIYIIIIII', 'IIIZIIIIII', 'IIXIIIIIII', 'IIYIIIIIII', 'IIZIIIIIII', 'IXIIIIIIII', 'IYIIIIIIII', 'IZIIIIIIII', 'XIIIIIIIII', 'YIIIIIIIII', 'ZIIIIIIIII'],
coeffs=[0.39269908+0.j, 0.78539816+0.j, 1.57079633+0.j, 0.39269908+0.j,
0.78539816+0.j, 1.57079633+0.j, 0.39269908+0.j, 0.78539816+0.j,
1.57079633+0.j, 0.39269908+0.j, 0.78539816+0.j, 1.57079633+0.j,
0.39269908+0.j, 0.78539816+0.j, 1.57079633+0.j, 0.39269908+0.j,
0.78539816+0.j, 1.57079633+0.j, 0.39269908+0.j, 0.78539816+0.j,
1.57079633+0.j, 0.39269908+0.j, 0.78539816+0.j, 1.57079633+0.j,
0.39269908+0.j, 0.78539816+0.j, 1.57079633+0.j, 1.04719755+0.j,
0.52359878+0.j, 0.34906585+0.j, 1.04719755+0.j, 0.52359878+0.j,
0.34906585+0.j, 1.04719755+0.j, 0.52359878+0.j, 0.34906585+0.j,
1.04719755+0.j, 0.52359878+0.j, 0.34906585+0.j, 1.04719755+0.j,
0.52359878+0.j, 0.34906585+0.j, 1.04719755+0.j, 0.52359878+0.j,
0.34906585+0.j, 1.04719755+0.j, 0.52359878+0.j, 0.34906585+0.j,
1.04719755+0.j, 0.52359878+0.j, 0.34906585+0.j, 1.04719755+0.j,
0.52359878+0.j, 0.34906585+0.j, 1.04719755+0.j, 0.52359878+0.j,
0.34906585+0.j])
Dari operator qubit, kita bisa membuat Circuit kuantum yang memodelkan evolusi waktunya. Kita menggunakan generate_time_evolution_circuit dengan dekomposisi Lie Trotter untuk membangun Circuit evolusi waktu.
circuit = generate_time_evolution_circuit(
hamiltonian,
time=0.2,
synthesis=LieTrotter(reps=2),
)
circuit.draw("mpl", style="iqp", fold=-1)

Langkah 2: Optimalkan masalah untuk eksekusi hardware kuantum
Buat irisan Circuit untuk dibackpropagasi
Fungsi backpropagate membackpropagasi seluruh irisan Circuit sekaligus. Oleh karena itu, pilihan cara memotong dapat berdampak pada seberapa baik backpropagation bekerja untuk masalah tertentu. Di sini, kita akan mengelompokkan Gate dengan tipe yang sama ke dalam irisan menggunakan fungsi slice_by_depth.
Untuk diskusi lebih detail tentang pemotongan Circuit, cek panduan how-to dari paket qiskit-addon-utils.
slices = slice_by_depth(circuit, max_slice_depth=1)
print(f"Separated the circuit into {len(slices)} slices.")
Separated the circuit into 18 slices.
Batasi seberapa besar operator dapat tumbuh selama backpropagation
Selama backpropagation, jumlah suku dalam operator secara umum akan mendekati dengan cepat, di mana adalah jumlah irisan. Ketika dua suku dalam operator tidak berkomutasi secara qubit-wise, kita memerlukan Circuit terpisah untuk mendapatkan nilai ekspektasi yang sesuai dengan keduanya. Misalnya, jika kita memiliki observable 2-qubit , maka karena , pengukuran dalam satu basis sudah cukup untuk menghitung nilai ekspektasi kedua suku ini. Namun, anti-berkomutasi dengan dua suku lainnya, sehingga kita memerlukan pengukuran basis terpisah untuk menghitung nilai ekspektasi . Dengan kata lain, kita memerlukan dua Circuit, bukan satu, untuk menghitung . Seiring bertambahnya jumlah suku dalam operator, ada kemungkinan jumlah eksekusi Circuit yang diperlukan juga meningkat.
Ukuran operator dapat dibatasi dengan menentukan argumen kata kunci operator_budget dari fungsi backpropagate, yang menerima instance OperatorBudget.
Untuk mengontrol jumlah sumber daya tambahan (jumlah eksekusi Circuit, dan dengan demikian waktu QPU yang dibutuhkan) yang dialokasikan, kita membatasi jumlah maksimum grup Pauli yang berkomutasi secara qubit-wise yang boleh dimiliki observable yang telah dibackpropagasi. Di sini kita tentukan bahwa backpropagation harus berhenti ketika jumlah grup Pauli yang berkomutasi secara qubit-wise dalam operator melebihi delapan.
op_budget = OperatorBudget(max_qwc_groups=8)
Backpropagasi irisan dari Circuit
Pertama kita tentukan observable sebagai , di mana adalah jumlah qubit. Kita akan membackpropagasi irisan dari Circuit evolusi waktu hingga suku-suku dalam observable tidak lagi dapat digabungkan menjadi delapan grup Pauli yang berkomutasi secara qubit-wise atau lebih sedikit.
observable = SparsePauliOp.from_sparse_list(
[("Z", [i], 1 / num_qubits) for i in range(num_qubits)],
num_qubits=num_qubits,
)
observable
SparsePauliOp(['IIIIIIIIIZ', 'IIIIIIIIZI', 'IIIIIIIZII', 'IIIIIIZIII', 'IIIIIZIIII', 'IIIIZIIIII', 'IIIZIIIIII', 'IIZIIIIIII', 'IZIIIIIIII', 'ZIIIIIIIII'],
coeffs=[0.1+0.j, 0.1+0.j, 0.1+0.j, 0.1+0.j, 0.1+0.j, 0.1+0.j, 0.1+0.j, 0.1+0.j,
0.1+0.j, 0.1+0.j])
Di bawah ini kamu akan melihat bahwa kita telah membackpropagasi enam irisan, dan suku-sukunya digabungkan menjadi enam, bukan delapan grup. Ini berarti membackpropagasi satu irisan lagi akan menyebabkan jumlah grup Pauli melebihi delapan. Kita dapat memverifikasi bahwa hal ini memang terjadi dengan memeriksa metadata yang dikembalikan. Perlu dicatat juga bahwa pada bagian ini transformasi Circuit bersifat eksak. Artinya, tidak ada suku dari observable baru yang dipangkas. Circuit yang telah dibackpropagasi dan operator yang telah dibackpropagasi memberikan hasil yang sama persis dengan Circuit dan operator aslinya.
# Backpropagate slices onto the observable
bp_obs, remaining_slices, metadata = backpropagate(
observable, slices, operator_budget=op_budget
)
# Recombine the slices remaining after backpropagation
bp_circuit = combine_slices(remaining_slices)
print(f"Backpropagated {metadata.num_backpropagated_slices} slices.")
print(
f"New observable has {len(bp_obs.paulis)} terms, which can be combined into "
f"{len(bp_obs.group_commuting(qubit_wise=True))} groups."
)
print(
f"Note that backpropagating one more slice would result in "
f"{metadata.backpropagation_history[-1].num_paulis[0]} terms "
f"across {metadata.backpropagation_history[-1].num_qwc_groups} groups."
)
print("The remaining circuit after backpropagation looks as follows:")
bp_circuit.draw("mpl", fold=-1, scale=0.6)
Backpropagated 6 slices.
New observable has 60 terms, which can be combined into 6 groups.
Note that backpropagating one more slice would result in 114 terms across 12 groups.
The remaining circuit after backpropagation looks as follows:
Untuk contoh skala kecil pada simulator, kita tidak akan menggunakan pemangkasan. Hal ini karena tanpa adanya derau, Circuit dengan dan tanpa backpropagation menghasilkan hasil yang sama, dan pemangkasan justru memperburuk hasil karena adanya aproksimasi tambahan.
Transpile Circuit ke basis gate set
Sekarang kita men-transpile Circuit asli dan Circuit yang telah dibackpropagasi ke basis gate backend. Kita tidak perlu men-transpile ke backend asli karena kita akan menjalankan di simulator untuk instance skala kecil ini.
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=133
)
print(backend)
<IBMBackend('ibm_kingston')>
pm_basis = generate_preset_pass_manager(
optimization_level=3, basis_gates=backend.configuration().basis_gates
)
isa_circuit = pm_basis.run(circuit)
isa_bp_circuit = pm_basis.run(bp_circuit)
Langkah 3: Eksekusi menggunakan primitif Qiskit
Pertama, kita membuat dua Primitive Unified Bloc (PUB) yang sesuai dengan Circuit asli dan Circuit yang telah dibackpropagasi. Kemudian kita menjalankan pub tersebut pada Estimator ideal untuk mendapatkan nilai ekspektasi.
pubs = [(isa_circuit, observable), (isa_bp_circuit, bp_obs)]
rng = np.random.default_rng()
estimator = StatevectorEstimator(seed=rng)
job = estimator.run(pubs)
Langkah 4: Pasca-proses dan kembalikan hasil ke format klasikal yang diinginkan
Sekarang kita mendapatkan nilai ekspektasi dari Circuit asli dan Circuit yang telah dibackpropagasi.
primitive_result = job.result()
circuit_expval = primitive_result[0].data.evs.item()
bp_circuit_expval = primitive_result[1].data.evs.item()
methods = [
"No backpropagation",
"Backpropagation",
]
values = [circuit_expval, bp_circuit_expval]
ax = plt.gca()
plt.bar(methods, values, color="#a56eff", width=0.4, edgecolor="#8a3ffc")
ax.set_ylim([0.6, 0.92])
ax.set_ylabel(r"$M_Z$", fontsize=12)
Text(0, 0.5, '$M_Z$')
Seperti yang diharapkan, kedua nilai ekspektasi tersebut sepakat. Karena kita menjalankan di simulator statevector tanpa derau, backpropagation adalah transformasi eksak dari pasangan Circuit-observable, sehingga alur kerja asli dan yang telah dibackpropagasi harus menghasilkan nilai yang sama. Manfaat backpropagation baru terlihat pada hardware yang berisik, di mana Circuit yang lebih pendek setelah backpropagasi mengakumulasi lebih sedikit kesalahan, sebagaimana diilustrasikan pada contoh hardware skala besar di bawah ini.
Contoh hardware skala besar
Saat mengembangkan eksperimen, berguna untuk memulai dengan Circuit kecil agar visualisasi dan simulasi lebih mudah. Sekarang kita melihat operator backpropagation untuk Hamiltonian Heisenberg 50-qubit dengan nilai yang sama untuk parameter dan serta observable yang sama, tetapi untuk empat langkah Trotter. Nilai ekspektasi ideal pada skala ini tidak dapat dihitung dengan metode brute force, sehingga kita menggunakan tensor network dan memperoleh nilai ekspektasi ideal sebesar .
Selain backpropagation, pada contoh skala besar ini kita juga memperkenalkan backpropagation dengan pemangkasan. Idealnya kita ingin membackpropagasi sebanyak mungkin untuk mengurangi kedalaman Circuit efektif. Namun, hal ini sering kali menyebabkan banyaknya suku yang tidak berkomutasi dalam observable yang diperbarui, sehingga meningkatkan overhead kuantum. Oleh karena itu, kita dapat menghilangkan suku-suku observable dengan koefisien kecil menggunakan praktik yang disebut pemangkasan. Sementara pemangkasan memungkinkan propagasi lebih banyak dengan mengurangi jumlah suku dalam observable yang diperbarui, pemangkasan juga memperkenalkan beberapa aproksimasi. Oleh karena itu, perlu membatasi pemangkasan dalam batas tertentu agar kesalahan aproksimasi tidak mengalahkan pengurangan derau yang diperoleh dari backpropagation yang lebih dalam.
Untuk membatasi jumlah pemangkasan, kita mengalokasikan anggaran kesalahan untuk setiap irisan sekaligus total anggaran kesalahan untuk seluruh Circuit yang telah dibackpropagasi menggunakan fungsi setup_budget. Ini memastikan bahwa pemangkasan terkontrol untuk setiap irisan maupun untuk keseluruhan Circuit. Lihat juga panduan ini untuk cara lain mengalokasikan anggaran.
num_qubits = 50
layout = [(i - 1, i) for i in range(1, num_qubits)]
# Instantiate a CouplingMap object
coupling_map = CouplingMap(layout)
hamiltonian = generate_xyz_hamiltonian(
coupling_map,
coupling_constants=(np.pi / 8, np.pi / 4, np.pi / 2),
ext_magnetic_field=(np.pi / 3, np.pi / 6, np.pi / 9),
)
# Generate a time evolution circuit for the Hamiltonian
circuit = generate_time_evolution_circuit(
hamiltonian,
time=0.2,
synthesis=LieTrotter(reps=4),
)
# Define the observable to measure
observable = SparsePauliOp.from_sparse_list(
[("Z", [i], 1 / num_qubits) for i in range(num_qubits)],
num_qubits,
)
slices = slice_by_depth(circuit, max_slice_depth=1)
# Define the maximum number of qwc groups allowed in the
# backpropagated observable,
# and the truncation error budget
op_budget = OperatorBudget(max_qwc_groups=15)
truncation_error_budget = setup_budget(
max_error_total=0.03, max_error_per_slice=0.005
)
# First backpropagation without truncation
bp_obs, remaining_slices, metadata = backpropagate(
observable, slices, operator_budget=op_budget
)
bp_circuit = combine_slices(remaining_slices)
# Now backpropagate with truncation, using the same operator budget and
# the defined truncation error budget
bp_obs_trunc, remaining_slices_trunc, metadata = backpropagate(
observable,
slices,
operator_budget=op_budget,
truncation_error_budget=truncation_error_budget,
)
bp_circuit_trunc = combine_slices(
remaining_slices_trunc, include_barriers=False
)
# Now we transpile the original circuit and the two backpropagated circuits,
# and apply the layout to the corresponding observables
pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
isa_circuit = pm.run(circuit)
isa_bp_circuit = pm.run(bp_circuit)
isa_bp_circuit_trunc = pm.run(bp_circuit_trunc)
isa_observable = observable.apply_layout(isa_circuit.layout)
isa_bp_observable = bp_obs.apply_layout(isa_bp_circuit.layout)
isa_bp_observable_trunc = bp_obs_trunc.apply_layout(
isa_bp_circuit_trunc.layout
)
# Compare the 2-qubit depth of each transpiled circuit to see how much
# depth backpropagation saved
print(
f"2-qubit depth without backpropagation: "
f"{isa_circuit.depth(lambda x: x.operation.num_qubits == 2)}"
)
print(
f"2-qubit depth with backpropagation: "
f"{isa_bp_circuit.depth(lambda x: x.operation.num_qubits == 2)}"
)
print(
f"2-qubit depth with backpropagation and truncation: "
f"{isa_bp_circuit_trunc.depth(lambda x: x.operation.num_qubits == 2)}"
)
pubs = [
(isa_circuit, isa_observable),
(isa_bp_circuit, isa_bp_observable),
(isa_bp_circuit_trunc, isa_bp_observable_trunc),
]
# Now we instantiate the Estimator primitive for the hardware with
# ZNE and measurement error
# mitigation and compute the three circuits and observables
options = EstimatorOptions()
options.default_precision = 0.01
options.resilience_level = 2
options.resilience.zne.noise_factors = [1, 1.2, 1.4]
options.resilience.zne.extrapolator = ["linear"]
estimator = EstimatorV2(mode=backend, options=options)
estimator.options.environment.job_tags = ["TUT_OBP"]
job = estimator.run(pubs)
# Retrieve the results and the standard deviations
result_no_bp = job.result()[0].data.evs.item()
result_bp = job.result()[1].data.evs.item()
result_bp_trunc = job.result()[2].data.evs.item()
std_no_bp = job.result()[0].data.stds.item()
std_bp = job.result()[1].data.stds.item()
std_bp_trunc = job.result()[2].data.stds.item()
2-qubit depth without backpropagation: 24
2-qubit depth with backpropagation: 20
2-qubit depth with backpropagation and truncation: 18
print(f"Expectation value without backpropagation: {result_no_bp}")
print(f"Backpropagated expectation value: {result_bp}")
print(f"Backpropagated expectation value with truncation: {result_bp_trunc}")
Expectation value without backpropagation: 0.9543907942381811
Backpropagated expectation value: 0.9445337385406468
Backpropagated expectation value with truncation: 0.934050286970965
# Plot the results
methods = [
"No backpropagation",
"Backpropagation",
"Backpropagation w/ truncation",
]
values = [result_no_bp, result_bp, result_bp_trunc]
error_bars = [std_no_bp, std_bp, std_bp_trunc]
ax = plt.gca()
plt.bar(methods, values, color="#a56eff", width=0.4, edgecolor="#8a3ffc")
plt.errorbar(methods, values, yerr=error_bars, fmt="o", color="r", capsize=5)
plt.axhline(0.89)
ax.set_ylim([0.8, 0.98])
plt.text(0.25, 0.895, "Exact result")
ax.set_ylabel(r"$M_Z$", fontsize=12)
Text(0, 0.5, '$M_Z$')
Langkah selanjutnya
Jika kamu menemukan karya ini menarik, kamu mungkin tertarik dengan materi berikut:
- Approximate quantum compilation for time evolution circuits
- Multi-product formulas to reduce Trotter error
pauli-prop, paket berakselerasi Rust untuk propagasi Pauli, dengan tutorial yang mencakup OBP, estimasi nilai ekspektasi klasikal, dan simulasi berisik