量子コンピュータでベクトルの足し算・引き算

量子コンピュータで、ベクトルの足し算と引き算をする方法。量子コンピュータでベクトルの内積 - yukobaのブログの続きです。今回も、古典コンピュータではO(N)ですが、量子コンピュータではO(1)になります。

アダマール行列(H)は、\left( \begin{array} a \\ b \end{array} \right) \to \sqrt{\frac{1}{2}}\left( \begin{array} a + b \\ a - b \end{array} \right)の変換を行います。これを使って、ベクトルの足し算・引き算を行います。"No-cloning theorm"により、量子コンピュータでは基本的に振幅のコピーはできません。しかし、Hで b = 0 とすると、\left( \begin{array} a \\ 0 \end{array} \right) \to \sqrt{\frac{1}{2}} \left( \begin{array} a \\ a \end{array} \right)となり、\sqrt{\frac{1}{2}}がつきますが、振幅のコピーができます。Hは元のベクトルを破壊してしまうので、次の計算に使えるように、振幅のコピーをとりました。

ベクトルの足し算・引き算は、今回も、a = (\sqrt{\frac{4}{7}}, \sqrt{\frac{2}{7}}, 0, \sqrt{\frac{1}{7}}), b = (\sqrt{\frac{1}{2}}, 0, 0, \sqrt{\frac{1}{2}})にて行います。Hを何度も使っているので、得られる結果は、\frac{1}{2}a, \frac{1}{2}b, \frac{1}{2 \sqrt{2}}(a + b), \frac{1}{2 \sqrt{2}}(a - b) です。

qcl -i vecPlus.qcl の実行結果は以下の通り。

: STATE: 4 / 32 qubits allocated, 28 / 32 qubits free
0.37796  |0>  + 0.26726 |1>  + 0.18898 |3> + 
0.35355  |4>                 + 0.35355 |7> + 
0.51726  |8>  + 0.18898 |9>  + 0.38363 |11> + 
0.017261 |12> + 0.18898 |13> - 0.11637 |15>

1列目に関しては、\frac{1}{2} \sqrt{\frac{4}{7}} = 0.37796, \frac{1}{2} \sqrt{\frac{1}{2}} = 0.35355より、1行目と2行目があっています。\frac{1}{2 \sqrt{2}} (sqrt{\frac{4}{7}} + sqrt{\frac{1}{2}}) = 0.51726, \frac{1}{2 \sqrt{2}} (sqrt{\frac{4}{7}} - sqrt{\frac{1}{2}}) = 0.017261 より、3行目と4行目があっています。

ソースコード

ファイル名はvecPlus.qcl

include "initAmpGeneral.qcl";

// ベクトルの複製
// (a, b, c, d, 0, 0, 0, 0) -> sqrt(0.5) * (a, b, c, d, a, b, c, d) に
// 振幅を複製します。
operator vecDup(qureg a) {
    H(a[#a - 1]);
}

// ベクトルの和と差。
// (a, b, c, d) -> (a, b, sqrt(0.5) * (c + d), sqrt(0.5) * (c - d)) に
// 基底状態をmod 4で見て、変換します。
// a = c, b = d で利用することを想定。
operator vecPlus(qureg a) {
    real p;
    p = sqrt(0.5);
    Matrix4x4(
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, p, p,
        0, 0, p,-p,
        a[0:1]);
}

procedure testVecPlus() {
    const patternBitSize = 2;
    int vector xPatterns = vector(
        0, 1, 3,
        4,    7);
    real vector xValues = vector(
        4.0/7.0, 2.0/7.0, 1.0/7.0,
        0.5,              0.5);
    qureg x[patternBitSize + 2];

    xValues = xValues * 0.5;
    initAmp(x[0:patternBitSize], xPatterns, xValues);

    vecDup(x);
    vecPlus(x[patternBitSize:patternBitSize + 1]);
    dump;
}