我有一个序列定义
xn + 1 = f(xn,xn-1)
其中xn是在时间tn评估的x。序列中的任何值都由前两个值的某个函数(以及时间步长,但现在是常量)定义。我希望在此序列中生成前N个值,给定x0和x1。
什么是最pythonic的方式来做到这一点?
我目前的做法只是循环。我创建一个正确大小的numpy.ones
数组,然后通过索引循环它。如果index = 0
或1
,那么我将值从1
分别更改为x0 / x1。对于更大的凹凸,我查找数组中的先前值并应用该函数。
但我觉得这似乎没有使用numpy数组方法,所以我想知道是否有更好的方法?
在我的代码中,我有一个createSequence
函数,它接受xn + 1的定义以及边界条件和时间步长,并输出遵循这些规则的序列。 NB,我是Python的新手,所以任何一般建议也将不胜感激!
import numpy as np
def x_next(x_current,x_previous,dt):
"""Function to return the next value in the sequence
x_current and x_previous are the values at tn and tn-1 respectively
dt is the time step
"""
return (x_current - x_previous)/dt #as an example
def createSequence(x_next,x0,x1,start,stop,dt):
""" Function to create sequence based on x_next function, and boundary conditions"""
num = (stop-start)/dt
x_array = np.ones(int(num))
x_array[0] = x0
x_array[1] = x1
for index in range(len(x_array)):
if index == 0:
x_array[index] = x0
elif index == 1:
x_array[index] = x1
else:
x_current = x_array[index - 1]
x_previous = x_array[index - 2]
x_array[index] = x_next(x_current,x_previous,dt)
return x_array
print(createSequence(x_next=x_next,x0=0.1,x1=0.2,start=0,stop=20,dt=0.1))
我建议使用发电机,因为
在下文中,我将使用Fibonacci sequence作为示例,因为它采用与您的问题类似的形式。
def fibonacci(a=0, b=1, length=None):
# Generate a finite or infinite sequence
num = 0
while length is None or num < length:
# Evaluate the next Fibonacci number
c = a + b
yield c
# Advance to the next item in the sequence
a, b = c, a
num += 1
请注意,a
对应于您的x_n
,b
对应于x_{n-1}
,而c
对应于x_{n+1}
。还有一个简单的例子:
>>> list(fibonacci(length=10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
如果你想让序列变成一个numpy数组
>>> np.fromiter(fibonacci(length=10), int)
array([ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55])
我想你想要最初的术语集合。但是,如果你或者读过这个问题的任何人都想要个别条款,那么sympy库会派上用场。这里到水平线的所有东西都来自Solve a recurrence relation。
>>> from sympy import *
>>> var('y')
y
>>> var('n', integer=True)
n
>>> f = Function('f')
>>> f = y(n)-2*y(n-1)-5*y(n-2)
>>> r = rsolve(f, y(n), [1, 4])
一旦你有r
,你可以在同情设施内评估它的各种n
值......
>>> N(r.subs(n,1))
4.00000000000000
>>> N(r.subs(n,2))
13.0000000000000
>>> N(r.subs(n,10))
265333.000000000
或者您可以“解除”r
中的代码并将其重新用于您自己的例程。
>>> r
(1/2 + sqrt(6)/4)*(1 + sqrt(6))**n + (-sqrt(6) + 1)**n*(-sqrt(6)/4 + 1/2)