Bill Allombert on Sun, 13 Jun 2004 19:30:26 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Computing the Frobenius form of a matrix |
Hello PARI developers, The attached script implement matrix reductions algorithms: matfrobenius(M{,flags}): compute the Frobenius form F of matrix M. If flag is 1, return [F,P] where P is the basis change. matbasischange(M,N}): Compute the basis change matrix P so that N=P*M*P^-1. Return 0 if such matrix does not exist. The algorithm use SNF computation over k[X] so work better with exact coefficients, but is generic. Using matbasischange() and matfrobenius(), it is easy to implement Jordan reduction even using POLMOD for the eigen value instead of complex approximation. I could add a function for computing elementary divisors of a matrix but it is trivial: matelemdivisors(M)=matsnf(M-'x*matid(#M),6) Before adding thoses features to PARI, I would like to hear comments about the algorithms and the terminology (how to name the functions, etc.). Cheers, Bill.
build_basischange(N,A,B)= { local(n,U); n=#N; U=B[1]^-1*A[1]; concat(vector(n,j, Mat(sum(i=1,n, subst(U[i,j],'x,N)[,i]) ))); } matbasischange(M,N)= { local(A,B,U,R,n); n=#M; A=matsnf(M-'x*matid(n),3); B=matsnf(N-'x*matid(n),3); if(A[3]!=B[3],print("warning: not semblable:",A[3]-B[3])); build_basischange(N,A,B); } addhelp(matbasischange,"matbasischange(M,N}): Compute the basis change matrix P so that N=P*M*P^-1. Return 0 if such matrix does not exist."); build_matfrobenius(n,R)= { local(P,d,s); concat(vector(#R,i, P=R[i];d=poldegree(P);s+=d; concat([matrix(d,s-d),matcompanion(P),matrix(d,n-s)])~ ))~ } matfrobenius(M,flags)= { local(n,A,B,N); n=#M; if (flags==0, A=matsnf(M-'x*matid(n),6); build_matfrobenius(n,A); , A=matsnf(M-'x*matid(n),3); N=build_matfrobenius(n,A[3]); B=matsnf(N-'x*matid(n),3); R=build_basischange(N,A,B); [N,R]) } addhelp(matfrobenius,"matfrobenius(M{,flags}): compute the Frobenius form F of matrix M. If flag is 1, return [F,P] where P is the basis change.");