量子计算机编程:从入门到实践
上QQ阅读APP看书,第一时间看更新

第 1 章 入门

不管你是软件工程、计算机图形学、数据科学等方面的专家,还是充满好奇心的计算机爱好者,我们都希望你能通过本书开始使用量子计算机,并了解如何发挥量子计算的潜力。

为了实现上述目标,本书不会详细解释量子物理(量子计算的底层定律)和量子信息理论(这些定律如何决定我们处理信息的能力),而会提供示例代码,帮助你深入理解量子计算这一令人兴奋的新技术及其用途。最重要的是,你可以调整和修改本书提供的示例代码。这样做可以让你以最有效的方式学习:亲自动手实践。在这个过程中,我们会在必要时解释核心概念,但只会点到为止,目的是帮助你编写量子计算程序,而不是精通量子力学。

我们有一个微不足道的愿望:感兴趣的读者或许能够运用这些知识,在连物理学家可能都没有听说过的领域应用和拓展量子计算技术。诚然,希望帮助引发量子革命,这个愿望绝对不算微不足道,但是成为先驱者无疑令人兴奋。

1.1 所需背景

理解量子计算背后的物理学需要大量的数学知识,晶体管背后的物理学也是如此,但学习 C++ 连一个物理方程都不需要涉及。本书采取所谓的以程序员为中心的方法,避开任何艰深的数学知识。下面简要列出有助于理解书中概念的知识点。

● 熟悉程序控制结构,例如 if、while 等。本书使用 JavaScript 提供对可以在线运行的示例的轻量级访问。如果你对 JavaScript 还不熟悉,但是有一些编程经验,那么或许能在一小时之内就掌握阅读本书所需的知识。有关 JavaScript 的全面介绍,请参见 Ethan Brown 的《JavaScript 学习指南(第 3 版)》。

● 掌握程序员应该了解的一些相关的数学知识,它们是必需的:

● 理解数学函数的用法;

● 熟悉三角函数;

● 熟练地操作二进制数以及在二进制表示和十进制表示之间相互转换;

● 理解复数的基本含义。

● 对如何评估算法的计算复杂度(大 O 记法)有最基本的理解。

书中超出上述要求的部分是第 13 章,其中将研究量子计算在机器学习中的一些应用。篇幅所限,那一章仅概述每种机器学习应用,并展示量子计算机在其中有何优势。尽管我们试图使内容通俗易懂,但是如果读者具备一些机器学习背景,在付诸实践时将有更大的收获。

本书的侧重点是量子计算机编程(不是构建或研究量子计算机),这就是你在阅读本书时不需要了解高等数学和量子理论的原因。不过,对于有兴趣进一步探索这个主题的读者来说,第 14 章提供了很好的参考,并将书中介绍的概念与量子计算研究界常用的数学符号联系起来。

1.2 何谓QPU

尽管人们经常谈及“量子计算机”,但这个词具有误导性。它让人联想到一种全新的计算机,并且这种计算机使用极具未来感的某种东西替代现有的一切软件。

在我们编写本书时,这是对量子计算机的一个很大却很常见的误解。量子计算机的前景并不在于它是“传统计算机杀手”,而在于它能够极大地扩展计算机处理的问题种类。一些重要的计算问题很容易在量子计算机上进行运算,而这在任何标准计算设备上都是做不到的 1

1关于这一点,我们常常举这样一个例子:假设可以将传统的晶体管缩小为原子大小,即便要在质因数分解能力上与普通的量子计算机相当,传统计算机的体积也得有仓库那么大。此外,这台传统计算机中的晶体管将组装得如此密集,以至于产生一个引力奇点。引力奇点使得计算非常困难,更别说这样的传统计算机能否真的存在。

重要的是,这种提升效果只适用于某些问题(后文会具体阐明)。尽管我们预计这样的问题会越来越多,但试图利用量子计算机解决所有的计算问题是没有意义的。对于笔记本计算机能够执行的大部分任务,量子计算机未必表现得更好。

换句话说,从程序员的角度来看,量子计算机实际上是协处理器。过去,计算机使用了各种各样的协处理器,每一种都各有所长,如进行浮点运算、信号处理和实时的图形渲染。基于这个思路,本书使用量子处理单元(quantum processing unit,QPU)来指代运行书中示例代码的设备。我们认为,这个术语强化了量子计算的定位。

