Simulate ang isang kicked Ising model gamit ang TEM function
Ang Tensor-network Error Mitigation (TEM) method ng Algorithmiq ay isang hybrid quantum-classical algorithm na dinisenyo para sa pagsasagawa ng noise mitigation nang buo sa loob ng classical post-processing stage. Gamit ang TEM, maaaring kalkulahin ng user ang mga expectation value ng observables, na mitigating ang hindi maiwasang noise-induced errors na nangyayari sa quantum hardware nang may mas mataas na katumpakan at cost efficiency, na ginagawa itong isang napaka-kaakit-akit na opsyon para sa mga quantum researcher at industry practitioner.
Ipinapakita ng tutorial na ito kung paano nakakakuha ang TEM ng makabuluhang resulta para sa dynamics ng isang quantum system, na hindi maaabot nang wala ang error mitigation at nangangailangan ng mas maraming quantum resources kung gagamit ng ibang error mitigation methods tulad ng PEC at ZNE.
Tinantyang paggamit: Gumagamit ang notebook na ito ng humigit-kumulang 10 QPU minutes sa Heron r3 devices. Maaaring malaki ang pagkakaiba ng runtime depende sa piniling device. Ang tinantyang paggamit bawat seksyon ay nasa ibaba.
Magpatakbo ng error-mitigated many-body physics experiments gamit ang TEM function
Ang tutorial na ito ay batay sa sumusunod na sanggunian: L. E. Fischer et al., Nat. Phys. (2026). Tinatalakay ng sangguniang ito ang isang tunay na simulation sa quantum hardware ng hanggang 91 qubits. Sa tutorial na ito, muling ginagawa namin ang isang katulad na simulation sa mas maliit na laki ng circuit.
Ang kicked Ising model ay katumbas ng karaniwang Ising model:
kung saan inilalapat ang isang transverse kick:
Ang layunin ay i-simulate ang dynamics ng isang estado sa ilalim ng transverse kicked Ising Hamiltonian, na ang time evolution ay maaaring ipatupad ng isang Floquet unitary . Ang initial state na ie-evolve ay ang isa kung saan ang unang qubit ay nasa estado , habang ang iba ay pinagsamasama at nakatakda sa Bell state .
Ang dami na nais nating obserbahan ay ang correlation function. Tinatalakay ng reference paper kung paano maaaring isulat muli ang daming ito bilang isang Pauli operator sa qubit. Pagkatapos ng ilang physical time steps , kinakalkula namin ang halaga ng Pauli operator . Depende sa mga parameter ng system, ang halaga ng observable na ito ay katumbas ng isang halagang maaaring kalkulahin nang eksakto, o simulation lamang sa pamamagitan ng mga approximate method. Specifically, para sa ito ay katumbas ng , na siyang halagang gagamitin namin para sa benchmarking ng mga resulta ng tutorial na ito. Bukod dito, sa isang ibinigay na time step , ang ay zero. Para sa mga detalye sa pagkuha ng mga halagang ito, at para sa paghahambing sa mga approximate classical simulation results sa labas ng mga parameter na ito, tingnan ang L. E. Fischer et al., Nat. Phys. (2026).
Gumagana ang TEM sa pamamagitan ng unang pag-characterize ng noise para sa bawat natatanging layer ng two-qubit gates sa circuit, pati na rin ang pag-characterize ng readout error. Pagkatapos, ang circuit ay isinasagawa sa quantum machine. Sa wakas, ang tensor network error mitigation ay isinasagawa sa mga classical resources sa IBM Cloud® at ibinabalik ang mitigated value. Sa halimbawang ito, ang circuit ay may dalawang natatanging layer na i-characterize.
Setup
Bilang prerequisite, tiyakin na naka-install ang mga kinakailangang dependency.
%pip install numpy matplotlib qiskit qiskit-ibm-catalog qiskit-ibm-runtime pylatexenc qiskit_qasm3_import
import os
from matplotlib import pyplot as plt
import numpy as np
from qiskit.quantum_info import SparsePauliOp
from qiskit.qasm3 import load
from qiskit_ibm_catalog import QiskitFunctionsCatalog
Error mitigation gamit ang TEM
Nagbibigay kami dito ng isang circuit na nagpapatupad ng kicked Ising model na inilarawan sa itaas. Ang circuit ay inihanda tulad ng sumusunod. Una, may isang state preparation phase, kung saan ang unang qubit ay nasa estado , habang ang iba ay nasa Bell pairs . Sinusundan ito ng brickwork structure na nagpapatupad ng unitary evolution . Ang bilang ng mga physical time steps ay katumbas ng circuit layers. Dino-download ng sumusunod na code ang dalawang QASM file na kinakailangan para sa tutorial na ito.
# Download required QASM files
import urllib
urllib.request.urlretrieve(
"https://ibm.box.com/shared/static/swy5jtq309b0xpzluzlmsmj908yphes8.qasm",
"ki_30q.qasm",
)
urllib.request.urlretrieve(
"https://ibm.box.com/shared/static/et3gkodonw6gsp2trs43lzaozrdtiu7s.qasm",
"ki_12q.qasm",
)
Maaari naming i-visualize ang isang maliit na bersyon ng circuit, na may 12 qubits at anim na time steps:
# Parameters of the kicked Ising model
h = 0.0
num_qubits = 12
t_steps = 6
# Load the circuit for the kicked Ising model
small_circuit = load("ki_12q.qasm")
# Draw the circuit
small_circuit.draw("mpl", scale=0.25, fold=-1)

