How to multiply a matrix by a Kronecker product more or less efficiently
Suppose you would like to calculate the product
To calculate Y = (A⊗ B)U', we use the fact that (A⊗ B)=(A⊗ Im)(In⊗ B), and compute (A⊗ Im)Û and (In⊗ B)U' separately:
Û = B %*% matrix(t(U), m) # m x (n . k)
Ŭ = A %*% matrix(t(Û), n) # n x (k . m)
Y = matrix(t(Ŭ), k) # k x (m . n)
Ŭ = A %*% matrix(t(Û), n) # n x (k . m)
Y = matrix(t(Ŭ), k) # k x (m . n)
That's it. The following simple and non-optimized function implements this:
function(A, B, U)
{
k = nrow(U)
if(missing(A)) A = diag(ncol(U)%/%ncol(B))
if(missing(B)) B = diag(ncol(U)%/%ncol(A))
U = B %*% matrix(t(U), ncol(B))
U = A %*% matrix(t(U), ncol(A))
U = matrix(t(U), k)
U
}
{
k = nrow(U)
if(missing(A)) A = diag(ncol(U)%/%ncol(B))
if(missing(B)) B = diag(ncol(U)%/%ncol(A))
U = B %*% matrix(t(U), ncol(B))
U = A %*% matrix(t(U), ncol(A))
U = matrix(t(U), k)
U
}
It accepts A and B, one of which may be missing (in which case it is taken equal to the identity matrix of suitable order), and U. It returns Y'.
The following routine generalizes this to the product (A1 &otimes A2 ⊗ ··· ⊗ An)U'. It is used as kronecker.U(A1,A2, …, An, t(U)). It is not time efficient because the implementation is recursive.
function(A, B, U)
{
kronecker.U <- function(...) { M = list(...); if(length(M)==2){ return(M[[1]] %*% M[[2]]); } else{ n = length(M); E = M[[n]]; A = M[[n-1]]; B = M[1:(n-2)]; nce = ncol(E); nca = ncol(A); nra = nrow(A); ncb = prod(sapply(B,ncol)); if(ncb*nca!=nrow(E)) stop("non-conformable arguments"); V = matrix( t(A%*%matrix(E, nca)), ncb); cl = match.call(); cl[[n+1]] = V; cl[2:(n-1)] = B; cl[[n]] = NULL; W = eval(cl); Z = matrix(t(matrix(W,,nra)),,nce); return(Z); } }
0 Comments:
Post a Comment
<< Home