Demo 1:Trotter Ising 链¶
可视化:3 子图(H+误差+末态分布) —— 一阶/二阶 Trotter 误差对数曲线
对应教程:第 5 章 哈密顿量模拟与 QSP 中相关小节 · 依赖安装:pip install "unified-quantum[visualization,simulation]"
实现要点¶
模型: H = -J Σ_{i=1}^{n-1} Z_i Z_{i+1} - h Σ_{i=1}^{n} X_i, n=4, J=1, h=0.5, t=1. 对 r ∈ {1, 2, 4, 8, 16, 32} 步数分别构造
一阶 Trotter: (Π_k e^{-iα_k H_k t/r})^r
二阶 Strang: 半步正序 + 半步反序 通过 c.get_matrix() 与精确 exp(-iHt) 比较 Frobenius 范数误差. ZZ 项 e^{iJδ Z_i Z_{i+1}} 由 CNOT(i,j) · R_z(j, -2Jδ) · CNOT(i,j) 实现. X 项 e^{ihδ X_j} = R_x(j, -2hδ).
完整源码¶
demos/ch05-hamiltonian-qsp/01_trotter_ising.py¶
1"""
2ch05 演示 1: 横场 Ising 链 4-qubit Trotter 一阶/二阶近似演化。
3
4模型: H = -J Σ_{i=1}^{n-1} Z_i Z_{i+1} - h Σ_{i=1}^{n} X_i, n=4, J=1, h=0.5, t=1.
5对 r ∈ {1, 2, 4, 8, 16, 32} 步数分别构造
6 - 一阶 Trotter: (Π_k e^{-iα_k H_k t/r})^r
7 - 二阶 Strang: 半步正序 + 半步反序
8通过 c.get_matrix() 与精确 exp(-iHt) 比较 Frobenius 范数误差.
9ZZ 项 e^{iJδ Z_i Z_{i+1}} 由 CNOT(i,j) · R_z(j, -2Jδ) · CNOT(i,j) 实现.
10X 项 e^{ihδ X_j} = R_x(j, -2hδ).
11
12对应教程: chenzhaoyun.com/quantum-tutorial/ch05-hamiltonian-qsp/trotterization-tutorial.html
13依赖: pip install unified-quantum[visualization]
14运行: python demos/ch05-hamiltonian-qsp/01_trotter_ising.py
15"""
16from uniqc import Circuit, submit_task, wait_for_result
17import matplotlib
18matplotlib.use("Agg")
19import matplotlib.pyplot as plt
20import numpy as np
21from pathlib import Path
22
23OUT = Path(__file__).parent
24
25N_QUBITS = 4
26J = 1.0
27H_FIELD = 0.5
28T_TOTAL = 1.0
29R_VALUES = [1, 2, 4, 8, 16, 32]
30
31
32def build_ising_hamiltonian(n: int, j: float, h: float) -> np.ndarray:
33 """Transverse Ising: H = -j Σ Z_i Z_{i+1} - h Σ X_i (dense matrix)."""
34 dim = 2 ** n
35 I = np.eye(2, dtype=complex)
36 X = np.array([[0, 1], [1, 0]], dtype=complex)
37 Z = np.array([[1, 0], [0, -1]], dtype=complex)
38
39 def kron_n(op: np.ndarray, idx: int) -> np.ndarray:
40 out = np.array([[1.0]], dtype=complex)
41 for q in range(n):
42 out = np.kron(out, op if q == idx else I)
43 return out
44
45 H_mat = np.zeros((dim, dim), dtype=complex)
46 for i in range(n - 1):
47 H_mat += -j * kron_n(Z, i) @ kron_n(Z, i + 1)
48 for i in range(n):
49 H_mat += -h * kron_n(X, i)
50 return H_mat
51
52
53def trotter_step_1st(c: Circuit, n: int, j: float, h: float, delta: float) -> None:
54 """One 1st-order Trotter step: all ZZ terms then all X terms."""
55 for i in range(n - 1):
56 c.cnot(i, i + 1)
57 c.rz(i + 1, -2.0 * j * delta)
58 c.cnot(i, i + 1)
59 for i in range(n):
60 c.rx(i, -2.0 * h * delta)
61
62
63def trotter_step_2nd(c: Circuit, n: int, j: float, h: float, delta: float) -> None:
64 """One 2nd-order Strang step: half-step forward + half-step reversed."""
65 half = delta / 2.0
66 for i in range(n - 1):
67 c.cnot(i, i + 1)
68 c.rz(i + 1, -2.0 * j * half)
69 c.cnot(i, i + 1)
70 for i in range(n):
71 c.rx(i, -2.0 * h * half)
72 for i in range(n):
73 c.rx(i, -2.0 * h * half)
74 for i in range(n - 2, -1, -1):
75 c.cnot(i, i + 1)
76 c.rz(i + 1, -2.0 * j * half)
77 c.cnot(i, i + 1)
78
79
80def build_trotter_circuit(n: int, j: float, h: float, t: float,
81 r: int, order: int) -> Circuit:
82 c = Circuit()
83 delta = t / r
84 for _ in range(r):
85 if order == 1:
86 trotter_step_1st(c, n, j, h, delta)
87 else:
88 trotter_step_2nd(c, n, j, h, delta)
89 return c
90
91
92H_mat = build_ising_hamiltonian(N_QUBITS, J, H_FIELD)
93from scipy.linalg import expm
94U_exact = expm(-1j * H_mat * T_TOTAL)
95
96errors = {1: [], 2: []}
97for r in R_VALUES:
98 for order in (1, 2):
99 circ = build_trotter_circuit(N_QUBITS, J, H_FIELD, T_TOTAL, r, order)
100 U_approx = circ.get_matrix()
101 err = np.linalg.norm(U_approx - U_exact, ord="fro")
102 errors[order].append(err)
103
104c_verify = build_trotter_circuit(N_QUBITS, J, H_FIELD, T_TOTAL, r=8, order=2)
105for q in range(N_QUBITS):
106 c_verify.h(q)
107for q in range(N_QUBITS):
108 c_verify.measure(q)
109res = wait_for_result(submit_task(circuit=c_verify,
110 backend="dummy:local:simulator", shots=2000))
111verify_counts = res.counts
112
113fig, axes = plt.subplots(1, 3, figsize=(16.0, 4.8))
114
115ax = axes[0]
116H_show = np.real(H_mat)
117vmax = np.max(np.abs(H_show))
118im = ax.imshow(H_show, cmap="RdBu_r", vmin=-vmax, vmax=vmax)
119ax.set_title(
120 f"Transverse Ising H (n={N_QUBITS})\n"
121 f"H = -J ΣZ_i Z_{{i+1}} - h ΣX_i, J={J}, h={H_FIELD}"
122)
123ax.set_xlabel("column index")
124ax.set_ylabel("row index")
125ax.set_xticks(np.arange(2 ** N_QUBITS))
126ax.set_yticks(np.arange(2 ** N_QUBITS))
127ax.set_xticklabels([f"{i:0{N_QUBITS}b}" for i in range(2 ** N_QUBITS)], fontsize=6)
128ax.set_yticklabels([f"{i:0{N_QUBITS}b}" for i in range(2 ** N_QUBITS)], fontsize=6)
129plt.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
130
131ax = axes[1]
132rs = np.array(R_VALUES, dtype=float)
133ax.loglog(rs, errors[1], "o-", color="#d62728", linewidth=2, markersize=8,
134 label="1st-order Trotter")
135ax.loglog(rs, errors[2], "s-", color="#1f77b4", linewidth=2, markersize=8,
136 label="2nd-order Strang")
137ref1 = errors[1][0] / rs[0]
138ref2 = errors[2][0] / rs[0] ** 2
139ax.loglog(rs, ref1 / rs, "--", color="#d62728", alpha=0.5, label=r"$\propto 1/r$ slope")
140ax.loglog(rs, ref2 / rs ** 2, "--", color="#1f77b4", alpha=0.5, label=r"$\propto 1/r^2$ slope")
141ax.set_xlabel("Trotter steps r")
142ax.set_ylabel(r"$\|U_{\rm Trotter} - e^{-iHt}\|_F$")
143ax.set_title(
144 f"Trotter error vs r (n={N_QUBITS}, t={T_TOTAL})\n"
145 f"exact via numpy.linalg.matrix_power-style expm"
146)
147ax.legend(loc="lower left", fontsize=9)
148ax.grid(True, which="both", alpha=0.3)
149
150ax = axes[2]
151N = 2 ** N_QUBITS
152labels_n = [f"{i:0{N_QUBITS}b}" for i in range(N)]
153vals = np.array([verify_counts.get(lbl, 0) for lbl in labels_n])
154vals_pct = vals / vals.sum() * 100
155order2_idx = np.argsort(vals_pct)[::-1][:6]
156colors = ["#1f77b4" if i in order2_idx else "#cccccc" for i in range(N)]
157ax.bar(np.arange(N), vals_pct, color=colors, edgecolor="black", linewidth=0.5)
158for i in order2_idx:
159 ax.text(i, vals_pct[i] + 1.5, f"{vals_pct[i]:.1f}%",
160 ha="center", va="bottom", fontsize=8, color="darkblue")
161ax.set_xticks(np.arange(N))
162ax.set_xticklabels(labels_n, rotation=0, fontsize=7)
163ax.set_xlabel("4-qubit measurement outcome (q3 q2 q1 q0)")
164ax.set_ylabel("probability (%)")
165ax.set_title(
166 "After Trotter (r=8, 2nd) on |+>^⊗n\n"
167 "top-6 outcomes (broadening from Trotter error)"
168)
169ax.grid(axis="y", alpha=0.3)
170
171fig.suptitle(
172 f"Trotterization on 4-qubit transverse-field Ising "
173 f"(J={J}, h={H_FIELD}, t={T_TOTAL})",
174 fontsize=13, y=1.02,
175)
176plt.tight_layout()
177plt.savefig(OUT / "01_trotter_ising.png", dpi=120, bbox_inches="tight")
178plt.close()
179
180
181slope1 = np.polyfit(np.log(R_VALUES), np.log(errors[1]), 1)[0]
182slope2 = np.polyfit(np.log(R_VALUES), np.log(errors[2]), 1)[0]
183print("ch05-hamiltonian-qsp demo 1: Trotter on 4-qubit transverse Ising")
184print(f" shots (verification only): 2000")
185print(f" Trotter steps tested: {R_VALUES}")
186print(f" exact ||U||_F (sanity): {np.linalg.norm(U_exact, 'fro'):.6f}")
187for r, e1, e2 in zip(R_VALUES, errors[1], errors[2]):
188 print(f" r={r:>2} order=1 err={e1:.4e} order=2 err={e2:.4e}")
189print(f" log-log slope: order-1 = {slope1:.2f} (theory -1), order-2 = {slope2:.2f} (theory -2)")
190print(f" verification r=8 order=2 measurement: dominant outcome = "
191 f"{labels_n[np.argmax(vals_pct)]} (p={vals_pct.max():.3f}%)")
192print(f" saved: {OUT / '01_trotter_ising.png'}")
运行结果¶

运行方式¶
# 仓库根目录执行;输出 PNG 到 demos/ch05-hamiltonian-qsp/01_trotter_ising.png,关键统计到 stdout
.venv/bin/python3 demos/ch05-hamiltonian-qsp/01_trotter_ising.py