--- title: 數學軟體實作 - Root finding tags: 2020 Fall - 數學軟體實作 GA: G-77TT93X4N1 --- # Lecture - Root finding ## 數列極限 已知 $\{a_n\}$ 是個收斂數列, 欲判斷數列極限 $$ \lim_{n\to\infty} a_n = L. $$ 想法就是看 $n$ 很大的時候 $a_n$ 的值是多少, 如果沒有變動太多我們就覺得他收斂了! 也就是說, 我們會設定一個容許值(tolerance), 如果 $|a_{n+1}-a_{n}|$ 小於這個數字, 我們就覺得差不多了, 並且覺得 $L \approx a_{n+1}$. 以下我們求 $a_n = \sin(\frac{1}{n})$的極限試試: ```matlab= % 求數列極限範例 tol = 10^(-5); % 設定容許值 difference = 100; % 前後項的差(初始值) ii=1; % 第一步 a0 = sin(1/ii); % a0 = 前一項(a_n) while difference > tol % 如果前後項差大於容許值就繼續做 ii = ii+1; % 下一步 a1 = sin(1/ii); % a1 = 下一項(a_{n+1}) difference = abs(a1-a0); % 計算前後項的差 a0 = a1; % 設定下個迴圈的初始值為 a_1 if(ii>10^5) % 設定跳脫次數 disp('****WARNING****') % 顯示示警及跳脫次數 disp(['Stop!! Too many iterations. ', 'Have not found limit yet.']) break end end disp(['# of iterations= ', num2str(ii)]) disp(['L= ', num2str(a1)]) % 顯示估計出的極限值 ``` --- #### Remark 容許值(tolerance) 越小, 估計出的極限值越準. 不過**容許值不等於誤差值**. --- ### Local function 如果我們常會需要算 $a_{n+1} = f(n)$ 這種樣子數列的極限, 可以用 local function 的方式定義 $f(x)$, 這樣以後若需要找數列極限只需要改 $f$ 的定義就好. 不用在函數裡翻來翻去看哪些地方需要改. #### Remark script 中的 local function 需要在整個 script 的最後, 並且每個 local function 都要有 `end` 做結尾 ```matlab= % % 求數列極限範例 % % 數列 a_{n+1} = f(a_n), 函數 f 定義在此檔案最後的 function y=f(x) % tol = 10^(-5); % 設定容許值 difference = 100; % 前後項的差(初始值) ii=1; % 第一步 a0 = f(ii); % a0 = 前一項(a_n) while difference > tol ii = ii+1; % 下一步 a1 = f(ii); % a1 = 下一項(a_{n+1}) difference = abs(a1-a0); % 計算前後項的差 a0 = a1; % 設定下個迴圈的初始值為 a_1 if(ii>10^5) % 設定跳脫次數 disp('****WARNING****') % 顯示示警及跳脫次數 disp(['Stop!! Too many iterations. ', 'Have not found limit yet.']) break end end disp(['# of iterations= ', num2str(ii)]) disp(['L= ', num2str(a1)]) % 顯示估計出的極限值 function y = f(x) % 定義函數 f(x) y = sin(1./x); end ``` --- ### Exercise 考慮數列 $a_{n+1} = 10\sin(a_n)$, 試用不同初始值 $a_1$ 求其極限. --- ## 函數實根個數 給定一個函數 $f(x)$, $x\in[a, b]$, 我們想要把它所有的實根求出來. 也就是找到所有 $x_r$ 使得 $f(x_r)=0$. 不過首先我們需要先知道有幾個根. 我們用暴力法解決這個問題. 先將 $[a, b]$ 區間分成 $N$ 等分, 這樣我們會得到 $a=x_0<x_1<\cdots<x_{N+1}=b$ 這些區間. 接著我們用中間值定理來看每個區間內有沒有函數的實根. 如果以下式子成立: $$ f(x_i)\cdot f(x_{i+1})<0, $$ 那我們就知道在 $[x_i, x_{i+1}]$ 這區間內至少有一個實根. --- ### Exercise 找出以下函數有多少個實根: $$ f(x) = \frac{\sin(x)}{x} - \frac{1}{10}, \quad x\in [-10, 10] $$ #### code structure - example ``` x = linspace(a, b, N+1); num = 0; for ii=1:N if f(x(ii))*f(x(ii+1))<0 num = num+1; return num ``` --- ## 函數求根 - 固定點迭代 假設我想要求 $f(x) = \frac{\sin(x)}{x} - \frac{1}{10}$ 這個函數的實根. 我可以定義一個數列如下: $$ \frac{\sin(a_n)}{a_{n+1}} -\frac{1}{10}=0, \quad \rightarrow \quad a_{n+1} = 10\sin(a_n). $$ 我們知道如果這數列收斂, 那收斂的值就會是 $f(x)$ 的實根. * **不過它不一定會收斂.** 一般而言, 我們可以定義所謂的固定點迭代 $$ a_{n+1} = f(a_n). $$ 如果 ${a_n}$ 收斂了, 那他就是函數 $f$ 的固定點, $a = f(a)$. ### Fixed point theorem 如果有個函數 $f$ 滿足 $$ |f'(x)|\le \alpha<1, \quad x\in[a, b], $$ 那這個函數就有唯一的固定點, 並且固定點迭代一定會收斂. ### Newton's iteration 假設我們想解 $g(x)=0$, 那我們可以定義另一個函數 $F$: $$ F(x) = x - \frac{g(x)}{g'(x)}, $$ * **$F$ 的固定點 = $g$ 的實根** 那這樣 $g$ 的實根會是 $F$ 的固定點, 並且在每個 $g$ 的實根附近一定有個區間使得以下固定點迭代會收斂, 並且收斂的很快: $$ a_{n+1} = a_n - \frac{g(a_n)}{g'(a_n)}. $$ * **不過我們不知道收斂區間的大小** 延伸閱讀 - [Te-Sheng Lin - Fixed point iteration](https://teshenglin.github.io/post/2019_fixed_point/) * 牛頓法最大迭代次數設定為**10** --- ## Exercise - Root finding 試寫一函數求出 $\frac{\sin(x)}{x}=c$ 所有的實數解. 此函數 input 為 $c$, output 為所有實數解. * $\left|\frac{\sin(x)}{x}\right| \le \frac{1}{|x|}$, 所以實數解只會落在 $\left[-\frac{1}{|c|}, \frac{1}{|c|}\right]$ 這個區間 * $|x|<\epsilon$ 需要單獨定義, 否則會出錯 * 若用牛頓法求根, 需驗證求出的解是否落在區間內 * 若用牛頓法求根10步不收斂, 就再將區間切細