练习 - 使用纠缠通过 Q# 进行传送

已完成

在上一单元中,你了解了量子隐形传态协议的步骤。 现在轮到你帮助 Alice 和 Bob 进行量子隐形传态试验了!

在本单元中,你将在 Q# 中创建一个量子隐形传态程序,该程序使用量子隐形传态协议将量子比特的状态从 Alice 发送给 Bob。

使用 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 操作。 该操作采用两个量子比特作为输入:包含要传送的量子状态的 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 量子比特纠缠,因此这两个量子比特与 bob 量子比特纠缠,并且 message 被编码。

  2. 然后,需要在 Bell 基中测量 alicemessage 量子比特。 如何使用 Q# 表示 Bell 基中的测量值? 你无法管理。 或者至少不是直接表示。 Q# 中具有 M 操作,该操作在 $Z$ 基或计算基中执行测量。 因此,要正确使用 M 操作,需要将 Bell 态转换为计算基态。 为此,可以将 H 操作应用到 message 量子比特。 下表显示了 Bell 态与计算基态之间的对应关系。

    响铃状态 计算基态
    $\ket{\phi^+}$ $\ket{00}$
    $\ket{\phi^-}$ $\ket{01}$
    $\ket{\psi^+}$ $\ket{10}$
    $\ket{\psi^-}$ $\ket{11}$

    提示

    一个很好的练习是在将 Hadamard 操作应用于第一个量子比特后验证 Bell 态和计算基态的等效性。 祝你好运!

  3. 最后,if 语句检查测量结果,并相应地对 bob 量子比特应用更正。 如果 message 量子比特是在 One 中测量的,则将 Z 门应用于 bob 量子比特。 如果 alice 量子比特也是在 One 中测量的,则将 X 门应用于 bob 量子比特。

定义 SetToPlusSetToMinus 操作

如果想要传送不同状态(例如 |0⟩、|1⟩、|+⟩ 和 |−⟩)的量子比特,必须定义初始化状态。 你已有传送量子比特的 Teleport 操作,但需要在传送之前准备处于正确状态的量子比特。

需要定义另外两个操作(SetToPlusSetToMinus)来将状态为 |0⟩ 的量子比特分别设置为 |+⟩ 和 |−⟩。

    /// 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. 它会定义一系列元组,包含量子状态、初始化处于此类状态的量子比特所需的初始程序操作以及隐形传态的基础。 初始程序操作为 I(用于 $\ket{0}$)、X(用于 $\ket{1}$)、SetToPlus(用于 $\ket{+}$)和 SetToMinus(用于 $\ket{-}$)。 上述步骤中定义了操作 SetToPlusSetToMinus
  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 操作、SetToPlusSetToMinus 操作,以及针对不同量子状态运行隐形传态协议的 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〉