Q_02_02 Writing a Quantum Program

你会学到什么

  • 如何在Visual Studio中设置量子解决方案和项目
  • Q#操作的组件
  • 如何从C#调用Q#操作
  • 如何构建和执行您的量子算法

在Q#中创建一个钟状态

现在您已经安装了Microsoft Quantum Development Kit,并了解了它的工作原理,我们来编写您的第一个量子应用程序。 我们将从最简单的程序开始,并将其构建起来以展示量子叠加和量子纠缠。 我们将从基础状态 

中开始一个量子位,对其执行一些操作,然后测量结果。

该页面上的说明是为Visual Studio 2017和Visual Studio代码编写的。 如果您使用的是其他开发环境,请按照Visual Studio代码的说明使用命令行调用.NET Core SDK。

第1步:创建一个项目和解决方案

  • Visual Studio 2017
  • 命令行/ Visual Studio代码

打开Visual Studio 2017.转到File菜单并选择New > Project... 在项目模板资源管理Installed > Visual C# ,选择Q# Application模板。 确保您在New Project对话框顶部的列表中选择了.NET Framework 4.6.1 给你的项目命名Bell

第2步:输入Q#代码

我们的目标是创建一个显示纠缠的贝尔状态 。 我们将逐个建立起来,以展示量子比特状态,门限和测量的概念。

您的开发环境应该打开两个文件: Driver.cs ,它将保存您的量子代码的C#驱动程序,以及Operation.qs ,它将保存量子代码本身。

第一步是将Q#文件重命名为Bell.qs 右键单击Visual Studio解决方案资源管理器中的Operation.qs (Ctrl + Alt + L进行聚焦)或Visual Studio代码资源管理器(Ctrl /⌘+ Shift + E进行聚焦),然后选择重命名选项。 Bell替换Operation并返回。

要输入Q#代码,请确保您正在编辑Bell.qs窗口。 Bell.qs文件应该包含以下内容:

Q#

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

    operation Operation () : ()
    {
        body
        {

        }
    }
}

首先,将字符串Operation替换为Set ,并更改操作参数(第一对括号)以包含desired: Result, q1: Qubit的字符串desired: Result, q1: Qubit 该文件现在应该如下所示:

Q#

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

    operation Set (desired: Result, q1: Qubit) : ()
    {
        body
        {

        }
    }
}

现在,在包围操作体的大括号之间键入以下内容:

Q#

            let current = M(q1);

            if (desired != current)
            {
                X(q1);
            }

该文件现在应该如下所示:

Q#

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

    operation Set (desired: Result, q1: Qubit) : ()
    {
        body
        {
            let current = M(q1);
            if (desired != current)
            {
                X(q1);
            }
        }
    }
}

现在可以调用这个操作来设置一个已知状态的量子位( ZeroOne )。 我们测量量子位,如果它处于我们想要的状态,我们将它放在一边,否则,我们用X门翻转它。


这段代码定义了一个Q# 操作 操作是Q#中量子执行的基本单位。 它大致相当于C或C ++或Python中的函数,或者C#或Java中的静态方法。

操作的参数在括号内被指定为一个元组。 操作的返回类型是在冒号后指定的。 在这种情况下, Set操作没有返回,所以它被标记为返回一个空元组() 这是F#中Q# unit等价物,大致类似于C#中的void

操作具有主体部分,其中包含操作的实现。 一个操作也可以有伴随的受控的受控的伴随节。 这些用于指定适当操作的特定变体。 有关更多信息,请参阅Q#语言参考 。

Set操作结束后,将以下操作添加到名称空间中:

Q#

operation BellTest (count : Int, initial: Result) : (Int,Int)
    {
        body
        {
            mutable numOnes = 0;
            using (qubits = Qubit[1])
            {
                for (test in 1..count)
                {
                    Set (initial, qubits[0]);

                    let res = M (qubits[0]);

                    // Count the number of ones we saw:
                    if (res == One)
                    {
                        set numOnes = numOnes + 1;
                    }
                }
                Set(Zero, qubits[0]);
            }
            // Return number of times we saw a |0> and number of times we saw a |1>
            return (count-numOnes, numOnes);
        }
    }

