如何向量化 python 中的以下四个 for 循环?

How can I vectorize the following four for-loops in python?

我必须构造一个大小为 (Nx*Ny, Nx*Ny) 的矩阵,其中 NxNy 可以大于 100。目前我正在使用四个 for 循环来初始化我的最终矩阵“matrix_result”(维度 (Nx*Ny, Nx*Ny))非常慢。

前两个循环遍历数组 xs 和 ys 中的所有元素。后两个循环再次针对 xs 和 ys 中的相同元素。然后我用 matrix_idx = idx_y1 + Ny * idx_xmatrix_idy = idx_y2 + Ny * idx_x2.

构造 matrix_result 的 x-index 和 y-index

这是完整的代码。如何向量化矩阵“matrix_result”的这些初始化?

import numpy as np

Nx = 100
Ny = 100

xs = np.linspace(0.0, 2.0, Nx)
ys = np.linspace(0.0, 2.0, Ny)

matrix_result = np.zeros((Nx * Ny, Nx * Ny))

for idx_x1 in range(Nx):
    for idx_y1 in range(Ny):

    # Get values of the arrays xs and ys
    x1 = xs[idx_x1]
    y1 = ys[idx_y1]

    # Compute arctan2 of y1 and x1
    argument1 = np.arctan2(y1, x1)

    for idx_x2 in range(Nx):
        for idx_y2 in range(Ny):

            if idx_x1 != idx_x2 or idx_y1 != idx_y2:

                # Get values of the arrays xs and ys
                x2 = xs[idx_x2]
                y2 = ys[idx_y2]

                # Compute arctan2 of y1 and x1
                argument2 = np.arctan2(y2, x2)

                # Compute the elements of the matrix matrix_results.
                distance_12 = np.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
                matrix_element = np.cos(argument2 - argument1) * np.exp(distance_12)

                # Construct indices of the matrix matrix_result with dimension (Nx * Ny, Nx * Ny)
                matrix_idx = idx_y1 + Ny * idx_x1
                matrix_idy = idx_y2 + Ny * idx_x2

                # Insert elements into matrix
                matrix_result[matrix_idx, matrix_idy] = matrix_element
def vectorised_calculation(xs, xy):
    Nx = len(xs)
    Ny = len(ys)
    matrix_result = np.zeros((Nx * Ny, Nx * Ny))

    indices = np.indices([Nx,Ny,Nx,Ny])
    #Remove those sets of indices that do not satisfy the following condition
    mask = np.logical_or(indices[0] != indices[2], indices[1] != indices[3])
    indices = indices[:, mask]

    x1 = xs[indices[0]]
    y1 = ys[indices[1]]
    x2 = xs[indices[2]]
    y2 = ys[indices[3]]
    argument1 = np.arctan2(y1,x1)
    argument2 = np.arctan2(y2,x2)
    
    # Compute the elements of the matrix matrix_results.
    distance_12 = np.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
    matrix_element = np.cos(argument2 - argument1) * np.exp(distance_12)
        
    # Construct indices of the matrix matrix_result with dimension (Nx * Ny,     Nx *     Ny)
    matrix_idx = indices[1] + Ny * indices[0]
    matrix_idy = indices[3] + Ny * indices[2]
        
    # Insert elements into matrix
    matrix_result[matrix_idx, matrix_idy] = matrix_element

    return matrix_result

我发现很难解释这个问题,但据我所知,这符合你的要求。

通常,您可以使用 np.indices 向量化嵌套 for 循环集。

xs = np.random.rand(40)
ys = np.random.rand(40)
s = time.time()
func1(xs, ys)
print("time taken for original:", time.time() - s)
s = time.time()
func2(xs, ys)
print("time taken for vectorised:", time.time() - s)

原始时间:19.610620737075806

矢量化所用时间:0.3943142890930176

有:

xs = np.linspace(0.0, 2.0, 100)
ys = np.linspace(0.0, 2.0, 100)

使用 plt.imshow 时会得到以下输出: