likes
comments
collection
share

《量子计算实践—Java样例》第六章:量子网络:基础知识

作者站长头像
站长
· 阅读数 61

本章内容包括:

  1. 理解量子计算机和量子网络之间的关系
  2. 创建量子网络所面临的挑战
  3. 编写一个传送算法和量子中继器

到目前为止,我们已经讨论了量子计算。计算确实是软件世界中的一个重要部分,但大多数由今天的软件开发人员开发的应用程序并不是孤立运行的。相反,应用程序通常包含不同的模块,这些模块可能不在同一台服务器上。它们通过REST接口与外部组件进行通信。它们从数据存储系统读取和写入信息。总的来说,软件是分布式的。要使一个完整的软件应用程序正常运行,关键要素之一是可靠、可预测的计算机网络。图6.1显示了一个典型的传统应用程序在网络上集成各种模块的设置。

《量子计算实践—Java样例》第六章:量子网络:基础知识

传统计算严重依赖于传统网络。同样地,量子计算可以从量子网络中受益,正如我们在本章中所学到的。

在前面的章节中,重点放在了量子计算机上。你学习了量子计算机如何管理一组量子比特,并对这些量子比特应用门操作。你创建了处理多个量子比特和门操作的小程序。所有的量子比特和门操作都局限于该程序内部。虽然我们没有做出具体的假设,但合理地假设这些量子比特位于一台量子计算机中,并且这些门操作也在这台量子计算机中,如图6.2所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

在之前的章节中,我们创建的量子程序执行所需的一切都可以包含在一台单独的量子计算机中。类似的情况也适用于我们的量子模拟器Strange。到目前为止,我们创建的所有应用程序都是在SimpleQuantumExecutionEnvironment中执行的。

预计在量子计算机上运行的大多数有用量子应用程序将需要大量的量子比特。然而,正如你在本章中将要体验的,也存在一些量子应用程序,它们可以使用少量量子比特组成的量子计算机网络运行。图6.3展示了一个由三台小型量子计算机通过量子网络连接的示例。实际上,这些小型量子计算机可能是带有一些量子功能的真实经典计算机,比如测量或操纵单个或少数几个量子比特的能力。

《量子计算实践—Java样例》第六章:量子网络:基础知识

量子网络允许量子计算机交换量子比特。因此,来自一台计算机的量子比特可以传送到另一台计算机。这听起来与经典情况相似,其中一台计算机将一个比特发送给另一台计算机。

量子网络的拓扑结构

最简单的量子网络形式是两台量子计算机之间的直接连接,如图6.4所示。在本章稍后我们会讨论一些限制,但现有的光纤连接可以用于将量子比特从一台量子计算机传输到另一台量子计算机。

《量子计算实践—Java样例》第六章:量子网络:基础知识

一个更有价值的量子网络包含多于两台量子计算机。与经典网络类似,连接的计算机数量通常意味着增加了更多的机会。添加计算机可以将重负荷计算在不同的计算实例之间分散,或者将系统与不同的输入连接起来。图6.5显示了一个可能的设置。

《量子计算实践—Java样例》第六章:量子网络:基础知识

这样的网络拓扑结构更难实现,因为它需要计算机之间的直接连接。一个典型的网络方法是使用交换机将流量定向到正确的计算机,如图6.6所示。虽然量子网络的网络拓扑结构可能看起来与经典网络的网络拓扑结构相似,但它们之间存在重要的区别。一方面,这使得实现量子网络变得更加困难,但另一方面,也带来了新的机遇。

《量子计算实践—Java样例》第六章:量子网络:基础知识

提示:其中一个最引人入胜的方面,你可以思考一下:在前面的章节中,你编写了代码展示了系统中的两个量子比特可以纠缠。量子程序的结果取决于这种纠缠。当其中一个量子比特被发送到另一台量子计算机,成为另一个量子程序的一部分时,会发生什么?

量子网络面临的障碍

在我们讨论量子网络的好处之前,我们希望适度降低期望值。在本节中,你将了解到,用于在经典网络上传送比特的典型方法并不容易适用于量子网络。在接下来的部分,你将看到这个问题可以得到解决。此外,这样做将带来巨大的新机遇,包括安全通信。

Java中的经典网络通信

在经典网络通信的典型情况下,信息从一台计算机传输到另一台计算机。让我们来看看在Java应用程序层面上,这将如何实现。

