你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

教程:使用 Q# 探索量子纠缠

在本教程中,你将编写一个 Q# 程序来操作和度量量子比特,并演示叠加和纠缠的影响。 你准备两个处于特定量子状态的量子比特,了解如何对量子比特 Q# 进行操作以更改其状态,并演示叠加和纠缠的影响。 构建程序逐条引入 Q# 量子比特状态、操作和度量。

下面是在开始之前要了解的一些关键概念:

  • 经典位保存单个二进制值(如 0 或 1),而量子比特的状态则可以是 0 和 1 的双量子状态的叠加。 每种可能的量子状态具有一个关联的概率幅度。
  • 测量量子比特的行为会产生具有特定概率的二进制结果,并将量子比特的状态更改为叠加。
  • 可以纠缠多个量子比特,以便无法相互独立地描述它们。 也就是说,无论纠缠对中的一个量子比特发生什么情况,另一个量子比特也会发生相同的情况。

本教程介绍以下操作:

  • 创建 Q# 操作以将量子比特初始化为所需状态。
  • 将量子比特置于叠加状态。
  • 纠缠一对量子比特。
  • 测量量子比特并观察结果。

提示

若要加速量子计算之旅,请查看 Azure Quantum 代码,这是 Azure Quantum 网站的独特功能。 在这里,你可以运行内置Q#示例或你自己的Q#程序,通过提示生成新Q#代码,在 VS Code for the Web打开并运行代码,只需单击一下,并询问 Copilot 有关量子计算的任何问题。

先决条件

若要在 Copilot for Azure Quantum 中运行代码示例,需要:

  • Microsoft(MSA)电子邮件帐户。

有关 Copilot 的详细信息,请参阅 探索 Azure Quantum

将量子位初始化为已知状态

第一步是定义一个 Q# 运算,用于将量子比特初始化为已知状态。 这可以调用以将量子比特设置为经典状态,这意味着在测量时,它 Zero 返回 100% 的时间或返回 One 100% 的时间。 测量量子比特将返回一个 Q# 类型,该类型 Result只能有一个值 ZeroOne

打开适用于 Azure QuantumCopilot 并将以下代码复制到代码编辑器窗口中。 请勿单击“运行;稍后将在本教程中运行代码。

   namespace Bell {
       open Microsoft.Quantum.Intrinsic;
       open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }
   }

该代码示例引入了用于变换量子比特状态的两个标准运算(MX)。

SetQubitState 运算:

  1. 采用两个参数:一个类型 Result,命名 desired,表示量子位处于(Zero 或) One和类型 Qubit所需的状态。
  2. 执行测量运算 M,以测量量子比特的状态(ZeroOne),并将结果与 desired 中指定的值进行比较。
  3. 如果度量值与比较的值不一致,它会运行 X 运算,将量子比特的状态翻转到度量结果为 ZeroOne 的概率相反的位置。 这样,SetQubitState 会始终将目标量子比特置于所需状态下。

编写测试操作以测试 Bell 状态

接下来,为了演示 SetQubitState 运算的效果,请创建名为 TestBellState 的另一个运算。 此操作将分配两个量子比特,调用 SetQubitState 将第一个量子比特设置为已知状态,然后测量量子比特以查看结果。

将以下代码复制到代码编辑器窗口中,操作下方 SetQubitState

operation TestBellState() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

在代码中,变量countinitial分别设置为1000One分别。 这会将第一个量子比特初始化为 One,并测量每个量子比特 1000 次。

TestBellState 运算:

  1. 设置计数器的变量和初始量子比特状态。
  2. 调用 use 语句以初始化两个量子比特。
  3. 循环 count 迭代。 对于每个循环,它:
    1. 调用 SetQubitState 以便对第一个量子比特设置指定的 initial 值。
    2. 再次调用 SetQubitState 以将第二个量子比特设置为 Zero 状态。
    3. 使用 M 运算来测量每个量子比特。
    4. 存储每个量子比特的、返回 One 的测量数目。
  4. 循环完成后,它会再次调用 SetQubitState 以将量子比特重置为已知状态 (Zero),使其他对象能够以已知状态分配量子比特。 这是 use 语句所必需的。
  5. 最后,它使用 Message 函数将结果打印到 Copilot 输出窗口,然后再返回结果。

