Creating a block diagonal matrix

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.

3 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....

 



0



The current version of GAUSS has a built-in function to create block diagonal matrices. The function name is blockDiag and it can take in a comma-separated list of one or more matrices. Here is a simple example.

// Create 3 matrices of different sizes
a = { 0.5 1.1,
      2.0 0.3 };
b = 0.8;
c = { 0.2 1.0 0.7,
      1.3 0.6 1.4 };

// Create block-diagonal matrix
d = blockDiag(a, b, c);

which will create a matrix d with the following contents

    0.5 1.1   0   0   0   0
    2.0 0.3   0   0   0   0
d =   0   0 0.8   0   0   0
      0   0   0 0.2 1.0 0.7
      0   0   0 1.3 0.6 1.4

aptech

1,773

Your Answer

3 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....

 

0

The current version of GAUSS has a built-in function to create block diagonal matrices. The function name is blockDiag and it can take in a comma-separated list of one or more matrices. Here is a simple example.

// Create 3 matrices of different sizes
a = { 0.5 1.1,
      2.0 0.3 };
b = 0.8;
c = { 0.2 1.0 0.7,
      1.3 0.6 1.4 };

// Create block-diagonal matrix
d = blockDiag(a, b, c);

which will create a matrix d with the following contents

    0.5 1.1   0   0   0   0
    2.0 0.3   0   0   0   0
d =   0   0 0.8   0   0   0
      0   0   0 0.2 1.0 0.7
      0   0   0 1.3 0.6 1.4


You must login to post answers.

Have a Specific Question?

Get a real answer from a real person

Need Support?

Get help from our friendly experts.