私は、python3で可能な限り効率的に計算する方法を検討しています。フォームの二重和内のドット積:
import cmath
for j in range(0,N):
for k in range(0,N):
sum_p += cmath.exp(-1j * sum(a*b for a,b in zip(x, [l - m for l, m in zip(r_p[j], r_p[k])])))
ここで、r_np は数千のトリプルの配列で、xa は定数トリプルです。N=1000トリプルの長さのタイミングは約2.4sです。numpy を使用して同じ:
import numpy as np
for j in range(0,N):
for k in range(0,N):
sum_np = np.add(sum_np, np.exp(-1j * np.inner(x_np,(r_np[j] - r_np[k]))))
実際には約 のランタイムで遅くなります4.0s。これは大きなベクトル化の利点がないためだと思います。短い 3 ドット 3 だけが np.dot であり、ループ内の N^2 を開始することによって消費されます。ただし、map と mul を使用してプレーンな python3 を使用することで、最初の例よりもわずかに高速化することができます。
from operator import mul
for j in range(0,N):
for k in range(0,N):
sum_p += cmath.exp(-1j * sum(map(mul,x, [l - m for l, m in zip(r_p[j], r_p[k])])))
ランタイムで2.0s
if 条件を使用して casej=kを計算しないようにします。
r_np[j] - r_np[k] = 0
したがって、ドット積も0になるか、合計を2つに分割して同じ結果を達成します
for j in range(0,N):
for k in range(j+1,N):
...
for k in range(0,N):
for j in range(k+1,N):
...
どちらもさらに遅くなりました。したがって、全体が O(N^2) でスケーリングされます。並べ替えなどの方法を使用して、ループを取り除き、O(N logN) でスケーリングできるかどうか疑問に思います。N~6000問題は、数千の合計を計算する必要があるため、トリプルのセットに対して 1 桁の秒ランタイムが必要なことです。それ以外の場合は、scipy の weave 、numba、pyrex、または python を試すか、完全に C パスをたどる必要があります…</p>
助けてくれてありがとう!
編集:
データ サンプルは次のようになります。
# numpy arrays
x_np = np.array([0,0,1], dtype=np.float64)
N=1000
xy = np.multiply(np.subtract(np.random.rand(N,2),0.5),8)
z = np.linspace(0,40,N).reshape(N,1)
r_np = np.hstack((xy,z))
# in python format
x = (0,0,1)
r_p = r_np.tolist()