在 Copilot for Azure Quantum 中运行代码

在继续执行叠加和纠缠的过程之前,可以测试到此点的代码,以查看量子比特的初始化和度量。

若要将代码作为独立程序运行, Q# Copilot 中的编译器需要知道 从何处 启动程序。 这是在 Q# 文件中完成的,方法是在要首先运行的操作前面添加一个 @EntryPoint() 直接操作。 例如,在本例中 TestBellState 是操作。

注意

只有独立的 Q# 程序才需要 @EntryPoint()。 在 Jupyter Notebooks 中运行 Q# 程序或从 Python 主机文件调用 Q# 程序时,不需要它,如果包含,将引发错误。

@EntryPoint()操作Q#前TestBellState立即添加,程序现在应如下所示:

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
            
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

将完整的代码示例复制并粘贴到 Copilot for Azure Quantum 代码窗口中,将拍摄次数的幻灯片设置为“1”,然后单击“ 运行”。 结果显示在直方图和 结果 字段中。

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0

由于尚未操作这些量子比特,因此它们保留了自己的初始值:第一个量子比特每次都返回 One,第二个量子比特返回 Zero

如果将值 initial 更改为 Zero 并再次运行程序,则应观察第一个量子比特每次也会返回 Zero

Q1 - Zeros: 1000
Q1 - Ones: 0
Q2 - Zeros: 1000
Q2 - Ones: 0

将量子比特置于叠加状态

目前,程序中的量子比特都处于经典状态,即,要么为 1,要么为 0。 之所以知道这一点,是因为该程序会将量子比特初始化为已知状态,并且你未添加任何过程来操作量子比特。 在纠缠量子比特之前,将第一个 量子比特置于叠加状态,其中量子比特的度量将返回 Zero 大约 50% 的时间和 One 大约 50% 的时间。 从概念上讲,量子比特可以视为测量概率相等 ZeroOne

Q# 提供了 H (Hadamard) 运算用于将量子比特置于叠加状态X将运算从“初始化量子比特”撤回到之前的已知状态过程,该过程将量子比特从 0 翻转为 1(反之亦然);该操作将H量子比特转为等于概率ZeroOne或的状态。 测量时,叠加的量子比特应返回大致相等数量的 ZeroOne 结果。

通过重置操作的初始值One并插入操作的行H来修改操作中的TestBellState代码:

for test in 1..count {
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        H(q1);                // Add the H operation after initialization and before measurement

        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2); 
        ...

现在,运行程序时,可以看到叠加中第一个量子位的结果。

Q1 - Zeros: 523            // results will vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0

每次运行该程序,第一个量子比特的结果略有不同,但在大约 50% 的时间为 One,大约 50% 的时间为 Zero,而第二个量子比特的结果始终保持为 Zero

Q1 - Zeros: 510           
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0

将第一个量子比特初始化为 Zero 会返回类似的结果。

Q1 - Zeros: 504           
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0

注意

通过在 Copilot for Azure Quantum 中移动滑块并增加拍摄次数,可以看到叠加结果在拍摄分布上稍有变化。

纠缠两个量子比特

如前所述,纠缠的量子比特的连接方式使得它们不能相互独立地描述。 也就是说,无论一个量子比特发生了什么运算,纠缠的量子比特也会发生这种运算。 这样,只需测量一个量子比特的状态,就能知道另一个量子比特的最终状态,而无需测量它。 (此示例使用两个量子比特;但是,也可以纠缠三个或更多量子比特)。

Q# 提供了 CNOT(Controlled-NOT 的缩写)运算用于实现纠缠。 对两个量子比特运行此操作的结果是,在第一个量子比特是 One 的情况下翻转第二个量子比特。

在程序中紧接在 H 运算的后面添加 CNOT 运算。 完整程序应如下所示:

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = Zero;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
        
            H(q1);            
            CNOT(q1, q2);      // Add the CNOT operation after the H operation

            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

现在,运行程序时,应会看到如下所示的内容:

Q1 - Zeros: 502           // results will vary
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498

