Q# を使用して量子もつれを作成する

完了

前のユニットでは、量子もつれとベル状態の概念について学習しました。

ここでは、Q# と Azure Quantum Development Kit を使って量子もつれを作成してみましょう。 もつれを作成するには、アダマール ゲートと制御 NOT (CNOT) ゲートの 2 つの量子演算を適用する必要があります。

制御 NOT (CNOT) 操作

2 つの量子ビットがもつれるとき、1 つの量子ビットの状態は、もう一方の量子ビットの状態に依存します。 このため、2 つの量子ビットをもつれさせるには、両方の量子ビットに同時に作用する操作が必要です。 これは、"複数量子ビット演算" と呼ばれます。

量子もつれを作成するには、"制御 NOT" を表す複数量子ビットの CNOT 演算が必要です。 この操作は 2 つの量子ビットを入力として受け取ります。1 つは制御量子ビットとして機能し、もう 1 つは target 量子ビットです。 CNOT 演算は、最初の量子ビット (制御量子ビット) の状態が $|1\rangle$ の場合にのみ、2 番めの量子ビット (target 量子ビット) の状態を反転します。

入力 出力
$\ket{00}$ $\ket{00}$
$\ket{01}$ $\ket{01}$
$\ket{10}$ $\ket{11}$
$\ket{11}$ $\ket{10}$

Q# では、CNOT 演算は 2 つの量子ビットの配列に作用し、最初の量子ビットが One の場合に 2 番めの量子ビットを反転します。

CNOT 操作を使用したもつれ

アダマール (H) 演算と制御 NOT (CNOT) 演算を適用することで、状態 $|00\rangle$ の 2 つの量子ビットを、ベル状態 $\ket{\phi^+}=\frac1{\sqrt2}(|00\rangle+|11\rangle)$ に変換できます。

