OpenQASM(open quantum assembly language),即開(kāi)放量子匯編語(yǔ)言,是一種命令式編程語(yǔ)言,它的特性類似于硬件描述語(yǔ)言(hardware description language),由 IBM 于 2017 年 7 月在其量子計(jì)算平臺(tái)推出,它能夠使用電路模型、基于測(cè)量的模型和近期量子計(jì)算實(shí)驗(yàn)來(lái)描述通用的量子計(jì)算,也是目前適用范圍較廣的量子匯編語(yǔ)言,目前已更新至 3.0 版本。
OpenQASM 作為一個(gè)開(kāi)源框架,廣泛用于基于門的設(shè)備的量子程序規(guī)范。借助 OpenQASM,用戶可以對(duì)構(gòu)成量子計(jì)算基石的量子門和測(cè)量操作進(jìn)行編程。目前,許多量子編程庫(kù)使用先前版本的 OpenQASM 2.0 來(lái)描述簡(jiǎn)單的程序。
OpenQASM 在框架中提供了一組參數(shù)化的物理邏輯門和并發(fā)的實(shí)時(shí)經(jīng)典計(jì)算的集合。它的主要目標(biāo)是作為高級(jí)編譯器與量子硬件通信的中間表示載體,在表示形式上,也考慮到了人們使用它時(shí)的易讀性。特別是,該語(yǔ)言允許同一程序的不同表示形式,所以 OpenQASM 可以由 Composer 生成,也支持手寫(xiě),或者由更高層次的軟件工具來(lái)完成,比如 ProjectQ、Quil、Liquid 等等。
OpenQASM 3.0 與之前版本相比,增加了更多功能,例如脈沖電平控制、門定時(shí)和經(jīng)典控制流程,以彌補(bǔ)最終用戶界面和硬件描述語(yǔ)言之間的差距??偨Y(jié)起來(lái),基本集中在以下三個(gè)方面:
遵循上述設(shè)計(jì)目標(biāo),OpenQASM 3.0 相比之前的 OpenQASM 2.0 規(guī)范進(jìn)行了大幅擴(kuò)展升級(jí)。增加了許多經(jīng)典控制流和計(jì)算的新功能,使編寫(xiě)量子算法更容易,并描述構(gòu)成這些算法一部分的經(jīng)典數(shù)據(jù)處理。然而,該語(yǔ)言并非設(shè)計(jì)用于通用經(jīng)典計(jì)算,并且在短期內(nèi),任何執(zhí)行 OpenQASM 3.0 程序的硬件都不太可能支持該語(yǔ)言可以描述的全套數(shù)據(jù)操作。
OpenQASM 3.0 的硬件能夠保證它們?cè)谶\(yùn)行時(shí)將處理性能穩(wěn)定在高效和實(shí)時(shí)執(zhí)行的操作上。這組操作在不同的實(shí)現(xiàn)工具下,實(shí)現(xiàn)方式會(huì)根據(jù)硬件種類略有所不同,需要提前了解不同硬件在運(yùn)行時(shí)可以實(shí)現(xiàn)哪些語(yǔ)言功能。隨著時(shí)間的推移,隨著量子控制的要求變得不那么繁重,實(shí)現(xiàn)組件可能會(huì)變得更加強(qiáng)大。
在將來(lái) OpenQASM 3.0 的編譯器也會(huì)支持一些經(jīng)典操作,這些經(jīng)典操作會(huì)被合理地判斷為編譯時(shí)常量,并在編譯時(shí)執(zhí)行這些操作。上面所說(shuō)到的“合理推斷”是指聲明為常量的值以及字面意義。例如,這意味著“科學(xué)計(jì)算器函數(shù)”(如sin、exp 等)將始終對(duì)只涉及兼容類型的字面符號(hào)和聲明為常量的值的表達(dá)式起作用,而且編譯器會(huì)將這些表達(dá)式完全折疊成單個(gè)常量。具體能夠如何實(shí)現(xiàn),還需要我們繼續(xù)等待相關(guān)的適配工作。
因?yàn)槟壳安皇撬谢陂T的量子設(shè)備和模擬器都支持 OpenQASM 3.0 ,所以在一些代碼示例中,將會(huì)使用部分 OpenQASM 2.0 的內(nèi)容。
首先展示一下如何利用 OpenQASM 中的語(yǔ)法規(guī)則設(shè)置部分量子門:
OPENQASM 2.0;
include "qelib1.inc";
qreg q[10];
creg c[10];
x q[0];
h q[1];
tdg q[2];
sdg q[2];
cx q[0],q[2];
cx q[1],q[4];
u1(pi) q[0];
u2(pi,pi) q[1];
u3(pi,pi,pi) q[2];
cz q[2],q[5];
ccx q[3],q[4],q[6];
cu3(pi,pi,pi) q[0],q[1];
measure q[2] -> c[2];
measure q[0] -> c[0];
可以看到,OpenQASM 會(huì)直接對(duì)需要進(jìn)行轉(zhuǎn)置共軛操作的量子邏輯門與量子線路進(jìn)行直接轉(zhuǎn)化;并且在對(duì)量子程序轉(zhuǎn)化 QASM 指令集之前,會(huì)對(duì)其中包含的控制操作進(jìn)行分解。
目前在已開(kāi)源的量子編程框架中,本源量子的 QPanda 框架提供了 QASM 轉(zhuǎn)換的工具接口的,接口為std::string convert_qprog_to_qasm(QProg &, QuantumMachine*),使用方式也較為簡(jiǎn)單。接下來(lái)我們可以來(lái)看看QPanda框架是如何進(jìn)行QASM轉(zhuǎn)換的:
#include "QPanda.h"
USING_QPANDA
int main(void)
{
auto qvm = CPUQVM();
qvm.init();
auto prog = QProg();
auto cir = Circuit();
auto q = qvm.qAllocMany(6);
auto c = qvm.cAllocMany(6);
// 構(gòu)建量子程序
cir << Y(q[2]) << H(q[2]);
cir.setDagger(true);
auto h1 = H(q[1]);
h1.setDagger(true);
prog << H(q[1])
<< X(q[2])
<< h1
<< RX(q[1], 2 / PI)
<< cir
<< CR(q[1], q[2], PI / 2)
<<MeasureAll(q,c);
// 量子程序轉(zhuǎn)換QASM,并打印QASM
std::cout << convert_qprog_to_qasm(prog,qvm);
return 0;
}
具體的操作步驟是這樣的:
最終的輸出結(jié)果如下:
OPENQASM 2.0;
include "qelib1.inc";
qreg q[6];
creg c[6];
h q[1];
x q[2];
h q[1];
rx(0.636620) q[1];
h q[2];
y q[2];
rz(-0.785398) q[2];
cx q[1],q[2];
rz(-0.785398) q[2];
cx q[1],q[2];
rz(1.570796) q[2];
rx(1.570796) q[1];
ry(-0.785398) q[1];
rx(-1.570796) q[1];
measure q[0] -> c[0];
measure q[1] -> c[1];
measure q[2] -> c[2];
measure q[3] -> c[3];
measure q[4] -> c[4];
measure q[5] -> c[5];
接下來(lái)我們可以看看目前已經(jīng)支持了 OpenQASM 3.0 的 Amazon Braket,是如何利用 OpenQASM 3.0 語(yǔ)言的:
具體示例為如何利用 Braket 創(chuàng)建一個(gè) OpenQASM 3.0 任務(wù)。比如,從準(zhǔn)備一個(gè)Gz狀態(tài)開(kāi)始:
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;
qubit[3] q;
bit[3] c;
h q[0];
cnot q[0], q[1];
cnot q[1], q[2];
c = measure q;
或者我們還可以使用 Boto 3 創(chuàng)建 OpenQASM 3.0 任務(wù)。在下面的實(shí)例中,使用了 ghz.qasm:
import boto3
import json
my_bucket = "Amazon-braket-my-bucket"
s3_prefix = "openqasm-tasks"
with open("ghz.qasm") as f:
source = f.read()
action = {
"braketSchemaHeader": {
"name": "braket.ir.openqasm.program",
"version": "1"
},
"source": source
}
device_parameters = {}
device_arn = "arn:aws:braket:::device/qpu/rigetti/Aspen-11"
shots = 100
braket_client = boto3.client('braket', region_name='us-west-1')
rsp = braket_client.create_quantum_task(
action=json.dumps(
action
),
deviceParameters=json.dumps(
device_parameters
),
deviceArn=device_arn,
shots=shots,
outputS3Bucket=my_bucket,
outputS3KeyPrefix=s3_prefix,
)
在噪聲模擬方面,我們也可以使用 OpenQASM 3.0 來(lái)完成。在 Braket 中提交以下程序即可完成噪聲模擬:
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;
qubit[3] q;
bit[3] c;
h q[0];
#pragma braket noise depolarizing(0.75) q[0] cnot q[0], q[1];
#pragma braket noise depolarizing(0.75) q[0]
#pragma braket noise depolarizing(0.75) q[1] cnot q[1], q[2];
#pragma braket noise depolarizing(0.75) q[0]
#pragma braket noise depolarizing(0.75) q[1]
c = measure q;
以下列表中提供了所有受支持的編譯指示噪聲運(yùn)算符的規(guī)范:
#pragma braket noise bit_flip(<float>) <qubit>
#pragma braket noise phase_flip(<float>) <qubit>
#pragma braket noise pauli_channel(<float>, <float>, <float>) <qubit>
#pragma braket noise depolarizing(<float in [0,3/4]>) <qubit>
#pragma braket noise two_qubit_depolarizing(<float in [0,15/16]>) <qubit>, <qubit>
#pragma braket noise two_qubit_dephasing(<float in [0,3/4]>) <qubit>, <qubit>
#pragma braket noise amplitude_damping(<float in [0,1]>) <qubit>
#pragma braket noise generalized_amplitude_damping(<float in [0,1]> <float in [0,1]>) <qubit>
#pragma braket noise phase_damping(<float in [0,1]>) <qubit>
#pragma braket noise kraus([[<complex m0_00>, ], ...], [[<complex m1_00>, ], ...], ...) <qubit>[, <qubit>] // maximum of 2 qubits and maximum of 4 matrices for 1 qubit, 16 for 2
) <qubit>[, <qubit>] // maximum of 2 qubits
目前除了較為通用的 OpenQASM 開(kāi)放量子匯編語(yǔ)言外,其實(shí)還存在很多專用匯編語(yǔ)言,這些語(yǔ)言在對(duì)應(yīng)設(shè)備的適配兼容性上,可能表現(xiàn)會(huì)更好。比如,啟科量子推出的一款量子匯編語(yǔ)言—— QuQASM ,是針對(duì)自研的量子編程框架 QuTrunk 來(lái)進(jìn)行適配的。
QuTrunk 使用 Python 作為宿主語(yǔ)言,利用 Python 的語(yǔ)法特性實(shí)現(xiàn)針對(duì)量子程序的 DSL (領(lǐng)域?qū)S谜Z(yǔ)言), 把用于量子編程的專用語(yǔ)言稱為:QuQASM。它的主要特點(diǎn)是最左邊是一個(gè)量子門操作,中間加入( * )號(hào)鏈接符,最右邊是操作的量子比特,形式如下:
gate * qubits
為了方便理解,我們可以再多看看幾個(gè)例子:
H * q[0]; # 對(duì)q[0]做hadamard門操作
CNOT * (q[0], q[1]); # q[0]為控制位,q[1]為目標(biāo)位
All(Measure) * q # 對(duì)q代表的所有量子比特做測(cè)量操作
使用該標(biāo)準(zhǔn)是充分利用了 Python 語(yǔ)法對(duì)( * )運(yùn)算符的重載特性。該表形式更接近量子物理計(jì)算公式,同時(shí) ( * )在計(jì)算機(jī)編程語(yǔ)言上表示乘法的意思,借此表示左邊的量子門操作實(shí)際上是對(duì)量子比特做矩陣乘法運(yùn)算。
使用該標(biāo)準(zhǔn)編寫(xiě)的量子匯編是可以直接被 QuTrunk 解析運(yùn)行的,不需要做語(yǔ)法方面的解析處理工作。基于該特性,QuTrunk 可以無(wú)縫銜接 QuBranch 通過(guò)可視化量子編程生成的量子線路。即 QuTrunk可以直接運(yùn)行 QuBranch 生成的量子線路(只需做一些簡(jiǎn)單的初始化工作),而無(wú)需做語(yǔ)法上的轉(zhuǎn)譯處理。
下面是 QuQASM 每個(gè)量子門操作介紹:
//H(hadamard): 哈德馬門,對(duì)a做H門操作,常用于使量子比特處于疊加態(tài)
H * a
//X(NOT): 非門(Pauli-X)對(duì)a進(jìn)行取反操作, 量子比特繞布洛赫球的x軸旋轉(zhuǎn)pi角度
X * a
//Y: Pauli-Y, 量子比特繞布洛赫球的y軸旋轉(zhuǎn)pi角度
Y * a
//Z: Pauli-Z, 量子比特繞布洛赫球的z軸旋轉(zhuǎn)pi角度
Z * a
//CNOT(CX): 受控非門,a作為控制位,b為目標(biāo)位,如果a為1則對(duì)b進(jìn)行取反,如果a為0則不做任何操作
CNOT * (a, b)
//Toffoli: 托佛利門,a, b作為控制位,c為目標(biāo)位, 如果a,b均為1則對(duì)b進(jìn)行取反,否則不做任何操作
Toffoli * (a, b, c)
//Measure: 測(cè)量門,對(duì)a進(jìn)行測(cè)量,結(jié)果要么是0,要么是1,測(cè)量結(jié)果受概率振幅影響
Measure * a
//P: 相移門,將量子比特0>態(tài)和1>態(tài)的相位根據(jù)給定的角度進(jìn)行移動(dòng)
P(theta) * a
//Rx: 量子比特繞布洛赫球的x軸旋轉(zhuǎn)theta角度
Rx(theta) * a
//Ry: 量子比特繞布洛赫球的y軸旋轉(zhuǎn)theta角度
Ry(theta) * a
//Rz: 量子比特繞布洛赫球的z軸旋轉(zhuǎn)theta角度
Rz(theta) * a
//S: 量子比特繞布洛赫球的z軸旋轉(zhuǎn)pi/2角度
S * a
//Sdg: 對(duì)S門的反向操作, 繞布洛赫球的z軸反方向旋轉(zhuǎn)pi/2角度
Sdg * a
//T: 量子比特繞布洛赫球的z軸旋轉(zhuǎn)pi/4角度
T * a
//Tdg: 對(duì)T門的反向操作, 繞布洛赫球的z軸反方向旋轉(zhuǎn)pi/4角度
Tdg * a
//Swap: 交換兩個(gè)量子比特的狀態(tài)
Swap * (a, b)
//SqrtSwap: 對(duì)兩個(gè)量子比特做sqrt交換
SqrtSwap * (a, b)
//SqrtX: 平方根X門
SqrtX * a
//Rxx: 兩個(gè)量子比特繞x^x旋轉(zhuǎn),旋轉(zhuǎn)角度為theta
Rxx(theta) * (a, b)
//Ryy: 兩個(gè)量子比特繞y^y旋轉(zhuǎn),旋轉(zhuǎn)角度為theta
Ryy(theta) * (a, b)
//Rzz: 兩個(gè)量子比特繞z^z旋轉(zhuǎn),旋轉(zhuǎn)角度為theta
Rzz(theta) * (a, b)
//Barrier: 分隔量子比特,阻止量子線路對(duì)相應(yīng)量子比特做優(yōu)化等處理
Barrier * a
Barrier * (a, b)
//U1: 對(duì)單個(gè)量子比特繞z軸旋轉(zhuǎn)
U1(lambda) * a
//U2: 對(duì)單個(gè)量子比特繞x+z軸旋轉(zhuǎn)
U1(phi, lambda) * a
//U3: 通用單量子比特旋轉(zhuǎn)門
U1(theta, phi, lambda) * a
//All: 對(duì)其他量子門操作進(jìn)行封裝,提供對(duì)多量子比特便捷操作
All(Measure) * qreg (對(duì)qreg代表的所有量子比特進(jìn)行測(cè)量)
All(H) * qreg (對(duì)qreg代表的所有量子比特進(jìn)行H門操作)
我們可以利用 QuQASM 語(yǔ)言來(lái)完成量子電路圖的編譯和輸出,具體操作方法如下:
# import package
from QuTrunk.circuit import QCircuit
from QuTrunk.circuit.gates import H, CNOT, Measure, All
# allocate resource
qc = QCircuit()
qr = qc.allocate(2)
# apply quantum gates
H * qr[0]
CNOT * (qr[0], qr[1])
All(Measure) * qr
# print circuit
qc.print()
# run circuit
res = qc.run(shots=1024)
# print result
print(res.get_counts())
# draw circuit
print(qc.draw())
輸出結(jié)果如下所示:
qreg q[2]
creg c[2]
H(0) * (q[0])
CX(1) * (q[0], q[1])
Measure(0) * (q[0])
Measure(0) * (q[1])
[{"00": 519}, {"11": 505}]
所以都2022年了,在眾多高級(jí)編程語(yǔ)言的包圍下,還會(huì)有人將匯編作為程序員入門的第一個(gè)編程語(yǔ)言嗎?答案是有的,前段時(shí)間一位用戶發(fā)帖稱:我的叔叔曾經(jīng)是一位程序員,建議我從匯編語(yǔ)言開(kāi)始學(xué)。
Reddit最近對(duì)編程有了點(diǎn)興趣,就找了之前做程序員的叔叔。想問(wèn)問(wèn)有什么建議嗎,結(jié)果叔叔開(kāi)口就是:一定要遠(yuǎn)離那些簡(jiǎn)單的高級(jí)編程語(yǔ)言,如Python或者Ruby。
叔叔解釋到,當(dāng)年他第一次接觸代碼的時(shí)候一度認(rèn)為自己是個(gè)天才,因?yàn)閹滋靸?nèi)就掌握了新技能。直到他接觸了C,才顛覆了自己對(duì)代碼的認(rèn)知。而且之前掌握的那些基礎(chǔ)技能在學(xué)習(xí)C語(yǔ)言的時(shí)候完全沒(méi)用。
如果Reddit能將匯編語(yǔ)言或者C語(yǔ)言入門,以后學(xué)習(xí)任何編程相關(guān)的內(nèi)容都會(huì)非常輕松。
然而經(jīng)過(guò)一番討論之后,網(wǎng)友和Reddit叔叔的觀點(diǎn)截然不同。很多網(wǎng)友認(rèn)為,能說(shuō)出這種觀點(diǎn)的叔叔年齡已經(jīng)非常大了。如果是1980年之前畢業(yè)說(shuō)先學(xué)會(huì)匯編還是很常見(jiàn)的,可以了解,畢竟當(dāng)時(shí)匯編很常見(jiàn)。然而在1990年以后,可以選擇的范圍太多了。
還有網(wǎng)友調(diào)侃到這就好像你叔叔讓你學(xué)車,不要學(xué)怎么開(kāi),而是知道每一個(gè)部分是如何工作的。
平心而論,學(xué)好匯編語(yǔ)言可以幫助我們深入理解計(jì)算機(jī)底層,但不意味著我們就一定要對(duì)高級(jí)編程語(yǔ)言避之不及。我們可以好好學(xué)匯編,但是如果你只是從事軟件看法,適當(dāng)了解一下即可。
]]>