Demo 3:QFT 振幅相位

第 3 章 量子算法基础 · 本章演示 · 代码演示总索引

可视化:双图:振幅+相位 —— QFT_4|0010⟩ 16 个分量的极坐标散点

对应教程:第 3 章 量子算法基础 中相关小节 · 依赖安装:pip install "unified-quantum[visualization,simulation]"

实现要点

完整源码

demos/ch03-algo-basics/03_qft_4qubit.py
  1"""
  2ch03 演示 3:QFT_4 作用在 |0010⟩ 上,画振幅-相位极坐标散点
  3
  4对应教程:chenzhaoyun.com/quantum-tutorial/ch03-algo-basics/quantum-fourier-transform.html
  5依赖:pip install unified-quantum[visualization]
  6运行:python demos/ch03-algo-basics/03_qft_4qubit.py
  7"""
  8from uniqc import Circuit, qft_circuit, submit_task, wait_for_result
  9import matplotlib
 10matplotlib.use("Agg")
 11import matplotlib.pyplot as plt
 12import numpy as np
 13from pathlib import Path
 14
 15OUT = Path(__file__).parent
 16N_QUBITS = 4
 17INPUT_INT = 2  # |0010>
 18SHOTS = 2000
 19
 20# === 1. 构造 |0010> + QFT_4,并跑 dummy backend 拿计数做交叉验证 ===
 21prep = Circuit()
 22# 把 qubit 1 翻成 1,得到 |0010>(qubit 0 是最低位)
 23prep.x(1)
 24prep.add_circuit(qft_circuit(n_qubits=N_QUBITS, swaps=True))
 25for q in range(N_QUBITS):
 26    prep.measure(q)
 27
 28result = wait_for_result(
 29    submit_task(circuit=prep, backend="dummy:local:simulator", shots=SHOTS)
 30)
 31counts = result.counts
 32total = sum(counts.values())
 33
 34# === 2. 用 Circuit.get_matrix() 解析地拿 4-qubit 状态向量(拿相位) ===
 35qft = qft_circuit(n_qubits=N_QUBITS, swaps=True)
 36U = qft.get_matrix()
 37state_in = np.zeros(2 ** N_QUBITS, dtype=complex)
 38state_in[INPUT_INT] = 1.0
 39state_out = U @ state_in  # QFT|0010> 的精确振幅
 40
 41amps = np.abs(state_out) ** 2
 42phases = np.angle(state_out)  # in (-pi, pi]
 43labels = [f"{i:0{N_QUBITS}b}" for i in range(2 ** N_QUBITS)]
 44
 45# 模拟测量的频率(仅用来显示在标注里)
 46empirical = np.array([counts.get(lbl, 0) / total for lbl in labels])
 47
 48# === 3. matplotlib 极坐标散点(振幅半径、相位角度) ===
 49fig, axes = plt.subplots(1, 2, figsize=(13, 6),
 50                         subplot_kw={"projection": "polar"})
 51
 52# 左图:所有 16 个分量的振幅-相位
 53ax = axes[0]
 54ax.scatter(phases, amps, s=120, c="#1f77b4", edgecolor="black", zorder=3)
 55ax.set_theta_zero_location("E")
 56ax.set_theta_direction(1)
 57ax.set_ylim(0, 0.30)
 58ax.set_yticks([0.0625, 0.125, 0.1875])
 59ax.set_yticklabels(["1/16", "1/8", "3/16"], fontsize=8)
 60ax.set_xlabel("phase (rad)")
 61ax.set_title(
 62    f"QFT_4 |{INPUT_INT:0{N_QUBITS}b}> : all 16 amplitudes\n"
 63    f"|amplitude|^2 = {amps.mean():.3f} (uniform → 1/{2**N_QUBITS})",
 64    fontsize=10,
 65    pad=18,
 66)
 67
 68# 右图:仅展示相位(半径固定),突出 QFT 相位编码
 69ax = axes[1]
 70fixed_r = 0.25
 71ax.scatter(phases, np.full_like(phases, fixed_r), s=140, c="#d62728",
 72           edgecolor="black", zorder=3)
 73# 用线连接相邻角度方便观察
 74order = np.argsort(phases)
 75ax.plot(phases[order], np.full_like(phases[order], fixed_r),
 76        color="#888", alpha=0.5, lw=1)
 77ax.set_theta_zero_location("E")
 78ax.set_theta_direction(1)
 79ax.set_ylim(0, 0.30)
 80ax.set_yticks([fixed_r])
 81ax.set_yticklabels([f"r={fixed_r}"], fontsize=8)
 82ax.set_xlabel("phase (rad)")
 83ax.set_title(
 84    f"Phase pattern of QFT_4 |{INPUT_INT:0{N_QUBITS}b}>\n"
 85    f"phase(k) = 2π·k·x / 2^n   (x={INPUT_INT}, n={N_QUBITS})",
 86    fontsize=10,
 87    pad=18,
 88)
 89
 90# 在散点旁标注 3 个有代表性的标签
 91for k in (0, 4, 8):
 92    ax = axes[0]
 93    ax.annotate(
 94        f"|{k:0{N_QUBITS}b}>",
 95        xy=(phases[k], amps[k]),
 96        xytext=(phases[k] + 0.15, amps[k] + 0.04),
 97        fontsize=8, arrowprops=dict(arrowstyle="-", color="gray", lw=0.5),
 98    )
 99
100fig.suptitle(
101    f"Quantum Fourier Transform on {N_QUBITS} qubits, input |{INPUT_INT:0{N_QUBITS}b}>  "
102    f"({SHOTS} shots cross-checked, dummy:local:simulator)",
103    fontsize=12, y=1.02,
104)
105plt.tight_layout()
106plt.savefig(OUT / "03_qft_4qubit.png", dpi=120, bbox_inches="tight")
107plt.close()
108
109# === 4. stdout 关键统计 ===
110print("ch03-algo-basics demo 3: QFT_4 amplitude + phase of |0010>")
111print(f"  total shots: {total}")
112print(f"  unique outcomes: {int((empirical > 0).sum())} / {2**N_QUBITS}  "
113      f"(all 16 expected for a uniform Fourier image)")
114print(f"  all probabilities ≈ 1/{2**N_QUBITS} = {1/2**N_QUBITS:.4f}  "
115      f"(max-min range = {empirical.max()-empirical.min():.3f})")
116print(f"  empirical mean |amp|^2 = {empirical.mean():.4f}")
117print(f"  phase spread (rad): [{phases.min():+.3f}, {phases.max():+.3f}]")
118print(f"  saved: {OUT / '03_qft_4qubit.png'}")

运行结果

Demo 3:QFT 振幅相位

运行方式

# 仓库根目录执行;输出 PNG 到 demos/ch03-algo-basics/03_qft_4qubit.png,关键统计到 stdout
.venv/bin/python3 demos/ch03-algo-basics/03_qft_4qubit.py

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