请注意,第一个量子比特的统计信息尚未更改(测量后仍有大约 50/50 个概率ZeroOne),但第二个量子比特的度量结果始终与第一个量子位的测量相同,无论运行程序多少次。 CNOT 运算将这两个量子比特纠缠在一起,因此,不论其中一个发生什么情况,另一个也会同样发生。

先决条件

若要在本地开发环境中开发和运行代码示例,请执行以下操作:

创建新 Q# 文件

  1. 打开 Visual Studio Code 并选择“文件”>“新建文本文件”以创建新文件。
  2. 将文件另存为 CreateBellStates.qs。 此文件将包含 Q# 程序的代码。

将量子位初始化为已知状态

第一步是定义一个 Q# 运算,用于将量子比特初始化为已知状态。 可以调用此运算以将量子比特设置为经典状态,这意味着它要么在 100% 的时间返回 Zero,要么在 100% 的时间返回 OneZeroOne 是表示对量子比特进行测量时仅有的两个可能结果的 Q# 值。

打开 CreateBellStates.qs 并复制以下代码:

   namespace Bell {
       open Microsoft.Quantum.Intrinsic;
       open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }
   }

该代码示例引入了用于变换量子比特状态的两个标准运算(MX)。

SetQubitState 运算:

  1. 采用两个参数:一个类型 Result,命名 desired,表示量子位处于(Zero 或) One和类型 Qubit所需的状态。
  2. 执行测量运算 M,以测量量子比特的状态(ZeroOne),并将结果与 desired 中指定的值进行比较。
  3. 如果度量值与比较的值不一致,它会运行 X 运算,将量子比特的状态翻转到度量结果为 ZeroOne 的概率相反的位置。 这样,SetQubitState 会始终将目标量子比特置于所需状态下。

编写测试操作以测试 Bell 状态

接下来,为了演示 SetQubitState 运算的效果,请创建名为 TestBellState 的另一个运算。 此操作将分配两个量子比特,调用 SetQubitState 将第一个量子比特设置为已知状态,然后测量量子比特以查看结果。

将以下运算添加到 CreateBellStates.qs 文件中的 SetQubitState 运算后面:

operation TestBellState() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

在代码中,变量countinitial分别设置为1000One分别。 这会将第一个量子比特初始化为 One,并测量每个量子比特 1000 次。

TestBellState 运算:

  1. 采用两个参数:count,即测量的运行次数;initial,即要将量子比特初始化到的所需状态。
  2. 调用 use 语句以初始化两个量子比特。
  3. 循环 count 迭代。 对于每个循环,它:
    1. 调用 SetQubitState 以便对第一个量子比特设置指定的 initial 值。
    2. 再次调用 SetQubitState 以将第二个量子比特设置为 Zero 状态。
    3. 使用 M 运算来测量每个量子比特。
    4. 存储每个量子比特的、返回 One 的测量数目。
  4. 循环完成后,它会再次调用 SetQubitState 以将量子比特重置为已知状态 (Zero),使其他对象能够以已知状态分配量子比特。 这是 use 语句所必需的。
  5. 最后,它使用 Message 函数在返回结果之前将消息输出到控制台。

运行代码

在继续执行叠加和纠缠过程之前,测试到目前为止的代码,以查看量子比特的初始化和测量。

此操作在文件中完成 Q# ,方法是在要运行的操作前面添加一个 @EntryPoint() 直接操作。 例如,在本例中 TestBellState 是操作。

注意

只有独立的 Q# 程序才需要 @EntryPoint()。 在 Jupyter Notebooks 中运行 Q# 程序或从 Python 主机文件调用 Q# 程序时,不需要它,如果包含,将引发错误。

  1. CreateBellStates.qs 文件现在应如下所示:

    namespace Bell {
        open Microsoft.Quantum.Intrinsic;
        open Microsoft.Quantum.Canon;
    
           operation SetQubitState(desired : Result, target : Qubit) : Unit {
               if desired != M(target) {
                   X(target);
               }
           }
    
        @EntryPoint()
        operation TestBellState() : (Int, Int, Int, Int) {
            mutable numOnesQ1 = 0;
            mutable numOnesQ2 = 0;
            let count = 1000;
            let initial = One;
    
            // allocate the qubits
            use (q1, q2) = (Qubit(), Qubit());   
            for test in 1..count {
                SetQubitState(initial, q1);
                SetQubitState(Zero, q2);
    
                // measure each qubit
                let resultQ1 = M(q1);            
                let resultQ2 = M(q2);           
    
                // Count the number of 'Ones' returned:
                if resultQ1 == One {
                    set numOnesQ1 += 1;
                }
                if resultQ2 == One {
                    set numOnesQ2 += 1;
                }
            }
    
            // reset the qubits
            SetQubitState(Zero, q1);             
            SetQubitState(Zero, q2);
    
    
            // Display the times that |0> is returned, and times that |1> is returned
            Message($"Q1 - Zeros: {count - numOnesQ1}");
            Message($"Q1 - Ones: {numOnesQ1}");
            Message($"Q2 - Zeros: {count - numOnesQ2}");
            Message($"Q2 - Ones: {numOnesQ2}");
            return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
    
        }
    }
    
  2. 在运行程序之前,需要将目标配置文件设置为“不受限制”。 选择视图 -> 命令面板,搜索 QIR,选择Q#:设置 Azure Quantum QIR 目标配置文件,然后选择Q#:不受限制

    注意

    如果目标配置文件未设置为 “不受限制”,则运行程序时会出现错误。

  3. 若要运行程序,请从右上角的播放图标下拉列表中选择“运行Q#文件”,从下面的@EntryPoint()命令列表中单击“运行,或按 Ctrl+F5。 程序运行在默认模拟器上用 @EntryPoint() 属性标记的操作或函数。

  4. 输出将显示在调试控制台中。

    Q1 - Zeros: 0
    Q1 - Ones: 1000
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

    由于尚未操作这些量子比特,因此它们保留了自己的初始值:第一个量子比特每次都返回 One,第二个量子比特返回 Zero

  5. 如果将值 initial 更改为 Zero 并再次运行程序,则应观察第一个量子比特每次也会返回 Zero

    Q1 - Zeros: 1000
    Q1 - Ones: 0
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

提示

回想一下,每次引入代码更改时保存文件,然后再再次运行它。

将量子比特置于叠加状态

目前,程序中的量子比特都处于经典状态,即,要么为 1,要么为 0。 之所以知道这一点,是因为该程序会将量子比特初始化为已知状态,并且你未添加任何过程来操作量子比特。 在纠缠量子比特之前,需要将第一个量子比特置于叠加状态,在此状态下,量子比特的测量会在 50% 的时间返回 Zero,在 50% 的时间返回 One。 从概念上讲,可将量子比特视为介于 ZeroOne 之间的一种中间状态。

