本篇文章小编给大家分享一下python使用ProjectQ生成量子算法指令集代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
输出算法操作
首先介绍一个最基本的使用方法,就是使用ProjectQ来打印量子算法中所输入的量子门操作,这里使用到了ProjectQ中的DummyEngine后端用于保存操作的指令。比如最简单的一个Bell State的制备,可以通过如下代码实现,并且打印出所保存的基本操作:
from projectq import MainEngine from projectq.cengines import DummyEngine from projectq.ops import H, CX, All, Measure backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend) qureg = eng.allocate_qureg(2) H | qureg[0] CX | (qureg[0], qureg[1]) All(Measure) | qureg eng.flush(deallocate_qubits=True) for cmd in backend.received_commands: print (cmd)
运行结果如下:
Allocate | Qureg[0] H | Qureg[0] Allocate | Qureg[1] CX | ( Qureg[0], Qureg[1] ) Measure | Qureg[0] Measure | Qureg[1] Deallocate | Qureg[0] Deallocate | Qureg[1]
这里有一点需要注意的是,如果是单次运算,我们到Measure就可以结束了。但是如果同一个线程的任务还没有结束的话,需要在Measure之后加上一个deallocate_qubits=True的配置项,用于解除当前分配的量子比特所占用的内存。
封装的操作
在量子算法的实现中,我们可以用一些函数或者类来封装一部分的量子算法操作指令,但是这可能会导致一个问题,那就是在ProjectQ上打印出来的操作指令没有把封装的模块的内容输出出来,比如如下的案例:
from projectq import MainEngine from projectq.cengines import DummyEngine from projectq.ops import H, CX, All, Measure, TimeEvolution, QubitOperator backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend) qureg = eng.allocate_qureg(3) H | qureg[0] CX | (qureg[0], qureg[1]) TimeEvolution(1, QubitOperator('X2 X1')) | qureg All(Measure) | qureg eng.flush() for cmd in backend.received_commands: print (cmd)
执行结果如下:
Allocate | Qureg[0] H | Qureg[0] Allocate | Qureg[1] CX | ( Qureg[0], Qureg[1] ) Measure | Qureg[0] Allocate | Qureg[2] exp(-1j * (1.0 X0 X1)) | Qureg[1-2] Measure | Qureg[1] Measure | Qureg[2]
我们发现这里的含时演化的操作算符没有被分解,而是直接打印输出了出来。但是如果在硬件系统中,只能够识别支持的指令操作,这里的含时演化操作可能并未在量子硬件体系中被实现,因此我们就需要在将指令发送给量子硬件之前,就对其进行分解。
含时演化算符的分解
这里我们直接调用ProjectQ的配置中的restrictedgateset方法进行操作分解,我们将单比特门操作的范围放宽到所有的操作,但是双比特操作只允许CX操作,并将这个配置作为engin_list配置到ProjectQ的MainEngine中:
from projectq import MainEngine from projectq.cengines import DummyEngine from projectq.ops import H, CX, All, Measure, TimeEvolution, QubitOperator from projectq.setups import restrictedgateset engine_list = restrictedgateset.get_engine_list(one_qubit_gates="any",two_qubit_gates=(CX,)) backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend,engine_list=engine_list) qureg = eng.allocate_qureg(3) H | qureg[0] CX | (qureg[0], qureg[1]) TimeEvolution(1, QubitOperator('X2 X1')) | qureg All(Measure) | qureg eng.flush(deallocate_qubits=True) for cmd in backend.received_commands: print (cmd)
打印输出的结果如下:
Allocate | Qureg[0] H | Qureg[0] Allocate | Qureg[1] CX | ( Qureg[0], Qureg[1] ) Measure | Qureg[0] Allocate | Qureg[2] H | Qureg[2] H | Qureg[1] CX | ( Qureg[1], Qureg[2] ) Rz(2.0) | Qureg[2] CX | ( Qureg[1], Qureg[2] ) H | Qureg[1] Measure | Qureg[1] H | Qureg[2] Measure | Qureg[2] Deallocate | Qureg[0] Deallocate | Qureg[1] Deallocate | Qureg[2]
可以看到含时演化算符已经被分解并输出了出来。由于已知单比特量子门加上一个CX是一个完备的量子门集合,因此一般我们可以直接使用这个集合来进行量子门操作指令集的限制。
QFT的分解
QFT是ProjectQ中所自带支持的量子傅里叶变换的量子门操作封装,跟上一个章节中所介绍的含时演化算符类似的,我们可以用restrictedgateset来具体分解QFT算符:
from projectq import MainEngine from projectq.cengines import DummyEngine from projectq.ops import H, CX, All, Measure, TimeEvolution, QubitOperator, QFT from projectq.setups import restrictedgateset engine_list = restrictedgateset.get_engine_list(one_qubit_gates="any",two_qubit_gates=(CX,)) backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend,engine_list=engine_list) qureg = eng.allocate_qureg(3) H | qureg[0] CX | (qureg[0], qureg[1]) QFT | qureg All(Measure) | qureg eng.flush(deallocate_qubits=True) for cmd in backend.received_commands: print (cmd)
输出的结果如下:
Allocate | Qureg[2] Allocate | Qureg[1] H | Qureg[2] Rz(0.785398163398) | Qureg[2] Allocate | Qureg[0] H | Qureg[0] CX | ( Qureg[0], Qureg[1] ) R(0.785398163398) | Qureg[1] CX | ( Qureg[1], Qureg[2] ) Rz(11.780972450962) | Qureg[2] CX | ( Qureg[1], Qureg[2] ) R(0.392699081698) | Qureg[0] Rz(0.392699081698) | Qureg[2] CX | ( Qureg[0], Qureg[2] ) H | Qureg[1] Rz(12.173671532661) | Qureg[2] CX | ( Qureg[0], Qureg[2] ) R(0.785398163398) | Qureg[0] Rz(0.785398163398) | Qureg[1] CX | ( Qureg[0], Qureg[1] ) Rz(11.780972450962) | Qureg[1] CX | ( Qureg[0], Qureg[1] ) H | Qureg[0] Measure | Qureg[0] Measure | Qureg[1] Measure | Qureg[2] Deallocate | Qureg[1] Deallocate | Qureg[2] Deallocate | Qureg[0]
如果2比特门操作也不加以限制的化,ProjectQ中会自动选取最简易的分解形式:
from projectq import MainEngine from projectq.cengines import DummyEngine from projectq.ops import H, CX, All, Measure, TimeEvolution, QubitOperator, QFT from projectq.setups import restrictedgateset engine_list = restrictedgateset.get_engine_list(one_qubit_gates="any",two_qubit_gates="any") backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend,engine_list=engine_list) qureg = eng.allocate_qureg(3) H | qureg[0] CX | (qureg[0], qureg[1]) QFT | qureg All(Measure) | qureg eng.flush(deallocate_qubits=True) for cmd in backend.received_commands: print (cmd)
输出结果如下:
Allocate | Qureg[0] Allocate | Qureg[1] H | Qureg[0] CX | ( Qureg[0], Qureg[1] ) Allocate | Qureg[2] H | Qureg[2] CR(1.570796326795) | ( Qureg[1], Qureg[2] ) CR(0.785398163397) | ( Qureg[0], Qureg[2] ) H | Qureg[1] CR(1.570796326795) | ( Qureg[0], Qureg[1] ) H | Qureg[0] Measure | Qureg[0] Measure | Qureg[1] Measure | Qureg[2] Deallocate | Qureg[1] Deallocate | Qureg[2] Deallocate | Qureg[0]
可以发现使用了CR来替代CX之后,分解出来的线路会更加的简短。