Simulasikan sistem kuantum berhingar dengan perambatan Pauli
Dalam panduan ini kita menggunakan pakej pauli-prop untuk mensimulasikan secara klasik dinamik masa bagi model Ising medan melintang (TFIM) sembilan-qubit berhingar pada kekisi segi empat sama 3x3. Kita menggunakan arahan PauliLindbladError untuk mentakrifkan saluran hingar, , yang bertindak pada satu set lapisan berbelit, . Kemudian kita merambatkan observable, , ke belakang melalui litar berhingar dan menganggarkan nilai jangkaan bagi pelbagai model hingar, serta kes tanpa hingar.

Apabila observable dirambatkan ke belakang melalui litar, setiap saluran hingar, , yang dikaitkan dengan lapisan berbelit, , meredam sebutan Pauli dalam yang anti-kalis tukar tertib dengan penjana Pauli-Lindblad-nya. Secara khusus, jika ialah penjana Pauli bagi dengan kadar, , maka sebutan Pauli, , dalam berubah sebagai: , dengan ialah pekali . Setelah dirambatkan ke permulaan litar, nilai jangkaan terhadap keadaan sifar, , boleh dikira dengan mudah dengan menjumlahkan pekali setiap sebutan pepenjuru dalam (sebutan yang mengandungi atau pada semua qubit).
Aliran kerja:
- Tentukan kekisi TFIM, dan gunakan pewarnaan tepi untuk mengenal pasti set minimum lapisan berbelit
- Hasilkan model hingar sintetik, , bagi setiap lapisan berbelit yang unik,
- Cipta model hingar pelbagai skala untuk mengkaji kesan hingar gate terhadap sistem
- Cipta litar kuantum tanpa hingar dan berhingar untuk pelbagai kedalaman dan skala hingar yang diminati
- Dalam litar berhingar, arahan
PauliLindbladErrordimasukkan sebelum setiap lapisan berbelit
- Dalam litar berhingar, arahan
- Gunakan perambatan Pauli untuk mensimulasikan nilai jangkaan tepat sistem pada pelbagai kedalaman
- Bagi sembilan qubit, ini dilakukan dengan membenarkan berkembang hingga sebutan, meliputi ruang Pauli penuh
- Gunakan perambatan Pauli untuk mensimulasikan nilai jangkaan berhingar
- Perhatikan bagaimana peningkatan hingar gate menjejaskan ketepatan model kuantum
Hasilkan kekisi segi empat sama 3x3 dan cari pewarnaan-4 pada tepi
Bucu dalam graf mewakili qubit, dan tepi mewakili sambungan antara dua qubit. Pewarnaan tepi sepadan dengan lapisan berbelit yang unik dalam litar kuantum supaya gate pada sambungan yang dikaitkan dengan warna berbeza tidak boleh dikenakan serentak.
Mengenal pasti set minimum lapisan berbelit yang unik selalunya penting untuk melaksanakan protokol pembelajaran hingar yang cekap, kerana hingar bagi setiap lapisan mesti dipelajari secara berasingan. Semakin banyak lapisan yang mesti kita pelajari, semakin banyak shot yang perlu kita ambil daripada QPU. Untuk demo ini, kita menggunakan maklumat lapisan untuk membina litar berhingar dan menyuntik arahan PauliLindbladError daripada qiskit-aer sebelum setiap lapisan berbelit untuk memodelkan hingar gate QPU.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "pauli_prop": "pauli-prop", "qiskit": "qiskit", "qiskit_addon_utils": "qiskit-addon-utils", "qiskit_aer": "qiskit-aer", "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")
from collections import defaultdict
import numpy as np
from qiskit.transpiler import CouplingMap
from qiskit_addon_utils.coloring import auto_color_edges
# Define rectangular square-lattice on 20 qubits
num_rows = 3
num_cols = 3
num_qubits = num_rows * num_cols
coupling_map = CouplingMap.from_grid(
num_rows=num_rows, num_columns=num_cols, bidirectional=False
)
# Create mapping from color to edge list
coloring = auto_color_edges(coupling_map.get_edges())
color_to_edge = defaultdict(list)
for edge, color in coloring.items():
color_to_edge[color].append(edge)
from rustworkx import PyDiGraph
from rustworkx.visualization import graphviz_draw
# Inspect graph coupling and unique entangling layers
print(
f"The circuit will have {num_qubits} qubits and {len(color_to_edge)} unique entangling layers."
)
sq_lattice = PyDiGraph()
sq_lattice.extend_from_weighted_edge_list(
[
(source, target, color)
for ((source, target), color) in coloring.items()
]
)
def color_edge_4color(edge):
color_dict = {0: "red", 1: "green", 2: "blue", 3: "orange"}
return {"color": color_dict[edge]}
graphviz_draw(sq_lattice, edge_attr_fn=color_edge_4color, method="neato")
The circuit will have 9 qubits and 4 unique entangling layers.

