练习 - 使用 Q# 创建不同的叠加态

已完成

在上一单元中,你了解了叠加和 Dirac 表示法。 理论部分就说到这里吧! 我们来通过编写一些代码探讨 Q# 中的叠加。

在本单元中,你将使用 DumpMachine 函数通过 Q# 创建量子叠加并深入了解概率。 DumpMachine 函数可转储有关在调用它时量子系统当前状态的信息。

创建新的 Q# 文件

  1. 打开 Visual Studio Code。
  2. 在 Visual Studio Code 中,选择“文件”>“新建文本文件”,然后将文件另存为 Main.qs
  3. 选择“视图”->“命令面板”并键入“Q#:设置 Azure Quantum QIR 目标配置文件”。 按 Enter
  4. 选择“Q#:无限制”。

叠加入门

让我们从一个简单的程序开始,该程序使用叠加中的量子比特生成一个随机位。 你将使用 DumpMachine 函数来查看程序中不同时间点的量子比特状态。

  1. 将以下代码添加到 Main.qs 文件

    import Microsoft.Quantum.Diagnostics.*;
    
    operation Main() : Result {
        use q = Qubit();
        Message("Initialized qubit:");
        DumpMachine(); // First dump
        Message(" ");
        H(q);
        Message("Qubit after applying H:");
        DumpMachine(); // Second dump
        Message(" ");
        let randomBit = M(q);
        Message("Qubit after the measurement:");
        DumpMachine(); // Third dump
        Message(" ");
        Reset(q);
        Message("Qubit after resetting:");
        DumpMachine(); // Fourth dump
        Message(" ");
        return randomBit;
    }
    

    此处,调用 DumpMachine 四次:

    • 分配量子位后。
    • 将量子比特置于叠加之后。
    • 测量量子比特的状态之后。
    • 重置量子比特后。

    将运算 MResetZ 拆分为两个运算:MReset。 这样做是因为要在测量之后检查状态。

  2. 若要在内置模拟器运行程序,请在 Main 操作上方单击“运行”,或按 Ctrl+F5。 输出会显示在调试控制台中。

  3. DumpMachine 函数创建一个表,其中包含描述量子位寄存器状态的信息。 具体而言,它为每个基础状态提供概率振幅、概率和相位(以弧度为单位)。

  4. 程序结束时,你将获得 ZeroOne 的结果。 让我们看看每个步骤。

    1. 初始化的量子比特:用 use 语句分配的每个量子位都将以状态 $|0\rangle$ 开始。 因此 DumpMachine 会生成与状态为 $|0\rangle$ 的单量子位寄存器对应的信息。

      Initialized qubit:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
    2. 应用 H 后的量子比特:应用 H 后,我们使量子位准备好进入叠加状态 $|\psi\rangle=\frac1{\sqrt2} |0\rangle + \frac1{\sqrt2} |1\rangle$。

      Qubit after applying H:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
         |1⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
      
    3. 测量后的量子比特:在测量并存储结果(可能是 ZeroOne)之后。 例如,如果生成的状态为 One,则寄存器的状态将折叠为 $|1\rangle$ 并且不再在叠加中。

      Qubit after the measurement:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |1⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
    4. 重置后的量子比特:运算 Reset 将量子位重置为状态 $|0\rangle$。 请记住,对于任何 Q# 运算,始终要将使用的量子位保留在状态 $|0\rangle$ 中,便于其他运算使用。

      Qubit after resetting:
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
         |0⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      

    注意

    输出可能会有所不同,因为随机数生成器是概率性的。 结果的概率是不确定的。

探索其他类型的叠加状态

了解如何检查寄存器状态后,可以查看修改量子位状态并将其置于叠加中的更多操作。

当前随机数生成器生成的 ZeroOne 的概率为 50%。 我们来看另一个示例,它以不同的概率生成随机数。

偏斜随机位生成器

假设你要创建一个倾斜的随机比特生成器,即,得到 Zero 的概率与得到 One 的概率不同。

例如,你希望结果 Zero 的概率为 $P$,结果 One 的概率为 $1-P$。 下面是产生这种随机比特生成器的有效量子比特状态:

