5.13 选读:常微分方程与动力系统视角
本章的最后节把前面各节用到的工具集中到一个具体场景:描述「随时间演化」的方程。这类方程在应用中出现得最多:物理中的运动方程、化学中的反应动力学、生物中的种群模型、机器学习中的参数演化(梯度下降本身就是一条常微分方程的离散化)。本节的目标不是把常微分方程理论讲完整,而是把本章前面各节的工具如何在其中起作用这件事说清楚。
四条线索构成本节。存在唯一性用 Picard 迭代证明,它的核心是 5.1 节的压缩映射原理:把初值问题写成积分方程,再证明右端是压缩映射。相平面分析用 5.8 节的线性化与 Jacobian 特征值,把平衡点分类为结点、鞍点、焦点与中心,稳定性由特征值的实部决定。Lyapunov 方法把「稳定性」的证明化为「找一个沿轨道单调的函数」,梯度流是它最直接的例子(
5.13.1 初值问题与存在唯一性
问题的提法与积分方程形式
一阶常微分方程组的初值问题指
其中
把方程写成积分方程(对
这两个形式是等价的(
Picard 迭代
Picard 迭代(逐步逼近法)把积分方程当作不动点方程来解:
从常函数
则存在
证明的骨架与 5.1 节的压缩映射原理完全一致:在连续函数空间
取
实验一第一组的数据给出收敛的量化形态(
Lipschitz 条件的必要性与解的爆破
Lipschitz 条件是定理的关键假设,去掉它之后存在性仍可能成立,但唯一性会失效。标准反例是
另一类现象是解的爆破:
后两行的迭代仍然收敛(误差有限),说明
5.13.2 线性系统与相平面
线性系统与矩阵指数
线性常系数系统
矩阵指数的级数与数量指数同形(5.7 节的幂级数结论(对矩阵同样成立):收敛半径无穷)。若
平衡点的分类
两实特征值同号:
两实特征值异号:鞍点,一条方向吸引、一条方向排斥。
共轭复特征值
判断稳定性只看实部:
实验三用四个线性系统核对分类(初始条件
| 系统 | 特征值 | ||
|---|---|---|---|
| 稳定结点 | |||
| 鞍点 | |||
| 稳定焦点 | |||
| 中心 |
四条数据的读法:
中心一行还有一个细节:
非线性系统与线性化
非线性系统
这条定理把非线性问题局部化为线性问题,是相平面分析的基本工具。它也是优化算法的收敛性分析的起点:梯度下降
5.13.3 Lyapunov 函数与梯度流
Lyapunov 稳定性
Lyapunov 函数是沿轨道单调(不增)的函数,它的存在给出稳定性的判据。设
蕴含
例子:线性系统
梯度流
取
等号只在临界点处成立。由 Lyapunov 判据,梯度流的轨道收敛到临界点(在适当条件下收敛到极小点)。
实验四用双井势
收敛速率由线性化给出:在
这两条数据的实用含义:梯度流的收敛速率由极小点处 Hessian 的特征值决定,目标函数的衰减速率是它的两倍。这个关系在优化中直接对应「梯度下降在强凸函数上的线性收敛率」(第三章 3.3 节):迭代格式的速率是
5.13.4 数值解法与刚性
显式方法与其稳定域
最简单的数值方法是显式 Euler:
四阶 Runge-Kutta(RK4)的放大因子是
刚性
若系统中同时存在时间尺度差异很大的分量(特征值的模相差多个数量级),称问题是刚性的。刚性比定义为
刚性问题的困难在于:解的光滑部分由慢尺度决定(
实验二用
解是光滑的余弦(快分量在瞬态之后消失),但方程的特征值是
隐式 Euler(
方法的选取
三条实用原则。
看刚性比:
看精度与稳定性的平衡:隐式 Euler 只有一阶精度,实际常用二阶的梯形法(A 稳定但不 L 稳定,对极刚分量处理不够好)或 BDF2、Radau 等方法(高阶且 L 稳定)。
检查数值耗散:对需要长时间积分的守恒系统(5.13.2 节的中心型轨道),格式的耗散性质比精度阶更重要,应当用辛格式或保结构格式;对刚性衰减问题,需要格式在
5.13.5 与其他章节的联系
常微分方程与动力系统的视角把本章的许多内容串起来。
与 5.1 节:存在唯一性用压缩映射原理证明,Lipschitz 条件、完备性与不动点迭代是同一条线索。
与 5.4 与 5.8 节:数值解法的精度阶用 Taylor 展开分析(局部截断误差),相平面分类用 Jacobian 的特征值,Lyapunov 函数的构造用二次型与梯度。
与 5.12 节:刚性问题的困难与边界层问题同源(小参数导致的时间或空间尺度分离),处理方法也平行(隐式方法对应指数拟合格式,后者是「在单元内精确求解」的思路)。
与第三章:梯度下降是最优化算法,同时是一条梯度流(连续时间极限
与第二章:随机微分方程是常微分方程加噪声项,其数值解法(Euler-Maruyama、Milstein)的稳定性分析沿用本节的框架;扩散过程与 Fokker-Planck 方程的联系也建立在这里。
5.13.6 数值实验
实验一:Picard 迭代与解的存在唯一性
第一组用线性问题观察迭代的收敛形态,第二组用非线性问题观察压缩条件与解的爆破。
import math
import numpy as np
print("(a) y' = y,y(0) = 1(精确解 e^x),Picard 迭代 y_{n+1} = 1 + int_0^x y_n dt")
xg = np.linspace(0, 1, 2001)
y = np.ones_like(xg)
print(f"{'n':>5} {'最大误差':>16} {'误差比值 (n-1 -> n)':>22}")
prev = None
for n in range(1, 9):
y = 1.0 + np.array([np.trapezoid(y[:i + 1], xg[:i + 1]) for i in range(len(xg))])
e = float(np.max(np.abs(y - np.exp(xg))))
r = "-" if prev is None else f"{prev / e:.2f}"
print(f"{n:>5} {e:>16.3e} {r:>22}")
prev = e
print("(b) y' = y^2,y(0) = 1(精确解 1/(1-x),在 x = 1 处爆破)")
print(f"{'区间右端 a':>10} {'迭代 8 次后的最大误差':>24} {'Lipschitz 常数 2/(1-a)':>24} {'a*L':>10}")
for a in [0.2, 0.3, 0.5, 0.8]:
xg2 = np.linspace(0, a, 2001)
y2 = np.ones_like(xg2)
for n in range(8):
y2 = 1.0 + np.array([np.trapezoid(y2[:i + 1] ** 2, xg2[:i + 1])
for i in range(len(xg2))])
exact = 1.0 / (1.0 - xg2)
L = 2.0 / (1.0 - a)
print(f"{a:>10.1f} {float(np.max(np.abs(y2 - exact))):>24.6e} {L:>24.4f} {a * L:>10.4f}")输出:
(a) y' = y,y(0) = 1(精确解 e^x),Picard 迭代 y_{n+1} = 1 + int_0^x y_n dt
n 最大误差 误差比值 (n-1 -> n)
1 7.183e-01 -
2 2.183e-01 3.29
3 5.162e-02 4.23
4 9.948e-03 5.19
5 1.615e-03 6.16
6 2.262e-04 7.14
7 2.780e-05 8.14
8 3.002e-06 9.26
(b) y' = y^2,y(0) = 1(精确解 1/(1-x),在 x = 1 处爆破)
区间右端 a 迭代 8 次后的最大误差 Lipschitz 常数 2/(1-a) a*L
0.2 1.304206e-09 2.5000 0.5000
0.3 5.565785e-08 2.8571 0.8571
0.5 2.526338e-05 4.0000 2.0000
0.8 4.203331e-02 10.0000 8.0000(a) 迭代的收敛形态。最大误差从
(b) 压缩条件与爆破。四行数据把
要注意的是后两行的迭代仍然收敛,尽管
实验二:刚性方程与显式/隐式方法
用刚性比
import math
import numpy as np
print("y' = -1000 (y - cos t) - sin t,y(0) = 1,精确解 y = cos t(刚性比 1000)")
print("显式 Euler 的稳定条件 |1 - 1000 h| <= 1,即 h <= 0.002")
def solve_stiff(h, T=2.0, scheme="explicit"):
N = int(round(T / h))
ts = np.linspace(0, T, N + 1)
y = np.zeros(N + 1)
y[0] = 1.0
lam = 1000.0
for i in range(N):
tn, tn1 = ts[i], ts[i + 1]
if scheme == "explicit":
y[i + 1] = y[i] + h * (-lam * (y[i] - math.cos(tn)) - math.sin(tn))
else:
y[i + 1] = (y[i] + h * (lam * math.cos(tn1) - math.sin(tn1))) / (1.0 + lam * h)
return ts, y
print(f"{'h':>10} {'显式 Euler 最大误差':>22} {'显式结果是否发散':>18} "
f"{'隐式 Euler 最大误差':>22}")
for h in [0.01, 0.002, 0.001, 0.0005, 0.0001]:
ts, ye = solve_stiff(h, scheme="explicit")
ts, yi = solve_stiff(h, scheme="implicit")
ex = np.cos(ts)
diverge = "是" if float(np.max(np.abs(ye))) > 10 else "否"
print(f"{h:>10} {float(np.max(np.abs(ye - ex))):>22.3e} {diverge:>18} "
f"{float(np.max(np.abs(yi - ex))):>22.3e}")输出:
y' = -1000 (y - cos t) - sin t,y(0) = 1,精确解 y = cos t(刚性比 1000)
显式 Euler 的稳定条件 |1 - 1000 h| <= 1,即 h <= 0.002
h 显式 Euler 最大误差 显式结果是否发散 隐式 Euler 最大误差
0.01 3.528e+185 是 4.996e-06
0.002 2.000e-06 否 9.998e-07
0.001 5.000e-07 否 4.999e-07
0.0005 2.500e-07 否 2.500e-07
0.0001 5.000e-08 否 5.000e-08隐式 Euler 的表现完全不同:
实验三:相平面与线性系统平衡点的分类
对四个线性系统计算特征值、终态范数与振荡指标。
import numpy as np
systems = [
("稳定结点", np.array([[-1.0, 0.0], [0.0, -2.0]])),
("鞍点", np.array([[1.0, 0.0], [0.0, -1.0]])),
("稳定焦点", np.array([[-0.5, 1.0], [-1.0, -0.5]])),
("中心", np.array([[0.0, 1.0], [-1.0, 0.0]])),
]
h = 0.001
T = 10.0
N = int(T / h)
print(f"{'类型':>10} {'特征值':>28} {'|y(T)|':>14} {'y1 的符号变化次数':>18}")
for name, A in systems:
ev = np.linalg.eigvals(A)
y = np.zeros((N + 1, 2))
y[0] = [1.0, 1.0]
for i in range(N):
y[i + 1] = y[i] + h * (A @ y[i])
sign_changes = int(np.sum(np.diff(np.sign(y[1:, 0])) != 0))
evs = ", ".join(f"{v.real:+.4f}{v.imag:+.4f}j" for v in ev)
print(f"{name:>10} {evs:>28} {float(np.linalg.norm(y[-1])):>14.6f} {sign_changes:>18}")输出:
类型 特征值 |y(T)| y1 的符号变化次数
稳定结点 -1.0000+0.0000j, -2.0000+0.0000j 0.000045 0
鞍点 +1.0000+0.0000j, -1.0000+0.0000j 21916.681339 0
稳定焦点 -0.5000+1.0000j, -0.5000-1.0000j 0.009565 3
中心 +0.0000+1.0000j, +0.0000-1.0000j 1.421302 3四行数据把分类的两条判据都显示出来了。稳定性由
中心一行的末值比初值大
实验四:梯度流与 Lyapunov 函数
对双井势与单井势分别运行梯度流,检验 Lyapunov 单调性与收敛速率。
import numpy as np
print("V(theta) = (theta^2 - 1)^2 / 4,梯度流 dtheta/dt = -theta(theta^2 - 1)")
print("起点 theta(0) = 1.8,向极小点 theta* = 1 收敛(线性化速率 2)")
h = 0.001
T = 20.0
N = int(T / h)
ts = np.linspace(0, T, N + 1)
th = np.zeros(N + 1)
th[0] = 1.8
for i in range(N):
d = th[i] * (th[i] ** 2 - 1.0)
th[i + 1] = th[i] - h * d
V = (th ** 2 - 1.0) ** 2 / 4.0
dV = np.diff(V)
print(f" V(theta(T)) = {V[-1]:.6e},theta(T) = {th[-1]:.10f}")
print(f" 单调性检验:所有步上 V 的增量 <= 0,最大增量 = {float(np.max(dV)):.3e}")
sel = (ts > 3.0) & (ts < 6.0)
slope = float(np.polyfit(ts[sel], np.log(V[sel]), 1)[0])
print(f" 区间 3 < t < 6 上 ln V 的斜率 = {slope:.6f}(理论值 -4)")
print(f" 该区间内 V 从 {float(V[sel][0]):.3e} 降到 {float(V[sel][-1]):.3e}")
print("V(theta) = theta^2/2(单井),起点 theta(0) = 2")
th2 = np.zeros(N + 1)
th2[0] = 2.0
for i in range(N):
th2[i + 1] = th2[i] - h * th2[i]
V2 = th2 ** 2 / 2
slope2 = float(np.polyfit(ts[sel], np.log(V2[sel]), 1)[0])
print(f" 区间 3 < t < 6 上 ln V 的斜率 = {slope2:.6f}(理论值 -2)")
print(f" V(theta(T)) = {V2[-1]:.6e},theta(T) = {th2[-1]:.12f}")输出:
V(theta) = (theta^2 - 1)^2 / 4,梯度流 dtheta/dt = -theta(theta^2 - 1)
起点 theta(0) = 1.8,向极小点 theta* = 1 收敛(线性化速率 2)
V(theta(T)) = 3.056885e-27,theta(T) = 1.0000000000
单调性检验:所有步上 V 的增量 <= 0,最大增量 = 0.000e+00
区间 3 < t < 6 上 ln V 的斜率 = -4.004766(理论值 -4)
该区间内 V 从 7.224e-07 降到 4.406e-12
V(theta) = theta^2/2(单井),起点 theta(0) = 2
区间 3 < t < 6 上 ln V 的斜率 = -2.001001(理论值 -2)
V(theta(T)) = 8.328351e-18,theta(T) = 0.000000004081双井势的轨道从
收敛速率的两条数据给出连续时间版本的「强凸收敛率」:双井势在
5.13.7 本节小结
常微分方程的四层内容
本节把常微分方程与动力系统的视角组织为四层。存在唯一性层给出 Picard-Lindelöf 定理:把初值问题写成积分方程
至此第五章完成。本章从实数与极限出发,经过数列与级数、连续与微分、积分与测度、多元微积分与变分、渐近分析,最终回到常微分方程与动力系统。这条路线把「极限」这一个工具在六个方向上的展开讲完了:数、函数、函数列、多元、测度、参数极端。第四章的信息论中的核心量(熵、互信息、KL 散度)都以本章积分的严格理论为基础,其中 KL 散度的定义需要 5.10 节的 Radon-Nikodym 定理才能说清楚;而当信息论与最优化用于分析具体算法与模型时,本章的一致收敛条件(5.6 节)、极限交换定理(5.10 节)与渐近分析(5.12 节)会成为判断结论有效性的依据。第三章的梯度下降、近端方法与对偶理论,分别对应本节的梯度流、非光滑动力系统与 Lagrangian 动力学,三条线索在最优化、动力系统与数值分析之间构成一组可以互相翻译的语言。
练习题
第 1 题 概念推导
(a) 把二阶方程
参考答案
(a) 令
特征方程是
(b)
被违反的假设是 Lipschitz 条件(
(c)
由此可以推出三条结论:一是
第 2 题 计算推理
(a) 求
参考答案
(a) 显式 Euler 的放大因子
在
(b) 矩阵是下三角,特征值是
(c)
第 3 题 代码验证
用本节代码做三组实验并解释:(a) 在实验三里把中心系统的
参考答案
(a) 放大因子是
(b) 刚性比
(c)
第 4 题 综合应用
某数值程序需要求解一个由
参考答案
刚性的量化判断。刚性比
方法选择。刚性问题的标准选择是隐式多步或隐式 Runge-Kutta(IRK)。三条候选:BDF(向后差分公式)方法的 BDF2 到 BDF5(L 稳定,阶数 2 到 5,每步需要解一次隐式方程,用 Newton 迭代,Jacobian 可以复用多个步);Radau IIA(L 稳定的 IRK,3 阶或 5 阶,每步需要解
步长策略。用自适应步长:步长的选择由局部误差估计(嵌入方法或步长加倍比较)与稳定性两方面决定。L 稳定方法没有稳定性限制,因此步长只受精度与 Newton 迭代收敛性的约束,初始阶段(快分量尚未衰减)需要小步长,之后可以迅速放大到与慢尺度匹配的步长(
精度与代价的估计。BDF2 的局部截断误差是
验证方案:用两种不同阶数的方法(如 BDF2 与 BDF3)或两种不同步长序列计算,检查精度阶是否与理论相符(步长减半误差降到四分之一);用守恒量或已知的稳态(若模型有稳态解,检查长期极限是否一致)做物理合理性检验;检查 Newton 迭代的收敛性(残差是否按预期下降)与步长序列的合理性(步长变化不应剧烈振荡,否则说明误差估计器有问题)。报告中给出刚性比、所用格式、稳定性质(A/L 稳定)、步长策略与总计算代价,这些信息合起来才能让结果可复核。
常见错误
错误 1 · 把稳定性与精度混为一谈
原因:稳定性(误差不放大)与精度(误差的大小)是两个独立的问题。显式 Euler 在
解决:分别检查两条性质。稳定性用稳定域分析(把
错误 2 · 用线性化的结论判断非双曲平衡点
原因:线性化定理只对双曲平衡点(Jacobian 特征值实部全非零)成立。非双曲情形(存在实部为零的特征值)下,高阶项决定稳定性,线性化给出的结论可能完全错误。典型例子:
解决:先检查特征值的实部是否全非零(计算
错误 3 · 在刚性问题上沿用显式方法的步长
原因:显式方法的步长限制由刚性尺度决定,与解的光滑程度无关。本节实验二的例子中,解是光滑的余弦(变化尺度是
解决:先估计 Jacobian 的特征值范围(解析求导、数值差分或用 Gershgorin 圆盘估计),算出刚性比与显式方法的步长限制,再决定方法。刚性比超过
错误 4 · 用数值解的长时行为代替理论分析
原因:数值格式本身可能改变系统的定性行为,因此长期积分的结果不能直接当作方程的结论。本节实验三给出例子:中心型系统(真实轨道闭合、能量守恒)用显式 Euler 积分后振幅按
解决:长时积分前先确定系统的定性性质(守恒量、平衡点的类型、是否耗散),再选择与之一致的格式(守恒系统用辛格式或保能量格式,耗散系统用 L 稳定格式)。用守恒量或 Lyapunov 函数监控数值解(本节实验四的单调性检验就是这种监控):守恒量的漂移量应当与格式的阶数和步长相符,出现系统性漂移说明格式不合适。报告中说明格式的性质(是否保结构)与监控量的漂移量,不要只报告终态的数值。