Python 通过递归稳定计算大量子

Python 通过递归稳定计算大量子,python,numpy,scipy,numerical-stability,Python,Numpy,Scipy,Numerical Stability,我有两个量a和b,通过递归和引用另一个值列表x=[x_1,x_2,…x_N]来定义,这将是程序的输入。程序将迭代x中的所有值,并根据以下内容更新a&b: for n in range(1,N) a[n] = a[n-1] * exp(+x[n]) + b[n-1] * exp(-x[n]) b[n] = b[n-1] * exp(+x[n]) + a[n-1] * exp(-x[n]) 和起始值 a[0] = exp(+x[0]) b[0] = exp(-x[0])

我有两个量a和b,通过递归和引用另一个值列表x=[x_1,x_2,…x_N]来定义,这将是程序的输入。程序将迭代x中的所有值,并根据以下内容更新a&b:

for n in range(1,N)
    a[n] = a[n-1] * exp(+x[n]) + b[n-1] * exp(-x[n])  
    b[n] = b[n-1] * exp(+x[n]) + a[n-1] * exp(-x[n])  
和起始值

a[0] = exp(+x[0])
b[0] = exp(-x[0])

x中的值不是大数字(始终我们可以将其改写为:

for n in range(1,N)
    a[n] = exp(log(a[n-1]) + x[n]) + exp(log(b[n-1]) - x[n])
    b[n] = exp(log(b[n-1]) + x[n]) + exp(log(a[n-1]) - x[n]))
然后更改我们的迭代变量:

for n in range(1,N)
    log_a[n] = log(exp(log_a[n-1] + x[n]) + exp(log_b[n-1] - x[n]))
    log_b[n] = log(exp(log_b[n-1] + x[n]) + exp(log_a[n-1] - x[n]))
使用
np.logaddexp
可以更稳定地计算:

for n in range(1,N)
    log_a[n] = np.logaddexp(log_a[n-1] + x[n], log_b[n-1] - x[n])
    log_b[n] = np.logaddexp(log_b[n-1] + x[n], log_a[n-1] - x[n])
据我所知,所有(?)递归问题都可以通过动态规划来解决。例如,斐波那契序列可以这样表示:

def fibo(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    return fibo(n-1) + fibo(n-2)
或者,迭代地:

n = 10
fibo_nums = [0, 1]
while len(fibo_nums) <= n:
    fibo_nums.append(fibo_nums[-2] + fibo_nums[-1])
n=10
fibo_nums=[0,1]

虽然len(fibo_nums)你的messier表达式可以通过使用
log1p(x)==log(1+x)
来改进,这在数值上更稳定。我假设你的起始值使用
x[0]
,而不是
x[n]
?是的,没错。它应该是x[0]在开始条件中。感谢关于log1p-tooth的提示,OP已经执行了这样的解包。公式本身是“递归的”,但问题中的代码是not@Eric啊。我在OP的代码中没有看到任何递归,也不熟悉问题域。由于问题标题谈到了递归,我假设他们的代码中有其他地方发生了什么。这很好,谢谢!使用logaddexp有任何缺点吗?你认为呢原始代码可能会出现不稳定的问题?@RGWinston:恐怕我不知道这两个问题的答案。
n = 10
fibo_nums = [0, 1]
while len(fibo_nums) <= n:
    fibo_nums.append(fibo_nums[-2] + fibo_nums[-1])