Langkau ke kandungan utama
Projek ini dalam fasa beta. Jumpa pepijat? Buat isu GitHub. Ada soalan atau idea? Tanya dalam Discussions — kami suka dengar maklum balas anda!
Bagaimana kualiti terjemahan pada halaman ini?

Pangkas sebutan Pauli semasa perambatan balik

Panduan ini menerangkan cara mengkonfigurasi mekanisme pemangkasan sebutan Pauli yang disediakan oleh modul qiskit_addon_obp.utils.truncating.

Operator backpropagation (OBP) boleh digunakan untuk mengurangkan kedalaman litar kuantum dengan kos observable yang lebih kompleks. Untuk mendapatkan keputusan yang bermakna daripada OBP, seseorang biasanya perlu memangkas sebutan daripada observable mereka bagi mengelakkannya daripada menjadi terlalu besar. Satu cara untuk membolehkan perambatan balik yang lebih dalam ke dalam litar, sambil mengelakkan operator menjadi terlalu besar, ialah memangkas sebutan berpekali kecil, dan bukannya menambahkannya pada operator. Memangkas sebutan boleh menghasilkan lebih sedikit litar kuantum untuk dilaksanakan, tetapi berbuat demikian menyebabkan sedikit ralat dalam pengiraan nilai jangkaan akhir, berkadar dengan magnitud pekali sebutan yang dipangkas.

Kaedah backpropagate menerima TruncationErrorBudget pilihan, yang mengkonfigurasi pemangkasan sebutan Pauli berpemberat rendah bagi setiap observable selepas perambatan balik setiap hirisan berjaya. Bilangan sebutan yang dipangkas bergantung pada pelbagai parameter konfigurasi yang ditentukan oleh pengguna. Setakat ini, hanya satu strategi pemangkasan tersedia - kaedah truncate_binary_search. Diberikan satu observable dan beberapa bajet, ia akan melakukan carian binari ke atas sebutan dan pekali Pauli dalam observable tersebut untuk mencari ambang optimum, supaya jumlah pekali yang dipangkas adalah maksimum tetapi lebih rendah daripada bajet.

Nota: Secara lalai, norma L1 digunakan untuk menilai dan menghadkan ralat pemangkasan; walau bagaimanapun, tetapan p_norm membolehkan norma Lp yang akan digunakan ditentukan. Untuk maklumat lanjut tentang cara menggunakan tetapan itu, rujuk panduan Gunakan norma Lp yang berbeza untuk pemangkasan sebutan Pauli. Contoh berikut menggambarkan pelbagai cara membina TruncationErrorBudget dengan menggunakan fungsi setup_budget yang disertakan.

Bina litar contoh​

Panduan ini menggunakan hirisan litar berikut:

# 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
linear_chain = rustworkx.generators.path_graph(10)

# 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, 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

Kita akan melihat satu observable ringkas:

from qiskit.quantum_info import SparsePauliOp

obs = SparsePauliOp("IIIIIZIIII")

Kes paling mudah: bajet pemangkasan tetap bagi setiap hirisan​

Bajet yang tersedia untuk pemangkasan sebutan Pauli boleh berbeza pada setiap langkah perambatan balik. Untuk memahami cara ini berfungsi, kita mula-mula melihat kes paling mudah iaitu bajet pemangkasan tetap seperti yang ditentukan oleh pengguna.

Cara paling mudah untuk menentukan bajet pemangkasan ialah menggunakan argumen max_error_per_slice. Sebenarnya, inilah yang dilakukan dalam tutorial Reducing depth of circuits with operator backpropagation. Menetapkan max_error_per_slice kepada float menyebabkan setiap hirisan diperuntukkan bajet yang sama dengan nilai itu. Dalam contoh di bawah, kami menetapkan nilai ini kepada 0.001 yang menjamin ralat pemangkasan tersirat paling banyak 0.018, jika kesemua 18 hirisan dirambat balik.

