用最有效的方法编写python代码

2024-09-27 23:26:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Python库MDAnalysis编写代码。 我有一个原子位置的数组(502,3) 我想得到一系列键(原子(I+1)-原子(I)的位置向量) 然后我想得到一个平均张量qab=它本质上是anp.外部(ua、ub) 所有原子的平均值。在

我可以用fortran子例程重写这段代码,但我认为看到一个美味的numpy切片解决方案会更令人愉快:)这是我写的代码,我想让它更快更漂亮。提前谢谢你的帮助。在

bb = u.selectAtoms("all")
coor = bb.positions
print coor.shape # return is (502,3)
# the coordinates of the atoms that we split on 3 dimensions
bbx = coor[:,0]
bby = coor[:,1]
bbz = coor[:,2]
#the bond vectors we obtain by subtructing atoms positions 
bbx_ave = bbx[:-1] - bbx[1:]
bby_ave = bby[:-1] - bby[1:]
bbz_ave = bbz[:-1] - bbz[1:]
#now we concentrate everything back so we have one big array
bb_res = np.vstack((bbx_ave, bby_ave, bbz_ave))
# print bb_res.shape # the return is (3,501)
# now we have an array of bonds

# qab - the result tensor which we want to get
nq = len(bb_res)
qab = np.zeros((3,3))
count = 0.

for i in xrange(0, nq):
    for j in xrange(0, i+1):
        qab = qab + np.outer(bb_res[:,i], bb_res[:,j])
        count += 1.
qab = qab/count
print qab
[[ 0.21333394  0.5333341   0.        ]
 [ 0.5333341   4.          0.        ]
 [ 0.          0.          0.        ]]

Tags: the代码countnpresweprint原子
2条回答

我已经尽力了。很容易更有效地生成bb_res,但我无法优化双for循环。在我的电脑上,我的方法大约快26%。另外,基于你对问题的陈述,我认为你的代码中有一个bug,我在评论中指出了这一点。我已经在我的答案中修复了这个错误,因此它产生的输出与您的代码略有不同。在

import numpy as np
from numpy.random import rand

# create some mock data
coor = rand(502,3)

def qab(coor):
  # this is the transpose of your bb_res
  # transposing is as simple as bb_res.T
  bb_res = coor[:-1] - coor[1:]

  nq = bb_res.shape[1]
  out = np.zeros((3,3))

  for i in xrange(0, nq):
    for j in xrange(0, i):
      tmp = np.outer(bb_res[i], bb_res[j])
      out += tmp + tmp.T
    out += np.outer(bb_res[i], bb_res[i])
  return out / nq**2

print qab(coor)

假设您在代码片段中的意思是nq = bb_res.shape[1],那么我可以用以下矢量化代码重现输出:

d = np.diff(coor, axis=0)
I, J = np.triu_indices(d.shape[0])
print np.dot(d[J].T, d[I]) / len(J)

相关问题 更多 >

    热门问题