今天要给大家介绍的是这本书《Programming Quantum Computers —— Essential Algorithms and Code Samples》,主要讲如何在量子计算机上编程,又示例的代码可以跑 https://oreilly-qc.github.io./ ,这本书的理解方向是纯粹计算机的,连矩阵都很少涉及,一个量子计算机就像是协处理器一样,很像我们现在的GPU。

这本书一共分为三个部分,我也将分成三篇文章来写。

量子计算机编程(一)——QPU编程

量子计算机编程(二)——QPU基础函数

量子计算机编程(三)——量子应用

单量子比特

这本书中对于量子的表达方式如下circle notation:

蓝色圈的面积就是这个量子态测量后是这个状态的概率,中间的蓝色短线代表他们的相位,因为全局相位也观察不出来,所以一般\(|0\rangle\)就是朝上的。对于一个量子比特来说,重要的也就这两个,magnitude和relative phase(可能因为重要的是概率大小,所以他其实没有提amplitude其实是一个复数)。

这两个态实际上是等价的。

电路图呢,一般长这样

这个电路图对应的代码如下:(这个例子都可以在上面那个网站上跑起来)

qc.reset(1);         // allocate one qubit
qc.write(0); // write the value zero
qc.had(); // place it into superposition of 0 and 1
var result = qc.read(); // read the result as a digital bit

第一步就是申请一个qubit,就像你要给变量分配空间一样。

第二步写0,其实写0很容易,你可以直接测量,要么0,要么1,如果结果是1的话,再做一个not操作就好;当然,你要是嫌麻烦,对于一个qubit,长时间的静置他,他也会变成0,毕竟还是基态比较稳定。

第三步就是进行一个H门的操作

第四步读,其实就是测量了

常见的作用于单量子比特操作的表达方式:

其中值得一提的是PHASE相位操作,phase操作只作用在 \(|1\rangle\) 上,因为他的效果是改变相对相位,如果大家都改变就没有什么用了。可能有同学听说过绕X轴旋转和绕Y轴旋转,这些都是针对Bloch球的表达方式,与这里的circle notation的方式不要弄混了。

一个操作也可能是其他几个操作的组合,比如:

如果我们可以把not变成H+180°旋转+H,那么我们也可以把中间的180°旋转变成两个90°的旋转,中间再加上两个H,因为\(HH=I\),他们可以相互抵消,这样我们还可以得到RNOT:

COPY:这是一个需要注意的操作,因为量子程序里没有复制,这也保障了量子传输的信息不会被窃听, 因为你要窃听,你就需要去读,一读就是测量,而量子比特一测量就是坍缩。由于量子不能复制,所以,上述所有操作都是在原有的那个比特上操作的,所以操作就会被发现。

一个简单例子:

对于这里例子来说, \(A_1\) 和 \(A_2\) 是对qubit Hadmard门操作后测量得到的随机值,因为这个是真随机,所以就不会被窃听者提前知道或者预估,那么当我传输这个被我用红色圈出来的比特的时候,spy并不知道这个比特是否执行了H门和not操作,那他就只能猜了,25%的概率,图里面所示就是他猜有执行了,然后他再按照他的猜测如法炮制一个qubit继续传递,当B收了这个bit后,B也随机一个数据\(B_2\),看是否执行H门,然后测量。这个时候消息也都收到了,测量也都测量好了,那么把 \(A_2\)的信息发过来也和窃听没有关系了,如果 \(B_2\) \(A_2\) 的结果一样,那么测量结果应该一样,如果不一样,那么一定被窃听了。

这样的成功概率有多少呢? \(B_2\) \(A_2\) 一样的概率0.5,在这种情况下spy被发现的概率0.25。看起来不是很高,但是如果我们有一百个比特先检测一下这条线路,不被发现的概率将会降到百万分之一。

现在来看一下代码:https://oreilly-qc.github.io/?p=2-4

qc.reset(3);//申请三个qubit
qc.discard();
var a = qint.new(1, 'alice'); //给其中一个变量命名为a,但是画出来的电路图中显示alice
var fiber = qint.new(1, 'fiber');
var b = qint.new(1, 'bob'); function random_bit(q) {//对一个初始化为0的比特,进行H操作,然后测量,测量结果是随机的
q.write(0);
q.had();
return q.read();
} // Generate two random bits
qc.label('get two random bits');
var send_had = random_bit(a);//得到是否执行H门的随机值
var send_value = random_bit(a);//得到是否not的随机值
qc.label(''); // Prepare Alice's qubit
a.write(0);//a重新赋值为0,所以前面取随机值的操作也可以在a上进行
qc.label('set value');
qc.nop();
if (send_value)
a.not();
qc.nop();
qc.label('');
qc.nop();
qc.label('apply had');
qc.nop();
if (send_had)
a.had();
qc.nop();
qc.label(''); // Send the qubit!
fiber.exchange(a); // Activate the spy
var spy_is_present = true;
if (spy_is_present)
{
var spy_had = 1;
qc.nop();
qc.label('spy');
if (spy_had)
fiber.had();
stolen_data = fiber.read();
fiber.write(0);
if (stolen_data)
fiber.not();
if (spy_had)
fiber.had();
qc.label('');
qc.nop();
} // Receive the qubit!
var recv_had = random_bit(b);
fiber.exchange(b);
qc.label('apply had');
qc.nop();
if (recv_had)
b.had();
qc.nop();
qc.label('');
qc.nop();
qc.label('read value');
qc.nop();
recv_val = b.read();
qc.nop();
qc.label('');
qc.nop(); // Now Alice emails Bob to tell
// him her had setting and value.
// If the had setting matches and the
// value does not, there's a spy!
if (send_had == recv_had)
if (send_value != recv_val)
qc.print('Caught a spy!\n');