Perhatikan bahawa sebarang baki bajet ralat selepas merambat balik sesuatu hirisan dan memangkas sebutan berpekali kecil akan sentiasa ditambah kepada bajet ralat hirisan berikutnya.

from qiskit_addon_obp.utils.truncating import setup_budget

truncation_error_budget = setup_budget(max_error_per_slice=0.001)
print(truncation_error_budget)
TruncationErrorBudget(per_slice_budget=[0.001], max_error_total=inf, p_norm=1)
from qiskit_addon_obp import backpropagate
from qiskit_addon_obp.utils.simplify import OperatorBudget

op_budget = OperatorBudget(max_qwc_groups=10)
bp_obs, remaining_slices, metadata = backpropagate(
obs,
slices,
operator_budget=op_budget,
truncation_error_budget=truncation_error_budget,
)
reduced_circuit = combine_slices(remaining_slices)
print(f"Backpropagated {len(slices) - len(remaining_slices)} circuit slices.")
print(
f"New observable contains {len(bp_obs)} terms and {len(bp_obs.group_commuting(qubit_wise=True))} commuting groups."
)
Backpropagated 11 circuit slices.
New observable contains 29 terms and 10 commuting groups.

Seterusnya kami menggunakan instance OBPMetadata dan alat yang disediakan oleh modul visualization untuk menggambarkan proses perambatan balik.

  • Plot kiri atas menunjukkan bahawa kita mempunyai bajet yang mencukupi untuk mula memangkas sebutan observable selepas merambat balik hirisan ketiga. Bermula dari hirisan ketiga, kita tahu bahawa kita memangkas sekurang-kurangnya satu sebutan daripada setiap hirisan yang kita rambat balik kerana kita menanggung sedikit ralat pemangkasan selepas setiap hirisan.

  • Plot kanan atas menunjukkan bahawa bajet ralat meningkat kepada .003 untuk hirisan ketiga. Kita melihat penurunan mendadak dalam baki bajet, yang bermakna sebutan telah dipangkas daripada observable. Ini selaras dengan apa yang kita simpulkan daripada plot kiri atas.

  • Plot kiri bawah menunjukkan bahawa semasa kita memangkas sebutan daripada observable kita, ralat terkumpul keseluruhan kita meningkat secara monotonik. Graf ini juga mengesahkan bahawa tiada sebutan dipangkas sehingga selepas hirisan ketiga dirambat balik.

  • Plot kanan bawah menunjukkan bahawa bilangan kumpulan Pauli commuting dalam observable kita telah meningkat sehingga had yang ditentukan iaitu 10. Plot ini juga menunjukkan bagaimana merambat balik satu lapisan lagi akan menyebabkan observable kita melebihi had yang ditentukan seperti yang anda dapat lihat daripada persilangan garis hitam dan merah.

Perhatikan bahawa dalam semua plot ini, paksi-x menyenaraikan hirisan yang dirambat balik, tetapi memandangkan OBP bekerja pada hujung litar, slice 1 ialah hirisan paling akhir, slice 2 ialah yang sebelumnya, dan seterusnya.

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

fig, axes = plt.subplots(2, 2, figsize=(20, 10))
plot_slice_errors(metadata, axes[(0, 0)])
plot_left_over_error_budget(metadata, axes[(0, 1)])
plot_accumulated_error(metadata, axes[(1, 0)])
plot_num_qwc_groups(metadata, axes[(1, 1)])

Output of the previous code cell

Tentukan bajet hirisan secara eksplisit​

Jika anda tahu cara memperuntukkan bajet kepada setiap hirisan supaya prestasi perambatan balik dioptimumkan, anda mungkin mahu memperuntukkan bajet secara eksplisit bagi setiap hirisan. Untuk tujuan demonstrasi, kami akan memperuntukkan bajet sifar kepada tiga hirisan pertama dan menggunakan bajet .001 bagi setiap hirisan untuk hirisan yang selebihnya.

