《微分方程與動力系統(tǒng)(Differential Equations and Dynamical Systems)》聽課筆記1

為了深入理解fMRI分析的原理,還是要學(xué)習(xí)一些微分方程與動力系統(tǒng)的東東,這是我的學(xué)習(xí)筆記,內(nèi)容還沒有很好的整理。

視頻在這里1-Differential Equations and Dynamical Systems Overview_嗶哩嗶哩_bilibili

課程的原始地址在這里:ME 564 - Mechanical Engineering Analysis (washington.edu)

1. Overview

線性代數(shù)是微分方程的一部分,如果可以的話,大學(xué)課程應(yīng)該將這兩部分一起傳授。這門課程除了基本的模型介紹以外,還會結(jié)合Matlab/Python的代碼來進行具體的實現(xiàn)。

這門課程會介紹以下幾個主題:

  1. 微積分:簡單回顧微積分的計算,重點是泰勒展開
  2. 簡單常微分方程(Simple Ordinary Differential Equations, ODEs):即\dot{x}=\lambda x,可以用于描述很多系統(tǒng)(如最常見的兔子吃草問題)
  3. 常微分方程組(System of ODEs):即\dot X = AX,常見的問題如在兔子吃草過程中引入其他動物(比如狼)
  4. 特征值與特征向量
  5. 非線性系統(tǒng)與混沌:即\dot X = f(X),常見的問題如行星運動
  6. 數(shù)值與計算:用Python或者Matlab

2. 微積分回顧:導(dǎo)數(shù)

導(dǎo)數(shù)反映的是一個函數(shù)f(x)對于獨立變量x的變化率。其定義如下:

\begin{equation} \frac{d f}{dx}=\lim\limits_{\Delta x \to 0}\frac{f(x+\Delta x)-f(x)}{\Delta x} \end{equation}

鏈式法則(Chain Rule):

\fracu0z1t8os{d x}f(g(x))=\frac{df}{dx}(g(x))\frac{dg(x)}{dx}=f'(g(x))g'(x)

例子:f(x)=sin(x)g(x)=x^3,則:

f(g(x))=sin(x^3)

\fracu0z1t8os{dx}f(g(x))=3cos(x^3)x^2

3. 向量和矩陣建模

【一個天氣模型】在這個模型中,天氣有三種狀態(tài),分別是多云(cloudy)、下雨(rainy)晴天(nice),已知:
\begin{array}{ll} P(cloudy|cloudy)=0.5 \\ P(rainy|cloudy)=0.25 \\ P(nice|cloudy)=0.25 \\ P(cloudy|rainy)=0.25 \\ P(rainy|rainy)=0.5 \\ P(nice|rainy)=0.25 \\ P(cloudy|nice)=0.5 \\ P(rainy|nice)=0.5 \\ P(nice|nice)=0 \end{array}
上面公式表示一個概率,例如第一條表示如果前一天的天氣為多云時,則第二天的天氣為多云的概率是0.5,后面以此類推。此時,我們可以用一個向量來表示當(dāng)前的天氣情況:
X_{today}=\begin{bmatrix} pr(R)\\ pr(N)\\ pr(C)\\ \end{bmatrix}=\begin{bmatrix} 0 \\ 1 \\ 0 \\ \end{bmatrix}
上式中表示當(dāng)前的天氣為晴天。則第二天的前期狀態(tài)可以根據(jù)之前的概率得到:
X_{tomorrow}=AX_{today}=\begin{bmatrix} 0.5 \\ 0 \\ 0.5 \\ \end{bmatrix}
不難看出,A為:
A=\begin{bmatrix} 0.5&0.5&0.25 \\ 0.25&0&0.25 \\ 0.25&0.5&0.5\\ \end{bmatrix}
此時,可以換一種形式來表示:
\begin{align} X_{k+1}=&AX_k \\ =&A^{k}X_1 \end{align}

clear all, close all, clc
A = [0.5 0.5 0.25;
0.25 0.0 0.25;
0.25 0.5 0.5];
xtoday = [1; 0; 0];
for k=1:50
    k
    xtomorrow = A * xtoday
    xtoday = xtomorrow;
end

運行上述代碼可以看到,這個模型中天氣會收斂到一個穩(wěn)定的狀態(tài),X=\begin{bmatrix}0.4\\0.2\\0.4\end{bmatrix}

有意思的事情是,這個穩(wěn)態(tài)值和矩陣特征向量與特征值的關(guān)系??梢杂?code>eig函數(shù)來得到矩陣的特征值與特征向量:

[T,D]=eig(A)
T =

   -0.6667   -0.7071    0.4082
   -0.3333    0.0000   -0.8165
   -0.6667    0.7071    0.4082


D =

    1.0000         0         0
         0    0.2500         0
         0         0   -0.2500

此時如果對第一個特征值對應(yīng)的特征向量進行歸一化處理,可以得到:

T(:,1)/sum(T(:,1))

ans =

    0.4000
    0.2000
    0.4000

可以看到其最終結(jié)果就是系統(tǒng)的穩(wěn)態(tài)分布,因此可以用這種方法來計算得到穩(wěn)態(tài)分布,而不是使用迭代的方法。

上面過程的Python代碼如下:

import numpy as np
import matplotlib.pyplot as plt
A = np.array([[0.5, 0.5, 0.25],[0.25, 0, 0.25],[0.25, 0.5, 0.5]])
xtoday = np.array([[1], [0], [0]])
the_weather = np.zeros((3,50))
for k in range(50):
    the_weather[:,k] = xtoday[:,0]
    xtomorrow = A@xtoday
    xtoday = xtomorrow
    print(k)
    print(xtomorrow)
    
plt.plot(the_weather.transpose())
plt.grid(True)
天氣收斂

4. 簡單常微分方程和它的指數(shù)解

簡單常微分方程的形式:\dot x = \lambda x

【例子】假設(shè)在一個草原上有x只兔子,兔子的增長速度與兔子的數(shù)量成正比。這個問題就可以描述為上面的公式:
\begin{array}{ll} \dot x = \frac{dx}{dt} = \lambda x \\ x = x(t) \\ \end{array}
其中,\lambda表示增長率,x是時間的函數(shù)。后面我們還會延續(xù)這個模型,引入一些其他的動物。

4.1 微分方程求解

要想計算這個微分方程,有很多種方法:

【method 1】
\begin{align}{ll} \because \frac{dx}{dt} =& \lambda x \\ \therefore dx =& \lambda x dt \\ \Rightarrow \int dx =& \int \lambda x dt \\ \Rightarrow ln(x(t)) =& \lambda t + C \\ \Rightarrow x(t) =& e^{\lambda t +C}= Ke^{\lambda t}\\ \end{align}
根據(jù)上式,不難得到以下結(jié)論:
\begin{array}{ll} x(0)=K \\ \therefore x(t) = e^{\lambda t} x(0) \end{array}

易知上述微分方程的差分形式為:\Delta x=rx(t)\Delta t

5. 使用冪級數(shù)求解微分方程

對于常微分方程\dot x=ax\Rightarrow x(t)=e^{at}x_0,假設(shè)函數(shù)x(t)可以寫成冪級數(shù)的形式,可知:
\begin{align} x(t) = c_0+c_1x+c_2x^2+...\\ \end{align}

\dot x(t)=c_1+2c_2x+3c_3x^2+...
同時:
\begin{align} ax(t) = ac_0+ac_1x+ac_2x^2+...\\ \end{align}
t的對應(yīng)系數(shù)應(yīng)該相等,因此:
\begin{align} c_1=&ac_0=ax_0 \\ 2c_2=&ac_1\Rightarrow c_2=\frac{a}{2}c_1=\frac{a^2}{2}x_0 \\ 3c_3 =&ac_2 \Rightarrow c_3=\frac{a}{3}c_2=\frac{a^3}{3!}x_0 \\ ...\\ (n+1)c_{n+1}=&ac_n \Rightarrow c_{n+1}=\frac{a}{(n+1)!}x_0 \end{align}
所以:
\begin{align} x(t)=&x_0+x_0at+x_0\frac{a^2t^2}{2!}+x_0\frac{a^3t^3}{3!}+...\\ =&x_0[1+at+\frac{a^2t^2}{2!}+\frac{a^3t^3}{3!}+...] \\ =&x_0e^{at} \end{align}

6. 泰勒級數(shù)和冪級數(shù)

一個函數(shù)f(x)可以在一個點xf(x)x處光滑)被泰勒展開:
f(x+\Delta x)=f(x)+\frac{df(x)}{dx}\Delta x+\frac{d^2f(x)}{dx^2}\frac{\Delta x^2}{2!}+\frac{d^3f(x)}{dx^3}\frac{\Delta x^3}{3!}+...+\frac{d^nf(x)}{dx^n}\frac{\Delta x^n}{n!}+...
如果在特定的點a(即x=a+\Delta x)展開,上述公式也可以寫為如下形式:
f(x)=f(a)+\frac{df}{dx}(x-a)+\frac{d^2f}{dx^2}\frac{(x-a)^2}{2!}+\frac{d^3f}{dx^3}\frac{(x-a)^3}{3!}+...
【例1】當(dāng)f(x)=sin(x)時,其泰勒展開為:
\begin{align} sin(x)=&sin(0)+cos(0)x-\frac{sin(0)}{2!}x^2-\frac{cos(0)}{3!}x^3+... \\ =&x-\frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+\frac{x^9}{9!}+... \\ \end{align}
【例2】當(dāng)f(x)=cos(x)時,其泰勒展開為:
cos(x)=1-\frac{x^2}{2!}+\frac{x^4}{4!}-\frac{x^6}{6!}+\frac{x^8}{8!}+...
Matlab代碼如下:

clear all, close all
x = -10:0.01:10;
y = sin(x);
plot(x, y, 'k', 'LineWidth',2)
axis([-10 10 -10 10])
grid on, hold on

%% 一階泰勒展開
P = [1 0];
yT1 = polyval(P, x);
plot(x, yT1, 'b--', 'LineWidth', 1.2)

%% 三階泰勒展開
P = [-1/factorial(3) 0 1 0];
yT3 = polyval(P, x);
plot(x, yT3, 'r--', 'LineWidth', 1.2)

%% 五階泰勒展開
P = [1/factorial(5) 0 -1/factorial(3) 0 1 0];
yT5 = polyval(P, x);
plot(x, yT5, 'g--', 'LineWidth', 1.2)

%% 七階泰勒展開
P = [-1/factorial(7) 0 1/factorial(5) 0 -1/factorial(3) 0 1 0];
yT7 = polyval(P, x);
plot(x, yT7, 'm--', 'LineWidth', 1.2)

%% 九階泰勒展開
P = [1/factorial(9) 0 -1/factorial(7) 0 1/factorial(5) 0 -1/factorial(3) 0 1 0];
yT9 = polyval(P, x);
plot(x, yT9, 'c--', 'LineWidth', 1.2)
talyor.png

Python的泰勒展開結(jié)果如下:

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
from scipy.special import factorial

x = np.linspace(-10, 10, 2000)
y = np.sin(x)
plt.plot(x, y, 'k', linewidth=2)
plt.xlim(-10, 10)
plt.ylim(-10, 10)
plt.grid(True)

# 一階泰勒展開
P = [1, 0]
yT1 = np.polyval(P, x)
plt.plot(x, yT1, 'b--', linewidth=1.2)

# 三階泰勒展開
P = [-1/factorial(3), 0, 1, 0]
yT3 = np.polyval(P, x)
plt.plot(x, yT3, 'r--', linewidth=1.2)

# 五階泰勒展開
P = [1/factorial(5), 0, -1/factorial(3), 0, 1, 0]
yT5 = np.polyval(P, x)
plt.plot(x, yT5, 'g--', linewidth=1.2)

# 七階泰勒展開
P = [-1/factorial(7), 0, 1/factorial(5), 0, -1/factorial(3), 0, 1, 0]
yT7 = np.polyval(P, x)
plt.plot(x, yT7, 'm--', linewidth=1.2)

# 九階泰勒展開
P = [1/factorial(9), 0, -1/factorial(7), 0, 1/factorial(5), 0, -1/factorial(3), 0, 1, 0]
yT9 = np.polyval(P, x)
plt.plot(x, yT9, 'c--', linewidth=1.2)
image.png

7.指數(shù)函數(shù)的泰勒級數(shù)和歐拉公式

本節(jié)課利用泰勒級數(shù)推導(dǎo)出歐拉公式,過程如下:
\begin{align} e^x =& 1 + x+\frac{x^2}{2!}+\frac{x^3}{3!}+\frac{x^4}{4!}+\frac{x^5}{5!}+... \\ =& \sum_{k=0}^{\infty}\frac{x^k}{k!}\\ \Rightarrow e^{ix}=& 1 + ix+\frac{(ix)^2}{2!}+\frac{(ix)^3}{3!}+\frac{(ix)^4}{4!}+\frac{(ix)^5}{5!}+...\\ =&(1-\frac{x^2}{2!}+\frac{x^4}{4!}-\frac{x^6}{6!}+...) + i(x-\frac{x^3}{3!}+\frac{x^5}{5!}+...) \\ =&cos(x)+isin(x) \end{align}
得到上述公式后,后面的計算會變得更加容易

8. 用二階常微分方程描述諧振子

此處,我們引入了一個物理學(xué)中的常見概念——諧振子,并使用微分方程來對其狀態(tài)進行建模。

問題描述如下:在一個光滑平面上,有一個質(zhì)量為 m 的物體,其一端用彈簧與墻壁相連,彈簧的系數(shù)為k,物體偏移靜止?fàn)顟B(tài)(即除支撐力外,不受任何彈簧彈力)的位移為x,則可知:

\begin{align} F=&-Kx=ma \\ v=&\frac{dx}{dt} \\ a=& \frac{dv}{dt}= \frac{d^2x}{dt^2} \\ \end{align}
m=1,K=1,則:
\begin{align} \frac{d^2x}{dt^2}=-x \Rightarrow \ddot x = -x \end{align}
求解上述方程的方法有很多種:

【Method 1】瞪眼法

因為x(0)=0,\dot x(0)=v_0=0,結(jié)合前面的泰勒展開結(jié)果,充分考慮這些初始條件,則可以猜測
\begin{align} x(t)=cos(t)x_0 \end{align}

\begin{align} \dot x(t)=&-sin(t)x_0\\ \ddot x(t)=&-cos(t)x_0\\ \end{align}
而上述結(jié)果滿足之前的\ddot x = -x,于是瞪眼成功。

對于一般的Km,
\begin{align} x(t)=cos(\sqrt\frac{K}{m}t)x(0) \end{align}

【Method 2】泰勒級數(shù)展開

\begin{align} x(t)=&c_0+c_1t+c_2t^2+c_3t^3+c_4t^4+...\\ \dot x(t)=&c_1+2c_2t+3c_3t^2+4c_4t^3+5c_5t^4... \\ \ddot x(t)=&2c_2+3\cdot2c_3t+4\cdot3c_4t^2+5\cdot4c_5t^3... \\ \end{align}

因此
\begin{align} c_0=&x_0 \\ c1=&v_0 \\ 2c_2=&-c_0 \Rightarrow c_2=-\frac{1}{2}x_0 \\ 3\cdot2c_3=&-c_1 \Rightarrow c_3=-\frac{1}{3!}v_0 \\ 4\cdot3c_4=&-c_2 \Rightarrow c_4 = \frac{1}{4!}x_0 \\ 5\cdot4c_5=&-c_3 \Rightarrow c_5 = \frac{1}{5!}v_0 \\ ... \end{align}
將其帶回,可得:
\begin{align} x(t)=&x_0+v_0t-\frac{1}{2!}x_0t^2-\frac{1}{3!}v_0t^3+\frac{1}{4!}x_0t^4+\frac{1}{5!}v_0t^5+... \\ =&x_0(1-\frac{t^2}{2!}+\frac{t^4}{4!}-\frac{t^6}{6!}+...)+v_0(t-\frac{t^3}{3!}+\frac{t^5}{5!}+...) \\ =&cos(t)x_0+sin(t)v_0 \end{align}

【Method 3】瞪眼法2

一個函數(shù)求導(dǎo)之后仍然是自身的函數(shù),最容易想到的就是指數(shù)函數(shù),因此不妨猜測x是一種指數(shù)函數(shù)。
\begin{align} x(t)=&e^{\lambda t}\\ \dot x=&\lambda e^{\lambda t} \\ \ddot x=&\lambda^2 e^{\lambda t} \end{align}

將其代入微分方程,可得:
\begin{align} \lambda^2 e^{\lambda t}=&-e^{\lambda t} \Rightarrow \lambda ^2=-1 \end{align}
所以:
\begin{align} x(t)=&c_1e^{it}+c_2e^{-it}\\ =&(c_1+c_2)cos(t)+i(c_1-c_2)sin(t) \end{align}

【Method 4】Suspend variable

在該方法中,引入一個新的變量v=\frac{dx}{dt}
\left. \begin{matrix} \dot x=v \\ \dot v=-x \end{matrix} \right\}\Rightarrow \fracu0z1t8os{dt} \begin{bmatrix} x \\ v \end{bmatrix}= \begin{bmatrix} 0 & 1 \\ -1 & 0 \end{bmatrix} \begin{bmatrix} x \\ v \end{bmatrix}
令:
A= \begin{bmatrix} 0 & 1 \\ -1 & 0 \end{bmatrix} \\ \underline x= \begin{bmatrix} x \\ v \end{bmatrix}
則:
\dot {\underline x} = A \underline x \Rightarrow \underline x=e^{At}\underline x(0)

9. 二階ODE,阻尼震蕩器

阻尼震蕩器

新的問題變成了添加了一個阻尼的震蕩子,如上圖所示,此時模型變?yōu)椋?br> \begin{align} F=ma \Rightarrow& -Kx-d\dot x = m\ddot x \\ \Rightarrow& m \ddot x+d \dot x+ Kx = 0 \end{align}

\begin{align} \zeta =& \fracu0z1t8os{m} \\ \omega^2 =& \frac{K}{m} \end{align}

所以:

\ddot x+\zeta \dot x+\omega^2x=0
看到這個模型,不難繼續(xù)要使用瞪眼法,令:

\left. \begin{align} x(t)=&e^{\lambda t} \\ \dot x(t) =& \lambda e^{\lambda t}\\ \ddot x(t) =& \lambda^2 e^{\lambda t} \end{align} \right\} \Rightarrow \lambda^2e^{\lambda t}+\zeta\lambda e^{\lambda t}+\omega^2 e^{\lambda t}=0

所以:

\lambda^2+\zeta\lambda+\omega^2=0
這個方程被稱為特征方程。

其解為:
\lambda=\frac{-\zeta \pm \sqrt{\zeta^2-4\omega^2}}{2}
最終
x(t)=c_1e^{\lambda_1t}+c_2e^{\lambda_2t}
還可以將模型寫為矩陣形式:
\left\{ \begin{align} \dot x =& v \\ \dot v =& -\omega^2x-\zeta v \\ \end{align} \right. \Rightarrow \fracu0z1t8os{dt} \begin{bmatrix} x \\ v \\ \end{bmatrix} = \begin{bmatrix} 0 & 1\\ -\omega^2 & -\zeta \\ \end{bmatrix} \begin{bmatrix} x \\ v\\ \end{bmatrix}
下面我們在Matlab中對這個過程進行模擬,需要注意的是:
\begin{align} \because \frac{dx}{dt} =& Ax \\ \therefore \Delta x =& Ax\Delta t \\ x_{k+1} =& x_{k}+Ax\Delta t \\ t_k =& k\Delta t \end{align}
看懂了上式就可以對上述過程進行編碼了,具體代碼如下

clear all; close all;

w = 2*pi; 
d = 0.25;

% dt = Ax,此處和文中給出的公式并不一致,相當(dāng)于k=.5,但是只要知道這是在做一些系統(tǒng)初始化的設(shè)置即可
A = [0 1; -w^2 -2*d*w];

dt = .01;   % time step
T = 10;     % amount of time to integrate

% 初始位置在2處,初始速度為0
x0 = [2; 0];

xF(:,1) = x0;
tF(1) = 0;
for k=1:T/dt
    tF(k+1) = k*dt;
    xF(:,k+1) = (eye(2) + dt*A)*xF(:,k);
end

plot(tF, xF(1,:), 'k')

% 使用龍格庫塔(Runge Kutta)得到的結(jié)果
[t, xGood] = ode45( @(t, x) A*x, 0:dt:T, x0);
hold on
plot(t, xGood(:,1), 'r')
xlabel('Time (s)')
ylabel('Position (m)')
legend('Forward Euler', 'ODE45(RK4)')

figure
plot(xGood(:,1),xGood(:,2),'k')
xlabel('Position [m]')
ylabel('Velocity [m/s]')
位置隨時間變化圖
狀態(tài)圖
import numpy as np
from matplotlib import pyplot as plt
from scipy.integrate import solve_ivp

# play around with different 'd' and 'dt' to see various behavior!

w = 2 * np.pi  # natural frequency
d = .25        # damping ratio

# spring-mass-damper system
A = np.array([[0, 1], [-w ** 2, -2 * d * w]])  # \dot{x} = Ax

dt = 0.01  # time step
T = 10     # amount of time to integrate
n = int(T / dt)
t = np.linspace(0, T, n)

x0 = [2, 0]  # initial condition (x=2, v=0)

# iterate forward Euler
xF = np.zeros((2, n))
xF[:, 0] = x0
for k in range(n - 1): 
    xF[:, k + 1] = (np.eye(2) + dt * A) @ xF[:, k]

# compute better integral using built-in python code
# 4th-order Runge Kutta 
def linear_ode(t, x):
    return A @ x  # @ symbol for matrix-vector product here

linear_ode_solution = solve_ivp(linear_ode, (0, T), x0, t_eval=t) 
xGood = linear_ode_solution.y

plt.figure(figsize=(20, 4))
plt.subplot(1, 2, 1)
plt.plot(t, xF[0, :], 'k')
plt.plot(t, xGood[0, :],'r')
plt.xlabel('Time [s]')
plt.ylabel('Position [m]')
plt.legend(['Forward Euler', 'ODE45 (RK4)'])
plt.grid(True)

plt.subplot(1, 2, 2)
plt.plot(xF[0, :], xF[1, :], 'k')
plt.plot(xGood[0, :], xGood[1, :], 'r')
plt.xlabel('Position [m]')
plt.ylabel('Velocity [m/s]')
plt.legend(['Forward Euler', 'ODE45 (RK4)'])
plt.grid(True)
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容