Creating a block diagonal matrix

User ForumCreating a block diagonal matrix
Abdulbaki asked 2 years ago

Dear Gaussians

I have a-ten equations with different sets of X  by 9700 x 22 as covariates and Xs are not at all the same in each equation. I run SUR model in Gauss and would like to compute log-L value and some other values manually for the system. Does anyone know how to create a block diagonal matrix of ( (10*9700) x (10*22) ) with a single command, like a=block(x,z) in SAS with proc iml? I know a long way how to come up with such matrix, but would like to have it with a short way.


2 Answers
caj1024 answered 2 years ago

If you can put your matrices into a 3 dimensional array, then this will work. I don't know if it is shorter than your code, but if you add this procedure to your user library you will be able to use it in any code with just the one-line call.

rndseed 22353;

//Create random array for example
num_mats = 4;
r = 2;
c = 3;
my_array = areshape(rndn(num_mats*r*c, 1), num_mats|r|c);

//Convert array to blockdiagonal matrix

proc (1) = makeBlockDiag(local_array);
   local out, start_r, start_c, num_rows, num_cols, orders;
   //assuming 3-D array
   orders = getOrders(local_array);
   num_rows = orders[2];
   num_cols = orders[3];

   //pre-allocate output matrix
   out = zeros(num_rows * orders[1], num_cols * orders[1]);
   //fill in the blocks
   for i(0, orders[1]-1, 1);
      start_r = i*num_rows+1;
      start_c = i*num_cols+1;
      out[start_r:start_r+num_rows-1,start_c:start_c+num_cols-1] = local_array[i+1,.,.];
Abdulbaki answered 2 years ago

Thanks a lot. My procedure was naïve as

blockXX= x1~zeros(ntot,9*kxa)                   || zeros(ntot,kxa)~x2~zeros(ntot,8*kxa)   || zeros(ntot,2*kxa)~x3~zeros(ntot,7*kxa)||
zeros(ntot,3*kxa)~x4~zeros(ntot,6*kxa) || zeros(ntot,4*kxa)~x5~zeros(ntot,5*kxa) || zeros(ntot,5*kxa)~x6~zeros(ntot,4*kxa)||
zeros(ntot,6*kxa)~x7~zeros(ntot,3*kxa) || zeros(ntot,7*kxa)~x8~zeros(ntot,2*kxa) || zeros(ntot,8*kxa)~x9~zeros(ntot,1*kxa)||

but this works great and I modified a lit bit not to print results on screen by

ord = 10|ntot|cols(xx);
xb  = areshape(xx, ord);

//Convert array to blockdiagonal matrix

Once again thanks indeed.

With best wishes....