その仕組みを次に示します。

  1. 状態 $|00\rangle$ の 2 つの量子ビットを使用します。 最初の量子ビットが制御量子ビットで、2 番めの量子ビットが target 量子ビットです。

  2. $H$ を適用して、制御量子ビットにのみ重ね合わせ状態を作成します。

    $$H |0_c\rangle=\frac{1}{\sqrt{{2}}(|0_c\rangle+|1_c\rangle)$$

    Note

    下付き文字 ${}_c$ と ${}_t$ は、制御量子ビットと target 量子ビットを示します。

  3. $CNOT$ 演算子を重ね合わせ状態の制御量子ビットと、$| 0_t \rangle$ 状態の target 量子ビットに適用します。

    $$ CNOT \frac{1}{\sqrt{2}}(\ket{0_c}+\ket{1_c})\ket{0}_t = CNOT \frac{1}{\sqrt2}(\ket{0_c 0_t}+|\ket{1_c 0_t})=$$$$=\frac{{1}{\sqrt2}(CNOT \ket{0_c 0_t} + CNOT \ket{1_c 0_t})=$$$$=\frac{1}{\sqrt2}(\ket{0_c 0_t}+\ket{1_c 1_t})$$

新しい Q# ファイルを作成する

  1. Visual Studio Code を開きます。
  2. [ファイル] > [新しいテキスト ファイル] の順に選択し、ファイルを Main.qs として保存します。
  3. [表示] -> [コマンド パレット] を選択し、「Q#: Azure Quantum QIR target プロファイルを設定する」と入力します。 Enter キーを押します。
  4. [Q#: 無制限] を選択します。

ベル状態 $\ket{\phi^+}$ を作成して測定する

ベル状態 $\ket{\phi^+}=\frac1{\sqrt2}(|00\rangle+|11\rangle)$ の作成から始めましょう。

Q# でベル状態 $\ket{\phi^+}$ を作成する

  1. 最初に、DumpMachine 関数が含まれる Microsoft.Quantum.Diagnostics 名前空間を標準ライブラリからインポートする必要があります。 この関数は、量子ビットの現在の状態を示します。 次の Q# コードをコピーして、Main.qs ファイルに貼り付けます。

    import Microsoft.Quantum.Diagnostics.*; // Aka Std.Diagnostics.*;
    

    ヒント

    Microsoft.QuantumStd に置き換えて、標準ライブラリをインポートすることもできます。 たとえば、import Std.Diagnostics.* は、import Microsoft.Quantum.Diagnostics.* と同じです。

  2. 量子ビットの測定結果である 2 つの Result 型の値を返す Main 演算を作成します。

    import Microsoft.Quantum.Diagnostics.*; // Aka Std.Diagnostics.*;
    
    operation Main() : (Result, Result) {
        // Your code goes here
    }
    
  3. Main 演算内では、q1q2 の 2 つの量子ビットを割り当てます。それをもつれさせます。

    import Microsoft.Quantum.Diagnostics.*; // Aka Std.Diagnostics.*;
    
    operation Main() : (Result, Result) {
        use (q1, q2) = (Qubit(), Qubit());
    }
    
  4. 1 番目の量子ビット q1 にアダマール ゲート H を適用して、それを重ね合わせ状態にします。 次に、CNOT 演算を使って 2 つの量子ビットをもつれさせます。

    import Microsoft.Quantum.Diagnostics.*; // Aka Std.Diagnostics.*;
    
    operation Main() : (Result, Result) {
        use (q1, q2) = (Qubit(), Qubit());
    
        H(q1);
        CNOT(q1, q2);
    }
    
  5. DumpMachine 関数を使って、量子ビットの現在の状態を表示します。 これは、量子ビットの測定と同じことではありません

    import Microsoft.Quantum.Diagnostics.*; // Aka Std.Diagnostics.*;
    
    operation Main() : (Result, Result) {
        use (q1, q2) = (Qubit(), Qubit());
    
        H(q1);
        CNOT(q1, q2);
    
        DumpMachine();
    }
    
  6. M 演算を使って量子ビットを測定し、結果を m1m2 に格納します。 次に、Reset 演算を使って量子ビットをリセットします。 Q# では、量子ビットを常に $|0\rangle$ 状態にリセットする必要があります。

    import Microsoft.Quantum.Diagnostics.*; // Aka Std.Diagnostics.*;
    
    operation Main() : (Result, Result) {
    
        use (q1, q2) = (Qubit(), Qubit());
    
        H(q1);
        CNOT(q1, q2);
        DumpMachine();
    
        let (m1, m2) = (M(q1), M(q2));
        Reset(q1);
        Reset(q2);
    
    }
    
  7. 最後に、return ステートメントで量子ビットの測定結果を返します。 Main.qs ファイルは次のようになります。

    import Microsoft.Quantum.Diagnostics.*; // Aka Std.Diagnostics.*;
    
    operation Main() : (Result, Result) {
        use (q1, q2) = (Qubit(), Qubit());
    
        H(q1);
        CNOT(q1, q2);
    
        DumpMachine();
    
        let (m1, m2) = (M(q1), M(q2));
        Reset(q1);
        Reset(q2);
    
        return (m1, m2);
    }
    

プログラムを実行する

  1. 組み込みのシミュレーターでプログラムを実行するには、Main 演算の上の [実行] をクリックするか、Ctrl + F5 キーを押します。 出力がデバッグ コンソールに表示されます。

  2. 測定結果には相関関係があるため、プログラムの終了時に、(Zero, Zero) または (One, One) の結果を等しい確率で取得します。

  3. Main 演算の上にあるコマンドの一覧で Circuit をクリックすると、回路図を視覚化できます。 この回路図は、最初の量子ビットにアダマール ゲートが適用され、両方の量子ビットに CNOT ゲートが適用されたことを示しています。

    ベル状態の回路のスクリーンショット。

ベル状態 $\ket{\phi^-}$ を作成して測定する

他のベル状態を作成するには、量子ビットに追加のパウリ $X$ 演算とパウリ $Z$ 演算を適用する必要があります。

たとえば、ベル状態 $\ket{\phi^-}=\frac1{\sqrt2}(|00\rangle-|11\rangle)$ を作成するために、制御量子ビットにアダマール ゲートを適用してから、パウリ $Z$ 演算を適用できます。 $Z$ 操作は、状態 $\ket{+}$ を $\ket{-}$ に反転します。

Note

状態 $\frac{{1}{\sqrt{2}}(|0\rangle+|1\rangle)$ と $\frac{1}{\sqrt{{2}}(|0\rangle -|1\rangle)$ は、それぞれ $\ket{+}$ と $\ket{{-}$ とも表されます。

その仕組みを次に示します。

  1. 状態 $|00\rangle$ の 2 つの量子ビットを使用します。

  2. $H$ を適用して、制御量子ビットにのみ重ね合わせ状態を作成します。

    $$H |0_c\rangle=\frac{{1}{\sqrt{2}}(|0_c\rangle+|1_c\rangle) =\ket{+}_c$$

  3. 制御量子ビットに $Z$ 演算を適用します。

    $$Z \frac{{1}{\sqrt{{2}}(|0_c\rangle+|1_c\rangle)=\frac{1}{\sqrt{{2}}(|0_c\rangle-|1_c\rangle)=\ket{{-}_c$$

  4. $CNOT$ 演算子を制御量子ビットと、$| 0_t \rangle$ 状態の target 量子ビットに適用します。

    $$ CNOT \frac{1}{\sqrt{2}}(\ket{0_c}-\ket{1_c})\ket{0}_t = CNOT \frac{1}{\sqrt2}(\ket{0_c 0_t}-|\ket{1_c 0_t})=$$$$=\frac{{1}{\sqrt2}(CNOT \ket{0_c 0_t} - CNOT \ket{1_c 0_t})=$$$$=\frac{1}{\sqrt2}(\ket{0_c 0_t}-\ket{1_c 1_t})$$

Q# でベル状態 $\ket{\phi^-}$ を作成する

  1. Q# コードを変更して、ベル状態 $\ket{\phi^-}$ を作成します。 Main.qs ファイルは次のようになります。

    import Microsoft.Quantum.Diagnostics.*; // Aka Std.Diagnostics.*;
    
    operation Main() : (Result, Result) {
        use (q1, q2) = (Qubit(), Qubit());
    
        H(q1);
        Z(q1); // Apply the Pauli Z operation to the control qubit
        CNOT(q1, q2);
    
        DumpMachine();
    
        let (m1, m2) = (M(q1), M(q2));
        Reset(q1);
        Reset(q2);
    
        return (m1, m2);
    }
    
  2. 組み込みのシミュレーターでプログラムを実行するには、Main 演算の上の [実行] をクリックするか、Ctrl + F5 キーを押します。 出力がデバッグ コンソールに表示されます。

  3. Main 演算の上にあるコマンドの一覧で Circuit をクリックすると、回路図を視覚化できます。 この回路図は、1 番目の量子ビットにアダマール ゲートが適用され、1 番目の量子ビットにパウリ $Z$ ゲートが適用されて、両方の量子ビットに CNOT ゲートが適用されたことを示しています。

ボーナス演習:ベル状態 $\ket{\psi^+}$ と $\ket{\psi^-}$ を作成する

同様に、量子ビットにパウリ $X$ 演算とパウリ $Z$ 演算を適用することで、ベル状態 $\ket{\psi^+}$ と $\ket{\psi^-}$ を作成できます。

  • ベル状態 $\ket{\psi^+}=\frac1{\sqrt2}(|01\rangle+|10\rangle)$ は、target 量子ビットにアダマール ゲートを適用してから、パウリ $X$ 演算を適用することで作成できます。
  • ベル状態 $\ket{\psi^-}=\frac1{\sqrt2}(|01\rangle-|10\rangle)$ は、制御量子ビットにパウリ $Z$ を適用し、target 量子ビットにアダマール ゲートを適用してから、パウリ $X$ を適用することで作成できます。

ベル状態 $\ket{\psi^+}$ と $\ket{\psi^-}$ を作成するように、Main.qs プログラムを変更してみましょう。