# Zero out the first 3 slices' budgets
max_error_per_slice = [0.0] * 3 + [0.001] * (len(slices) - 3)

truncation_error_budget = setup_budget(
max_error_per_slice=max_error_per_slice
)
print(truncation_error_budget)
TruncationErrorBudget(per_slice_budget=[0.0, 0.0, 0.0, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001], max_error_total=inf, p_norm=1)
bp_obs, remaining_slices, metadata = backpropagate(
obs,
slices,
operator_budget=op_budget,
truncation_error_budget=truncation_error_budget,
)
reduced_circuit = combine_slices(remaining_slices)
print(f"Backpropagated {len(slices) - len(remaining_slices)} circuit slices.")
print(
f"New observable contains {len(bp_obs)} terms and {len(bp_obs.group_commuting(qubit_wise=True))} commuting groups."
)
Backpropagated 11 circuit slices.
New observable contains 32 terms and 10 commuting groups.

Membuang bajet daripada tiga lapisan pertama menyebabkan tiada sebutan dipangkas sehingga selepas lapisan keempat, seperti yang dapat disahkan dalam tiga plot ini. Yang mungkin agak mengejutkan ialah walaupun hirisan keempat tidak mempunyai baki bajet yang disalurkan kepadanya, satu sebutan masih dipangkas dengan menggunakan bajet .001 yang diperuntukkan. Ini jelas daripada plot kiri atas, tetapi juga boleh diperhatikan dalam plot kanan atas, kerana lengkung baki bajet mendatar antara hirisan tiga dan empat. Satu lagi perincian ketara ialah sekurang-kurangnya satu sebutan dipangkas mulai titik ini, sama seperti dalam contoh sebelumnya.

Pengajaran utama ialah walaupun kita menanggung ralat pemangkasan yang lebih kecil dalam contoh kedua kerana menyifarkan bajet sesetengah hirisan, kita dapat merambat balik bilangan hirisan yang sama, dan observable kita mengandungi bilangan kumpulan Pauli commuting yang sama. Kita boleh mengesahkan bahawa had ralat kita lebih kecil dalam contoh kedua dengan memeriksa plot kiri bawah.

fig, axes = plt.subplots(2, 2, figsize=(20, 10))
plot_slice_errors(metadata, axes[(0, 0)])
plot_left_over_error_budget(metadata, axes[(0, 1)])
plot_accumulated_error(metadata, axes[(1, 0)])
plot_num_qwc_groups(metadata, axes[(1, 1)])

Output of the previous code cell

Tentukan bajet secara kitaran​

Jika anda mempunyai litar dengan beberapa corak berulang, seperti litar Trotter, anda mungkin mahu menentukan bajet bagi subset hirisan yang berulang itu dan menggunakan bajet tersebut untuk semua pengulangan hirisan berikutnya.

Lebih konkrit, litar contoh yang kita gunakan mempunyai enam hirisan yang diulang tiga kali, dengan jumlah 18 hirisan. Kami akan memperuntukkan bajet sifar secara sewenang-wenangnya kepada lapisan satu qubit dan RYY, dan bajet .003 kepada setiap lapisan RXX. Kami akan melihat bagaimana menentukan bajet sebagai jujukan panjang-6 menyebabkan bajet diterapkan kepada kesemua 18 hirisan secara kitaran.

Sekali lagi, perhatikan bahawa hirisan dirambat balik dalam susunan terbalik (iaitu, bermula dari hujung). Oleh itu, entri pertama dalam bajet kitaran kita sebenarnya digunakan untuk hirisan terakhir, entri kedua untuk hirisan sebelumnya, dan seterusnya.

# Specify a length-6 per-slice budget.
# This will be cycled over three times to be applied to the 18 slices
max_error_per_slice = [0.0] * 4 + [0.003] * 2

