// *********************************************************** // * MAGMA tool for handling commutative matrix algebras * // * * // * by Gabor Wiese * // * version of 30 March 2003 * // *********************************************************** // ********************** creation functions ******************************** intrinsic MatrixAlgebra ( L :: SeqEnum ) -> AlgMat {Creates the matrix algebra generated by the matrices in the list L.} local i,F,c,r,s,M; if #L eq 0 then return MatrixAlgebra(IntegerRing(),0); end if; F := BaseRing (L[1]); c := NumberOfColumns(L[1]); r := NumberOfRows(L[1]); if r ne c then return MatrixAlgebra(IntegerRing(),0); end if; if Type(L[1]) ne AlgMatElt then s := MatrixAlgebra (F,c); M := []; for i := 1 to #L do M[i] := s!(L[i]); end for; L := M; end if; return MatrixAlgebra < F, c | L >; end intrinsic; intrinsic MatrixAlgebra ( L :: SeqEnum, S :: Tup ) -> AlgMat {Creates the matrix algebra generated by the matrices in the list L restricted to the stable subspace S.} local M,A; M := RestrictList (L,S); A := MatrixAlgebra(M); return A; end intrinsic; intrinsic MatrixAlgebra ( A :: AlgMat, S :: Tup ) -> AlgMat {Creates the matrix algebra obtained by restricting A to the stable subspace S.} return MatrixAlgebra ( SetToSequence(Generators(A)), S); end intrinsic; intrinsic Transpose ( A :: AlgMat ) -> AlgMat {Given a matrix algebra A, creates the transposed matrix algebra.} local L,M,i,B; L := SetToSequence(Generators(A)); M := []; for i := 1 to #L do M[i] := Transpose(L[i]); end for; B := MatrixAlgebra(M); return B; end intrinsic; // ********************** Jordan form *************************************** // because the usual one crashes for 0x0 matrices _JordanForm := function ( A ) if NumberOfRows (A) ge 1 then return JordanForm(A); else return A,A,<>; end if; end function; intrinsic JordanDecomposition ( M :: Mtrx ) -> Mtrx, Mtrx {Calculates the decomposition M = D + N with D diagonalisable and N nilpotent.} local i,j,z,D,N,F,n,alg,J,C,S,d; F := BaseRing(M); n := NumberOfColumns(M); alg := MatrixAlgebra (F,n); N := alg!0; J,C,S := _JordanForm (M); z := 1; for i := 1 to #S do d := Degree (S[i][1]); for j := 1 to S[i][2] - 1 do N := N + MatrixUnit (alg, z+d-1,z+d); z := z + d; end for; z := z + d; end for; N := C^(-1) * N * C; D := M - N; return D,N; end intrinsic; // ********************** local factors ************************************ intrinsic IdealTorsion ( m :: AlgMat ) -> ModTupFld {Given an ideal m in a matrix algebra of degree d over a field F, calculate the sub vector space of F^d consisting of those elements killed by every element of m.} local g,i,Vi; if Degree(m) eq 0 then return VectorSpace(GF(2),0); end if; g := SetToSequence(Generators(m)); Vi := VectorSpace(CoefficientRing(m),Degree(m)); for i := 1 to #g do Vi := Vi meet (Kernel (g[i])); end for; return Vi; end intrinsic; intrinsic Idempotents ( D :: Tup ) -> SeqEnum, Tup {Given a decomposition D, calculate a list of the corresponding idempotents as matrices.} local i,L,n,F,j,z,C1,C,alg,V,W; n := NumberOfColumns (D[1][1]); F := BaseRing(D[1][1]); alg := MatrixAlgebra (F,n); C := []; L := []; z := 1; for i := 1 to #D do L[i] := alg!0; for j := 1 to NumberOfRows(D[i][1]) do C[z] := D[i][1][j]; L[i] := L[i] + MatrixUnit (alg,z,z); z := z + 1; end for; end for; V := VectorSpaceWithBasis(C); W := Generic(V); C := alg!(ExtendBasis(V,W)); C1 := C^(-1); for i := 1 to #D do L[i] := C1*L[i]*C; end for; return L,; end intrinsic; intrinsic CommonLowerTriangular ( A :: AlgMat ) -> Tup,Tup {See the documentation.} local max,n,S,C,d,L,r,i,V,b,m,D; if Dimension(A) eq 0 then return <>,; end if; d := Degree(A); C := A!0; // the base change matrix to be determined L := []; // store the dimensions of the primary spaces in here r := 1; // row number of matrix C currently treated // get maximal ideals max := MaximalIdeals(A); // for each maximal ideal m calculate the power m^i st m^i = m^(i+1) // and a basis of V[ m^i ], which becomes part of the basis to // be calculated for i := 1 to #max do n := max[i]; V := IdealTorsion (n); b := Basis(V); m := n * max[i]; while m ne n do W := IdealTorsion(m); b := ExtendBasis (b, W); n := m; m := m * max[i]; end while; L[i] := #b; for j := 1 to #b do C[r] := b[j]; r := r + 1; end for; end for; // calculate our form of the decomposition S := <>; D := C^(-1); r := 1; for i := 1 to #max do Append (~S, ); r := r + L[i]; end for; return S,; end intrinsic; intrinsic LocalDecomposition ( A :: AlgMat ) -> Tup,Tup {Same as CommonLowerTriangular.} return CommonLowerTriangular (A); end intrinsic; // ************* generalized eigenspaces ******************************************** intrinsic CommonGeneralizedEigenspaces ( A :: AlgMat ) -> Tup {See the documentation.} local max, alg, d, W, C, L, r, i, n, V, b, j, S; if Dimension(A) eq 0 then return <>; end if; alg := Generic(A); d := Degree(A); W := VectorSpace(CoefficientRing(A),d); C := []; L := []; // store the dimensions of the primary spaces in here r := 1; // row number of matrix C currently treated // get maximal ideals max := MaximalIdeals(A); // for each maximal ideal m calculate the power m^i st m^i = m^(i+1) // and a basis of V[ m^i ], which becomes part of the basis to // be calculated for i := 1 to #max do n := max[i]; V := IdealTorsion (n); b := Basis(V); L[i] := #b; for j := 1 to #b do C[r] := W!(b[j]); r := r + 1; end for; end for; // take some complement to the direct sum of the gen eigenspaces V := VectorSpaceWithBasis(C); W := Generic(V); C := alg!(ExtendBasis(V,W)); // calculate our form of the decomposition S := <>; D := C^(-1); r := 1; for i := 1 to #max do Append (~S, ); r := r + L[i]; end for; return S; end intrinsic; // ************************* eigenspaces ******************************************** // B : set of lin. indep. vectors of n-dim v.s. // calculates base change matrices C,D such that the restriction of // an n x n matrix A to the subspace generated by B can be // calculated as C A D. _restrict := function (B) local n,F,C,M,d,V; d := #B; V := VectorSpaceWithBasis(B); C := Matrix(B); F := BaseField(V); n := NumberOfColumns(B[1]); B := ExtendBasis(B,KSpace(F,n)); D := Matrix(B); D := SubmatrixRange(D^(-1),1,1,n,d); return C,D; end function; intrinsic Eigenspaces ( M :: Mtrx ) -> Tup {Calculates the eigenspaces of the matrix M.} local i,k,l,F,S,T,B,L,y,z,n,J,f; n := NumberOfRows(M); F := BaseRing(M); J,T,S := _JordanForm(M); B := <>; i := 1; l := 1; while (i le #S) do f := S[i][1]; if (Degree (f) eq 1) then L := []; while (i le #S) and (f eq S[i][1]) do L := Append(L,T[l + S[i][2] - 1]); l := l + S[i][2]; i := i + 1; end while; y,z := _restrict(L); B := Append(B,); else l := l + Degree(f) * S[i][2]; i := i + 1; end if; end while; return B; end intrinsic; // Given a list of commuting matrices, return the common eigenspaces. _CommonEigenspacesList := function (L) local T,S,S1,i,j,k; if #L eq 0 then return <>; end if; S := Eigenspaces(L[1]); for i := 2 to #L do S1 := <>; for j := 1 to #S do T := Eigenspaces(S[j][1] * L[i] * S[j][2]); for k := 1 to #T do S1 := Append(S1, < T[k][1] * S[j][1], S[j][2] * T[k][2] >); end for; end for; S := S1; end for; return S; end function; intrinsic CommonEigenspaces ( A :: AlgMat ) -> Tup {Given a commutative algebra, return the common eigenspaces for all elements.} return _CommonEigenspacesList(SetToSequence(Generators(A))); end intrinsic; // ************************ Gorenstein property ***************************** _localGorensteinDefect := function (A) local m,n,an; m := MaximalIdeals(A); an := LeftAnnihilator(A,m[1]); n := Dimension (quo ); return ((Dimension(an)) div n) - 1; end function; intrinsic GorensteinDefect ( A :: AlgMat ) -> RngIntElt {Returns the Gorenstein defect of the commutative algebra, that is the maximum of the Gorenstein defect for the local algebra. This is the number of module generators of the annihilator of the maximal ideal minus one.} local max,i,S,n; if Dimension(A) eq 0 then return 0; end if; max := -1; S := LocalDecomposition(A); for i := 1 to #S do n := _localGorensteinDefect (Algebra(MatrixAlgebra(A,S[i]))); if n gt max then max := n; end if; end for; return max; end intrinsic; intrinsic IsGorenstein ( M :: AlgMat ) -> BoolElt {} return (GorensteinDefect(M) eq 0); end intrinsic; // ************************ unipotency order ****************************** intrinsic UPO ( A :: AlgMat ) -> RngIntElt {Computes the unipotency order of the matrix algebra A.} local L,n,nl,m,d; if Dimension(A) eq 0 then return 0; end if; max := MaximalIdeals(A); n := 0; for i := 1 to #max do nl := 0; m := max[i]; d := Dimension(A); while d gt Dimension(m) do nl := nl + 1; d := Dimension(m); m := m * max[i]; end while; if nl gt n then n := nl; end if; end for; return n; end intrinsic; // ************************ other functions ******************************** intrinsic RestrictMatrix ( M :: Mtrx, P :: Tup ) -> Mtrx {Restricts the matrix M to the stable subspace P.} return P[1] * M * P[2]; end intrinsic; intrinsic RestrictList ( L :: SeqEnum, P :: Tup ) -> SeqEnum {Restricts all matrices in the list L to the stable subspace P.} local i,M; M := []; for i := 1 to #L do M := Append(M,RestrictMatrix(L[i],P)); end for; return M; end intrinsic; intrinsic IsLocalAlgebra ( A :: AlgMat ) -> BoolElt {Returns whether the matrix algebra A is local.} local m; m := MaximalIdeals(A); return (#m eq 1); end intrinsic; intrinsic CommonResidueField ( A :: AlgMat ) -> Any {Returns the field generated by the residue fields of the matrix algebra A.} local i,d,L,max; d := Dimension(A); if d eq 0 then return BaseRing(A); end if; max := MaximalIdeals(A); L := []; for i := 1 to #max do L[i] := d - Dimension(max[i]); end for; return GF(Characteristic(A), Lcm(L)); end intrinsic; intrinsic ChangeRingList ( L :: SeqEnum , F :: Rng ) -> SeqEnum {Changes the coefficient ring of all the matrices in the list L to the ring F.} local i,B; B := []; for i := 1 to #L do B := Append (B, ChangeRing(L[i],F)); end for; return B; end intrinsic;