Demo 3:QSVT sign 近似

第 5 章 哈密顿量模拟与 QSP · 本章演示 · 代码演示总索引

可视化:3 子图(相位+多项式+测量) —— 17 个 x 处 P(0)/P(1) 与 sign(x) 对比

对应教程:第 5 章 哈密顿量模拟与 QSP 中相关小节 · 依赖安装:pip install "unified-quantum[visualization,simulation]"

实现要点

模型: QSVT 在单比特上, 信号算子 W(x) = e^{i arccos(x) X} (在 X 基上对角), 处理器 S(phi) = e^{i phi Z} = R_z(2 phi). d=3 阶 QSVT: U_QSVT(x) = S(phi_0) W S(phi_1) W S(phi_2) W S(phi_3)

通过数值优化在 x in [-1, 1] 上最小化 ||U[0,0](x) - sign(x)||^2, 得到一组近似 sign 的相位因子. 把 QSVT 电路作用在 |+>, 测 P(0)/P(1).

相位因子只取 4 个参数, 所以多项式是次数 <= 3 的奇函数多项式, d=3 限制下 sign 只能近似, 不是精确符号函数.

完整源码

demos/ch05-hamiltonian-qsp/03_qsvt_sign.py
  1"""
  2ch05 演示 3: QSVT sign 近似 (单比特, d=3 奇数阶多项式).
  3
  4模型: QSVT 在单比特上, 信号算子 W(x) = e^{i arccos(x) X} (在 X 基上对角),
  5处理器 S(phi) = e^{i phi Z} = R_z(2 phi).
  6d=3 阶 QSVT: U_QSVT(x) = S(phi_0) W S(phi_1) W S(phi_2) W S(phi_3)
  7
  8通过数值优化在 x in [-1, 1] 上最小化 \\||U\\[0,0\\](x) - sign(x)\\||^2,
  9得到一组近似 sign 的相位因子. 把 QSVT 电路作用在 |+>, 测 P(0)/P(1).
 10
 11相位因子只取 4 个参数, 所以多项式是次数 <= 3 的奇函数多项式,
 12d=3 限制下 sign 只能近似, 不是精确符号函数.
 13
 14对应教程: chenzhaoyun.com/quantum-tutorial/ch05-hamiltonian-qsp/qsvt-tutorial.html
 15依赖: pip install unified-quantum[visualization]
 16运行: python demos/ch05-hamiltonian-qsp/03_qsvt_sign.py
 17"""
 18from uniqc import Circuit, submit_task, wait_for_result
 19import matplotlib
 20matplotlib.use("Agg")
 21import matplotlib.pyplot as plt
 22import numpy as np
 23from pathlib import Path
 24from scipy.optimize import minimize
 25
 26OUT = Path(__file__).parent
 27SHOTS = 4000
 28N_PHASES = 4  # d=3 -> 4 phases
 29
 30
 31def qs_unitary(x, phases):
 32    """Analytical QSVT unitary with W(x) = e^{i arccos(x) X} (standard convention)."""
 33    theta = np.arccos(x)
 34    c, si = np.cos(theta), np.sin(theta)
 35    W = np.array([[c, 1j * si], [1j * si, c]], dtype=complex)
 36    S = lambda phi: np.diag([np.exp(1j * phi), np.exp(-1j * phi)])
 37    U = S(phases[0]) @ W @ S(phases[1])
 38    U = U @ W @ S(phases[2])
 39    U = U @ W @ S(phases[3])
 40    return U
 41
 42
 43def loss_sign(phases):
 44    err = 0.0
 45    for x in np.linspace(-1, 1, 41):
 46        U = qs_unitary(x, phases)
 47        target = float(np.sign(x)) if abs(x) > 0.01 else 0.0
 48        err += abs(U[0, 0] - target) ** 2
 49    return err
 50
 51
 52result = minimize(loss_sign, [0.0] * N_PHASES, method="Nelder-Mead",
 53                   options={"xatol": 1e-7, "fatol": 1e-9, "maxiter": 5000})
 54PHASES = result.x.tolist()
 55
 56
 57def build_qsvt_circuit(x):
 58    theta = float(np.arccos(x))
 59    c = Circuit()
 60    c.h(0)
 61    c.rz(0, 2 * PHASES[0])
 62    c.rx(0, -2 * theta)
 63    c.rz(0, 2 * PHASES[1])
 64    c.rx(0, -2 * theta)
 65    c.rz(0, 2 * PHASES[2])
 66    c.rx(0, -2 * theta)
 67    c.rz(0, 2 * PHASES[3])
 68    return c
 69
 70
 71x_test = np.linspace(-1.0, 1.0, 17)
 72probs_p0 = []
 73probs_p1 = []
 74poly_vals = []
 75sign_vals = []
 76for x in x_test:
 77    c = build_qsvt_circuit(x)
 78    c.measure(0)
 79    res = wait_for_result(submit_task(circuit=c, backend="dummy:local:simulator",
 80                                      shots=SHOTS))
 81    cnt = res.counts
 82    total = sum(cnt.values())
 83    probs_p0.append(cnt.get("0", 0) / total)
 84    probs_p1.append(cnt.get("1", 0) / total)
 85    poly_vals.append(qs_unitary(x, PHASES)[0, 0].real)
 86    sign_vals.append(float(np.sign(x)) if abs(x) > 1e-9 else 0.0)
 87
 88
 89fig, axes = plt.subplots(1, 3, figsize=(16.0, 4.6))
 90
 91ax = axes[0]
 92phi_labels = [f"phi_{k}" for k in range(N_PHASES)]
 93colors = ["#1f77b4" if abs(p) < 0.01 else "#d62728" for p in PHASES]
 94bars = ax.bar(range(N_PHASES), PHASES, color=colors, edgecolor="black")
 95ax.set_xticks(range(N_PHASES))
 96ax.set_xticklabels(phi_labels)
 97ax.axhline(0, color="gray", lw=0.5)
 98ax.set_xlabel("phase index")
 99ax.set_ylabel("phase value (rad)")