truncation_error_budget = setup_budget(
max_error_per_slice=max_error_per_slice
)
print(truncation_error_budget)
TruncationErrorBudget(per_slice_budget=[0.0, 0.0, 0.0, 0.0, 0.003, 0.003], max_error_total=inf, p_norm=1)
op_budget = OperatorBudget(max_qwc_groups=20)
bp_obs, remaining_slices, metadata = backpropagate(
obs,
slices,
operator_budget=op_budget,
truncation_error_budget=truncation_error_budget,
)
reduced_circuit = combine_slices(remaining_slices)
print(f"Backpropagated {len(slices) - len(remaining_slices)} circuit slices.")
print(
f"New observable contains {len(bp_obs)} terms and {len(bp_obs.group_commuting(qubit_wise=True))} commuting groups."
)
Backpropagated 13 circuit slices.
New observable contains 49 terms and 14 commuting groups.

Seperti yang dilihat dalam imej kiri atas dan kiri bawah, tiada pemangkasan dilakukan ke atas empat hirisan pertama kerana tiada bajet ralat diperuntukkan kepadanya. Hirisan lima dan enam mempunyai sebahagian sebutannya dipangkas apabila bajet menjadi tersedia.

Seperti yang dilihat dalam imej kiri atas, ralat yang agak besar timbul selepas merambat balik hirisan tujuh, walaupun hirisan itu tidak diperuntukkan bajet. Ini kerana hanya kira-kira .002 daripada jumlah bajet .006 yang diperuntukkan kepada hirisan lima dan enam telah digunakan, jadi bakinya disalurkan kepada hirisan tujuh dan kebanyakannya dibelanjakan, seperti yang dilihat dalam imej kanan atas.

Imej kiri atas dan kanan atas menunjukkan bahawa baki bajet yang sedikit itu dihabiskan antara hirisan 8-10, dan bajet baharu menjadi tersedia dalam hirisan 11, seperti yang dijangkakan. Imej kiri atas, kanan atas, dan kiri bawah semuanya menunjukkan tingkah laku kitaran bagi argumen max_error_per_slice apabila panjangnya kurang daripada bilangan hirisan. Tingkah laku kitaran ini akan berterusan melalui semua hirisan, tetapi kriteria penghentian max_qwc_groups dicapai selepas merambat balik 13 hirisan, seperti yang dilihat dalam imej kanan bawah.

Menarik juga bahawa bilangan kumpulan Pauli sebenarnya menurun selepas pusingan kedua bajet menjadi tersedia pada hirisan 11. Ini kerana terdapat kumpulan berpekali kecil yang tidak dapat dipangkas sehingga ada lebih banyak bajet selepas merambat balik hirisan 11, jadi ia terkumpul dalam observable selama beberapa lelaran. Kes ini juga menonjolkan bahawa max_qwc_groups mesti dilebihi untuk algoritma ditamatkan.

fig, axes = plt.subplots(2, 2, figsize=(20, 10))
plot_slice_errors(metadata, axes[(0, 0)])
plot_left_over_error_budget(metadata, axes[(0, 1)])
plot_accumulated_error(metadata, axes[(1, 0)])
plot_num_qwc_groups(metadata, axes[(1, 1)])

Output of the previous code cell

Hadkan jumlah ralat​

Selain menentukan bajet ralat bagi setiap hirisan, anda boleh menentukan jumlah ralat maksimum yang ditanggung daripada pemangkasan. Setelah had itu dicapai, tiada lagi pemangkasan akan dilakukan; walau bagaimanapun, perambatan balik akan diteruskan sehingga observable menjadi terlalu besar dan salah satu kriteria penghentian dipenuhi.

Kami seterusnya menjalankan semula eksperimen di atas, dengan menetapkan had pada max_error_total supaya bajet ralat dihabiskan selepas merambat balik hirisan tujuh.

# Specify a length-6 per-slice budget.
# This will be cycled over 3 times to be applied to the 18 slices
max_error_per_slice = [0.0] * 4 + [0.003] * 2

truncation_error_budget = setup_budget(
max_error_per_slice=max_error_per_slice, max_error_total=0.006
)
print(truncation_error_budget)
TruncationErrorBudget(per_slice_budget=[0.0, 0.0, 0.0, 0.0, 0.003, 0.003], max_error_total=0.006, p_norm=1)
bp_obs, remaining_slices, metadata = backpropagate(
obs,
slices,
operator_budget=op_budget,
truncation_error_budget=truncation_error_budget,
)
reduced_circuit = combine_slices(remaining_slices)
print(f"Backpropagated {len(slices) - len(remaining_slices)} circuit slices.")
print(
f"New observable contains {len(bp_obs)} terms and {len(bp_obs.group_commuting(qubit_wise=True))} commuting groups."
)
Backpropagated 10 circuit slices.
New observable contains 67 terms and 20 commuting groups.

Seperti yang dijangkakan, ralat pemangkasan kita mencapai had pada .006 (carta kiri bawah). Perlu diperhatikan bahawa dalam larian ini kita tidak dapat merambat balik hirisan 11. Ini kerana kita tidak mempunyai bajet yang mencukupi untuk memangkas sebutan dan bilangan kumpulan Pauli commuting melebihi had 20, seperti yang dilihat dalam imej kanan bawah.

fig, axes = plt.subplots(2, 2, figsize=(20, 10))
plot_slice_errors(metadata, axes[(0, 0)])
plot_left_over_error_budget(metadata, axes[(0, 1)])
plot_accumulated_error(metadata, axes[(1, 0)])
plot_num_qwc_groups(metadata, axes[(1, 1)])

Output of the previous code cell

Mungkin wajar untuk sekadar menghadkan bajet keseluruhan dengan max_error_total tanpa menentukan max_error_per_slice.

truncation_error_budget = setup_budget(max_error_total=0.018)
print(truncation_error_budget)
TruncationErrorBudget(per_slice_budget=[0.018], max_error_total=0.018, p_norm=1)

Output sel di atas mungkin agak mengejutkan kerana per_slice_budget ditetapkan kepada max_error_total. Ini menunjukkan bahawa keseluruhan bajet yang tersedia akan digunakan secara tamak. Anda boleh memikirkannya begini: keseluruhan bajet tersedia untuk setiap hirisan (kerana kita membuat gelung ke atas per_slice_budget). Tetapi sebarang bajet yang telah digunakan akan ditolak daripada bajet yang tersedia pada titik tertentu dalam algoritma itu.

op_budget = OperatorBudget(max_qwc_groups=10)
bp_obs, remaining_slices, metadata = backpropagate(
obs,
slices,
operator_budget=op_budget,
truncation_error_budget=truncation_error_budget,
)
reduced_circuit = combine_slices(remaining_slices)
print(f"Backpropagated {len(slices) - len(remaining_slices)} circuit slices.")
print(
f"New observable contains {len(bp_obs)} terms and {len(bp_obs.group_commuting(qubit_wise=True))} commuting groups."
)
Backpropagated 9 circuit slices.
New observable contains 25 terms and 9 commuting groups.

Imej kanan atas menunjukkan bagaimana keseluruhan bajet ralat .018 disediakan kepada hirisan pertama. Tiada pemangkasan dilakukan sehingga hirisan ketiga, jadi baki bajet kekal malar. Bajet berkurangan secara monotonik, kerana bajet penuh disediakan kepada setiap hirisan yang dirambat balik sehingga ia dihabiskan.

Perlu diperhatikan bahawa eksperimen ini menghasilkan dua hirisan yang dirambat balik lebih sedikit berbanding eksperimen pertama dalam notebook ini, yang hampir serupa. Ini menunjukkan bahawa bagi sesetengah masalah, mengagihkan bajet secara sekata mungkin optimum. Bagi masalah lain, membenarkan hirisan membelanjakan bajet penuh secara tamak mungkin menghasilkan prestasi yang lebih baik.