$$|\psi\rangle=\sqrt{P}|0\rangle+\sqrt{1-P}|1\rangle$$

此处,$\alpha=\sqrt{P}$ 和 $\beta=\sqrt{1-P}$ 分别是基态 $|0\rangle$ 和 $|1\rangle$ 的振幅。

可以通过按顺序将运算符 $R_y(2\arccos\sqrt{P})$ 应用到状态 $|0\rangle.$ 中的量子位来获取此状态。你可以在 Q# 中使用标准库的 Ry 运算来实现此结果。

提示

若要详细了解单量子比特运算背后的数学原理,请参阅 Quantum Katas 中的单量子比特门教程

  1. 按如下所示修改 Main.qs,然后保存文件。 此示例选择与 $\frac13$ 近似的 $\alpha$。

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Math.*;
    
    operation Main() : Result {
        use q = Qubit();
        let P = 0.333333; // P is 1/3
        Ry(2.0 * ArcCos(Sqrt(P)), q);
        Message("The qubit is in the desired state.");
        Message("");
        DumpMachine(); // Dump the state of the qubit 
        Message("");
        Message("Your skewed random bit is:");
        let skewedrandomBit = M(q);
        Reset(q);
        return skewedrandomBit;
    }
    
  2. 若要在内置模拟器运行程序,请在 Main 操作上方单击“运行”,或按 Ctrl+F5。 输出会显示在调试控制台中。

  3. 可以看到 DumpMachine 如何在应用运算后显示预期状态并显示关联的概率。 请注意,得到 Zero 的概率大约为 33.33%,得到 One 的概率大约为 66.67%。 因此,随机比特生成器是倾斜的。

    The qubit is in the desired state.
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
       |0⟩ |  0.5773+0.0000𝑖 |    33.3333% |   0.0000
       |1⟩ |  0.8165+0.0000𝑖 |    66.6667% |   0.0000
    
    
    Your skewed random bit is:
    Result: "One"
    

    注意

    输出可能会有所不同,因为随机数生成器是概率性的。 结果的概率是不确定的。

多量子位叠加

现在,我们来研究包含多个量子位的寄存器的叠加。 例如,如果有一个寄存器,其中包含三个量子位,则有 8 个基态:

$$|000\rangle,|001\rangle,|010\rangle,|011\rangle,|100\rangle,|101\rangle, |110\rangle,|111\rangle $$

因此,你可以将任意三个量子位的状态表示为:

$$|\psi\rangle=\alpha_0|000\rangle+\alpha_1|001\rangle+\alpha_2|010\rangle+\alpha_3|011\rangle+\alpha_4|100\rangle+\alpha_5|101\rangle+\alpha_6 |110\rangle+\alpha_7|111\rangle$$

此处,$\alpha_i$ 是满足 $\sum|\alpha_i|^2=1$ 的复数。

例如,通过对每个量子比特应用 H,可以将量子比特置于均匀叠加状态。 可以使用这种均匀叠加来创建一个不同版本的量子随机数生成器,该生成器通过测量叠加中的三个量子位而不是一次测量一个量子位来生成 3 位数。

