­

Python實現量子態取樣

什麼是量子態矢量?

在前面一篇量子系統模擬的部落格中,我們介紹了使用python去模擬一個量子系統演化的過程。當我們嘗試理解量子態和量子門操作時,可以通過其矩陣形式的運算來描述量子態演化的過程:

\[\left|\psi_t\right>=e^{-iHt}\left|\psi_0\right>
\]

這裡的狄拉克標記符號和矩陣指數運算,在這篇部落格中同樣進行了介紹。我們可以簡單的將該過程理解為:一個矩陣和一個矢量進行了一個點乘操作,得到了一個更新後的態矢量:

\[\overrightarrow{x’}=\textbf{A}\overrightarrow{x}
\]

在量子計算的框架下,由於通用的量子門操作都是酉矩陣(Unitary),因此不論是更新前還是更新後的操作,得到的態矢量總是歸一化的:

\[\left<\psi^*|\psi\right>=1
\]

因此,在本文中考慮取樣時,為了方便計算,我們將態矢量先轉換為概率幅矢量,再進行取樣。概率幅矢量的特徵表現為:

\[\sum_{i=0}^{2^n-1}p_i=1
\]

這裡的\(n\)就表示該量子系統的比特數,一個量子系統的量子態元素個數,或者是概率幅的元素個數是比特數的指數倍數(跟量子比特所佔用的能級數有關,最常用的是兩能級系統,因此為\(2^n\)個元素個數)。

如何實現取樣?

在上一個章節中所表述的是量子態的形式,在轉換為概率幅矢量之後,其每一個元素都代表獲取到當前二進位量子態的概率。這樣我們獲得一個量子態的態矢量或者概率幅矢量時,其實就是獲得了該系統的概率分布。通過該概率分布,我們可以進行蒙特卡羅模擬:先在\([0,1)\)上面進行均勻隨機撒點,同時將概率幅矢量轉換為其對應的累積分布圖,最後計算隨機撒的點對應的累積分布圖的位置,即可獲得當前概率下的模擬取樣,具體實現請參考如下示例。

取樣示例一

我們先假設一個概率幅的分布,再對其進行取樣。

給定一個指數下降的概率幅分布

這裡我們先給定一個\(e^{-x}\)的概率分布函數,注意我們採取的是概率幅,因此要對其進行歸一化的話只需要計算\(y_i=\frac{y_i}{\sum_jy_j}\)即可。

import numpy as np
import matplotlib.pyplot as plt

plt.figure()
x=[i for i in range(32)]
y=[np.exp(-i) for i in range(32)]
y/=sum(y)
plt.title('Distribution of Quantum States')
plt.xlabel('Quantum States')
plt.ylabel('Probabilities')
plt.xticks(x,('0'*(7-len(str(bin(i))))+str(bin(i)).split('b')[1] for i in range(32)),rotation=70)
plt.plot(x,y,color='black')
plt.show()


在這個案例中我們還使用了一些matplotlib的特殊繪圖技巧,這裡我們不展開介紹,後續會單獨寫一篇文章來分析常用的matploblib畫圖姿勢。

均勻隨機數

這裡我們直接使用python的random函數,就可以生成\([0,1)\)之間的均勻隨機數,撒點數量越多,呈現的均勻分布的結果就越明顯。

import random
import matplotlib.pyplot as plt

x = [random.random() for i in range(1000)]
y = [random.random() for i in range(1000)]
plt.figure()
plt.plot(x,y,'.',color='red')
plt.show()

累積分布函數

所謂的累積分布函數,其實就是將前面獲取到的概率幅矢量做一個累積疊加的操作,對應的計算方法如下:

\[y_i=\sum_{j<=i}y_j
\]

我們很容易可以預測,在累積分布函數的終點一定是1,這是因為前面所定義的\(\sum_{i=0}^{2^n-1}p_i=1\)

import numpy as np
import matplotlib.pyplot as plt

plt.figure()
x=[i for i in range(32)]
y=[np.exp(-i) for i in range(32)]
y/=sum(y)
for i in range(len(y)-1):
    y[i+1]+=y[i]