多量子比特

多量子比特的表示方法和单量子比特没有什么区别,下面的数字就是把他们从01的二进制换算成了我们熟悉的十进制。0x是十六进制的表示方法,最上面的是地位,正好可以not操作表示了出来,0就是000,1就是001,2就是010……以此类推

真要说和单量子比特的区别,那主要是两方面,一个是纠缠;另一个就是受控操作。

纠缠

纠缠好说,两个纠缠的量子比特就是其中一个的测量结果会影响另一个。

具体可以看一下这篇量子纠缠1——量子比特、Bell态、EPR佯谬

受控操作

受控操作就是说有两类比特,一个是用来控制的,另一个是被控制的。

比如大家耳熟能详的CNOT,当控制比特是1的时候,就翻转被控制的比特,如果控制比特是0的时候,那就不做操作。还有CCNOT门,又叫做toffli门,有两个控制比特,只有当他们都为1的时候才翻转。

现在要介绍一个前面没有提过的CPHASE受控相位门,和CNOT相似,同样是当控制比特为1的时候才进行,但是正如前面我们提过,PHASE操作只操作在1上,也就是说,如果这个操作被执行其实只有一种情况,那就是\(|11\rangle\) 。

在前面我们表示过一个旋转180°的相位操作可以表示成一个 H+NOT+H figure 2-14

那么现在受控相位操作拥有了三种表示方法:

当控制比特为0的时候,CNOT就不会发生,两个H又正好抵消了。

phase kickback

在这之所以说这么多的受控相位操作是因为这里面有个一很有趣的小技巧 QPU Trick: Phase Kickback 来看下面这个电路图

这个电路图很容易理解,一种理解方式就是把register 1当作控制比特,register 2 当作受控比特,两个H门使得register 1变成了等可能的四种情况 \(\frac{1}{2}|00\rangle+\frac{1}{2}|01\rangle+\frac{1}{2}|10\rangle+\frac{1}{2}|11\rangle\) 。

现在来看看结果:

因为register 2并不是叠加态,所以没有相对相位,而绝对相位又测不出来,所以他可以说是没有变的,改变了的,反而是register 1 , \(|3\rangle\) 转了135°是因为两个都为1,45°和90°都转了。作为一个受控操作,控制比特反而变了,而受控比特没有改变。

swap

受控操作当然也能连在一起,得到一些有用的结果,比如三个CNOT操作,他就可以交换两条线路。

这个的证明是一件很容易的事情,你可以取一个任意态推一边,专门把这个提出来说一遍是因为这个还能做一件有趣的事情,那就是验证两个比特是否相等。我们需要用到的是CSWAP,即当控制比特为1时才交换。

当我们的output比特经过H门后,他就变成了等概率的 \(|0\rangle\) 和 \(|1\rangle\) 经过一个CSWAP,为1情况下的input1和input2就会交换,也就是说他们原来x概率的ab就变成了x概率的ba了,这样的问题出在哪?

如果概率还是原来的分布,那么在经过一个H门output等待率的 \(|0\rangle\) 和 \(|1\rangle\) 又会化简成 \(|0\rangle\) ,各种各样的 \(|1\rangle\) 的概率会相互抵消掉,那么在经历一个NOT操作就一定会得到1。

那,如果这两个数据不一样,就一定得不到1吗?不一定,只是他有概率不是1,而一旦有概率不是1,那只要多检测几次就一定能检测出来,就像上面那个窃听一样,明明只有四分之一的概率,但仅需要一百次,测不出来的可能性就降到了百万分之一。

当然,代码在这里https://oreilly-qc.github.io/?p=3-4,这也是这本书的特色了。

受控操作当然不止这些,但是很多受控操作都可以分解成CNOT加上一些相位操作,我们可以自己构造自己需要的操作。

远距离操控随机

这里的远距离操控不是指我能扣确定他是什么,如果我能确定,那就不是随机了,而是说,我把两个比特弄成纠缠,当我一个测出来是0的时候,另一个以x%的概率得到0,至于我测出来是不是0看天意,对面测出来是不是0,也看天意,其中唯一能确定的,就只有这个x了。

这个例子是书上例子3-6 https://oreilly-qc.github.io/?p=3-6 方法很简单,就是我H门操作后,我旋转45°的角度,这样再来一个H门,因为相位变了,符号对不上,所以回不去了,就有了关联。

更强大的一点的应用是——量子隐形传态,量子隐形传态 Quantum Teleportation 提过了,就不在累述。

