0
$\begingroup$

Suppose I have a symbolic matrix called MAIN as follows $$ \begin{matrix} H_{00} & H_{01} & \ldots & H_{0n}\\ H_{10} & H_{11}& \ldots & H_{1n}\\ \vdots & \vdots & \ddots & \vdots\\ H_{n0} & \ldots & \ldots & H_{nn}\\ \end{matrix} $$

where each of these matrix elements is a block itself (a matrix or a vector). For example $H_{01}$ is

$$ \begin{matrix} h_1\\ h_2\\ \vdots\\ h_i \end{matrix} $$

or $H_nn$ is $$ \begin{matrix} h_{11} & h_{12} & \ldots & h_{1i}\\ h_{21} & h_{22}& \ldots &h_{2i}\\ \vdots &\vdots & \ddots & \vdots\\ h_{j1}&h_{j2}&\ldots & h_{ij}\\ \end{matrix} $$

I have calculated each of these matrix elements before and now I want to construct the MAIN matrix using them so that each matrix element is placed in the appropiate position of the MAIN matrix and the additional elements which are created due to this replacement are set to zero. How can I do this?

I applied the ArrayFlatten command to the calculated matrix elements and then simply defined the MAIN matrix using this simplified example command

MAIN={{H00,H01,H02},{H10,H11,H12}};

but the result was not my desire one.

A Toy example: assume the initial symbolic MAIN matrix is a 2x2 matrix and H00 is just a number, H01 and H10 are 2x1 matrices, and also H22 is a 2x2 matrix so the final form of the MAIN matrix after substituting must be as follows: $$ \begin{matrix} H_{00}& u_{11}&0\\ 0&u_{21}&0\\ y_{11}&p_{11}&p_{12}\\ y_{21}&p_{21}&p_{22}\\ \end{matrix} $$

where I have called the inner elements of H01,H10 and H22 by $u$,$y$ and $p$ respectively.

$\endgroup$
  • 3
    $\begingroup$ I guess you meant ArrayFlatten... If those inner matrices doesn't have the same dimensions then it is not very clear what you expect to see. Do you want to pad the rest with zeros? Probably not... $\endgroup$ – user59583 Dec 4 '18 at 13:06
  • $\begingroup$ Can you provide a toy example of how MAIN is supposed to look like after the substitution? Using e.g. Table to construct a matrix-of-matrices is straightforward, but I also do not understand what the result should be. $\endgroup$ – Titus Dec 4 '18 at 13:38
  • $\begingroup$ @ Buddha_the_Scientist Sorry yeah I meant $ArrayFlatten$, I corrected it. Thanks. Yes the rest must be set to zeros $\endgroup$ – Wisdom Dec 4 '18 at 13:40
  • $\begingroup$ @Titus I wrote a toy example $\endgroup$ – Wisdom Dec 4 '18 at 14:03
0
$\begingroup$

Complete answer

I assume 6 matrices of unknown dimensions in a known (2x3) grid, according to the toy example. I construct a list of the matrices, set some basic variables and get their dimensions.

mat1 = ConstantArray[aa, {2, 2}]; 
mat2 = ConstantArray[bb, {3, 3}]; 
mat3 = ConstantArray[c, {4, 4}]; 
mat4 = ConstantArray[d, {5, 5}]; 
mat5 = ConstantArray[f, {6, 6}]; 
mat6 = ConstantArray[g, {7, 7}];
matlist = {mat1, mat2, mat3, mat4, mat5, mat6};(*list of sub-matrices*)
T = 3;(*Row length in MAIN*)
TT = 2; (*Column length in MAIN, T can be used for square matrix *)
nsm = 6; (*number of sub-matrices*)
end = {20, 20};(*coordinates of bottom right point in MAIN*)
ted = Dimensions /@ matlist

I then get the coordinates of the top-left point of each matrix and construct the MAIN matrix mat containing the placeholders.

xx = Accumulate /@ Most /@ Partition[Prepend[Riffle[ted[[All, 1]], 1, T + 1], 1], T + 1];
yy = Table[ConstantArray[Accumulate[Drop[Prepend[Max /@ Partition[ted[[All, 2]], T], 1], -1]]
[[i]], T], {i, 1, TT}];
aux = Join @@ Transpose /@ Thread[{yy, xx}]
mat = Normal[SparseArray[{aux -> ConstantArray[B, nsm], end -> 0}]];

I then perform the replacement.

a = Join @@ Position[mat, B];
b = Join @@ Dimensions /@ matlist;
coor = Flatten /@ Partition[Thread[{a, b + a - 1}], 2];
Table[mat[[coor[[i, 1]] ;; coor[[i, 2]], coor[[i, 3]] ;; coor[[i, 4]]]] = matlist[[i]];, 
{i, 1, nsm}]
mat // MatrixForm

The code works with an equal number of matrices in each row but it is easy to alter xx and yy to accomodate for that (it just needs to count the length of each row instead of having a fixed T). For a 3*3,, 4*3,4 *4 etc matrix you add the matrices in matlist and change T. To see the various steps remove the semicolons.

I am certain that a much simpler version with Grid or SparseArray is possible.

$\endgroup$
  • $\begingroup$ Thanks a lot. The dimension of the final MAIN matrix is known and is (1+i+j+ij). Your idea is good, I will try it, however I'm not sure that it will be efficient for my real problem, where the dimension of MAIN matrix is 88×88. $\endgroup$ – Wisdom Dec 4 '18 at 17:46
  • $\begingroup$ @NSR I added a small update that might help streamline the process. The method works but it is not the fastest way. $\endgroup$ – Titus Dec 4 '18 at 19:36
  • $\begingroup$ @ Titus Many Thanks, your codes work properly, but for my real problem where the final MAIN is an 88 by 88 matrix, it's very hard and time-consuming to specify the position of each submatrix. You know I'm looking for an efficient code so that when I specify the initial dimensions of the MAIN (for my real problem it's a 4x4 matrix) and then give submatrices and their positions in the initial MAIN matrix, it replaces them into the MAIN and extend it to final dimensions (for my real problem to 88x88 matrix) and set the other added elements to zeros. $\endgroup$ – Wisdom Dec 5 '18 at 7:48
  • $\begingroup$ Are your matrices always adjacent from left to right, or can you have e.g. H(1,2), then zeroes, then H(1,3)? A grid is possible, but if you have e.g. a full row or column of zeroes in MAIN it will not give you what you want. $\endgroup$ – Titus Dec 5 '18 at 12:09
  • $\begingroup$ yeah, they are. There isn't a full row or column of zeroes. $\endgroup$ – Wisdom Dec 5 '18 at 16:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.