我正在执行两个3D向量的以下点积:
import numpy as np
Nk = 8
Ns = 15
k_box = np.zeros(Nk**3)
R_box = np.zeros(Ns**3)
for k in range(Nk**3):
Kx = int(k / (Nk*Nk))
Ky = int(k / Nk) % Nk
Kz = k % Nk
for R in range(Ns**3):
Rx = int(R / (Ns*Ns))
Ry = int(R / Ns) % Ns
Rz = R % Ns
# This is the only place these variables are used!
dot_product = Rx*Kx + Ry*Ky + Rz*Kz
k_box[k], R_box[R] = perform_some_calculation(dot_product)
是否有一种无需先显式计算x, y, z
分量就可以计算点积的方法?将其转换为6个循环会起作用,但看起来很麻烦。这似乎是一种技巧。
我可能还需要将其扩展到非立方体积,因此,如果有一个窍门并且它适用于一般的盒子几何形状,那将是理想的选择。
答案 0 :(得分:2)
点积应按以下步骤进行
import numpy as np
R = np.array([Rx,Ry,Rz])
K = np.array([Kx,Ky,Kz])
value = np.dot(R,K)
答案 1 :(得分:0)
使用itertools.product
生成点列表,该列表等效于每个坐标范围的<笛卡尔笛卡尔积:
>>> list(itertools.product(range(3), range(3), range(3)))
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 2, 0),
(0, 2, 1), (0, 2, 2), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1),
(1, 1, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (2, 0, 0), (2, 0, 1), (2, 0, 2),
(2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 2, 0), (2, 2, 1), (2, 2, 2)]
您还可以将所有6个坐标组合为一个生成器:
coords = itertools.product(range(Nk), range(Nk), range(Nk), range(Ns), range(Ns), range(Ns))
for kz, ky, kx, rz, ry, rx in coords:
k, r = Nk * (Nk * kz + ky) + kx, Ns * (Ns * rz + ry) + rx
dot_product = kx * rx + ky * ry + kz * rz
k_box[k], R_box[r] = perform_some_calculation(dot_product)
或者,为避免索引计算,请使用enumerate
:
for k, (kz, ky, kx) in enumerate(itertools.product(range(Nk), range(Nk), range(Nk))):
for r, (rz, ry, rx) in enumerate(itertools.product(range(Ns), range(Ns), range(Ns))):
dot_product = kx * rx + ky * ry + kz * rz
k_box[k], R_box[r] = perform_some_calculation(dot_product)