這裏有一個方法利用的slicing
和總結 -
def slicing_summing(a,b,c):
c0 = b[:,1]*c[:,2] - b[:,2]*c[:,1]
c1 = b[:,2]*c[:,0] - b[:,0]*c[:,2]
c2 = b[:,0]*c[:,1] - b[:,1]*c[:,0]
return a[:,0]*c0 + a[:,1]*c1 + a[:,2]*c2
我們可以用一行代替計算c0, c1, c2
及其堆疊版本的前三個步驟,如 -
b[:,[1,2,0]]*c[:,[2,0,1]] - b[:,[2,0,1]]*c[:,[1,2,0]]
這將產生另一個(n,3)
陣列,其具有與a
到用於總和還原導致(n,)
形陣列。通過建議的slicing_summing
方法,我們直接進入那個(n,)
形狀的陣列,並將這三個切片相加,從而避免了中間的(n,3)
陣列。
採樣運行 -
In [86]: # Setup inputs
...: n = 871
...: a = np.random.rand(n, 3)
...: b = np.random.rand(n, 3)
...: c = np.random.rand(n, 3)
...:
In [87]: # Original approach
...: omega = np.einsum('ij, ij->i', a, np.cross(b, c))
In [88]: np.allclose(omega, slicing_summing(a,b,c))
Out[88]: True
運行測試 -
In [90]: %timeit np.einsum('ij, ij->i', a, np.cross(b, c))
10000 loops, best of 3: 84.6 µs per loop
In [91]: %timeit slicing_summing(a,b,c)
1000 loops, best of 3: 63 µs per loop
過去的問題已經表明,它做什麼,目前的'cross'是有效的,http://stackoverflow.com/q/ 39662540/901925 – hpaulj
單獨的交叉產品很好,這是一個點產品,使其具有特定的對稱性。這讓我覺得奇怪,應該沒有進一步的優化。 –
如果A,B和C是特定的3向量,那麼當epsilon是Levi-Civita符號時,您正在尋找的愛因斯坦符號是'\ epsilon_ {ijk} A^i B^j C^k'。它不認爲它已經在'numpy.einsum'中實現了。作爲@B的 。 M.說,這與'np.dstack(A,B,C)'的設計完全相同。 – tsvikas