plt.title('Cumulative Distribution Function')
plt.xlabel('Quantum States')
plt.ylabel('Cumulative Probabilities')
plt.xticks(x,('0'*(7-len(str(bin(i))))+str(bin(i)).split('b')[1] for i in range(32)),rotation=70)
plt.plot(x,y,color='black')
plt.show()

量子態取樣

這裡我們將概率分布函數和模擬取樣結果直接放在一起進行對比:

import numpy as np
import matplotlib.pyplot as plt
import random

plt.figure()
x=[i for i in range(32)]
y=[np.exp(-i) for i in range(32)]
y/=sum(y)
plt.plot(x,y,color='black',label='Real Distribution')
for i in range(len(y)-1):
    y[i+1]+=y[i]

sp=np.zeros(32)
for i in range(50):
    r = random.random()
    for j in range(32):
        if y[j]>r:
            sp[j]+=1/50
            break

plt.title('Sampling Results with 50 times')
plt.xlabel('Quantum States')
plt.ylabel('Probabilities')
plt.xticks(x,('0'*(7-len(str(bin(i))))+str(bin(i)).split('b')[1] for i in range(32)),rotation=70)
plt.plot(x,sp,color='red',label='Simulated Sampling')
plt.legend()
plt.show()


這裡我們可以看到結果已經是非常的接近了,如果我們繼續提高取樣次數,結果當然會更加接近真實分布:

因此,在獲得概率幅之後,我們可以根據場景對精度的要求,對該概率幅進行取樣,到這裡就完成了所有的功能實現。

取樣示例二

除了單調函數外,這裡我們再考慮另外一種形式的分布:正弦概率分布函數:

import numpy as np
import matplotlib.pyplot as plt

plt.figure()
x=[i for i in range(32)]
y=[np.sin(i/2)+1 for i in range(32)]
y/=sum(y)
plt.title('Distribution of Quantum States')
plt.xlabel('Quantum States')
plt.ylabel('Probabilities')
plt.xticks(x,('0'*(7-len(str(bin(i))))+str(bin(i)).split('b')[1] for i in range(32)),rotation=70)
plt.plot(x,y,color='black')
plt.show()


由於上面一個示例我們已經介紹完成了基本的操作流程和原理,這裡我們就不過多的贅述,直接展示累積分布函數和最終的模擬取樣效果:

累積分布函數

import numpy as np
import matplotlib.pyplot as plt

plt.figure()
x=[i for i in range(32)]
y=[np.sin(i/2)+1 for i in range(32)]
y/=sum(y)
for i in range(len(y)-1):
    y[i+1]+=y[i]
plt.title('Cumulative Distribution Function')
plt.xlabel('Quantum States')
plt.ylabel('Cumulative Probabilities')
plt.xticks(x,('0'*(7-len(str(bin(i))))+str(bin(i)).split('b')[1] for i in range(32)),rotation=70)
plt.plot(x,y,color='black')
plt.show()

模擬取樣結果

import numpy as np
import matplotlib.pyplot as plt
import random

plt.figure()
x=[i for i in range(32)]
y=[np.sin(i/2)+1 for i in range(32)]
y/=sum(y)
plt.plot(x,y,color='black',label='Real Distribution')
for i in range(len(y)-1):
    y[i+1]+=y[i]

sp=np.zeros(32)
for i in range(3000):
    r = random.random()
    for j in range(32):
        if y[j]>r:
            sp[j]+=1/3000
            break

plt.title('Sampling Results with 3000 times')
plt.xlabel('Quantum States')
plt.ylabel('Probabilities')
plt.xticks(x,('0'*(7-len(str(bin(i))))+str(bin(i)).split('b')[1] for i in range(32)),rotation=70)
plt.plot(x,sp,color='red',label='Simulated Sampling')
plt.legend()
plt.show()

總結概要

對一個量子態矢量進行取樣的過程,主要可以分為三個步驟:

  1. 計算量子態對應的概率分布函數(矢量);
  2. 計算量子態對應的累積分布函數(矢量);
  3. 均勻隨機取樣,映射到累積分布函數中所對應的量子態,在足夠多的取樣次數下就可以完整的模擬出原始的量子態分布。

版權聲明

本文首發鏈接為://www.cnblogs.com/dechinphy/p/state.html
作者ID:DechinPhy
更多原著文章請參考://www.cnblogs.com/dechinphy/