【问题标题】:Is there an efficient way to compute the dot product of two 3D vectors from array index?有没有一种有效的方法来计算数组索引中两个 3D 向量的点积?
【发布时间】:2019-03-05 13:51:50
【问题描述】:

我正在执行以下两个 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 个循环会起作用,但看起来很恶心。这似乎是一种技巧。

我可能还需要将其扩展到非立方体积,所以如果有一个技巧并且它适用于一般的盒子几何体,那将是理想的。

【问题讨论】:

  • 您的代码没有意义,因为您的内部循环只是重复重新计算value 的值——每次都有不同的值,但只有最后一个存储在任何地方。某处是否有数组、列表、元组或简单数据容器?请更清楚地解释您的问题。
  • 是的,我将编辑代码以使其更清楚我在做什么。我只是想只包含相关部分。
  • @ColinB:您将算术结果转换为整数的任何特殊原因(使用int())?如果我将它们作为浮点值可以吗?
  • @ColinB:您的问题是:“有没有一种方法可以在不首先明确计算 x、y、z 分量的情况下计算点积?”。如果这真的是您的问题,那么它不在我的范围内,我只能(毫不含糊地)向您指出点积的替代定义(向量的大小和它们之间夹角的余弦的乘积)。但是,如果您的问题是关于减少可见循环的数量,我可以提供一些解决方案。请澄清。

标签: python algorithm dot-product


【解决方案1】:

点积应该如下做

import numpy as np

R = np.array([Rx,Ry,Rz])
K = np.array([Kx,Ky,Kz])
value = np.dot(R,K)

【讨论】:

  • 这不能解决我的问题。
  • for 循环中的最后一行在做什么?
【解决方案2】:

使用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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多