Hasilkan model hingar sintetik
Sebelum mencipta litar kuantum, kita menghasilkan model hingar (contoh PauliLindbladError) bagi setiap lapisan berbelit. Kita akan membenamkannya sebagai arahan dalam litar kuantum kita kemudian. Bagi setiap lapisan, kita menghasilkan saluran hingar pelbagai skala. Secara khusus, kita menghasilkan model hingar dengan Error Per Layered Gate (EPLG) kira-kira .0004, .0008, .0012, .0016, dan .002.
from qiskit.quantum_info import SparsePauliOp, pauli_basis
from qiskit_aer.noise import PauliLindbladError
# Pauli-Lindblad noise parameters
seed = 1764
target_EPLGs = [0.0004, 0.0008, 0.0012, 0.0016, 0.002]
def generate_random_pauli_lindblad_noise(
edges,
num_qubits: int | None = None,
noise_scale: float = 1e-3,
seed: int | None = None,
) -> PauliLindbladError:
"""Generate random Pauli-Lindblad noise over the full Pauli basis."""
if num_qubits is None:
num_qubits = np.max(edges)
basis_paulis = [p for p in pauli_basis(2) if np.sum(p.x + p.z)]
basis_paulis = SparsePauliOp.from_sparse_list(
[
(pauli.to_label(), edge, 1)
for pauli in basis_paulis
for edge in edges
],
num_qubits=num_qubits,
)
basis_paulis = basis_paulis.simplify()
basis_paulis = basis_paulis.paulis
rng = np.random.default_rng(seed=seed)
rates = rng.random(len(basis_paulis)) * noise_scale
return PauliLindbladError(generators=basis_paulis, rates=rates)
num_generators = (
(num_rows * num_cols)
+ (num_rows - 1) * num_cols
+ num_rows * (num_cols - 1)
)
noise_scales = [
EPLG * (num_rows * num_cols) / num_generators for EPLG in target_EPLGs
]
noise_models_per_EPLG = [
[
generate_random_pauli_lindblad_noise(
color_to_edge[color],
num_qubits=num_qubits,
noise_scale=noise_scale,
seed=seed,
)
for color in range(len(color_to_edge))
]
for noise_scale in noise_scales
]
Cipta litar kuantum
Untuk demo ini, kita mensimulasikan dinamik masa model Ising medan melintang (TFIM) bagi bilangan langkah Trotter yang meningkat (1-10 langkah). Bagi setiap 10 kedalaman litar, kita mensimulasikan kesan hingar gate, dengan model hingar pelbagai skala (EPLGs = .0004, .0008, .0012, .0016, .002). Hingar dimasukkan ke dalam QuantumCircuit sebagai arahan PauliLindbladError daripada Qiskit Aer. Hamiltonian yang dipertimbangkan ialah:
dengan menerangkan gandingan spin jiran terdekat, , dan ialah medan melintang global.
Di sini kita melaksanakan Hamiltonian berevolusi masa merentasi pelbagai skala masa dan hingar. Kita mencipta 60 litar kesemuanya: 10 litar tanpa hingar yang berbeza dalam kedalaman Trotter, dan 50 litar berhingar untuk 10 kedalaman Trotter merentasi lima skala hingar. Diberi graf kesambungan, model ini diparameterkan oleh beberapa pemboleh ubah:
num_steps: Bilangan langkah TrotterJ: Kekuatan gandingan tapak yang bersambungh: Kekuatan medan magnet luarandt: Perubahan masa merentasi satu langkah Trotterinitial_state_angle: Pengujaan awal, , yang dikenakan secara seragam pada semua qubit
from typing import Any
from qiskit import QuantumCircuit
# Ising model parameters
num_steps = 10
J = -1.0
dt = 0.25 / abs(J)
h = 2.0 * abs(J)
initial_state_angle = np.pi / 18.0
rx_angle = 2.0 * h * dt
rzz_angle = 2.0 * J * dt
def generate_ising_circuit(
num_qubits: int,
num_steps: int,
rx_angle: float,
rzz_angle: float,
coloring: dict[Any, list[tuple[int, int]]],
layer_noise_models: list[PauliLindbladError] | None = None,
initial_state_angle: float | None = None,
) -> QuantumCircuit:
"""Generate a quantum circuit implementing a transverse-field Ising model"""
qc = QuantumCircuit(num_qubits)
if initial_state_angle:
qc.ry(initial_state_angle, range(num_qubits))
qc.rx(rx_angle / 2, range(num_qubits))
for i in range(num_steps):
for j, layer in enumerate(coloring):
edges = coloring[layer]
if layer_noise_models:
qc.append(layer_noise_models[j], qargs=range(num_qubits))
for edge in edges:
qc.rzz(rzz_angle, *edge)
if i == num_steps - 1:
qc.rx(rx_angle / 2, range(num_qubits))
else:
qc.rx(rx_angle, range(num_qubits))
return qc
# Create the noiseless and noisy circuits
noiseless_circs = []
noisy_circs = []
for steps in range(1, num_steps + 1):
noiseless_circs.append(
generate_ising_circuit(
num_qubits,
steps,
rx_angle,
rzz_angle,
color_to_edge,
initial_state_angle=initial_state_angle,
)
)
noisy_circs_per_step = []
for noise_models in noise_models_per_EPLG:
noisy_circs_per_step.append(
generate_ising_circuit(
num_qubits,
steps,
rx_angle,
rzz_angle,
color_to_edge,
layer_noise_models=noise_models,
initial_state_angle=initial_state_angle,
)
)
noisy_circs.append(noisy_circs_per_step)
print(
f"{num_steps} noiseless and {num_steps * len(target_EPLGs)} noisy Trotter circuits generated. {num_steps} different depths across {len(target_EPLGs)} different noise models"
)
print("\nBelow: Initial state and one noisy Trotter step.")
noisy_circs[0][0].draw("mpl", fold=-1)
10 noiseless and 50 noisy Trotter circuits generated. 10 different depths across 5 different noise models
Below: Initial state and one noisy Trotter step.

