计算列表内成对点积的Pythonic方法

时间:2018-10-25 20:03:05

标签: python for-loop

我有一个包含元组所有组合的列表,每个元素只能是-1或1。该列表可以生成为:

N=2
list0 = [p for p in itertools.product([-1, 1], repeat=N)]

例如,如果元组具有N=2个元素:

  

list0 = [(-1,-1),(-1,1),(1,-1),(1,1)]

因此,元组的总数为2^2=4

如果元组具有N=3个元素:

  

list0 = [(-1,-1,-1),(-1,-1,1),(-1,1,-1),(-1,1,1),    (1,-1,-1),(1,-1、1),(1、1,-1),(1、1、1)]

这是我的关注点

现在,我想获取列表中任何一对元组之间的点积的所有结果(包括一个自身的元组)。因此,对于N=2,将有6(pairs) + 4(itself) = 10 combinations;,对于N=3,将是28(pairs) + 8(itself) = 36 combinations.

对于小型N,我可以执行以下操作:

for x in list0:
    for y in list0:
        print(np.dot(x,y)) 

但是,假设我已经有了list0,那么如果N大(例如〜50),那么计算点积所有可能性的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

您可以使用np.dot本身:

import numpy as np

list0 = [(-1, -1, -1), (-1, -1, 1), (-1, 1, -1), (-1, 1, 1), (1, -1, -1), (1, -1, 1), (1, 1, -1), (1, 1, 1)]

# approach using np.dot
a = np.array(list0)
result = np.dot(a, a.T)

# brute force approach
brute = []
for x in list0:
    brute.append([np.dot(x, y) for y in list0])
brute = np.array(brute)

print((brute == result).all())

输出

True

您要问的是documentationa与自身的矩阵乘法:

  

如果a和b均为二维数组,则为矩阵乘法,

请注意,最 pythonic 解决方案是使用运算符@

import numpy as np

list0 = [(-1, -1, -1), (-1, -1, 1), (-1, 1, -1), (-1, 1, 1), (1, -1, -1), (1, -1, 1), (1, 1, -1), (1, 1, 1)]

# approach using np.dot
a = np.array(list0)
result = a @ a.T

# brute force approach
brute = []
for x in list0:
    brute.append([np.dot(x, y) for y in list0])
brute = np.array(brute)

print((brute == result).all())

输出

True

注意:该代码已在Python 3.5中运行

答案 1 :(得分:0)

您可以坚持使用numpy

import numpy as np
import random


vals = []
num_vecs = 3
dimension = 4
for n in range(num_vecs):
    val = []
    for _ in range(dimension):
        val.append(random.random())
    vals.append(val)

# make into numpy array
vals = np.stack(vals)
print(vals.shape == (num_vecs, dimension))

# multiply every vector with every other using broadcastin
every_with_every_mult = vals[:, None] * vals[None, :]
print(every_with_every_mult.shape == (num_vecs, num_vecs, dimension))

# sum the final dimension
every_with_every_dot = np.sum(every_with_every_mult, axis=every_with_every_mult.ndim - 1)
print(every_with_every_dot.shape == (num_vecs, num_vecs))

# check it works
for i in range(num_vecs):
    for j in range(num_vecs):
        assert every_with_every_dot[i,j] == np.sum(vals[i]*vals[j])