特征多项式


13

方阵A特征多项式定义为多项式p A(x)= detI x- A),其中I单位矩阵,det行列式。请注意,此定义始终为我们提供单项多项式,以使解决方案唯一。

解决此难题的任务是为整数矩阵计算特征多项式的系数,为此,您可以使用内置函数,但是不建议使用。

规则

  • 输入是任何方便格式的NxN(N≥1)个整数矩阵
  • 您的程序/函数将以升序或降序输出/返回系数(请指定哪个)
  • 对系数进行归一化,使得x N的系数为1(请参见测试用例)
  • 您不需要处理无效的输入

测试用例

系数以降序给出(即x N,x N-1,...,x 2,x,1):

[0] -> [1 0]
[1] -> [1 -1]
[1 1; 0 1] -> [1 -2 1]
[80 80; 57 71] -> [1 -151 1120] 
[1 2 0; 2 -3 5; 0 1 1] -> [1 1 -14 12]
[4 2 1 3; 4 -3 9 0; -1 1 0 3; 20 -4 5 20] -> [1 -21 -83 559 -1987]
[0 5 0 12 -3 -6; 6 3 7 16 4 2; 4 0 5 1 13 -2; 12 10 12 -2 1 -6; 16 13 12 -4 7 10; 6 17 0 3 3 -1] -> [1 -12 -484 3249 -7065 -836601 -44200]
[1 0 0 1 0 0 0; 1 1 0 0 1 0 1; 1 1 0 1 1 0 0; 1 1 0 1 1 0 0; 1 1 0 1 1 1 1; 1 1 1 0 1 1 1; 0 1 0 0 0 0 1] -> [1 -6 10 -6 3 -2 0 0]



1
我可以输出多项式吗?
alephalpha

1
@alephalpha:好的。
ბიმო

[ 1.00000000e+00 -1.51000000e+02 1.12000000e+03]例如,我可以输出为吗?
Xcoder先生17年

Answers:



9

八度16 4字节

@BruteForce刚刚告诉我,我在以前的解决方案中使用的功能之一实际上可以完成全部工作:

poly

在线尝试!

16字节:此解决方案计算输入矩阵的特征值,然后从给定的根开始构建多项式。

@(x)poly(eig(x))

但是当然也很无聊

charpoly

symbolic在Octave中需要一个类型矩阵,但在MATLAB中可以使用通常的矩阵。)

在线尝试!



6

R,53个字节

function(m){for(i in eigen(m)$va)T=c(0,T)-c(T,0)*i
T}

在线尝试!

以递增顺序返回系数;即a_0, a_1, a_2, ..., a_n

通过找到矩阵的特征值来计算多项式。

R + pramma,16个字节

pracma::charpoly

pracma 是R的“ PRACICAL MAth”库,具有许多便捷功能。


5

Mathematica,22个字节

Det[MatrixExp[0#]x-#]&

来自alephalpha的-7个
字节来自Misha Lavrov的-3个字节

在线尝试!

而且当然...

Mathematica,29个字节

#~CharacteristicPolynomial~x&

在线尝试!

两个答案都输出一个多项式


4

Haskell243223222字节

s=sum
(&)=zip
z=zipWith
a#b=[[s$z(*)x y|y<-foldr(z(:))([]<$b)b]|x<-a]
f a|let c=z pure[1..]a;g(u,d)k|m<-[z(+)a b|(a,b)<-a#u&[[s[d|x==y]|y<-c]|x<-c]]=(m,-s[s[b|(n,b)<-c&a,n==m]|(a,m)<-a#m&c]`div`k)=snd<$>scanl g(0<$c<$c,1)c

在线尝试!

感谢@ØrjanJohansen帮助我打高尔夫球!

说明

这使用Faddeev–LeVerrier算法来计算系数。这是带有更多详细名称的非公开版本:

-- Transpose a matrix/list
transpose b = foldr (zipWith(:)) (replicate (length b) []) b

-- Matrix-matrix multiplication
(#) :: [[Int]] -> [[Int]] -> [[Int]]
a # b = [[sum $ zipWith (*) x y | y <- transpose b]|x<-a]


-- Faddeev-LeVerrier algorithm
faddeevLeVerrier :: [[Int]] -> [Int]
faddeevLeVerrier a = snd <$> scanl go (zero,1) [1..n]
  where n = length a
        zero = replicate n (replicate n 0)
        trace m = sum [sum [b|(n,b)<-zip [1..n] a,n==m]|(m,a)<-zip [1..n] m]
        diag d = [[sum[d|x==y]|y<-[1..n]]|x<-[1..n]]
        add as bs = [[x+y | (x,y) <- zip a b] | (b,a) <- zip as bs]
        go (u,d) k = (m, -trace (a#m) `div` k)
          where m = add (diag d) (a#u)

注意:我直接从此解决方案


1
这里还有一个字节:c=z pure[1..]a
与Orjan约翰森

该死的,那很聪明!
ბიმო

谢谢!我刚刚发现f a|let c=z pure[0..]a;g(u,d)k|m<-[z(+)a b|(a,b)<-a#u&[[s[d|x==y]|y<-c]|x<-c]]=(m,-s[a#m!!n!!n|n<-c]`div`(k+1))=snd<$>scanl g(0<$c<$c,1)c,类似的东西也应该适用于另一个。
与Orjan约翰森



1

CJam(48字节)

{[1\:A_,{1$_,,.=1b\~/A@zf{\f.*1fb}1$Aff*..+}/;]}

在线测试套件

解剖

这与我对整数矩阵行列式的回答非常相似。它有一些调整,因为符号不同,并且因为我们想保留所有系数,而不仅仅是最后一个。

{[              e# Start a block which will return an array
  1\            e#   Push the leading coefficient under the input
  :A            e#   Store the input matrix in A
  _,            e#   Take the length of a copy
  {             e#     for i = 0 to n-1
                e#       Stack: ... AM_{i+1} i
    1$_,,.=1b   e#       Calculate tr(AM_{i+1})
    \~/         e#       Divide by -(i+1)
    A@          e#       Push a copy of A, bring AM_{i+1} to the top
    zf{\f.*1fb} e#       Matrix multiplication
    1$          e#       Get a copy of the coefficient
    Aff*        e#       Multiply by A
    ..+         e#       Matrix addition
  }/
  ;             e#   Pop AM_{n+1} (which incidentally is 0)
]}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.