量子コンピューティング向け言語Q#の問題集 QuantumKatas Teleportation Task 1.5~1.7 メッセージがパウリ行列の固有状態のときのテレポーテーション

Task 1.5~1.7 はパウリ行列の固有状態をメッセージとするテレポーテーションです。

登場人物は以下の3つです。

テレポーテーションのおおまかな手順は以下です。

  1. AliceとBobの量子ビットエンタングルさせる
  2. メッセージの量子ビットを準備する
  3. メッセージとAliceの量子ビットエンタングルさせる
  4. Alice側でメッセージの量子ビットとAliceの量子ビットを測定し、測定結果を古典ビットとしてBobに送信する
  5. Bob側で受信した古典ビットを利用して、Bobの量子ビットをメッセージの量子ビットと同じ状態にする

あまり、深く理解していないのですが、上記の4と5を行ってしまったら、古典的な通信と何が違うのかなぁと、疑問に思っています。

それはさておき、問題を解きます。

パウリ行列とその固有状態は以下です。

パウリ行列 固有値+1の固有状態 固有値-1の固有状態
 \sigma_{x} (|0⟩ + |1⟩) / sqrt(2) (|0⟩ - |1⟩) / sqrt(2)
 \sigma_{y} (|0⟩ - i|1⟩) / sqrt(2) (|0⟩ + i|1⟩) / sqrt(2)
 \sigma_{z} |0⟩ |1⟩

Task 1.5は手順の2〜4までを行う問題です。

Task 1.6は手順の5を行う問題です。

Task 1.7は全ての手順を行ってテストするという問題です。

    // Task 1.5. Prepare a state and send it as a message (Alice's task)
    // Given a Pauli basis along with a state 'True' as 'One' or 'False'
    // as 'Zero' prepare a message qubit, entangle it with Alice's qubit,
    // and extract two classical bits to be sent to Bob.
    // Inputs:
    //      1) Alice's part of the entangled pair of qubits qAlice.
    //      2) A PauliX, PauliY, or PauliZ basis in which the message
    //         qubit should be prepared
    //      3) A Bool indicating the eigenstate in which the message
    //         qubit should be prepared
    // Output:
    //      Two classical bits Alice will send to Bob via classical channel as a tuple of Bool values.
    //      The first bit in the tuple should hold the result of measurement of the message qubit,
    //      the second bit - the result of measurement of Alice's qubit.
    //      Represent measurement result 'One' as 'True' and 'Zero' as 'False'.
    // The state of the qubit qAlice in the end of the operation doesn't matter.
    operation PrepareAndSendMessage (qAlice : Qubit, basis : Pauli, state : Bool) : (Bool, Bool) {
      mutable bMessage = false;
      mutable bAlice = false;

      using (qMessage = Qubit()) {
        if (state) {
          X(qMessage);
        }

        PrepareQubit(basis, qMessage);
        CNOT(qMessage, qAlice);
        H(qMessage);

        set bMessage = M(qMessage) == One;
        set bAlice = M(qAlice) == One;

        Reset(qMessage);
      }

      return (bMessage, bAlice);
    }
    
    
    // Task 1.6. Reconstruct and measure the message state (Bob's task)
    // Transform Bob's qubit into the required state using the two classical bits
    // received from Alice and measure it in the same basis in which she prepared the message.
    // Inputs:
    //      1) Bob's part of the entangled pair of qubits qBob.
    //      2) The tuple of classical bits received from Alice,
    //         in the format used in task 1.5.
    //      3) The PauliX, PauliY, or PauliZ basis in which the
    //         message qubit was originally prepared
    // Output:
    //      A Bool indicating the eigenstate in which the message qubit was prepared, 'One' as
    //      'True' and 'Zero' as 'False'.
    // Goal: transform Bob's qubit qBob into the state in which the message qubit was originally
    // prepared, then measure it. The state of the qubit qBob in the end of the operation doesn't matter.
    operation ReconstructAndMeasureMessage (qBob : Qubit, (b1 : Bool, b2 : Bool), basis : Pauli) : Bool {
      if (b2) {
        X(qBob);
      }

      if (b1) {
        Z(qBob);
      }

      return Measure([basis], [qBob]) == One;
    }
    
    
    // Task 1.7. Testing standard quantum teleportation
    // Goal: Test that the StandardTeleport operation from task 1.4 is able
    // to successfully teleport the states |0⟩ and |1⟩, as well as superpositions such as
    // (|0⟩ + |1⟩) / sqrt(2),
    // (|0⟩ - |1⟩) / sqrt(2),
    // (|0⟩ + i|1⟩) / sqrt(2), and
    // (|0⟩ - i|1⟩) / sqrt(2)
    operation StandardTeleport_Test () : Unit {
        // Hint: You may find your answers for 1.5 and 1.6 useful
        let messages = [(PauliZ, false),  // |0>
                        (PauliZ, true ),  // |1>
                        (PauliX, false),  // (|0> + |1>) / sqrt(2)
                        (PauliX, true ),  // (|0> - |1>) / sqrt(2)
                        (PauliY, true ),  // (|0> + i|1>) / sqrt(2)
                        (PauliY, false)   // (|0> - i|1>) / sqrt(2)
                        ];

        using ((qAlice, qBob) = (Qubit(), Qubit())) {
          for (i in 0 .. Length(messages) - 1) {
            H(qAlice);
            CNOT(qAlice, qBob);

            let (basis, state) = messages[i];

            let classicalBits = PrepareAndSendMessage(qAlice, basis, state);
            let receivedState = ReconstructAndMeasureMessage(qBob, classicalBits, basis);
            AssertBoolEqual(receivedState, state, $"send state: {state}, received state: {receivedState}");
            ResetAll([qAlice, qBob]);
          }
        }
    }