Python NumPy:n个向量的稀疏外积(双曲线交叉)
我试图计算Python NumPy:n个向量的稀疏外积(双曲线交叉),python,algorithm,performance,numpy,Python,Algorithm,Performance,Numpy,我试图计算n向量的完全外积的某个子集。完整外积的计算如中所述 形式上:设v1,v2,…,vk为某种长度的向量n,K为正常数。我想要一个包含所有产品的列表,v1[i1]v2[i2]…vk[ik]对于这些产品,i1*i2*…*ik如果索引与简单循环相比变得太混乱,我通常用C编写swig包装器和生成函数。这可以实现良好的性能(很容易用openmp并行执行),保持逻辑性和可读性,并且在我的numpy调用之间作为函数很好地匹配。由于这不是一个“纯”的numpy解决方案,我把它作为一个注释放在这里。您能展示
n
向量的完全外积的某个子集。完整外积的计算如中所述
形式上:设
v1
,v2
,…,vk
为某种长度的向量n
,K
为正常数。我想要一个包含所有产品的列表,v1[i1]v2[i2]…vk[ik]
对于这些产品,i1*i2*…*ik如果索引与简单循环相比变得太混乱,我通常用C编写swig包装器和生成函数。这可以实现良好的性能(很容易用openmp并行执行),保持逻辑性和可读性,并且在我的numpy调用之间作为函数很好地匹配。由于这不是一个“纯”的numpy解决方案,我把它作为一个注释放在这里。您能展示一下当前解决方案的代码,以及一个带有预期输入和输出的详细工作示例吗?因为这不容易理解这到底是如何工作的。特别是,可以有多组索引来验证i1*i2*…*ik
,那么您如何知道应该使用哪些索引呢?还是我遗漏了什么?(关于你链接到的外部产品的另一篇文章中没有提到这个条件。)那么,一个常规的叉积就是k
和k
都等于2或3吗?你对这些产品加总了吗?
import numpy as np
def get_cross_indices(n, k, K):
"""
Assume k > 0.
Returns a hierarchical list containg elements of type
(i1, list) with
- i1 being a index (zero based!)
- list being again a list (possibly empty) with all indices i2, such
that (i1+1) * (i2+1) * ... * (ik+1) <= K (going down the hierarchy)
"""
if k == 1:
num = min(n, K)
return (num, [(x, []) for x in range(num)])
else:
indices = []
nums = 0
for i in xrange(min(n, K)):
(num, tail) = get_cross_indices(n,
k - 1, K // (i + 1))
indices.append((i, tail))
nums += num
return (nums, indices)
def calc_cross_outer_product(vectors, result, factor, indices, pos):
"""
Fills the result list recursively with all products
vectors[0][i1] * ... * vectors[k-1][ik]
such that i1,...,ik is a feasible index sequence
from `indices` (they are in there hierarchically,
also see `get_cross_indices`).
"""
for (x, list) in indices:
if not list:
result[pos] = factor * vectors[0][x]
pos += 1
else:
pos = calc_cross_outer_product(vectors[1:], result,
factor * vectors[0][x], list, pos)
return pos
k = 3 # number of vectors
n = 4 # vector length
K = 3
# using random values here just for demonstration purposes
vectors = np.random.rand(k, n)
# get all indices which meet the condition
(count, indices) = get_cross_indices(n, k, K)
result = np.ones(count)
calc_cross_outer_product(vectors, result, 1, indices, 0)
## Equivalent version ##
alt_result = np.ones(count)
# create full outer products
outer_product = reduce(np.multiply, np.ix_(*vectors))
pos = 0
for inds in np.ndindex((n,)*k):
# current index set is feasible?
if np.product(np.array(inds) + 1) <= K:
# compute [ vectors[0][inds[0]],...,vectors[k-1][inds[k-1]] ]
values = map(lambda x: vectors[x[0]][x[1]],
np.dstack((np.arange(k), inds))[0])
alt_result[pos] = np.product(values)
pos += 1