图形处理单元(graphics processing unit,GPU)等其他协处理器一样,对 QPU 的编程需要程序员编写代码,这些代码主要在普通计算机的中央处理器(central processing unit,CPU)上运行。CPU 向 QPU 协处理器发送指令,只为启动与其处理能力相匹配的任务。

1.3 动手实践

本书的核心是能够动手实践的示例代码。但是在编写本书时,还不存在成熟通用的 QPU,那么该如何运行本书中的代码呢?幸运的是,在编写本书时,已经有了一些可通过云端访问和使用的原型 QPU,这令人兴奋。此外,对于较小的问题,可以在传统计算机上模拟 QPU 的表现。尽管无法模拟大型 QPU 程序,但对于简短的代码片段来说,这是一种学习如何控制实际 QPU 的简便方法。本书中的示例代码符合上述要求,并且即便以后出现更复杂的 QPU,这些代码也将保持可用性和教学性。

目前有许多可用的 QPU 模拟器、库和系统。你可以在 http://oreilly-qc.github.io 上找到一份列表,其中列出了几个具有良好支持的系统。在该网页上,我们以多种编程语言提供了本书的示例代码。不过,为了避免书中出现过多的代码,我们仅在本书中列举用于 QCEngine 的 JavaScript 示例。QCEngine 是免费的在线量子计算模拟器,利用它,用户可以在浏览器中运行示例代码,无须额外安装任何软件。QCEngine 由本书作者开发,初衷是自用,现在作为本书的配套工具使用。QCEngine 对我们特别有用,这不仅因为它无须下载任何软件即可运行,还因为它集成了我们在整本书中用作可视化工具的圆形表示法

QCEngine入门

由于我们将大量使用 QCEngine,因此值得花点时间来了解这个模拟器的用法。你可以在 http://oreilly-qc.github.io 上找到它。

运行代码

如图 1-1 所示,利用 QCEngine 的 Web 界面,能够轻松地实现所需的各种可视化效果。只需在 QCEngine 的代码编辑器中输入代码,即可生成图像。

图 1-1:QCEngine 的 Web 界面

要运行本书中的示例代码,请从代码编辑器顶部的下拉列表中选择它,然后单击“运行程序”(Run Program)按钮。在屏幕上将出现一些新的交互式界面元素,用于将代码的运行结果可视化,如图 1-2 所示。

图 1-2:用于可视化 QPU 结果的 QCEngine 界面元素

量子电路可视化工具

该界面元素用可视化方式表示代码所代表的量子电路。第 2 章和第 3 章会介绍量子电路所用的表示符号。可以通过它交互式地单步执行程序。

圆形表示法可视化工具

该界面元素以圆形表示法将 QPU(或模拟器)寄存器可视化。第 2 章会解释如何理解和使用圆形表示法。

输出控制台

输出控制台用于显示通过命令 qc.print() 打印的任何文本(用于调试)。使用标准的 JavaScript 函数 console.log() 打印的任何内容仍将在 Web 浏览器的 JavaScript 控制台上输出。
 

调试代码

调试 QPU 程序有一定的难度。要理解程序背后的逻辑,最简单的方法通常是慢慢地单步执行,同时查看每个步骤的可视化效果。将鼠标悬停在量子电路可视化工具上,应该会看到一条橙色竖线出现在固定位置,此时若移动鼠标,还会看到一条灰色竖线跟随鼠标移动。橙色竖线表示圆形表示法可视化工具当前显示的信息在量子电路及程序中的位置。它默认在程序的结束位置,但是通过单击量子电路的其他部分,可以让圆形表示法可视化工具显示程序中单击处的 QPU 配置情况。来看一个例子,图 1-3 显示了当在默认 QCEngine 程序的两个步骤之间切换时,圆形表示法可视化工具的变化情况。

图 1-3:使用量子电路可视化工具和圆形表示法可视化工具单步执行 QCEngine 程序

用过 QPU 模拟器后,你可能会忍不住开始摆弄它。请尽管尝试!在第 2 章中,我们会看到越来越复杂的 QPU 程序。

1.4 原生QPU指令

可以用多种工具运行和检查 QPU 代码,QCEngine 就是其中之一。可是,QPU 代码究竟是什么样子的呢?通常使用传统的高级语言来控制低级 QPU 指令(我们已经在基于 JavaScript 的 QCEngine 中看到过例子)。本书将带你在高级语言和低级指令间穿梭。一方面,学习真正的量子计算机级的 QPU 编程有助于掌握全新的 QPU 基本逻辑;另一方面,了解如何通过 JavaScript、Python、C++ 等更高级的传统编程语言执行这些操作,有助于掌握更务实的编码范式。对专用、新的量子编程语言的定义仍在火热进行中。本书不会过多地阐述这个话题,若对此感兴趣,请参阅第 14 章。

