我一直在尝试优化此代码:
def spectra(mE, a):
pdf = lambda E: np.exp(-(a+1)*E/mE)*(((a+1)*E/mE)**(a+1))/(scipy.special.gamma(a+1)*E)
u=[]
n=np.random.uniform()
E=np.arange(0.01,150, 0.1)
for i in E:
u.append(scipy.integrate.quad(pdf,0,i)[0])
f=interp1d(u, E)
return f(n)
我试图用f
创建一个查找表,但似乎每次调用该函数时它都会重新进行集成。有没有办法放入类似if语句的东西,这样我就可以为f
和mE
的值创建a
一次,之后再调用它?
感谢您的帮助。
干杯。
答案 0 :(得分:2)
如果使用相同的(mE, a)
值重新调用函数,那么您想要做的就是返回一个已知值,如果输入是新的,则执行计算。
这称为 memoization 。请参阅示例What is memoization and how can I use it in Python?。请注意,在现代版本的Python中,您可以创建一个装饰器来应用函数的memoization,这样可以让您更加整洁。
答案 1 :(得分:0)
很可能你不能存储 spectrum(x,y)的值,并通过精确浮点 x的值合理地检索它们和 y 。在现实生活中,您很少遇到完全相同的浮点值。
请注意,我认为您不能直接缓存f
,这取决于很长的浮动列表。可能的输入空间太大,以至于发现一个接近的匹配对我来说似乎是不太可能的。
如果缓存spectra()
的值,则可以合理的概率检索足够接近的参数对的值。
问题在于寻找如此紧密的配对。哈希表无法工作(我们需要不精确的匹配),有序列表和二进制搜索也无法工作(我们有2个维度)。我会使用quad tree或其他形式的spatial index。您可以动态有效地构建它,搜索您给定点附近的最近已知点。
如果您发现缓存的点非常接近您需要的点,您只需返回缓存的值即可。如果没有足够接近的点,则将其添加到索引中,希望将来可以重用它。如果您的点位于两个已知点之间,也许您甚至可以进行插值。
大先决条件当然是缓存中有足够数量的点可以重用。要估计这一点,运行您的一些计算并在某处(例如在文件中)存储(mE, a)
对,然后绘制它们。你会立即看到你是否有一组彼此接近的点。当然,你也可以在没有绘图的情况下寻找紧密的集群。如果您有足够紧密的群集(您可以将一个点的值重用于另一个点),您的缓存将起作用。如果没有,请不要打扰它。