原文:
zh.annas-archive.org/md5/d36b115ba52130eb6fd1400da3fcf417译者:飞龙
第五章:第五章:使用 Qiskit®游览 IBM Quantum®硬件
在前面的章节中,我们主要使用了内置和本地各种形式的量子计算机模拟器,但我们也将一些量子程序连接到实际的 IBM 量子计算机上并运行。在本章中,我们将更深入地研究这些后端,直至实际的物理量子比特层面。
我们将通过使用 IBM Quantum Experience®和 Qiskit®访问有关可用硬件的数据,快速游览 IBM Quantum®实验室。在这些事情中,我们将查看量子芯片布局的图形视图,量子计算机的一些物理方面,如 T1 和 T2 退相干参数,一些基本和高级错误度量,可用的量子比特之间如何相互交互,等等。
在本章中,我们将涵盖以下食谱:
-
IBM Quantum®机器是什么?
-
定位可用的后端
-
比较后端
-
寻找最不繁忙的后端
-
可视化后端
-
使用 Qiskit®探索选定的后端
在本章中,我们将一般使用我们在第四章中使用的贝尔态程序,从 Terra 的起点开始,作为其理想结果,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_001.png和https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_002.png,这些结果对我们来说是已知的,我们可以使用它们来比较不同机器和不同量子比特集上的运行。
技术要求
在您开始本章的量子程序之前,请确保您已完成了第一章中所有步骤,准备您的环境,特别是安装您的 API 密钥并访问您的提供商食谱。
本章中讨论的量子程序可以在此找到:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/tree/master/Chapter05。
IBM Quantum®机器是什么?
本节与其说是食谱,不如说是对您将遇到的量子组件和过程的基本概述。如果您想直接跳过并开始编码,请转到下一食谱。
使用 Qiskit®,您可以在两种类型的量子计算机上运行您的量子程序:ibmq_qasm_simulator – 可在线使用 – 允许您在最多 32 个量子比特 上运行相当深入的量子程序。您本地模拟器的性能取决于您的硬件;请记住,模拟量子计算机随着每个量子比特的增加而呈指数级变难。
实际的 IBM 量子计算机硬件位于 IBM 实验室中,并通过云访问。这样做有很好的理由,所以让我们一步步了解如何设置和运行 IBM Quantum®提供的超导量子比特量子计算机。
准备工作
超导量子计算机对噪声非常敏感,如电磁辐射、声波和热量。配备低温冷却的隔离环境提供了一个尽可能少的干扰的位置。
量子计算机可能使用所谓的约瑟夫森结,在低温下保持并受微波脉冲操控。普通人没有这种硬件,因此,在这本书中,我们将使用云中免费可用的 IBM 量子计算机进行量子编程。
如何操作…
以下步骤是对在真实的 IBM 量子计算机上运行你的量子程序过程的非常高级的描述:
-
在你的本地 Qiskit®环境中或在 IBM Quantum Experience®上编写量子程序。
-
将你的程序通过云发送到 IBM Quantum®进行排队。
IBM 云®量子计算模型意味着你将不会无限制地访问这些机器。这是一个时间共享系统,每个人都会得到一些访问权限,类似于计算机早期使用过的经典时间共享系统。这种类比并不太坏。
-
你的程序现在获得了
u1、u2、u3、id和cx。结果证明,你编写的所有量子程序都可以仅使用这些门来表示。作为转换的一部分,你的电路可能会在大小和深度上有所变化,因为单个门根据你运行程序的底层转换成一系列门。简单来说,电路的大小是使用的门的基本数量,深度是电路从左到右的长度,这大致相当于量子计算机运行你的程序时必须进行的并行操作的数量。你的原始程序结构可能需要改变以适应你运行的芯片的物理布局。
-
你的转换程序中的门被编码成波包。
现在代码已经被转换成可以在芯片上运行的组件,这些组件被转换成微波包,可以发送到量子芯片。每个门可以看作是量子比特布洛赫矢量绕三个轴的旋转,每个角度都可以编码为不同频率和持续时间的微波脉冲。
-
量子芯片被重置。
在我们能在芯片上执行任何量子计算之前,其量子比特需要重置到其基态。这是通过向每个量子比特发送特定的微波脉冲来完成的,就像在下一步中描述的将你的门发送到量子比特一样。
-
你的编码门随后被发送到量子比特。
每个门都作为波包发送到相应的量子比特,这个波包位于一个 GHz 载波波上,其频率正好调谐到接收量子比特的频率。我们现在离开了所谓的室温电子设备,进入了低温环境。编码门的信号通过依次冷却的层向下传输到量子计算机的内部,最终到达 15 毫开尔文温度的量子芯片——比外太空还要冷。在旅程结束时,波包最终通过微波谐振器撞击量子比特,以改变量子比特的状态。
这对每个量子比特上应用的每个门都重复进行,这就是在后端运行量子程序的过程。
-
现在读取了量子比特。
到程序结束时,一种特定的波包与谐振器发生干涉,然后产生的包干涉被发送回堆栈,通过依次变暖的层,然后进入室温电子设备。
干涉被解释为
0或1,因此你的程序结果被记录下来。在这个状态下,你共振量子比特的微妙平衡已经被破坏——量子比特不再表现出量子行为,在我们可以再次使用它之前需要将其重置到基态。
整个过程会根据你要求的射击次数重复进行,所有结果都存储在云端。最后,如果你的耐心足够,你的完整运行会被打包并返回给你,同时也会被存储以供以后检索。
它是如何工作的…
之前提到的多数步骤都是高度自动化的。你只需编写你的量子程序并发送出去,然后 IBM Quantum®会完成剩余的工作,并将你的量子比特测量结果以 1 或 0 的形式返回。
如你所见,有几个步骤你可以介入并指定如何操作,例如,选择后端,根据量子比特参数选择要使用的量子比特,决定要运行的射击次数,等等。在本章中,我们将介绍如何从 IBM Quantum®机器中挖掘硬件信息和配置参数。
参考信息
-
想了解更多关于 IBM Quantum®硬件的信息,请参阅
www.research.ibm.com/ibm-q/technology/devices/ -
你还可以阅读由 John M. Martinis 和 Kevin Osborne 在 NIST 撰写的关于超导量子比特和约瑟夫森结物理学的文章:
web.physics.ucsb.edu/~martinisgroup/classnotes/finland/LesHouchesJunctionPhysics.pdf -
此外,这里有一篇关于 QC – 如何使用超导电路构建量子计算机? 的令人愉快的 Medium 文章,作者是 Jonathan Hui:
medium.com/@jonathan_hui/qc-how-to-build-a-quantum-computer-with-superconducting-circuit-4c30b1b296cd
定位可用的后端
在 Qiskit®中,后端代表您运行量子程序的系统。一个 后端 可以是一个模拟器,比如我们之前使用过的本地 Aer 模拟器。如果您想在本地模拟器而不是在您的本地模拟器上运行量子程序,您必须将一个 IBM Quantum®机器识别为后端来使用,然后配置您的量子程序以使用它。
让我们看看我们将要进行的步骤:
-
首先,导入所需的类和方法,并加载您的账户信息。在这种情况下,我们使用 IBM Q 类,它包含主要的硬件相关功能。
-
查看您账户可用的机器。
-
选择一个通常可用的后端。
-
在选定的后端上创建并运行贝尔态量子程序。
-
选择一个模拟器后端,再次运行贝尔态量子程序以进行比较。
准备工作
在这个菜谱中,我们将使用 IBM Q provider.backends() 方法来识别和过滤可用的后端以运行您的程序,然后使用 provider.get_backend() 方法来选择后端。在下面的示例中,我们将使用 ibmqx2 和 ibmq_qasm_simulator 后端。然后我们将在一个硬件后端上运行一个小型量子程序,然后是在模拟器后端上。
在以下菜谱中的 Python 文件可以从这里下载:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter05/ch5_r1_identifying_backends.py。
如何做到这一点…
-
总是先导入 Qiskit®类和方法以使用:
from qiskit import IBMQ, QuantumCircuit, execute from qiskit.tools.monitor import job_monitor -
在您可以使用
IBMQ类和后端方法(如果尚未设置)之前,您必须设置与您的账户关联的提供者:if not IBMQ.active_account(): IBMQ.load_account() provider = IBMQ.get_provider() -
provider.backends()方法用于定位对您的 IBM Quantum®账户可用的 IBM Quantum®后端。有了这些信息,您可以通过使用provider.get_backend()方法来设置您想要在它上面运行量子程序的后端:print(provider.backends(operational=True, simulator=False)) -
之前的代码可能会产生类似于以下输出的结果:
Available backends: [<IBMQBackend('ibmqx2') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_16_melbourne') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_vigo') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_ourense') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_valencia') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_london') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_burlington') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_essex') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_armonk') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_santiago') from IBMQ(hub='ibm-q', group='open', project='main')>] >>> provider.backends(simulator=False)或者,您可以使用复杂的过滤,如 lambda 函数:
>>> provider.backends(filters=lambda x: not x.configuration().simulator)我们也只对那些没有因维护而关闭的后端感兴趣。为此,我们通过
operational参数进行过滤:>>> provider.backends(operational=True, simulator=False)或者,您可以使用以下代码:
>>> provider.backends(filters=lambda x: not x.configuration().simulator and x.status().operational) -
因此,考虑到这一点,当你想在 IBM Quantum®机器上运行你的量子程序时,你需要指定要运行的后端,为此,你可以使用
get_backend()方法。让我们手动从我们之前的列表中选择一个后端,例如,ibmqx2:backend = provider.get_backend('ibmqx2') print("\nSelected backend:", backend.name()) -
前面的代码应该给出以下结果:
Out[]: Selected backend: ibmqx2 -
现在,选择了一个后端,你可以使用命令
job = execute(<your_quantum_circuit>, backend)在该后端上执行作业。在这种情况下,我们将使用以下命令:job = execute(qc, backend, shots=1000) -
我们现在可以创建电路进行测试:
qc = QuantumCircuit(2,2) qc.h(0) qc.cx(0,1) qc.measure([0,1],[0,1]) print("\nQuantum circuit:") print(qc) job = execute(qc, backend, shots=1000) job_monitor(job) result = job.result() counts = result.get_counts(qc) print("\nResults:", counts) -
示例代码应该给出类似以下的结果:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.1_B14436.jpg
图 5.1 – 在所选后端上贝尔量子电路的输出
-
要选择 IBM Quantum®模拟器作为后端,并在其上运行电路,你可以这样做:
print(provider.backends(operational=True, simulator=True)) backend = provider.get_backend('ibmq_qasm_simulator') job = execute(qc, backend, shots=1000) job_monitor(job) result = job.result() counts = result.get_counts(qc) print("\nSimulator results:", counts) -
前面的代码应该给出以下结果:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.2_B14436.jpg
图 5.2 – 在 ibmq_qasm_simulator 后端上贝尔量子电路的输出
因此,我们现在已经确定了可用的 IBM Quantum®后端,并在我们选择的后端以及模拟后端上运行了一个量子程序。在下一道菜谱“比较后端”中,我们将对可用的后端进行简单的性能比较。
更多内容…
你还可以使用backends()方法查看你本地安装的 Qiskit®环境中可用的模拟后端。首先,导入Aer模拟器类,然后使用backends()方法查看可用的后端:
from qiskit import Aer
Aer.backends()
前面的代码应该给出以下结果:
Out[]: [<QasmSimulator('qasm_simulator') from AerProvider()>,
<StatevectorSimulator('statevector_simulator') from
AerProvider()>,
<UnitarySimulator('unitary_simulator') from AerProvider()>,
<PulseSimulator('pulse_simulator') from AerProvider()>]
这些都是模拟器:
-
'qasm_simulator':这个模拟器允许你运行你的量子程序,并得到的结果就像你在没有错误和噪声的完美量子计算机上运行一样。 -
'statevector_simulator':使用这个,你可以模拟你的量子比特在整个电路中的状态向量。 -
'unitary_simulator':这个模拟器允许你为你的电路创建单位矩阵。 -
'pulse_simulator':这个模拟器允许你向量子比特发送离散脉冲。
我们已经看到了在第四章,“从 Terra 的起点开始”,中使用的'qasm_simulator'和'statevector_simulator',我们将在第六章,“理解 Qiskit®门库”中更详细地查看'unitary_simulator'。
参见
-
关于可用的 IBM Quantum®系统的更多信息:
www.ibm.com/quantum-computing/technology/systems/. -
你还可以使用 Python 帮助,使用
help(IBMQ)和help(provider.backends)来查找有关这些 Qiskit®方法的更多信息。
比较后端
IBM Quantum®后端在数量、比特数以及这些比特之间的行为和交互上都有所不同。根据你编写的量子程序,你可能希望在具有特定特性的机器上运行代码。
IBMQ 返回的后端信息只是一个普通的 Python 列表,你可以用任何其他列表来操作返回的数据。例如,你可以编写一个 Python 脚本来查找可用的 IBM Quantum®后端,然后在每个后端上运行量子程序,并在显示后端比特质量大致测量的图表中比较结果。
在这个菜谱中,我们将使用一个简单的 Python 循环,在可用的 IBM Quantum®后端上运行一系列相同的贝尔态量子程序,以获得后端性能的大致估计。
准备工作
用于此菜谱所需的文件可以从这里下载:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter05/ch5_r2_comparing_backends.py。
如何操作…
让我们看看如何比较后端:
-
首先,我们导入所需的类和方法。
在这种情况下,我们使用 IBMQ 库,它包含主要的硬件相关函数。我们还导入了构建量子电路、监控作业和显示结果的类。然后加载存储的账户 API 密钥并获取提供者:
from qiskit import IBMQ, QuantumCircuit, execute from qiskit.tools.monitor import job_monitor from qiskit.visualization import plot_histogram if not IBMQ.active_account(): IBMQ.load_account() provider = IBMQ.get_provider() -
现在,我们将创建一个已知预期结果的量子程序。
例如,一个贝尔态程序,在完美的量子计算机上只会给出 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_003.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_004.png 的结果:
qc = QuantumCircuit(2,2) qc.h(0) qc.cx(0,1) qc.measure([0,1],[0,1]) -
上一段代码应该给出以下结果:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.3_B14436.jpg
图 5.3 – 一个贝尔态量子电路
-
现在,我们将获取所有可用和可操作的后端,包括用于基准测试的 IBM Quantum®模拟器:
backends = provider.backends(filters=lambda b: b.configuration().n_qubits > 1 and b.status().operational) print("\nAvailable backends:", backends)过滤掉单比特后端
看看我们在这里是如何使用过滤器,只包括具有超过 1 个比特的后端。这样做的原因是我们的代码需要两个操作比特,如果我们在只有一个比特的后端上运行代码,代码将会失败。可用的 IBM Quantum®机器之一—
ibmq_armonk—是一个只有一个比特的量子计算机;我们不希望使用它,并使用过滤器将其从我们的后端列表中删除。ibmq_armonk后端的目的在于进行量子比特脉冲编程的实验,这超出了本书的范围。 -
上一段代码可能会得到以下结果:
Available backends: [<IBMQSimulator('ibmq_qasm_simulator') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmqx2') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_16_melbourne') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_vigo') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_ourense') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_valencia') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_london') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_burlington') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_essex') from IBMQ(hub='ibm-q', group='open', project='main')>, <IBMQBackend('ibmq_santiago') from IBMQ(hub='ibm-q', group='open', project='main')>] -
然后,我们将按顺序在这些后端上运行简单的量子程序。结果计数存储在一个我们称之为
counts的字典中:counts = {} for n in range(0, len(backends)): print('Run on:', backends[n]) job = execute(qc, backends[n], shots=1000) job_monitor(job) result = job.result() counts[backends[n].name()] = result.get_counts(qc)排队
在几台不同的机器上运行四个量子程序可能需要一段时间,具体取决于其他用户在积极使用后端的人数以及排队作业的数量。例如,在典型的周日晚上,在八个后端和一个模拟器上运行此程序可能需要大约一个小时。
-
之前的代码可能会得到以下结果:
Run on: ibmq_qasm_simulator Job Status: job has successfully run Run on: ibmqx2 Job Status: job has successfully run Run on: ibmq_16_melbourne Job Status: job has successfully run ... Run on: ibmq_essex Job Status: job has successfully run Run on: ibmq_santiago Job Status: job has successfully run -
现在作业正在运行,我们可以使用以下代码打印并绘制结果:
print("\nRaw results:", counts) #Optionally define the histogram colors. colors = ['green','darkgreen','red','darkred','orange', 'yellow','blue','darkblue','purple'] #Plot the counts dictionary values in a histogram, using #the counts dictionary keys as legend. display(plot_histogram(list(counts.values()), title = "Bell results on all available backends legend=list(counts), color = colors[0:len(backends)], bar_labels = True) -
之前的代码可能会得到以下结果:
Raw results: {'ibmq_qasm_simulator': {'00': 510, '11': 490}, 'ibmqx2': {'00': 434, '01': 77, '10': 39, '11': 450}, 'ibmq_16_melbourne': {'00': 474, '01': 42, '10': 48, '11': 436}, 'ibmq_vigo': {'00': 512, '01': 18, '10': 42, '11': 428}, 'ibmq_ourense': {'00': 494, '01': 26, '10': 19, '11': 461}, 'ibmq_valencia': {'00': 482, '01': 31, '10': 30, '11': 457}, 'ibmq_london': {'00': 463, '01': 48, '10': 39, '11': 450}, 'ibmq_burlington': {'00': 385, '01': 182, '10': 84, '11': 349}, 'ibmq_essex': {'00': 482, '01': 46, '10': 24, '11': 448}, 'ibmq_santiago': {'00': 514, '01': 17, '10': 17, '11': 452}}
这些原始结果显示了每个后端运行程序的效果。ibmq-qasm-simulator 代表在模拟的通用量子计算机上的理想结果;其他结果显示了程序在实际 IBM Quantum® 后端上的运行情况。一个完美的量子计算机将得到与模拟器相似的结果,从而得到 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_005.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_006.png 的值:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.4_B14436.jpg
图 5.4 – 贝尔结果的图形视图
我们在这里创建的是一个简单的比较,使用一个 基本的 2 量子比特贝尔态量子程序来比较可用的 IBM Quantum® 后端。在一个完美的量子计算机上,我们只期望得到结果 – https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_007.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_008.png – 这正是我们在 ibmq_qasm_simulator 上看到的结果。正如我们在第四章,从 Terra 的基础开始所讨论的,对于真实的 有噪声的中尺度量子(NISQ)机器,我们期望有一些噪声和混合结果,包括 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_009.png,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_010.png,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_011.png,和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_012.png 对于 IBM Quantum® 硬件。
一般而言,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_013.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_05_014.png 条形图越小,后端的表现越好,但有许多因素在起作用。这些将在本章的后面以及第八章,用 Ignis 清理你的量子行为中探讨。
此外,请注意,我们在这里只比较了你的量子程序默认执行情况。不同的量子比特配置、读出错误、量子比特连接问题和其他在真实硬件上发生的错误也会起作用,并使结果变得有些随机。
更多内容
在这个配方中,我们在几乎所有可用的后端上运行了我们的量子程序。正如你在 定位可用的后端 配方中所看到的,你还可以过滤后端。这个配方至少需要两个量子比特来运行,因此我们添加了一个过滤器来包括具有一个以上量子比特的后端:
backends = provider.backends(filters=lambda b: b.configuration().n_qubits > 1 and b.status().operational)
你可以使用过滤功能出于其他原因;例如,仅运行在 5 量子比特机器上,通过量子比特数量进行过滤:
# Get all available and operational backends.
backends = provider.backends(n_qubits=5)
你现在可以看到可用的后端如何表现,以及其中一些可能有多忙碌。是时候找出一种方法,通过找到队列最短的后端来加速你的量子程序执行了。
寻找最近忙的后端
当您在 IBM Quantum®后端上运行量子程序时,您会很快意识到,您可能不是唯一一个同时尝试使用相同后端的人。根据时间和星期几,以及正在运行的量子程序的类型和目的,并非所有 IBM Quantum®机器的使用程度都相同。
如果您不关心应该在哪个机器上运行代码,您可以使用least_busy方法自动找到运行程序的最佳后端。后端的最不繁忙状态通常意味着您有最少的等待时间,但这并不一定正确。有些程序运行时间比其他程序长,队列(就像在超市里一样)可能以不同的速度移动。
让我们看看以下步骤:
-
首先,导入所需的
IBMQ和least_busy方法,并加载我们的账户。 -
使用
least_busy方法自动选择通常可用的最不繁忙的后端,以及具有 5 量子比特的最不繁忙的后端。 -
最后,让我们显示所有后端的概述数据,以验证我们选择的后端确实是最近忙的后端。
如果我们不希望等待执行但可能不是最佳选择,least_busy方法就非常方便。Qiskit®已经为我们提供了最不繁忙的后端名称。我们现在可以信任 Qiskit®并在该后端上运行我们的量子代码,或者,根据我们的目的,我们可能选择另一个后端来运行。结果可能是,最不繁忙的后端是一个具有噪声量子比特或 T1 或 T2 时间短的机器,这并不适合我们的需求。
准备工作
下面的食谱中所需文件可以从这里下载:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter05/ch5_r3_least_busy.py。
如何做到这一点…
least_busy正在寻找包含pending_jobs参数的后端。如果您添加了额外的筛选功能,排除了实际最不繁忙的后端,该方法将返回符合筛选标准的具有最少挂起作业的后端。
让我们看看:
-
首先,导入所需的
IBMQ和least_busy方法,并加载我们的账户:from qiskit import IBMQ from qiskit.providers.ibmq import least_busy if not IBMQ.active_account(): IBMQ.load_account() provider = IBMQ.get_provider() -
现在,我们可以询问 IBM Quantum®哪个后端是最不繁忙的,并相应地设置我们的
backend参数:backend = least_busy(provider.backends(simulator=False)) print("Least busy backend:", backend.name())上述代码可能会得到以下结果:
Out[]: Least busy backend: ibmq_armonk在这个例子中,最不繁忙的后端是
ibmq_armonk,这是一台用于脉冲测试的 1 量子比特机器。这不是您想在上面运行多量子比特电路的后端。 -
筛选最不繁忙的结果。
您可以将
least_busy方法传入一个经过筛选的后端列表,例如,仅包括 5 量子比特的机器,或者直接使用未经筛选的provider.backends()函数调用该方法,如下面的示例所示:filtered_backend = least_busy(provider.backends( n_qubits=5, operational=True, simulator=False)) print("\nLeast busy 5-qubit backend:", filtered_backend.name())以下代码可能给出以下输出:
Out[]: Least busy 5-qubit backend: ibmq_santiago就这样 – 这是拥有五个量子比特的最不繁忙的后端。
-
为了检查所选方法是否选择了最佳后端,我们可以使用
backend_overview()方法查看可用后端的挂起作业数量:from qiskit.tools.monitor import backend_overview print("\nAll backends overview:\n") backend_overview()以下代码可能给出以下结果:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.5_B14436.jpg
图 5.5 – 未过滤的所有可用后端
注意最不繁忙参数。如您所见,最不繁忙的后端挂起作业数量是最小的。
因此,本食谱的要点是您可以自动化您运行的量子程序的后端,但如果您需要在特定数量的量子比特上运行程序,返回的后端可能不是您想要的。如果是这种情况,通过量子比特数量过滤搜索以获取队列最短的后端。
可视化后端
现在我们已经开始探索 IBM Quantum®后端的各个参数,有一个简单的方法来获取量子芯片和各个重要参数的视觉概述将很有帮助,例如量子比特如何相互连接,哪些连接比其他连接更好,每个量子比特的质量如何,等等。Qiskit®内置了可视化功能。
准备工作
下面的食谱中所需的文件可以从这里下载:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter05/ch5_r4_backend_vis.py。
如何操作…
我们将使用qiskit.visualization包的三个方法来查看后端:plot_gate_map()、plot_error_map()和plot_circuit_layout()。对于最后一个,我们还需要使用transpile()方法对量子电路进行转换,然后显示 Qiskit®将您的门映射到后端上的哪些量子比特。
让我们看看以下步骤:
-
首先导入所需的
qiskit和qiskit.visualization方法,并加载我们的账户:from qiskit import IBMQ, QuantumCircuit, transpile from qiskit.providers.ibmq import least_busy # Import the backend visualization methods from qiskit.visualization import plot_gate_map, plot_error_map, plot_circuit_layout if not IBMQ.active_account(): IBMQ.load_account() provider = IBMQ.get_provider() -
获取并获取所有具有超过 1 个量子比特且不是模拟器的可用 IBM Quantum®后端:
available_backends = provider.backends(filters=lambda b: b.configuration().n_qubits > 1 and b.status(). operational) print("{0:20} {1:<10}".format("Name","#Qubits")) print("{0:20} {1:<10}".format("----","-------")) for n in range(0, len(available_backends)): backend = provider.get_backend(str(available_ backends[n])) print("{0:20} {1:<10}".format(backend.name(), backend.configuration().n_qubits)) -
选择您想要查看的后端:
backend_input = input("Enter the name of a backend, or X for the least busy:") if backend_input not in ["X","x"]: backend = provider.get_backend(backend_input) else: backend = least_busy(provider.backends( filters=lambda b: b.configuration().n_qubits > 1 and b.status().operational)) -
现在,让我们显示后端的门映射图和错误映射图:
print("\nQubit data for backend:",backend.status(). backend_name) display(plot_gate_map(backend, plot_directed=True)) display(plot_error_map(backend))这种首次可视化显示了后端的逻辑布局,可选地显示了量子比特之间允许的通信方向(
plot_directed=True)。考虑以下示例:
display(plot_gate_map(backend, plot_directed=True))。以下代码可能为
ibmq_burlington提供以下输出:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.6_B14436.jpg
图 5.6 – ibmq_burlington 的门映射图
通过错误映射可视化,你可以看到后端的读出错误和 CX 错误率。此图为你提供了关于量子比特质量的信息,这些量子比特可以提供准确的读出结果,并在两个量子比特之间的 受控-NOT (CX) 门上正确执行:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.7_B14436.jpg
图 5.7 – ibmq_burlington 的错误映射
-
最后,创建一个贝尔电路,将其翻译,并使用它来显示电路布局:
# Create and transpile a 2 qubit Bell circuit qc = QuantumCircuit(2) qc.h(0) qc.cx(0,1) display(qc.draw('mpl')) qc_transpiled = transpile(qc, backend=backend, optimization_level=3) display(qc_transpiled.draw('mpl')) # Display the circuit layout for the backend. display(plot_circuit_layout(qc_transpiled, backend, view='physical'))电路布局稍微复杂一些,因为它不仅需要后端作为输入,你还必须提供你想要在其上运行的编译后的量子电路。
例如,仍然在
ibmq_burlington上,我们可能想要运行一个贝尔电路。前面的代码可能会得到以下结果:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.8_B14436.jpg
图 5.8 – 具有两个量子比特的贝尔量子电路
翻译后的电路告诉我们,我们将在量子比特 0 和 1 上运行电路。因为我们开始时是一个 2 量子比特电路,所以我们给了编译器将任意两个量子比特分配给我们的电路的选项:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.9_B14436.jpg
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.9_B14436.jpg
图 5.9 – 翻译后的贝尔电路
电路布局显示给我们预期的量子比特分配:
图 5.10 – 贝尔电路中的 CX 门从量子比特 0 映射到量子比特 1
该视图以象征性的方式说明了物理芯片的外观,没有任何技术细节。
还有更多…
我们已经看到了 Qiskit® 中的可视化步骤。你也可以在 IBM Quantum Experience® 中获得相同的信息。
让我们看看:
-
登录 IBM Quantum Experience®
quantum-computing.ibm.com。 -
在 欢迎 页面的右侧,你会看到一个可用后端的列表:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.11_B14436.jpg
图 5.11 – IBM Quantum Experience® 主页
-
点击你感兴趣的后端,例如
ibmq_burlington,以查看芯片布局和附加信息:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.12_B14436.jpg
图 5.12 – ibmq_burlington 芯片的细节
这里有一个简短的数据列表,你可以看到所选芯片的不同部分:
-
在线或离线:后端目前可用吗?
-
当前队列:目前有多少人在使用后端?这个数字为你提供了一个粗略的估计,即后端有多忙,以及你的程序可能需要多长时间才能运行。
-
提供商:这将是对免费后端开放的。
-
实际量子芯片的蓝图视图:该视图以象征性的方式说明了物理芯片的外观,没有任何技术细节。
-
连接图:量子比特之间的箭头说明了它们如何使用 2 量子比特门(如CNOT门,也称为受控非或CX)进行连接。连接可以从箭头开始的量子比特到箭头结束的量子比特。
-
单量子比特错误率:这是量子比特质量的衡量标准。它是量子比特本身的错误率和读出错误的总结。基本上,这是量子比特处于一个状态时被读取为另一个状态的概率。
-
CNOT 错误率:这是量子比特连接质量的衡量标准。它是两个纠缠量子比特读取相反纠缠的概率。
-
量子比特数量:可用的量子比特数量。
-
上线时间:机器上线的时间和日期。
-
最大射击次数:你可以在后端上运行的最大射击次数。
-
量子体积:后端的测量量子体积。量子体积是 IBM 为衡量今天量子计算机性能所提出的基准。
-
u1、u2、u3、cx和id。有了这些门,你可以构建 Qiskit®支持的所有其他量子门。
你可以使用可视化的 IBM Quantum®信息作为编写和执行你的量子程序的指导,并包括诸如量子比特属性和错误图等方面,以针对特定的后端微调你的程序。然而,在纯、非用户界面 Qiskit®环境中,你可能希望在不使用用户界面的情况下访问这些数据。所有这些内容都在下一个菜谱中介绍,我们将直接在 Qiskit®中挖掘这些数据。
参见
关于量子体积概念的概述和解释,请参阅 Medium 文章:量子体积究竟是什么?,作者 Ryan F. Mandelbaum,IBM Quantum®和 Qiskit®的高级技术作家:medium.com/qiskit/what-is-quantum-volume-anyway-a4dff801c36f
使用 Qiskit®探索选定的后端
可视化探索后端数据是一个方便但严格的手动过程。有时你可能想在运行程序时将后端信息包含在程序逻辑中,例如,选择合适的后端或动态地在最佳量子比特上应用你的门。为此,我们可以通过使用 Qiskit®直接从可用的后端信息中提取这些数据。
在这个菜谱中,我们将使用backend.configuration()、backend.status()和backend.properties()方法来检索和列出可用的和正在运行的后端,以及一些重要的配置数据,例如量子比特数量、你可以运行的最大实验数量以及队列中挂起的作业数量。我们还将挖掘一些重要的量子比特参数,例如选定的后端的 T1、T2、频率和读出错误。
好的,让我们看看它是如何完成的:
-
首先导入 IBMQ 类并加载我们的账户。
-
获取所有可用和运行中的后端。
-
挖掘并打印出用于比较的后端标准,例如名称、量子比特数量、最大实验次数和挂起的作业数量。
-
选择具有五个量子比特的最不繁忙的后端。
-
打印出选定后端的量子比特属性。
你现在可以更仔细地查看后端选定的属性,例如,使用这些信息来决定你想要在哪个后端上运行你的程序。
准备工作
下一个菜谱中所需文件可从以下链接下载:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter05/ch5_r5_explore.py。
如何操作…
根据你编写的量子程序类型,后端的一些方面可能对你很重要,你可能希望在编写程序时直接包含这些方面。例如,你可能对具有最小门错误和读出错误的量子比特感兴趣,或者如果你正在运行深度电路,你可能对长的 T1 和 T2 时间感兴趣:
-
像往常一样,让我们首先导入 IBMQ 类并加载我们的账户:
from qiskit import IBMQ from qiskit.providers.ibmq import least_busy if not IBMQ.active_account(): IBMQ.load_account() provider = IBMQ.get_provider() -
获取所有可用后端。
我们将使用简单的 Python 脚本来根据不同的标准(名称、量子比特数量、每天允许的最大实验次数和挂起的作业数量)比较可用的后端。首先,我们需要一个可用后端的列表:
available_backends = provider.backends(operational=True) -
挖掘一些后端参数进行比较。
要找到参数,我们遍历列表并打印出每个后端的四个选定参数 –
name、n_qubits、max_experiments和pending_jobs:print("{0:20} {1:<10} {2:<10} {3:<10}".format("Name", "#Qubits","Max exp.","Pending jobs")) print("{0:20} {1:<10} {2:<10} {3:<10}".format("----","--- ----","--------","------------")) for n in range(0, len(available_backends)): backend = provider.get_backend(str( available_backends[n])) print("{0:20} {1:<10} {2:<10} {3:<10}". format(backend.name(), backend.configuration().n_qubits, backend.configuration(). max_experiments,backend.status().pending_jobs))上述代码可能给出以下结果:
![图 5.13 – 显示选定参数的可用后端]
](https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_5.13_B14436.jpg)
图 5.13 – 显示选定参数的可用后端
-
现在,我们可以深入了解并查看一些最不繁忙的后端(具有五个量子比特)的可用量子比特数据,例如 T1 和 T2 热退相干值、频率和量子比特的读出错误。
对于这个练习,我们可以编写另一个简单的 Python
for循环来打印后端量子比特的属性,例如名称、值和相关的数据条目单位。我们将遍历后端的量子比特数量(
least_busy_backend.configuration().n_qubits)以及每个量子比特的属性参数数量(len(least_busy_backend.properties().qubits[0])):least_busy_backend = least_busy(provider.backends( n_qubits=5,operational=True, simulator=False)) print("\nQubit data for backend:", least_busy_backend.status().backend_name) for q in range (0, least_busy_backend.configuration().n_qubits): print("\nQubit",q,":") for n in range (0, len(least_busy_backend. properties().qubits[0])): print(least_busy_backend.properties().qubits[q] [n].name,"=",least_busy_backend.properties(). qubits[q][n].value, least_busy_backend.properties() .qubits[q][n].unit)上述代码应给出类似于以下的结果:
图 5.14 – 选定后端的量子比特详细信息
这样,我们突然对量子比特有了更多的了解。它们不再是逻辑实体,而是具体的物理对象,尽管这些物理对象表现出量子行为。在第八章的“用 Ignis 清理您的量子行为”菜谱中,即[比较芯片上的量子比特],我们将探讨如何在您的程序中使用backend.properties().gates信息。
更多…
在这个菜谱中,我们查看了一组选定的后端和量子比特属性。使用 Qiskit®,您可以通过以下方法挖掘更多信息:
-
backend.configuration()backend_namebackend_versionn_qubitsbasis_gatesgateslocalsimulatorconditionalopen_pulsememorymax_shots -
backend.status()backend_namebackend_versionoperationalpending_jobsstatus_msg -
backend.properties()backend_namebackend_versionlast_update_datequbitsgatesgeneral小贴士
要打印出每个方法的所有值的完整列表,请使用
to_dict()参数。例如:backend.configuration().to_dict()
尝试修改示例代码以查找特定的参数,如下所示:
-
后端名称
-
后端可用的基本门
-
指定单个量子比特如何通信的量子比特耦合图
-
后端中门及其属性的列表
第六章:第六章:理解 Qiskit® 量子门库
在本章中,我们将探索 Qiskit® 提供的量子门。通过包含一个具有最常见门的量子门库,Qiskit® 使编写电路变得容易。
我们将要探讨的门中包括用于基本量子比特翻转的泡利 X、Y 和 Z 门,用于创建量子比特叠加的 H(或哈达玛)门,以及用于创建量子纠缠的 CX(控制非)门。为了快速复习,请查看 第四章,从 Terra 的基础开始。
我们还将探讨专门的 S 和 T 门,使用 R 门旋转我们的量子比特,然后展示如何仅使用最小的一组 U1、U2、U3、ID 和 CX 基础门来转换其他门,以便直接在量子计算机上使用。
我们将简要介绍多量子比特门,并最终以对 Qiskit® 程序中我们串出的简单门如何被编译器转换成更复杂的基门集的简要了解来结束我们的参观,这样我们才能在真实的量子计算机上运行它们。
在本章中,我们将涵盖以下内容:
-
可视化量子门
-
使用泡利 X、Y 和 Z 门进行翻转
-
使用 H 门创建叠加态
-
使用相位移位门 S、S†、T 和 T† 进行固定的 Z 旋转
-
使用 Rx、Ry 和 Rz 在轴周围进行自由旋转
-
使用基础门 – U1、U2、U3 和 ID 构建我们的电路
-
在 2 个量子比特上使用门
-
在超过 2 个量子比特上使用门
-
你的量子电路真正看起来是什么样子
在这些菜谱中,你将接触到量子门单位矩阵和量子比特状态向量,这些我们在 第二章,使用 Python 进行量子计算和量子比特中的“快速介绍量子门”菜谱中从数学上进行了讨论。如有需要,请随时返回并再次测试数学。
技术要求
本章中讨论的量子程序可以在以下链接找到:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/tree/master/Chapter06。
可视化量子门
为了帮助我们理解量子门,我们可以使用 ch6_r1_quantum_gate_ui.py 示例程序。
这个菜谱与我们所看到的略有不同。到目前为止,我们主要只是在 Python 包装器内使用 Qiskit® 命令,没有进行任何实际的编码。这次,我们首先构建了一个基本的 Python 实现,以创建一个非常基本的 门探索前后界面。当你运行程序时,它会提示你选择一个初始量子比特状态和一个要应用于量子比特的门;然后它创建一个可视化来显示门对量子比特的作用。
脚本为您构建电路,然后显示支持门、状态向量和对应于门操作的布洛赫球或 Q 球可视化的基本最小电路。可视化突出显示了门之前量子比特的状态以及门之后状态的变化。
混合经典/量子程序
因此,我们在这里做的是构建一个混合经典/量子程序,其中我们使用 Python 来驱动用户输入控制、通用逻辑和展示,并使用 Qiskit®组件来访问量子相关功能。这就是我们在接下来的章节中将要做的事情。
准备工作
在我们进入可视化器之前,让我们花一点时间讨论一些基本的量子比特状态,我们可以用这些状态初始化我们的量子比特。你们很熟悉其中两个(https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_001.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_002.png),但为了理解我们的量子比特状态向量在布洛赫球上的指向,这里快速介绍一下其余的状态,包括它们的狄拉克矢量描述和布洛赫球参考:
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_003.png:沿 z 轴直接向上
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_004.png:沿 z 轴直接向下
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_005.png:沿 + x 轴向外延伸
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_006.png:沿 - x 轴向内延伸
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_007.png:沿 + y 轴向右延伸
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_008.png:沿 - y 轴向左延伸
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.1_B14436.jpg
图 6.1 – 布洛赫球上映射的初始量子比特状态
在本食谱中,我们将探索几个有趣的 Qiskit®功能:
-
qiskit.visualization类包含各种方法来可视化您的量子比特和电路。在本食谱中,我们将使用以下方法:布洛赫球:显示单个量子比特作为布洛赫球:
plot_bloch_multivector(state_vector)Q 球:在球面上显示 1 个或多个量子比特作为状态概率向量:
plot_state_qsphere(state_vector) -
初始化:用于将量子比特初始化到特定的初始状态:
circuit.initialize(initial_vector,qubit) -
状态向量模拟器:一个 Aer 量子模拟器,用于计算量子比特的状态向量:
Aer.get_backend('statevector_simulator') -
单元模拟器:一个 Aer 量子模拟器,允许您计算量子电路的单元矩阵。如果您在只包含单个门的电路上使用此模拟器,本质上可以提取该量子门的矩阵表示:
Aer.get_backend('unitary_simulator') -
QuantumCircuit.from_qasm_str(qasm_string)方法,我们在第三章的“在两个世界之间移动”食谱中进行了探索,IBM Quantum® 经验 – 拖放量子计算。
如何做到这一点…
示例程序稍微有些复杂,但运行起来很简单。每个步骤都通过选择起始状态和门或简单的 Hit Enter(在下一步开始之前)之间的输入步骤来分隔:
-
在您的 Python 环境中运行
ch6_r1_quantum_gate_ui.py示例文件。在第一次提示时,输入您第一个量子比特的起始状态。如果您选择使用超过 1 个量子比特的门,例如 CX 门,则您在此处选择的量子比特状态是用于控制量子比特的。您的选项如下:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.2_B14436.jpg
# List our start states start_states=["1","+","-","R","L","r","d"] valid_start=["0"]+start_states -
在第二次提示时,输入您想要探索的门,例如
X:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.3_B14436.jpghttps://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.3_B14436.jpg
# List our gates rot_gates=["rx","ry","rz"] unitary_gates=["u1","u2","u3"] single_gates=["id","x","y","z","t","tdg","s","sdg","h"] +rot_gates oneq_gates=single_gates+unitary_gates control_gates=["cx","cy","cz","ch"] twoq_gates=control_gates+["swap"] all_gates=oneq_gates+twoq_gates+rot_gates+unitary_gates现在程序使用从空白电路上的示例代码中获取的
get unitary()函数来检索并打印您所选门的单位矩阵。对于 X 门,输出将类似于以下内容:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.4_B14436.jpg
图 6.4 – 第一次输出:门的单位矩阵
将此与我们在 第二章 中计算的 X 门的矩阵版本进行比较,使用 Python 进行量子计算和量子比特:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_019.jpg
我们现在已准备好程序的精华部分。
-
按 Enter 键以创建初始设置。
程序调用
qgate(gate,start)函数根据您的输入设置电路。它使用create_circuit(n_qubits,start)与门输入一起设置 1 个量子比特或 2 个量子比特的电路,然后使用qgate_out(circuit,start)函数显示空电路。在此阶段,电路将仅包括一个设置为所选起始状态的initialized量子比特,如果输入状态是 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_001.png,则我们根本不需要初始化电路。initialize()方法接受一个复数振幅向量和目标量子比特作为输入,并添加一个看起来很像门的电路指令。复数振幅必须是归一化的,在程序中,我们使用以下方式创建向量:[a * complex(1, 0), b * complex(1, 0)]。输出应该类似于以下内容:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.5_B14436.jpg
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.5_B14436.jpg
图 6.5 – 第二次输出:初始电路、状态向量和 Bloch 球
-
再次按 Enter 键以添加您所选的门并显示门应用后的最终结果。
调用
qgate(gate,start)函数的最终结果是返回完整的电路。我们现在使用qgate_out(circuit,start)函数来显示在应用门之后的最终结果。这是 X 门作用于初始化为 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_021.png 的量子比特的预期输出:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.6_B14436.jpg
图 6.6 – 第三个输出:门后的电路、状态矢量和布洛赫球体
初始运行的结果是量子比特从 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_022.png 状态开始,指向正上方,然后通过 X 门翻转至 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_002.png,指向正下方。
它是如何工作的…
在程序中,我们定义了几个运行程序 Qiskit®特定功能的函数:
-
get_psi(circuit): 这是我们之前在第四章中介绍的函数,从 Terra 开始脚踏实地,略有变化。我们不是用它直接绘制布洛赫矢量,而是设置它返回状态矢量,这样我们就可以在其他地方使用它。该函数接受一个量子电路作为输入,并使用 Qiskit Aer 提供的statevector_simulator后端返回该电路的状态矢量:def get_psi(circuit): global psi backend = Aer.get_backend('statevector_simulator') result = execute(circuit, backend).result() psi = result.get_statevector(circuit) return(psi) -
get_unitary(circuit): 这个函数接受一个量子电路作为输入,并使用 Aer 后端中的unitary_simulator返回该电路的单位矩阵:def get_unitary(circuit): simulator = Aer.get_backend('unitary_simulator') result = execute(circuit, simulator).result() unitary = result.get_unitary(circuit) return(unitary) -
create_circuit(n_qubits,start): 这个函数创建一个量子电路并将其初始化为所选的起始状态。我们首先根据用户输入设置起始向量:
1,+,-,R,L,r或d:def create_circuit(n_qubits,start): if start=="1": initial_vector = [0,complex(1,0)] elif start=="+": # Create |+> state initial_vector = [1/sqrt(2) * complex(1, 0), 1/sqrt(2) * complex(1, 0)] elif start=="-": # Create |-> state initial_vector = [1/sqrt(2) * complex(1, 0), -1/sqrt(2) * complex(1, 0)] elif start=="R": # Create state initial_vector = [1/sqrt(2) * complex(1, 0), 1*1.j/sqrt(2) * complex(1, 0)] elif start=="L": # Create state initial_vector = [1/sqrt(2) * complex(1, 0), -1*1.j/sqrt(2) * complex(1, 0)] elif start=="r": # Create random initial vector theta=random.random()*pi phi=random.random()*2*pi a = cos(theta/2) b = cmath.exp(phi*1j)*sin(theta/2) initial_vector = [a * complex(1, 0), b * complex(1, 0)] elif start=="d": a = cos(start_theta/2) b = cmath.exp(start_phi*1j)*sin(start_theta/2) initial_vector = [a * complex(1, 0), b * complex(1, 0)] else: initial_vector = [complex(1,0),0] if start!="n": print("\nInitial vector for |"+start+"\u232A:") print(np.around(initial_vector, decimals = 3))然后,我们为指定的量子比特数量创建电路,并在起始状态不是 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_001.png 的情况下初始化量子比特:
circuit = QuantumCircuit(n_qubits) if start in start_states: circuit.initialize(initial_vector,n_qubits-1) return(circuit) -
qgate_out(circuit,start): 此外,我们还使用print功能与一些 Qiskit®方法一起创建和保存我们电路和量子比特的布洛赫球表示的图像:def qgate_out(circuit,start): # Print the circuit psi=get_psi(circuit) if start!="n": print("\nCircuit:") print("--------") print(circuit) print("\nState vector:") print("-------------") print(np.around(psi, decimals = 3)) display(plot_bloch_multivector(psi)) if circuit.num_qubits>1 and gate in control_gates: display(plot_state_qsphere(psi)) return(psi) -
qgate(gate,start): 这个函数接受一个门和一个起始状态作为输入,然后从这些输入创建一个量子电路。对于单量子比特门,门被添加到第一个量子比特上,而对于双量子比特门,第二个量子比特是控制量子比特,第一个量子比特是被控制量子比特。然后它将输入门与
oneq_gates列表进行比较,并立即调用create_circuit()函数来创建一个 1 量子比特或 2 量子比特电路。在此阶段,我们还创建了正确的 1 量子比特或 2 量子比特 QASM 字符串,我们使用from_qasm_str()方法将其附加到电路中,该方法我们在第三章的在两个世界之间移动食谱中开始探讨,IBM Quantum Experience® – 量子拖放。幸运的是,我们门的 QASM 代码与门名一一对应。要添加x门,我们使用以下命令:circuit+=QuantumCircuit.from_qasm_str(qasm_string+gate+" q[0];")字符串加法在
from_qasm_string()命令中:qasm_string+gate+" q[0];"这转化为以下代码,并将
x门添加到电路中:OPENQASM 2.0; include "qelib1.inc"; qreg q[1]; x q[0];qgate()函数然后返回电路,我们可以继续:def qgate(gate,start): # If the gates require angles, add those to the QASM # code qasm_angle_gates={"rx":"rx("+str(theta)+") q[0];", "ry":"ry("+str(theta)+") q[0];", "rz":"rz("+str(phi)+") q[0];", "u1":"u1("+str(phi)+") q[0];", "u2":"u2("+str(phi)+", "+str(lam)+") q[0];", "u3":"u3("+str(theta)+", "+str(phi)+","+str(lam)+") q[0];"} # Create the circuits and then add the gate using # QASM import if gate in oneq_gates: circuit=create_circuit(1,start) qasm_string='OPENQASM 2.0; include "qelib1.inc"; qreg q[1];' else: circuit=create_circuit(2,start) qasm_string='OPENQASM 2.0; include "qelib1.inc"; qreg q[2];' qgate_out(circuit,start) if gate in oneq_gates: if gate in rot_gates+unitary_gates: circuit+=QuantumCircuit.from_qasm_str( qasm_string+qasm_angle_gates[gate]) else: circuit+=QuantumCircuit.from_qasm_str( qasm_string+gate+" q[0];") else: circuit+=QuantumCircuit.from_qasm_str( qasm_string+gate+" q[1],q[0];") return(circuit)
因此,现在您拥有了一个小程序,可以设置非常基本的单门电路,研究初始和最终状态向量,查看所选门的单位矩阵,并查看门如何使 Bloch 向量移动,并在Q-sphere上可视化,其中Bloch 球不再足够。
现在通过完成本章剩余的食谱来尝试这个程序,以探索 Qiskit®提供的量子门的基本集合。
参见
要快速直观地查看单量子比特的 Bloch 球表示以及某些门操作对其的影响,请查看 Qiskit 倡导者詹姆斯·韦弗的grok-bloch应用程序:github.com/JavaFXpert/grok-bloch。您可以从自己的 Python 环境中安装并运行它,或者在此处在线运行:javafxpert.github.io/grok-bloch/。
使用 Pauli X、Y 和 Z 门翻转
Pauli X、Y 和 Z 门都作用于单个量子比特,并执行类似于经典 NOT 门的作用,翻转经典比特的值。例如,X 门将https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_027.png发送到https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_028.png,反之亦然。
正如我们将要看到的,X 门实际上是在https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_029.png弧度下围绕x轴的旋转。对于 Pauli Y 和 Z 门也是如此,但沿着y和z轴相应地旋转。
从数学上讲,X、Y 和 Z 门可以用以下单位矩阵表示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_030.png https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_031.png https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_032.png
这个食谱将作为如何使用章节中提供的示例代码的模板。其余的食谱将主要概述更深入的细节。
让我们通过运行量子门 UI 示例程序来查看 Pauli X、Y 和 Z 门。程序首先设置一个简单的量子电路,其中包含一个从您选择的态开始的单一量子比特。然后,将选定的门添加到电路中,然后运行单位模拟器和状态向量模拟器,以显示以量子比特状态向量和门单位矩阵形式的结果。
如何操作…
-
运行
ch6_r1_quantum_gate_ui.py示例程序。 -
选择您的量子比特的起始状态。
X 和 Y 门与https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_0221.png和https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_023.png配合良好,本质上充当 NOT 门。
在https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_035.png)的情况下,X 门将不执行任何操作,但 Y 和 Z 门将创建一个https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_036.png的相移,创建https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_037.png。
还要测试https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_038.png和https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_039.png以查看它们的作用。如果您使用r(随机)或d(定义)输入,那么您可以更详细地探索门旋转。
-
当提示时,输入
x、y或z以选择要测试的门。我们在可视化量子门菜谱中测试了 X 门。现在来看看其他的。
随机起始状态的 Z 门可能会产生以下输出:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.7_B14436.jpg
图 6.7 – 随机起始状态的 Z 门
更多…
Pauli 门不能直接在量子后端上运行,但在你运行程序之前会自动转换为以下单位基门:
x(qubit) = u3(3.141,0,3.141,qubit)
y(qubit) = u3(3.141,1.571,1.571,qubit)
z(qubit) = u1(3.141,qubit)
更多信息,请参阅本章中的使用基本门构建我们的电路 – U1、U2、U3 和 ID和你的量子电路真正看起来是什么样子菜谱。
使用 H 门创建叠加
现在,让我们回顾一下我们的老朋友第四章,从 Terra 的起点开始,Hadamard或H门。这是一个相当专业的门,我们可以用它来创建一个通用的量子比特叠加。但不仅如此;我们还可以利用 H 门来改变测量轴,从通用的z(或计算)轴变为x轴,以获得对量子比特行为的更深入了解。更多内容请参阅更多内容部分。
H 门可以用以下单位矩阵表示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_040.jpg
除非你非常擅长解释矩阵运算,否则这个门会对你的量子比特做什么可能并不完全清楚。如果我们将其描述为两个量子比特旋转的组合,事情可能会变得清晰起来。当你对你的量子比特应用 Hadamard 门时,你让它经历两个旋转:首先是一个围绕y轴的https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_041.png旋转,然后是一个围绕x轴的https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_042.png旋转。
对于处于状态https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_043.png的量子比特,这意味着我们从一个北极开始,然后下降到赤道,最终到达布洛赫球上的https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_044.png位置,最后围绕x轴旋转。同样,如果您从南极https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_045.png开始,您首先上升到赤道,但在x轴的另一端,最终到达https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_046.png。
如果我们对https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_047.png进行矩阵运算,我们得到以下结果:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_048.jpg
现在我们可以使用以下狄拉克矢量表示法:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_049.jpg
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_050.png
如果我们将a和b替换为上面的https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_051.png,我们得到https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_052.png和https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_053.png,这对应于https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_044.png。
如果我们将哈达玛门应用于处于纯 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_055.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_056.png 以外的量子比特状态,我们将量子比特旋转到新的位置。
如何操作…
要探索哈达玛门,我们运行了在 可视化量子门 食谱中描述的量子门程序:
-
运行
ch6_r1_quantum_gate_ui.py示例程序。 -
为你的量子比特选择一个起始状态。
H 门与 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_057.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_058.png 配合良好,将你置于赤道上的等概率叠加状态。使用 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_059.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_060.png,H 门将等概率叠加返回到相应的计算状态,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_0221.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_023.png。尝试使用 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_063.png、https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_0391.png、随机或定义输入来更详细地探索门旋转。
-
当提示时,输入 h 选择要测试的门。将 H 门应用于 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_0221.png 将产生以下输出:
![图 6.8 – 以 |0> 为起始状态的 H 门]
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.8_B14436.jpg
图 6.8 – 以 |0> 为起始状态的 H 门
还有更多…
哈达玛门不能直接在量子后端运行,但在你运行程序之前,会自动编译成以下单位算子基门:
h(qubit)=u2(0,3.141,qubit)
如需更多信息,请参阅本章中的 使用基本门构建我们的电路 – U1、U2、U3 和 ID 以及 你的量子电路真正看起来是什么样子 两个食谱。
哈达玛门通常也用于将你的测量轴从默认(计算)z 轴更改为 x 轴。通过沿 x 轴测量,你可以检测量子比特的相位。
为了确定相位的值,你必须进行一次额外的测量,这次是沿 y 轴。为此,你使用哈达玛门与 S dagger 门结合,以将量子比特移动到 Y 轴。
你可以通过想象我们将量子比特旋转以匹配我们想要测量的轴,然后进行标准的 Z 轴测量来可视化测量基的变化。当我们沿 x 轴测量时,我们将量子比特旋转到面向 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_066.png 方向,而对于 y 轴,则指向 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_156.png 方向。
这里是需要应用于测量三个玻尔球体轴的门的组合:
沿 z 轴测量(计算基):
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.9_B14436.jpg
图 6.9 - 沿 z 轴测量
沿 x 轴测量:
图 6.10 - 沿 x 轴测量
沿 y 轴测量:
图 6.11 - 沿 y 轴测量
参见
有关沿不同轴测量量子比特相位的示例,请参阅 第九章 的 探索量子相位回冲 菜谱 [第九章,Grover 的搜索算法]。
固定 z 轴旋转与相位移位门 S、![img/Formula_06_0681.png]、T 和 ![img/Formula_06_0691.png]
S、![img/Formula_06_070.png]、T 和 ![img/Formula_06_071.png] 门都在量子比特的 z 轴周围进行旋转。这意味着当你测量量子比特时,测量结果为 1 或 0 的概率不会发生变化。发生变化的是量子比特的相位。
S 门和 T 门不是它们自己的逆
由于 S 门和 T 门在 z 轴周围进行固定旋转,它们是不可逆的。连续添加两个这样的门不会取消它们。相反,Qiskit 包含 S† 和 T† 门,它们作为逆 S 和 T 门。为了快速回顾,请参阅 第二章,使用 Python 进行量子计算和量子比特 中的 快速介绍量子门 菜谱。
从数学上讲,S 门和 T 门可以表示为以下单位矩阵:
![img/Formula_06_072.png] ![img/Formula_06_073.png] ![img/Formula_06_074.png] ![img/Formula_06_075.png]
如何做到…
要探索相位移位门,我们运行了在 可视化量子门 菜谱中描述的量子门 UI 程序:
-
运行
ch6_r1_quantum_gate_ui.py示例程序。 -
为您的量子比特选择一个起始状态。
由于这些相位移位门在 z 轴周围进行旋转,因此使用默认的 ![img/Formula_06_0221.png] 或 ![img/Formula_06_023.png] 量子比特几乎没有意义,这些量子比特是无相的。相反,选择一个叠加态量子比特,例如 +、-、L、R、r 或 d。
-
当提示时,输入
s、sdg、t或tdg以选择要测试的门。https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.12_B14436.jpg
图 6.12 – 具有起始状态 ![img/Formula_06_079.png] 的 S 门
更多…
相位移位门不能直接在量子后端上运行,但在你运行程序之前会自动编译成以下单位基门:
s(qubit) = u1(1.570,qubit)
sdg(qubit) = u1(-1.570,qubit)
t(qubit) = u1(0.785,qubit)
tdg(qubit) = u1(-0.785,qubit)
更多信息,请参阅本章的 使用基本门构建我们的电路 – U1、U2、U3 和 ID 和 你的量子电路真正看起来是什么样子 菜谱。
在轴周围进行自由旋转的 Rx、Ry 和 Rz
虽然所有相移门都围绕 z 轴旋转以改变量子比特的相位,但旋转门在布洛赫球的相应轴周围进行旋转。Rx 和 Ry 在相位角 (https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_080.png) 0 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_081.png 处旋转量子比特 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_015.png 角度,而 Rz 围绕 Z 旋转,特殊情况为 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_082.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_083.png,对应于 S 和 T 门。
R 门不是它们自己的逆
由于 R 门在 X、Y 或 Z 轴周围执行自由旋转,它们是不可逆的。连续添加两个这样的门不会抵消它们。为了快速回顾,请参阅第二章中的快速介绍量子门菜谱,使用 Python 进行量子计算和量子比特。
从数学上讲,R 门可以用单位矩阵表示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_084.jpghttps://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_085.jpghttps://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_086.jpg
如何做到…
要探索相移门,我们运行了在可视化量子门菜谱中描述的量子门程序:
-
运行
ch6_r1_quantum_gate_ui.py样本程序。 -
为你的量子比特选择一个起始状态。
R 门在相应的轴周围执行任意旋转。
由于所有这些门都在相应的轴周围进行旋转,请玩转 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_087.png 以获得对旋转位置的感觉。然后使用随机或定义来测试,以探索更多奇特的旋转。
-
当提示时,输入
rx、ry或rz以选择要测试的门。 -
输入旋转的角度 (https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_088.png)。设置为 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_089.png 旋转的 Rx 门在 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_090.png 上,应该产生以下输出:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.13_B14436.jpg
图 6.13 – Rx 门以 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_091.png 角度与 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_092.png 起始状态旋转
现在,再次使用不同的旋转角度进行测试,通过输入以下值来观察 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_093.png 和/或 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_094.png 角度的行为:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_095.jpghttps://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_096.jpghttps://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_097.jpg
更多内容…
保罗门不能直接在量子后端上运行,但在你运行程序之前会自动编译成以下单位基门:
rx(,qubit) = u3(,-1.507,1.507,qubit)
ry(,qubit) = u3(,0,0,qubit)
rz(,qubit) = u1(,qubit)
更多信息,请参阅本章中的使用基门构建我们的电路 – U1、U2、U3 和 ID和你的量子电路真正看起来是什么样子菜谱。
使用基门构建我们的电路 – U1、U2、U3 和 ID
让我们从探索我们在 第五章 中认识的三个门开始,使用 Qiskit® 探索 IBM Quantum® 硬件。你不会在你的量子程序中使用这三个基础门,U1、U2 和 U3,但是当你在量子计算机上运行电路时,它们作为所有其他单量子比特门的构建块。实际上,每个其他单量子比特门都可以只用 U3 门来表示。没有明确阻止你使用它们,但我们在后续食谱中将要介绍的门集合涵盖了我们需要的所有内容。
U 门不是它们自己的逆
由于 U 门在 x、y 和 z 轴周围进行自由旋转,它们通常是不可逆的。连续添加两个这样的门不会取消它们,除非旋转的总和是完整的旋转。为了快速回顾,请参阅 第二章 中的 A quick introduction to quantum gates 食谱,使用 Python 进行量子计算和量子比特。
如果你还记得我们在 第五章 中探索 IBM Quantum® 后端时的情况,使用 Qiskit® 探索 IBM Quantum® 硬件,我们使用以下命令查看硬件后端可用的所谓 基础门:
backend.configuration().basis_gates
返回的结果如下:
['u1', 'u2', 'u3', 'cx', 'id']
CX 和 ID 门是你在程序中使用的普通门,UX(受控非)用于创建纠缠,ID 用于运行一个不改变量子比特状态的门(关于这些内容稍后会有更多介绍)。U1、U2 和 U3 门则有所不同。
记得从 第二章 中,使用 Python 进行量子计算和量子比特,我们如何将量子门视为在 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_104.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_105.png 角度周围的旋转。这正是 U 门所做的事情,分别有一个、两个和三个输入。实际上,单量子比特 U 门旋转和 CNOT 门构成了量子计算的通用门集。在这里,Id 门是旋转的特殊情况,完全没有旋转。
基础门的关键在于,你可以直接在硬件上使用它们来编程你的量子比特。所有其他门都会被转换为基础门,然后按照你将在讨论编译器时看到的方式执行。
U3 门
U3 门实际上是量子门的瑞士军刀。它是量子比特操作的基单位矩阵。可以完成的每个单量子比特操作都可以使用 U3 门来完成,它可以表示为以下单位矩阵:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_106.jpg
三个角度如下:
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_093.png = 与状态向量之间的极角 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_0221.png
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_109.png = 从 x 轴的纵向角度 (https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_078.png)
-
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_111.png = 量子比特的总相位角(在 Bloch 球上不可见)
U2 门和 U1 门基本上是 U3 门的专业化,就像其他量子门是 U 门的一般专业化一样。
U2 门
使用 U2 门,您可以同时操作两个角度。U2 门与具有https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_112.png的 U3 门相同。
U2 门可以用以下单位矩阵表示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_113.jpg
U1 门
使用 U1 门,您可以在z轴周围旋转量子比特的相位。U1 的一个特殊情况是 Rz 门,它具有相同的输入。U1 门与具有https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_114.png和https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_115.png的 U3 门相同。
U1 门可以用以下单位矩阵表示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_116.jpg
使用这三个门,您可以执行所有可能的单量子比特操作。它们在阅读上并不那么用户友好,因此 Qiskit®包括所有相关量子门的翻译,以方便您的编程。然而,当您运行电路时,所有门都被翻译成所选后端支持的基门集合。
Pauli Id 门是一种特殊的门,它使量子比特保持其原始状态。该门可以用以下矩阵表示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_117.png = https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_118.png.
准备工作
在这个菜谱中,我们使用 Pillow 包来创建、保存和合并图像。有关 Pillow 的更多信息,请参阅pypi.org/project/Pillow/.
安装 Pillow
如果您需要在环境中安装 Pillow,可以使用以下命令:
(环境名称) … $ pip install --upgrade pip
(环境名称) … $ pip install --upgrade Pillow
如何操作…
在这个菜谱中,我们将可视化 U 门在 Bloch 球上的旋转。如您所知,我们可以使用plot_bloch_multivector()和plot_state_qsphere()方法来可视化我们的状态矢量的行为以及可能的输出。这两个方法都提供了在某一时刻量子比特和特定角度集的 U 门的静态视图。
在示例程序中,您输入 U 门的角输入,然后程序在 0 和给定分辨率的角度之间进行快照,并生成一个动画 GIF,显示量子比特状态矢量在 Bloch 球上的移动。
注意,这个动画并没有真正展示您应用门时量子比特矢量的移动方式,而是展示了如何使用 U 门将量子比特状态矢量定位到您想要的位置:
-
首先,在你的 Python 环境中运行
ch6_r2_u_animation.py脚本。 -
在提示下,输入你想要测试的门类型,然后输入该门所需的输入角度。对于 U3 门,你的输入可能如下所示,对于 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_119.png:
Animating the U gates --------------------- Enter u3, u2, or u3: u3 Enter : 1.57 Enter : 3.14 Enter : 0 Building animation...在后台,我们现在调用
create_images()函数,该函数接收你提供的输入,然后迭代创建一系列电路,这些电路迭代应用你选择的 U 门,输入角度被分成更小的角度,这由 steps 参数决定。然后,每个电路通过我们在第一个菜谱“可视化量子门”中创建的get_psi()函数中的状态向量模拟器运行,并最终使用plot_bloch_multivector()和plot_state_qsphere()将其保存为 Bloch 球图像和 Q 球图像。这些图像持续追加到两个列表中,稍后将合并成动画。这就是我们构建函数的方法。
首先,设置输入参数和所有内部函数变量:
def create_images(gate,theta=0.0,phi=0.0,lam=0.0): steps=20.0 theta_steps=theta/steps phi_steps=phi/steps lam_steps=lam/steps n, theta,phi,lam=0,0.0,0.0,0.0然后创建图像和动画工具:
global q_images, b_images, q_filename, b_filename b_images=[] q_images=[] b_filename="animated_qubit" q_filename="animated_qsphere"最后,根据输入参数运行图像创建循环:
while n < steps+1: qc=QuantumCircuit(1) if gate=="u3": qc.u3(theta,phi,lam,0) title="U3: \u03B8 = "+str(round(theta,2))+" \u03D5 = "+str(round(phi,2))+" \u03BB = "+str(round(lam,2)) elif gate=="u2": qc.u2(phi,lam,0) title="U2: \u03D5 = "+str(round(phi,2))+" \u03BB = "+str(round(lam,2)) else: qc.h(0) qc.u1(phi,0) title="U1: \u03D5 = "+str(round(phi,2)) # Get the statevector of the qubit # Create Bloch sphere images plot_bloch_multivector(get_psi(qc),title). savefig('images/bloch'+str(n)+'.png') imb = Image.open('images/bloch'+str(n)+'.png') b_images.append(imb) # Create Q-sphere images plot_state_qsphere(psi).savefig( 'images/qsphere'+str(n)+'.png') imq = Image.open('images/qsphere'+str(n)+'.png') q_images.append(imq) # Rev our loop n+=1 theta+=theta_steps phi+=phi_steps lam+=lam_steps -
创建并保存动画 GIF。
最后一步是创建 GIF。在这里,我们使用
save_gif(gate)函数迭代我们创建的图像列表,让 Pillow 使用我们的初始参数构建 GIF。这是我们所做的:def save_gif(gate): duration=100 b_images[0].save(gate+'_'+b_filename+'.gif', save_all=True, append_images=b_images[1:], duration=duration, loop=0) q_images[0].save(gate+'_'+q_filename+'.gif', save_all=True, append_images=q_images[1:], duration=duration, loop=0) print("Bloch sphere animation saved as: \n"+os. getcwd()+"/"+gate+"_"+b_filename+". gif"+"\nQsphere animation saved as: \n"+os. getcwd()+"/"+gate+"_"+q_filename+".gif")最终的 Python 输出可能如下所示:
Bloch sphere animation saved as: /<path_to_your_directory>/ch6/Recipes/u3_animated_qubit.gif Qsphere animation saved as: /<path_to_your_directory>/ch6/Recipes/u3_animated_qsphere.gif -
最终结果将是两个保存在你运行脚本相同目录下的动画 GIF。
现在,你可以在图像查看器或网页浏览器中打开 GIF,查看一下:
图 6.14 – 动画 GIF 的静态图像,展示 Bloch 球和 Q 球
如果你并排同步查看动画 GIF,Q 球表示法将显示在 U 门应用于其上的量子比特的相对概率和相位角。尝试不同的角度和不同的循环参数,看看你如何使动画为你所用。
如果你将角度设置在 0 到 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_123.png 的范围内,并将你的步骤设置为合理的较高数值,你可以创建出漂亮的平滑循环效果。尽管如此,你完全可以设置非常高的角度,这将导致动画中出现相当混乱的行为。祝您玩得开心!
当你使用脚本测试 U 门时,请记住以下几点:
-
U3 允许你使用两个角度,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_124.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_125.png,将量子比特向量指向 Bloch 球上的任何位置。第三个角度,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_111.png,对 Bloch 球表示没有影响。
-
U2 与 U3 相同,但将 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_015.png 设置为 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_128.png ,这会将量子比特向量放置在赤道上。
-
U1 与 U3 相同,但将 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_124.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_130.png 都设置为 0。U1 的一个特殊情况是 Rz。
更多内容…
嗯,在这种情况下,是少而不是多。本菜谱中的示例脚本将在你的本地环境中工作,但在你的 IBM Quantum Experience® 笔记本环境中效果不佳,因为你无法访问底层文件系统。
在 2 个量子位上使用门
双量子位门,如控制门,与普通单量子位门略有不同;它们允许你在量子位之间创建交互。一般来说,这相当于使用一个量子位作为控制量子位,另一个作为作用量子位。从数学上来说,这并不特别复杂,但直观上你可能需要思考一两次才能理解正在发生的事情。
准备中
我们将要接触的第一个双量子位门是我们在 第四章 中看到的控制非门,从 Terra 的基态开始。CX 门通常用于在控制量子位处于叠加态时在量子位之间创建纠缠。
当控制量子位是第二个量子位,受控量子位是第一个量子位时,CX 门可以表示为以下矩阵:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_131.jpg
这对应于以下电路:
![图 6.15 – CX 门从 q_1 到 q_0]
图 6.15 – 从 q_1 到 q_0 的 CX 门
解释这个方法的方式是运行第一个或控制量子位通过一个 Id 门,使其保持不变。第二个,或受控,量子位如果第一个量子位是 1,则应用一个 X 门。
这里有两个矩阵计算来演示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_132.jpg
在这里,第一个量子位是 1,第二个是 0。结果是两个量子位都是 1:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_133.jpg
在这里,两个量子位都是 1。结果是第一个量子位是 1,第二个是 0。
CX 门是 IBM Quantum® 后端的基本门之一。
其他 CX 矩阵
如果 CX 门的方向相反,第一个量子位作为控制量子位,矩阵将看起来像这样:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_134.png
为了让你确信,请进行计算。为了快速复习,请参阅 第二章 中的 快速量子门简介 菜谱,使用 Python 进行量子计算和量子位。
如何操作…
之前,对于单量子位门,量子门程序设置了一个只有一个量子位处于基态的简单量子电路 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_0221.png。当我们开始使用多量子位门时,程序将以两个量子位都处于 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_0221.png 的状态初始化。然后,选定的门将在电路中运行,并以量子位状态向量和门单位矩阵的形式显示结果。
要探索控制门,我们运行了可视化量子门配方中描述的量子门程序:
-
运行
ch6_r1_quantum_gate_ui.py示例程序。 -
为你的控制量子比特选择一个起始状态。
Cn 门使用单个量子比特作为控制量子比特,其他量子比特作为受控量子比特。如果控制量子比特的状态不是https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_0221.png,则会在受控量子比特上执行一些操作。
如果你想的话,可以先使用https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_0221.png进行测试——只是为了验证没有执行任何操作,并且 2 量子比特的状态没有改变。然后使用起始状态https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_139.png来创建贝尔态,就像我们在第四章中做的那样,从 Terra 的起点开始。完成这些后,尝试使用https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_140.png、随机或定义来探索其他控制状态。
-
当提示时,输入
cx、cy、cz或ch以选择要测试的门。例如,控制量子比特状态https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_078.png的 CX 门将生成以下输出:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.16_B14436.jpg
图 6.16 – CX 门与起始状态|+>
在这里,请注意,在应用 CX 门之后,Bloch 球表示没有意义。量子比特现在是纠缠的,我们无法从它们那里获取更多的单个信息。在这种情况下,我们显示 Q 球解释以供说明,其中初始 Q 球表示得到状态https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_142.png和https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_143.png的概率相等,在 X 门之后,得到https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_144.png的概率相等,这是贝尔态所预期的。
它是如何工作的…
CX 门只是许多可能的二量子比特控制门之一。在 Qiskit®中内置的其他门还包括 CY 和 CZ 门:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_145.jpghttps://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_146.jpg
或者为什么不试试受控 Hadamard 门?
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_147.jpg
另一个实用的 2 量子比特门是 SWAP 门,它交换第一个和第二个量子比特的值。在这种情况下,没有纠缠,单个量子比特保持独立:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_148.jpg
更多…
双量子比特门也可以写成基门组合的形式。例如,这是如何编码 CY 门的:
qc.u1(-1.507,0)
qc.cx(1,0)
qc.u1(1.507,0)
更多信息和测试转换其他 Cn 门,请参阅你的量子电路真正看起来是什么样子配方。
参见
《量子计算与量子信息》,第 10 周年纪念版,迈克尔·A·尼尔森与艾萨克·L·丘恩,第 4.3 节受控操作。
使用超过 2 个量子比特的门
除了单量子比特和双量子比特门之外,Qiskit® 还支持 3 个和更多量子比特的门。当我们构建第九章 “Grover 搜索算法” 中的 3 量子比特 Grover 搜索算法电路时,我们将使用其中之一,即 Toffoli 门。为了完整性,我们将包括 Fredkin 门,但不会在其他示例中使用它;请随意尝试。
本食谱中的多量子比特门分别使用 2、更多和 1 个控制量子比特:
-
Toffoli:受控受控非(CCX),它接受 2 个量子比特作为输入,如果两个控制量子比特都被设置,则翻转第三个量子比特。
-
MCX:多控制非接受多个量子比特(控制)作为输入,如果所有量子比特都被设置,则翻转受控量子比特。
(原则上)你使用的控制量子比特的数量没有限制。在 4 个或更多量子比特的 Grover 搜索算法电路中 第九章,“Grover 搜索算法”,我们通过使用 MCX 门构建了一个 4 量子比特的 CCCX 受控受控受控 门。
-
Fredkin:受控交换,(CSWAP),它接受单个量子比特作为输入,如果控制量子比特被设置,则交换其他两个量子比特。
如何做到这一点…
在你的量子程序中,使用以下示例代码来实现这些 3 量子比特门。
Toffoli
Toffoli 或 CCX 门由以下单位矩阵表示,其中第二个和第三个量子比特控制第一个量子比特:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_149.jpg
以下代码实现了 CCX 门:
from qiskit import QuantumCircuit
qc=QuantumCircuit(3)
qc.ccx(2,1,0)
print(qc)
电路看起来是这样的:
](https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.17_B14436.jpg)
图 6.17 – Toffoli 门
其他 CCX 矩阵
就像 CX 门一样,矩阵将根据你应该使用哪些量子比特来控制而有所不同。例如,这里是一个 CCX 门,其中第一个和第二个量子比特控制第三个量子比特的矩阵:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_150.png
为了说服自己,做一下计算。
MCX
MCX 门用于构建具有一个以上控制门的通用受控非门。Toffoli(CCX)门是一个特殊例子,其中这是一个已经编码的门。对于具有超过 2 个控制量子比特的受控非门,你可以使用 MCX 门。
以下代码实现了 MCX 门作为 CCCX 门,其中第二个、第三个和第四个量子比特控制第一个量子比特:
from qiskit import QuantumCircuit
qc=QuantumCircuit(4)
qc.mcx([1,2,3],0)
print(qc)
电路看起来是这样的:
图 6.18 – 3 个控制量子比特的 MCX 门(CCCX)
Fredkin
Fredkin 或 CSWAP 门由以下单位矩阵表示,其中控制第三个量子比特交换第一个和第二个量子比特:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_151.jpg
以下代码实现了 CSWAP 门:
from qiskit import QuantumCircuit
qc=QuantumCircuit(3)
qc.cswap(2,1,0)
print(qc)
电路看起来是这样的:
](https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.19_B14436.jpg)
图 6.19 – Fredkin 门
还有更多…
就像我们在本章中查看的其他门一样,Toffoli 和 Fredkin 门包含在 Qiskit® 的基本门集中。然而,它们不是基本门,这意味着它们需要使用一组基本门(如 u1、u2、u3、id 和 cx)重写。这被称为 转换,这是我们将在下一道菜谱“你的量子电路真正看起来是什么样子”中要做的。但在这里我们只是稍微提前了一点,展示了构建这些看似简单的门的复杂性。请尝试在下一道菜谱中尝试它们。
由基本门构建的 Toffoli
Toffoli 门可以在 Qiskit® 中作为一个单独的门输入,这让你相信门的执行将对应于 单个时间步,就像其他门一样:
图 6.20 – 由 10+ 个基本门构建的单个 Toffoli 门
当我们这样解开 CCX 时,我们看到事实略逊于仅仅一个时间步;单个门被转换成电路深度为 11。
由基本门构建的 Fredkin
与 Toffoli 门类似,当在硬件后端执行时,Fredkin 可能会被转换成大量基本门:
图 6.21 – 由 20+ 个基本门构建的单个 Fredkin 门
对于单个 Fredkin 门,电路深度从 1 到 22。在量子计算机上并非所有事情都容易做到。
你的量子电路真正看起来是什么样子
在 第三章,IBM Quantum Experience® – Quantum Drag and Drop 和 第五章,使用 Qiskit® 探索 IBM Quantum® 硬件,我们提到了 u1、u2、u3、id 和 cx 的概念。我们在本章前面的菜谱中讨论了这些门,甚至列出了其他门如何作为这些门的实现或组合。
在这道菜谱中,我们将探讨电路转换的其他一些方面,例如以下内容:
-
将常用门简单地转换为基本门
-
为模拟器进行转换
-
如果你的电路与后端物理布局不匹配,则进行电路转换
单量子比特后端基本门
大多数 IBM Quantum® 后端都有以下基本门:
u1、u2、u3、id和cx。单量子比特后端(如ibmq_armonk)不需要多量子比特门(如 CX),它不包括在内。如果你将后端设置为ibmq_armonk并运行以下命令,你将得到相应的输出:>>> backend.configuration().basis_gates Out: ['id', 'u1', 'u2', 'u3']。
当我们在 IBM 量子计算机上执行量子程序时,我们的代码首先被转换成我们可以在硬件上直接执行的核基本门(u1、u2、u3、id 和 cx)。
准备工作
下面的食谱中所需的文件可以从这里下载:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter06/ch6_r3_transpiler.py。
这就是我们构建 Python 示例的方法:
-
首先,我们导入所需的类和方法,包括
transpile:from qiskit import QuantumCircuit, IBMQ from qiskit.compiler import transpile from qiskit.providers.ibmq import least_busy我们还加载了我们的账户(如果需要),并使用
5个量子比特设置了一个后端:if not IBMQ.active_account(): IBMQ.load_account() provider = IBMQ.get_provider() backend = least_busy(provider.backends(n_qubits=5, operational=True, simulator=False)) -
让我们看看所选后端的基本门和耦合图。耦合图指定了双量子比特电路可能的量子比特连接:
print("Basis gates for:", backend) print(backend.configuration().basis_gates) print("Coupling map for:", backend) print(backend.configuration().coupling_map)上述代码应该产生类似于以下输出的结果:
图 6.22 – 后端的基本门和 CX 耦合图
对于单量子比特门的转换,耦合图并不重要。当我们编写使用双量子比特门的量子程序时,情况就不同了。
-
然后,我们设置
build_circuit()函数来创建一个基本电路,并根据我们想要探索的电路选择性地添加门:def build_circuit(choice): # Create the circuit qc = QuantumCircuit(5,5) if choice=="1": # Simple X qc.x(0) elif choice=="2": # H + Barrier #''' qc.x(0) qc.barrier(0) qc.h(0) elif choice=="3": # Controlled Y (CY) qc.cy(0,1) elif choice=="4": # Non-conforming CX qc.cx(0,4) else: # Multi qubit circuit qc.h(0) qc.h(3) qc.cx(0,4) qc.cswap(3,1,2) # Show measurement targets #qc.barrier([0,1,2,3,4]) #qc.measure([0,1,2,3,4],[0,1,2,3,4]) return(qc) -
最后,我们设置了
main()函数来运行电路。主函数提示输入要测试的电路,调用
build_circuit()函数,使用transpile()类转换返回的电路,然后显示结果:def main(): choice="1" while choice !="0": choice=input("Pick a circuit: 1\. Simple, 2\. H + Barrier, 3\. Controlled-Y, 4\. Non-conforming CX, 5\. Multi\n") qc=build_circuit(choice) trans_qc = transpile(qc, backend) print("Circuit:") display(qc.draw()) print("Transpiled circuit:") display(trans_qc.draw()) print("Circuit depth:") print("---------------") print("Circuit:", qc.depth()) print("Transpiled circuit:", trans_qc.depth()) print("\nCircuit size:") print("---------------") print("Circuit:", qc.size()) print("Transpiled circuit:", trans_qc.size()) if __name__ == '__main__': main()
如何做到这一点…
让我们构建并转换一个简单的 X 电路:
-
在你的 Python 环境中运行
ch6_r3_transpiler.py。 -
当提示时,输入
1以选择SimpleX电路:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.23_B14436.jpg图 6.23 – 首先,选择 Simple X 电路
-
这段代码应该产生类似于以下输出的结果:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_6.24_B14436.jpg
图 6.24 – 简单的单 X 门电路的输出
结果电路看起来相当相似。唯一真正的变化是 X 门现在是一个 U3 门,即基本门之一。
-
我们还可以通过提取电路及其转换电路的深度和大小来获得数值结果。
这段代码应该产生以下电路深度和大小:
图 6.25 – 电路深度和大小
在这里,深度指的是量子计算机必须执行的端到端步骤的数量。每一步可能包括一个或多个门,具体取决于电路的布局。大小只是执行的总门数。
对于这个非常简单的电路转换,变化不大。U3 门执行围绕x轴所需的旋转,电路的深度和大小保持不变。技术上,你可以在代码中使用 U3 门而不是 X 门,但这样会不太透明。
为模拟器转换?
那么,如果你尝试为模拟后端转换你的电路会发生什么?实际上,模拟器包含的基门比硬件后端要多得多,因此转换会有所不同。为了测试这一点,只需在脚本中取消以下行的注释,将后端设置为模拟器,然后再次运行程序:
backend = provider.get_backend('ibmq_qasm_simulator')
ibmq_qasm_simulator 支持以下基门:
['u1', 'u2', 'u3', 'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 't', 'tdg', 'ccx', 'swap', 'unitary', 'initialize', 'kraus']
话虽如此,你可以在运行转换器时提供额外的参数,例如 basis_gates 和 coupling_map,以定义你想要使用的基门,并指定量子比特如何连接,以便在转换多量子比特门时使用。我们在这章中不会深入探讨这一点,但可以查看 Qiskit® 帮助以获取更多信息:
>>> from qiskit.compiler import transpile
>>> help(transpile)
现在看看 还有更多 部分,看看事情如何迅速变得更加复杂。
还有更多…
这个快速配方快速展示了转换器为非常简单的量子程序做了什么,并说明了转换器如何将你的通用电路转换为可以直接在量子芯片上执行的电路。
以下快速示例说明了如果要求转换器构建与后端物理布局完全不匹配的电路,可能会遇到哪些复杂性。你可以在示例代码中测试这些电路,看看你是否得到类似的结果。
运行示例代码时,测试以下输入:
添加 H 和 H + 障碍 – 多个门和障碍电路元件
单个门的转换并不会给转换器留下太多工作要做,但一旦你添加了更多的门,事情会迅速变得更加复杂。记住,量子门通常是围绕三个轴 x、y 和 z 的旋转。如果连续添加两个门,转换器会试图通过将多个门组合成单个基门来简化电路(从而使其更短;更浅)。
在示例代码中,我们在 X 门之后添加了一个 Hadamard 门来扩展量子电路:
# Add H
qc.x(0)
qc.h(0)
当你现在运行电路时,你应该能看到类似这样的东西:
图 6.26 – 简化的转换电路
如您所见,编译器将两个门合并为一个,通过预览门组合的结果来简化并缩短电路,并将其编码为 U 门。然而,并不总是希望这种简化。例如,正如我们在第二章中“快速介绍量子门”配方中看到的,“使用 Python 进行量子计算和量子比特”,连续两个相同的量子门可能会有效地相互抵消。在某些情况下,量子电路最终可能由重复的门组成,如果移除这些重复的门,电路将无法按预期工作。
解决方案是barrier()电路组件,它阻止编译器通过合并门来简化。通过使用H + Barrier选项,我们在 X 门和 H 门之间添加一个障碍,如下所示:
# H + Barrier
qc.x(0)
qc.barrier(0)
qc.h(0)
当您使用H + Barrier选项时,您应该看到类似以下内容:
图 6.27 – 编译器不会越过障碍
现在门是逐个编译的,电路深度得到了保留。所以,没问题,对吧?嗯,这些门相当简单。当我们稍微复杂化我们的电路时会发生什么?请看下一节。
控制 Y
控制 X 门(CX)是 IBM Quantum®后端的基门,但控制 Y(CY)不是。为了创建可以在后端运行的 CY 门,编译器添加了一些额外的基门。
通过使用Controlled-Y选项,我们添加一个cy()门,如下所示:
# Controlled Y (CY)
qc.cy(0,1)
为了创建可以在后端运行的 CY 门,编译器添加了一些额外的基门:
图 6.28 – 编译 CY 门
这里编译器做了一个小技巧,在 CX 门中的 X 前后添加 Z 旋转。如果控制量子比特为 0,我们将在 z 轴周围来回旋转。如果控制量子比特为 1,我们得到 Z 轴的负四分之一旋转,X 轴的半转旋转,然后是 Z 轴的四分之一旋转,实际上相当于半转 Y 旋转。当然,Y 旋转可以用Y(qubit) = U3(https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_154.png, https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_154.png, https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_06_154.png, `qubit)``轻松完成,但由于 CX 的控制功能不能附加到 Y 门上,我们不得不进行这种重做。
让我们看看一些其他示例。这些将说明编译器如何将看似简单的量子电路转换为可以在实际 IBM Quantum®硬件上运行的基门电路。
不符合规范的 CX
在这个例子中,我们在两个物理上未连接的量子比特之间设置了一个 CX 门。如您所见,CX 是一个基本门,因此这不应该需要任何转换,对吧?但是,在这种情况下,我们迫使转换器尝试在两个未直接连接的量子比特之间构建您的电路。在这种情况下,转换器必须将您的 CX 门映射到几个中间量子比特上,这将增加电路的复杂性。在我们的示例代码中,我们构建了这个电路:
# Non-conforming CX
qc.cx(0,4)
使用不符合规定的 CX 输入运行示例代码应该产生类似于以下的结果:
图 6.29 – 在非连接量子比特之间转换 CX 门
注意这个简单的单 CX 电路突然膨胀到包含七个 CX 门。这不是最有效的编码示例。如果你查看我们正在进行转换的量子计算机的耦合图,即 IBM Quantum® Ourense,原因就一目了然。量子比特 4 不能直接与量子比特 0 通信,而必须先通过 3 和 1:
图 6.30 – IBM Quantum® 5 量子比特后端之一的物理布局
对于简单的电路,原始电路和转换电路之间没有太大差异;尝试将 CX 门从量子比特 0 连接到量子比特 1,看看你得到什么。但对于更复杂的电路,电路会迅速分化。
但等等!
对于那些像我自己一样仔细检查电路并思考如果量子比特 0 设置为 1 以触发 CX 会发生什么的挑剔者,您会注意到原始电路的结果应该是代码中的barrier和measure行,并再次运行:
# Show measurement targets
qc.barrier([0,1,2,3,4])
qc.measure([0,1,2,3,4],[0,1,2,3,4])
这应该产生以下输出:
图 6.31 – 转换器也会移动测量指令
如您从新的映射中看到的那样,量子比特 1 和 3 现在被测量为经典比特 0 和 4,正如我们所期望的。最终的测量输出将是正确的。
多门 – 结合贝尔和 CSWAP 电路
最后这个例子说明了当你试图实现一个相对简单但路径有限的目标时,会出现的复杂性。我们正在创建量子比特 0 和 4 的贝尔态,并添加一个从量子比特 3 到量子比特 1 和 2 的控制-SWAP 门,以便这些量子比特交换值:
# Multi qubit circuit
qc.h(0)
qc.h(3)
qc.cx(0,4)
qc.cswap(3,1,2)
多门输入应该给出以下结果:
图 6.32 – 一个相对简单的贝尔+CSWAP 电路的复杂转换
嗯,尝试这个相对简单的电路很快就变得糟糕起来。它的深度从 2 增加到 32。电路的大小也从最初的 4 个门增加到惊人的 43。看看所有那些 CX 门!
图 6.33 – 多门电路的深度和大小
再次,如果你看一下 图 6.33,你就可以看到为什么会发生这种情况。我们简单地连接量子位 0 和 4 在物理上是不可行的,因为量子芯片的布局。相反,这个连接需要通过量子位 1、2 和 3 的中间量子位连接链。这些额外的连接导致了单个门的数量激增。
现在尝试以下电路,看看这如何改变计数。你应该预期深度和大小都会显著缩小,因为你现在正在为可以直接相互通信的量子位编写代码。显然,在这个**噪声中等规模量子(NISQ)**时代,为你要运行的程序编写后端代码仍然很重要:
图 6.34 – 更好的符合要求的 Bell + CSWAP 电路
正如我们在本章中看到的,高质量的编程在量子计算中与在经典计算中一样重要,如果不是更重要。编译器会尽其所能将你的电路翻译到你计划运行的底层。
如果电路变得拥挤,并且你充分利用了所有的量子位,那么电路的重写可能会使执行时间超过 T1 和 T2 时间,即使电路本身构建得非常完美,在今天NISQ 计算机上也可能产生垃圾结果。
量子编程绝对是一门艺术!
第七章:第七章:使用 Aer 模拟量子计算机
到目前为止,我们主要在我们的本地 QASM 模拟器上运行我们的量子程序,它默认模拟了一个通用纠错量子计算机——量子计算界期望或至少希望在未来几年内成为现实的机器类型。
但这些令人惊叹的机器目前还不可用,因此在本章中,我们将探索量子模拟器,无论是在本地使用Qiskit Aer还是在云端的IBM Quantum®模拟器。我们将了解如何在这些模拟的完美后端上运行您的量子电路。
然而,您也可以通过为模拟器设置噪声配置文件来模拟今天的有噪声的中规模量子(NISQ)计算机,以模拟真实的 IBM Quantum®硬件,包括门错误和噪声。因此,我们也将探讨这一点。
我们还将探讨两种其他本地模拟器类型及其用途:幺正模拟器和状态向量模拟器。
在本章中,我们将介绍以下食谱:
-
理解量子模拟器的使用
-
比较 Qiskit Aer 模拟器和 IBM 量子计算机
-
将 IBM Quantum®后端的噪声配置文件添加到本地模拟器中
-
通过使用幺正模拟器理解您的电路
-
使用状态向量模拟器进行诊断
本章的目标是让您在开发和测试量子程序时能够使用模拟器,这样您就不必等待您的 IBM Quantum®后端运行测试。我们将首先探索qasm_simulator后端,然后查看幺正和状态向量模拟器。
技术要求
本章中我们讨论的量子程序可以在这里找到:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/tree/master/Chapter07。
理解量子模拟器的使用
量子计算机模拟器是一种软件程序,它模拟真实量子计算机的量子力学行为。模拟器在您在云端的 IBM Quantum®后端运行之前,在本地环境中测试您的量子电路非常有用。您还可以使用基于云的模拟器来测试可能还无法在实际量子计算机上运行或运行时间太长的较大量子电路。
在这个食谱中,我们将快速浏览可用的 Qiskit®模拟器——无论是在本地的Qiskit Aer上还是在云端的IBM Quantum®上。
准备工作
确保您从第一章,“准备您的环境”中的一切都正常工作。
这个菜谱的示例代码可以在以下位置找到:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter07/ch7_r1_aer.py。
如何做…
让我们看看代码:
-
如同往常,我们首先导入所需的类。我们导入
Aer和IBMQ,因为我们将在本地和远程使用模拟器。如果需要,我们也会加载我们的账户并获取我们的提供商:from qiskit import Aer, IBMQ if not IBMQ.active_account(): IBMQ.load_account() provider = IBMQ.get_provider() -
然后,我们使用
backends()方法查看可用的本地 Qiskit Aer 后端:backends=Aer.backends() print("\nAer backends:\n\n",backends)之前的代码应该给出以下结果:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.1_B14436.jpg
图 7.1 – 本地 Aer 后端;所有模拟器
-
我们可以将这些模拟器的配置细节存储在
simulators列表中,以供进一步处理。使用backend.configuration()方法提取这些信息,并遍历可用的后端,将每个的数据添加到列表中:simulators=[] for sim in range(0,len(backends)): backend = Aer.get_backend(str(backends[sim])) simulators.append(backend.configuration()) -
为了完整性,我们将通过将信息附加到列表中为 IBM Quantum®模拟器添加配置细节:
ibmq_simulator=provider.backends(simulator=True) simulators.append(provider.get_backend(str(ibmq_simulator[0])). simulator[0])).configuration()) -
显示原始模拟器配置细节。让我们遍历
simulators列表,打印并查看我们模拟器的可用配置细节:# Display the raw simulator configuration details print("\nSimulator configuration details:") for sim in range(0,len(simulators)): print("\n") print(simulators[sim].backend_name) print(simulators[sim].to_dict())代码应该类似于每个模拟器的以下输出:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.2_B14436.jpg
图 7.2 – 模拟器配置细节的堆叠
这原始的打印输出将产生大量需要处理的信息。在下一步中,我们将整理并显示一些用于比较的常见参数。
-
比较模拟器。
因此,每个模拟器都有大量的信息。为了进行比较,让我们抓取一些感兴趣的参数,并为每个模拟器列出它们。就我们的目的而言,以下参数可能很有趣:
ibmq_qasm_simulator的详细信息,你会看到这个非本地的 IBM Quantum®模拟器没有描述:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.3_B14436.jpg
图 7.3 – ibmq_qasm_simulator 没有描述
在代码中,我们为了完整性,使用if/elif命令为每个模拟器的local属性添加自己的描述,如果local==False则添加自己的描述:
# Fish out criteria to compare
print("\n")
print("{0:25} {1:<10} {2:<10} {3:<10}". format("Name","#Qubits","Max shots.","Description"))
print("{0:25} {1:<10} {2:<10} {3:<10}". format("----","-------","--------","------------"))
description=[]
for sim in range(0,len(simulators)):
if simulators[sim].local==True:
description.append(simulators[sim].description)
elif simulators[sim].local==False:
description.append("Non-local IBM Quantum simulator")
print("{0:25} {1:<10} {2:<10} {3:<10}". format(simulators[sim].backend_name,
simulators[sim].n_qubits, simulators[sim].max_shots, description[sim]))
之前的示例代码将产生以下类似的结果:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.4_B14436.jpg
图 7.4 – 选择模拟器属性列表
从这个列表中,我们可以获得模拟器能做什么以及每个的具体标准的概述:
qasm_simulator:这个模拟器允许你运行你的量子程序,并返回结果,就像你在一个完美的量子计算机上运行一样,没有错误和噪声,但可以选择添加错误和噪声配置文件来模拟 NISQ 后端。这个模拟器是用 C++ 编写的,并在你的本地机器上运行。
statevector_simulator:使用这个模拟器,你可以在电路的任何位置模拟你的量子比特的状态向量。这个模拟器是用 C++ 编写的,并在你的本地机器上运行。
unitary_simulator:使用这个模拟器,你可以计算电路的单位矩阵。这个模拟器是一个本地 Python 模拟器。
pulse_simulator:这是一个基于脉冲的哈密顿模拟器,用于脉冲 Qobj 文件。使用这个模拟器,你可以通过基于脉冲的编程直接与后端量子比特交互进行测试,从而绕过标准门。
ibmq_qasm_simulator:这是该组中唯一的非本地模拟器。它的工作方式与本地 qasm_simulator 模拟器类似,但性能更高。
我们现在知道了我们可以使用哪些模拟器来工作,我们将在本章中进一步探讨它们。我们将不会触及的唯一模拟器是 pulse_simulator,因为使用这个模拟器超出了本书的范围。如果你感兴趣,请查看食谱末尾的 深入真实量子硬件核心 链接。
还有更多…
查看两个 QASM 模拟器的性能数据——量子比特数量和最大射击次数。它们都允许你玩大约 30 个量子比特,并且每次运行都可以进行数千次射击。那么,它们之间有什么区别呢?
在运行模拟器时需要记住的一点是,它们正在模拟量子计算机——正是我们期望在未来能够解决复杂问题的量子计算机。这本质上意味着在像你的这样的经典计算机上模拟量子计算机,每增加一个量子比特,其复杂性大约会增加两倍。
对于在线的 ibmq_qasm_simulator 模拟器,由于它运行在 IBM POWER9™ 服务器上,这是一台相当庞大的硬件设备,因此这并不一定是一个大问题。你可以向它投递规模相当大的量子程序,高达 32 个量子比特,而不会有任何问题。
相比之下,你自己的硬件则是另一回事。本地 qasm_simulator 模拟器的性能将取决于你运行它的硬件。当你开始感觉到本地机器上的延迟和缓慢时,可能就是时候使用在线的 ibmq_qasm_simulator 模拟器了。
另请参阅
-
《一个用于量子电路的开源高性能模拟器,IBM 研究博客》,2018 年 5 月 1 日:
www.ibm.com/blogs/research/2018/05/quantum-circuits/ -
《深入真实量子硬件核心,IBM 研究博客》,2019 年 12 月 12 日:
www.ibm.com/blogs/research/2019/12/qiskit-openpulse/ -
IBM Power 系统:
www.ibm.com/it-infrastructure/power
比较 Qiskit Aer 模拟器和 IBM 量子计算机
在这个食谱中,我们将创建一个长的量子电路,交换两个量子比特之间的![img/Formula_07_001.png]状态。你会发现电路在你的本地 Qiskit Aer 模拟器上提供了完美的结果,但在实际的 IBM Quantum®机器上并不完全完美。
准备工作
本食谱的示例代码可以在以下链接找到:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter07/ch7_r2_ootb.py.
如何做到这一点…
这是代码,存储在ch7_r2_ootb.py文件中:
-
和往常一样,首先导入所需的类和方法,并加载你的账户:
# Import Qiskit from qiskit import QuantumCircuit from qiskit import Aer, IBMQ, execute # Import visualization tools from qiskit.tools.visualization import plot_histogram from qiskit.tools.monitor import job_monitor # Load account if not IBMQ.active_account(): IBMQ.load_account() provider = IBMQ.get_provider() -
选择要包含的 SWAP 门数量:
# Enter number of SWAP gates to include with your circuit # with (default 10) user_input = input("Enter number of SWAP gates to use:") try: n = int(user_input) except ValueError: n=10 n_gates=n -
现在我们构建一个包含一排选定数量的 SWAP 门的量子电路:
# Construct quantum circuit circ = QuantumCircuit(2, 2) circ.x(0) while n >0: circ.swap(0,1) circ.barrier() n=n-1 circ.measure([0,1], [0,1]) print("Circuit with",n_gates,"SWAP gates.\n",circ) -
在
qasm_simulator上运行电路并获取结果:# Select the QasmSimulator from the Aer provider simulator = Aer.get_backend('qasm_simulator') # Execute and get counts result = execute(circ, simulator, shots=simulator.configuration().max_shots).result() counts = result.get_counts(circ) print("Simulated SWAP counts:",counts) display(plot_histogram(counts, title='Simulated counts for '+str(n_gates)+' SWAP gates.'))
结果会显示一个提示,要求在 IBM Quantum®后端上运行相同的电路。在这里休息一下,继续阅读。
它是如何工作的…
当你在模拟器上运行这个量子电路时,它会完美模拟,我们得到了预期的完美 100%的结果:
Simulated SWAP counts: {'01': 10000}
如果你跟随以下电路,你会看到我们首先使用一个 X 门将量子比特q0设置为![img/Formula_02_029.png],然后我们交换量子比特q0和q1 10 次。我们期望最终得到的是q0在![img/Formula_07_003.png]和q1在![img/Formula_07_004.png],或者用两个量子比特的表示法,![img/Formula_07_005.png]:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.5_B14436.jpg
图 7.5 – 一个包含 10 个 SWAP 门的量子电路
小贴士
注意这里的屏障门。这些是为了指示 Qiskit®编译器不要跨越屏障进行编译,并且不要通过仅仅移除连续的 SWAP 门来简化电路,因为它们会相互抵消。为了快速回顾,请参考第三章中的抛量子硬币食谱,IBM Quantum Experience® – 量子拖放。
当运行 10 个 SWAP 门的程序时,你应该得到以下输出:
Simulated SWAP counts: {'01': 100000}
这在数字和以下条形图中都可以看到:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.6_B14436.jpg
图 7.6 – 在完美的量子计算机上经过 10 个 SWAP 门后的预期结果:01
这意味着程序运行得非常完美,我们将初始的![img/Formula_07_006.png]量子比特来回交换了 10 次,最终使量子比特回到它们开始的位置,在![img/Formula_07_007.png]。没有错误。
在未来的通用纠错量子计算机中,您将能够在整个计算过程中使用完全一致的纠错逻辑量子位运行像这样的长量子电路。默认情况下,Qiskit Aer 模拟器模拟一个无错误的通用量子计算机。
然而,当您在今天的NISQ硬件上运行相同的程序时,随着您的量子电路规模和执行时间的增长,错误开始累积。为了检查这一点,您现在可以按Enter键,并在 IBM Quantum®后端上运行电路。
我们现在导入最不繁忙的后端,具有五个量子位,并在其上运行相同的电路:
# Import the least busy backend
from qiskit.providers.ibmq import least_busy
backend = least_busy(provider.backends(n_qubits=5, operational=True, simulator=False))
print("Least busy backend:",backend)
# Execute and get counts
job = execute(circ, backend, shots=backend.configuration(). max_shots)
job_monitor(job)
nisq_result=job.result()
nisq_counts=nisq_result.get_counts(circ)
print("NISQ SWAP counts:",nisq_counts)
display(plot_histogram(nisq_counts, title='Counts for '+str(n_gates)+' SWAP gates on '+str(backend)))
之前的代码可能会产生以下结果:
Least busy backend: ibmq_vigo
Job Status: job has successfully run
NISQ SWAP counts: {'00': 1002, '10': 585, '11': 592, '01': 6013}
这在数值和随后的条形图中都可以看到:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.7_B14436.jpg
图 7.7 – 在 10 个 SWAP 门之后,一些错误已经渗透进来;我们得到的结果不是预期的 01
如您所见,QASM 模拟器的清晰结果在运行于 IBM Quantum®机器之一时变得有些模糊。您很可能会仍然得到正确结果(01)的显著峰值,但也会有大量错误结果。
更多内容…
您可能会认为 10 个 SWAP 门是一个相当小的量子电路的例子,我们不应该在这么大的电路中看到这样的错误。但是,您必须记住的是,您构建的相对简单的逻辑电路将被转译成一个可以使用后端可用的基础门运行的电路。
使用以下transpile示例来打印后端的基础门,并在转译前后检查 SWAP 电路的门深度:
# Comparing the circuit with the transpiled circuit
from qiskit.compiler import transpile
trans_swap = transpile(circ, backend)
print(trans_swap)
print("Basis gates:",backend.configuration().basis_gates)
print("SWAP circuit depth:",circ.depth(),"gates")
print("Transpiled SWAP circuit depth:", trans_swap.depth(),"gates")
之前的代码应该在 IBM Quantum®五量子位机器(如ibmq_vigo)上产生以下结果:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.8_B14436.jpg
图 7.8 – 转译后的 10 个 SWAP 门电路的外观
之前的代码示例应该会产生以下类似的输出:
Basis gates: ['u1', 'u2', 'u3', 'cx', 'id']
SWAP circuit depth: 12 gates
Transpiled SWAP circuit depth: 32 gates
当您在真实的量子计算机上运行时,每个门都会引入噪声和门错误。正如您在前面的图中所见,一个单独的 SWAP 门在转译后可能会变成三个连续的 CX 门,而连续添加 10 个这样的门会导致 30 个 CX 门。这可能导致一些潜在的大错误。请注意,转译门的数量取决于所选的后端,可能比本例中的 30 个更多。
参见
量子计算在 NISQ 时代及其之后,作者为加州理工学院信息与物质研究所和沃尔特·伯克理论物理研究所的约翰·普雷斯科尔,地址:美国加利福尼亚州帕萨迪纳,加州理工学院,91125:quantum-journal.org/papers/q-2018-08-06-79/.
将 IBM Quantum®后端的噪声配置文件添加到本地模拟器中
在本菜谱中,我们找到 IBM Quantum®后端的噪声数据,以构建一个噪声配置文件,然后在我们运行模拟器时将其添加到模拟器中。这将使模拟器表现得像真实的 NISQ 后端。
准备工作
本菜谱的示例代码可以在以下链接找到:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter07/ch7_r3_noise.py。
如何操作…
让我们看看以下代码:
-
获取可用后端的列表并选择一个进行模拟。
我们将获取一个 IBM Quantum®后端的噪声配置文件,并将其与我们的模拟器一起使用。首先,我们使用
select_backend()函数列出后端并做出选择:def select_backend(): # Get all available and operational backends. available_backends = provider.backends(filters=lambda b: not b.configuration().simulator and b.configuration().n_qubits > 1 and b.status().operational) # Fish out criteria to compare print("{0:20} {1:<10} {2:<10}".format("Name", "#Qubits","Pending jobs")) print("{0:20} {1:<10} {2:<10}".format("----", "-------","------------")) for n in range(0, len(available_backends)): backend = provider.get_backend(str( available_backends[n])) print("{0:20} {1:<10}".format(backend.name(), backend.configuration().n_qubits), backend.status().pending_jobs) select_backend=input("Select a backend ( 'exit' to end): ") if select_backend!="exit": backend = provider.get_backend(select_backend) else: backend=select_backend return(backend)上述代码可能会导致以下列表:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.9_B14436.jpg
图 7.9 – 可用的 IBM Quantum®后端列表
由于我们还将量子电路运行在后台上,您应该选择一个队列时间相对较短的,以避免等待结果的时间过长。
-
获取噪声配置文件。可以通过使用
NoiseModel.from_backend(backend)方法从后端提取噪声模型:def build_noise_model(backend): # Construct the noise model from backend noise_model = NoiseModel.from_backend(backend) print(noise_model) return(noise_model)噪声模型将根据您选择的后端而有所不同。这里展示了一个示例模型:
图 7.10 – IBM Quantum®后端的噪声模型
我们现在可以使用噪声模型和其他参数运行模拟器,将所选后端的 NISQ 特性应用于模拟器计算,并使其表现得像一个实际的物理后端,而不是一个完美的模拟器。
-
构建一个 GHZ 状态电路并在四个不同的后端上运行它。
execute_circuit()函数用于在所有后端上运行所有变体。在 Python 中,我们首先获取后端的基本门和耦合图:
def execute_circuit(backend, noise_model): # Basis gates for the noise model basis_gates = noise_model.basis_gates # Coupling map coupling_map = backend.configuration().coupling_map print("Coupling map: ",coupling_map)我们然后构建一个 GHZ 状态量子电路,在模拟器上执行它,并获取计数:
circ = QuantumCircuit(3, 3) circ.h(0) circ.cx(0, 1) circ.cx(0, 2) circ.measure([0,1,2], [0,1,2]) print(circ) # Execute on QASM simulator and get counts counts = execute(circ, Aer.get_backend( 'qasm_simulator')).result().get_counts(circ) display(plot_histogram(counts, title='Ideal counts for 3-qubit GHZ state on local qasm_simulator'))然后,我们使用噪声模型和耦合图在本地和 IBM Quantum® QASM 模拟器上执行有噪声的模拟,并获取计数:
counts_noise = execute(circ, Aer.get_backend( 'qasm_simulator'), noise_model=noise_model, coupling_map=coupling_map, basis_gates=basis_gates).result().get_ counts(circ) display(plot_histogram(counts_noise, title="Counts for 3-qubit GHZ state with noise model on local qasm simulator")) # Execute noisy simulation on the ibmq_qasm_simulator # and get counts counts_noise_ibmq = execute(circ, provider.get_ backend('ibmq_qasm_simulator'), noise_model=noise_model, coupling_map=coupling_ map, basis_gates=basis_gates).result().get_ counts(circ) display(plot_histogram(counts_noise_ibmq, title="Counts for 3-qubit GHZ state with noise model on IBMQ qasm simulator"))最后,我们在 IBM Quantum®后端上执行作业并获取计数:
job = execute(circ, backend) job_monitor(job) counts_ibmq=job.result().get_counts() title="Counts for 3-qubit GHZ state on IBMQ backend " + backend.name() display(plot_histogram(counts_ibmq, title=title))最后一步是显示所有运行的收集结果:
display(plot_histogram([counts, counts_noise, counts_noise_ibmq, counts_ibmq], bar_labels=True, legend=["Baseline","Noise on simulator", "Noise on IBMQ simulator", "IBM Q backend"], title="Comparison"))
在我们遍历这四个 GHZ 电路的执行过程中,我们将看到初始完美的模拟,它只提供输出https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_008.png或https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_009.png,概率约为 50%,是如何被错误污染的;我们得到所有可能的状态输出。
在最终输出中,我们比较所有执行与所选后端的最终执行。运行程序时您可能会看到以下一系列截图:
-
首先,我们在无噪声的模拟器上运行,得到以下输出:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.11_B14436.jpg
图 7.11 – 首次在本地模拟器上理想运行
-
然后,我们添加噪声模型并再次运行:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.12_B14436.jpg
图 7.12 – 将噪声模型添加到本地模拟器
如我们现在所看到的,我们不再得到漂亮、干净、完美的量子计算机结果,而是得到一个结果,这个结果与您在实际上运行电路时得到的结果非常接近。
-
我们再次通过在在线 IBM Quantum® QASM 模拟器上运行带有噪声模型进行测试:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.13_B14436.jpg
图 7.13 – 将噪声模型添加到 IBM Quantum® 模拟器
-
最后,我们再次运行电路,现在是在我们最初选择的后端上:
图 7.14 – 在 IBM Quantum® 后端运行电路
这次运行的结果应该与我们根据从实际 IBM Quantum® 后端推导出的噪声模型进行的模拟运行相似。
我们现在可以将所有结果合并到一个单独的图表中进行比较:
图 7.15 – 模拟器和 IBM Quantum® 后端之间的输出比较
在最终输出中,您可以看到,添加了噪声模型的模拟器在统计上至少表现得像它们所模拟的 IBM Quantum® 后端。如您所见,对于 基线 Aer 模拟,我们只得到 GHZ 状态的预期 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_008.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_009.png 结果,但对于所有其他运行,我们还得到了 噪声,如 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_059.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_060.png 等结果。
参见
Qiskit Backend Specifications for OpenQASM and OpenPulse Experiments,arXiv,IBM Research 等人,2018 年 9 月 11 日:arxiv.org/pdf/1809.03452.pdf。
通过使用单位矩阵模拟器理解您的电路
结果表明,任何仅由门组成的有效量子电路都可以被转换成一个单位矩阵,该矩阵描述了每个可能的状态向量输入的预期结果。正如您在 第二章 中所看到的,使用 Python 进行量子计算和量子比特,每个量子门本身就是一个 单位矩阵,构成完整量子电路的单位矩阵的组合本身也可以描述为 单位。
Qiskit® 允许您使用 Qiskit Aer unitary_simulator 模拟器返回与您的量子电路相对应的单位矩阵。您运行作业的方式与 qasm_simulator 作业相同。
当运行unitary_simulator时,您只运行电路一次。然后,我们可以使用返回结果上的get_unitary(qc)方法查看电路的单位算符,例如这个使用 Hadamard 门的单量子比特叠加电路:
图 7.16 – 带有一个 Hadamard 门的量子电路
该电路对应以下单位算符:
[[ 0.707+0.j 0.707+0.j]
[ 0.707+0.j -0.707+0.j]]
在更清晰的打印输出中,它将如下所示:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_014.jpg
您可能认出这是Hadamard 门矩阵,这正是它所代表的。就像这样,您可以使用单位算符模拟器返回任何有效量子电路的单位算符矩阵。这正是我们将在这个食谱中探讨的内容。
我们将创建几个简单的量子电路,并通过单位算符模拟器运行它们以获取单位算符矩阵。然后,我们将 Qiskit®单位算符与电路表示的门的组合的理论单位算符进行比较。
最后,我们在qasm模拟器上运行电路,并将结果与输入量子比特状态向量的计算进行比较,[1,0](对于单个量子比特)和**[1,0,0,0]**(对于两个量子比特),它们代表所有量子比特从状态https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_0041.png开始。
脚本包括一组我们定义的函数,用于控制电路的创建和其他需要完成的计算。
例如,我们使用circuits()函数创建三个基本的量子电路,并将它们存储在列表中以供以后使用。
在脚本中,我们还使用了两个我们自己创建的函数来处理单位算符信息:show_unitary()和calc_unitary()。
输入和函数调用由脚本末尾的main循环控制。
准备工作
该食谱的示例代码可以在以下位置找到:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter07/ch7_r4_unitary.py。
如何操作…
-
在您的 Python 环境中运行
ch7_r4_unitary.py。 -
当您首次运行脚本时,您会看到一个输入菜单:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.17_B14436.jpg
图 7.17 – 输入菜单
输入一个数字以选择要运行的电路。脚本中预定义了1至3选项,而4选项允许您从 IBM Quantum Experience®输入 QASM 代码进行测试,就像我们在第三章的在两个世界之间移动食谱中所做的那样,IBM Quantum Experience® – 量子拖放。
重要:无测量指令
如果您在量子电路中包含测量指令,您必须在提交为输入之前将其删除。如果代码包含测量电路,模拟器将因 Aer 错误而崩溃。
-
在你选择了要探索的电路之后,程序会创建我们需要的电路,并将它们作为列表返回:
def circuits(): circuits=[] # Circuit 1 - one qubit in superposition circuit1 = QuantumCircuit(1,1) circuit1.h(0) # Circuit 2 - two qubits in superposition circuit2 = QuantumCircuit(2,2) circuit2.h([0,1]) # Circuit 3 - two entangled qubits circuit3 = QuantumCircuit(2,2) circuit3.h([0]) circuit3.cx(0,1) # Bundle the circuits in a list and return the list circuits=[circuit1,circuit2,circuit3] return(circuits) -
我们现在将选定的电路发送以打印单位算符。
在
show_unitary()中,我们将后端设置为unitary_simulator并运行电路。从执行结果中检索返回的单位算符,并以矩阵形式打印:# Calculate and display the unitary matrix def show_unitary(circuit): global unit backend = Aer.get_backend('unitary_simulator') unit=execute(circuit, backend).result(). get_unitary(qc) print("Unitary matrix for the circuit:\n------------- ------------------\n",unit) -
最后,使用单位算符来计算电路的预测结果,并在
qasm_simulator上运行电路以进行比较。在
calc_unitary()函数中,我们使用返回的单位算符以及量子电路作为输入。然后我们为电路指定的量子比特数量创建一个状态向量,并使用qasm_simulator来比较计算结果与模拟结果:def calc_unitary(circuit,unitary): # Set number of shots shots=1000 # Calculate possible number of outcomes, 2^n qubits binary=int(pow(2,circuit.width()/2)) # Set the binary key for correct binary conversion bin_key='0'+str(int(circuit.width()/2))+'b' # Create a qubit vector based on all qubits in the # ground state and a results list for all # possible outcomes. vector=[1] outcomes=[format(0, bin_key)+":"] for q in range (1,binary): vector.append(0) outcomes.append(format(q, bin_key)+":") qubits=np.array(vector) # Calculate the dot product of the unitary matrix and # the qubits set by the qubits parameter. a_thru_d=np.dot(unitary,qubits) # Print the probabilities (counts) of the calculated # outcome. calc_counts={} for out in range (0,len(a_thru_d)): calc_counts[outcomes[out]]=(int(pow(abs( a_thru_d[out]),2)*shots)) print("\nCalculated counts:\n------------------\ n",calc_counts) # Automate creation of measurement gates from number # of qubits # Run the circuit on the backend if circuit.width()==2: circuit.measure([0],[0]) else: circuit.measure([0,1],[0,1]) backend_count = Aer.get_backend('qasm_simulator') counts=execute(circuit, backend_count,shots=shots). result().get_counts(qc) # Print the counts of the measured outcome. print("\nExecuted counts:\n----------------\ n",counts,"\n")总的来说,如果我们用输入 1 运行脚本,对于 单量子比特叠加态,我们将得到一个类似于以下的结果:
图 7.18 – 单量子比特叠加态输出
-
对于单量子比特叠加态,我们将创建一个仅包含 Hadamard 门的简单量子电路。这个电路的单位算符如下:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_017.jpg
-
计算结果与在 QASM 模拟器上运行电路返回的计数很好地对应。
-
现在,测试选项 2 和 3,看看稍微复杂一些的电路的单位算符是什么样的。当你觉得你对正在发生的事情有了很好的把握时,看看下一个菜谱,了解如何将任何电路作为 QASM 字符串导入。
使用状态向量模拟器进行诊断
在这个菜谱中,我们将探索状态向量模拟器,看看你如何使用它来对你的电路进行诊断,以了解你的量子比特是如何表现的。状态向量模拟器本身不是一个量子计算机模拟器,而是一个工具,它通过一次运行你的量子电路,并返回结果量子比特状态向量。由于这些是模拟器,你可以实际上使用它们来对你的电路进行诊断测试,而不会干扰它们并破坏量子状态。
你会注意到我们在显示量子比特作为 布洛赫球 之前已经使用了状态向量模拟器,但当时我们没有深入探讨。使用布洛赫球可视化在单量子比特或多量子比特可视化中效果很好,当每个量子比特都有一个可以投影到布洛赫球上的简单确定状态时。
有不同的输出——实际上,有几个——我们将涉及到。这些中的每一个都让你能够在测量之前,在电路的特定点上展示你的量子比特的状态。
所以,这是我们将会处理的。状态向量模拟器返回一个状态向量,类似于以下示例:
-
对于处于叠加态的量子比特:
[0.707+0.j 0.707+0.j] -
对于贝尔态纠缠的量子比特对:
[0.707+0.j 0\. +0.j 0\. +0.j 0.707+0.j]
用标准矩阵形式写出来,这些对应于以下:
- 处于叠加态的量子比特:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_018.png
- 一个纠缠量子比特对:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_019.jpg
我们可以尝试使用 plot_bloch_multivector() 方法来显示这些。这种可视化让你可以观察随着电路的进行,每个量子比特如何变化:
图 7.19 – 状态 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_020.png 的单量子比特
只要量子比特可以单独表示,这种方法就适用。对于纠缠量子比特,这种可视化方法就不再适用:
图 7.20 – 状态 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_021.png 的纠缠量子比特对
正如你所见,布洛赫球体并不是一个很好的纠缠可视化工具,因为量子比特不能单独描述,只能作为一个整体。对于这些更复杂的可视化,我们可以使用 plot_state_qsphere() 方法。Q-球体可视化是 Qiskit® 的独特功能,它将量子状态显示为 Q-球体上的一或多个矢量。
Q-球体显示一个圆(表示单量子比特状态)或一个球体(表示多量子比特状态),其中有一个或多个矢量代表状态。矢量的大小和尖端表示测量指示状态的概率;对于单量子比特 Q-球体,北极代表基态,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_022.png,南极代表激发态,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_0031.png,颜色表示状态的相位角:
图 7.21 – 状态 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_024.png 的单量子比特,测量 0 的概率为 100%
例如,单量子比特示例表明测量状态 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_025.png 的概率是 1(向上指的矢量),相位角是 0。你可以使用 Q-球体来可视化我们无法用布洛赫球体可视化的纠缠量子比特对:
图 7.22 – 状态 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_026.png 的纠缠量子比特对,测量 0 或 1 的概率各为 50%
在纠缠量子比特示例中,有两种可能的结果,概率相等:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_027.png(向上指的矢量)和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_028.png(向下指的矢量),两者相位角均为 0。
注意,对于双量子比特示例,你也会看到球体的赤道。赤道存在的原因是双量子比特系统有另外两种可能的结果:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_031.png 和 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_030.png。在这种情况下,结果占据了赤道上的两个相对节点:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_031.png 在左端极限处,https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_032.png 在右端:
图 7.23 – 处于 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_033.png 状态的纠缠量子比特对,测量 01 和 10 的概率均为 50%
正如我们将看到的,如果你添加更多的量子比特,Q-球将配备额外的纬度线,就像这些一样,每条纬度线代表具有相等 汉明 值的状态,或者处于状态 https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_034.png 的量子比特数量。例如,三量子比特 Q-球将有两个纬度线,每个纬度线有三个可能的节点。
单个量子比特叠加的三种类型:
-
三量子比特叠加状态向量:
[0.354+0.j 0.354+0.j 0.354+0.j 0.354+0.j 0.354+0.j 0.354+0.j 0.354+0.j 0.354+0.j] -
标准矩阵形式下的三量子比特叠加:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_035.jpg
以下结果将在 Q-球上显示:
-
北极: https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_036.png
-
第一纬度线: https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_037.png
-
第二纬度线: https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_038.png
-
南极: https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_039.png:
图 7.24 – 具有等概率( https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_040.png ,或 12.5%)所有结果节点的三量子比特 Q-球示例
好的,有了这个基础,让我们直接深入。
准备工作
该配方的示例代码可以在以下位置找到:github.com/PacktPublishing/Quantum-Computing-in-Practice-with-Qiskit-and-IBM-Quantum-Experience/blob/master/Chapter07/ch7_r5_state_vector.py。
如何操作…
对于这个配方,我们将设置一个量子电路,其中所有量子比特要么是简单的叠加,要么是所有量子比特之间的纠缠。当我们构建电路时,我们将在每个门之后进行状态向量测量,并将结果存储在列表中。然后我们将打印返回的状态向量,并将它们绘制在 Bloch 球和 Q-球上,以说明量子比特在电路执行过程中的移动情况:
-
设置量子比特的数量。
在这一步中,我们设置量子比特的数量,然后通过使用
s或e作为输入来选择构建叠加电路或纠缠电路:def s_vec(circuit): backend = Aer.get_backend('statevector_simulator') print(circuit.num_qubits, "qubit quantum circuit:\n------------------------") print(circuit) psi=execute(circuit, backend).result(). get_statevector(circuit) print("State vector for the",circuit.num_qubits, "qubit circuit:\n\n",psi) print("\nState vector as Bloch sphere:") display(plot_bloch_multivector(psi)) print("\nState vector as Q sphere:") display(plot_state_qsphere(psi)) measure(circuit) input("Press enter to continue...\n") -
可以使用以下命令选择状态向量模拟器:
backend = Aer.get_backend('statevector_simulator') -
选择该模拟器后,当你执行一个量子电路时,模拟器会一次性运行整个电路,并返回你的量子比特计算出的状态向量。对于双量子比特电路的结果应该如下所示:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.26_B14436.jpg
def measure(circuit): measure_circuit=QuantumCircuit(circuit.width()) measure_circuit+=circuit measure_circuit.measure_all() #print(measure_circuit) backend_count = Aer.get_backend('qasm_simulator') counts=execute(measure_circuit, backend_count,shots=10000).result(). get_counts(measure_circuit) # Print the counts of the measured outcome. print("\nOutcome:\n",{k: v / total for total in (sum(counts.values()),) for k, v in counts.items()},"\n")如您所见,对于一个空的双量子比特电路,我们期望以 100% 的确定性测量到 00,这可以从状态向量中看出:
https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_044.jpg
你也可以看到两个量子比特都指向https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_045.png,Q 球矢量指向https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_046.png。
-
接下来,按Return键向一个量子比特添加一个 Hadamard 门,并再次运行显示函数:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.27_B14436.jpg
图 7.27 – 两个量子比特,其中一个处于叠加状态,作为布洛赫球和 Q 球
现在,我们看到当第二个量子比特与布洛赫矢量指向https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_041.png状态叠加时,对状态矢量的影响。查看 Q 球,我们现在看到两个可能的结果,每个结果都有相同的概率:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_042.png和https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_043.png。
-
最后,再次按Return键添加第二个 Hadamard 门,并再次显示:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Figure_7.28_B14436.jpg
图 7.28 – 两个量子比特在叠加状态作为布洛赫球和 Q 球
我们现在已经一步一步地走过了我们的叠加步骤。
在最后一步,你可以看到两个量子比特的布洛赫矢量都处于https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_047.png状态,这是一个https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_048.png叠加状态。状态矢量现在如下所示:
这在最终结果中得到了反映,其中以下状态都具有相同的 25%概率,如 Q 球所示:https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_050.png。
-
你现在可以用两个量子比特再次运行电路,但选择e来选择纠缠,以查看量子比特如何一步一步地表现。
-
最后,尝试用
sp或ep作为输入运行程序,通过向最后一个量子比特添加 T 门来向你的叠加或纠缠电路添加相位角。正如你从第六章,“理解 Qiskit®门库”中回忆的那样,这将向该量子比特引入https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_051.png相位,这将反映在 Q 球输出中:
图 7.29 – 向量子比特 1 添加https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_052.png相位
再次,你可以看到以 25%的确定性预期的测量结果https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_053.png,增加了https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_054.png和https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_055.png状态具有https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_056.png相位的附加变化:
图 7.30 – 现在的结果具有https://github.com/OpenDocCN/freelearn-ds-zh/raw/master/docs/qnt-comp-prac/img/Formula_07_057.png相位
注意输出计数没有变化;给量子比特添加一个相位不会改变结果的可能性。然而,相位对于其他更复杂的量子算法可能非常有用,正如我们将在第九章,“Grover 搜索算法”中看到的。
还有更多…
在这个阶段,你可能会有一种似曾相识的感觉;你之前确实见过这个,而且你是对的。翻回到第三章中的使用电路作曲家构建量子分数配方,IBM Quantum Experience® – 量子拖放,看看我们之前讨论的检查功能。我们在该配方中讨论的是在 Qiskit®中检查你的电路的相应方法。
这是对 Qiskit®中包含的模拟器的一次快速浏览。我们简要介绍了如何在编写量子程序时使用它们的最基本示例,但只是刚刚触及了所有可用功能的一角。去探索吧,亲自试一试,看看它们如何在开发你的真实量子算法时作为工具使用。
4759



被折叠的 条评论
为什么被折叠?