此操作( BellTest )将循环进行count迭代,在量子位上设置指定的initial值,并测量( M )结果。 它会收集统计我们已经测量了多少零和一些零并将它们返回给调用者。 它执行另一个必要的操作。 它在返回它之前将量子位重置为已知状态( Zero ),以允许其他人以已知状态分配该量子位。 这是using语句所要求的。

所有这些调用都使用Microsoft.Quantum.Primitive命名空间中定义的原始量子操作。 例如, M操作在计算( Z )基础上测量其变元量子位,并且X将围绕x轴的状态翻转应用到其变元量子位。

正如你所看到的,Q#使用类似C#的分号和大括号来表示程序结构。

Q#有一个非常类似于C#的if语句。

Q#以独特的方式处理变量。 默认情况下,Q#中的变量是不可变的; 他们的价值在绑定后可能不会改变。 let关键字用于指示不可变变量的绑定。 操作参数总是不变的。

如果你需要一个变量值可以改变的变量,例如这个例子中的numOnes ,你可以用mutable关键字声明变量。 可变变量的值可以使用set语句进行更改。

在这两种情况下,编译器都会推断变量的类型。 Q#不需要变量的任何类型注释。

using语句对Q#也是特殊的。 它用于分配一个用于代码块的量子比特数组。 在Q#中,所有量子位都是动态分配和释放的,而不是在复杂算法的整个生命周期中存在的固定资源。 using语句在开始时分配一组量子位,并在块的末尾释放这些量子位。 有一个类似的borrowing说明用于分配潜在的肮脏的附属量子比特。

Q#中的for循环总是迭代一个范围。 没有Q#相当于一个传统的C型电脑声明。 范围可以由范围中的第一个和最后一个整数指定,如下例所示: 1..10是范围1,2,3,4,5,6,7,8,9和10.如果a需要使用除+1以外的步骤,然后使用三个整数,它们之间有.. 1..2..10是范围1,3,5,7和9.请注意,范围在两端都包含在内。

BellTest操作以元组的BellTest返回两个值。 该操作的返回类型是(Int, Int) ,并且return语句具有包含两个整数变量的显式元组。 Q#使用元组来传递多个值,而不是使用结构或记录。

第3步:输入C#驱动程序代码

切换到开发环境中的Driver.cs文件。 这个文件应该有以下内容:

C#

using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;

namespace Quantum.Bell
{
    class Driver
    {
        static void Main(string[] args)
        {

        }
    }
}

Main方法中,输入以下代码:

C#
 
            using (var sim = new QuantumSimulator())
            {
                // Try initial values
                Result[] initials = new Result[] { Result.Zero, Result.One };
                foreach (Result initial in initials)
                {
                    var res = BellTest.Run(sim, 1000, initial).Result;
                    var (numZeros, numOnes) = res;
                    System.Console.WriteLine(
                        $"Init:{initial,-4} 0s={numZeros,-4} 1s={numOnes,-4}");
                }
            }
            System.Console.WriteLine("Press any key to continue...");
            System.Console.ReadKey();

C#驱动程序有四个部分:

  • 构建量子模拟器。 在这个例子中, sim是模拟器。
  • 计算量子算法所需的任何参数。 在这个例子中, count固定为1000, initial是量子比特的初始值。
  • 运行量子算法。 每个Q#操作都会生成一个具有相同名称的C#类。 这个类有一个Run方法, 异步执行该操作。 执行是异步的,因为在实际硬件上的执行将是异步的。

    由于Run方法是异步的,因此我们获取Result属性; 这会阻止执行,直到任务完成并同步返回结果。

  • 处理操作的结果。 在这个例子中, res会收到操作的结果。 这里的结果是由模拟器测量的零个数( numZeros )和个数( numZeros )的元组。 这是在C#中作为ValueTuple返回的。 我们解构元组以获得两个字段,打印结果,然后等待按键。

第4步:构建并运行

  • Visual Studio 2017
  • 命令行/ Visual Studio代码

只需点击F5 ,你的程序就会建立并运行!

结果应该是:

Output
 Init:Zero 0s=1000 1s=0
