Python 加速循环,也许用发电机?

Python 加速循环,也许用发电机?,python,performance,iterator,generator,Python,Performance,Iterator,Generator,我对python相当陌生,我有一个问题,我试图计算一个等式有多少个解,比如输入e的Ta+Nb+Mc+Pd=e。我不在乎解决方案是什么,只在乎数量 Abcd是可变正整数,NMPT是固定整数 我知道这是新手犯的错误,但我尝试了4个嵌套for循环,时间太长了,所以我放弃了,但想不出更优雅的方法。即使我排除了允许循环的潜在数字,我最终还是得到了更大的计算时间 我读过关于发电机所用时间大大减少的文章,但我不确定如何正确地使用它们,我设法将时间缩短到一两分钟,但希望使用一个具有收益率的函数能更快 比如,不完

我对python相当陌生,我有一个问题,我试图计算一个等式有多少个解,比如输入e的Ta+Nb+Mc+Pd=e。我不在乎解决方案是什么,只在乎数量

Abcd是可变正整数,NMPT是固定整数

我知道这是新手犯的错误,但我尝试了4个嵌套for循环,时间太长了,所以我放弃了,但想不出更优雅的方法。即使我排除了允许循环的潜在数字,我最终还是得到了更大的计算时间


我读过关于发电机所用时间大大减少的文章,但我不确定如何正确地使用它们,我设法将时间缩短到一两分钟,但希望使用一个具有收益率的函数能更快

比如,不完全是这样,但在这个程度上,是的,我知道嵌套循环是不利的,但我是一个新手,正在努力学习

def function():
    count = 0 
    for a is in range (0,e)
        for b is in range (0,int(e/N))
            Another for loop 
                Another for loop
                    count += 1
    yield count
输出结果,它给了我更快的结果,但还不够快

还是我的想法完全错了


感谢

这是一类问题,在这类问题中,一个更好的算法将产生远远优于改变代码工作方式的性能增益

所以你的问题是,给定
T
N
M
p
,和
e
,找出有多少种解决方案

现在,类似于
yield
的方法适用于需要所有解决方案的情况。。。获取所有的解决方案将涉及枚举所有的解决方案,这将是4个嵌套循环<代码>收益率可能对这种情况有所帮助

计算解决方案可以让我们找到减少步行量的方法

让我们从最外层的环开始

for a in range(1, ?)
射程能达到多高?我们知道,对于有效的解决方案,
a
b
c
d
都必须是正的,即
=1
,因此如果
T*a+N*1+M*1+P*1==e,我们可以得到最高的
a
值。。。因此
a
的上限是
int((e-N-M-P)/T)

b
的范围能达到多高?我们知道我们已经有了
T*a

for a in range(1, int((e - N - M - P) / T))
  for b in range(1, int((e - T*a - M - P) / N))
    for c in range(1, ?)
c
的范围能达到多高?同样的原则

for a in range(1, int((e - N - M - P) / T))
  for b in range(1, int((e - T*a - M - P) / N))
    for c in range(1, int((e - T*a - N*b - P) / M))
      ?
现在,您可能会尝试执行另一个for循环。。。但这里是我们需要聪明的地方,如果我们可以避免最后的循环。。。因为范围的上限实际上是有效解决方案的计数

count = 0
for a in range(1, int((e - N - M - P) / T))
  for b in range(1, int((e - T*a - M - P) / N))
    for c in range(1, int((e - T*a - N*b - P) / M))
      count = count + int((e - T*a - N*b - M*c) / P)
这是一个优越的算法,因为它有较少的循环,因此将返回更快


哦,但是还有更多。。。如果你懂数学,如果我没记错的话,你当然可以删除另一个循环,如果不能删除所有的循环。。。但这正是您需要真正了解数学的地方,而不仅仅是强制执行解决方案,这是加速嵌套for循环的常用方法,用于生成所有参数值并将参数应用于函数:

而不是:

for a in range(5):
    for b in range(8):
        for c in range(10, 17):
            for d in range(5, 11):
                 v = f(a, b, c, d)
                 ...
写下以下内容:

for v in starmap(f, product(range(5), range(8), range(10,17), range(5,11))):
    ...
好处是:

  • 更简洁的功能风格
  • 整数值只创建一次
  • 您不会不断地重建相同的整数列表
  • product()只分配了一个元组,并且可以重用它
  • starmap()和product()都以C速度运行(没有纯python步骤)
  • 函数“f”只查找一次

这是对
产量的错误应用。您通常会在一个地方使用它,您将返回几十个值,而不仅仅是一个值
yield
有助于延迟计算,而您的函数实际上返回一个生成单个值的生成器-计数。生成器优化内存使用,而不是速度。“我读过关于生成器花费的时间少得多的文章”-不幸的是,它们没有。相对于列表理解,它们占用的内存更少,如果不需要所有元素,您可以提前停止它们,但是相对于您已经使用的循环,它们甚至可能更慢。我还不完全清楚这里的问题是什么。谢谢!移动这个额外的循环将非常方便。另外,忘了提到abcd可以是0。我确实懂数学,但不幸的是,如果没有另一个方程式来优化它,你真的无法做任何事情。我也不完全确定最后一行是如何工作的?
for v in starmap(f, product(range(5), range(8), range(10,17), range(5,11))):
    ...