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
Your Answer
3 Answers
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;
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....
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