Overview of the LinearAlgebra:-Generic Package
Description
Notes on the definition of the domains
Examples
The LinearAlgebra:-Generic package provides generic implementations of algorithms for linear algebra over fields, Euclidean domains, integral domains and rings.
We show below an example of how to use the MatrixInverse operation in the package to invert a Matrix A over a field. The calling sequence is
MatrixInverse[F](A);
The indexed parameter F is called the domain of computation. For the matrix inverse operation, it must define the operations of a field, namely, addition, subtraction, multiplication and division of elements of F. It must also define the 0 and 1 of the field and a boolean procedure for testing if two elements are equal. To achieve this, the parameter F must be a table or module with the following procedures and constants:
F[`0`] : a constant, the additive identity of F
F[`1`] : a constant, the multiplicative identity of F
F[`+`] : a procedure for adding zero or more elements of F
F[`-`] : a procedure for negating or subtracting elements of F
F[`*`] : a procedure for multiplying two elements of F
F[`/`] : a procedure for dividing two elements of F
F[`=`] : a boolean procedure for comparing two elements of F
Implementation of F for Q, the field of rational numbers, is fairly straightforward:
F[`0`] := 0:
F[`1`] := 1:
F[`=`] := (x,y)->evalb( x=y ):
F[`+`] := `+`:
F[`-`] := `-`:
F[`*`] := `*`:
F[`/`] := `/`:
To use F we do
with(LinearAlgebra:-Generic):
A := Matrix([[1,2,3],[2,1,2],[3,2,1]]);
A≔123212321
−38121812−1121812−38
The code for MatrixInverse is generic. It can be used to invert a matrix over any field, we just need to define the required operations. Let's do it for a finite field. We will represent elements of GF(27) as polynomials in z over the integers modulo 3. That is, we represent elements of the field as polynomials modulo m(z), an irreducible polynomial of degree 3 in z. We will assume that elements of the field are reduced, i.e., have degree less than 3.
p := 3;
p≔3
m := z^3+2*z+1;
m≔z3+2⁢z+1
GF27[`0`] := 0:
GF27[`1`] := 1:
GF27[`=`] := `=`:
GF27[`+`] := ()->modp(`+`(args),p):
GF27[`-`] := (a,b)->`if`(nargs=1,modp(-a,p),modp(a-b,p)):
GF27[`*`] := (a,b)->modp(Rem(a*b,m,z),p):
GF27[`/`] := proc(a,b) local i; if b=0 then error "division by zero"; end if; Gcdex(b,m,z,'i') mod p; Rem(a*i,m,z) mod p; end proc:
A := Matrix([[1,z,z^2],[z,1,z],[z^2,z,1]]);
A≔1zz2z1zz2z1
B := MatrixInverse[GF27](A);
B≔z2⁢z202⁢z22⁢z+22⁢z202⁢z2z
MatrixMatrixMultiply[GF27](A,B);
100010001
In the above example we demonstrated the use of the MatrixMatrixMultiply routine to verify that the computed inverse really is the inverse.
List of LinearAlgebra:-Generic Package Commands
BareissAlgorithm
BerkowitzAlgorithm
CharacteristicPolynomial
Determinant
GaussianElimination
GenericCheck
HermiteForm
HessenbergAlgorithm
HessenbergForm
LinearSolve
MatrixAdd
MatrixInverse
MatrixMatrixMultiply
MatrixVectorMultiply
MinorExpansion
NullSpace
ReducedRowEchelonForm
RREF
SmithForm
StronglyConnectedBlocks
VectorAdd
The package exports algorithms and commands for linear algebra which are parameterized by the ring in which the matrix entries lie. The package also exports algorithms. For example, the Bareiss fraction-free algorithm is well known. It is an algorithm which computes the determinant of a matrix over any integral domain D. It assumes exact division and does O(n^3) operations from D. The Berkowitz algorithm is division free and takes O(n^4) operations. The output Matrix B over D satisfies certain properties, in particular, B[i,i] is the determinant (up to sign) of the principal i x i minor. So one can compute the determinant using this algorithm by doing
Determinant[D](A,method=BareissAlgorithm);
and also, one can compute the Matrix B by doing
BareissAlgorithm[D](A);
The domain may be a Maple table or a Maple module.
A common mistake is to forget to specify the domain of computation. If you do this you will get an error. For example:
MatrixInverse(A); # should be MatrixInverse[GF27](A);
Error, (in LinearAlgebra:-Generic:-GenericCheck) LinearAlgebra:-Generic:-MatrixInverse is not indexed by a domain
Another common error is to omit one of the operations in the domain. The package checks that the required operations are defined and of type procedure (or constant). Here is an example of an error
HermiteForm[GF27](A);
Error, (in LinearAlgebra:-Generic:-GenericCheck) missing operation: Gcdex
The required operations for the domain of computation F for each algorithm are specified in the help page for that algorithm. The package been designed to keep this list minimal. Note, even if the algorithm requires a field, it may not use all of the basic operations from a field, for example, the algorithm for Gaussian elimination does not use addition. Nevertheless, addition is a required operation.
The additive identity 0 may or may not be unique. The algorithms will always use the following to test for zero:
if F[`=`](x,F[`0`]) then ... else ... end if;
Other elements of a ring, including 1, do not need a unique representation.
Suppose we want to compute the determinant of a matrix of integers modulo a composite integer n using the Berkowitz algorithm. We need to first define the ring of integers modulo n as a domain.
with⁡LinearAlgebra:-Generic:
R ≔ module_export⁡`0`,`1`,`=`,`+`,`-`,`*`;`0` ≔ 0;`1` ≔ 1;`=` ≔ x,y→evalb⁡x=y;`+` ≔ →modp⁡:-`+`⁡args,n;`*` ≔ a,b→modp⁡a*b,n;`-` ≔ a,b→`if`⁡nargs=1,modp⁡−a,n,modp⁡a − b,nend module
R ≔ moduleexport0,1,`=`,`+`,`-`,`*`;end module
n≔6:
R`*`⁡2,4
2
A≔Matrix⁡2,3,4,5,3,4,1,2,4,1,1,5,3,1,5,4:
DeterminantR⁡A,method=BerkowitzAlgorithm
3
A more efficient algorithm is the Bareiss fraction free algorithm. It assumes only exact division and computes the determinant in O(n^3) operations in R. Hence it is valid for the integers. We illustrate this time using a table Z of operations for the ring.
Z`0`,Z`1`≔0,1
Z0,Z1≔0,1
Z`+`,Z`-`,Z`*`,Z`=`≔`+`,`-`,`*`,`=`
ZDivide≔x,y↦evalb⁡irem⁡x,y,args3..nargs=0:
DeterminantZ⁡A,method=BareissAlgorithm
195
BareissAlgorithmZ⁡A
23450−1−10−1100−43−50000195
Given a Matrix A of algebraic numbers which were input using Maple's RootOf notation, suppose we want to compute the nullspace of A. We will convert to a univariate polynomial representation for the computation to obtain greater efficiency.
ANNullSpace := proc(AA::Matrix,rof::RootOf) local M,z,R,m,n,i,j,A,F,B; M := subs(_Z=z,op(1,rof)); R := polynom(rational,z); if not type(M,R) then error "invalid RootOf"; end if; m,n := LinearAlgebra:-Dimensions(AA); A := Matrix(m,n); for i to m do for j to n do A[i,j] := subs(rof=z,AA[i,j]); if not type(A[i,j],R) then error "invalid matrix entries"; end if; A[i,j] := rem(A[i,j],M,z); end do; end do; F[`0`] := 0; F[`1`] := 1; F[`=`] := `=`; F[`+`] := `+`; F[`-`] := `-`; F[`*`] := (a,b)->rem(a*b,M,z); F[`/`] := proc(a,b) local i; if b=0 then error "division by zero"; elif gcdex(b,M,z,'i')<>1 then error "invalid RootOf"; else rem(a*i,M,z); end if; end proc: B := LinearAlgebra:-Generic:-NullSpace[F](A); subs( z=rof, B ); end proc:
a≔RootOf⁡z3−2
a≔RootOf⁡_Z3−2
M≔Matrix⁡1,a,a2,a+a2,a+a2,3,a2,a,1
M≔1RootOf⁡_Z3−2RootOf⁡_Z3−22RootOf⁡_Z3−22+RootOf⁡_Z3−2RootOf⁡_Z3−22+RootOf⁡_Z3−23RootOf⁡_Z3−22RootOf⁡_Z3−21
B≔ANNullSpace⁡M,a
B≔1−RootOf⁡_Z3−222−RootOf⁡_Z3−21
For the last example, we compute the nullspace of a matrix of complex rationals.
C`0`≔0:
C`1`≔1:
C`=`≔`=`:
C`+`≔`+`:
C`-`≔`-`:
C`*`≔`*`:
C`/`≔`/`:
A≔Matrix⁡1,I,−I,3,−1+I,−4⁢I,I,1−I,2
A≔1I−I3−1+I−4⁢II1−I2
B≔NullSpaceC⁡A
B≔−15+7⁢I5−25−I51
To check that the answer is correct we need to verify that A.B[1] = 0. We will write a procedure to do this. This illustrates how the procedures in LinearAlgebra[Generic] are coded. The GenericCheck procedure checks that the procedure was called with a domain (a table or module) and that it has the required values/exports.
MatrixTimesVector := proc(A::Matrix,v::Vector) local D,n,p,m,C,i,k; D := GenericCheck( procname, [`0`,`+`,`*`] ); n,p := op(1,A); m := op(1,v); if p<>m then error "incompatible dimensions"; end if; C := Vector(n,'fill'=D[`0`]); for i to n do for k to p do C[i] := D[`+`](C[i],D[`*`](A[i,k],v[k])); end do; end do; C; end proc:
MatrixTimesVectorC⁡A,B1
000
See Also
Download Help Document