fig, axes = plt.subplots(2, 2, figsize=(20, 10))
plot_slice_errors(metadata, axes[(0, 0)])
plot_left_over_error_budget(metadata, axes[(0, 1)])
plot_accumulated_error(metadata, axes[(1, 0)])
plot_num_qwc_groups(metadata, axes[(1, 1)])

Output of the previous code cell

Hadkan bilangan hirisan yang dirambat balik dan jumlah ralat bersama-sama​

Jika anda tidak mahu mengagihkan bajet ralat anda sepanjang litar tetapi anda juga tidak mahu membelanjakannya secara tamak, anda boleh menentukan bilangan hirisan yang anda berhasrat untuk rambat balik (num_slices), bersama jumlah bajet ralat (max_error_total). Ini akan mengagihkan bajet ralat secara seragam (mengikut p_norm) merentasi hirisan input.

Di sini, kami akan menghadkan bilangan hirisan yang mungkin kami rambat balik pada 12, dan kami akan mengekalkan jumlah bajet ralat yang sama.

num_slices = 12

truncation_error_budget = setup_budget(
max_error_total=0.018, num_slices=num_slices, p_norm=1
)
print(truncation_error_budget)
TruncationErrorBudget(per_slice_budget=[0.0014999999999999998], max_error_total=0.018, p_norm=1)

Sekarang kami akan cuba merambat balik 12 hirisan yang telah kami peruntukkan sedikit bajet pada langkah sebelumnya. Kami melakukannya dengan hanya menghantar 12 hirisan terakhir dalam litar kami. Dengan p_norm=1, setiap satu daripada 12 hirisan mempunyai bajet tersedia sebanyak 0.018 / num_slices = 0.0015.

bp_obs, remaining_slices, metadata = backpropagate(
obs,
slices[-num_slices:],
operator_budget=op_budget,
truncation_error_budget=truncation_error_budget,
)

Memandangkan kami menghantar subset hirisan kami (dalam kod slices[-num_slices:]) kepada backpropagate, kami mesti menggabungkan hirisan yang tinggal selepas perambatan balik dengan hirisan yang tidak pernah dihantar untuk perambatan balik (dalam kod slices[:-num_slices]).

Setelah kita menggabungkan semua hirisan yang tinggal, kita boleh menggunakan combine_slices untuk menjana QuantumCircuit berkedalaman terkurang. Seterusnya, kita memeriksa berapa banyak hirisan yang dirambat balik berbanding seberapa besar observable kita menjadi.

# Recombine the slices remaining after backprop with the rest of the original circuit
reduced_circuit = combine_slices(slices[:-num_slices] + remaining_slices)

print(f"Backpropagated {num_slices - len(remaining_slices)} circuit slices.")
print(
f"New observable contains {len(bp_obs)} terms and {len(bp_obs.group_commuting(qubit_wise=True))} commuting groups."
)
Backpropagated 12 circuit slices.
New observable contains 29 terms and 9 commuting groups.

Plot menunjukkan bahawa kita berjaya melakukan backpropagation pada kesemua 12 slice sambil mengekalkan observable kita di bawah 10 kumpulan Pauli yang berkomut. Kita juga dapat melihat bahawa penggunaan num_slices bersama max_error_total menghasilkan taburan bajet merentasi slice dan bajet yang tidak digunakan sekali lagi dipindahkan ke slice seterusnya. Ini paling jelas dalam plot kanan atas, kerana bajet digunakan dan diisi semula sepanjang backpropagation.

Perlu diperhatikan bahawa kaedah pengagihan ralat ini menghasilkan keputusan terbaik (lebih banyak slice yang dibackpropagate) berbanding eksperimen pertama dalam notebook ini dan contoh sebelum ini. Semua contoh ini memperuntukkan bajet ralat .018, tetapi backpropagation berprestasi secara berbeza bergantung pada cara bajet itu diagihkan.