注意:在典型的Java应用程序中,开发人员使用位于Java平台的低级网络API之上的库。这些库通常提供便利的方法,用于使用诸如XML和JSON等语言或格式,轻松地将数据从一台计算机传输到另一台计算机。我们在示例中使用的低级网络API有助于我们理解信息如何从一台计算机传输到另一台计算机。

开发人员通常使用高级网络库,使他们免于编写低级代码。在大多数企业应用程序中,Java开发人员几乎不会手动创建java.net.Socket类的实例,而是使用的库会使用这些类及其相关类。同样,大多数使用量子计算编写应用程序的开发人员不直接处理实现量子通信的底层类。高级库隐藏了底层复杂性,使我们能够利用量子通信,而无需手动编写相关代码。

这样的量子网络栈的蓝图尚未最终确定。许多团体和标准化组织正在讨论类似于图6.7所示的经典栈的量子版本。其中一个有趣的倡议是量子互联网联盟(参见quantum-internet.team)。图6.8展示了由荷兰代尔夫特理工大学的Axel Dahlberg(qutech.nl)创建的量子网络栈的提案。关于该栈的更多信息可在arxiv.org/pdf/1903.09…中找到。

《量子计算实践—Java样例》第六章:量子网络:基础知识

《量子计算实践—Java样例》第六章:量子网络:基础知识

为了理解与量子网络相关的挑战和机遇,将其与经典网络进行比较会有所帮助。在ch06/classic目录中的示例中,一个主要的Java文件演示了在Java中如何进行低级别的网络通信。下面展示了相关代码。

static final int PORT = 9753;                              ❶
 
public static void main(String[] args)
                throws InterruptedException {
  startReceiver();                                         ❷
  startSender();                                           ❸
}
 
static void startSender() {
  Thread thread = new Thread(() -> {
    try {
      byte b = 0x8;
      System.err.println("[Sender] Create a connection
                          to port "+PORT);
      Socket socket = new Socket("localhost", PORT);       ❹
      OutputStream outputStream =
                   socket.getOutputStream();
      System.err.println("[Sender] Write a byte: "+b);
      outputStream.write(b);                               ❺
      outputStream.close();
      System.err.println("[Sender] Wrote a byte: "+b);     ❻
    } catch (IOException e) {
      e.printStackTrace();
    }
  });
  t.start();
}
 
static void startReceiver()
         throws InterruptedException {
 
  final CountDownLatch latch = new CountDownLatch(1);
  Thread thread = new Thread(() -> {
    try {
      System.err.println("[Receiver] Starting to listen
                     for incoming data at port "+PORT);
      ServerSocket serverSocket =
                     new ServerSocket(PORT);               ❼
      latch.countDown();
      Socket s = serverSocket.accept();                    ❽
      InputStream inputStream = s.getInputStream();
      int b = inputStream.read();                          ❾
      System.err.println("[Receiver] Got a byte "+b);      ❿
    } catch (IOException e) {
      e.printStackTrace();
    }
  });
  thread.start();
  latch.await();
}

❶ 此处定义的端口号在发送数据的线程和接收数据的线程之间共享。

❷ 接收字节的代码在一个线程上执行。

❸ 发送字节的代码在第二个线程上执行。

❹ 发送线程打开一个低级别的Java网络套接字。

❺ 发送方通过该套接字向接收方写入一个特定的字节。

❻ 传输的字节值仍可以由发送方使用(例如打印)。

❼ 接收方打开一个低级别的Java网络服务器套接字,监听传入的请求。

❽ 当服务器套接字发现一个连接时,发送方和接收方之间将创建一个直接的套接字连接。

❾ 接收方从该连接读取一个字节。

❿ 接收方打印他们接收到的字节的值。

这个应用程序的输出如下:

[Receiver] Starting to listen for incoming data at port 9753
[Sender] Create a connection to port 9753
[Sender] Write a byte: 8
[Sender] Wrote a byte: 8
[Receiver] Got a byte 8

请注意,在我们将字节发送到另一台计算机之后,我们仍然在本地拥有它的值。在Java中声明的字节内部指向我们计算机上的某个内存。当字节被传输到另一台计算机时,并不会从内存中删除。相反,操作系统的低级网络驱动程序会读取特定内存位置处字节的值,并将该值的副本发送到另一台计算机。

对于熟悉网络软件的开发人员来说,这听起来是微不足道的,事实上,在经典计算中确实如此,但当涉及到量子计算时就不再是微不足道的。为了从高层次解释这些挑战,让我们看一下你刚刚创建的Java程序的示意图,如图6.9所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

注意:该程序在同一台计算机上创建了两个线程,而图中显示了两台不同的计算机。后者当然更加真实,但在网络演示中,通常使用在同一台计算机上通过套接字进行通信的两个线程。套接字的端点由主机名和端口号组合定义。主机名对应于计算机的物理地址,而端口号对应于计算机的内部端口。对于我们的目的,只需指定一个端口号,并将通信限定在一台计算机内即可。

图6.9展示了经典网络通信中的两个主要步骤:

  1. 我们要传输的字节被复制。
  2. 字节通过网络传输到另一台计算机(在那里再次被复制)。

不幸的是,在量子计算中,这两个步骤都存在问题:

  1. 量子比特无法被复制。
  2. 量子比特不能轻易地在长距离上传输。

在接下来的几节中,我们将详细讨论这些问题。之后,我们将解释如何解决这些问题,并将其转化为机遇。

不克隆定理(No-cloning theorem)

量子计算的一个核心概念是不克隆定理(No-cloning theorem),它指出无法对一个量子比特进行精确复制。在经典计算中,你可以查看比特的值并创建一个具有相同值的新比特。通过这样做,你不会改变原始比特的值。

以下Java代码演示了如何将一个Boolean对象的值复制到另一个Boolean对象中。请注意,这在Java中可以更简单地实现,但我们想要模拟克隆行为,以便我们可以尝试将其应用于Qubit对象:

static Boolean makeCopy(Boolean source) {                     ❶
  Boolean target;
  if (source == true) {
    target = new Boolean(true);
  } else {
     target = Boolean.valueOf(false);
  }
  return target;
}
 
public static void main(String[] args) {
  Boolean tr = Boolean.TRUE;
  Boolean trueCopy = makeCopy(tr);                            ❷
  System.err.println("Source: "+tr+" and copy : "+trueCopy);
 
  Boolean fa = Boolean.FALSE;
  Boolean falseCopy = makeCopy(fa);                           ❸
  System.err.println("Source: "+fa+" and copy : "+falseCopy);
}

❶ makeCopy方法接受一个Boolean对象作为参数,并返回一个新的Boolean对象,该对象包含与传入的源参数相同的值。

❷ 复制一个包含true的Boolean对象,并打印原始对象和复制对象。

❸ 复制一个包含false的Boolean对象,并打印原始对象和复制对象。

在这段代码片段中(你可以在示例存储库的ch06/classiccopy中找到),我们有一个makeCopy方法,它接受一个Boolean对象source作为参数,并返回一个新的Boolean实例,该实例具有与source实例相同的值。当source实例包含值true时,返回的实例也将包含值true。如果source实例包含值false,则返回的实例也将包含值false。

返回的Boolean对象是一个全新且独立的对象。在应用makeCopy方法后,source实例和返回的实例的值完全相同。通过重复此过程,我们可以制作精确的副本或一系列比特。

在量子计算中也有这样的诱惑。请记住,从方程式4.3中,我们可以将一个量子比特的状态写为|0〉状态和|1〉状态的线性组合:

∣ψ >= α∣0〉 + β∣1>|ψ > = α|0〉 + β|1>ψ >= α∣0 + β∣1>

如果查看Strange模拟器中org.redfx.strange包中Qubit类的源代码,请注意该类包含以下字段:

private Complex alpha;
private Complex beta;

这些字段包含模拟器执行操作所需的量子比特信息。我们可以很容易地向Qubit类中添加一个构造函数,该构造函数执行以下操作:

public Qubit(Qubit src) {
    this.alpha = src.alpha;
    this.beta = src.beta;
}

这样做,我们就有了一个在Java中复制一个量子比特信息到另一个量子比特的方法。我们的量子应用程序可以使用它,并且我们可以编写代码在各个地方愉快地复制量子比特。然而,在真实的量子计算机上实现这一点是不可能的。因此,你的应用程序可以在Strange模拟器中复制量子比特,但它在真实的量子计算机上将无法工作。因此,在Strange中没有量子比特的复制构造函数。

在量子计算中,如果你想查看处于叠加态的量子比特的值,你必须进行测量。正如之前学到的,测量一个量子比特会破坏其叠加态,它会坍缩成其中的一个基态。因此,通过这样做,你会破坏原始的量子比特,并且没有足够的信息来创建一个具有相同值的新量子比特。让我们通过一个例子来说明这一点。

假设你有一个量子比特,在测量时有25%的概率测量为0,有75%的概率测量为1。这个量子比特的状态可以写为:

《量子计算实践—Java样例》第六章:量子网络:基础知识

记住,如果我们想获得测量结果为0的可能性,我们需要对α进行平方运算。在这种情况下,α等于1/2,因此α的平方是1/4,即25%。类似地,测量结果为1的可能性可以通过对√3/2进行平方运算得到,即3/4或75%。

接下来,假设你测量了该量子比特,并得到了值0。在这一点上,你仍然不知道该量子比特是持有值0,还是处于一个测量结果为0的25%的叠加态、测量结果为1的75%的叠加态,或者任何其他状态——除了α等于0的状态。要对该量子比特的原始状态得到准确的了解,你需要对该量子比特进行无限次的测量。然而,量子物理定律规定你只能进行一次测量。一旦进行一次测量,该量子比特将不再处于叠加态,信息将被丢失。简而言之,你无法重新构建概率,而这正是在谈论量子比特时重要的数字。

注意:不克隆定理与量子物理直接相关。使用软件方法,我们可以很容易地规避这一点,但那时你的应用程序只能在模拟器上运行,而不能在真正的硬件上运行。

量子比特的不克隆特性带来了许多挑战:

  1. 无法通过复制和传输来将量子比特从一处发送到另一处。
  2. 网络交换机和信号中继器的概念需要对比特进行读取、可能是放大,并重新放在另一根导线上。如果我们无法复制量子比特,我们如何处理这些网络要求?

另一方面,克隆特性带来了有趣的机遇。例如,无法在量子通信信道上进行窃听而不被通知。当攻击者想要拦截从A发送到B的量子比特时,他们必须对量子比特进行测量。结果,原始量子比特中的信息消失,接收方会知道出现了问题。我们将在后面的章节讨论这个机遇,但我们首先要解决一些问题。

在第6.4节中,您将学习如何规避不克隆定理带来的问题。您将创建一个量子电路,允许您将一个量子比特中的信息发送到另一个量子比特中。

在转移量子比特方面的物理限制

让我们从一些好消息开始:量子比特可以通过多种现有的物理通信渠道进行传输。量子比特可以由光子表示,这些光子可以通过现有的光纤或卫星连接进行传输。这很有趣,因为这意味着电信公司在经典物理通信基础设施上的投资可以在很大程度上用于量子通信。

不好的消息是,在长距离上保持量子比特的状态是困难的。光子在光纤电缆上传输的距离越长,出现错误的可能性就越大。目前,可以覆盖的最大距离在100公里左右。这足够实用,但不足以实现长距离连接而无需额外解决方案。

如果我们想通过现有的光纤在长距离上发送量子比特,我们需要以某种方式连接不同的段,并使量子比特从一个段的末尾传输到下一个段的开头,如图6.10所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

乍一看,这个问题可能看起来类似于经典通信中的现有情况:当使用信号通过物理连接传输数据时,信号会变弱(信噪比降低)而传输。在某个时候,信号需要被放大,以再次增加信噪比。这是通过使用中继器来实现的。

然而,量子通信的问题在于我们不能简单地使用传统的中继器,因为那样会以某种方式测量量子比特并放大它。但通过测量量子比特,它所携带的信息将消失。因此,我们需要一种不同类型的中继器:量子中继器。当前的技术已经允许我们创建这样的量子中继器,可以预期在未来几年内这些对于真正的长距离量子网络至关重要的组件将会可用。在第6.5节,您将编写一个软件解决方案,允许创建一个量子中继器。

Pauli-Z门和测量

在我们能够着手解决前一节中描述的障碍的量子算法之前,我们需要引入一个新的门,并且需要花一些时间来了解量子程序中测量的含义。我们将在即将介绍的算法中使用这个新门和测量块。

Pauli-Z门

在第3.4节中,我们介绍了Pauli-X门,通常被称为量子非门(quantum NOT gate)。在第4.3节中,我们解释了这个门可以由以下矩阵表示:

《量子计算实践—Java样例》第六章:量子网络:基础知识

这个门的一个变体是Pauli-Z门,它由以下矩阵表示:

《量子计算实践—Java样例》第六章:量子网络:基础知识

如果您想知道当该门应用于量子比特时会发生什么,您需要将这个矩阵与量子比特的概率向量相乘。所考虑的量子比特表示如下:

ψ>=α∣0〉+β∣1>ψ > = α |0〉 + β |1>ψ>=α∣0+β∣1>

这对应着以下概率向量:

《量子计算实践—Java样例》第六章:量子网络:基础知识

在应用Pauli-Z门到这个量子比特后,概率向量计算如下:

《量子计算实践—Java样例》第六章:量子网络:基础知识

因此,该量子比特现在处于这个状态:

ψ>=α∣0〉–β∣1>ψ > = α |0〉 – β |1>ψ>=α∣0β∣1>

当仅应用这个门到一个量子比特时,测量0或1的概率不会改变。不要让β前面的负号混淆您:测量1的概率是-β的平方,仍然是β²。

这个门的物理相关性超出了本书的范围。但重要的是要意识到有物理方式来实现这个门,并且它对应于真实的量子物理行为,因此我们可以在软件中使用它。这个Z门的符号如图6.11所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

类似于在第5.5.2节中介绍的CNot门,在条件满足时,CNot门将有条件地应用Pauli-X门,即当控制量子比特被测量为1时。而控制-Z门(Cz)是一个双量子比特门,在控制量子比特被测量为1时,将应用Pauli-Z门。这个控制-Z门的符号如图6.12所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

测量

我们之前已经谈到过测量。在第3.1节中,我们解释了当量子比特被测量时,它将始终具有值0或值1。如果在测量之前,该量子比特处于叠加态,那么在测量后,叠加态将消失。在许多量子模拟器中,包括Strange,可以对程序中的量子比特进行测量。一旦应用了测量操作,量子比特就会被破坏,并得到一个经典比特作为结果。因此,不再可能应用与叠加相关的任何门。在Strange中,可以通过对量子比特应用测量操作来进行测量。尽管测量不是一个真正的门,但Strange提供了org.redfx.strange.gate.Measurement类,该类继承自Gate接口。原因是通过这样做,Measurement类可以从Gate接口和子类提供的功能中受益。我们使用测量操作这个术语是为了明确测量不是一个门。

当在Strange中将测量操作应用于一个量子比特时,表示量子比特流的线变成双线。测量操作本身用M标记,如图6.13所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

量子隐形传态

由于其名称,量子隐形传态是一个容易吸引注意的概念。尽管我们不会将一个人从一个物理位置传送到另一个位置,但我们将讨论的是朝着真正的量子网络迈出的一个极其重要的步骤。

量子隐形传态的目标是什么?

在本节中,您将从Alice持有的量子比特发送信息到Bob持有的量子比特。然而,Alice的量子比特仍然留在Alice那里,因此您并未在物理上转移该量子比特。然而,结果是您将一些量子信息从Alice传输到Bob。这听起来与前面几节中描述的核心问题有关:量子比特无法被复制,但是如果我们有一种方法在距离上传输其量子信息,我们将更接近一个量子网络。

接下来的章节将展示隐形传态的算法。逐步地,您将创建一个程序,使用之前讨论过的技术和门来实现量子隐形传态。可以通过数学证明即将编程的算法确实将信息从Alice传输到Bob。但是,这个证明不在本书的范围之内。您将人为地给一些初始值,以便稍后检查隐形传态是否成功。

第一部分:Alice和Bob之间的纠缠

Alice持有的量子比特在图6.14中表示为量子比特q。量子隐形传态的先决条件是Alice和Bob共享一个纠缠对的量子比特,如图6.15所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

《量子计算实践—Java样例》第六章:量子网络:基础知识

根据您在上一章学到的知识,您可以编写代码来实现这个状态。下面的代码清单展示了如何实现图6.15中的情况。

Program program = new Program(3);      ❶
Step step1 = new Step();
step1.addGate(new Hadamard(1));        ❷
Step step2 = new Step();
step2.addGate(new Cnot(1,2));          ❸
program.addStep(step1);                ❹
program.addStep(step2);

❶ 这个程序包含三个量子比特:q,要传输给Bob的量子比特;以及a和b,纠缠的量子比特。

❷ 给量子比特a添加一个Hadamard门。

❸ 给量子比特a和b添加一个CNot门。

❹ 将到目前为止创建的步骤(包括门)添加到程序中。

在图6.16中,这个代码片段的示意图如电路所示。请记住,量子比特q[0](即量子比特q)和q[1](即量子比特a)位于Alice,而量子比特q[2](即量子比特b)位于Bob。

《量子计算实践—Java样例》第六章:量子网络:基础知识

第二部分:Alice的操作

在隐形传态算法的第二部分中,Alice将让量子比特q与她纠缠的量子比特对中的成分进行交互。示意图如图6.17所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

可以通过数学证明以下步骤将信息从量子比特q传输到由Bob持有的量子比特b。然而,与其依赖于数学证据,我们在这里构建所需的代码然后进行测试。首先,Alice在她的量子比特q和她半部分的纠缠对之间应用一个CNot门。接下来,她在她的量子比特上应用一个Hadamard门。到目前为止创建的量子电路的示意图如图6.18所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

我们在量子电路中添加了两个步骤,代码中的实现如下:

Step step3 = new Step();
step3.addGate(new Cnot(0,1));       ❶
Step step4 = new Step();
step4.addGate(new Hadamard(0));     ❷
program.addStep(step3);             ❸
program.addStep(step4);

❶ 给量子比特q和a添加一个CNot门

❷ 给量子比特q添加一个Hadamard门

❸ 添加我们创建的新步骤(包括门)

在接下来的步骤中,Alice必须测量她的两个量子比特。到目前为止创建的量子电路的示意图如图6.19所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

执行这些测量所需的代码是:

Step step5 = new Step();
step5.addGate(new Measurement(0));
step5.addGate(new Measurement(1));
program.addStep(step5);

第三部分:Bob的操作

最后,基于Alice所做的测量,Bob对他的量子比特应用一些操作。如果第一个量子比特(要传输的原始量子比特)的测量结果为1,Bob会对他的量子比特应用一个Pauli-X门。如果量子比特a的测量结果为1,Bob会对他的量子比特应用一个Pauli-Z门。这些操作的流程如图6.20所示,而您创建的量子电路的示意图如图6.21所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

《量子计算实践—Java样例》第六章:量子网络:基础知识

这些有条件的步骤的代码是:

Step step6 = new Step();
step6.addGate(new Cnot(1,2));    ❶
Step step7 = new Step();
step7.addGate(new Cz(0,2));      ❷
program.addStep(step6);
program.addStep(step7);

❶ 如果量子比特q[1](即a)的测量结果为1,将Pauli-X门应用到q[2](即b)上。

❷ 如果量子比特q[0](即q)的测量结果为1,将Pauli-Z门应用到q[2]上。

这就是将信息从量子比特q传输到量子比特b所需的全部步骤。

运行程序

现在,您可以通过运行位于ch06/teleport目录下的整个程序来执行它,方法是运行: mvn javafx:run

您将会看到图6.22所示的输出结果。

《量子计算实践—Java样例》第六章:量子网络:基础知识

输出结果包含两个部分。在屏幕截图的上半部分,您可以看到包含三个量子比特的电路,右侧显示了测量得到1的概率。这个概率结果显示了以下几点:

  1. 量子比特q(表示为q[0])被测量为1的概率为50%,被测量为0的概率也为50%。
  2. 量子比特q_A(表示为q[1])被测量为1的概率为50%,被测量为0的概率也为50%。
  3. 量子比特q_B(表示为q[2])被测量为0的概率为100%。

最后一部分是最重要的。最初,量子比特q的值是0。在传输电路结束时,量子比特q的值尚未确定,但量子比特q_B的值现在是0。因此,量子比特q的信息被传输到了量子比特q_B。

同样的信息可以通过分析图6.23底部得到,该图显示了我们的量子传输程序模拟执行1,000次的统计结果。x轴显示可能的结果。第一个值000表示三个量子比特都被测量为0的情况。第二个值001表示第一个量子比特(q[0]或q)被测量为1,而其他量子比特被测量为0的情况。

提示:在图6.23的上半部分中,将量子比特与下半部分的结果相匹配是很重要的。在量子电路中,我们将索引为0的量子比特(最低有效量子比特)显示在顶部。索引最高(最重要)的量子比特显示在底部。当我们按顺序写下量子比特时,我们从最重要的量子比特开始在左侧,并以最低有效量子比特在右侧结束。

《量子计算实践—Java样例》第六章:量子网络:基础知识

在这1,000次运行中:

  • 约有250次的结果是000(因此,所有的量子比特都被测量为0)。
  • 约有250次的结果是001,这意味着量子比特q被测量为1,而量子比特q_A和q_B都被测量为0。
  • 约有250次的结果是010,这意味着量子比特q被测量为0,量子比特q_A被测量为1,而量子比特q_B被测量为0。
  • 约有250次的结果是011,这意味着量子比特q被测量为1,量子比特q_A被测量为1,而量子比特q_B被测量为0。

请注意,在所有这些情况下,量子比特q_B都被测量为0。其他量子比特可以是0或1,但量子比特q_B始终是0。

这些结果似乎表明您编写的算法确实将一个量子比特从Alice传输到了Bob。至少,当Alice的量子比特值为0时,Bob的量子比特值也是0。

如果您正确地执行了练习,那么您应该在整个传输算法开始之前,向第一个量子比特添加了一个Pauli-X门,这样Alice的量子比特在传输前处于1状态。这表明该算法在量子比特处于1状态时也有效。但是,如果它处于叠加态呢?

幸运的是,Strange可以测试这一点。在执行程序之前,您可以使用Program.initializeQubit(int index, double alpha)方法初始化量子比特的值。在此方法中,index指定我们要设置的量子比特的索引号,alpha指定我们要给alphaalphaalpha赋予的值。在调用runProgram之前,在程序中添加以下行:

program.initializeQubit(0, .4);

通过这样做,我们将原始量子比特q[0]的α值设置为0.4。测量0的概率是α的平方,这意味着测量0的概率为16%,测量1的概率为84%。

如果您运行修改后的程序,您会看到类似于图6.24所示的输出。在输出的上半部分,我们可以看到Bob的量子比特q[2]被测量为1的概率为84%。图的下半部分显示了类似的结果。这正是我们希望看到的:它显示了该算法将最初由Alice持有的量子比特中包含的量子信息传送到由Bob持有的量子比特中。再次注意,我们没有提供数学证据,这超出了本书的范围。您可以在许多在线资源中找到证据,比如Ryan LaRose的研讨会“The Quantum Teleportation Algorithm”(mng.bz/Rqav)。

《量子计算实践—Java样例》第六章:量子网络:基础知识

恭喜!您刚刚成功地将一个量子比特从一个人传送到另一个人那里!

量子通信与经典通信

需要注意的重要一点是,Alice 和 Bob 之间只有有限的量子交互。在算法的第一步中,你创建了一个纠缠对,其中一部分由 Alice 持有,另一部分由 Bob 持有。除此之外,在 Alice 和 Bob 之间并不需要其他的量子通信。无论 Bob 需要应用 Pauli-X 门、Pauli-Z 门还是不需要应用门,都取决于 Alice 进行的两次测量结果。测量结果始终是一个经典比特,因此可以通过使用经典网络传输结果。因此,量子传送算法的通信方面可以分为两个步骤:

  1. 确保 Alice 和 Bob 各自拥有属于一个纠缠对的量子比特。
  2. 通过经典通信将两次测量结果(0 或 1)从 Alice 传输到 Bob。

这在图 6.25 中示意。 《量子计算实践—Java样例》第六章:量子网络:基础知识

在这个图示中,纠缠态量子比特通过一个量子信道传输,而测量结果则通过一个经典信道传输。因此,如果我们有一个可以创建一对纠缠态量子比特的设备,并且这个设备可以将其中一个量子比特发送给Bob,我们就可以在Alice和Bob之间传输任意量子比特,而无需额外的Alice和Bob之间的量子相互作用。

量子中继器

在前面的部分,您成功地在不违反禁止克隆定理的情况下将信息从一个量子比特传输到另一个量子比特。如果我们可以传输纠缠态量子比特,我们就可以传输一个量子比特中包含的信息。

但是,如果Alice和Bob彼此距离很远(距离超过1000公里),经典数据通道不是问题。如果信噪比下降太多,可以使用经典中继器来放大信号。然而,将其中一个纠缠态量子比特从Alice发送到Bob变得极其困难。在本节中,您将为这个问题创建一个软件解决方案,该解决方案使用您在本章前面编写的代码。

我们需要使用量子中继器。量子中继器不会放大量子比特中的信号(因为那将需要我们测量它,从而破坏信息),但它可以使用相同的量子隐形传态将信息从一个段传输到下一个段,如图6.26所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

在展示创建这个量子中继器的代码之前,我们将从高层次上了解如何实现这一点。图6.15展示了相对简单的情况,其中Alice和Bob彼此靠近(也就是说,足够近,可以从Alice发送一半的纠缠对给Bob)。而图6.27则展示了在Alice和Bob之间添加了一个量子中继器的情况。

《量子计算实践—Java样例》第六章:量子网络:基础知识

在这种情况下,存在两对纠缠态:

  1. Alice和中继器共享一个纠缠态对,其包含量子比特qA和R1。
  2. 中继器和Bob共享一个纠缠态对,其包含量子比特R2和qB。

量子中继器的代码可以在示例代码存储库的ch06/repeater目录中找到。由于现在涉及到五个量子比特(一个包含要传输的信息的量子比特和两个纠缠态对的量子比特),该程序的结构如下:

Program program = new Program(5);

准备系统需要创建两对纠缠态。在量子隐形传态的代码中,纠缠态对是在代码的开头创建的。我们将扩展该代码如下所示(我们添加的行已经做了标注):

Step step1 = new Step();
        step1.addGate(new Hadamard(1));
        step1.addGate(new Hadamard(3));     ❶
        Step step2 = new Step();
        step2.addGate(new Cnot(1,2));
        step2.addGate(new Cnot(3,4));       ❷

❶ 在q[3]上添加一个Hadamard门。

❷ 在q[3]和q[4]之间添加一个CNot门。

请注意,在量子比特3上添加了一个Hadamard门,并在量子比特3和4之间添加了一个CNot门,从而在量子比特3和量子比特4之间创建了一个纠缠态对。除了这个准备步骤之外,第一部分是使用之前创建的隐形传态算法将信息从量子比特q传输到量子比特R1。第一部分的流程如图6.28所示。该代码与隐形传态算法中的代码完全相同,我们这里不再重复。

《量子计算实践—Java样例》第六章:量子网络:基础知识

原本位于Alice的量子比特q中的信息现在已经传输到了中继器的量子比特R1上。接下来,您需要重复隐形传态算法,这次将R1中的信息传输到量子比特qB。第二部分的流程如图6.29所示。

《量子计算实践—Java样例》第六章:量子网络:基础知识

所需的代码与第一部分类似,但门作用于不同的量子比特。在第一部分中,第3至7步执行了隐形传态。您需要添加第8至12步,在其他量子比特上执行类似的操作:

Step step8 = new Step();
step8.addGate(new Cnot(2,3));           ❶
Step step9 = new Step();
step9.addGate(new Hadamard(2));         ❷
Step step10 = new Step();
step10.addGate(new Measurement(2));     ❸
step10.addGate(new Measurement(3));     ❹
Step step11 = new Step();
step11.addGate(new Cnot(3,4));          ❺
Step step12 = new Step();
step12.addGate(new Cz(2,4));            ❻

❶ 在q[2]和q[3]之间添加一个CNot门。

❷ 在q[2]上施加一个Hadamard门。

❸ 测量q[2]。

❹ 测量q[3]。

❺ 如果测量结果显示q[3]为1,对q[4]施加一个Pauli-X门。

❻ 如果测量结果显示q[2]为1,对q[4]施加一个Pauli-Z门。

请注意,在示例代码存储库中的代码中,我们人为地初始化了原始量子比特(我们想要传输的那个量子比特),类似于之前的做法,以便它有16%的几率被测量为0,有84%的几率被测量为1。这是通过与量子隐形传态算法中相同的代码实现的:

program.initializeQubit(0, .4);

请注意,我们这样做只是为了使结果更易于解释。

当程序执行时,输出结果应该类似于图6.30中的输出。从这个输出结果确实清楚地表明,原本包含在Alice的量子比特q[0]中的信息已经传输到了Bob的量子比特q[4]上。

《量子计算实践—Java样例》第六章:量子网络:基础知识

总结

  • 经典网络为经典计算提供了许多优势;同样,量子网络对于量子计算也能提供重要的优势。
  • 为了实现量子网络,需要解决许多低层次的问题。目前正在进行这方面的工作,并正在讨论标准。
  • 您可以创建一个Java应用程序来模拟量子网络,并将一个量子比特从网络的一部分传输到网络的另一部分。
  • 使用Strange,您可以创建一个量子中继器,从而使您能够在更长的距离上传输量子比特。
转载自:https://juejin.cn/post/7258069406961893436
评论
请登录