问题来源 #

笔者经常学习的数学研发论坛曾有一帖讨论下述非线性差分方程的渐近求解:
an+1=an+1a2n,a1=1
原帖子在这里,从这帖子中我获益良多,学习到了很多新技巧。主要思路是通过将两边立方,然后设xn=a3n,变为等价的递推问题:
xn+1=xn+3+3xn+1x2n,x1=1
然后可以通过巧妙的技巧得到渐近展开式:
xn=3n+lnn+a+13(lnn+a)518n+
具体过程就不提了,读者可以自行到上述帖子学习。

然而,这种形式的解虽然精妙,但存在一些笔者不是很满意的地方:

1、解是渐近的级数,这就意味着实际上收敛半径为0;
2、是nk形式的解,对于较小的n难以计算,这都使得高精度计算变得比较困难;
3、当然,题目本来的目的是渐近计算,但是渐近分析似乎又没有必要展开那么多项;
4、里边带有了一个本来就比较难计算的极限值a
5、求解过程似乎稍欠直观。

当然,上面这些缺点,有些是鸡蛋里挑骨头的。不过,也正是这些缺点,促使我寻找更好的形式的解,最终导致了这篇文章。

隐式解 #

递推
xn+1=xn+3+3xn+1x2n,x1=1
的第一级渐近解是通过略去后面的3xn+1x2n得出的,得到xn+1=xn+3,所以xn=3n2

接下来的思路有很多,比如迭代、待定系数等,都可以求得渐近解,但是我尝试了另外一条途径:求隐式的解。首先我们考虑:
xn+1+f(xn+1)=xn+3+3xn+1x2n+f(xn+3+3xn+1x2n)
将最后一项在xn处展开至1阶:
xn+1+f(xn+1)=xn+3+3xn+1x2n+f(xn)+f(xn)(3+3xn+1x2n)
1/xn为阶,略去二阶项,得到
xn+1+f(xn+1)=xn+f(xn)+3+3[1xn+f(xn)]
如果让f(xn)=lnxn,那么方括号就为0,于是得到
xn+1lnxn+1=xnlnxn+3
这个等式的精度是O(x2n),为了兼顾简洁与精度,从x2=8出发比较好,这样
xnlnxn=3(n2)+8ln8
这就是一个隐式(近似)解,精度是O(x1n)。它几乎对于所有的n都保持同样的精度。这里的要点就是引入新的项,使得它变成了线性的递推(等差数列)。这个过程可以继续下去,在前述的基础上引入新的函数,继续将它展开到二阶,算得到:
xn+1lnxn+1+56xn+1=xnlnxn+56xn+3
它具有O(x3n)的精度,由此可以解得精度为O(x2n)的隐式解。

为什么要隐式解? #

为什么要寻找隐式解?大概有如下的好处。

一般情况下,传统渐近解是通过泰勒级数展开得到的,泰勒级数展开本身就存在限制(要求可导且导函数有限),因此容易出现渐近解,即使不渐近,收敛半径也可能较小。而隐函数的解通常来说比较稳定,收敛性比较好,虽然可能还是渐近的,但是发散速度会降低不少。比如x=1+t,展开为幂级数,收敛半径仅为1,但是可以表示为隐函数形式x2+1=t,保持了精度和简洁。

简而言之,如果显式展开式能做到的,基本上隐函数也能做到;而显式展开式不能做到的,隐函数也可能做到。因此显然隐函数性能会更好。

此外,对于本文的递推来说,隐函数的解更加简洁,不到处出现难以计算的a。可能读者觉得,每求一次xn都需要求解一次非线性方程,比较复杂。事实上,如果愿意的话,可以直接通过求反函数来从隐式解获得显式解,但是这又回到了渐近级数了,就没有什么必要了。

利于编程的递推格式 #

前面所计算的两项,仅仅是介绍性的演示,由于阶数不高,计算也不困难,但是为了进一步计算下去,尤其是为了编程计算,需要构造便于理解的递推格式,就好比摄动法的递推计算。

假设引入的f(xn)是精确的,那么显然,对于精确的f(x),需要满足
3x+1x2+f(x+3+3x+1x2)f(x)=0
这时候原来的递推就变成了
xn+1+f(xn+1)=xn+f(xn)+3
求解就容易多了。

