量子计算入门 - 第三部分:量子电路和OpenQASM





5.00/5 (2投票s)
介绍量子电路以及用于描述量子电路的开源语言OpenQASM。
第二部分:量子门 | 第四部分:IBM量子体验 |
目录
引言
在前两篇文章中,我们介绍了量子计算以及量子门如何作用于量子比特。然而,这本身不足以执行量子计算。我们需要一种方法将量子门组合起来以执行特定功能(即计算)。这就是量子电路的目的。
最基本地说,量子电路是描述量子门应用于一个或多个量子比特的顺序,以执行特定功能。例如,如果您想在翻转第一个量子比特后对第二个量子比特应用CNOT门,电路需要显示在第一个量子比特上应用Pauli-X门,然后对第二个量子比特应用CNOT门。反向执行这些操作将产生完全不同的结果。
为了辅助设计量子电路,已经开发了一种简单的编程语言来描述量子电路——OpenQASM(Open Quantum ASseMbly)。该语言可用于描述任何量子门,以及指定哪些量子比特被哪些门以及以何种顺序作用。在概述量子电路之后,我们将深入探讨OpenQASM语言以及如何在其上编写程序。
量子电路
作者:Stefan Birkner (squizzz) - 此图像使用gedit(文本编辑器)创建。, CC BY-SA 3.0, 链接
上面是一个包含三个量子比特和几个门的基本量子电路。虽然电路图可能因绘制方式而异,但大多数(如果不是全部)都包含以下关键元素
- 量子比特:电路中的每条水平线代表一个特定的量子比特。水平绘制时,时间从左到右流动;垂直绘制时,时间从上到下流动(除非另有说明)。
- 标识符/起始状态:每个量子比特线(或垂直绘制时的顶部)的左侧通常有一个标识符。例如,\(q_1\)、\(q_2\)、\(q_3\)等代表量子比特1、2、3等。除非另有说明,所有量子比特都假定起始于\(|0\rangle\)状态。有时,代替q,会使用c。在这种情况下,c指的是经典比特而不是量子比特。另外,代替标识符,也可以列出起始状态。在上图中,第一个量子比特起始于\(|x_0\rangle\)状态,第二个量子比特处于\(|x_1\rangle\)状态,依此类推。
- 标识符/结束状态:您会注意到图表中每条线右侧的状态与左侧列出的状态不同。在这种情况下,\(|y_0\rangle\)、\(|y_1\rangle\)和\(|y_2\rangle\)代表电路运行结束后每个量子比特的状态。
- 门:没有门,量子电路什么也做不了。每个方框代表一个门,里面的文本描述了门的类型(例如,H是Hadamard门)。当一个门连接到另一个量子比特时,它是一个受控门,例如CNOT门,其中方框所在的量子比特是受操作的量子比特,连接线指向控制量子比特。
这基本上就是量子电路的全部内容。遵循时间流(从左到右或从上到下),并根据作用于量子比特的门修改每个量子比特的状态。如果两条单独量子比特线上的两个门垂直对齐(或在图本身垂直时水平对齐),则表示这两个门同时修改每个量子比特。
OpenQASM
虽然量子电路图在视觉上很好地展示了量子电路的运行方式,但在编程量子电路方面却不太有用,并且在模拟量子电路方面效率不高。这时OpenQASM就派上用场了。它是一种相对简单的编程语言,可以在经典计算机上编写,用于生成量子电路图,用于编程量子电路(如我们在第四部分将看到的),甚至可以用作解释性语言在经典计算机上模拟量子电路。
下面是OpenQASM程序的语法。您也可以在OpenQASM规范的附录A中找到该语法的副本。如果您一开始不理解,不用担心。我们将逐一介绍OpenQASM的主要部分,并描述如何编写程序。请注意,在语法描述中,粗体文本(例如\(\mathbf{OPENQASM}\))、标点符号(例如逗号、分号、方括号等)以及通常未包含在尖括号(即\(\langle\rangle\))内的任何内容都是字符串字面量,将在OpenQASM程序中按原样输入。一旦我们开始编写演示OpenQASM程序,这一点就会变得更加清楚。
OpenQASM语法
\(\langle\)mainprogram\(\rangle\) | \(\vDash\) | \(\mathbf{OPENQASM}\langle\)real\(\rangle\mathbf{;}\langle\)program\(\rangle\) |
\(\langle\)program\(\rangle\) | \(\vDash\) | \(\langle\)statement\(\rangle\vert\langle\)program\(\rangle\langle\)statement\(\rangle\) |
\(\langle\)statement\(\rangle\) | \(\vDash\) | \(\langle\)decl\(\rangle\) |
\(\vert\langle\)gatedecl\(\rangle\langle\)goplist\(\rangle\mathbf{\}}\) | ||
\(\vert\langle\)gatedecl\(\rangle\mathbf{\}}\) | ||
\(\vert\mathbf{opaque\langle}\)id\(\rangle\langle\)idlist\(\rangle\mathbf{;}\) | ||
\(\vert\mathbf{opaque\langle}\)id\(\rangle\mathbf{( )}\langle\)idlist\(\rangle\mathbf{;}\vert\mathbf{opaque}\langle\)id\(\rangle\mathbf{(}\langle\)idlist\(\rangle\mathbf{)}\langle\)idlist\(\rangle\mathbf{;}\) | ||
\(\vert\langle\)qop\(\rangle\) | ||
\(\vert\mathbf{if ( }\langle\)id\(\rangle\mathbf{==}\langle\)nninteger\(\rangle\mathbf{)}\langle\)qop\(\rangle\) | ||
\(\vert\mathbf{barrier}\langle\)anylist\(\rangle\mathbf{;}\) | ||
\(\langle\)decl\(\rangle\) | \(\vDash\) | \(\mathbf{qreg}\langle\)id\(\rangle\mathbf{[}\langle\)nninteger\(\rangle\mathbf{];}\vert\mathbf{creg}\langle\)id\(\rangle\mathbf{[}\langle\)nninteger\(\rangle\mathbf{];}\) |
\(\langle\)gatedecl\(\rangle\) | \(\vDash\) | \(\mathbf{gate}\langle\)id\(\rangle\langle\)idlist\(\rangle\mathbf{\{}\) |
\(\vert\mathbf{gate}\langle\)id\(\rangle\mathbf{()}\langle\)idlist\(\rangle\mathbf{\{}\) | ||
\(\vert\mathbf{gate}\langle\)id\(\rangle\mathbf{(}\langle\)idlist\(\rangle\mathbf{)}\langle\)idlist\(\rangle\mathbf{\{}\) | ||
\(\langle\)goplist\(\rangle\) | \(\vDash\) | \(\langle\)uop\(\rangle\) |
\(\vert\mathbf{barrier}\langle\)idlist\(\rangle\mathbf{;}\) | ||
\(\vert\langle\)goplist\(\rangle\langle\)uop\(\rangle\) | ||
\(\vert\langle\)goplist\(\rangle\mathbf{barrier}\langle\)idlist\(\rangle\mathbf{;}\) | ||
\(\langle\)qop\(\rangle\) | \(\vDash\) | \(\langle\)uop\(\rangle\) |
\(\vert\mathbf{measure}\langle\)argument\(\rangle\mathbf{->}\langle\)argument\(\rangle\mathbf{;}\) | ||
\(\vert\mathbf{reset}\langle\)argument\(\rangle\mathbf{;}\) | ||
\(\langle\)uop\(\rangle\) | \(\vDash\) | \(\mathbf{U ( }\langle\)explist\(\rangle\mathbf{)}\langle\)argument\(\rangle\mathbf{;}\) |
\(\vert\mathbf{CX}\langle\)argument\(\rangle\mathbf{,}\langle\)argument\(\rangle\mathbf{;}\) | ||
\(\vert\langle\)id\(\rangle\langle\)anylist\(\rangle\mathbf{;}\vert\langle\)id\(\rangle\mathbf{()}\langle\)anylist\(\rangle\mathbf{;}\) | ||
\(\vert\langle\)id\(\rangle\mathbf{(}\langle\)explist\(\rangle\mathbf{)}\langle\)anylist\(\rangle\mathbf{;}\) | ||
\(\langle\)anylist\(\rangle\) | \(\vDash\) | \(\langle\)idlist\(\rangle\vert\langle\)mixedlist\(\rangle\) |
\(\langle\)idlist\(\rangle\) | \(\vDash\) | \(\langle\)id\(\rangle\vert\langle\)idlist\(\rangle\mathbf{,}\langle\)id\(\rangle\) |
\(\langle\)mixedlist\(\rangle\) | \(\vDash\) | \(\langle\)id\(\rangle\mathbf{[}\langle\)nninteger\(\rangle\mathbf{]}\vert\langle\)mixedlist\(\rangle\mathbf{,}\langle\)id\(\rangle\) |
\(\vert\langle\)mixedlist\(\rangle\mathbf{,} \langle\)id\(\rangle\mathbf{[}\langle\)nninteger\(\rangle\mathbf{]}\) | ||
\(\vert\langle\)idlist\(\rangle\mathbf{,} \langle\)id\(\rangle\mathbf{[}\langle\)nninteger\(\rangle\mathbf{]}\) | ||
\(\langle\)argument\(\rangle\) | \(\vDash\) | \(\langle\)id\(\rangle\vert\langle\)id\(\rangle\mathbf{[}\langle\)nninteger\(\rangle\mathbf{]}\) |
\(\langle\)explist\(\rangle\) | \(\vDash\) | \(\langle\)exp\(\rangle\vert\langle\)explist\(\rangle\mathbf{,}\langle\)exp\(\rangle\) |
\(\langle\)exp\(\rangle\) | \(\vDash\) | \(\langle\)real\(\rangle\vert\langle\)nninteger\(\rangle\vert\mathbf{pi}\vert\langle\)id\(\rangle\) |
\(\vert\langle\)exp\(\rangle+\langle\)exp\(\rangle\vert\langle\)exp\(\rangle-\langle\)exp\(\rangle\vert\langle\)exp\(\rangle*\langle\)exp\(\rangle\) | ||
\(\vert\langle\)exp\(\rangle/\langle\)exp\(\rangle\vert-\langle\)exp\(\rangle\vert\langle\)exp\(\rangle)^\(\langle\)exp\(\rangle\) | ||
\(\vert\mathbf{(}\langle\)exp\(\rangle\mathbf{)}\vert\langle\)unaryop\(\rangle\mathbf{(}\langle\)exp\(\rangle\mathbf{)}\) | ||
\(\langle\)unaryop\(\rangle\) | \(\vDash\) | \(\mathbf{sin}\vert\mathbf{cos}\vert\mathbf{tan}\vert\mathbf{exp}\vert\mathbf{ln}\vert\mathbf{sqrt}\) |
未列出的产生式 \(\langle\)id\(\rangle\), \(\langle\)real\(\rangle\), and \(\langle\)nninteger\(\rangle\) 由以下正则表达式定义
开始一个OpenQASM程序
OpenQASM程序融合了C语言和汇编语言的元素。程序的第一条非注释行必须是OPENQASM M.m;,其中M为主版本,m为次版本。目前当前版本为2.0,本文档中的所有内容均参照此版本。对于所有OpenQASM程序:
- OPENQASM M.m;语句只能出现一次,并且必须是第一条非注释语句。
- 语句之间用;分隔(类似于C语言)。
- 忽略空格。
- 注释以一对斜杠(即//)开头,以换行符结束。
- 标识符(例如门的名称)必须以小写字母开头,并可包含字母数字字符和下划线。
- 该语言区分大小写。
- include "filename";语句会继续解析filename,并将该文件的内容视为已粘贴到include语句所在位置的文本。filename的路径相对于当前工作目录指定。
V2中唯一的存储类型是经典寄存器和量子寄存器。它们分别是比特和量子比特的一维数组。量子寄存器使用qreg name[size];定义,经典寄存器使用creg name[size].定义。要引用特定的比特/量子比特,请使用标签name[j],其中\(j \in {0,1,...,size(name)-1}\)。所有量子比特都初始化为\(\vert 0 \rangle\),所有经典比特都初始化为0。
内置门
对于IBM Quantum Experience平台,只实现了两种门:通用U门和受控非门C-NOT门。但是,您可以使用include qelib1.inc语句来包含一个预构建文件,该文件包含许多其他门的定义。这些额外的门包括Pauli门、旋转门、单位门、Toffoli门、Hadamard门等。有关此文件中实现的门的全列表,请参阅规范的第10-12页。
我们已在本文系列的上一部分了解了C-NOT门。但是,U门是新的。它是一个单量子比特、三参数门。qelib1.inc文件中的所有门都构建于受控非门和此门之上。此门的矩阵定义为
其中
和
theta、phi和lambda的值由使用中缀表示法构建的参数表达式给出。对于IBM Quantum Experience,这包括科学计数法、实数运算、对数、三角函数、指数函数、平方根以及内置常数\(\pi\)。所有实数都使用双精度浮点数。不幸的是,OpenQASM的当前版本无法基于测量结果计算参数。
门可以应用于量子寄存器或特定量子比特。语句U(theta, phi, lambda) a;意味着对寄存器a中的每个索引j应用U(theta, phi, lambda) a[j];。然而,U(theta, phi, lambda) a[0];意味着只将U(theta, phi, lambda)应用于寄存器a中的量子比特0。
自定义门
新门必须在使用前定义。门定义可以被视为宏,在运行时进行展开。门的基本格式如下:
//comment gate name(parameters) qargs { body }
其中parameters是可选的逗号分隔的变量参数列表。参数列表qargs是量子比特参数的逗号分隔列表。参数名称和量子比特参数都是标识符。parameters变量是可选的,如果没有,也可以省略括号。但是,至少需要一个量子比特参数,因为门必须作用于至少一个量子比特。此外,门不能调用自身(即不允许递归)。
例如,让我们创建一个基本上对单个量子比特寄存器不做任何事情的门。我们将其命名为g,可以这样写:
gate g a { U(0, 0, 0) a; }
需要注意的一个重要事项是,在门定义的主体中,不能对qargs参数进行索引。也就是说,虽然上面的定义是一个有效的门定义,但下面的定义是无效的:
gate g a { U(0, 0, 0) a[0]; }
假设我们有一个定义为qreg qr0[1]的量子寄存器,我们刚才定义的门可以通过两种方式调用。第一种方式是仅使用量子寄存器名称:g qr0。在这种情况下,该门将应用于此寄存器中的所有量子比特,对于qr0来说总共有两个。第二种方式是使用特定量子比特调用该门,例如g qr0[1]。在这种情况下,该门将仅应用于qr0寄存器的第二个量子比特,而不是第一个。
语句概述
下表提供了OpenQASM程序中各种语句的快速概览。该表的副本可以在OpenQASM规范的第9页找到。
声明 | 描述 | 示例 |
OPENQASM 2.0; | 表示OpenQASM格式的文件 | OPENQASM 2.0; |
qreg name[size]; | 声明一个命名的量子比特寄存器 | qreg q[5]; |
creg name[size]; | 声明一个命名的比特寄存器 | creg c[5]; |
include "filename" | 打开并解析另一个源文件 | include "qelib1.inc"; |
gate name(params) qargs { body } | 声明一个酉门 | |
opaque name(params) qargs | 声明一个不透明门 | |
// comment text | 注释行 | // oops! |
U(theta, phi, lambda) qubit|qreg; | 应用内置的单量子比特门(s) | U(pi/2, 2*pi/3, 0) q[0]; |
CX qubit|qreg, qubit|qreg; | 应用内置的CNOT门(s) | CX q[0], q[1]; |
measure qubit|qreg -> bit|creg; | 在Z基进行测量(s) | measure q -> c; |
reset qubit|qreg; | 将量子比特准备在\(\vert 0 \rangle\)状态 | reset q[0]; |
gatename(params) qargs; | 应用用户定义的酉门 | crz(pi/2) q[1],q[0]; |
if(creg==int) qop; | 有条件地应用量子操作 | if (c==5) CX q[0],q[1]; |
barrier qargs | 阻止在该源线上重排门 | barrier q[0],q[1]; |
其他语句
除了内置门和自定义门之外,OpenQASM还提供了其他语句,可用于影响量子电路的运行方式。
Reset
reset qubit|qreg;语句将指定的量子比特或整个量子寄存器重置为\(\vert 0 \rangle\)状态。
reset qubit|qreg;语句对应于对这些量子比特进行部分迹(即丢弃它们),然后再用\(\vert 0 \rangle \langle 0 \vert\)替换它们。
条件 if
if语句是OpenQASM目前唯一可用的经典控制的量子操作。if语句根据经典寄存器的值来执行量子操作。经典寄存器被解释为一个整数值,其中索引0处的比特作为低位比特。例如,如果以下代码行出现在OpenQASM程序中
if(c==3) U(theta, phi, lambda) q[0];
那么,仅当经典寄存器c等于整数值3时,才会将U门操作应用于q[0]量子比特。
测量
measure语句用于实际检索量子操作的值。语句measure qubit|qreg -> bit|creg;在Z基测量量子比特(s),并通过覆盖比特(s)来记录结果。两个参数都必须是寄存器类型,或者都必须是比特类型。在两个参数都是寄存器类型且大小相同的情况下,语句measure q -> c;意味着对寄存器q中的每个索引j执行**measure q[j] -> c[j]**。
栅栏
barrier语句阻止优化将门重排到其源线之外。例如,如果我们有以下代码
CX r[0],r[1]; h q[0]; h s[0]; barrier r,q[0]; h s[0]; CX r[1],r[0]; CX r[0],r[1];
barrier语句将阻止尝试组合CNOT门,但允许**h s[0];**门对抵消。
不透明
opaque语句用于当一个门可能在物理上实现但没有指定定义时。在这种情况下,您会声明一个“不透明”的门声明。不透明门声明的语法与常规门声明相同,但没有主体。
程序示例
下面是三个OpenQASM程序示例,将演示如何进行抛硬币、生成随机数以及对三个量子比特执行多数函数。每个示例都包含完整的OpenQASM程序,然后对其工作原理进行说明。我建议至少保存前两个示例到文本文件,因为我们将在本系列的第四部分实际模拟它们,并让它们在真实的量子计算机上运行。
抛硬币示例
//Coin Flip Example OPENQASM 2.0; include "qelib1.inc" qreg q[0]; creg c[0]; h q; measure q -> c;
上面的OpenQASM程序执行位翻转操作。前三行是注释,描述了程序的功能、版本语句以及包含IBM Quantum Experience平台上所有预定义门的包含语句。必须包含qelib1.inc文件,以便我们使用Hadamard(h)门。
接下来的两行定义了一个单量子比特寄存器(q)和一个单比特寄存器(c)。下一行将Hadamard门应用于q寄存器,最后一行测量q寄存器并将其值放入c寄存器。
在本文系列的第二部分,我们了解到Hadamard门由以下矩阵表示:
并且它将\(\vert 0\rangle\)状态(量子比特最初初始化为此状态)映射到\(\frac{\vert 0\rangle + \vert 1\rangle}{\sqrt{2}}\)。这意味着当在最后一行测量时,量子比特有相等的机会为\(\vert 0\rangle\)或\(\vert 1\rangle\)。这个程序比任何经典计算机程序都好,因为经典计算机是确定性的,永远无法真正随机。量子计算机则不然。最后一行测量是一个真正随机的量子过程,在足够多的运行次数后,应该返回\(\vert 0\rangle\)和\(\vert 1\rangle\)的次数相等。
随机数示例
//Random Number Example OPENQASM 2.0; include "qelib1.inc" qreg q[4]; creg c[4]; h q; measure q -> c;
这个程序几乎与抛硬币示例相同。唯一的区别是我们增加了量子寄存器和经典寄存器的数量,分别为五个量子比特和五个经典比特。当Hadamard门应用于量子寄存器时,它会单独地将门应用于每个量子比特。因此,每个量子比特都有相等的机会成为\(\vert 0\rangle\)或\(\vert 1\rangle\),从而随机生成一个介于0到31之间的数字。同样,由于这是在量子处理器上运行的,它是一个真正的随机数生成器。
我们可以根据需要增大寄存器的大小,但是IBM Quantum Experience平台对可模拟的量子比特数量有限制,而实际处理器只有五个量子比特。因此,我将寄存器大小限制为五个量子比特/比特,以便我们可以在第四部分中的量子计算机上运行该程序而无需进行任何更改。
结论
在这一部分,我们学习了如何绘制和解释量子电路图以及如何编写OpenQASM程序。在下一部分,第四部分 - IBM量子体验,我们将运行本节中介绍的示例程序。它们将作为模拟和在真实的量子处理器上执行,以便我们能够确认它们是否成功运行。
参考文献
- \(\langle q|pic\rangle\):一种脚本语言,用于生成高质量的量子电路图,可包含在LaTeX文档中,格式为TikZ或PDF格式
- OpenQASM规范
历史
2017年6月26日:第一个版本
第二部分:量子门 | 第四部分:IBM量子体验 |