Lewati ke konten utama

Memulai dengan multi-product formulas (MPF)

Mulai dengan Multi-product formulas (MPFs)​

Versi paket

Kode di halaman ini dikembangkan menggunakan persyaratan berikut. Kami menyarankan menggunakan versi ini atau yang lebih baru.

qiskit[all]~=2.3.0
qiskit-addon-utils~=0.3.0
qiskit-addon-mpf~=0.3.0
scipy~=1.16.3

Panduan ini menunjukkan cara menggunakan paket qiskit-addon-mpf, dengan evolusi waktu model Ising sebagai contoh. Dengan paket ini, kamu bisa membangun Multi-Product Formula (MPF) yang dapat mencapai error Trotter lebih rendah pada pengukuran observable. Alat yang disediakan memungkinkan kamu menentukan bobot dari MPF yang dipilih, yang kemudian bisa digunakan untuk menggabungkan kembali nilai ekspektasi yang diestimasi dari beberapa Circuit evolusi waktu, masing-masing dengan jumlah langkah Trotter yang berbeda.

Mulailah dengan mempertimbangkan Hamiltonian dari model Ising dengan 10 situs:

HIsing=βˆ‘i=19Ji,(i+1)ZiZi+1+βˆ‘i=110hiXiH_{\text{Ising}} = \sum_{i=1}^9 J_{i,(i+1)}Z_iZ_{i+1} + \sum_{i=1}^{10} h_i X_i

di mana Ji,(i+1)J_{i,(i+1)} adalah kekuatan kopling dan hih_i adalah kekuatan medan magnet eksternal. Untuk menyiapkan masalah ini, observable yang akan diukur adalah total magnetisasi sistem

⟨M⟩=βˆ‘i=110⟨Zi⟩.\langle M \rangle = \sum_{i=1}^{10} \langle Z_i \rangle.

Cuplikan kode di bawah ini menyiapkan Hamiltonian dari rantai Ising menggunakan paket qiskit-addon-utils, dan mendefinisikan observable yang akan diukur.

# Added by doQumentation β€” required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-mpf qiskit-addon-utils scipy
from qiskit.transpiler import CouplingMap
from qiskit.synthesis import SuzukiTrotter
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import StatevectorEstimator
from qiskit.providers.fake_provider import GenericBackendV2
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_addon_utils.problem_generators import (
generate_xyz_hamiltonian,
generate_time_evolution_circuit,
)
from qiskit_addon_mpf.costs import (
setup_exact_problem,
setup_sum_of_squares_problem,
)
from qiskit_addon_mpf.static import setup_static_lse

from scipy.linalg import expm
import numpy as np

# Generate some coupling map to use for this example
coupling_map = CouplingMap.from_line(10, bidirectional=False)

# Get a qubit operator describing the Ising field model
hamiltonian = generate_xyz_hamiltonian(
coupling_map,
coupling_constants=(0.0, 0.0, 1.0),
ext_magnetic_field=(0.4, 0.0, 0.0),
)
print(f"Hamiltonian:\n {hamiltonian}\n")

L = coupling_map.size()
observable = SparsePauliOp.from_sparse_list(
[("Z", [i], 1 / L / 2) for i in range(L)], num_qubits=L
)
print(f"Observable:\n {observable}")
Hamiltonian:
SparsePauliOp(['IIIIIIIZZI', 'IIIIIZZIII', 'IIIZZIIIII', 'IZZIIIIIII', 'IIIIIIIIZZ', 'IIIIIIZZII', 'IIIIZZIIII', 'IIZZIIIIII', 'ZZIIIIIIII', 'IIIIIIIIIX', 'IIIIIIIIXI', 'IIIIIIIXII', 'IIIIIIXIII', 'IIIIIXIIII', 'IIIIXIIIII', 'IIIXIIIIII', 'IIXIIIIIII', 'IXIIIIIIII', 'XIIIIIIIII'],
coeffs=[1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j, 1. +0.j,
1. +0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j, 0.4+0.j,
0.4+0.j, 0.4+0.j, 0.4+0.j])

Observable:
SparsePauliOp(['IIIIIIIIIZ', 'IIIIIIIIZI', 'IIIIIIIZII', 'IIIIIIZIII', 'IIIIIZIIII', 'IIIIZIIIII', 'IIIZIIIIII', 'IIZIIIIIII', 'IZIIIIIIII', 'ZIIIIIIIII'],
coeffs=[0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j,
0.05+0.j, 0.05+0.j, 0.05+0.j])

Selanjutnya kamu menyiapkan MPF. Pilihan pertama yang harus dibuat adalah apakah koefisien akan bersifat statis (tidak bergantung waktu) atau dinamis; tutorial ini menggunakan MPF statis. Pilihan berikutnya adalah sekumpulan nilai kjk_j. Ini menentukan berapa banyak suku yang akan ada dalam MPF, serta berapa banyak langkah Trotter yang digunakan setiap suku untuk mensimulasikan evolusi waktu. Pemilihan nilai kjk_j bersifat heuristik, sehingga kamu perlu mendapatkan sekumpulan nilai kjk_j yang "baik" sendiri. Baca panduan untuk menemukan sekumpulan nilai yang baik di akhir halaman memulai.

Kemudian, setelah nilai kjk_j ditentukan, kamu bisa menyiapkan sistem persamaan, Ax=bAx=b, untuk diselesaikan. Matriks AA juga ditentukan oleh formula produk yang digunakan. Pilihannya adalah orde-nya, yang diset ke 22 dalam contoh ini, serta apakah formula produk harus bersifat simetris, yang diset ke True untuk contoh ini. Cuplikan kode di bawah ini memilih total waktu untuk mengevolusi sistem, nilai kjk_j yang akan digunakan, dan sekumpulan persamaan untuk diselesaikan menggunakan metode qiskit_addon_mpf.static.setup_static_lse.

