Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

How can I effectively extract and replace a rectangular subpart of a toroidal matrix, i.e. one where boundaries are connected at opposite ends? Since the submatrix can overhang the edges, a simple Take won't work, as the submatrix cannot be extracted if it is not continuous. At present, I construct a table of positions that are extracted/replaced via ReplacePart, but I feel there must be more elegant and faster solutions. Such answers could add to the usefulness of Elegant operations on matrix rows and columns. Consider the following example:

n = 8; (* matrix edge length *)
m = 4; (* submatrix edge length *)

matrix = Table[0, {n}, {n}];
sub = RandomReal[{.2, 1}, {m, m}]; (* random submatrix *)
pos = {6, 7}; (* position of sub assuming bottom left corner as origo *)

subPos = Table[{i, j}, {i, m}, {j, m}];
repPos = Map[Mod[# + pos - 1, n, 1] &, subPos, {2}]; (* list of positions to extract *)

new = ReplacePart[ReplacePart[matrix, Flatten@MapThread[Rule, {repPos, sub}, 2]], pos -> 2];
  (* Replace the explicit list of positions with the elements of sub *)

ArrayPlot[Reverse@Transpose@new, 
 ColorRules -> {2 -> Pink, 0 -> White}, Mesh -> All, ImageSize -> 300]

Mathematica graphics

Pink cell indicates the origin of the submatrix.

Question: Can the extraction/replacement done faster, assuming that matrix and sub could be huge (e.g. 10 000x10 000 and 50x50, respectively)?

share|improve this question
1  
+1 Excellently presented question. I wish we had many more of those. –  halirutan Sep 25 '12 at 2:07
add comment

1 Answer 1

up vote 11 down vote accepted
 n = 8; m = 4;
 origin ={6,7};
 matrix = Table[0, {n}, {n}];
 sub2 = Array[s, {m, m}];
 sub3 = RandomReal[{.2, 1}, {m, m}];
 sub3[[1,1]]=2;


{dimmat, dimsub} = Dimensions /@ {matrix, sub2};
(* using Istvan's suggestion for generating row and column indices of the part to be replaced:*)
{rows, columns} =  Mod[Range @@@ Transpose@{origin, origin + dimsub - 1}, dimmat, 1];
matrix[[rows, columns]] = sub2;
matrix // Grid

enter image description here

matrix[[rows, columns]] = sub3;
matrix // Grid

enter image description here

ArrayPlot[Reverse@Transpose@matrix, 
     ColorRules -> {2 -> Pink, 0 -> White}, Mesh -> All, ImageSize -> 300]

enter image description here

Note: Finding the row and column indices takes almost no time. For random 10,000x10,000 matrixs and random 50 by 50 submatrices, with random origins in the last 100x100 block, it takes less than a second to replace the parts of the matrix.

share|improve this answer
1  
Thanks, I always forget about this way of part extraction and reassignment! However, I still would prefer the modulo: {rows, columns} = Mod[Range @@@ Transpose@{origin, origin + m - 1}, n, 1]. –  István Zachar Sep 24 '12 at 13:55
    
Istvan, thanks for the accept. I also prefer your Mod[...]. –  kguler Sep 24 '12 at 22:25
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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