5

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',...}
NOhs
  • 869
  • 7
  • 13
  • where did the b's come from? b1,b2,....? did you mean d1,d2,....? – Nasser Apr 01 '15 at 14:32
  • yes indeed, my bad – NOhs Apr 01 '15 at 14:33
  • 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. – Jens Apr 01 '15 at 16:23

3 Answers3

6

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)$

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • 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? – NOhs Apr 01 '15 at 16:04
  • @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. – Jens Apr 01 '15 at 16:14
  • @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. – NOhs Apr 01 '15 at 16:18
  • @MrZ The positioning is in the PadLeft command. You could use ArrayPad there, too. That would allow arbitrary positioning. – Jens Apr 01 '15 at 16:21
  • @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. – Mr.Wizard Apr 01 '15 at 16:51
  • Your suggestion with PadLeft[...,1] doesn't work for me. I get {{11, 12, 13, 10, 7, 8, 9, 6}, {12, d1, d2, 11, 8, 9, 10, 7}, {13, d2, d3, 12, 9, 10, 11, 8}, {10, 11, 12, 9, 6, 7, 8, 5}, {7, 8, 9, 6, 3, 4, 5, 2}, {8, 9, 10, 7, 4, 5, 6, 3}, {9, 10, 11, 8, 5, 6, 7, 4}, {6, 7, 8, 5, 2, 3, 4, 1}} – NOhs Apr 02 '15 at 08:58
  • @MrZ You're right again. Sorry for the crummy suggestion. I'm sort of distracted these days I guess. For the current code I would need PadLeft[#, Dimensions@#2, #2, {0, 0, 1, 1}] for what I originally meant, but it still doesn't work right and never did. Let me think about this and get back to you. PadRight does work for upper-left insertion at least. – Mr.Wizard Apr 02 '15 at 14:08
  • @MrZ Please see the updated answer. – Mr.Wizard Apr 02 '15 at 14:23
4

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
Ivan
  • 235
  • 1
  • 7
4
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)$

kglr
  • 394,356
  • 18
  • 477
  • 896