1. 程式人生 > >Python魔法函式與兩位元量子系統模擬

Python魔法函式與兩位元量子系統模擬

# 技術背景 本文主要涵蓋兩個領域的知識點:python的魔法函式和量子計算模擬,我們可以通過一個實際的案例來先審視一下這兩個需求是如何被結合起來的。 ## 量子計算模擬背景 `ProjectQ`是一個非常優雅的開源量子計算程式設計框架,其原作者是來自與瑞士聯邦理工的博士Damian和Thomas。該量子計算程式設計框架是一個從量子計算應用->量子線路編譯->哈密頓量模擬->量子計算模擬->量子硬體API對接都有相應實現的、非常全面的量子計算程式設計框架。其開源地址為:[https://github.com/ProjectQ-Framework/ProjectQ](https://github.com/ProjectQ-Framework/ProjectQ),支援使用pip進行安裝:`python3 -m pip install projectq --upgrade`。 下面來看一個例子,關於如何使用`projectq`進行量子計算的模擬: ```python [dechin@dechin-manjaro simulator]$ ipython Python 3.8.5 (default, Sep 4 2020, 07:30:14) Type 'copyright', 'credits' or 'license' for more information IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: from projectq import MainEngine In [2]: from projectq.ops import X In [3]: eng = MainEngine() In [4]: qubits = eng.allocate_qureg(2) In [5]: X | qubits[0] In [6]: from projectq.ops import CX In [7]: CX | (qubits[0], qubits[1]) In [8]: eng.flush() In [9]: print (eng.backend.cheat()[1]) [0j, 0j, 0j, (1+0j)] ``` 在這個案例中,我們一共分配了2個量子位元,這2個位元的初始狀態都是$\left|0\right>$態,對應於`projectq`輸出的amplitude向量應為`[1, 0, 0, 0]`。這個向量中的4個元素,分別對應`00,01,10,11`這四個量子態可能出現的概率幅,如果需要計算某一個態被測量所出現的概率的話,需要對其進行取模平方操作: $$ P(00)=(a_{00}+b_{00}i)(a_{00}-b_{00}i) $$ 注意概率幅是一個複數(Complex Number),因此需要取厄米共軛之後再進行點乘操作。 那麼回到上述projectq的使用案例,這個案例在分配了兩個位元之後,對其中的第一個位元執行了泡利矩陣$\sigma^X$操作,然後又執行了一個糾纏門操作`CX`。這裡`CX(i,j)`量子門操作對應的操作為:如果量子位元`i`處於$\left|0\right>$態,不進行任何的操作;但是如果量子位元`i`出於$\left|1\right>$態,則對量子位元`j`執行`取反操作`,也就是說,如果原來`j`是$\left|0\right>$就會變成$\left|1\right>$,如果原來`j`是$\left|1\right>$就會變成$\left|0\right>$。這就是量子糾纏在量子計算中的作用,而多位元的門操作在實際的硬體體系中的高質量實現,目前依舊是一大難題。而量子疊加特性就體現在,一個量子位元可能處於$\left|0\right>$態,也可能處於$\left|1\right>$態,還有可能處在$\left|0\right>$和$\left|1\right>$的中間態,這種中間態會以上述提到的概率幅的形式來對$\left|0\right>$和$\left|1\right>$進行劃分: $$ P(0)=(a_0+b_0i)\cdot(a_0-b_0i)\\ P(1)=(a_1+b_1i)\cdot(a_1-b_1i) $$ 這些的概率幅就可以用一個向量的形式組織起來: $$ \left|\psi\right>=\left(a_0+b_0i, a_1+b_1i\right)^{T} $$ 最終這個向量的元素個數會`隨著位元數的增加而指數增長`,當位元數增長到`41`時,所需要儲存的記憶體空間需要`32TB`以上!要注意的是,因為計算過程中需要將所有的概率幅載入到記憶體中,所以這裡區別於硬碟儲存空間,單指記憶體就需要到`32TB`的大小!因此,使用經典計算機去模擬量子計算,其實是一種非常消耗資源的手段。當然,量子計算模擬器依然有其研究的價值,在現階段量子晶片規模和質量無法提升的狀態下,模擬器就起到了重要的作用。 ## Python的魔法函式實現 如果讀者需要了解詳細全面Python的魔法函式的實現方案,可以從本文的參考連結中獲取兩篇不錯的文章。這裡我們僅針對上述`projectq`的程式碼用例中所可能使用到的部分功能:`__or__`和`__str__`,並且可以針對其進行一個簡單的復現。 Python的魔法函式可用於定義一個類(class)的特殊運算算符,如:類的加減乘除等,在引入魔法函式之後,就不需要單獨對類中的元素進行操作,而可以用魔法函式對操作進行封裝。最後的效果,我們可以直接在程式碼中使用操作符對不同的類進行操作,比如可以自定義`class1 + class2`這樣的二元操作算符。在本章節我們不詳細展開介紹,可以參考下述的具體使用示例或者參考連結中的博文。 # 量子態定義及實現 根據第一個章節中對量子態向量的介紹,這裡我們可以實現一個簡單的量子態的類,我們可以僅考慮兩個量子位元的簡單系統: ```python # QubitPair.py import numpy as np class QubitPair: def __init__(self): self.state = np.array([1, 0, 0, 0], dtype=complex) def __str__(self): return str(self.state) ``` 這個量子態的類的定義非常簡單,就是一個`4×1`的矩陣。需要補充說明的是,這裡我們定義了一個`__str__(self)`的魔法函式,該函式主要用於列印類的字串表示,如我們這裡直接將量子態向量轉化成`str`格式之後進行輸出。那麼我們如果去`print`一個自定義的`QubitPair`類的話,就會展示當前類所對應的概率幅的字串表示。 # 量子門操作定義及實現 關於量子門操作,我們可以將其視作作用在量子態向量上的矩陣,這裡我們可以先展示定義好的門操作的Python類再對其進行展開說明: ```python # Operator.py import numpy as np class QubitOperator: """Pauli rotations and entanglement on qubit-pair""" def __init__(self, operation=None, theta=0, index=0): self.index = index self.name = operation paulix = np.array([[0, 1], [1, 0]], dtype=complex) pauliy = np.array([[0, -1j], [1j, 0]], dtype=complex) pauliz = np.array([[1, 0], [0, -1]], dtype=complex) cnot = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) if operation == 'X' or operation == 'Rx': self.operation = np.cos(theta/2)*np.identity(2)-1j*np.sin(theta/2)*paulix elif operation == 'Y' or operation == 'Ry': self.operation = np.cos(theta/2)*np.identity(2)-1j*np.sin(theta/2)*pauliy elif operation == 'Z' or operation == 'Rz': self.operation = np.cos(theta/2)*np.identity(2)-1j*np.sin(theta/2)*pauliz elif operation == 'CX' or operation == 'CNOT': self.operation = cnot def __or__(self, qubitpair): if self.name == 'CX' or self.name == 'CNOT': qubitpair.state = np.dot(self.operation, qubitpair.state) return None elif self.index == 0: operation = np.kron(self.operation, np.identity(2)) else: operation = np.kron(np.identity(2), self.operation) qubitpair.state = np.dot(operation, qubitpair.state) ``` ## 單位矩陣與泡利矩陣的定義 這些是基本的泡利矩陣,這三個兩能級體系的泡利矩陣具有非常好的物理性質,如都是酉矩陣且存在特殊的對易關係等: $$ \sigma^I=\left( \begin{array}{1} 1 & 0\\ 0 & 1 \end{array} \right), \sigma^X=\left( \begin{array}{1} 0 & 1\\ 1 & 0 \end{array} \right), \sigma^Y=\left( \begin{array}{1} 0 & -i\\ i & 0 \end{array} \right), \sigma^Z=\left( \begin{array}{1} 1 & 0\\ 0 & -1 \end{array} \right) $$ ## 矩陣指數與旋轉門操作 矩陣的指數計算一般採用泰勒級數展開的方法來進行定義: $$ e^{A}=\sum^{\infty}_{k=0}\frac{1}{k!}A^{k} $$ 這裡如果我們代入上述介紹的泡利矩陣就會得到這樣的結果: $$ R_M=e^{-i\theta\sigma^M}=cos\left(\frac{\theta}{2}\right)\sigma^I-isin\left(\frac{\theta}{2}\right)M,M\in\left(X,Y,Z\right) $$ ## CX門操作的定義 在上述提到的所有的量子門操作中,`CX`是唯一的一個兩位元量子門操作,也就是同時作用在兩個量子位元上面,其矩陣形式的定義如下所示: $$ CX=\left( \begin{array}{1} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0 \end{array} \right) $$ ## 使用魔法函式`__or__`來實現量子門操作運算 我們首先簡單談一下為什麼要用`__or__`這個魔法函式而不是其他的二元運算子來實現,這點跟開源庫`ProjectQ`是同步的,理由是我們在量子力學中的運算,一般寫成如下的形式: $$ \left|\psi_t\right>=U\left|\psi_0\right> $$ 將量子態寫成狄拉克符號的形式,中文稱為"左矢"和"右矢",英文稱之為"bra"和"ket"。因此豎線形式的定義,在形式上會更加契合量子力學的思維,當然,就算是換成其他的符號也是無可厚非的。 # 功能測試驗證 在定義了`量子態`的類和`量子門操作的類`之後,我們可以寫如下所示的一個測試指令碼來測試程式的執行效果: ```python # TestQubits.py from QubitPair import QubitPair from Operator import QubitOperator if __name__ == '__main__': qubits = QubitPair() print ('The initial state is: {}'.format(qubits)) QubitOperator('X', 3.1415926, 0) | qubits print ('Applying X on the 0th qubit...') print ('The new state is: {}'.format(qubits)) QubitOperator('CX') | qubits print ('Applying entanglement on qubits...') print ('The new state is: {}'.format(qubits)) QubitOperator('X', 3.1415926, 0) | qubits print ('Applying X on the 0th qubit...') print ('The new state is: {}'.format(qubits)) QubitOperator('CX') | qubits print ('Applying entanglement on qubits...') print ('The new state is: {}'.format(qubits)) ``` 這個程式的測試邏輯為:先定義一個兩位元的量子系統,然後對第一個位元執行`X`門操作,使得其從$\left|0\right>$態變成$\left|1\right>$態,再對這兩個位元執行糾纏門`CX`操作,觀察其態的變化情況。之後再將第一個位元的狀態變回$\left|0\right>$態,再觀察作用`CX`的態的變化情況,執行結果如下所示: ```bash [dechin@dechin-manjaro simulator]$ python3 TestQubits.py The initial state is: [1.+0.j 0.+0.j 0.+0.j 0.+0.j] Applying X on the 0th qubit... The new state is: [2.67948966e-08+0.j 0.00000000e+00+0.j 0.00000000e+00-1.j 0.00000000e+00+0.j] Applying entanglement on qubits... The new state is: [2.67948966e-08+0.j 0.00000000e+00+0.j 0.00000000e+00+0.j 0.00000000e+00-1.j] Applying X on the 0th qubit... The new state is: [ 7.17966483e-16+0.00000000e+00j -1.00000000e+00+0.00000000e+00j 0.00000000e+00-2.67948966e-08j 0.00000000e+00-2.67948966e-08j] Applying entanglement on qubits... The new state is: [ 7.17966483e-16+0.00000000e+00j -1.00000000e+00+0.00000000e+00j 0.00000000e+00-2.67948966e-08j 0.00000000e+00-2.67948966e-08j] ``` 這個結果所展示出來的數字也許比較亂,這是因為在運算過程中的計算精度不足所導致的,這裡低於`1e-06`的數字其實我們可以認為就是`0`。那麼我們從這個結果中可以分析總結出量子態的演變歷程: $$ \left|00\right>\Rightarrow\left|10\right>\Rightarrow\left|11\right>\Rightarrow\left|01\right>\Rightarrow\left|01\right> $$ *注意*:上面的這種寫法,其實不太合乎程式語言的邏輯,一般從右到左的方向才是從低位到高位的寫法。因此,嚴格來說寫法應該是:$\left|00\right>\Rightarrow\left|01\right>\Rightarrow\left|11\right>\Rightarrow\left|10\right>\Rightarrow\left|10\right>$。 這裡我們就完成了基於魔法函式的量子計算模擬的過程,感興趣的讀者可以自行嘗試更多的玩法,這裡就不進行更多的測試了! # 總結概要 本文主要嘗試了用Python的魔法函式`__str__`來定義一個量子態,以及使用`__or__`來定義一個量子門操作的運算,我們附帶的也簡單介紹了一下量子計算模擬的一些背景知識。因為程式有簡單而明確的執行邏輯,因此用程式語言的方式來定義和理解科學常識,也能夠加深對科學的理解。 # 版權宣告 本文首發連結為:https://www.cnblogs.com/dechinphy/p/magic.html 作者ID:DechinPhy 更多原著文章請參考:https://www.cnblogs.com/dechinphy/ # 參考連結 1. https://zhuanlan.zhihu.com/p/24567545 2. https://www.cnblogs.com/jhao/p/6022