Tentukan observable dan jalankan simulasi
Untuk demo ini, kita mensimulasikan nilai jangkaan bagi korelator dua-tapak purata:
dengan sepadan dengan putaran seragam pada semua qubit, menerangkan lapisan Trotter, dan mengindeks semua pasangan bucu yang bersambung pada kekisi.
Akhir sekali, kita menggunakan pauli_prop untuk mensimulasikan nilai jangkaan observable bagi setiap litar. Untuk demo sembilan-qubit ini, kita melakukan semua simulasi secara tepat. Tiada pemangkasan perambatan Pauli akan dilakukan; oleh itu, perbezaan nilai jangkaan merentasi model hingar yang berbeza boleh dikaitkan sepenuhnya dengan ralat gate. Proses simulasi dikendalikan dalam empat langkah:
- Evolusikan gate Clifford dalam litar ke hadapan litar menggunakan
pauli_prop.evolve_through_cliffords - Rambatkan observable melalui bahagian bukan Clifford litar menggunakan
pauli_prop.propagate_through_circuit- Kita melakukan simulasi tepat dengan membenarkan observable berkembang hingga saiz ruang Pauli penuh,
- Rambatkan observable yang telah berevolusi melalui bahagian Clifford litar menggunakan
SparsePauliOp.evolveQiskit - Anggarkan nilai jangkaan terhadap keadaan sifar, , dengan menjumlahkan pekali setiap sebutan pepenjuru dalam (sebutan yang mengandungi atau pada semua qubit)
import time
from pauli_prop import evolve_through_cliffords, propagate_through_circuit
from qiskit.quantum_info import Pauli
# Average ZZ-correlator observable
id_pauli = Pauli("I" * num_qubits)
observable = 2 * SparsePauliOp(
[
id_pauli.dot(Pauli("ZZ"), [i, j])
for i in range(num_qubits)
for j in range(i + 1, num_qubits)
]
)
observable /= num_qubits**2
# Pauli propagation parameters
max_terms = 4**num_qubits # Exact propagation
atol = 1e-12
# Run simulations
exact_evs = []
noisy_evs = [[] for _ in range(len(target_EPLGs))]
st = time.perf_counter()
for i, noiseless_circ in enumerate(noiseless_circs):
cliff, non_cliff = evolve_through_cliffords(noiseless_circ)
evolved_obs = propagate_through_circuit(
observable, non_cliff, max_terms=max_terms, atol=atol, frame="h"
)[0]
evolved_obs.paulis = evolved_obs.paulis.evolve(cliff, frame="h")
exact_evs.append(
float(evolved_obs.coeffs[~evolved_obs.paulis.x.any(axis=1)].sum())
)
for j in range(len(target_EPLGs)):
noisy_circ = noisy_circs[i][j]
cliff, non_cliff = evolve_through_cliffords(noisy_circ)
evolved_obs = propagate_through_circuit(
observable, non_cliff, max_terms=max_terms, atol=1e-12, frame="h"
)[0]
evolved_obs.paulis = evolved_obs.paulis.evolve(cliff, frame="h")
noisy_evs[j].append(
float(evolved_obs.coeffs[~evolved_obs.paulis.x.any(axis=1)].sum())
)
print(
f"Ran {len(noiseless_circs)} noiseless and {len(target_EPLGs) * num_steps} noisy simulations in {int(time.perf_counter() - st)}s."
)
Ran 10 noiseless and 50 noisy simulations in 103s.
Perhatikan kesan ralat gate terhadap model
Ingat bahawa, memandangkan ini ialah eksperimen sembilan-qubit, rutin perambatan Pauli adalah tepat, dan semua ralat dalam plot hingar boleh dikaitkan dengan ralat gate.
import matplotlib.pyplot as plt
xs = range(1, num_steps + 1)
plt.plot(xs, exact_evs, label="Noiseless", color="black", marker="o")
colors = [".3", ".4", ".5", ".6", ".7"]
for i, evs in enumerate(noisy_evs):
plt.plot(
xs,
evs,
label=f"{target_EPLGs[i]} EPLG",
linestyle="--",
color=colors[i],
marker="o",
)
plt.xlabel("# Trotter steps")
plt.ylabel(r"$\langle Z_{tot}^2 \rangle$")
plt.legend()
plt.show()
