Resources

Creating a block diagonal matrix

0

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.

Thanks.

asked June 11, 2014

2 Answers

0

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.

new;
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
makeBlockDiag(my_array);

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,.,.];
   endfor;
	
   retp(out);
endp;
0

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)||
zeros(ntot,9*kxa)~x10;

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
blckxx=makeBlockDiag(xb);

Once again thanks indeed.

With best wishes….