--- title: 數學軟體實作 - 稀疏矩陣 tags: 2020 Fall - 數學軟體實作 GA: G-77TT93X4N1 --- # Lecture - Solving sparse linear system ### Example 1 如果某矩陣大部分的元素為零, 只有少部分的非零元素, 那麼一個比較有效率的做法是不要將整個矩陣的元素都存下來, 只需要存非零部分就好. 這種矩陣稱為稀疏矩陣(sparse matrix). 舉例來說, 以下這矩陣只有對角線部分有值, 其他皆為零, $$ \begin{bmatrix} 2 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 2 \end{bmatrix} $$ ```matlab= A = diag([2 1 2]) % 產生一個只有對角線有值的矩陣 S = sparse(A) % 將 A 變成稀疏矩陣 ``` 執行結果為: ``` A = 2 0 0 0 1 0 0 0 2 S = (1,1) 2 (2,2) 1 (3,3) 2 ``` 可以看出兩種作法的差別, $A$ 記全部元素, $B$ 則只記非零的部分. 再來試更大的矩陣, 這次是 $10000\times 10000$: ```matlab= A = diag(rand(10^4, 1)); % 產生一個只有對角線有值的矩陣 S = sparse(A); % 將 A 變成稀疏矩陣 whos % 看看變數細節 ``` 可以看出 $A$ 跟 $S$ 都是 $1000\times 1000$ 的矩陣, 不過所需要存的記憶體則有約三千倍的差別 (Bytes 那欄). ``` Name Size Bytes Class Attributes A 10000x10000 800000000 double S 10000x10000 240008 double sparse ``` 所以, 如果一個矩陣很稀疏, 那就務必存成稀疏矩陣的格式. --- ### Example 2 再舉個例子, 假設我們想解 $$ D x = b, $$ 其中 $D$ 是個只有對角線有值的矩陣, $D_{k,k} = 1+\frac{1}{k}$, $b$ 則是個向量, $b_k=1$. $D$ 是個 $n\times n$ 矩陣, 我們有三種作法來解這問題. 先分別將三種作法所需要的矩陣造出來: ```matlab= n = 10^4; % 矩陣 size 為 nxn d0 = 1+1./(1:n)'; % 對角線自己存成一向量 D1 = diag(d0); % 造出整個矩陣 D2 = sparse(D1); % 造出稀疏矩陣 b = ones(n,1); % 等號右邊 ``` 以下我們要分別計時一下, 看三種做法速度差多少 #### Method 1 因為我們知道這問題的解是 $$ x_k = \frac{b_k}{d_{k,k}}, $$ 因此我們可以這樣做 (也就是直接把 $b$ 向量點除矩陣對角線向量): ```matlab= tic x = b./d0; toc ``` 第一次 run 程式時間會比較長, 建議多跑幾次取時間的平均. 我所得的時間為 ``` Elapsed time is 0.015570 seconds. ``` #### Method 2 我們知道解線性系統 $Dx=b$ 問題在 `matlab` 裡的指令為 `x = b\D`, 所以我們就這樣做: ```matlab= tic x = D1\b; toc ``` 結果是 ``` Elapsed time is 0.646748 seconds. ``` #### Method 3 第三種一樣是反除, 只不過我們這次是反除那個稀疏矩陣 ```matlab= tic x = D2\b; toc ``` 結果是 ``` Elapsed time is 0.015434 seconds. ``` #### Conclusion 可以看出, 直接做跟對稀疏矩陣反除效果都很好, 不過對整個大矩陣反除就慢多了. --- #### Rule: 以上這種將矩陣造出, 再 `sparse` 變成稀疏矩陣的作法純屬課堂效果, 絕對不可以用. 不過我們還是介紹兩個指令: `sparse`: 如同前面的例子, 將一個矩陣轉成稀疏矩陣 `full`: 這是反過來, 將一個稀疏矩陣變成一般矩陣 ```matlab= A = diag([2 1 2]) % 產生一個只有對角線有值的矩陣 S = sparse(A) % 將 A 變成稀疏矩陣 B = full(S) % 將 A 變回來 ``` --- ## 稀疏矩陣指令 生成稀疏矩陣有幾個重要指令: #### `speye`: sparse identity matrix `speye(m, n)`: 生成一個稀疏的 $m\times n$ 矩陣, 其中主對角線都是 $1$, 其餘所有元素都是 $0$. #### `spdiags`: sparse matrix formed from diagonals `spdiags(B,d,m,n)`: 生成一個 $m\times n$ 的稀疏矩陣, $B$ 是個 $m\times 1$ 向量, $d$ 則是要將這向量放在哪個位置, $d=0$ 表示對角線, $d=1$ 表示對角線往上移一排, $d=-1$ 則表示對角線往下移一排. 以下兩個範例: ```matlab= A1 = spdiags([1;2;3], 0, 3,3) A2 = full(A1) ``` ``` A1 = (1,1) 1 (2,2) 2 (3,3) 3 A2 = 1 0 0 0 2 0 0 0 3 ``` ```matlab= B = [2 7; 4 9; 1 3]; d = [1 -1]; S = spdiags(B, d, 4, 3) A = full(S) ``` ``` S = (2,1) 7 (1,2) 4 (3,2) 9 (2,3) 1 (4,3) 3 A = 0 4 0 7 0 1 0 9 0 0 0 3 ``` ### Exercise 1 改寫 Jacobi method 的程式, 確保他執行速度夠快. ### Exercise 2 使用 Jacobi method 來解以下問題, $n=10^5$, $$ \begin{bmatrix} -2 & 1 & & & & \\ 1 & -2 & 1 & & & \\ & 1 & \ddots & \ddots & & \\ & & \ddots & \ddots & 1 & \\ & & & 1 & -2 \end{bmatrix}_{n\times n} x = b, $$ 其中 $$ b_k = \frac{1}{(n+1)^2}\sin\left(\frac{k\pi}{n+1}\right). $$