[英]Is it possible to do linalg.multi_dot for an ndarray along an axis?
首先,我有一組12(2x2)矩陣。
II = np.identity(2, dtype=complex)
X = np.array([[0, 1], [1, 0]], dtype=complex)
Y = np.array([[0, -1j], [1j, 0]], dtype=complex)
Z = np.array([[1, 0], [0, -1]], dtype=complex)
PPP = (-II + 1j*X + 1j*Y + 1j*Z)/2
PPM = (-II + 1j*X + 1j*Y - 1j*Z)/2
PMM = (-II + 1j*X - 1j*Y - 1j*Z)/2
MMM = (-II - 1j*X - 1j*Y - 1j*Z)/2
MMP = (-II - 1j*X - 1j*Y + 1j*Z)/2
MPP = (-II - 1j*X + 1j*Y + 1j*Z)/2
PMP = (-II + 1j*X - 1j*Y + 1j*Z)/2
MPM = (-II - 1j*X + 1j*Y - 1j*Z)/2
目前,我有一個功能operator_groups
,它為每個j
循環從該組中繪制一個隨機矩陣,並將其追加到列表sequence
。 然后,將所有j
循環之間繪制的隨機矩陣用於進行一些計算,與此處的討論無關。 在j
循環的末尾,列表sequence
中元素的sequence
被顛倒,然后執行linalg.multi_dot
,然后采用其linalg.multi_dot
共軛(因此.conj().T
)
def operator_groups():
return random.choice([II, X, Y, Z, PPP, PPM, PMM, MMM, MMP, MPP, PMP, MPM])
for i in range(1, sample_size+1, 1):
sequence = []
for j in range(1, some_number, 1):
noise = operator_groups()
"""some matrix calculations here"""
sequence.append(noise)
sequence_inverse = np.linalg.multi_dot(sequence[::-1]).conj().T
現在,我希望通過在一個大矩陣中執行j
循環來向量化i
循環 。 現在, noise
是從組中隨機采樣的N個矩陣的ndarray(而不是僅1個矩陣),每個矩陣表示j
的迭代,但並行化。 代碼現在看起來像這樣。
def operator_groups(sample_size):
return random.sample([II, X, Y, Z], sample_size)
sequence = []
for j in range(1, some_number, 1):
noise = operator_groups(sample_size)
sequence.append(noise)
sequence_inverse = np.linalg.multi_dot(sequence[::-1]).conj().T
現在,該sequence
是多維數組,在將多維noise
添加到sequence
的正確順序時遇到了麻煩,然后又linalg.multidot
了對sequence
的逆執行linalg.multidot
並采用其Hermitian共軛的問題。 在這種情況下,我想對與每個j
循環相對應的每個j
行的所有存儲的noise
的倒數進行multi_dot
處理。 如何才能做到這一點?
我將在下面提供一些“偽示例”,以使用j
= 3進一步演示我的問題。為簡單起見,這里我僅“隨機繪制” X, Y, Z
。
非向量化情況:
i = 1
sequence = []
j = 1
noise = X (randomised)
sequence.append(noise)
sequence = [X]
j = 2
noise = Y (randomised)
sequence.append(noise)
sequence = [X, Y]
j = 3
noise = Z (randomised)
sequence.append(noise)
sequence = [X, Y, Z]
end of j loop
take reverse order: [Z, Y, X]
do multi_dot: [ZYX] (Note: dot products, not element-wise multiplication)
take conjugate and tranpose(to get Hermitian): [ZYX].conj().T = [ZYX.conj().T]
向量化案例(假設我是否在執行sample_size
= 3):
sequence = []
j = 1
noise = [X,Z,Y](randomised)
sequence.append(noise)
sequence = [[X,Z,Y]]
j = 2
noise = [Z,Y,X] (randomised)
sequence.append(noise)
sequence = [[X,Z,Y],
[Z,Y,X]]
j = 3
noise = [Z,Z,X] (randomised)
sequence.append(noise)
sequence = [[X,Z,Y],
[Z,Y,X],
[Z,Z,X]]
end of j loop
take reverse order: [[Z,Z,X],
[Z,Y,X],
[X,Z,Y]]
do multi_dot(along an axis,
which is what I have trouble with): [ZZX,ZYZ,XXY]
take conjugate and tranpose(to get Hermitian):
[ZZX,ZYZ,XXY].conj().T = [ZZX.conj().T, ZYZ.conj().T, XXY.conj().T]
我希望這些例子能說明我的問題
使用您的兩個隨機選擇器:
In [13]: operator_groups() # returns one (2,2) array
Out[13]:
array([[-0.5+0.5j, 0.5-0.5j],
[-0.5-0.5j, -0.5-0.5j]])
In [14]: operator_groups1(4) # returns a list of (2,2) arrays
Out[14]:
[array([[0.+0.j, 1.+0.j],
[1.+0.j, 0.+0.j]]), array([[ 0.+0.j, -0.-1.j],
[ 0.+1.j, 0.+0.j]]), array([[ 1.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j]]), array([[1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j]])]
您的循環創建一個數組列表:
In [15]: seq=[]
...: for j in range(4):
...: seq.append(operator_groups())
...:
In [16]: seq
Out[16]:
[array([[-0.5-0.5j, -0.5+0.5j],
[ 0.5+0.5j, -0.5+0.5j]]), array([[1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j]]), array([[-0.5+0.5j, -0.5-0.5j],
[ 0.5-0.5j, -0.5-0.5j]]), array([[-0.5-0.5j, 0.5-0.5j],
[-0.5-0.5j, -0.5+0.5j]])]
可以將其賦予multi_dot
以便進行順序multi_dot
:
In [17]: np.linalg.multi_dot(seq)
Out[17]:
array([[0.-1.j, 0.+0.j],
[0.+0.j, 0.+1.j]])
如果使用groups選擇器構建序列,則會獲得列表列表:
In [18]: seq=[]
...: for j in range(4):
...: seq.append(operator_groups1(3))
...:
In [19]: seq
Out[19]:
[[array([[ 0.+0.j, -0.-1.j],
[ 0.+1.j, 0.+0.j]]), array([[ 1.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j]]), array([[0.+0.j, 1.+0.j],
[1.+0.j, 0.+0.j]])], [array([[ 0.+0.j, -0.-1.j],
[ 0.+1.j, 0.+0.j]]), array([[ 1.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j]]), array([[0.+0.j, 1.+0.j],
[1.+0.j, 0.+0.j]])], [array([[1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j]]), array([[ 1.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j]]), array([[ 0.+0.j, -0.-1.j],
[ 0.+1.j, 0.+0.j]])], [array([[1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j]]), array([[ 1.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j]]), array([[ 0.+0.j, -0.-1.j],
[ 0.+1.j, 0.+0.j]])]]
In [20]: len(seq)
Out[20]: 4
In [21]: len(seq[0])
Out[21]: 3
我們可以“堆疊”內部列表,創建一個(n,2,2)個數組的列表:
In [22]: seq1 = [np.stack(el) for el in seq]
In [23]: seq1
Out[23]:
[array([[[ 0.+0.j, -0.-1.j],
[ 0.+1.j, 0.+0.j]],
[[ 1.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j]],
[[ 0.+0.j, 1.+0.j],
[ 1.+0.j, 0.+0.j]]]), array([[[ 0.+0.j, -0.-1.j],
[ 0.+1.j, 0.+0.j]],
[[ 1.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j]],
[[ 0.+0.j, 1.+0.j],
[ 1.+0.j, 0.+0.j]]]), array([[[ 1.+0.j, 0.+0.j],
[ 0.+0.j, 1.+0.j]],
[[ 1.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j]],
[[ 0.+0.j, -0.-1.j],
[ 0.+1.j, 0.+0.j]]]), array([[[ 1.+0.j, 0.+0.j],
[ 0.+0.j, 1.+0.j]],
[[ 1.+0.j, 0.+0.j],
[ 0.+0.j, -1.+0.j]],
[[ 0.+0.j, -0.-1.j],
[ 0.+1.j, 0.+0.j]]])]
然后,我們可以在此列表上重復應用matmul
:
In [25]: res = seq1[0]
...: for el in seq1[1:]:
...: res = res@el
...:
...:
In [26]: res
Out[26]:
array([[[1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j]],
[[1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j]],
[[1.+0.j, 0.+0.j],
[0.+0.j, 1.+0.j]]])
實際上, matmul
就像dot
一樣,但是它將前導維視為“批量”維。
使用隨機選擇時,比較不同的結果很麻煩(除非我設置了種子),所以我將驗證留給您。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.