本篇重用M0.2導航的三十秒:Taylor 展開與「假設直線」·M2.0河面上的箭頭:Vector Field 與 ODE
一條彎路,一台省電的導航
你的車以時速 60 公里在一條大彎道上行駛:彎道是四分之一圓,半徑 2 公里。導航為了省電,每 30 秒才讀一次車子的行進方向;在兩次讀取之間,它假設你一直沿著上次讀到的方向直走,把位置往前推 30 秒的距離。
走完這個四分之一圓(約 3.1 公里、三分多鐘),導航上的位置和你真正的位置會差多遠?如果換成一條筆直的路呢?
先用直覺回答,並寫下你有多確定、依據是什麼。常見的直覺是「直路完全不會錯;彎路會偏一點,大概幾十公尺吧」。第一句對。第二句對不對——以及「幾十公尺」是怎麼估出來的——直覺說不出來。而且有一個更重要的問題直覺回答不了:如果改成每 10 秒更新一次,誤差會縮成多少?三分之一?九分之一?
課堂提問Q1
翻成數學。「真正的位置」是哪個物件?「導航算出的位置」又是哪個?「每 30 秒直走一段」寫成式子是什麼?我們想知道的量是什麼?
先想一想,再展開看整理後的答案
這一題可以直接對上前一篇的語言:真正的位置是 ODE x˙=u(x,t) 的解 x(t),u 是「在位置 x 時車的速度向量」——沿著路的方向、大小 v=60 km/h≈16.7 m/s(M2.0)。
導航算的是另一串東西。令 h=30 秒,tn=nh。導航記錄的位置 xn 由
xn+1=xn+hu(xn,tn)一步一步算出來:在目前的位置看一次方向,往那個方向直走 h 秒。這條規則叫 Euler 法,它就是 M2.0 結尾那段「順著箭頭走」的程式。
我們想知道的量是全域誤差 eN=∥x(tN)−xN∥:走完全程(N=T/h 步)之後,真實位置與導航位置的距離。以及它怎麼隨 h 變化。這裡沒有隨機變數;誤差完全來自「兩次讀取之間假設直走」。
先看畫面:切線離開了圓
把彎道畫成一段圓弧,車在圓弧上。Euler 的一步是沿著切線往前走 500 公尺(30 秒 × 16.7 m/s)。切線是直的、圓弧是彎的,走完這一步,導航的點落在圓的外側——這是一步的誤差,叫局部誤差。
下一步從那個已經偏外的點出發。它會犯同樣的錯(又沿切線離開),還會多一件事:它現在站在一個「真車從來沒去過」的位置,讀到的方向也不是真車此刻的方向。前面的錯誤會被帶著走,有時還會被放大。全程的誤差就是這兩件事的疊加:每步新犯的錯,加上舊錯被帶著走的方式。
直路上切線就是路本身,一步的誤差是零,帶著走的也是零。這就是「直路完全不會錯」的畫面版。
寫成數學:一步的錯、多步的累積
局部誤差。 假設第 n 步從正確的位置 x(tn) 出發。真實的下一個位置用 Taylor 展開(M0.2):
x(tn+h)=x(tn)+hx˙(tn)+2h2x¨(ξn),ξn∈[tn,tn+h].
Euler 給的是 x(tn)+hu(x(tn),tn)=x(tn)+hx˙(tn)——恰好是 Taylor 的前兩項。兩者相減:
x(tn+h)−[x(tn)+hu(x(tn),tn)]=2h2∥x¨(ξn)∥.
一步的誤差是 h2 的量級,係數是加速度 x¨。沿著解,x¨=dtdu(x(t),t)=∂tu+(∇u)u(M0.3);對等速轉彎的車,∥x¨∥=v2/R。
全域誤差。 記 en=x(tn)−xn。第 n 步 Euler 不是從正確位置出發,而是從 xn:
en+1=x(tn+1)x(tn)+hu(x(tn),tn)+2h2x¨(ξn)−xn+1[xn+hu(xn,tn)]=en+h[u(x(tn),tn)−u(xn,tn)]+2h2x¨(ξn).
中括號裡是「在兩個相距 ∥en∥ 的位置讀到的方向差」,Lipschitz 條件(M2.0)說它不超過 L∥en∥。所以
∥en+1∥≤(1+hL)∥en∥+2h2Mn,Mn=[tn,tn+1]max∥x¨∥.
這就是離散版 Grönwall 不等式的形狀:每步舊誤差乘上 (1+hL)、再加上新的局部誤差。從 e0=0 展開,用 (1+hL)k≤ekhL≤eLT:
∥eN∥≤n=0∑N−1(1+hL)N−1−n2h2Mn≤eLT2hn=0∑N−1hMn≈2heLT∫0T∥x¨(t)∥dt
□(最後一步把黎曼和換成積分。)三個因子各有意思:h——步長縮一半、誤差縮一半,Euler 是一階方法;∫∥x¨∥dt——整條路的加速度總量,路越彎、轉得越急,誤差越大;直路是零。eLT——場對位置越敏感(L 越大),舊誤差被放大得越凶。這是一個上界,不是等式:前兩個因子通常抓得很準,eLT 常常太悲觀。
展開細節連續版 Grönwall 不等式與它的證明(四行)
連續版:若 φ(t) ≥ 0 滿足 φ(t) ≤ A + L∫₀ᵗ φ(s) ds,則 φ(t) ≤ A·e^(Lt)。
證明:令 Ψ(t) = A + L∫₀ᵗ φ。則 Ψ′ = Lφ ≤ LΨ,所以 d/dt [Ψ e^(−Lt)] = (Ψ′ − LΨ)e^(−Lt) ≤ 0,Ψ(t)e^(−Lt) ≤ Ψ(0) = A,故 φ ≤ Ψ ≤ A e^(Lt)。□
用法:兩條從相距 δ 的起點出發的軌跡,其距離 φ(t) = ‖x(t) − y(t)‖ 滿足 φ(t) ≤ δ + L∫₀ᵗ φ,所以 φ(t) ≤ δ e^(Lt)——起點的差距至多指數放大。Euler 的舊誤差被「帶著走」時放大的就是這個倍數;離散版只是把積分換成和、把 e^(Lh) 換成 (1+hL)。
回到彎道:直覺對了一半,數字對不上
用界估一次。v=16.7 m/s、R=2000 m,∥x¨∥=v2/R≈0.139 m/s²,全程 T≈188 s,所以 ∫∥x¨∥dt≈26 m/s。h=30:2h×26≈390 m。L 是場對位置的敏感度:方向隨位置改變的速率約 v/R≈0.008 /s,LT≈1.6,eLT≈4.8,上界約 1900 m。
真實跑出來(下一節)是 486 公尺。所以:直覺的「幾十公尺」錯了一個數量級——隱含的假設是「每步只偏一點」,忘了六步會累積、還會被帶著放大;「直路不會錯」則完全正確,因為 x¨=0。上界 1900 m 抓到了正確的數量級,但 eLT 把它撐大了四倍——這正是理論常見的處境:它告訴你誤差隨哪些量、以什麼速率變化,但常數要靠實作校準。
而那個直覺回答不了的問題現在有答案:更新間隔改成 10 秒,h 縮三倍,誤差也縮三倍(不是九倍);要縮九倍得每 3.3 秒更新一次。
還有一件容易忘的假設:x¨ 是加速度,不只是轉彎。直路上如果你一直在加減速,x¨=0,Euler 也會錯——只是錯在沿路的前後位置,不是偏出路面。
回到彎道:跑一次,再把 h 調到壞掉
import numpy as np
R, v = 2000.0, 60/3.6
T = (np.pi/2)*R/v # 走完四分之一圓的時間
def u(x): r = np.hypot(*x); return v*np.array([-x[1], x[0]])/r # 沿圓切線
def euler(h):
N = int(round(T/h)); x = np.array([R, 0.0])
for _ in range(N): x = x + (T/N)*u(x)
return np.linalg.norm(x - np.array([0.0, R])) # 與真實終點 (0, R) 的距離
for h in [30, 10, 3, 1]: print(h, round(euler(h)))
# 486, 161, 49, 17:h 縮三倍、誤差縮三倍——一階
四個數字每次縮三倍,符合「一階」。再把 h 往另一邊推:對 x˙=−kx(往路中央拉回的修正力,k 大表示拉得急),Euler 一步是 xn+1=(1−hk)xn。hk<1 時單調收斂;1<hk<2 時來回震盪但仍收斂;hk>2 時 ∣1−hk∣>1,每步放大,發散——這對應到界裡的 (1+hL)N 真的爆掉,界不再「太悲觀」,而是老實地預告了災難。步長不只影響精度,還影響穩定。
先消化一下
參考文獻
- Hairer, E., Nørsett, S. P., Wanner, G. Solving Ordinary Differential Equations I: Nonstiff Problems. Springer, 2nd ed., 1993.(第 I.7 節與第 II.3 節:Euler 法的局部與全域誤差、Grönwall 型的累積論證。)
- Butcher, J. C. Numerical Methods for Ordinary Differential Equations. Wiley, 3rd ed., 2016.(第 2 章:Euler 法的收斂與穩定性。)
- Grönwall, T. H. Note on the Derivatives with Respect to a Parameter of the Solutions of a System of Differential Equations. Annals of Mathematics 20(4), 1919.(Grönwall 不等式的原始出處。)