目录
一、QWhile
二、QIf
各位读者老爷们,大家好呀,前些时忙着学校的期末考试,小编好久没更新量子计算的文章啦,这段时间也有读者私信小编,问了一些问题。我知道大家都很急,但大家先别急。这不,小编刚考完就来更新量子计算的文章啦,感谢大家的支持!
谈到量子计算,这里就不得不提一部电影了。相信很多读者在寒假春节档看过《流浪地球2》这部电影(可能还有《流浪气球3》),未来的计算机550A、550C与550w(最后化身为MOSS)都是量子计算机,其计算速度一代比一代快,我相信这也是各位读者想要学好量子计算的原因。这是一部科幻片,它思考了人类的未来是怎么样的,科技水平是怎么样的,而我们负责将这些幻想一个一个实现,尽管有一定的困难。革命尚未成功,各位读者们还需努力!
一、QWhile
在c语言与python中,我们可以构造一个while或者for来构造循环。我们在量子程序中用QWhile实现循环控制操作,输入参数为条件判断表达式,功能是执行while循环操作。其构造方式如下:
qwile = QWhileProg(ClassicalCondition, QNode)
上述函数需要提供两个参数,即ClassicalCondition量子表达式与QNode节点 可以传入的QNode类型有: QProg、QCircuit、QGate、QWhileProg、QIfProg、QMeasure。
我知道大家看到上面这些话会感觉到特别懵,啥玩意儿,小编你这不是念课本吗,听君一席话,胜似一席话,说了等于没说。别急,如果只是这么干巴巴的讲知识点,就会略显无聊,我们上一个例子,让大家感受一下。
from pyqpanda import *
if __name__ == "__main__":
qvm = CPUQVM()
qvm.init_qvm()
qubits = qvm.qAlloc_many(3)
cbits = qvm.cAlloc_many(3)
cbits[0].set_val(0)
cbits[1].set_val(1)
prog = QProg()
prog_while = QProg()
# 构建QWhile的循环分支
prog_while << H(qubits[0]) << H(qubits[1])<< H(qubits[2])\
<< measure_all(qubits, cbits)
# 构建QWhile
qwhile = QWhileProg(cbits[1], prog_while)
# QWhile插入到量子程序中
prog << qwhile
# 运行,并打印测量结果
result = qvm.directly_run(prog)
print(result)
print(cbits[1].get_val())
看不懂没事的哈,听小编给你说道说道。不过小编在这里给大家提一个小小的要求,听完小编的分析后,请大家算一算输出的结果是多少。
首先前几行,小编只想通俗易懂的说一个字:略。详情看小编上一篇量子计算的文章。不过小编像先请读者们思考一下,为什么qubits的数量要与经典寄存器cbits的数量一致。这个问题困扰了小编一阵子,直到今天查阅资料的时候,才真正解决掉。
然后再是set_val()函数,它的作用是赋值,即cbits[0]赋值为0,cbits[1]赋值为1。到这里都不难理解。紧接着就是构建了一个while的量子程序。我们先看qwhile=xxx的这一行。首先判定条件为cbits[1],而在计算机中0代表着False,1代表着True。也就是说cbits[1]为0时,才会执行prog_while循环。
接着,我们就要看看prog_while是何方神圣,如何执行这一循环了。
结果乍一看,这不就是在三条量子线路上分别加了一个H门吗,然后再进行测量,而H门的作用是使|1>态与|0>态的概率各占一半。但是,cbits[1]为0时我们才能跳出循环,而小编通过查阅资料发现measure_all操作是测量所有的量子比特并将其存储到对应的经典寄存器上。也就是说只有qubits[1]为|0>时才能跳出循环,此时cbits[1]被赋值为0。所以qubits[1]最后测量的结果一定是|0>。如果是|1>则会不断重复循环,直到某一次测量结果为|0>。
这也是为什么qubits的数量与cbits的数量一致的原因,正所谓一个萝卜一个坑,这样做是为了我们测量结果着想。如果不一致会报错,如下图:
那么问题来了,有没有哪位读者能告诉我,最后程序跑出的结果是多少?小编将答案写在评论区。
二、QIf
QIf表示量子程序条件判断操作,输入参数为条件判断表达式,功能是执行条件判断。具体形式有以下两种:
qif = QIfProg(ClassicalCondition, QNode)
qif = QIfProg(ClassicalCondition, QNode, QNode)
它需要我们提供两种类型参数,即ClassicalCondition量子表达式与QNode节点, 当传入1个QNode参数时,QNode表示正确分支节点,当传入2个QNode参数时,第一个表示正确分支节点,第二个表示错误分支节点。
其中QNode可以传入QProg、QCircuit、QGate、QWhileProg、QIfProg、QMeasure。
我们用代码举一个小小的例子:
from pyqpanda import *
if __name__ == "__main__":
qvm = CPUQVM()
qvm.init_qvm()
qubits = qvm.qAlloc_many(3)
cbits = qvm.cAlloc_many(3)
cbits[0].set_val(0)
cbits[1].set_val(3)
prog = QProg()
branch_true = QProg()
branch_false = QProg()
# 构建QIf正确分支以及错误分支
branch_true << H(qubits[0])<< H(qubits[1]) << H(qubits[2])
branch_false << H(qubits[0]) << CNOT(qubits[0], qubits[1]) << CNOT(qubits[1], qubits[2])
# 构建QIf
qif = QIfProg(cbits[0] > cbits[1], branch_true, branch_false)
# QIf插入到量子程序中
prog << qif
# 概率测量,并返回目标量子比特的概率测量结果,下标为十进制
result = qvm.prob_run_tuple_list(prog, qubits, -1)
# 打印概率测量结果
print(result)
乍一看,看不大懂,对吧?别急,小编也是刚开始学量子编程,我按照自己的理解一点一点为读者们解读。
首先前面几行,都是老生常谈的内容。无非就是上一篇文章我们说的导入pyqpanda包、创建量子虚拟机以及申请量子比特以及量子寄存器。而cbits[0].set_val(0)的意思是,给cbits[0]设置初值为0,同理cbits[1]的初值为3。
我们先跳过branch_true与branch_false这两行,直接看qif=xxx这一行,它代表着如果cbits[0]>cbits[1],那么就执行branch_true的量子程序指令,否则就执行branch_false的量子程序指令。显然0不可能大于3,所以我们执行branch_false的量子程序指令。
再来看看branch_false做了什么操作。首先将qubits[0]转变为|+>态,并且通过qubits[0]去控制qubits[1],用qubits[1]去控制qubits[2]。我们不难发现,qubits[0]为|1>时,才能让qubits[1]变为|1>,qubits[2]才能跟着变为|1>。且qubits[0]为|0>或者|1>的概率各占一半。
所以最终测量|000>与|111>的概率各占一半。结果如下图(转换为了十进制):
好的,本期的量子计算编程教学就到这里啦,感兴趣的读者们可以私下自己设计设计量子线路,编编程,希望小编的文章能给大家带来帮助。