Broadcasting/Vectorizing python/NumPy 中的内部和外部 for 循环
Broadcasting/Vectorizing inner and outer for loops in python/NumPy
目的
我使用 vectorization
将双 for loop
变成了单 for loop
。我现在想摆脱最后一个 loop
.
我想 slice
一个 Nx3 array
坐标并计算切片部分和剩余部分之间的距离 不使用 for 循环.
两例
(1) 切片总是 3x3
。
(2) 切片是可变的,即 Mx3
其中 M 总是明显小于 N
矢量化切片的 1 行与其余部分交互的交互很简单。但是,我坚持使用 for 循环来执行(在大小为 3 的切片的情况下)3 个循环,以计算所有距离。
上下文:
Nx3数组为原子坐标,切片为特定分子中的所有原子。我想计算给定分子与系统其余部分相互作用的能量。第一步是计算分子中每个原子与所有其他原子之间的距离。第二部分是在函数中使用这些距离来计算能量,这超出了本题的范围。
这是我的最小工作示例(我有 vectorized
内部循环,但是,需要(真的很想...)vectorize
outer loop
。那个循环不会总是只有 3 个大小,并且 python
在 for 循环中很慢。
最小工作示例
import numpy as np
box=10 # simulation box is size 10 for this example
r = np.random.rand(1000,3) * box # avoids huge numbers later by scaling coords
start=0 #fixed starting index for example (first atom)
end=2 #fixed ending index for example (last atom)
rj=np.delete(r, np.arange(start,end), 0)
ri = r[np.arange(start,end),:]
atoms_in_molecule, coords = np.shape(ri)
energy = 0
for a in range(atoms_in_molecule):
rij = ri[a,:] - rj # I want to get rid of this 'a' index dependance
rij = rij - np.rint(rij/box)*box # periodic boundary conditions - necessary
rij_sq = np.sum(rij**2,axis=1)
# perform energy calculation using rij_sq
ener = 4 * ((1/rij_sq)**12 - (1/rij_sq)**6) # dummy LJ, do not optimize
energy += np.sum(ener)
print(energy)
这个问题不是关于优化我已有的矢量化。我玩过 pdist/cdist 和其他人。我想要的只是摆脱讨厌的原子循环。剩下的我会优化。
这里是你如何做到的:
R = ri[:,None] - rj[None, :]
R = R - np.rint(R/box)*box
R_sq = np.sum(np.square(R), axis=2)
energy = np.sum(4 * ((1/R_sq)**12 - (1/R_sq)**6))
目的
我使用 vectorization
将双 for loop
变成了单 for loop
。我现在想摆脱最后一个 loop
.
我想 slice
一个 Nx3 array
坐标并计算切片部分和剩余部分之间的距离 不使用 for 循环.
两例
(1) 切片总是 3x3
。
(2) 切片是可变的,即 Mx3
其中 M 总是明显小于 N
矢量化切片的 1 行与其余部分交互的交互很简单。但是,我坚持使用 for 循环来执行(在大小为 3 的切片的情况下)3 个循环,以计算所有距离。
上下文:
Nx3数组为原子坐标,切片为特定分子中的所有原子。我想计算给定分子与系统其余部分相互作用的能量。第一步是计算分子中每个原子与所有其他原子之间的距离。第二部分是在函数中使用这些距离来计算能量,这超出了本题的范围。
这是我的最小工作示例(我有 vectorized
内部循环,但是,需要(真的很想...)vectorize
outer loop
。那个循环不会总是只有 3 个大小,并且 python
在 for 循环中很慢。
最小工作示例
import numpy as np
box=10 # simulation box is size 10 for this example
r = np.random.rand(1000,3) * box # avoids huge numbers later by scaling coords
start=0 #fixed starting index for example (first atom)
end=2 #fixed ending index for example (last atom)
rj=np.delete(r, np.arange(start,end), 0)
ri = r[np.arange(start,end),:]
atoms_in_molecule, coords = np.shape(ri)
energy = 0
for a in range(atoms_in_molecule):
rij = ri[a,:] - rj # I want to get rid of this 'a' index dependance
rij = rij - np.rint(rij/box)*box # periodic boundary conditions - necessary
rij_sq = np.sum(rij**2,axis=1)
# perform energy calculation using rij_sq
ener = 4 * ((1/rij_sq)**12 - (1/rij_sq)**6) # dummy LJ, do not optimize
energy += np.sum(ener)
print(energy)
这个问题不是关于优化我已有的矢量化。我玩过 pdist/cdist 和其他人。我想要的只是摆脱讨厌的原子循环。剩下的我会优化。
这里是你如何做到的:
R = ri[:,None] - rj[None, :]
R = R - np.rint(R/box)*box
R_sq = np.sum(np.square(R), axis=2)
energy = np.sum(4 * ((1/R_sq)**12 - (1/R_sq)**6))