优化多元多项式指数的生成器
嗨,
我正在尝试找一个通用的方法来获取一个多变量多项式的指数,这个多项式的阶数是order
,变量的数量是n_variables
,就像在这个参考文献中的公式(3)所展示的那样。
这是我目前的代码,它使用了itertools.product
这个生成器。
def generalized_taylor_expansion_exponents( order, n_variables ):
"""
Find the exponents of a multivariate polynomial expression of order
`order` and `n_variable` number of variables.
"""
exps = (p for p in itertools.product(range(order+1), repeat=n_variables) if sum(p) <= order)
# discard the first element, which is all zeros..
exps.next()
return exps
我想要的输出是这样的:
for i in generalized_taylor_expansion_exponents(order=3, n_variables=3):
print i
(0, 0, 1)
(0, 0, 2)
(0, 0, 3)
(0, 1, 0)
(0, 1, 1)
(0, 1, 2)
(0, 2, 0)
(0, 2, 1)
(0, 3, 0)
(1, 0, 0)
(1, 0, 1)
(1, 0, 2)
(1, 1, 0)
(1, 1, 1)
(1, 2, 0)
(2, 0, 0)
(2, 0, 1)
(2, 1, 0)
(3, 0, 0)
其实这段代码运行得很快,因为生成器对象只被创建了一次。如果我想用这个生成器的值填充一个列表,执行速度就会变得很慢,主要是因为调用sum
的次数太多。通常情况下,order
和n_variables
的值分别是5和10。
我该如何显著提高执行速度呢?
谢谢你的帮助。
达维德·拉萨尼亚
2 个回答
0
我会尝试用递归的方式来编写,这样可以只生成我们想要的那些元素:
def _gtee_helper(order, n_variables):
if n_variables == 0:
yield ()
return
for i in range(order + 1):
for result in _gtee_helper(order - i, n_variables - 1):
yield (i,) + result
def generalized_taylor_expansion_exponents(order, n_variables):
"""
Find the exponents of a multivariate polynomial expression of order
`order` and `n_variable` number of variables.
"""
result = _gtee_helper(order, n_variables)
result.next() # discard the first element, which is all zeros
return result
2
其实你最大的性能问题是你生成的大部分元组(tuple)都太大了,很多都是多余的,需要被丢掉。下面的代码应该能准确生成你想要的元组。
def generalized_taylor_expansion_exponents( order, n_variables ):
"""
Find the exponents of a multivariate polynomial expression of order
`order` and `n_variable` number of variables.
"""
pattern = [0] * n_variables
for current_sum in range(1, order+1):
pattern[0] = current_sum
yield tuple(pattern)
while pattern[-1] < current_sum:
for i in range(2, n_variables + 1):
if 0 < pattern[n_variables - i]:
pattern[n_variables - i] -= 1
if 2 < i:
pattern[n_variables - i + 1] = 1 + pattern[-1]
pattern[-1] = 0
else:
pattern[-1] += 1
break
yield tuple(pattern)
pattern[-1] = 0