我试图计算n
向量的完整外积的某个子集。完整外部产品的计算在this question中描述。
正式:让v1
,v2
,...,vk
为某个长度为n
的向量,K
为正常数。我想要一个包含v1[i1]v2[i2]...vk[ik]
(索引从一开始)的所有产品i1*i2*...*ik <= K
的列表。注意:例如,如果K = n ** k
,则列表将包含每个组合。
我目前的做法是创建一个满足上述条件的索引的分层列表,然后递归计算产品,这有利于重用某些因素。
此实现比使用NumPy计算完整外部产品要快得多(对于相同的n
和k
)。我希望获得比完整产品的计算更好的性能。我对k
的较大的值和 small K
感兴趣(这个问题来自使用稀疏基数的函数逼近,即双曲线十字)。
有没有人知道更高效的方式来获取此列表?也许通过使用更多的NumPy或其他算法?我接下来会尝试C实现。
这是我目前的实施:
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
要了解我感兴趣的指数的视觉概念,以下是k=3
的图片,K=n
:
(摘自this website)