量子计算机编程(一)——QPU编程的更多相关文章

  1. 量子计算机编程(二)——QPU基础函数

    第二部分主要是QPU的基础功能,第一部分就像是我们有了哪些基本的语句,第二部分就是我们能写一些简单基础的函数,一些小模块,第三部分就是他的应用了. 先来看一下一个简单量子应用的结构: 第一步,将量子态 ...

  2. angular2系列教程(六)两种pipe:函数式编程与面向对象编程

    今天,我们要讲的是angualr2的pipe这个知识点. 例子

  3. Atitit 函数式编程与命令式编程的区别attilax总结  qbf

    Atitit 函数式编程与命令式编程的区别attilax总结  qbf 1.1. 函数式程序就是一个表达式.命令式程序就是一个冯诺依曼机的指令序列. 命令式编程是面向计算机硬件的抽象,有变量(对应着存 ...

  4. 物联网网络编程、Web编程综述

    本文是基于嵌入式物联网研发工程师的视觉对网络编程和web编程进行阐述.对于专注J2EE后端服务开发的童鞋们来说,这篇文章可能稍显简单.但是网络编程和web编程对于绝大部分嵌入式物联网工程师来说是一块真 ...

  5. RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大、最高效的方法之一。它为在分布式计算环境中运行的几乎所有应用程序提供基础。

    RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大.最高效的方法之一.它为在分布式计算环境中运行的几乎所有应用程序提供基础.本文介绍 RPC 客户机和服务器之间基本的事件流 ...

  6. .net 系列:并发编程之一 并发编程的初步理论

    一.关于并发编程的几个误解 1)并发就是多线程 实际上多线程只是并发编程的一种形式而已,在C#中还有很多其他的并发编程技术,包括异步编程,并行编程,TPL数据流,响应式编程等.  2)只有大型服务器才 ...

  7. Python编程和 Lua编程的比较

    Python编程和 Lua编程的比较 2016.4.21 定义函数: python: def functionname( parameters ): "函数_文档字符串" func ...

  8. 【憩园】C#并发编程之异步编程(一)

    写在前面 C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不需要深刻了解异步编程的底层原理,就可以写出十分优美而又代码量极少的代码.如果使用得当 ...

  9. 如何用ABP框架快速完成项目(面向项目交付编程面向客户编程篇)(1) - 目录

    昨天发表了<如何用ABP框架快速完成项目 - 自动化测试 - 前端angular e2e protractor>后,大家十分热情,几个小时内就收到了不少问题,包括: 对于ui自动化测试这方 ...

随机推荐

  1. Java String类相关知识梳理(含字符串常量池(String Pool)知识)

    目录 1. String类是什么 1.1 定义 1.2 类结构 1.3 所在的包 2. String类的底层数据结构 3. 关于 intern() 方法(重点) 3.1 作用 3.2 字符串常量池(S ...

  2. Vmware下Ubuntu 14.04静态IP地址的设置方法

    一.环境 宿主机 Win 8.1 虚拟机工具 VMware 10.0 虚拟主机系统 Ubuntu 14.04   二.说明 这里需要注意的是:VMware对于VMnet8采用如下规则(192.168. ...

  3. 20.java-JDBC连接mysql数据库详解

    1.JDBC介绍 jdbc(java database connectivity)为java开发者使用数据库提供了统一的编程接口,它由一组java类和接口组成. JDBC需要用到的类和接口有: Dri ...

  4. vue实现checked 全选功能

    记录一下 module.data = {  result: {}, items: [] //初始化全选按钮, 默认不选 ,isCheckedAll: false};module.vue = new V ...

  5. 【UWP】使用 LiteDB 存储数据

    序言: 在 UWP 中,常见的存储数据方式基本上就两种.第一种方案是 UWP 框架提供的 ApplicationData Settings 这一系列的方法,适用于存放比较轻量的数据,例如存个 Bool ...

  6. AVR单片机教程——小结

    本文隶属于AVR单片机教程系列.   第一期挺让我失望的,是我太菜,没有把想讲的都讲出来.经常写了很多,然后一点一点删掉,最后就没多少了. 而且感觉难度不合适,处于很尴尬的位置.讲得简单,难的丢给库, ...

  7. 如何修改netbeans的系统字体?

    1. 打开/etc/netbeans.config 2. 找到netbeans_default_options 3. 追加 --fontsize 12

  8. ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'问题的解决

    .与limit相关的sql语句作为临时表 select * from 临时表 limit ) as B 缺点:只能查临时表的数据 .可以查原表的数据 select * from test where ...

  9. Django 添加 app

    一.创建Django项目的时候添加 二.在终端创建app python manage.py startapp app名称 运行完命令后,要在settings.py文件中,添加配置文件

  10. [UVA1494] Qin Shi Huang's National Road System

    题目 戳这里 题解 从今天起我要改邪归正,好好刷题准备联赛! 这是一道经典的最小生成树题目. 枚举每一条边作为道士要修的路,求出包含这条边的最小生成树. 先求出原图的最小生成树. 如果要删的边在最小生 ...