Susunod, i-build ang observable, . Ito ay itinayo bilang isang simpleng Pauli string na may order na tumutugma sa ginagamit ng Qiskit:
def xt_observable(n_qubits, t_steps):
pauli_str = "".join(["I" * t_steps, "X", "I" * (n_qubits - t_steps - 1)])
pauli_str = pauli_str[::-1] # Reverse the string to match qiskit order
return SparsePauliOp(data=pauli_str, coeffs=1.0)
Sa aming maliit na 12-qubit na halimbawa, ganito ang hitsura ng observable:
# Build the observable for the kicked Ising model
small_observable = xt_observable(n_qubits=12, t_steps=6)
print(small_observable)
SparsePauliOp(['IIIIIXIIIIII'],
coeffs=[1.+0.j])
Gumagamit ang Qiskit Functions ng PUBs bilang paraan ng pag-collect ng mga input. Sa aming kaso, isaalang-alang natin ang isang solong circuit at observable bilang aming PUB:
# Collect the input PUBs, in this case composed of a
# single circuit and observable
pubs = [(small_circuit, [small_observable])]
Susunod, magkakakuha tayo ng access sa TEM function. Una, i-set up namin ang kinakailangang authentication sa IBM Cloud at pipili ng backend mula sa mga available na device. Ang token, available backends, at mga katumbas na cloud resource names (CRN) ay makukuha sa pamamagitan ng pag-log in sa iyong account sa IBM Quantum Platform dashboard.
# Set IBM Quantum credentials and backend configuration
personal_token = os.environ.get(
"QISKIT_IBM_TOKEN", "<API-KEY>"
) # Replace with your personal token or set the environment variable
channel = "ibm_quantum_platform"
crn = "your_crn" # Replace with the Cloud Resource Name (CRN)
# Select the QPU backend
backend_name = "ibm_qpu_name" # Replace with your desired backend's name
I-load ang TEM function mula sa Qiskit Functions Catalog:
# Load the TEM function from the Qiskit Functions Catalog
catalog = QiskitFunctionsCatalog(
channel=channel,
token=personal_token,
instance=crn,
)
tem = catalog.load("algorithmiq/tem")
Maaari na tayong magpatakbo ng eksperimento sa kicked Ising circuit na may error mitigation na ibinibigay ng TEM. Gamit ang mga default na setting, maaaring patakbuhin ang TEM nang simple na may inaasahang QPU runtime na humigit-kumulang 2.5 minuto, depende sa QPU:
tem_job = tem.run(pubs=pubs, backend_name=backend_name)
Sa mga default na opsyon, nagpapatakbo ang TEM function ng tatlong trabaho sa quantum computer: noise learning, readout mitigation, at circuit sampling. Ang bilang ng shots na ginagamit ng bawat isa ay maaaring baguhin sa mga opsyon na ipinasa sa function. Bilang default, ang mga parameter na ito ay itinakda para makamit ang precision na 0.05 sa mga mitigated expectation values. Maaari mong suriin ang status ng iyong trabaho sa IBM Quantum Platform dashboard o gamit ang:
print(tem_job.status())
QUEUED
Kapag ang status ay DONE, maaari na tayong suriin ang mga raw at mitigated na resulta. Ang tem_evs na tinukoy sa ibaba ay ang mga expectation value ng mga hiniling na observable, sa kasong ito ay isa lamang observable, ang , at ang tem_std ay ang mga katumbas na standard deviation.
# Get the results of the TEM job
tem_results = tem_job.result()[
0
] # Get the first and only result from the job
tem_evs = tem_results.data.evs[0]
tem_std = tem_results.data.stds[0]
print(f"TEM Result: {tem_evs:.3f} ± {tem_std:.3f}")
TEM Result: 1.031 ± 0.046
Maaari rin nating suriin kung gaano karaming quantum runtime ang ginamit para sa bawat tawag sa IBM Quantum Platform, o sa pamamagitan ng pag-inspect ng result metadata mula sa Python code.
# Get the TEM job runtime
tem_runtime = tem_job.result().metadata["resource_usage"][
"RUNNING: EXECUTING_QPU"
]["QPU_TIME"]
print(f"TEM Runtime: {tem_runtime} seconds")
TEM Runtime: 155.0 seconds
I-customize ang mga TEM parameter at advanced na opsyon
Nagbibigay ang TEM function ng ilang advanced na opsyon para i-customize ang iyong error mitigation workflow. Ang mga opsyon na ito ay nagbibigay-daan sa iyo na kontrolin ang precision, bilang ng shots, mga estratehiya sa noise learning, at iba pang mga parameter upang mas maiangkop sa mga kinakailangan ng iyong eksperimento at mga available na quantum resources.
Ang mga karaniwang advanced na opsyon ay:
precision: Tukuyin ang target precision para sa mga mitigated expectation value.default_shots: Sa halip naprecision, maaari mong tukuyin ang bilang ng shots na ginagamit ng measurement job.tem_max_bond_dimension: Ang maximum bond dimension na ginagamit sa tensor network.tem_compression_cutoff: Ang cutoff value na gagamitin para sa tensor network.- Mga opsyon sa noise learning: I-configure kung paano nai-characterize ang noise, tulad ng bilang ng mga repetisyon o mga tiyak na calibration circuit.
private: Tiyakin na ang mga circuit at resulta ng eksperimento ay pribado para sa iyo at i-disable ang maramihang pag-download ng mga resulta ng trabaho.
Sumangguni sa dokumentasyon ng TEM o sa Qiskit Functions Catalog para sa kumpletong listahan ng mga sinusuportahang opsyon at ang kanilang mga paglalarawan. Maaari mong ayusin ang mga parameter na ito para balansehin ang runtime, paggamit ng resource, at katumpakan ng resulta.
Maaari mong ipasa ang mga opsyon na ito bilang isang dictionary sa options argument kapag nagpapatakbo ng TEM function:
options = {
"default_shots": 10_000,
"tem_max_bond_dimension": 512,
"tem_compression_cutoff": 1e-16,
# This option helps optimizing the measurement
# stage since the observable is strongly biased
# toward the X operator for all the qubits.
"compute_shadows_bias_from_observable": True,
# set to True to keep experiment results private,
# recommended for confidential circuits
"private": False,
}
Maaari ring ipasa ang mga custom na opsyon para sa noise learner. Sumusunod ang mga ito sa mga kahulugan na ginagamit sa Qiskit Runtime NoiseLearnerOptions:
nl_options = {
"num_randomizations": 32,
"max_layers_to_learn": 2,
"shots_per_randomization": 128,
"layer_pair_depths": [0, 1, 2, 4, 16, 32],
}
# add noise learning options to the overall options
options |= nl_options
Ulit na patakbuhin ang eksperimento gamit ang mga custom na opsyon na ito na na-tune para sa aming circuit. Ang inaasahang runtime ay humigit-kumulang apat na QPU minuto.
tem_job_custom = tem.run(
pubs=pubs, backend_name=backend_name, options=options
)
Kung ang trabaho ay hindi itinakda bilang pribado, maaari nating makuha ang resulta sa ibang pagkakataon. Para magawa iyon, i-save ang job ID na naka-print dito at gamitin ang tem_job_custom = catalog.get_job_by_id("your-job-id").
job_id = tem_job_custom.job_id
print(f"Job ID: {job_id}")
Job ID: 1ba10094-a541-457a-9287-dbd49306d12d
results_custom = tem_job_custom.result()
tem_evs = results_custom[0].data.evs[0]
tem_std = results_custom[0].data.stds[0]
print(f"TEM Result: {tem_evs:.3f} ± {tem_std:.3f}")
TEM Result: 0.956 ± 0.018
Maaari na nating suriin ang mga resulta at ang metadata para makakuha ng pananaw sa eksperimento:
metadata_custom = results_custom[0].metadata
unmitigated_evs = metadata_custom["evs_non_mitigated"][0]
unmitigated_stds = metadata_custom["stds_non_mitigated"][0]
print(f"Unmitigated Result: {unmitigated_evs:.3f} ± {unmitigated_stds:.3f}")
# Exact result for the kicked Ising model from the reference paper
exact_evs = np.cos(2 * h) ** t_steps
print("Exact Result:", exact_evs)
Unmitigated Result: 0.894 ± 0.015
Exact Result: 1.0
# Plot comparing the different expectation values
plt.bar(
["Unmitigated", "TEM"],
[unmitigated_evs, tem_evs],
yerr=[unmitigated_stds, tem_std],
color=["grey", "c"],
)
plt.hlines(y=exact_evs, xmin=-0.5, xmax=1.5, colors="r", linestyles="dashed")
plt.ylabel("Expectation Value")
plt.ylim(0, 1.1)
plt.show()
Sa wakas, maaari nating suriin ang epekto ng mga custom na opsyon sa QPU at classical runtime:
# Get the metadata of the TEM job
job_metadata = results_custom.metadata
# Get the runtime of the TEM job
qpu_runtime = job_metadata["resource_usage"]["RUNNING: EXECUTING_QPU"][
"QPU_TIME"
]
classical_runtime = (
job_metadata["resource_usage"]["RUNNING: OPTIMIZING_FOR_HARDWARE"][
"CPU_TIME"
]
+ job_metadata["resource_usage"]["RUNNING: POST_PROCESSING"]["CPU_TIME"]
)
print(f"QPU Runtime: {qpu_runtime} seconds")
print(f"Classical Runtime: {classical_runtime} seconds")
QPU Runtime: 342.0 seconds
Classical Runtime: 107.632604 seconds
I-scale ang TEM sa malalaking circuit
Ang malalaking circuit ay maaaring, sa prinsipyo, patakbuhin gamit ang TEM function. Gayunpaman, mahalagang maging mulat sa mga limitasyon ng mga classical resources, dahil ang TEM ay isinasagawa sa mga IBM Cloud runner na may potensyal na napakahaba ng run times. Para sa napakalalaking mga circuit, makipag-ugnayan sa TEM support team sa qiskit_ibm@algorithmiq.fi.
Dito tatakbuhin namin ang isang halimbawa na may mas malaki, utility-scale-sized na 30-qubit circuit, na ino-optimize ang mga TEM parameter para sa bilis kaysa sa katumpakan.
# Kicked Ising model parameters
n_qubits = 30
t_steps = 15
h = 0.0
# Load the circuit for the kicked Ising model
circuit = load("ki_30q.qasm")
# Build the observable for the kicked Ising model
observable = xt_observable(n_qubits=n_qubits, t_steps=t_steps)
# Collect the input PUBs, in this case composed of a
# single circuit and observable
pubs = [(circuit, [observable])]
Tukuyin natin ang ilang mga opsyon na nakatuon sa performance:
options = {
"num_randomizations": 32,
"max_layers_to_learn": 2,
"shots_per_randomization": 128,
"layer_pair_depths": [0, 1, 2, 4, 16, 32, 64],
"default_shots": 5_000,
"tem_max_bond_dimension": 128,
"tem_compression_cutoff": 1e-10,
"compute_shadows_bias_from_observable": True,
"private": False,
}
Sa wakas, patakbuhin ang eksperimento, kunin ang resulta, at i-visualize ito. Tatagal ito ng humigit-kumulang 3.5 QPU minuto.
tem_job_large = tem.run(pubs=pubs, backend_name=backend_name, options=options)
job_id = tem_job_large.job_id
print(f"Job ID: {job_id}")
Job ID: 9f3f190f-f4b0-4dcb-bb83-5f71f37d0d77
results_large = tem_job_large.result()
tem_evs = results_large[0].data.evs[0]
tem_std = results_large[0].data.stds[0]
print(f"TEM Result: {tem_evs:.3f} ± {tem_std:.3f}")
# Get the metadata of the TEM job
job_metadata = tem_job_large.result().metadata
# Get the runtime of the TEM job
qpu_runtime = job_metadata["resource_usage"]["RUNNING: EXECUTING_QPU"][
"QPU_TIME"
]
classical_runtime = (
job_metadata["resource_usage"]["RUNNING: OPTIMIZING_FOR_HARDWARE"][
"CPU_TIME"
]
+ job_metadata["resource_usage"]["RUNNING: POST_PROCESSING"]["CPU_TIME"]
)
print(f"QPU Runtime: {qpu_runtime} seconds")
print(f"Classical Runtime: {classical_runtime} seconds")
TEM Result: 0.794 ± 0.026
QPU Runtime: 203.0 seconds
Classical Runtime: 251.71805499999996 seconds
# Plot comparing the different expectation values
metadata_large = results_large[0].metadata
unmitigated_evs = metadata_large["evs_non_mitigated"][0]
unmitigated_stds = metadata_large["stds_non_mitigated"][0]
exact_evs = np.cos(2 * h) ** t_steps
plt.bar(
["Unmitigated", "TEM"],
[unmitigated_evs, tem_evs],
yerr=[unmitigated_stds, tem_std],
color=["grey", "c"],
)
plt.hlines(y=exact_evs, xmin=-0.5, xmax=1.5, colors="r", linestyles="dashed")
plt.ylabel("Expectation Value")
plt.ylim(0, 1.1)
plt.show()