简介
Qiskit是一个基于Python语言的开源量子计算框架,由IBM开发和维护。它提供了一整套用于量子计算的工具和库,包括量子线路模拟器、量子计算机仿真器、量子算法库、量子机器学习库、量子编译器、量子错误校正等。Qiskit旨在帮助用户快速学习和使用量子计算,并将其应用于解决实际问题。
Qiskit支持多种硬件平台,包括IBM Quantum、IonQ、AQT等,并与多个量子计算平台合作,使得用户可以轻松地访问不同的量子计算机。同时,Qiskit也支持使用经典计算机进行量子仿真,使得用户能够在没有量子计算机的情况下进行量子算法的设计和测试。
Qiskit提供了直观易用的API,使得用户可以快速构建量子线路、实现量子算法,以及进行量子仿真和实验。同时,Qiskit还支持可视化工具,如量子线路绘图、量子态向量/密度矩阵绘图等,帮助用户更好地理解和可视化量子计算的过程和结果。
总之,Qiskit是一个全面、易用、灵活的量子计算框架,为用户提供了从量子计算的基础知识到高级应用的一整套工具和支持,具有广泛的应用前景。
作者的话
撰写此篇文章的主要目的是记录在学习和使用Qiskit的过程中,遇到的一些比较常用的类和方法,以便以后查阅。
因为Qiskit官网没有中文文档,本人英语又比较差,所以难免有理解错误的地方,如有发现,敬请批评和指导。
本文不会讨论量子计算的基础理论,也不会介绍各种门的作用以及如何构建量子线路解决经典问题,仅仅记录Qiskit库的使用。
画量子电路图
QuantumCircuit的draw方法可以轻松地画出量子电路图。以下代码画出一个Toffoli门。
from qiskit import QuantumCircuit
qc = QuantumCircuit(3)
qc.ccx(0, 1, 2)
qc.draw('mpl').show()
draw方法参数详解:
output
: 可选值为 mpl、text 和 latex。默认值为 mpl,表示将量子电路绘制为 Matplotlib 图形。text 和 latex 可以将电路输出为字符串,以便进一步使用或保存。如果要将电路绘制为 PDF 或 SVG 等格式的文件,可以将字符串保存为文件。filename
: 如果 output 值为字符串 text 或 latex,则可以使用该参数指定要将电路输出到的文件名或路径。如果未指定此参数,则输出到标准输出(控制台)。style
: 该参数指定绘图样式。可选的值包括 default、iqx 和 bw。默认值为 default,表示使用 Qiskit 的默认绘图样式。iqx 和 bw 样式分别对应于 IBM Quantum Experience 和黑白两种样式。plot_barriers
: 如果设置为 True,则会在绘制电路中显示障碍。默认为 True。reverse_bits
: 如果设置为 True,则按照从右向左的顺序显示量子位。默认为 False。justify
: 如果设置为 True,则在绘制电路时将所有行居中对齐。默认为 False。idle_wires
: 如果设置为 True,则在绘制电路中显示空闲线。默认为 True。with_layout
: 如果设置为 True,则在绘制电路时显示布局信息。默认为 False。fold
: 该参数指定是否将多个相同的门折叠成一个,以减少绘图中的噪音。默认为 None,表示不折叠。可以设置为一个整数,表示折叠的最大数量;或者设置为一个布尔值,表示是否应该进行折叠。ax
: 该参数指定要在其上绘制电路的 Matplotlib 轴。如果未指定,则创建一个新的 Matplotlib 图形并在其上绘制电路。
本人常用参数参考
circuit.draw('mpl', scale=1, filename=os.path.join(os.getcwd(), 'out.png'), initial_state=True, plot_barriers=False, justify='left', fold=-1)
QASM
QASM(Quantum Assembly Language)是一种用于编写量子程序的语言,类似于经典计算机中的汇编语言。QASM可以描述量子算法中的量子线路,包括量子门、测量、初始化等操作,同时支持定义自定义的量子门和变量。QASM的语法规则与其他编程语言类似,包括注释、变量声明、循环、条件判断等。
QASM是量子计算中最为常用的编程语言之一,可以用来描述量子程序,生成量子程序的二进制表示,同时也可以用来模拟量子程序的运行过程,以及进行量子程序的优化和编译。在量子计算中,QASM的作用类似于经典计算机中的汇编语言,在实现和优化量子算法时具有重要的作用。
Qiskit中可以将QuantumCircuit 和QASM语言相互转换。
from qiskit import QuantumCircuit
qc = QuantumCircuit(3)
qc.ccx(0, 1, 2)
qasm = qc.qasm()
print(qasm)
new_qc = QuantumCircuit.from_qasm_str(qasm)
print(new_qc)
运行结果如下
OPENQASM 2.0;
include "qelib1.inc";
qreg q[3];
ccx q[0],q[1],q[2];
q_0: ──■──
│
q_1: ──■──
┌─┴─┐
q_2: ┤ X ├
└───┘
MCT门
在处理mct门的时候发现两个问题:
- 从qasm中导入一个4控制位的mct门是,会报以下错误:
qiskit.qasm.exceptions.QasmError: Cannot find gate definition for 'c3sx', line 5 file
原因是因为qasm中存在一个c3sx
门的定义在qelib1.inc
中不存在
from qiskit import QuantumCircuit
qc = QuantumCircuit(5)
qc.mct(list(range(4)), 4)
qasm = qc.qasm()
print(qasm)
new_qc = QuantumCircuit.from_qasm_str(qasm)
运行结果:
OPENQASM 2.0;
include "qelib1.inc";
gate rcccx_dg q0,q1,q2,q3 { u2(-2*pi,pi) q3; u1(pi/4) q3; cx q2,q3; u1(-pi/4) q3; u2(-2*pi,pi) q3; u1(pi/4) q3; cx q1,q3; u1(-pi/4) q3; cx q0,q3; u1(pi/4) q3; cx q1,q3; u1(-pi/4) q3; cx q0,q3; u2(-2*pi,pi) q3; u1(pi/4) q3; cx q2,q3; u1(-pi/4) q3; u2(-2*pi,pi) q3; }
gate rcccx q0,q1,q2,q3 { u2(0,pi) q3; u1(pi/4) q3; cx q2,q3; u1(-pi/4) q3; u2(0,pi) q3; cx q0,q3; u1(pi/4) q3; cx q1,q3; u1(-pi/4) q3; cx q0,q3; u1(pi/4) q3; cx q1,q3; u1(-pi/4) q3; u2(0,pi) q3; u1(pi/4) q3; cx q2,q3; u1(-pi/4) q3; u2(0,pi) q3; }
gate mcx q0,q1,q2,q3,q4 { h q4; cu1(pi/2) q3,q4; h q4; rcccx q0,q1,q2,q3; h q4; cu1(-pi/2) q3,q4; h q4; rcccx_dg q0,q1,q2,q3; c3sx q0,q1,q2,q4; }
qreg q[5];
mcx q[0],q[1],q[2],q[3],q[4];
Traceback (most recent call last):
File "D:\projects\量子计算\venv\lib\site-packages\qiskit\qasm\qasm.py", line 53, in parse
return qasm_p.parse(self._data)
File "D:\projects\量子计算\venv\lib\site-packages\qiskit\qasm\qasmparser.py", line 1137, in parse
self.parser.parse(data, lexer=self.lexer, debug=self.parse_deb)
File "D:\projects\量子计算\venv\lib\site-packages\ply\yacc.py", line 333, in parse
return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
File "D:\projects\量子计算\venv\lib\site-packages\ply\yacc.py", line 1120, in parseopt_notrack
p.callable(pslice)
File "D:\projects\量子计算\venv\lib\site-packages\qiskit\qasm\qasmparser.py", line 796, in p_gate_op_2
self.verify_as_gate(program[1], program[2])
File "D:\projects\量子计算\venv\lib\site-packages\qiskit\qasm\qasmparser.py", line 142, in verify_as_gate
obj.file,
qiskit.qasm.exceptions.QasmError: "Cannot find gate definition for 'c3sx', line 5 file "
python-BaseException
经过比对发现qelib1.inc
中有c3sx
的定义,只是名字叫c3sqrtx
,那么只需要在qelib1.inc
中加入c3sx
的定义就可以了
gate c3sx a,b,c,d
{
h d; cu1(pi/8) a,d; h d;
cx a,b;
h d; cu1(-pi/8) b,d; h d;
cx a,b;
h d; cu1(pi/8) b,d; h d;
cx b,c;
h d; cu1(-pi/8) c,d; h d;
cx a,c;
h d; cu1(pi/8) c,d; h d;
cx b,c;
h d; cu1(-pi/8) c,d; h d;
cx a,c;
h d; cu1(pi/8) c,d; h d;
}
- 从qasm中导入的mct门,用draw画出来的图会变成一个方框。下面代码画出的两个3控制mct门不一样。
from qiskit import QuantumCircuit
qc = QuantumCircuit(4)
qc.mct(list(range(3)), 3)
qc.draw('mpl').show()
qasm = qc.qasm()
new_qc = QuantumCircuit.from_qasm_str(qasm)
new_qc.draw('mpl').show()
出现这种情况的原因未知,可通过以下方法解决。
from qiskit import QuantumCircuit
qc = QuantumCircuit(4)
qc.mct(list(range(3)), 3)
qc.draw('mpl').show()
qasm = qc.qasm()
new_qc = QuantumCircuit.from_qasm_str(qasm)
fix_qc = QuantumCircuit(*new_qc.qregs, *new_qc.cregs)
for c in qc:
if c.operation.name == 'mcx':
fix_qc.mcx(list(c.qubits[:-1]), c.qubits[-1])
else:
fix_qc.append(c)
fix_qc.draw('mpl').show()
transpile
在量子计算中,硬件实现可能与逻辑电路不完全匹配,因此通常需要对量子电路进行编译或优化以更好地适应硬件约束。Qiskit提供了一个transpile()方法来对一个量子电路进行编译或优化。
transpile()方法的语法如下:
transpile(circuits, backend=None, basis_gates=None, coupling_map=None, initial_layout=None, seed_transpiler=None, optimization_level=None, pass_manager=None, callback=None, output_name=None)
transpile参数详解
circuits
:要进行编译或优化的一个或多个量子电路,可以是单个QuantumCircuit对象,也可以是一个List类型。backend
:选定的后端,可以是Aer的后端,也可以是实际的硬件后端。默认为None,表示使用默认的后端。basis_gates
:所需的基本门集。默认情况下,Qiskit将自动选择一个基本门集。如果使用不同的基本门集,则需要提供自己的基本门集。coupling_map
:两个量子比特之间的连接关系。如果没有提供,Qiskit将自动推断。initial_layout
:电路的初态,即将每个逻辑量子比特映射到硬件中的哪个物理量子比特上。seed_transpiler
:随机数生成器的种子,用于控制transpile()方法的随机性。optimization_level
:优化级别。可以是整数或枚举类型,代表不同的优化级别。可选值为0,1,2,3,优化程度由低到高,0表示完全不优化,默认为1。pass_manager
:优化流程管理器。可以是PassManager对象或由transpile()方法自动生成的默认PassManager对象。callback
:回调函数,用于在优化过程中获取中间结果。output_name
:输出电路的名称。
transpile()方法将一个或多个量子电路编译或优化为一个较小的电路,以便于在硬件上运行。该方法基于优化级别和流程管理器来执行一系列优化技术,包括寻找可重用的子电路、分解多量子比特门、插入优化的Barrier以及优化量子电路的布局等等。
transpile()方法返回一个新的QuantumCircuit对象,代表已经被编译或优化的电路。该方法还可以接受一些回调函数和输出文件名,用于保存优化过程中的中间结果和输出电路。
下面代码将一个经典电路分解为由u门和cnot门组成的量子电路
from qiskit import QuantumCircuit, transpile
qc = QuantumCircuit(4)
qc.cx(0, 1)
qc.cx(1, 2)
qc.ccx(0, 1, 2)
qc.mct(list(range(3)), 3)
qc.ccx(0, 1, 2)
qc.cx(1, 2)
qc.cx(0, 1)
qc.draw('mpl').show()
transpile(qc, basis_gates=['cx', 'u'], optimization_level=3).draw('mpl').show()