Q# を使用してテレポーテーションを作成する

完了

前のユニットでは、量子テレポート プロトコルの手順を確認しました。 今度は、Alice と Bob の量子テレポーテーション実験を手助けする番です。

このユニットでは、量子テレポート プロトコルを使用して量子ビットの状態を Alice から Bob に送信する量子テレポート プログラムを Q# で作成します。

Q# で量子テレポーテーション プログラムを作成する

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

必要なライブラリをインポートする

最初に、Q# の演算と関数を使用するために必要なライブラリをインポートする必要があります。 次のコードをコピーし、Main.qs ファイルに貼り付けます。

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

Teleport 演算を定義する

まず、量子テレポーテーション プロトコルを実装する Teleport 演算を定義する必要があります。 この演算は、2 つの量子ビットを入力として受け取ります。テレポートされる量子状態を含む message 量子ビットと、その状態を受け取る bob 量子ビットです。

operation Teleport(message : Qubit, bob : Qubit) : Unit {
        // Allocate an alice qubit.
        use alice = Qubit();

        // Create some entanglement that we can use to send our message.
        H(alice);
        CNOT(alice, bob);

        // Encode the message into the entangled pair.
        CNOT(message, alice);
        H(message);

        // Measure the qubits to extract the classical data we need to decode
        // the message by applying the corrections on the bob qubit
        // accordingly.
        if M(message) == One {
            Z(bob);
        }
        if M(alice) == One {
            X(bob);
        }

        // Reset alice qubit before releasing.
        Reset(alice);
    }

以下で Teleport 演算を詳しく見ていきましょう。

  1. この演算は、alice 量子ビットを使用して、alicebob の量子ビットの間にエンタングルメントを作成します。 その後、message 量子ビットは alice 量子ビットとのエンタングル状態になるため、この 2 つの量子ビットは bob 量子ビットとのエンタングル状態となり、message がエンコードされます。

  2. 次に、ベル基底で alicemessage の量子ビットを測定する必要があります。 どうすればベル基底での測定を Q# で表現できるでしょうか? できません。 少なくとも直接的にはできません。 Q# には M 演算が存在し、これは $Z$ 基底あるいは計算基底で測定を実行します。 そのため、M 演算を正しく使用するには、ベル状態を計算基底状態に変換する必要があります。 これを行うには、message 量子ビットに H 演算を適用します。 次の表は、ベル状態と計算基底状態の対応関係を示しています。

    ベルの状態 計算基底状態
    $\ket{\phi^+}$ $\ket{00}$
    $\ket{\phi^-}$ $\ket{01}$
    $\ket{\psi^+}$ $\ket{10}$
    $\ket{\psi^-}$ $\ket{11}$

    ヒント

    最初の量子ビットにアダマール演算を適用した後のベル状態と計算基底状態の等価性を確認することは良い演習となります。 がんばってください。

  3. 最後に、if ステートメントは測定結果をチェックし、それに応じて bob 量子ビットに修正を適用します。 message 量子ビットを One で測定する場合は、Z ゲートを bob 量子ビットに適用します。 alice 量子ビットも One で測定する場合は、bob 量子ビットに X ゲートを適用します。

SetToPlus および SetToMinus 演算を定義する

|0⟩、|1⟩、|+⟩、|−⟩ などのさまざまな状態の量子ビットをテレポートしたい場合は、初期状態を定義する必要があります。 量子ビットをテレポートする Teleport 演算は既に存在しますが、テレポートする前に、量子ビットを正しい状態に準備する必要があります。

|0⟩ 状態の量子ビットをそれぞれ |+⟩ と |−⟩ に設定する SetToPlusSetToMinus という 2 つの演算をさらに定義する必要があります。

    /// Sets a qubit in state |0⟩ to |+⟩.
    operation SetToPlus(q : Qubit) : Unit is Adj + Ctl {
        H(q);
    }

    /// Sets a qubit in state |0⟩ to |−⟩.
    operation SetToMinus(q : Qubit) : Unit is Adj + Ctl {
        X(q);
        H(q);
    }

Main 演算を定義する

すべての Q# プログラムには、プログラムのエントリ ポイントとして機能する Main 演算が必要です。 Main 演算は、さまざまな量子状態 ($\ket{{0}$、$\ket{1}$、$\ket{+}$、$\ket{-}$) に対してテレポート プロトコルを実行します。

以下で Main 演算を詳しく見ていきましょう。

  1. この演算では、messagebob の 2 つの量子ビットを割り当てます。
  2. 量子状態、その状態で量子ビットを初期化するために必要な初期化子演算、テレポートの基準を含むタプルの一覧を定義します。 初期化子演算は、$\ket{0}$ の場合は I、$\ket{1}$ の場合は X、$\ket{+}$ の場合は SetToPlus、$\ket{-}$ の場合は SetToMinus です。 SetToPlus および SetToMinus 演算は、前の手順で定義されています。
  3. この操作では、タプルの一覧を反復処理し、対応する状態の message 量子ビットを初期化し、DumpMachine を使用して状態を表示します。 次に、前の手順で定義した Teleport 演算を使用して、message 量子ビットの状態を bob 量子ビットにテレポートします。
  4. 状態をテレポートした後、この演算は、対応する基準で bob 量子ビットを測定し、量子ビットをリセットして、さらに別のメッセージのテレポートを続行します。
  5. 最後に、この演算は各テレポートの測定結果を返します。