Init:One  0s=0    1s=1000
Press any key to continue... 

按下键后程序将退出。

第5步:创建叠加

现在我们想操纵这个量子位。 首先,我们将尝试翻转它。 这是通过在我们测试BellTest之前执行一个X门完成的:

Q#
 
    X(qubits[0]);
    let res = M (qubits[0]);

现在结果(在按下F5 )相反:

Output
 Init:Zero 0s=0    1s=1000
Init:One  0s=1000 1s=0 

但是,迄今为止我们所看到的一切都是古典的。 让我们得到一个量子结果。 我们所需要做的就是用H或Hadamard门替换上一次运行中的X门。 我们不会一直将量子比特从0改为1,而只是将其翻转一半。 BellTest的替换行如下所示:

Q#
 
    H(qubits[0]);
    let res = M (qubits[0]);

现在结果变得更有趣了:

Output
 Init:Zero 0s=484  1s=516
Init:One  0s=522  1s=478 

每次我们测量时,我们都要求一个经典值,但量子位在0和1之间,所以我们得到(统计上)0时间的一半和时间的一半。 这被称为叠加 ,给我们第一个真正的量子态。

第6步:创建纠缠

现在我们将做出承诺的贝尔州并炫耀纠缠 我们需要做的第一件事是在BellTest分配2个量子位而不是1个量子位:

Q#
  using (qubits = Qubit[2]) { 

在我们测量BellTestM )之前,这将允许我们添加一个新的门( CNOT ):

Q#
 
                    Set (initial, qubits[0]);
                    Set (Zero, qubits[1]);

                    H(qubits[0]);
                    CNOT(qubits[0],qubits[1]);
                    let res = M (qubits[0]);

我们添加了另一个Set操作来初始化量子位1,以确保它在我们启动时始终处于Zero状态。

我们还需要在释放它之前重置第二个量子位(这也可以用for循环完成)。 我们将在量子位0重置后添加一行:

Q#
 
            Set(Zero, qubits[0]);
            Set(Zero, qubits[1]);

完整的例程现在看起来像这样:

Q#
 
    operation BellTest (count : Int, initial: Result) : (Int,Int)
    {
        body
        {
            mutable numOnes = 0;
            using (qubits = Qubit[2])
            {
                for (test in 1..count)
                {
                    Set (initial, qubits[0]);
                    Set (Zero, qubits[1]);

                    H(qubits[0]);
                    CNOT(qubits[0],qubits[1]);
                    let res = M (qubits[0]);

                    // Count the number of ones we saw:
                    if (res == One)
                    {
                        set numOnes = numOnes + 1;
                    }
                }

                Set(Zero, qubits[0]);
                Set(Zero, qubits[1]);
            }
            // Return number of times we saw a |0> and number of times we saw a |1>
            return (count-numOnes, numOnes);
        }
    }

如果我们运行这个,我们会得到与之前一样的50-50结果。 然而,我们真正感兴趣的是第二个量子位对第一个量子态的反应。 我们将在BellTest操作的新版本中添加此统计信息:

Q#
 
operation BellTest (count : Int, initial: Result) : (Int,Int,Int)
    {
        body
        {
            mutable numOnes = 0;
            mutable agree = 0;
            using (qubits = Qubit[2])
            {
                for (test in 1..count)
                {
                    Set (initial, qubits[0]);
                    Set (Zero, qubits[1]);

                    H(qubits[0]);
                    CNOT(qubits[0],qubits[1]);
                    let res = M (qubits[0]);

                    if (M (qubits[1]) == res) 
                    {
                        set agree = agree + 1;
                    }

                    // Count the number of ones we saw:
                    if (res == One)
                    {
                        set numOnes = numOnes + 1;
                    }
                }

                Set(Zero, qubits[0]);
                Set(Zero, qubits[1]);
            }
            // Return number of times we saw a |0> and number of times we saw a |1>
            return (count-numOnes, numOnes, agree);
        }
    }

现在有一个新的返回值( agree ),它将记录每次来自第一个量子位的测量与第二个量子位的测量相匹配。 当然,我们也必须相应地更新Driver.cs文件:

C#
 
            using (var sim = new QuantumSimulator())
            {
                // Try initial values
                Result[] initials = new Result[] { Result.Zero, Result.One };
                foreach (Result initial in initials)
                {
                    var res = BellTest.Run(sim, 1000, initial).Result;
                    var (numZeros, numOnes, agree) = res;
                    System.Console.WriteLine(
                        $"Init:{initial,-4} 0s={numZeros,-4} 1s={numOnes,-4} agree={agree,-4}");
                }
            }
            System.Console.WriteLine("Press any key to continue...");
            System.Console.ReadKey();

现在当我们跑步时,我们得到了一些非常惊人

Output
 Init:Zero 0s=499  1s=501  agree=1000
Init:One  0s=490  1s=510  agree=1000 

我们对第一个量子位的统计没有改变(一个0或1的概率为50-50),但现在当我们测量第二个量子位时,它总是和第一个量子位相同。 我们的CNOT使这两个量子纠缠在一起,所以无论发生在其中一个发生什么,发生在另一个发生。 如果你颠倒了测量(在第一个之前做了第二个量子比特),同样的事情会发生。 第一次测量是随机的,第二次测量将与第一次测量的结果保持一致。



内容概要:《2024年中国城市低空经济发展指数报告》由36氪研究院发布,指出低空经济作为新质生产力的代表,已成为中国经济新的增长点。报告从发展环境、资金投入、创新能力、基础支撑和发展成效五个维度构建了综合指数评价体系,评估了全国重点城市的低空经济发展状况。北京和深圳在总指数中名列前茅,分别以91.26和84.53的得分领先,展现出强大的资金投入、创新能力和基础支撑。低空经济主要涉及无人机、eVTOL(电动垂直起降飞行器)和直升机等产品,广泛应用于农业、物流、交通、应急救援等领域。政策支持、市场需求和技术进步共同推动了低空经济的快速发展,预计到2026年市场规模将突破万亿元。 适用人群:对低空经济发展感兴趣的政策制定者、投资者、企业和研究人员。 使用场景及目标:①了解低空经济的定义、分类和发展驱动力;②掌握低空经济的主要应用场景和市场规模预测;③评估各城市在低空经济发展中的表现和潜力;④为政策制定、投资决策和企业发展提供参考依据。 其他说明:报告强调了政策监管、产业生态建设和区域融合错位的重要性,提出了加强法律法规建设、人才储备和基础设施建设等建议。低空经济正加速向网络化、智能化、规模化和集聚化方向发展,各地应找准自身比较优势,实现差异化发展。
数据集一个高质量的医学图像数据集,专门用于脑肿瘤的检测和分类研究以下是关于这个数据集的详细介绍:该数据集包含5249张脑部MRI图像,分为训练集和验证集。每张图像都标注了边界框(Bounding Boxes),并按照脑肿瘤的类型分为四个类别:胶质瘤(Glioma)、脑膜瘤(Meningioma)、无肿瘤(No Tumor)和垂体瘤(Pituitary)。这些图像涵盖了不同的MRI扫描角度,包括矢状面、轴面和冠状面,能够全面覆盖脑部解剖结构,为模型训练提供了丰富多样的数据基础。高质量标注:边界框是通过LabelImg工具手动标注的,标注过程严谨,确保了标注的准确性和可靠性。多角度覆盖:图像从不同的MRI扫描角度拍摄,包括矢状面、轴面和冠状面,能够全面覆盖脑部解剖结构。数据清洗与筛选:数据集在创建过程中经过了彻底的清洗,去除了噪声、错误标注和质量不佳的图像,保证了数据的高质量。该数据集非常适合用于训练和验证深度学习模型,以实现脑肿瘤的检测和分类。它为开发医学图像处理中的计算机视觉应用提供了坚实的基础,能够帮助研究人员和开发人员构建更准确、更可靠的脑肿瘤诊断系统。这个数据集为脑肿瘤检测和分类的研究提供了宝贵的资源,能够帮助研究人员开发出更准确、更高效的诊断工具,从而为脑肿瘤患者的早期诊断和治疗规划提供支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值