经过分析,可以通过人工引入参数q,并且将f(x)当作x,q的二元函数f(x,q),求得f(x,q)的级数解,然后让q=1,得到f(x)=f(x,1)。引入的格式如下:
3qx+q2x2+f(x+3q+3q2x+q3x2,q)f(x,q)=0
这样引入的思路是:以x1为无穷小阶,且让f(n)(x)也具有xn的阶,所以,在f()xnqn+1xn,在f()外有xnqnxn。这时候,可以用Mathematica之类的软件,很快展开它:

Series[f[x + 3\cdot q + 3\cdot q^2/x + q^3/x^2, q] - f[x, q] + 3\cdot q/x +
q^2/x^2, {q, 0, 5}]

结果是
q(3f(1,0)(x,0)+3x)+q2(3f(1,0)(x,0)x+3f(1,1)(x,0)+92f(2,0)(x,0)+1x2)+q3(f(1,0)(x,0)x2+3f(1,1)(x,0)x+32f(1,2)(x,0)+9f(2,0)(x,0)x+92f(2,1)(x,0)+92f(3,0)(x,0))+
q的各阶系数为0,逐次解得:
f(0,0)(x,0)=lnxf(0,1)(x,0)=56xf(0,2)(x,0)=43x2
因此
f(x)=f(x,1)=lnx+56x+23x2+
也就是
xn+1lnxn+1+56xn+1+23x2n+1=xnlnxn+56xn+23x2n+3
得到
xnlnxn+56xn+23x2n=3(n2)+8ln8+56×8+23×82
这具有O(x3n)的精度。

将思路稍加变动,就可以用Mathematica写出自动计算程序:

g[x_] = 0;
ff[x_] = 3\cdot 1/x + 1/x^2
Do[e = q^n;
g[x_] = g[x] +
q^n\cdot Integrate[-D[
f[x + 3\cdot q\cdot e + ff[x/q]\cdot e\cdot q, q] - f[x, q] +
g[x + 3\cdot q + ff[x/q]\cdot q] - g[x] + ff[x/q], {q,
n + 1}] /. {q -> 0, f -> 0} // Simplify, x]/
3/(n + 1)!;, {n, 0, 5}]
h[x_] = g[x] /. {q -> 1} // Expand

通过修改{n, 0, 5}中的5可以增减精度。上述代码给出:
f(x)=lnx+56x+23x2+77108x3+133240x426695400x5

渐近结果与极限值 #

此时解得
xn+f(xn)=3(nk)+xk+f(xk),xk为初值的情况下

a=xk+f(xk)3k+ln3
得到
xn+f(xn)=3n+aln3
如果要得到显式的渐近表达式,可以以上式为基础构建迭代式:
x(k+1)n=3n+aln3f(x(k)n)
这里的x(k)n指的是xn的第k级近似。以x(0)n=3n+aln3为初值,进行迭代,并展开,得到
xn=3n+a+lnn+6a+6lnn518n+3a26alnn+11a3ln2n+11lnn954n2+
这跟研发论坛上mathe给出的渐近式是一样的。

迭代的Mathematica代码为(接前):

p[n_] = 3\cdot n + a - Log[3];
Do[p[n_] =
Normal[Series[-h[p[n]] + 3\cdot n + a - Log[3], {n, Infinity, 5}]], {i,
0, 5}]
Series[p[n], {n, Infinity, 5}]

由此发现,这里的a正好是极限值a
a=lim
这也正好同时给出了求a的渐近表达式:
x_k+f(x_k)-3k+\ln 3
利用wayne算出的x_{10^9},代入上式,算得
a=1.1352558473155037141953943477479\dots

转载到请包括本文地址:https://spaces.ac.cn/archives/3696

更详细的转载事宜请参考:《科学空间FAQ》

如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。

如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!

如果您需要引用本文,请参考:

苏剑林. (Apr. 09, 2016). 《一个非线性差分方程的隐函数解 》[Blog post]. Retrieved from https://spaces.ac.cn/archives/3696

@online{kexuefm-3696,
        title={一个非线性差分方程的隐函数解},
        author={苏剑林},
        year={2016},
        month={Apr},
        url={\url{https://spaces.ac.cn/archives/3696}},
}