es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La forma más rápida de encontrar todos los pares únicos de vectores 3D (casi) paralelos de N vectores en Numpy.

Tengo una gran matriz de N = 10000 vectores 3D. Para simplificar, usaré una matriz de 10 x 3 como ejemplo:

import numpy as np
A = np.array([[1.2, 2.3, 0.8],
[3.2, 2.1, 0.5],
[0.8, 4.4, 4.4],
[-0.2, -1.1, -1.1],
[2.4, 4.6, 1.6],
[0.5, 0.96, 0.33],
[1.1, 2.2, 3.3],
[-2.2, -4.41, -6.62],
[3.4, 5.5, 3.8],
[-5.1, -28., -28.1]])

Quiero encontrar todos los pares únicos de vectores que son casi paralelos entre sí. Se debe utilizar una medida de tolerancia, y quiero obtener todos los pares únicos de índices de fila (independientemente del orden). Logré escribir el siguiente código:

def all<em>parallel</em>pairs(A, tol=0.1):
    res = set()
    for i, v1 in enumerate(A):
        for j, v2 in enumerate(A):
            if i == j:
                continue
            norm = np.linalg.norm(np.cross(v1, v2))
            if np.isclose(norm, 0., rtol=0, atol=tol):
                res.add(tuple(sorted([i, j])))
    return np.array(list(res))
print(all<em>parallel</em>pairs(A, tol=0.1))

<p>out[1]: [[0 4]
         [2 3]
         [6 7]
         [4 5]
         [0 5]]

Sin embargo, debido a que estoy utilizando dos bucles for, se vuelve lento cuando N es grande. Siento que debería haber maneras más eficientes y de numpy para hacer esto. ¿Algún consejo?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Una forma de optimizar este código es usar la difusión de numpy en lugar de los dos bucles for. Aquí está el código modificado:

    def all_parallel_pairs(A, tol=0.1):
        res = set()
        norms = np.linalg.norm(np.cross(A[:, None], A, axisa=2), axis=2)
        mask = np.isclose(norms, 0., rtol=0, atol=tol)
        idx = np.argwhere(mask)
        res.update(tuple(sorted([i, j])) for i, j in idx if i != j)
        return np.array(list(res))
    
    • A[:, None] y A se difunden para formar una matriz N x N x 3.
    • np.cross() calcula el producto cruzado de todos los pares de vectores.
    • np.linalg.norm() calcula la norma de cada vector de producto cruzado.
    • np.isclose() crea una máscara booleana para todos los vectores que son casi paralelos.
    • np.argwhere() encuentra los índices de los elementos True en la máscara.
    • res.update() agrega todos los pares de índices únicos al conjunto.
    • El resultado final se convierte en una matriz numpy para mayor consistencia.

    Este enfoque es mucho más rápido que el enfoque original cuando N es grande.

Comments are closed.