Demo 1:Deutsch-Jozsa

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

可视化:双子图柱状 —— 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'}")

运行结果

Demo 1:Deutsch-Jozsa

运行方式

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

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