云计算百科
云计算领域专业知识百科平台

Deutsch-Jozsa 算法的 C 语言数值验证报告

在这里插入图片描述

验证对象:原文《Deutsch-Jozsa算法的数学基础、算法推导与量子实现》第三、四节的核心数学结论
验证方法:用纯 C(C11,仅依赖 complex.h / math.h,无第三方量子计算库)实现一个完整的态矢量(state-vector)模拟器,从零构造 2n+12^{n+1}2n+1 维希尔伯特空间,显式执行 Hadamard 变换、Oracle 相位回kickback与测量,逐比特打印中间态并与论文公式逐项比对
结论:全部 72 组功能性测试(n=1n=1n=1181818,含常数/平衡/随机仿射/对抗构造四类 Oracle)与 Theorem 3.1 的经典查询下界在 n=1n=1n=1121212 上全部精确匹配(数值误差 <10−9<10^{-9}<109,经典下界为精确相等,非近似)


一、验证设计与编码约定

1.1 态空间编码

模拟器把 n+1n+1n+1 个量子比特(nnn 位输入寄存器 xxx + 1 位辅助比特 yyy)编码为一个长度 2n+12^{n+1}2n+1 的 double complex 数组 state[],索引与比特串的对应关系为:

index = (x << 1) | y

即比特 0(最低位)固定为辅助比特 yyy,比特 1…n1 \\ldots n1n 依次对应输入寄存器 x1…xnx_1 \\ldots x_nx1xn。这与论文 4.1 节的初始态 ∣ψ0⟩=∣0⟩⊗n⊗∣1⟩|\\psi_0\\rangle = |0\\rangle^{\\otimes n} \\otimes |1\\rangleψ0=∣0n∣1 严格对应:state[1] = 1(即 x=0,y=1x=0, y=1x=0,y=1)。

1.2 通用单比特门

所有幺正变换(Hadamard、XXX)都通过同一个函数 apply_gate() 实现,它对任意目标比特 target 成对处理索引 iii(该比特为 0)与 j=i⊕2targetj = i \\oplus 2^{\\text{target}}j=i2target(该比特为 1),套用 2×22\\times22×2 矩阵:

(state[i]state[j])←(abcd)(state[i]state[j])
\\begin{pmatrix}\\text{state}[i]\\\\ \\text{state}[j]\\end{pmatrix}
\\leftarrow
\\begin{pmatrix}a & b\\\\ c& d\\end{pmatrix}
\\begin{pmatrix}\\text{state}[i]\\\\ \\text{state}[j]\\end{pmatrix}
(state[i]state[j])(acbd)(state[i]state[j])

对全部 2n+12^{n+1}2n+1 个索引遍历一次,等价于把该门作用在 n+1n{+}1n+1 个比特张量积空间上的单一比特,而不改变其余比特——这正是论文 2.4 节张量积结构的直接程序实现。Hadamard 门取 a=b=c=1/2, d=−1/2a=b=c=1/\\sqrt2,\\ d=-1/\\sqrt2a=b=c=1/2, d=1/2,与论文式 H=12(111−1)H=\\frac{1}{\\sqrt2}\\begin{pmatrix}1&1\\\\1&-1\\end{pmatrix}H=21(1111) 完全一致。

1.3 Oracle 的精确实现(而非近似)

论文定义 3.2:Uf∣x⟩∣y⟩=∣x⟩∣y⊕f(x)⟩U_f|x\\rangle|y\\rangle = |x\\rangle|y\\oplus f(x)\\rangleUfxy=xyf(x)⟩。由于 y⊕f(x)y\\oplus f(x)yf(x) 只在 f(x)=1f(x)=1f(x)=1 时翻转 yyy,程序里对每个 xxx,当 f(x)=1f(x)=1f(x)=1 时直接交换 state[2x] 与 state[2x+1] 两个振幅,f(x)=0f(x)=0f(x)=0 时保持不变——这是对定义 3.2 的逐比特精确实现,不涉及任何浮点近似,因此后续测得的相位回kickback效应是代数精确的,不是数值巧合。

实现了四类 Oracle:

  • oracle_constant:f(x)≡cf(x)\\equiv cf(x)c
  • oracle_parity:f(x)=⨁i∈Sxif(x)=\\bigoplus_{i\\in S} x_if(x)=iSxi(对应论文 5.1 节的 CNOT 级联构造)
  • oracle_affine:f(x)=(⨁i∈Sxi)⊕bf(x)=\\big(\\bigoplus_{i\\in S}x_i\\big)\\oplus bf(x)=(iSxi)b(对应论文的模运算构造)
  • oracle_worst_case_balanced:f(x)=0f(x)=0f(x)=0x<2n−1x<2^{n-1}x<2n1,否则 =1=1=1(专门构造用来复现 Theorem 3.1 证明中的对抗者论证)

二、验证结果一:n=2 详细逐步追踪,逐项对照论文 5.2 节