fig, axes = plt.subplots(2, 2, figsize=(20, 10))
plot_slice_errors(metadata, axes[(0, 0)])
plot_left_over_error_budget(metadata, axes[(0, 1)])
plot_accumulated_error(metadata, axes[(1, 0)])
plot_num_qwc_groups(metadata, axes[(1, 1)])

Output of the previous code cell

Bekerja dengan berbilang observable​

Kaedah qiskit_addon_obp.backpropagate membolehkan anda menghantar satu jujukan observable. Ini memudahkan aliran kerja apabila berurusan dengan berbilang observable sasaran.

Kami menyebutnya secara jelas di sini untuk mengajar anda bagaimana strategi pemangkasan mengendalikan kes sedemikian. Demi contoh ini, kami menambah satu observable tambahan kepada yang telah kita gunakan setakat ini:

obs = [SparsePauliOp("IIIIIZIIII"), SparsePauliOp("IIIIIXIIII")]

Akhir sekali, kami mengulangi eksperimen pertama daripada tutorial ini, tetapi dengan dua observable untuk backpropagate litar ke dalamnya.

Untuk contoh ini, ini tidak menjejaskan bilangan slice yang dapat dibackpropagate. Walau bagaimanapun, kita dapat melihat bahawa kedua-dua observable menghasilkan bilangan sebutan Pauli dan kumpulan berkomut yang berbeza.

truncation_error_budget = setup_budget(max_error_per_slice=0.001)
print(truncation_error_budget)
TruncationErrorBudget(per_slice_budget=[0.001], max_error_total=inf, p_norm=1)
bp_obs, remaining_slices, metadata = backpropagate(
obs,
slices,
operator_budget=op_budget,
truncation_error_budget=truncation_error_budget,
)
reduced_circuit = combine_slices(remaining_slices)
print(f"Backpropagated {len(slices) - len(remaining_slices)} circuit slices.")
print(
f"The new first observable contains {len(bp_obs[0])} terms and {len(bp_obs[0].group_commuting(qubit_wise=True))} commuting groups."
)
print(
f"The new second observable contains {len(bp_obs[1])} terms and {len(bp_obs[1].group_commuting(qubit_wise=True))} commuting groups."
)
Backpropagated 11 circuit slices.
The new first observable contains 29 terms and 10 commuting groups.
The new second observable contains 23 terms and 8 commuting groups.

Plot di bawah membantu menggambarkan bagaimana algoritma backpropagation mengendalikan berbilang observable.

Pertama, plot di kiri atas, kanan atas dan kiri bawah menunjukkan bahawa bajet untuk memangkas sebutan ditetapkan secara individu bagi setiap observable. Dengan kata lain, kedua-dua observable mempunyai keupayaan untuk memangkas sebutan dengan mengandaikan ralat 0.001 bagi setiap slice yang dibackpropagate. Disebabkan sifat observable yang berbeza, ini menghasilkan penggunaan bajet yang berbeza. Dalam contoh ini, kedua-duanya menunjukkan banyak pertindihan, yang tidak selalu berlaku.

Plot kanan bawah menggambarkan bahawa max_qwc_groups mengambil kira semua observable. Ini bermakna sebutan semua observable dikumpulkan bersama untuk mendapatkan satu bilangan akhir kumpulan berkomut qubit-wise, yang dibandingkan dengan max_qwc_paulis. Perkara yang sama dilakukan untuk ambang max_paulis (tidak dibincangkan dalam notebook ini), yang membolehkan anda menetapkan had pada bilangan sebutan Pauli merentasi semua observable.

fig, axes = plt.subplots(2, 2, figsize=(20, 10))
plot_slice_errors(metadata, axes[(0, 0)])
plot_left_over_error_budget(metadata, axes[(0, 1)])
plot_accumulated_error(metadata, axes[(1, 0)])
plot_num_qwc_groups(metadata, axes[(1, 1)])

Output of the previous code cell