【问题标题】:Optimize generator for multivariate polynomial exponents优化多元多项式指数生成器
【发布时间】:2011-06-22 06:48:28
【问题描述】:

嗨, 我试图找到一个通用表达式来获得 ordern_variables 阶的多元多项式的指数,就像等式 (3) 中的 reference 中呈现的那样。

这是我当前的代码,它使用 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 的大量调用。 ordern_variables 的典型值分别为 5 和 10。

如何显着提高执行速度?

感谢您的帮助。

大卫烤宽面条

【问题讨论】:

  • 我不太了解你想要做什么的细节,但你有没有在 numpy 中查看是否有任何功能可以帮助你?

标签: python optimization generator itertools


【解决方案1】:

我会尝试递归编写它以便只生成所需的元素:

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】:

实际上,您最大的性能问题是您生成的大多数元组太大,需要丢弃。下面应该生成你想要的元组。

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

【讨论】:

  • 是的,你提到的问题是真的。其实这解决了我的问题。谢谢。
猜你喜欢
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 2015-02-20
  • 1970-01-01
  • 2021-11-01
  • 1970-01-01
  • 2023-03-11
  • 2011-06-28
相关资源
最近更新 更多