4
$\begingroup$

I have a 4x4 matrix

      v1 v2 v3 v4

myM={{a1,a2,c1,c2},    v1
     {a2,a3,c2,c3},    v2
     {c1,c2,d1,d2},    v3
     {c2,c3,d2,d3}}    v4

And I want to insert this matrix into a 8x8 matrix as follows:

       u1  u2  v1  v2  u3  u4  v3  v4

myLM={{ 0,  0,  0,  0,  0,  0,  0,  0},    u1
      { 0,  0,  0,  0,  0,  0,  0,  0},    u2
      { 0,  0, a1, a2,  0,  0, c1, c2},    v1
      { 0,  0, a2, a3,  0,  0, c2, c3},    v2
      { 0,  0,  0,  0,  0,  0,  0,  0},    u3
      { 0,  0,  0,  0,  0,  0,  0,  0},    u4
      { 0,  0, c1, c2,  0,  0, d1, d2},    v3
      { 0,  0, c2, c3,  0,  0, d2, d3}}    v4

Is there a way to do this without index-nightmares?

It would also be great if the answer was general enough, in a sense that it works for 2x2 or also 8x8 matrices that I want to include into a larger matrix.

Both the smaller and the larger matrix have always an even number of columns/rows. And I divide the small and large matrices in 4 blocks and place each sub-block of the small matrix into the corresponding one of the large matrix. So in the given example the index 3 would be given and then it is clear how to insert the matrix (a1-> (3,3) and the rest follows).

So the general idea is I guess, that one has a matrix in some basis representation and wants to have this matrix now in a larger vector space adding the appropriate zeros and matrix elements etc.)

Initial basis:

{v1,v2,...,v1',v2'...}

New Basis (inserting at position n):

{u1,u2,...,un-1,v1,v2,...,un,....,u1',u2',...,un-1',v1',v2',...,un',...}
$\endgroup$
  • $\begingroup$ where did the b's come from? b1,b2,....? did you mean d1,d2,....? $\endgroup$ – Nasser Apr 1 '15 at 14:32
  • $\begingroup$ yes indeed, my bad $\endgroup$ – NOhs Apr 1 '15 at 14:33
  • $\begingroup$ Your myM has many repeated identical elements. Is that always the case, or are they supposed to be all different? I mean, is there a pattern we can assume for the repetitions? Also, do you only need zeros in the large matrix to start with? This would affect the degree to which one could simplify things. $\endgroup$ – Jens Apr 1 '15 at 16:23
4
$\begingroup$

I propose:

quarter = Partition[#, Dimensions[#]/2] &;

pad = PadLeft[#, Dimensions@#2, #2] &;

matrixInsert[small_, large_] :=
  ArrayFlatten[ pad @@ quarter /@ {small, large} ]

Test:

myM = {{a1, a2, c1, c2}, {a2, a3, c2, c3}, {c1, c2, d1, d2}, {c2, c3, d2, d3}};

myLM = Array[Plus, {8, 8}, {0, 1}];

matrixInsert[myM, myLM] // MatrixForm

$\left( \begin{array}{cccccccc} 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\ 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 \\ 3 & 4 & \text{a1} & \text{a2} & 7 & 8 & \text{c1} & \text{c2} \\ 4 & 5 & \text{a2} & \text{a3} & 8 & 9 & \text{c2} & \text{c3} \\ 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 \\ 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 \\ 7 & 8 & \text{c1} & \text{c2} & 11 & 12 & \text{d1} & \text{d2} \\ 8 & 9 & \text{c2} & \text{c3} & 12 & 13 & \text{d2} & \text{d3} \\ \end{array} \right)$


Here is an extension to control placement of the smaller blocks within the larger blocks.

ClearAll[quarter, pad, matrixInsert]

quarter = Partition[#, Dimensions[#]/2] &;

pad[pos_][a_, b_] := PadRight[a, Dimensions@b, b ~RotateLeft~ pos, pos];

matrixInsert[small_, large_, r_: 0, c_: 0] := 
  pad[{0, 0, r, c}] @@ quarter /@ {small, large} // ArrayFlatten

Test:

matrixInsert[myM, myLM] // MatrixForm   (* default *)

$\left( \begin{array}{cccccccc} \text{a1} & \text{a2} & 3 & 4 & \text{c1} & \text{c2} & 7 & 8 \\ \text{a2} & \text{a3} & 6 & 7 & \text{c2} & \text{c3} & 10 & 11 \\ 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 \\ 10 & 11 & 12 & 13 & 14 & 15 & 16 & 17 \\ \text{c1} & \text{c2} & 15 & 16 & \text{d1} & \text{d2} & 19 & 20 \\ \text{c2} & \text{c3} & 18 & 19 & \text{d2} & \text{d3} & 22 & 23 \\ 19 & 20 & 21 & 22 & 23 & 24 & 25 & 26 \\ 22 & 23 & 24 & 25 & 26 & 27 & 28 & 29 \\ \end{array} \right)$

matrixInsert[myM, myLM, 1] // MatrixForm  (* one row down *)

$\left( \begin{array}{cccccccc} 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\ \text{a1} & \text{a2} & 6 & 7 & \text{c1} & \text{c2} & 10 & 11 \\ \text{a2} & \text{a3} & 9 & 10 & \text{c2} & \text{c3} & 13 & 14 \\ 10 & 11 & 12 & 13 & 14 & 15 & 16 & 17 \\ 13 & 14 & 15 & 16 & 17 & 18 & 19 & 20 \\ \text{c1} & \text{c2} & 18 & 19 & \text{d1} & \text{d2} & 22 & 23 \\ \text{c2} & \text{c3} & 21 & 22 & \text{d2} & \text{d3} & 25 & 26 \\ 22 & 23 & 24 & 25 & 26 & 27 & 28 & 29 \\ \end{array} \right)$

matrixInsert[myM, myLM, 1, 2] // MatrixForm  (* one row down, two columns in *)

$\left( \begin{array}{cccccccc} 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\ 4 & 5 & \text{a1} & \text{a2} & 8 & 9 & \text{c1} & \text{c2} \\ 7 & 8 & \text{a2} & \text{a3} & 11 & 12 & \text{c2} & \text{c3} \\ 10 & 11 & 12 & 13 & 14 & 15 & 16 & 17 \\ 13 & 14 & 15 & 16 & 17 & 18 & 19 & 20 \\ 16 & 17 & \text{c1} & \text{c2} & 20 & 21 & \text{d1} & \text{d2} \\ 19 & 20 & \text{c2} & \text{c3} & 23 & 24 & \text{d2} & \text{d3} \\ 22 & 23 & 24 & 25 & 26 & 27 & 28 & 29 \\ \end{array} \right)$

$\endgroup$
  • $\begingroup$ That looks neat. What is the , 2 for in matrixInsert ? I just removed it and got the same result (Mathematica 10) And is there any way I can control the position of the small matrix within the quarter part of the large one? $\endgroup$ – NOhs Apr 1 '15 at 16:04
  • $\begingroup$ @MrZ If you want to have a more general approach, then you may want to look at @kguler's answer here. But then your question should have made it clearer that you want a more general outcome. $\endgroup$ – Jens Apr 1 '15 at 16:14
  • $\begingroup$ @Jens I thought that Mr.Wizard's code is already able to do what I asked for and that I was just unable to see how to change it accordingly. I do not understand why his code places the smaller matrix in the lower right corner. $\endgroup$ – NOhs Apr 1 '15 at 16:18
  • $\begingroup$ @MrZ The positioning is in the PadLeft command. You could use ArrayPad there, too. That would allow arbitrary positioning. $\endgroup$ – Jens Apr 1 '15 at 16:21
  • $\begingroup$ @MrZ (1) I hadn't thought about it but yes I guess in this case the result is the same even without the level parameter of MapThread. In fact MapThread can be eliminated. You can control placement by using the forth parameter of PadLeft, e.g. PadLeft[#, Dimensions@#2, #2, 1], or by using PadRight instead. ArrayPad could also be used but its padding specification is additive rather than absolute. $\endgroup$ – Mr.Wizard Apr 1 '15 at 16:51
3
$\begingroup$

If the larger matrix consists of zeros (or other equal elements), one can use SparseArray function:

myM = {{a1, a2, c1, c2}, {a2, a3, c2, c3}, {c1, c2, d1, d2}, {c2, c3, 
d2, d3}};
newM = SparseArray[{Band[{3, 3}] -> myM[[1 ;; 2, 1 ;; 2]],
   Band[{3, 7}] -> myM[[1 ;; 2, 3 ;; 4]],
   Band[{7, 3}] -> myM[[3 ;; 4, 1 ;; 2]],
   Band[{7, 7}] -> myM[[3 ;; 4, 3 ;; 4]]}, {8, 8}]

Here Band[{3, 3}]->A says that starting from position {3,3} matrix A should be inserted. And myM[[i ;; j, k ;; m]] is just a submatrix of your small matrix. More information on Band can be found in documentation.

To get sparse matrix in normal form type:

newM // Normal
$\endgroup$
3
$\begingroup$
myM2 = Nest[Insert[#, 0, {{1}, {1}, {3}, {3}}] & /@ Transpose[#] &,  myM, 2];
myM2 // MatrixForm // TeXForm

$\left( \begin{array}{cccccccc} 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & \text{a1} & \text{a2} & 0 & 0 & \text{c1} & \text{c2} \\ 0 & 0 & \text{a2} & \text{a3} & 0 & 0 & \text{c2} & \text{c3} \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & \text{c1} & \text{c2} & 0 & 0 & \text{d1} & \text{d2} \\ 0 & 0 & \text{c2} & \text{c3} & 0 & 0 & \text{d2} & \text{d3} \\ \end{array} \right)$

$\endgroup$

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.