Q# 提供了 H (Hadamard) 运算用于将量子比特置于叠加状态X回想一下之前从“初始化量子比特”到已知状态过程的操作,该操作将量子比特从Zero转为One(反之亦然H);该操作将量子位在一个相等概率ZeroOne的状态中翻转为等于概率的状态。 测量时,叠加的量子比特应返回大致相等数量的 ZeroOne 结果。

  1. 修改 TestBellState 运算中的代码以包含 H 运算:

        for test in 1..count {
            use (q1, q2) = (Qubit(), Qubit());   
            for test in 1..count {
                SetQubitState(initial, q1);
                SetQubitState(Zero, q2);
    
                H(q1);                // Add the H operation after initialization and before measurement
    
                // measure each qubit
                let resultQ1 = M(q1);            
                let resultQ2 = M(q2); 
                ...
    
  2. 现在,当你运行该程序时,可以看到第一个量子比特的叠加结果:

    Q1 - Zeros: 523            // results will vary
    Q1 - Ones: 477
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  3. 每次运行该程序,第一个量子比特的结果略有不同,但在大约 50% 的时间为 One,大约 50% 的时间为 Zero,而第二个量子比特的结果始终保持为 Zero

    Q1 - Zeros: 510           
    Q1 - Ones: 490
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  4. 将第一个量子比特初始化为 Zero 会返回类似的结果。

    Q1 - Zeros: 504           
    Q1 - Ones: 496
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    

纠缠两个量子比特

如前所述,纠缠的量子比特的连接方式使得它们不能相互独立地描述。 也就是说,无论一个量子比特发生了什么运算,纠缠的量子比特也会发生这种运算。 这样,只需测量一个量子比特的状态,就能知道另一个量子比特的最终状态,而无需测量它。 (此示例使用两个量子比特;但是,也可以纠缠三个或更多量子比特)。

Q# 提供了 CNOT(Controlled-NOT 的缩写)运算用于实现纠缠。 对两个量子比特运行此操作的结果是,在第一个量子比特是 One 的情况下翻转第二个量子比特。

  1. 在程序中紧接在 H 运算的后面添加 CNOT 运算。 完整程序应如下所示:

    namespace Bell {
        open Microsoft.Quantum.Intrinsic;
        open Microsoft.Quantum.Canon;
    
           operation SetQubitState(desired : Result, target : Qubit) : Unit {
               if desired != M(target) {
                   X(target);
               }
           }
    
        @EntryPoint()
        operation TestBellState() : (Int, Int, Int, Int) {
            mutable numOnesQ1 = 0;
            mutable numOnesQ2 = 0;
            let count = 1000;
            let initial = One;
    
            // allocate the qubits
            use (q1, q2) = (Qubit(), Qubit());   
            for test in 1..count {
                SetQubitState(initial, q1);
                SetQubitState(Zero, q2);
    
                H(q1);            
                CNOT(q1, q2);      // Add the CNOT operation after the H operation
    
                // measure each qubit
                let resultQ1 = M(q1);            
                let resultQ2 = M(q2);           
    
                // Count the number of 'Ones' returned:
                if resultQ1 == One {
                    set numOnesQ1 += 1;
                }
                if resultQ2 == One {
                    set numOnesQ2 += 1;
                }
            }
    
            // reset the qubits
            SetQubitState(Zero, q1);             
            SetQubitState(Zero, q2);
    
    
            // Display the times that |0> is returned, and times that |1> is returned
            Message($"Q1 - Zeros: {count - numOnesQ1}");
            Message($"Q1 - Ones: {numOnesQ1}");
            Message($"Q2 - Zeros: {count - numOnesQ2}");
            Message($"Q2 - Ones: {numOnesQ2}");
            return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
    
        }
    }
    
    
    Q1 - Zeros: 502           
    Q1 - Ones: 498       // results will vary
    Q2 - Zeros: 502
    Q2 - Ones: 498
    

第一个量子比特的统计信息没有变化(测量后返回 ZeroOne 的概率各为50%),但第二个量子比特的测量结果始终与第一个量子比特的测量结果相同CNOT 运算将这两个量子比特纠缠在一起,因此,不论其中一个发生什么情况,另一个也会同样发生。

绘制频率直方图

让我们直观显示从运行量子程序多次获取的结果分布。 频率直方图有助于可视化这些结果的概率分布。

  1. 选择 视图 -> 命令面板,或按 Ctrl+Shift+P,然后键入“直方图”,此时应显示 Q#:“运行文件并显示直方图 ”选项。 还可以从下面的@EntryPoint()命令列表中单击直方图。 选择此选项可打开 Q# 直方图窗口。

  2. 输入执行程序的大量 镜头 ,例如 100 次拍摄,然后按 Enter。 直方图将显示在 Q# 直方图窗口中。

  3. 直方图中的每个条形图对应于可能的结果,其高度表示观察到结果的次数。 在这种情况下,有 50 个不同的唯一结果。 请注意,对于每个结果,第一个和第二个量子比特的度量结果始终相同。

    Q# Visual Studio Code 中的直方图窗口的屏幕截图。

    提示

    可以使用鼠标滚轮或触控板手势缩放直方图。 放大时,可以在滚动时按“Alt”平移图表。

  4. 单击一个栏可显示 该结果的百分比

  5. 单击左上角 的设置图标 以显示选项。 可以显示前 10 个结果、前 25 个结果或所有结果。 还可以将结果从高到低或从低到高对结果进行排序。

    Q#显示如何显示设置的 Visual Studio Code 中的直方图窗口的屏幕截图。

浏览其他 Q# 教程: