Gonzalo Tornaria on Tue, 20 May 2003 12:00:08 -0500 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Programs: Sparse matrix multiplication // charpoly |
Here are the GP programs; they don't check the dimensions of the matrices in any way, and in fact there's no way to know the dimensions of a "studied matrix" (only one dimension is known). The functions "matrix_sparseleft" and "matrix_sparseright" study any matrix for multiplication on the left/right. The functions "sparseleft_mul" and "sparseright_mul", multiply studied matrices by regular ones. One could define multiplication like: mul_l(m1,m2) = sparseleft_mul(matrix_sparseleft(m1), m2); mul_r(m1,m2) = sparseright_mul(m1, matrix_sparseright(m2)); Lastly, the function "matrix_sparsecharpoly" computes the charpoly of (any) matrix using this. It is correct in any case, but it should be a factor worse than the PARI function for dense matrices. I believe the factor is constant, and not too big (going to 1 as the size of the matrix goes to infinity, and in practice seems to be less than 1.10 for 100x100). Note that I have "inlined" the function "sparseright_mul", and replaced the matrix that is computed in each iteration by a vector of vectors (the columns). The random sparse matrices I'm constructing are given by DENSE(n)=matrix(n,n, i,j, (random(10000)+1)); SPARSE(n)=matrix(n,n, i,j, (random(10000)+1)*random(n)<4)); SPARSE1(n)=matrix(n,n, i,j, random(n)<4)); Gonzalo /*******************************************************************************/ /* Studies a matrix to improve multiplication on the left */ matrix_sparseleft(m) = { local(n, k, row); n=matsize(m)[1]; k=matsize(m)[2]; vector(n, i, row=[]; for(j=1,k, if(m[i,j]!=0, row=concat(row,[[j,m[i,j]]])) ); row ) } /* Studies a matrix to improve multiplication on the right */ matrix_sparseright(m) = { local(n, k, col); n=matsize(m)[2]; k=matsize(m)[1]; vector(n, i, col=[]; for(j=1,k, if(m[j,i]!=0, col=concat(col,[[j,m[j,i]]])) ); col ) } /* Multiplies a "sparseleft" by a matrix */ sparseleft_mul(sl, m) = { local(n, k, v0, v); n=length(sl); k=matsize(m)[2]; v0=vector(k,i,0); v=vector(n,i, sum(j=1,length(sl[i]), m[sl[i][j][1],]*sl[i][j][2], v0)); matrix(n,k, i,j, v[i][j]) } /* Multiplies a matrix by a "sparseright" */ sparseright_mul(m, sr) = { local(n, k, v0, v); n=length(sr); k=matsize(m)[1]; v0=vector(k,i,0)~; v=vector(n,i, sum(j=1,length(sr[i]), m[,sr[i][j][1]]*sr[i][j][2], v0)); matrix(k,n, i,j, v[j][i]) } /* Computes the characteristic polynomial of a matrix */ matrix_sparsecharpoly(m) = { local(n, v0, Fk, pk, sr, sri); n=matsize(m)[1]; v0=vector(n,i,0); Fk=vector(n,i,v0); pk=1; /* k=0 */ sr=matrix_sparseright(m); Pol(concat([1], vector(n,k, /* Fk = Fk + pk */ for(i=1,n, Fk[i][i]+=pk); /* Fk = Fk * m */ Fk=vector(n,i, sri=sr[i]; sum(j=1, length(sri), Fk[sri[j][1]]*sri[j][2], v0) ); /* pk = -trace(Fk)/k */ pk=-sum(i=1,n,Fk[i][i])/k; ))); } /*******************************************************************************/ -- GM/CS/S d? a-- C++(+++) UL+++(++++) P++>+++ L+++>++++ E--- W-(+) N+(++) w--- O M-(--) V-(--) PGP(--) b++(+++) G++ e>++++ ... A mathematician is a machine for converting coffee into theorems.