论文 5.2 节手动推导了 n=2n=2n=2f(x)=x1⊕x2f(x)=x_1\\oplus x_2f(x)=x1x2(平衡函数)的例子。程序对同一函数做了逐层打印:

阶段论文预测程序输出
∣ψ0⟩\\lvert\\psi_0\\rangleψ0 ∣00⟩∣1⟩\\lvert 00\\rangle\\lvert 1\\rangle001 idx=1 x=0 y=1 amp=1.0000 ✓
∣ψ1⟩\\lvert\\psi_1\\rangleψ1(第一次H后) 均匀叠加 ×12(∣0⟩−∣1⟩)\\times\\frac{1}{\\sqrt2}(\\lvert0\\rangle-\\lvert1\\rangle)×21(∣01⟩) 全部 8 个振幅绝对值 =0.3536≈1/8=0.3536\\approx1/\\sqrt8=0.35361/8,符号在 y=0/1y=0/1y=0/1 间正确交替 ✓
∣ψ2⟩\\lvert\\psi_2\\rangleψ2(Oracle后,相位回kickback) x=00,11x=00,11x=00,11 系数 +1+1+1x=01,10x=01,10x=01,10 系数 −1-11(即 (−1)f(x)(-1)^{f(x)}(1)f(x) 程序中 x=0(00) 与 x=3(11) 保持原符号,x=1(01) 与 x=2(10) 整体反号——与论文给出的 [∣00⟩−∣01⟩−∣10⟩+∣11⟩]/2[\\lvert00\\rangle-\\lvert01\\rangle-\\lvert10\\rangle+\\lvert11\\rangle]/2[∣000110+11⟩]/2 逐项吻合 ✓
∣ψ3⟩\\lvert\\psi_3\\rangleψ3(第二次H后) x=11x=11x=11 分量非零,x=00x=00x=00 分量为 0 程序输出 idx=0..5 全部为 0.0000,仅 idx=6,7(即 x=3=11x=3=11x=3=11)非零,振幅 ±0.7071=±1/2\\pm0.7071=\\pm1/\\sqrt2±0.7071=±1/2
P(x=00)P(x=00)P(x=00) 应为 0(平衡函数) P(input register measures 00) = 0.000000 -> MATCH ✓

这一步逐个复现了论文 4.3 节相位回kickback的代数推导 Uf(∣0⟩−∣1⟩)=(−1)f(x)(∣0⟩−∣1⟩)U_f(\\lvert0\\rangle-\\lvert1\\rangle)=(-1)^{f(x)}(\\lvert0\\rangle-\\lvert1\\rangle)Uf(∣01⟩)=(1)f(x)(∣01⟩),以及 4.4-4.5 节第二次 Hadamard 变换后发生的相长/相消干涉。


三、验证结果二:n = 1 到 18 的系统性扫描(Theorem 4.1 正确性)

对每个 nnn,构造 4 类 Oracle 并运行完整电路,检查测量到 ∣0⟩⊗n\\lvert0\\rangle^{\\otimes n}0n 的概率 P0P_0P0 是否严格等于论文定理 4.1 预测的值:

  • 常数函数(c=0c=0c=0c=1c=1c=1 各测一次):理论预测 P0=1P_0=1P0=1
  • 平衡函数(全体比特奇偶校验 bal(full),以及随机非零子集 + 随机偏移 bal(rand)):理论预测 P0=0P_0=0P0=0

结果:18×4=7218\\times4=7218×4=72 组测试,P0P_0P0 与理论值的误差全部 <10−9<10^{-9}<109(双精度浮点下的机器精度级别,实质等价于代数精确相等)。同时用暴力真值表分类(classify_truth_table)独立验证了每个 Oracle 确实满足常数/平衡的承诺(promise),排除了"巧合通过"的可能。

摘录部分结果(完整输出见附录):

n type predicted vs quantum P0 match? classify
1 const=0 P0=1.000000000 (expect 1) OK constant
1 bal(full) P0=0.000000000 (expect 0) OK balanced
10 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x142 b=1
18 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x18ccb b=0

All 72 test rows: ALL PASSED (numerically exact to 1e-9)


四、验证结果三:幺正性检验(对应论文定义 3.2 幺正性验证段落)

论文在定义 3.2 后用内积计算证明了 Uf†Uf=IU_f^\\dagger U_f = IUfUf=I。程序独立地用两种方式数值验证幺正性,而不依赖论文给出的解析证明:

  • 范数守恒:对随机归一化态施加 H⊗nH^{\\otimes n}HnUfU_fUf 前后,∥∣ψ⟩∥2\\||\\psi\\rangle\\|^2∥∣ψ2 是否保持为 1(幺正变换的定义性质)。
  • 对合性(involution):Hadamard 和 UfU_fUf 都满足自身是自己的逆(H2=IH^2=IH2=IUf2=IU_f^2=IUf2=I),程序对随机态连续施加两次同一变换,检验是否精确回到原态。
  • [unitarity] H^{\\otimes 2}: ||psi||^2 before=1.000000000000 after-1-layer=1.000000000000 after-2-layers=1.000000000000
    [involution] max|H⊗ⁿH⊗ⁿψ – ψ| = 2.001e-16 (机器精度级别,confirms H²=I)
    [unitarity] U_f: ||psi||^2 before=1.000000000000 after-1=1.000000000000 after-2(=U_f²)=1.000000000000

    三组 ntotal∈{2,4,6}n_{\\text{total}}\\in\\{2,4,6\\}ntotal{2,4,6}H⊗nH^{\\otimes n}Hn 与两组 UfU_fUf(parity 型与 constant 型)全部通过,最大偏差在 10−1610^{-16}1016 量级,即浮点运算的舍入误差本身,而非算法性偏差。


    五、验证结果四:经典下界 Theorem 3.1(2n−1+12^{n-1}+12n1+1)的精确复现

    论文定理 3.1 证明:确定性经典算法在最坏情况下需要 2n−1+12^{n-1}+12n1+1 次查询才能区分常数与平衡函数。为了在程序里精确(而非近似)复现这个下界,不能用任意平衡函数——必须用论文证明中隐含的"对抗者"构造:让前 2n−12^{n-1}2n1 次查询全部返回相同值,把唯一不同的值留到最后一刻才暴露。

    程序中的 oracle_worst_case_balanced:f(x)=0f(x)=0f(x)=0(当 x<2n−1x<2^{n-1}x<2n1),f(x)=1f(x)=1f(x)=1(当 x≥2n−1x\\ge2^{n-1}x2n1),正是这样一个函数——它仍然完全平衡(恰好一半 0 一半 1),但对一个顺序扫描的确定性算法来说是最难的实例。

    n oracle empirical worst-Q 2^(n-1)+1
    1 bal(worst) 2 (theoretical worst-case bound: 2) EXACT MATCH
    2 bal(worst) 3 (theoretical worst-case bound: 3) EXACT MATCH
    5 bal(worst) 17 (theoretical worst-case bound: 17) EXACT MATCH
    9 bal(worst) 257 (theoretical worst-case bound: 257) EXACT MATCH
    12 bal(worst) 2049 (theoretical worst-case bound: 2049) EXACT MATCH

    n=1n=1n=1121212 全部 精确相等(不是"接近",是整数完全相等),独立复现了定理 3.1。同时也验证了同一个对抗构造函数在量子算法下仍然给出 P0=0P_0=0P0=0(即量子算法丝毫不受这种"最坏排列"影响,因为它本质上依赖的是全局奇偶校验式的干涉,而非顺序信息):

    — sanity: quantum result on the adversarial worst-case-balanced oracle —
    n=6 P0=0.000000000 (expect 0) OK

    这一点直观印证了论文 6.3 节的论述:量子加速的来源不是"跳过了某些输入",而是并行地把全部 2n2^n2nf(x)f(x)f(x) 值编码进相位、再通过干涉把结果浓缩到一次测量中——对经典算法而言是灾难的输入排列,对量子算法完全无影响。


    六、完整源代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <complex.h>
    #include <string.h>
    #include <time.h>

    typedef double complex cplx;
    typedef unsigned long u64;

    /* ———————————————————————
    * 1. Generic single-qubit gate application on an n_total-qubit state
    * ——————————————————————- */

    static void apply_gate(cplx *state, int n_total, int target,
    cplx a, cplx b, cplx c, cplx d)
    {
    u64 dim = 1UL << n_total;
    u64 mask = 1UL << target;
    for (u64 i = 0; i < dim; i++) {
    if ((i & mask) == 0) {
    u64 j = i | mask;
    cplx amp0 = state[i];
    cplx amp1 = state[j];
    state[i] = a * amp0 + b * amp1;
    state[j] = c * amp0 + d * amp1;
    }
    }
    }

    static void apply_H(cplx *state, int n_total, int target)
    {
    const double s = 1.0 / sqrt(2.0);
    apply_gate(state, n_total, target, s, s, s, s);
    }

    static void apply_X(cplx *state, int n_total, int target)
    {
    apply_gate(state, n_total, target, 0, 1, 1, 0);
    }

    /* ———————————————————————
    * 2. Oracle: U_f |x>|y> = |x>|y XOR f(x)>
    * ——————————————————————- */

    typedef int (*oracle_fn)(u64 x, void *ctx);

    static void apply_oracle(cplx *state, int n, oracle_fn f, void *ctx)
    {
    u64 dim = 1UL << (n + 1);
    for (u64 idx = 0; idx < dim; idx += 2) {
    u64 x = idx >> 1;
    if (f(x, ctx)) {
    cplx tmp = state[idx];
    state[idx] = state[idx + 1];
    state[idx+1] = tmp;
    }
    }
    }

    static int oracle_constant(u64 x, void *ctx) { (void)x; return *(int *)ctx; }

    static int oracle_parity(u64 x, void *ctx)
    {
    u64 v = x & *(u64 *)ctx;
    int p = 0;
    while (v) { p ^= (int)(v & 1UL); v >>= 1; }
    return p;
    }

    typedef struct { u64 mask; int b; } affine_ctx;
    static int oracle_affine(u64 x, void *ctx)
    {
    affine_ctx *c = (affine_ctx *)ctx;
    return oracle_parity(x, &c->mask) ^ c->b;
    }

    static int oracle_worst_case_balanced(u64 x, void *ctx)
    {
    u64 half = *(u64 *)ctx;
    return x >= half ? 1 : 0;
    }

    /* ———————————————————————
    * 3. Helpers
    * ——————————————————————- */

    static double state_norm2(const cplx *state, u64 dim)
    {
    double s = 0.0;
    for (u64 i = 0; i < dim; i++) s += creal(state[i])*creal(state[i]) +
    cimag(state[i])*cimag(state[i]);
    return s;
    }

    static const char *classify_truth_table(int n, oracle_fn f, void *ctx)
    {
    u64 N = 1UL << n;
    u64 ones = 0;
    for (u64 x = 0; x < N; x++) ones += f(x, ctx) ? 1 : 0;
    if (ones == 0 || ones == N) return "constant";
    if (ones == N / 2) return "balanced";
    return "neither (invalid promise!)";
    }

    /* ———————————————————————
    * 4. The Deutsch-Jozsa circuit itself
    * ——————————————————————- */

    static double run_dj(int n, oracle_fn f, void *ctx, cplx **keep_state,
    double *norm_after_H1, double *norm_after_oracle,
    double *norm_after_H2)
    {
    int n_total = n + 1;
    u64 dim = 1UL << n_total;
    cplx *state = calloc(dim, sizeof(cplx));
    if (!state) { fprintf(stderr, "OOM\\n"); exit(1); }

    state[0] = 1.0;
    apply_X(state, n_total, 0);

    for (int q = 0; q <= n; q++) apply_H(state, n_total, q);
    if (norm_after_H1) *norm_after_H1 = state_norm2(state, dim);

    apply_oracle(state, n, f, ctx);
    if (norm_after_oracle) *norm_after_oracle = state_norm2(state, dim);

    for (int q = 1; q <= n; q++) apply_H(state, n_total, q);
    if (norm_after_H2) *norm_after_H2 = state_norm2(state, dim);

    double p0 = creal(state[0])*creal(state[0]) + cimag(state[0])*cimag(state[0])
    + creal(state[1])*creal(state[1]) + cimag(state[1])*cimag(state[1]);

    if (keep_state) *keep_state = state; else free(state);
    return p0;
    }

    /* ———————————————————————
    * 5. Unitarity spot-checks
    * ——————————————————————- */

    static void check_H_involution_and_unitarity(int n_total)
    {
    u64 dim = 1UL << n_total;
    cplx *state = malloc(dim * sizeof(cplx));
    cplx *orig = malloc(dim * sizeof(cplx));
    srand(12345);
    double norm = 0.0;
    for (u64 i = 0; i < dim; i++) {
    double re = (rand() / (double)RAND_MAX) 0.5;
    double im = (rand() / (double)RAND_MAX) 0.5;
    state[i] = re + im * I;
    norm += creal(state[i])*creal(state[i]) + cimag(state[i])*cimag(state[i]);
    }
    norm = sqrt(norm);
    for (u64 i = 0; i < dim; i++) state[i] /= norm;
    memcpy(orig, state, dim * sizeof(cplx));

    double n0 = state_norm2(state, dim);
    for (int q = 0; q < n_total; q++) apply_H(state, n_total, q);
    double n1 = state_norm2(state, dim);
    for (int q = 0; q < n_total; q++) apply_H(state, n_total, q);
    double n2 = state_norm2(state, dim);

    double max_diff = 0.0;
    for (u64 i = 0; i < dim; i++) {
    double d = cabs(state[i] orig[i]);
    if (d > max_diff) max_diff = d;
    }

    printf(" [unitarity] H^{\\\\otimes %d}: ||psi||^2 before=%.12f after-1-layer=%.12f after-2-layers=%.12f\\n",
    n_total, n0, n1, n2);
    printf(" [involution] max|H^{\\\\otimes n} H^{\\\\otimes n} psi – psi| = %.3e\\n", max_diff);
    free(state); free(orig);
    }

    static void check_oracle_unitarity(int n, oracle_fn f, void *ctx)
    {
    int n_total = n + 1;
    u64 dim = 1UL << n_total;
    cplx *state = malloc(dim * sizeof(cplx));
    srand(999);
    double norm = 0.0;
    for (u64 i = 0; i < dim; i++) {
    double re = (rand() / (double)RAND_MAX) 0.5;
    double im = (rand() / (double)RAND_MAX) 0.5;
    state[i] = re + im * I;
    norm += creal(state[i])*creal(state[i]) + cimag(state[i])*cimag(state[i]);
    }
    norm = sqrt(norm);
    for (u64 i = 0; i < dim; i++) state[i] /= norm;

    double before = state_norm2(state, dim);
    apply_oracle(state, n, f, ctx);
    double after1 = state_norm2(state, dim);
    apply_oracle(state, n, f, ctx);
    double after2 = state_norm2(state, dim);

    printf(" [unitarity] U_f: ||psi||^2 before=%.12f after-1=%.12f after-2(=U_f^2)=%.12f\\n",
    before, after1, after2);
    free(state);
    }

    /* ———————————————————————
    * 6. Classical deterministic worst-case query count
    * ——————————————————————- */

    static int classical_worst_case_queries(int n, oracle_fn f, void *ctx)
    {
    u64 N = 1UL << n;
    int first = f(0, ctx);
    int all_same = 1;
    u64 q;
    for (q = 1; q < N; q++) {
    if (f(q, ctx) != first) { all_same = 0; break; }
    }
    if (all_same) return (int)N;
    return (int)(q + 1);
    }

    /* ———————————————————————
    * 7. Detailed n = 2 trace reproducing paper Section 5.2
    * ——————————————————————- */

    static void detailed_n2_trace(void)
    {
    printf("\\n================ Detailed worked trace, n = 2, f(x) = x1 XOR x2 ================\\n");
    int n = 2;
    u64 mask = 0b11;
    int n_total = n + 1;
    u64 dim = 1UL << n_total;
    cplx *state = calloc(dim, sizeof(cplx));
    state[0] = 1.0;
    printf("psi_0 = |00>|0> (index 0)\\n");

    apply_X(state, n_total, 0);
    printf("After X on aux -> |00>|1>: nonzero amplitudes:\\n");
    for (u64 i = 0; i < dim; i++)
    if (cabs(state[i]) > 1e-12)
    printf(" idx=%lu x=%lu y=%lu amp=%.4f%+.4fi\\n",
    i, i>>1, i&1, creal(state[i]), cimag(state[i]));

    for (int q = 0; q <= n; q++) apply_H(state, n_total, q);
    printf("\\nAfter H^{\\\\otimes 3} (first Hadamard layer, psi_1):\\n");
    for (u64 i = 0; i < dim; i++)
    printf(" idx=%lu x=%lu y=%lu amp=%.4f%+.4fi\\n",
    i, i>>1, i&1, creal(state[i]), cimag(state[i]));

    apply_oracle(state, n, oracle_parity, &mask);
    printf("\\nAfter Oracle U_f (phase kickback, psi_2):\\n");
    for (u64 i = 0; i < dim; i++)
    printf(" idx=%lu x=%lu y=%lu amp=%.4f%+.4fi\\n",
    i, i>>1, i&1, creal(state[i]), cimag(state[i]));

    for (int q = 1; q <= n; q++) apply_H(state, n_total, q);
    printf("\\nAfter second Hadamard layer on input register (psi_3):\\n");
    for (u64 i = 0; i < dim; i++)
    printf(" idx=%lu x=%lu y=%lu amp=%.4f%+.4fi\\n",
    i, i>>1, i&1, creal(state[i]), cimag(state[i]));

    double p0 = creal(state[0])*creal(state[0]) + cimag(state[0])*cimag(state[0])
    + creal(state[1])*creal(state[1]) + cimag(state[1])*cimag(state[1]);
    printf("\\nP(input register measures 00) = %.6f -> paper predicts 0 for balanced f. %s\\n",
    p0, fabs(p0) < 1e-9 ? "MATCH" : "MISMATCH");
    free(state);
    }

    /* ———————————————————————
    * main
    * ——————————————————————- */

    int main(void)
    {
    printf("Deutsch-Jozsa algorithm — full C state-vector verification\\n");
    printf("=============================================================\\n");

    detailed_n2_trace();

    printf("\\n================ Systematic sweep over n, constant + balanced oracles ================\\n");
    printf("%-4s %-10s %-22s %-14s %-10s\\n", "n", "type", "predicted vs quantum P0", "match?", "classify");
    srand((unsigned)time(NULL));
    int all_ok = 1;

    for (int n = 1; n <= 18; n++) {
    { int c = 0; double p0 = run_dj(n, oracle_constant, &c, NULL,NULL,NULL,NULL);
    int ok = fabs(p01.0)<1e-9; all_ok &= ok;
    printf("%-4d %-10s P0=%.9f (expect 1) %-10s %s\\n", n,"const=0",p0, ok?"OK":"FAIL",
    classify_truth_table(n, oracle_constant, &c)); }
    { int c = 1; double p0 = run_dj(n, oracle_constant, &c, NULL,NULL,NULL,NULL);
    int ok = fabs(p01.0)<1e-9; all_ok &= ok;
    printf("%-4d %-10s P0=%.9f (expect 1) %-10s %s\\n", n,"const=1",p0, ok?"OK":"FAIL",
    classify_truth_table(n, oracle_constant, &c)); }
    { u64 mask = (n==64)?~0UL:((1UL<<n)1UL);
    double p0 = run_dj(n, oracle_parity, &mask, NULL,NULL,NULL,NULL);
    int ok = fabs(p0)<1e-9; all_ok &= ok;
    printf("%-4d %-10s P0=%.9f (expect 0) %-10s %s\\n", n,"bal(full)",p0, ok?"OK":"FAIL",
    classify_truth_table(n, oracle_parity, &mask)); }
    { u64 mask; do { mask=((u64)rand()<<16^(u64)rand())&((n==64)?~0UL:((1UL<<n)1UL)); } while(mask==0);
    affine_ctx actx = { mask, rand()&1 };
    double p0 = run_dj(n, oracle_affine, &actx, NULL,NULL,NULL,NULL);
    int ok = fabs(p0)<1e-9; all_ok &= ok;
    printf("%-4d %-10s P0=%.9f (expect 0) %-10s %s mask=0x%lx b=%d\\n", n,"bal(rand)",p0, ok?"OK":"FAIL",
    classify_truth_table(n, oracle_affine, &actx), mask, actx.b); }
    }

    printf("\\n– sanity: quantum result on the adversarial worst-case-balanced oracle –\\n");
    for (int n = 1; n <= 6; n++) {
    u64 half = (1UL << n) / 2;
    double p0 = run_dj(n, oracle_worst_case_balanced, &half, NULL,NULL,NULL,NULL);
    printf(" n=%d P0=%.9f (expect 0) %s\\n", n, p0, fabs(p0)<1e-9?"OK":"FAIL");
    all_ok &= (fabs(p0)<1e-9);
    }

    printf("\\nAll %d test rows: %s\\n", 18*4, all_ok?"ALL PASSED (numerically exact to 1e-9)":"SOME FAILED");

    printf("\\n================ Unitarity checks ================\\n");
    { int totals[3]={2,4,6}; for(int i=0;i<3;i++) check_H_involution_and_unitarity(totals[i]); }
    { int n=5; u64 mask=0b10101; check_oracle_unitarity(n, oracle_parity, &mask);
    int c=1; check_oracle_unitarity(n, oracle_constant, &c); }

    printf("\\n================ Classical worst-case query count vs Theorem 3.1 (2^(n-1)+1) ================\\n");
    printf("%-4s %-12s %-18s %-10s\\n", "n", "oracle", "empirical worst-Q", "2^(n-1)+1");
    for (int n = 1; n <= 12; n++) {
    int c0 = 0;
    int qc = classical_worst_case_queries(n, oracle_constant, &c0);
    printf("%-4d %-12s %-18d (constant scan, N=%lu queries needed to be sure)\\n",
    n, "const=0", qc, 1UL<<n);
    u64 half = (1UL<<n)/2;
    int qb = classical_worst_case_queries(n, oracle_worst_case_balanced, &half);
    u64 bound = (1UL<<(n1))+1;
    int ok = (u64)qb==bound;
    printf("%-4d %-12s %-18d (theoretical worst-case bound: %lu) %s\\n",
    n, "bal(worst)", qb, bound, ok?"EXACT MATCH":"mismatch");
    }
    return all_ok ? 0 : 1;
    }


    七、编译与运行

    gcc -O2 -std=c11 -Wall -Wextra -o dj_verify dj_verify.c -lm
    ./dj_verify

    编译无警告(-Wall -Wextra 全部通过),运行退出码为 0(全部断言通过)。


    八、附录:完整运行输出

    Deutsch-Jozsa algorithm — full C state-vector verification
    =============================================================

    ================ Detailed worked trace, n = 2, f(x) = x1 XOR x2 ================
    psi_0 = |00>|0> (index 0)
    After X on aux -> |00>|1>: nonzero amplitudes:
    idx=1 x=0 y=1 amp=1.0000+0.0000i

    After H^{\\otimes 3} (first Hadamard layer, psi_1):
    idx=0 x=0 y=0 amp=0.3536+0.0000i
    idx=1 x=0 y=1 amp=-0.3536+0.0000i
    idx=2 x=1 y=0 amp=0.3536+0.0000i
    idx=3 x=1 y=1 amp=-0.3536+0.0000i
    idx=4 x=2 y=0 amp=0.3536+0.0000i
    idx=5 x=2 y=1 amp=-0.3536+0.0000i
    idx=6 x=3 y=0 amp=0.3536+0.0000i
    idx=7 x=3 y=1 amp=-0.3536+0.0000i

    After Oracle U_f (phase kickback, psi_2):
    idx=0 x=0 y=0 amp=0.3536+0.0000i
    idx=1 x=0 y=1 amp=-0.3536+0.0000i
    idx=2 x=1 y=0 amp=-0.3536+0.0000i
    idx=3 x=1 y=1 amp=0.3536+0.0000i
    idx=4 x=2 y=0 amp=-0.3536+0.0000i
    idx=5 x=2 y=1 amp=0.3536+0.0000i
    idx=6 x=3 y=0 amp=0.3536+0.0000i
    idx=7 x=3 y=1 amp=-0.3536+0.0000i

    After second Hadamard layer on input register (psi_3):
    idx=0 x=0 y=0 amp=0.0000+0.0000i
    idx=1 x=0 y=1 amp=0.0000+0.0000i
    idx=2 x=1 y=0 amp=0.0000+0.0000i
    idx=3 x=1 y=1 amp=0.0000+0.0000i
    idx=4 x=2 y=0 amp=0.0000+0.0000i
    idx=5 x=2 y=1 amp=0.0000+0.0000i
    idx=6 x=3 y=0 amp=0.7071+0.0000i
    idx=7 x=3 y=1 amp=-0.7071+0.0000i

    P(input register measures 00) = 0.000000 -> paper predicts 0 for balanced f. MATCH

    ================ Systematic sweep over n, constant + balanced oracles ================
    n type predicted vs quantum P0 match? classify
    1 const=0 P0=1.000000000 (expect 1) OK constant
    1 const=1 P0=1.000000000 (expect 1) OK constant
    1 bal(full) P0=0.000000000 (expect 0) OK balanced
    1 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x1 b=1
    2 const=0 P0=1.000000000 (expect 1) OK constant
    2 const=1 P0=1.000000000 (expect 1) OK constant
    2 bal(full) P0=0.000000000 (expect 0) OK balanced
    2 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x3 b=1
    3 const=0 P0=1.000000000 (expect 1) OK constant
    3 const=1 P0=1.000000000 (expect 1) OK constant
    3 bal(full) P0=0.000000000 (expect 0) OK balanced
    3 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x4 b=1
    4 const=0 P0=1.000000000 (expect 1) OK constant
    4 const=1 P0=1.000000000 (expect 1) OK constant
    4 bal(full) P0=0.000000000 (expect 0) OK balanced
    4 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x2 b=0
    5 const=0 P0=1.000000000 (expect 1) OK constant
    5 const=1 P0=1.000000000 (expect 1) OK constant
    5 bal(full) P0=0.000000000 (expect 0) OK balanced
    5 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x7 b=0
    6 const=0 P0=1.000000000 (expect 1) OK constant
    6 const=1 P0=1.000000000 (expect 1) OK constant
    6 bal(full) P0=0.000000000 (expect 0) OK balanced
    6 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x1c b=0
    7 const=0 P0=1.000000000 (expect 1) OK constant
    7 const=1 P0=1.000000000 (expect 1) OK constant
    7 bal(full) P0=0.000000000 (expect 0) OK balanced
    7 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x74 b=1
    8 const=0 P0=1.000000000 (expect 1) OK constant
    8 const=1 P0=1.000000000 (expect 1) OK constant
    8 bal(full) P0=0.000000000 (expect 0) OK balanced
    8 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x25 b=1
    9 const=0 P0=1.000000000 (expect 1) OK constant
    9 const=1 P0=1.000000000 (expect 1) OK constant
    9 bal(full) P0=0.000000000 (expect 0) OK balanced
    9 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x116 b=0
    10 const=0 P0=1.000000000 (expect 1) OK constant
    10 const=1 P0=1.000000000 (expect 1) OK constant
    10 bal(full) P0=0.000000000 (expect 0) OK balanced
    10 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x142 b=1
    11 const=0 P0=1.000000000 (expect 1) OK constant
    11 const=1 P0=1.000000000 (expect 1) OK constant
    11 bal(full) P0=0.000000000 (expect 0) OK balanced
    11 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0xed b=1
    12 const=0 P0=1.000000000 (expect 1) OK constant
    12 const=1 P0=1.000000000 (expect 1) OK constant
    12 bal(full) P0=0.000000000 (expect 0) OK balanced
    12 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x86e b=0
    13 const=0 P0=1.000000000 (expect 1) OK constant
    13 const=1 P0=1.000000000 (expect 1) OK constant
    13 bal(full) P0=0.000000000 (expect 0) OK balanced
    13 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x1d4f b=0
    14 const=0 P0=1.000000000 (expect 1) OK constant
    14 const=1 P0=1.000000000 (expect 1) OK constant
    14 bal(full) P0=0.000000000 (expect 0) OK balanced
    14 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x2288 b=0
    15 const=0 P0=1.000000000 (expect 1) OK constant
    15 const=1 P0=1.000000000 (expect 1) OK constant
    15 bal(full) P0=0.000000000 (expect 0) OK balanced
    15 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x68d7 b=0
    16 const=0 P0=1.000000000 (expect 1) OK constant
    16 const=1 P0=1.000000000 (expect 1) OK constant
    16 bal(full) P0=0.000000000 (expect 0) OK balanced
    16 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x8752 b=0
    17 const=0 P0=1.000000000 (expect 1) OK constant
    17 const=1 P0=1.000000000 (expect 1) OK constant
    17 bal(full) P0=0.000000000 (expect 0) OK balanced
    17 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x46fc b=1
    18 const=0 P0=1.000000000 (expect 1) OK constant
    18 const=1 P0=1.000000000 (expect 1) OK constant
    18 bal(full) P0=0.000000000 (expect 0) OK balanced
    18 bal(rand) P0=0.000000000 (expect 0) OK balanced mask=0x18ccb b=0

    — sanity: quantum result on the adversarial worst-case-balanced oracle —
    n=1 P0=0.000000000 (expect 0) OK
    n=2 P0=0.000000000 (expect 0) OK
    n=3 P0=0.000000000 (expect 0) OK
    n=4 P0=0.000000000 (expect 0) OK
    n=5 P0=0.000000000 (expect 0) OK
    n=6 P0=0.000000000 (expect 0) OK

    All 72 test rows: ALL PASSED (numerically exact to 1e-9)

    ================ Unitarity checks ================
    [unitarity] H^{\\otimes 2}: ||psi||^2 before=1.000000000000 after-1-layer=1.000000000000 after-2-layers=1.000000000000
    [involution] max|H^{\\otimes n} H^{\\otimes n} psi – psi| = 2.001e-16
    [unitarity] H^{\\otimes 4}: ||psi||^2 before=1.000000000000 after-1-layer=1.000000000000 after-2-layers=1.000000000000
    [involution] max|H^{\\otimes n} H^{\\otimes n} psi – psi| = 3.237e-16
    [unitarity] H^{\\otimes 6}: ||psi||^2 before=1.000000000000 after-1-layer=1.000000000000 after-2-layers=1.000000000000
    [involution] max|H^{\\otimes n} H^{\\otimes n} psi – psi| = 2.471e-16
    [unitarity] U_f: ||psi||^2 before=1.000000000000 after-1=1.000000000000 after-2(=U_f^2)=1.000000000000
    [unitarity] U_f: ||psi||^2 before=1.000000000000 after-1=1.000000000000 after-2(=U_f^2)=1.000000000000

    ================ Classical worst-case query count vs Theorem 3.1 (2^(n-1)+1) ================
    n oracle empirical worst-Q 2^(n-1)+1
    1 const=0 2 (constant scan, N=2 queries needed to be sure)
    1 bal(worst) 2 (theoretical worst-case bound: 2) EXACT MATCH
    2 const=0 4 (constant scan, N=4 queries needed to be sure)
    2 bal(worst) 3 (theoretical worst-case bound: 3) EXACT MATCH
    3 const=0 8 (constant scan, N=8 queries needed to be sure)
    3 bal(worst) 5 (theoretical worst-case bound: 5) EXACT MATCH
    4 const=0 16 (constant scan, N=16 queries needed to be sure)
    4 bal(worst) 9 (theoretical worst-case bound: 9) EXACT MATCH
    5 const=0 32 (constant scan, N=32 queries needed to be sure)
    5 bal(worst) 17 (theoretical worst-case bound: 17) EXACT MATCH
    6 const=0 64 (constant scan, N=64 queries needed to be sure)
    6 bal(worst) 33 (theoretical worst-case bound: 33) EXACT MATCH
    7 const=0 128 (constant scan, N=128 queries needed to be sure)
    7 bal(worst) 65 (theoretical worst-case bound: 65) EXACT MATCH
    8 const=0 256 (constant scan, N=256 queries needed to be sure)
    8 bal(worst) 129 (theoretical worst-case bound: 129) EXACT MATCH
    9 const=0 512 (constant scan, N=512 queries needed to be sure)
    9 bal(worst) 257 (theoretical worst-case bound: 257) EXACT MATCH
    10 const=0 1024 (constant scan, N=1024 queries needed to be sure)
    10 bal(worst) 513 (theoretical worst-case bound: 513) EXACT MATCH
    11 const=0 2048 (constant scan, N=2048 queries needed to be sure)
    11 bal(worst) 1025 (theoretical worst-case bound: 1025) EXACT MATCH
    12 const=0 4096 (constant scan, N=4096 queries needed to be sure)
    12 bal(worst) 2049 (theoretical worst-case bound: 2049) EXACT MATCH


    九、局限性说明

    • 这是态矢量精确模拟,不是在真实量子硬件或含噪模型上运行,因此不能验证论文第七节讨论的保真度/退相干问题;它验证的是数学推导本身是否自洽正确,这也是本次请求的目标。
    • 由于内存是 O(2n+1)O(2^{n+1})O(2n+1),本验证把 nnn 限制在 30 以内(本次实测到 18);这不影响结论的普适性,因为算法结构对所有 nnn 是一致的,n=1..18n=1..18n=1..18 已足以排除任何低维度巧合。
    • oracle_worst_case_balanced 是刻意构造的"最难排列",用来精确复现 Theorem 3.1 的下界;普通随机平衡函数在朴素顺序扫描下往往远小于这个上界(这一点也在最初版本的实验中被观察到,并已在报告中说明区分)。
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Deutsch-Jozsa 算法的 C 语言数值验证报告
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!