为了满足你的好奇心,表 1-1 列出了一些基本的 QPU 指令。后文将详细地解释其中每一条指令。

表1-1:基本的QPU指令集

具体的指令和时序取决于 QPU 的品牌和架构。不过,表 1-1 中的是一组基本指令,应该在所有 QPU 中都可用。这些指令构成了 QPU 编程的基础,就像 MOV 和 ADD 这样的指令之于 CPU 程序员一样。

1.4.1 模拟器的上限

尽管模拟器在运行小型 QPU 程序时非常方便,但与真正的 QPU 相比,它们的性能仍然不够强大。衡量 QPU 性能的一个指标是在其上可操作的量子比特(qubit)的数量 2。量子比特就是量子位,稍后会详细说明。

2尽管媒体很喜欢将硬件可以处理的量子比特数作为衡量量子计算机性能的基准,但这样做过于简单化。要想评估 QPU 的真正能力,还需考虑更微妙的因素。

截至本书原版出版之时,测试得出的 QPU 模拟器的世界记录是 51 个量子比特。在实践中,公众可以使用的模拟器和硬件通常能够在停止运行之前处理约 26 个量子比特。

本书中的示例考虑到了上述限制。对量子计算初学者来说,这些示例是很好的着手点。每向示例中添加一个量子比特,都会使运行模拟器所需的内存加倍,速度减半。

1.4.2 硬件的上限

在本书写作之时,实际可用的最大 QPU 硬件大约有 70 个物理量子比特(physical qubit),而通过 Qiskit 开源软件开发工具包向公众提供的最大 QPU 包含 16 个物理量子比特 3。与逻辑量子比特(logical qubit)不同的是,这 70 个物理量子比特没有纠错能力,易受干扰,且不稳定。与传统比特相比,量子比特要脆弱得多,与周围环境发生轻微的相互作用,就会令计算出错。

3当本书出版时,这个数字可能会过时!

在使用逻辑量子比特时,程序员无须了解 QPU 硬件即可实现任何教科书介绍的算法,并且不必担心特定的硬件限制。本书专注于用逻辑量子比特编程,书中的示例代码都可以在较小的 QPU 中(比如本书出版时可用的 QPU)运行。忽略物理硬件细节意味着,即使未来硬件进一步发展,你掌握的技能和拥有的经验也仍然极具价值。

1.5 QPU与GPU的共同点

尽管在 Stack Exchange 网站上已经有了关于 QPU 编程的讨论区,但在一种全新的处理器上编程的想法仍会令人望而却步。下面是一些关于 QPU 编程的事实。

● 一个程序完全在 QPU 中运行的情况十分罕见。通常是由在 CPU 上运行的程序发出 QPU 指令,然后获取结果。

● 有些任务非常适合在 QPU 中执行,有些任务则不适合。

● QPU 时钟与 CPU 时钟不同,QPU 往往通过专用的硬件接口连接到外部设备(如光学输出设备)。

● 典型的 QPU 有专用的随机存储器,CPU 不能高效地访问它。

● 简单的 QPU 可以是由笔记本计算机访问的一块芯片,甚至可以只是芯片上的一块区域。更先进的 QPU 可以是昂贵的大型附加设备,并一直需要特殊的冷却措施。

● 即便是简单的类型,早期的 QPU 也有冰箱大小,需要特殊的大电流电源插座。

● 当计算完成时,QPU 向 CPU 返回计算结果的投影,并舍弃大部分内部工作数据。

● QPU 调试可能非常棘手,需要特殊的工具和技术。单步执行一个程序可能很困难,通常最好的方法是更改程序,并观察更改对输出的影响。

● 对一条 QPU 指令的执行速度进行优化可能会拖慢另一条 QPU 指令的执行速度。

虽然听上去似乎不太可能,但这是一个事实:对于上述每一项,都可以用 GPU 替换 QPU,并且表述仍然成立。

可以说,QPU 是具有超能力且与众不同的技术。尽管如此,QPU 编程面临的问题并不新鲜,软件工程师前辈早已遇到过。的确,QPU 编程与传统编程存在一些细微的差别,这些差别是非常新颖的(否则本书就没有存在的必要!),但二者有很多共同点。相信自己,你一定能掌握 QPU 编程!