100ax.set_title(
101    f"QSVT phase factors (d={N_PHASES - 1}, optimized for sign)\n"
102    f"red = nonzero phase"
103)
104for i, p in enumerate(PHASES):
105    ax.text(i, p + (0.05 if p >= 0 else -0.08), f"{p:.3f}",
106            ha="center", va="bottom" if p >= 0 else "top", fontsize=9)
107ax.grid(axis="y", alpha=0.3)
108
109ax = axes[1]
110x_fine = np.linspace(-1, 1, 201)
111poly_fine = [qs_unitary(x, PHASES)[0, 0].real for x in x_fine]
112sign_fine = [float(np.sign(x)) if abs(x) > 1e-9 else 0.0 for x in x_fine]
113ax.plot(x_fine, poly_fine, "-", color="#1f77b4", lw=2,
114        label="QSVT polynomial P(x) = U[0,0]")
115ax.plot(x_fine, sign_fine, "--", color="#d62728", lw=2, label="ideal sign(x)")
116ax.axhline(0, color="gray", lw=0.5)
117ax.axvline(0, color="gray", lw=0.5)
118ax.set_xlabel("signal value x")
119ax.set_ylabel("polynomial value")
120ax.set_title(
121    f"Polynomial implemented by QSVT phases\n"
122    f"(d={N_PHASES - 1} Chebyshev-style, sign approx)"
123)
124ax.set_ylim(-1.5, 1.5)
125ax.legend(loc="upper left", fontsize=9)
126ax.grid(True, alpha=0.3)
127
128ax = axes[2]
129ax.plot(x_test, sign_vals, "k--", lw=1.5, label="ideal sign(x)")
130ax.scatter(x_test, [v for v in probs_p0], color="#1f77b4", s=60,
131           edgecolor="black", label=f"measured P(0) (shots={SHOTS})")
132ax.scatter(x_test, [v for v in probs_p1], color="#d62728", s=60,
133           edgecolor="black", label="measured P(1)", marker="s")
134for x, p0, p1 in zip(x_test, probs_p0, probs_p1):
135    if p0 > 0.55 or p1 > 0.55:
136        ax.text(x, max(p0, p1) + 0.05,
137                f"P(0)={p0:.2f}\nP(1)={p1:.2f}",
138                ha="center", va="bottom", fontsize=7)
139ax.set_xlabel("signal value x")
140ax.set_ylabel("P(0), P(1)")
141ax.set_title(
142    f"QSVT applied to |+>, measured in Z basis\n"
143    f"sign-like behavior: positive x -> mostly |0>, negative x -> mostly |1>"
144)
145ax.set_ylim(-0.05, 1.2)
146ax.legend(loc="upper center", fontsize=8)
147ax.grid(True, alpha=0.3)
148
149fig.suptitle(
150    f"QSVT sign approximation (single qubit, d=3)  "
151    f"(loss = {loss_sign(PHASES):.3f})",
152    fontsize=13, y=1.02,
153)
154plt.tight_layout()
155plt.savefig(OUT / "03_qsvt_sign.png", dpi=120, bbox_inches="tight")
156plt.close()
157
158
159print("ch05-hamiltonian-qsp demo 3: QSVT sign approximation (d=3)")
160print(f"  Phase factors (optimized for sign):")
161for i, p in enumerate(PHASES):
162    print(f"    phi_{i} = {p:.6f}")
163print(f"  loss = ||U[0,0](x) - sign(x)||^2 = {loss_sign(PHASES):.4f}")
164print(f"  Test points x and measured P(0), P(1):")
165for x, p0, p1 in zip(x_test, probs_p0, probs_p1):
166    sign_x = float(np.sign(x)) if abs(x) > 1e-9 else 0.0
167    print(f"    x={x:+.3f}: P(0)={p0:.3f}, P(1)={p1:.3f}  (sign={int(sign_x):+d})")
168print(f"  saved: {OUT / '03_qsvt_sign.png'}")

运行结果

Demo 3:QSVT sign 近似

运行方式

# 仓库根目录执行;输出 PNG 到 demos/ch05-hamiltonian-qsp/03_qsvt_sign.png,关键统计到 stdout
.venv/bin/python3 demos/ch05-hamiltonian-qsp/03_qsvt_sign.py

← 本章演示 · ↑ 代码演示总索引 · ⌂ 教程门户