我有一个线性递归问题,其中下一个元素不仅依赖于前一个值,例如: Fibonacci序列。计算n th 元素的一种方法是通过函数调用来定义它,例如
Fibonacci[0] = 0; Fibonacci[1] = 1;
Fibonacci[n_Integer?Positive] := Fibonacci[n] + Fibonacci[n - 1]
对于我正在使用的序列,这正是我所做的。 (定义在Module
内部,所以我不会污染Global`
。)但是,我将使用2 10 - 2 13 点,所以当我只需要最后一个术语而没有任何先前的元素时,我担心额外的开销。我想使用Fold
来执行此操作,但Fold
仅传递前一个结果,这意味着它对一般线性递归问题不直接有用。
我想要一对函数来替换Fold
和FoldList
,它们将指定数量的先前序列元素传递给函数,即
In[1] := MultiFoldList[f, {1,2}, {3,4,5}] (* for lack of a better name *)
Out[1]:= {1, 2, f[3,2,1], f[4,f[3,2,1],2], f[5,f[4,f[3,2,1],2],f[3,2,1]]}
我有一些东西可以做到这一点,但我在保存之前关闭了笔记本。所以,如果我自己重写它,我会发布它。
修改:为什么我没有使用RSolve
或MatrixPower
来解决此问题。我的具体问题是我正在执行n-point Pade approximant以分析方式继续我只知道假想轴上的一定数量的点{z i }的函数。创建近似值的一部分是生成一组系数,一个 i ,这是另一个递归关系,然后被送入最终关系
A[n+1]== A[n] + (z - z[[n]]) a[[n+1]] A[n-1]
不适合RSolve
或MatrixPower
,至少我能看到。
答案 0 :(得分:5)
RecurrenceTable可以为您执行此任务吗?
根据之前的两个值找出重复的第1000个术语:
In[1]:= RecurrenceTable[{a[n] == a[n - 1] + a[n - 2],
a[1] == a[2] == 1}, a,
{n, {1000}}]
Out[1]= {4346655768693745643568852767504062580256466051737178040248172\
9089536555417949051890403879840079255169295922593080322634775209689623\
2398733224711616429964409065331879382989696499285160037044761377951668\
49228875}
修改:如果您的重复定义是由不希望评估非数字m和n的函数f[m, n]
定义的,那么您可以使用Condition :
In[2]:= f[m_, n_] /; IntegerQ[m] && IntegerQ[n] := m + n
以f
:
In[3]:= RecurrenceTable[{a[n] == f[a[n - 1], a[n - 2]],
a[1] == a[2] == 1}, a, {n, {1000}}]
Out[3]= {4346655768693745643568852767504062580256466051737178040248172\
9089536555417949051890403879840079255169295922593080322634775209689623\
2398733224711616429964409065331879382989696499285160037044761377951668\
49228875}
答案 1 :(得分:4)
多个折叠列表可能很有用,但它不是一种有效的方法来获得对大输入进行评估的线性重复。一些替代方案是使用RSolve或矩阵幂乘以初始值的向量。
如果第n个术语等于n-1个术语加上n-2个术语的两倍,这些方法适用于这个例子。
f[n_] = f[n] /. RSolve[{f[n] == f[n - 1] + 2*f[n - 2], f[1] == 1, f[2] == 1},
f[n], n][[1]]
Out [67] = 1/3( - ( - 1)^ n + 2 ^ n)
f2[n_Integer] := Last[MatrixPower[{{0, 1}, {2, 1}}, n - 2].{1, 1}]
{f[11], f2[11]}
出[79] = {683,683}
Daniel Lichtblau Wolfram Research
答案 2 :(得分:3)
几乎是一个令人费解的笑话,但你可以使用NestWhileList
的副作用
fibo[n_] :=
Module[{i = 1, s = 1},
NestWhileList[ s &, 1, (s = Total[{##}]; ++i < n) &, 2]];
性能不太好:
In[153]:= First@Timing@fibo[10000]
Out[153]= 0.235
通过将任何整数更改为最后2
,您可以将最后的k个结果传递给您的函数(在本例中为Total [])。
答案 3 :(得分:2)
LinearRecurrence
和RecurrenceTable
非常有用。
对于小内核,Daniel给出的MatrixPower
方法是最快的。
对于某些问题,这些可能不适用,您可能需要自己动手。
我将使用Nest,因为我认为这适用于此问题,但类似的构造可以与Fold一起使用。
一个具体的例子,Fibonacci序列。这可能不是最干净的,但我相信你会继续看到效用。
fib[n_] :=
First@Nest[{##2, # + #2} & @@ # &, {1, 1}, n - 1]
fib[15]
Fibonacci[15]
我在这里使用Apply
(@@
),以便我可以使用#
,#2
等来处理元素,而不是#[[1]]
等。使用SlotSequence
删除旧列表中的第一个元素,同时Sequence
将其放入新列表中。
如果您要一次操作整个列表,那么简单的Append[Rest@#, ...
可能会更好。这两种方法都可以很容易地推广。例如,一个简单的线性重复实现是
lr[a_, b_, n_Integer] := First@Nest[Append[Rest@#, a.#] &, b, n - 1]
lr[{1,1}, {1,1}, 15]
(内核与内置的LinearRecurrence
)