time = 8.0
trotter_steps = (8, 12, 19)

lse = setup_static_lse(trotter_steps, order=2, symmetric=True)
print(lse)
LSE(A=array([[1.00000000e+00, 1.00000000e+00, 1.00000000e+00],
[1.56250000e-02, 6.94444444e-03, 2.77008310e-03],
[2.44140625e-04, 4.82253086e-05, 7.67336039e-06]]), b=array([1., 0., 0.]))

Setelah sistem persamaan linear diinstansiasi, sistem itu bisa diselesaikan secara eksak atau melalui model aproksimasi menggunakan jumlah kuadrat (atau norma Frobenius untuk koefisien dinamis; lihat referensi API untuk informasi lebih lanjut). Pilihan untuk menggunakan model aproksimasi biasanya muncul ketika norma koefisien untuk sekumpulan nilai kjk_j yang dipilih dianggap terlalu tinggi dan sekumpulan nilai kjk_j yang berbeda tidak bisa dipilih. Panduan ini mendemonstrasikan keduanya untuk membandingkan hasilnya.

model_exact, coeffs_exact = setup_exact_problem(lse)
model_approx, coeffs_approx = setup_sum_of_squares_problem(
lse, max_l1_norm=3.0
)
model_exact.solve()
model_approx.solve()
print(f"Exact solution: {coeffs_exact.value}")
print(f"Approximate solution: {coeffs_approx.value}")
Exact solution: [ 0.17239057 -1.19447005  2.02207947]
Approximate solution: [-0.40454257 0.57553173 0.8290123 ]
catatan

Objek LSE juga memiliki metode LSE.solve(), yang akan menyelesaikan sistem persamaan secara eksak. Alasan setup_exact_problem() digunakan dalam panduan ini adalah untuk mendemonstrasikan antarmuka yang disediakan oleh metode aproksimasi lainnya.

Siapkan dan jalankan Circuit Trotter​

Sekarang setelah koefisien xjx_j diperoleh, langkah terakhir adalah menghasilkan Circuit evolusi waktu untuk orde dan sekumpulan langkah kjk_j yang dipilih dari MPF. Paket qiskit-addon-utils bisa mempercepat proses ini.

circuits = []
for k in trotter_steps:
circ = generate_time_evolution_circuit(
hamiltonian,
synthesis=SuzukiTrotter(order=2, reps=k),
time=time,
)
circuits.append(circ)
circuits[0].draw("mpl", fold=-1)

Output of the previous code cell

circuits[1].draw("mpl", fold=-1)

Output of the previous code cell

circuits[2].draw("mpl", fold=-1)

Output of the previous code cell

Setelah Circuit-circuit ini dibuat, kamu bisa melakukan transpilasi dan menjalankannya menggunakan QPU. Untuk contoh ini, kita akan menggunakan salah satu simulator bebas noise untuk mendemonstrasikan bagaimana error Trotter berkurang.

backend = GenericBackendV2(num_qubits=10)
transpiler = generate_preset_pass_manager(
optimization_level=2, backend=backend
)

transpiled_circuits = [transpiler.run(circ) for circ in circuits]

estimator = StatevectorEstimator()
job = estimator.run([(circ, observable) for circ in transpiled_circuits])
result = job.result()

mpf_evs = [res.data.evs for res in result]
print(mpf_evs)
[array(0.23799162), array(0.35754312), array(0.38649906)]

Rekonstruksi hasil​

Sekarang setelah Circuit-circuit dijalankan, merekonstruksi hasilnya cukup mudah. Seperti yang disebutkan di halaman gambaran umum MPF, observable kita direkonstruksi melalui jumlah berbobot

⟨M⟩=βˆ‘jxj⟨Mj⟩.\langle M \rangle = \sum_j x_j \langle M_j \rangle.

di mana xjx_j adalah koefisien yang kita temukan dan ⟨Mj⟩\langle M_j \rangle adalah estimasi observable βˆ‘i⟨Zi⟩\sum_i \langle Z_i \rangle untuk setiap Circuit. Kita kemudian bisa membandingkan hasil yang diperoleh dengan nilai eksak menggunakan paket scipy.linalg.

exp_H = expm(-1j * time * hamiltonian.to_matrix())
initial_state = np.zeros(exp_H.shape[0])
initial_state[0] = 1.0

time_evolved_state = exp_H @ initial_state
exact_obs = (
time_evolved_state.conj() @ observable.to_matrix() @ time_evolved_state
)

# Print out the different observable measurements
print(f"Exact value: {exact_obs.real}")
print(f"PF with 19 steps: {mpf_evs[-1]}")
print(f"MPF using exact solution: {mpf_evs @ coeffs_exact.value}")
print(f"MPF using approximate solution: {mpf_evs @ coeffs_approx.value}")
Exact value: 0.4006024248789992
PF with 19 steps: 0.3864990619977402
MPF using exact solution: 0.3954847855979902
MPF using approximate solution: 0.4299121425348959

Di sini kamu bisa melihat bahwa MPF telah mengurangi error Trotter dibandingkan dengan yang diperoleh hanya dengan satu PF dengan kj=19k_j=19. Namun, model aproksimasi menghasilkan nilai ekspektasi yang lebih buruk daripada model eksak. Ini menunjukkan pentingnya menggunakan kriteria konvergensi yang ketat pada model aproksimasi dan menemukan sekumpulan nilai kjk_j yang "baik".

Source: IBM Quantum docs β€” updated 13 Feb 2026
English version on doQumentation β€” updated 7 Mei 2026
This translation based on the English version of 11 Mar 2026