Basis Number
$\ket{000}$ 0
$\ket{001}$ 1
$\ket{010}$ 2
$\ket{011}$ 3
$\ket{100}$ 4
$\ket{101}$ 5
$\ket{110}$ 6
$\ket{111}$ 7
  1. 按如下所示修改 Main.qs,然后保存文件。

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Math.*;
    import Microsoft.Quantum.Convert.*;
    import Microsoft.Quantum.Arrays.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        let result = ForEach(M, qubits);
        Message("Measuring the qubits collapses the superposition to a basis state.");
        DumpMachine();
        ResetAll(qubits);
        return BoolArrayAsInt(ResultArrayAsBoolArray(result));
    }
    

    在这里,你将看到三个概念:

    • qubits 变量现表示一个长度为 3 的 Qubit 数组。
    • ApplyToEachForEach 运算可以用更少的代码对多个量子比特进行测量和处理。 Q# 库提供了多种运算和函数,使编写量子程序的效率更高。
    • Microsoft.Quantum.Convert 库中的 BoolArrayAsIntResultArrayAsBoolArray 函数将 ForEach(M, qubits) 返回的二进制 Result 数组转换为整数。
  2. 若要运行程序,请单击 Main 操作上方的“运行”,或按 Ctrl+F5。 输出会显示在调试控制台中。

  3. 使用 DumpMachine 可以看到测量三个量子位的操作如何将寄存器的状态折叠到八个可能的基础状态之一。 例如,如果得到结果 3,则表示寄存器的状态已折叠为 $|110\rangle$。

    The qubit register in a uniform superposition:
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
     |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
    
    Measuring the qubits collapses the superposition to a basis state.
    
    DumpMachine:
    
     Basis | Amplitude      | Probability | Phase
     -----------------------------------------------
     |110⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
    
    Result: "3"
    

    注意

    输出可能会有所不同,因为随机数生成器是概率性的。 结果的概率是不确定的。

  4. ForEach(M, qubit) 运算依次测量每个量子位,从而逐渐折叠状态。 还可以在每次测量后转储中间状态。 为此,请如下所示修改 Main.qs,然后保存文件。

    import Microsoft.Quantum.Diagnostics.*;
    import Microsoft.Quantum.Measurement.*;
    import Microsoft.Quantum.Math.*;
    import Microsoft.Quantum.Convert.*;
    
    operation Main() : Int {
        use qubits = Qubit[3];
        ApplyToEach(H, qubits);
        Message("The qubit register in a uniform superposition: ");
        DumpMachine();
        mutable results = [];
        for q in qubits {
            Message(" ");
            set results += [M(q)];
            DumpMachine();
        }
        Message(" ");
        Message("Your random number is: ");
        ResetAll(qubits);
        return BoolArrayAsInt(ResultArrayAsBoolArray(results));
    }
    
  5. 在这里,使用 for 循环按顺序处理每个量子位。 Q# 具有经典的流控制功能,例如 for 循环和 if 语句,你可以使用这些功能来控制程序流。

  6. 要运行程序,请从 Main 操作上方的命令列表中单击“运行”,或按 Ctrl+F5

  7. 可以看到每个连续测量是如何改变量子态的,并因此改变获得每个结果的概率。 例如,如果结果为数字 5,你将得到以下输出。 让我们简单了解下每个步骤:

    1. 状态准备:在将 H 应用到寄存器的每个量子位后,将获得一个均匀叠加。

      The qubit register in a uniform superposition: 
      
      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |000⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |001⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |010⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |011⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |100⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |101⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |110⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
       |111⟩ |  0.3536+0.0000𝑖 |    12.5000% |   0.0000
      
    2. 第一次测量:在第一次测量中,结果为 One。 因此,最右边的量子位为 Zero 的状态的所有振幅已不再存在。 振幅为:$|0\rangle=|000\rangle、|2\rangle=|010\rangle、|4\rangle=|100\rangle$ 和 $|6\rangle= |110\rangle$。 振幅的其余部分将增加以满足标准化条件。

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |001⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |011⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |101⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
       |111⟩ |  0.5000+0.0000𝑖 |    25.0000% |   0.0000
      
    3. 第二次测量:在第二次测量中,结果为 Zero。 因此,最右边第二个(中间)量子位为 One 的状态的所有振幅都将消失。 振幅为 $|3\rangle=|011\rangle$ 和 $|7\rangle=|111\rangle$。 振幅的其余部分将增加以满足标准化条件。

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |001⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
       |101⟩ |  0.7071+0.0000𝑖 |    50.0000% |   0.0000
      
    4. 第三次测量:在第三次测量中,结果为 One。 因此,最左边的量子位为 Zero 的状态的所有振幅都将被清除。唯一兼容的状态是 $|5\rangle=|101\rangle$。 此状态获取的振幅概率为 $1$。

      DumpMachine:
      
       Basis | Amplitude      | Probability | Phase
       -----------------------------------------------
       |101⟩ |  1.0000+0.0000𝑖 |   100.0000% |   0.0000
      
      
      Your random number is: 
      Result: "5"
      

    注意

    输出可能会有所不同,因为随机数生成器是概率性的。 结果的概率是不确定的。