Demo 1:Deutsch-Jozsa¶
可视化:双子图柱状 —— 4-qubit 常数 vs 平衡 Oracle 一次查询
对应教程:第 3 章 量子算法基础 中相关小节 · 依赖安装:pip install "unified-quantum[visualization,simulation]"
实现要点¶
完整源码¶
demos/ch03-algo-basics/01_dj_constant_balanced.py¶
1"""
2ch03 演示 1:Deutsch-Jozsa 算法 4-qubit 常数 vs 平衡 Oracle
3
4对应教程:chenzhaoyun.com/quantum-tutorial/ch03-algo-basics/deutsch-jozsa.html
5依赖:pip install unified-quantum[visualization]
6运行:python demos/ch03-algo-basics/01_dj_constant_balanced.py
7"""
8from uniqc import (
9 Circuit,
10 deutsch_jozsa_circuit,
11 deutsch_jozsa_oracle,
12 submit_task,
13 wait_for_result,
14)
15import matplotlib
16matplotlib.use("Agg")
17import matplotlib.pyplot as plt
18import numpy as np
19from pathlib import Path
20
21OUT = Path(__file__).parent
22N_INPUT = 4
23SHOTS = 2000
24
25
26def run_dj(balanced: bool):
27 """构建并运行一个 4-qubit DJ 电路,返回 4-bit 输入寄存器上的计数。"""
28 oracle = deutsch_jozsa_oracle(qubits=list(range(N_INPUT)), balanced=balanced)
29 c = deutsch_jozsa_circuit(oracle=oracle, qubits=list(range(N_INPUT)))
30 # DJ 助手已经隐式测量输入寄存器,不要重复 measure()
31 result = wait_for_result(
32 submit_task(circuit=c, backend="dummy:local:simulator", shots=SHOTS)
33 )
34 # 丢弃 ancilla(最高位 qubit 4),只保留输入寄存器的 4 个比特
35 input_counts = {}
36 for bitstring, cnt in result.counts.items():
37 # bitstring 长度=5:key[0] = ancilla(q4), key[1:] = input(q3,q2,q1,q0)
38 input_bits = bitstring[1:]
39 input_counts[input_bits] = input_counts.get(input_bits, 0) + cnt
40 return input_counts
41
42
43# === 1. 跑常数 Oracle 和平衡 Oracle ===
44const_counts = run_dj(balanced=False)
45balan_counts = run_dj(balanced=True)
46
47# 构造完整的 4-bit 标签
48all_labels = [f"{i:0{N_INPUT}b}" for i in range(2 ** N_INPUT)]
49const_vals = np.array([const_counts.get(lbl, 0) for lbl in all_labels])
50balan_vals = np.array([balan_counts.get(lbl, 0) for lbl in all_labels])
51
52const_total = const_vals.sum()
53balan_total = balan_vals.sum()
54const_frac_zero = const_vals[0] / const_total
55non_zero_frac = balan_vals[1:].sum() / balan_total
56
57# === 2. matplotlib 可视化(2 子图:常数 / 平衡) ===
58fig, axes = plt.subplots(1, 2, figsize=(13, 4.8), sharey=True)
59
60for ax, vals, title, expected in (
61 (axes[0], const_vals, "Constant oracle (f(x)=0)", "expect 100% on 0000"),
62 (axes[1], balan_vals, "Balanced oracle (f(x)=x_0)", "expect 0% on 0000"),
63):
64 color = np.where(vals > 0, "#1f77b4", "#d3d3d3")
65 # 突出 0000
66 color = np.where(np.arange(len(vals)) == 0, "#d62728", color)
67 ax.bar(np.arange(len(vals)), vals / vals.sum() * 100, color=color, edgecolor="black")
68 ax.set_xticks(np.arange(len(vals)))
69 ax.set_xticklabels(all_labels, rotation=90, fontsize=7)
70 ax.set_xlabel("Input register (qubits 3..0)")
71 ax.set_ylabel("Probability (%)")
72 ax.set_title(f"{title}\n{expected}", fontsize=11)
73 ax.set_ylim(0, 105)
74 ax.grid(axis="y", alpha=0.3)
75
76fig.suptitle(
77 f"Deutsch-Jozsa on {N_INPUT} input qubits "
78 f"({SHOTS} shots per circuit, dummy:local:simulator)",
79 fontsize=12,
80 y=1.02,
81)
82plt.tight_layout()
83plt.savefig(OUT / "01_dj_constant_balanced.png", dpi=120, bbox_inches="tight")
84plt.close()
85
86# === 3. stdout 关键统计 ===
87print("ch03-algo-basics demo 1: Deutsch-Jozsa 4-qubit constant vs balanced")
88print(f" total shots per circuit: {SHOTS}")
89print(
90 f" constant: P(0000) = {const_frac_zero:.3f} "
91 f"(unique outcomes: {int((const_vals > 0).sum())})"
92)
93print(
94 f" balanced: P(0000) = {balan_vals[0] / balan_total:.3f} "
95 f"P(non-zero) = {non_zero_frac:.3f} "
96 f"(unique outcomes: {int((balan_vals > 0).sum())})"
97)
98print(f" saved: {OUT / '01_dj_constant_balanced.png'}")
运行结果¶

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