operation Main() : Result[] {
    // Allocate the message and bob qubits.
    use (message, bob) = (Qubit(), Qubit());

    // Use the `Teleport` operation to send different quantum states.
    let stateInitializerBasisTuples = [
        ("|0〉", I, PauliZ),
        ("|1〉", X, PauliZ),
        ("|+〉", SetToPlus, PauliX),
        ("|-〉", SetToMinus, PauliX)
    ];

    mutable results = [];
    for (state, initializer, basis) in stateInitializerBasisTuples {
        // Initialize the message and show its state using the `DumpMachine`
        // function.
        initializer(message);
        Message($"Teleporting state {state}");
        DumpMachine();

        // Teleport the message and show the quantum state after
        // teleportation.
        Teleport(message, bob);
        Message($"Received state {state}");
        DumpMachine();

        // Measure bob in the corresponding basis and reset the qubits to
        // continue teleporting more messages.
        let result = Measure([basis], [bob]);
        set results += [result];
        ResetAll([message, bob]);
    }

    return results;
}

プログラムの実行

これで量子テレポーテーション プログラムの準備ができました。 プログラムを実行して、さまざまな量子状態に対して量子テレポーテーションがどのように機能するかを確認できます。 このプログラムは、message 量子ビットをさまざまな状態に初期化し、その状態を bob 量子ビットへテレポートします。

次のコードには、Teleport 演算、SetToPlus および SetToMinus 演算、そしてさまざまな量子状態に対してテレポーテーション プロトコルを実行する Main 演算が含まれています。

  1. Main.qs ファイルは次のようになります。

    /// This Q# program implements quantum teleportation.
    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Intrinsic.*;
    import Microsoft.Quantum.Measurement.*;
    
    operation Main() : Result[] {
        // Allocate the message and bob qubits.
        use (message, bob) = (Qubit(), Qubit());
    
        // Use the `Teleport` operation to send different quantum states.
        let stateInitializerBasisTuples = [
            ("|0〉", I, PauliZ),
            ("|1〉", X, PauliZ),
            ("|+〉", SetToPlus, PauliX),
            ("|-〉", SetToMinus, PauliX)
        ];
    
        mutable results = [];
        for (state, initializer, basis) in stateInitializerBasisTuples {
            // Initialize the message and show its state using the `DumpMachine`
            // function.
            initializer(message);
            Message($"Teleporting state {state}");
            DumpMachine();
    
            // Teleport the message and show the quantum state after
            // teleportation.
            Teleport(message, bob);
            Message($"Received state {state}");
            DumpMachine();
    
            // Measure bob in the corresponding basis and reset the qubits to
            // continue teleporting more messages.
            let result = Measure([basis], [bob]);
            set results += [result];
            ResetAll([message, bob]);
        }
    
        return results;
    }
    
    /// # Summary
    /// Sends the state of one qubit to a bob qubit by using teleportation.
    ///
    /// Notice that after calling Teleport, the state of `message` is collapsed.
    ///
    /// # Input
    /// ## message
    /// A qubit whose state we wish to send.
    /// ## bob
    /// A qubit initially in the |0〉 state that we want to send
    /// the state of message to.
    operation Teleport(message : Qubit, bob : Qubit) : Unit {
        // Allocate an alice qubit.
        use alice = Qubit();
    
        // Create some entanglement that we can use to send our message.
        H(alice);
        CNOT(alice, bob);
    
        // Encode the message into the entangled pair.
        CNOT(message, alice);
        H(message);
    
        // Measure the qubits to extract the classical data we need to decode
        // the message by applying the corrections on the bob qubit
        // accordingly.
        if M(message) == One {
            Z(bob);
        }
        if M(alice) == One {
            X(bob);
        }
    
        // Reset alice qubit before releasing.
        Reset(alice);
    }
    
    /// # Summary
    /// Sets a qubit in state |0⟩ to |+⟩.
    operation SetToPlus(q : Qubit) : Unit is Adj + Ctl {
        H(q);
    }
    
    /// # Summary
    /// Sets a qubit in state |0⟩ to |−⟩.
    operation SetToMinus(q : Qubit) : Unit is Adj + Ctl {
        X(q);
        H(q);
    }
    
  2. 組み込みのシミュレーターでプログラムを実行するには、Main 演算の上の [実行] をクリックするか、Ctrl+F5 キーを押します。 出力がデバッグ コンソールに表示されます。

  3. 受信した状態がテレポートしている状態と一致することを確認します。 次に例を示します。

    Teleporting state |0〉
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
      |00⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
    Received state |0〉