如何解决Python中的递归关系

时间:2014-03-27 20:28:54

标签: python math numpy scipy

我正在尝试编写代码来给出递归关系的数字答案。关系本身很简单,定义如下。变量x是整数

  • p(i)= p(i + 2)/ 2 + p(i-1)/ 2,如果i> 0和i< X
  • p(0)= p(2)/ 2
  • 如果i> = x ,则
  • p(i)= 1

这也在此代码中。

from __future__ import division
def p(i):
    if (i == 0):
        return p(2)/2
    if (i >= x):
        return 1
    return p(i-1)/2+p(i+2)/2


x = 4
#We would like to print p(0)  for example.

这当然不会让你计算p(0)。你怎么能在python中做到这一点?


是否有可能建立一个numpy.linalg.solve可以求解的联立方程组?

4 个答案:

答案 0 :(得分:6)

你是对的,这可以用线性代数来解决。我在下面做的是一个简单的硬编码翻译。您p(0)p(3)的等式通过重新排列来编码,以便右侧为=0。对于作为基本情况出现在重复关系中的p(4)p(5),右侧有=1

  • -p(0) + p(2)/2 = 0

  • p(i-1)/2 - p(i) + p(i+2)/2 = 0 for i> 0和i< X

  • p(i) = 1如果i> = x

以下是n=4

的硬编码程序
import numpy
a=numpy.array([[-1,   0, 0.5,  0,   0,   0], # 0
               [0.5, -1,   0,0.5,   0,   0], # 1
               [0,  0.5,  -1,  0, 0.5,   0], # 2
               [0,    0, 0.5, -1,   0, 0.5], # 3
               [0,    0,   0,  0,   1,   0], # 4
               [0,    0,   0,  0,   0,   1], # 5
              ])
b=numpy.array([0,0,0,0,1,1])
# solve ax=b
x = numpy.linalg.solve(a, b)
print x

编辑,这是以编程方式构造矩阵的代码,仅针对n=4进行了测试!

n = 4

# construct a
diag = [-1]*n + [1]*2
lowdiag = [0.5]*(n-1) + [0]*2
updiag = [0.5]*n
a=numpy.diag(diag) + numpy.diag(lowdiag, -1) + numpy.diag(updiag, 2)

# solve ax=b
b=numpy.array([0]*n + [1]*2)
x = numpy.linalg.solve(a, b)

print a
print x[:n]

此输出

[[-1.   0.   0.5  0.   0.   0. ]
 [ 0.5 -1.   0.   0.5  0.   0. ]
 [ 0.   0.5 -1.   0.   0.5  0. ]
 [ 0.   0.   0.5 -1.   0.   0.5]
 [ 0.   0.   0.   0.   1.   0. ]
 [ 0.   0.   0.   0.   0.   1. ]]
[ 0.41666667  0.66666667  0.83333333  0.91666667]

与您评论中的解决方案相匹配。

答案 1 :(得分:2)

这里的问题是,无论你从哪里开始,你最终都会进行无限递归,因为递归不是明确的,而是最终产生线性方程组来解决。如果这是你必须使用Python解决的问题,我会使用Python来计算这个方程组的系数,并使用Cramer的规则来解决它。

编辑:具体来说,你的未知数是p(0),...,p(x-1)。直接击球的一个系数行向量是(1,0,-1 / 2,0,...,0)(来自p(0)-p(2)/ 2 = 0),而所有其他的都是形式(...,-1 / 2,1,0,-1 / 2,...)。这些中有x-1个(p(1),...,p(x-1)各一个),因此系统要么具有唯一解,要么根本没有。直观地说,似乎总是应该有一个独特的解决方案。

最后两个方程式将是唯一的,因为它们将以p(x)和p(x + 1)为特征,因此这些项将被省略;我相信,Cramer规则的RHS的列向量将是(0,0,...,0,1 / 2,1)。

Numpy有矩阵支持。

答案 2 :(得分:2)

这不是已发布问题的答案,但是此页面是Google在“使用Python解决重现关系”方面的热门话题,因此我将写一个答案。

如果您具有线性递归,并且想要查找递归公式,则可以使用Sympy的find_linear_recurrence函数。例如,假设您具有以下序列:0、1、3、10、33、109、360、1189、3927、12970。然后下面的代码将产生递归关系:

import sympy
from sympy.abc import n
L = [0, 1, 3, 10, 33, 109, 360, 1189, 3927, 12970]
print(sympy.sequence(L, (n, 1, len(L))).find_linear_recurrence(len(L)))

输出为:

[3, 1]

所以您知道A(n)= 3 * A(n-1)+ A(n-2)。

答案 3 :(得分:0)

我很困惑,因为你的代码似乎应该这样做。

def p(i):
    x = 4 # your constant should be defined in-function

    if (i == 0):
        return p(2)/2
    elif (i >= x):
        return 1
    return p(i-1)/2+p(i+2)/2

这里最大的问题是你的递归。对于p(1)它确实:

p(0)/2                    +                    p(3)/2
p(2)/2                    +           p(2)/2 + p(4)/2
p(1)/2                    +              p(1)/2 + 1/2
# each side of the operator is now the same as the original problem!
# that's a sure sign of infinite recursion.

你期望什么作为输出?