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

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

本教程演示如何编写 Q# 程序来操作和测量量子比特并演示叠加和纠缠效果。 准备处于特定量子状态的两个量子比特,了解如何使用 对量子比特 Q# 进行操作以更改其状态,并演示叠加和纠缠的影响。 逐一生成 Q# 程序来引入量子比特状态、操作和度量。

注意

Microsoft Quantum 开发工具包 (经典 QDK) 在 2024 年 6 月 30 日之后将不再受支持。 如果你是现有的 QDK 开发人员,建议过渡到新的 Azure Quantum 开发工具包 (新式 QDK) ,以继续开发量子解决方案。 有关详细信息,请参阅 将 Q# 代码迁移到新式 QDK

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

  • 经典位保存单个二进制值(如 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只能具有 或 One的值Zero

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

   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),表示量子比特在 (或 One) Zero 中所需的状态,以及一个类型 Qubit
  2. 执行测量运算 M,以测量量子比特的状态(ZeroOne),并将结果与 desired 中指定的值进行比较。
  3. 如果测量结果与比较值不匹配,则运行 X 运算,以将量子比特的状态翻转为返回 ZeroOne 的测量的概率反转位置。 这样,SetQubitState 会始终将目标量子比特置于所需状态下。

编写测试操作以测试贝尔状态

接下来,为了演示 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 Notebook 中运行 Q# 程序或从 Python 主机文件调用 Q# 程序时,这不是必需的,如果包含,则会引发错误。

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

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

如果将 的值initialZero更改为 并再次运行程序,则应注意到第一个量子比特也每次都会返回Zero

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

将量子比特置于叠加状态

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

Q# 提供了 H (Hadamard) 运算用于将量子比特置于叠加状态。 X回顾前面从将量子比特初始化为已知状态的过程的操作,该过程将量子比特从 0 翻转为 1 (反之亦然) ;H该操作将量子比特半转为等于 或 One的概率Zero状态。 测量时,叠加的量子比特应返回大致相等数量的 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

注意

通过移动适用于 Azure Quantum 的 Copilot 中的滑块并增加拍摄次数,可以看到叠加结果在拍摄分布中如何略有不同。

纠缠两个量子比特

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

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 的概率 Zero ,但第二个 One 量子比特的度量结果 始终 与第一个量子比特的测量相同,无论运行程序多少次。 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),表示量子比特在 (或 One) Zero 中所需的状态,以及一个类型 Qubit
  2. 执行测量运算 M,以测量量子比特的状态(ZeroOne),并将结果与 desired 中指定的值进行比较。
  3. 如果测量结果与比较值不匹配,则运行 X 运算,以将量子比特的状态翻转为返回 ZeroOne 的测量的概率反转位置。 这样,SetQubitState 会始终将目标量子比特置于所需状态下。

编写测试操作以测试贝尔状态

接下来,为了演示 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 Notebook 中运行 Q# 程序或从 Python 主机文件调用 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);
           }
       }

    @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 );

    }
}

在运行程序之前,需要将目标配置文件设置为 “无限制”。 选择“ 视图 -> 命令面板”,搜索“QIR”,选择“ Q#设置 Azure Quantum QIR 目标配置文件”,然后选择“ Q#不受限制”。

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

注意

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

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

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

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

如果将 的值initialZero更改为 并再次运行程序,则应注意到第一个量子比特也每次都会返回Zero

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

提示

在再次运行之前,每次对代码引入更改时,请重新调用 以保存文件。

将量子比特置于叠加状态

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

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

修改 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); 
            ...

现在,当你运行该程序时,可以看到第一个量子比特的叠加结果:

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

纠缠两个量子比特

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

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 = 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#“运行文件并显示直方图 ”选项。 选择此选项可打开 Q# 直方图窗口。

  2. 输入执行程序(例如 100 个 镜头 )的镜头数,然后按 Enter。 直方图将显示在 Q# 直方图窗口中。

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

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

    提示

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

  4. 单击条形图可显示该结果的 百分比

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

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

后续步骤

浏览其他 Q# 教程: