起因
- 前一阵子(几个月前)在学习根轨迹方程,想要写出画根轨迹的代码,却无论如何都画不出来.因为教材上的根轨迹的法则是用来直到人类的,而不是直到机器画的.但是matlab却可以画根轨迹.
- 前一阵子,看到一篇关于分布式3D无人机编队的论文中用到了SVD,半定规划的问题,其中求SVD需要用到求特征值的数值解法.无奈的是,线性代数当初根本就没有学懂,现在都还给老师了.
- 前一阵子要学图像处理,小波变换,但是我不想用matlab,自己的代码能力又没那么强,只能写出dct,并参照oiwiki的fft算法和蝴蝶变换翻译成javascript.后来有作业,要用matlab,还好老师推荐了GNU octave(于是我也画了根轨迹:>).
octave的rlocus,之后猛然意识到,它是直接求根然后连线的.于是乎,我就在百度和必应上搜高阶方程的数值解法
,结果硬是没搜到,甚至找到一篇cmu的课件,可他讲的是人如何解三阶或者四届方程,然后了解到高于四阶的一般方程无法通过各项系数无法通过简单的一些运算得到解.于是最终还是打开了roots.m文件(之前eig函数好像使用c++实现的,有些复杂,各种依赖好像).
文件
点击,可以自己去看
octave 是开源的.
算法
- 将多项式按降幂排列,移除头部的0: P ( x ) = a n x n + a n − 1 x n − 1 + a n − 2 x n − 2 + ⋯ P(x)=a_nx^n+a_{n-1}x^{n-1}+a_{n-2}x^{n-2}+\cdots P(x)=anxn+an−1xn−1+an−2xn−2+⋯.
- 将多项式除以最低项,即将最后一项化为常数: P ( x ) = a n x n − l + a n − 1 x n − 1 − l + a n − 2 x n − 2 − l + ⋯ + a l P(x)=a_nx^{n-l}+a_{n-1}x^{n-1-l}+a_{n-2}x^{n-2-l}+\cdots+a_l P(x)=anxn−l+an−1xn−1−l+an−2xn−2−l+⋯+al.
- 取出各项的系数,不存在时记为0.
- 构造矩阵 [ − a n − 1 / a n − a n − 2 / a n − a n − 3 / a n ⋯ 1 0 0 ⋯ 0 1 0 ⋯ 0 0 1 ⋯ 0 0 0 ⋯ ⋮ ⋮ ⋮ ⋱ ] \begin{bmatrix}-a_{n-1}/a_n&-a_{n-2}/a_n&-a_{n-3}/a_n&\cdots\\1&0&0&\cdots\\0&1&0&\cdots\\0&0&1&\cdots\\0&0&0&\cdots\\\vdots&\vdots&\vdots&\ddots\end{bmatrix} ⎣⎢⎢⎢⎢⎢⎢⎢⎡−an−1/an1000⋮−an−2/an0100⋮−an−3/an0010⋮⋯⋯⋯⋯⋯⋱⎦⎥⎥⎥⎥⎥⎥⎥⎤
- 求解矩阵的所有特征值.
- 所求得的特征值就是所要求的多项式的根.
简单说明
- 首先我不会证明.
- 学过线性代数的人都知道(:p),求解矩阵的特征值可以通过解特征方程( det ( A − λ E ) = 0 \det (A-\lambda E)=0 det(A−λE)=0)的方法,解出来的根就是矩阵A的特征值.
- 这里通过构造一个特征方程为以所给参数为多项式的矩阵,并通过数值方法求解矩阵特征值的做法来反求特征方程的根.
以下通过归纳法证明所构造的矩阵的特征方程是所给的多项式.
- 只考虑前两项则
A − x E = [ − a n − 1 / a n − x ] A-x E=\begin{bmatrix}-a_{n-1}/a_n-x\end{bmatrix} A−xE=[−an−1/an−x]
则,A的特征多项式为 det [ − a n − 1 / a 1 − x ] = 0 \det\begin{bmatrix}-a_{n-1}/a_1-x\end{bmatrix}=0 det[−an−1/a1−x]=0,即 a n x + a n − 1 = 0 a_{n}x+a_{n-1}=0 anx+an−1=0. - 设只考虑前
k
k
k项的时候,矩阵的特征方程为
a
n
−
1
x
n
−
1
+
a
n
−
2
x
n
−
2
+
a
n
−
3
x
n
−
3
+
⋯
+
a
n
−
k
+
1
x
n
−
k
+
1
a_{n-1}x^{n-1}+a_{n-2}x^{n-2}+a_{n-3}x^{n-3}+\cdots+a_{n-k+1}x^{n-k+1}
an−1xn−1+an−2xn−2+an−3xn−3+⋯+an−k+1xn−k+1,当考虑第
k
+
1
k+1
k+1项的时候,矩阵具有如下形式.
[ − a n − 1 / a n − x − a n − 2 / a n ⋯ − a n − k + 1 / a n − a n − k / a n 1 − x ⋯ 0 0 0 1 ⋯ 0 0 ⋮ ⋮ ⋱ 0 0 0 0 ⋯ 1 − x ] \left[\begin{array}{cccc|c}-a_{n-1}/a_n-x&-a_{n-2}/a_n&\cdots&-a_{n-k+1}/a_n&-a_{n-k}/a_n\\1&-x&\cdots&0&0\\0&1&\cdots&0&0\\\vdots&\vdots&\ddots&0&0\\\hline\\0&0&\cdots&1&-x\end{array}\right] ⎣⎢⎢⎢⎢⎢⎢⎢⎡−an−1/an−x10⋮0−an−2/an−x1⋮0⋯⋯⋯⋱⋯−an−k+1/an0001−an−k/an000−x⎦⎥⎥⎥⎥⎥⎥⎥⎤
由行列式的计算方法知当增加新的一行和新的一列时,原行列式中的每一项需要乘 − x -x −x,而新增加的 − a n − k / a n -a_{n-k}/a_n −an−k/an所得的系数的正负号与原行列式的阶次相关且与其它各项的正负保持相同.
结果
可是我不知道如何求矩阵的特征值.计算方法里讲到的Jacobi方法当时是用来解是对称矩阵的特征值的.对于非对称的的实矩阵,其特征值为复数.我还不会:<