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.

So, earlier today I asked the question

How to transform this matrix & swap its columns in a simple way?

and was given useful and elaborated answers. Now, I'm still not used to the "Array", "Reverse", "Map", etc. functions (which were new to me this morning) and this question is in fact a particular case of the other one :

I would like to transform matrix $\mathbf A = \begin{pmatrix} a_{11}&b_{11}&a_{12}&b_{12}&a_{13}&b_{13}\\ a_{21}&b_{21}&a_{22}&b_{22}&a_{23}&b_{23} \\ a_{31}&b_{31}&a_{32}&b_{32}&a_{33}&b_{33} \\ a_{41}&b_{41}&a_{42}&b_{42}&a_{43}&b_{43} \\ a_{51}&b_{51}&a_{52}&b_{52}&a_{53}&b_{54} \\ a_{61}&b_{61}&a_{62}&b_{62}&a_{63}&b_{63} \\ a_{71}&b_{71}&a_{72}&b_{72}&a_{73}&b_{73} \\ a_{81}&b_{81}&a_{82}&b_{82}&a_{83}&b_{83} \end{pmatrix}$ into matrix $\mathbf B = \begin{pmatrix} a_{83}&-b_{83}&a_{82}&-b_{82}&a_{81}&-b_{81} \\ a_{73}&-b_{73}&a_{72}&-b_{72}&a_{71}&-b_{71}\\ a_{63}&-b_{63}&a_{62}&-b_{62}&a_{61}&-b_{61} \\ a_{53}&-b_{53}&a_{52}&-b_{52}&a_{51}&-b_{51} \\ a_{43}&-b_{43}&a_{42}&-b_{42}&a_{41}&-b_{41}\\ a_{33}&-b_{33}&a_{32}&-b_{32}&a_{31}&-b_{31} \\ a_{23}&-b_{23}&a_{22}&-b_{22}&a_{21}&-b_{21} \\ a_{13}&-b_{13}&a_{12}&-b_{12}&a_{11}&-b_{11} \end{pmatrix}$.

In fact, to do this, I can multiply matrix $\mathbf A$ by the anti-diagonal identity matrix on the left : $\begin{pmatrix} 0&0&0&0&0&0&0&1\\ 0&0&0&0&0&0&1&0 \\ 0&0&0&0&0&1&0&0 \\ 0&0&0&0&1&0&0&0 \\ 0&0&0&1&0&0&0&0 \\ 0&0&1&0&0&0&0&0 \\ 0&1&0&0&0&0&0&0 \\ 1&0&0&0&0&0&0&0 \end{pmatrix}$, and multiply on the right by $\begin{pmatrix} 0&0&0&0&0&0&1&0\\ 0&0&0&0&0&0&0&-1 \\ 0&0&0&0&1&0&0&0 \\ 0&0&0&0&0&-1&0&0 \\ 0&0&1&0&0&0&0&0 \\ 0&0&0&-1&0&0&0&0 \\ 1&0&0&0&0&0&0&0 \\ 0&-1&0&0&0&0&0&0\end{pmatrix}$ to obtain matrix $\mathbf B$.

But I can't figure out how to generalize this to $\{n\times m,\ n>8,\ m>6\}$ size matrices, and most importantly how to make it efficient in terms of time consumption... Does anyone have any ideas?

Thanks in advance.

Mathematica expression of A :

    A = Table[Sequence @@ {a[i, j], b[i, j]}, {i, 8}, {j, 3}]

Additional note : What I intend to do is to :

  • Turn the matrix upside down

  • Treat block matrices by sets of two columns and in each set

    • Change the sign of the second column of each set
  • Finally flipping the matrix as in a mirror image (but keeping the sets of two columns in order : for the example above $\rightarrow$ columns 1 & 2 become 4 & 6; columns 2 & 3 stay in their place (only in this example); columns 4 & 6 become 1 & 2.
share|improve this question

3 Answers 3

up vote 3 down vote accepted
  arrngF1 = MapAt[-1 # &,
   #[[Range[Dimensions[#][[1]], 1, -1],
  Join @@ Reverse@Partition[Range[Dimensions[#][[2]]], {2}]]],
  {;; , 2 ;; ;; 2}] &;
  arrngF2 = Module[{temp = #[[Range[Dimensions[#][[1]], 1, -1],
    Join @@ Reverse@Partition[Range[Dimensions[#][[2]]], {2}]]]},
   temp[[;; , 2 ;; ;; 2]] = (-1) temp[[;; , 2 ;; ;; 2]]; temp] &;

Example:

  mat = make[8, 3] (* from whuber's answer *);
  Grid[{{"mat", "arrngF1[mat]", "arrngF2[mat]"},
   MatrixForm /@ {mat, arrngF1[mat], arrngF2[mat]}}, Dividers -> All]

enter image description here

Timings:

  ClearSystemCache[];
  ClearAll[c, d, d0, d1, d2]
  c = make[1000, 1000];
  AbsoluteTiming[d = arrange[c];]
  (* {2.83919999,Null} *)
  AbsoluteTiming[d0 = rM[#, {1, -1}] & /@ Reverse[c];]
  (* {9.95279999,Null} *)
  AbsoluteTiming[d1 = arrngF1[c];]
  (* {1.9812000000,Null} *)
  AbsoluteTiming[d2 = arrngF2[c];]
  (* {2.2307999999,Null} *)
  d == d0 == d1 == d2
  (* True *)

Update: Modifying @whuber's method (using Band in the construction of the SparseArrays for pre/post-multiplying the input array):

  ClearAll[arrange2];
  arrange2[c_] := 
  Module[{m = Dimensions[c][[1]], n = Dimensions[c][[2]]},
  SparseArray[Band[{1, m}, Automatic, {1, -1}] -> 1, {m, m}].c.
  SparseArray[{Band[{1, n - 1}, Automatic, {2, -2}] -> 1,
  Band[{2, n}, Automatic, {2, -2}] -> -1}, {n, n}]];

Timings:

  ClearSystemCache[];
  ClearAll[c, d, d0, d1, d2]
  c = make[1000, 1000];
  AbsoluteTiming[d = arrange[c];]
  (* {3.0360000000,Null} *)
  AbsoluteTiming[d0 = arrange2[c];]
  (* {1.528000,Null}*)
  AbsoluteTiming[d1 = arrngF1[c];]
  (* {2.08800,Null}*)
  AbsoluteTiming[d2 = arrngF2[c];]
  (* {2.467000,Null} *)
  d == d0 == d1 == d2
  (* True *)

(All timings for Intel Core Duo2 T9600 @ 2.8GHz with 8G memory running Mathematica 9.0. on MS Windows Vista 64-bit.)

share|improve this answer
    
+1. ArrngF1 fails on v. 8.0 with an error about an invalid position specification, but ArrngF2 works beautifully. On this machine, for large symbolic matrices it is 20% to 100% faster than arrange and for large numeric matrices it is 100% faster. Nevertheless, I would still favor the OP's approach (based on pre- and post-multiplying by suitable matrices) as being perhaps the best general-purpose strategy for such matrix manipulation, because it will work just as efficiently for much more complicated re-arrangements involving arbitrary row and column permutations. –  whuber Feb 18 '13 at 17:18
    
Re the edit, The use of Band seems to be your theme for today :-). Thank you for the very nice application. –  whuber Feb 18 '13 at 20:26
    
@kguler Thanks for your proposition! I'm using elements from your answer and mixing them with some of whuber's... The Band hint is really useful. Seems to accelerate the calculations. –  jrojasqu Feb 20 '13 at 13:08

On many platforms, matrix operations are really fast, so using them is a good idea. (You have to get their dimensions correct, though!)

SparseArray objects are likely to be efficient in RAM and time usage. All we have to do is code the rules used to generate the right and left matrices:

arrange[c_] := Block[{m, n, sa},
   {m, n} = Dimensions[c];
   sa[x__] := SparseArray[Array[x]];
   sa[{#, m + 1 - #} -> 1 &, m] . c . sa[{#, n + 1 - # + (-1)^#} -> (-1)^(# - 1) &, n]];

As an example, let's construct arbitrarily large forms of the matrix in the question:

make[m_, n_] := Table[Sequence@@{Subscript[a,i,j], Subscript[b,i,j]},{i,m},{j,n}];

How about operating on a $1000$ by $2000$ symbolic matrix?

c = make[1000, 1000]; AbsoluteTiming[d = arrange[c];]

{1.2210698, Null}

We can store the result and inspect small parts of it to confirm correctness; e.g.,

With[{e = Normal[d]}, 
  Join[Join[e[[1 ;; 3, 1 ;; 3]], ConstantArray["...", {3, 1}], 
    e[[1 ;; 3, -3 ;; -1]], 2], ConstantArray["...", {1, 7}], 
   Join[e[[-3 ;; -1, 1 ;; 3]], ConstantArray["...", {3, 1}], 
    e[[-3 ;; -1, -3 ;; -1]], 2]]] // TraditionalForm

$$\left( \begin{array}{ccccccc} a_{1000,1000} & -b_{1000,1000} & a_{1000,999} & \text{...} & -b_{1000,2} & a_{1000,1} & -b_{1000,1} \\ a_{999,1000} & -b_{999,1000} & a_{999,999} & \text{...} & -b_{999,2} & a_{999,1} & -b_{999,1} \\ a_{998,1000} & -b_{998,1000} & a_{998,999} & \text{...} & -b_{998,2} & a_{998,1} & -b_{998,1} \\ \text{...} & \text{...} & \text{...} & \text{...} & \text{...} & \text{...} & \text{...} \\ a_{3,1000} & -b_{3,1000} & a_{3,999} & \text{...} & -b_{3,2} & a_{3,1} & -b_{3,1} \\ a_{2,1000} & -b_{2,1000} & a_{2,999} & \text{...} & -b_{2,2} & a_{2,1} & -b_{2,1} \\ a_{1,1000} & -b_{1,1000} & a_{1,999} & \text{...} & -b_{1,2} & a_{1,1} & -b_{1,1} \end{array} \right)$$

share|improve this answer
    
What is this one-argument form of Array you are using? –  Mr.Wizard Feb 18 '13 at 8:33
    
@Mr.Wizard: It's the old familiar multiple-argument form: although it may be hard to see, sa[x__] has two underscores in the pattern and you can check that both invocations of sa actually use two arguments. I used this abbreviation in order to clarify the ultimate line, which otherwise would be obscured by the two references to SparseArray[Array[..]]. –  whuber Feb 18 '13 at 17:09
1  
@whuber Thanks! It all works great! Although I think I'm mixing your answer with the one kguler (@kguler) provided. I also believe that multiplying on the left and on the right is more intuitive and maybe even more "logical" if I may... Thanks again! –  jrojasqu Feb 20 '13 at 13:04

You could use Reverse for the first part and define a helper function to do the rest :

rM[avector_, {m1_, m2_}] := 
 Module[{nc, local, rules},
  nc = Length[avector]/2;
  local = {m1, m2} # & /@ Partition[avector, 2];
  Flatten[ReplacePart[local, (# -> local[[ nc + 1 - #]]) & /@  Range[nc]], 1]
 ]

The argument {m1, m2} will be used to multiply each couple of columns by input factors.

Test :

bigA = (Flatten[#] & /@ 
Outer[{Subscript[a, #1, #2], Subscript[b, #1, #2]} &, Range[8], Range[3], 1, 1]);
bigA // MatrixForm

$\left( \begin{array}{cccccc} a_{1,1} & b_{1,1} & a_{1,2} & b_{1,2} & a_{1,3} & b_{1,3} \\ a_{2,1} & b_{2,1} & a_{2,2} & b_{2,2} & a_{2,3} & b_{2,3} \\ a_{3,1} & b_{3,1} & a_{3,2} & b_{3,2} & a_{3,3} & b_{3,3} \\ a_{4,1} & b_{4,1} & a_{4,2} & b_{4,2} & a_{4,3} & b_{4,3} \\ a_{5,1} & b_{5,1} & a_{5,2} & b_{5,2} & a_{5,3} & b_{5,3} \\ a_{6,1} & b_{6,1} & a_{6,2} & b_{6,2} & a_{6,3} & b_{6,3} \\ a_{7,1} & b_{7,1} & a_{7,2} & b_{7,2} & a_{7,3} & b_{7,3} \\ a_{8,1} & b_{8,1} & a_{8,2} & b_{8,2} & a_{8,3} & b_{8,3} \\ \end{array} \right)$

(rM[#, {1, -1}] & /@ Reverse[bigA]) // MatrixForm

$\left( \begin{array}{cccccc} a_{8,3} & -b_{8,3} & a_{8,2} & -b_{8,2} & a_{8,1} & -b_{8,1} \\ a_{7,3} & -b_{7,3} & a_{7,2} & -b_{7,2} & a_{7,1} & -b_{7,1} \\ a_{6,3} & -b_{6,3} & a_{6,2} & -b_{6,2} & a_{6,1} & -b_{6,1} \\ a_{5,3} & -b_{5,3} & a_{5,2} & -b_{5,2} & a_{5,1} & -b_{5,1} \\ a_{4,3} & -b_{4,3} & a_{4,2} & -b_{4,2} & a_{4,1} & -b_{4,1} \\ a_{3,3} & -b_{3,3} & a_{3,2} & -b_{3,2} & a_{3,1} & -b_{3,1} \\ a_{2,3} & -b_{2,3} & a_{2,2} & -b_{2,2} & a_{2,1} & -b_{2,1} \\ a_{1,3} & -b_{1,3} & a_{1,2} & -b_{1,2} & a_{1,1} & -b_{1,1} \\ \end{array} \right)$

bigA = (Flatten[#] & /@ 
Outer[{Subscript[a, #1, #2], Subscript[b, #1, #2]} &, Range[8], Range[4], 1,1]);
bigA // MatrixForm

$\left( \begin{array}{cccccccc} a_{1,1} & b_{1,1} & a_{1,2} & b_{1,2} & a_{1,3} & b_{1,3} & a_{1,4} & b_{1,4} \\ a_{2,1} & b_{2,1} & a_{2,2} & b_{2,2} & a_{2,3} & b_{2,3} & a_{2,4} & b_{2,4} \\ a_{3,1} & b_{3,1} & a_{3,2} & b_{3,2} & a_{3,3} & b_{3,3} & a_{3,4} & b_{3,4} \\ a_{4,1} & b_{4,1} & a_{4,2} & b_{4,2} & a_{4,3} & b_{4,3} & a_{4,4} & b_{4,4} \\ a_{5,1} & b_{5,1} & a_{5,2} & b_{5,2} & a_{5,3} & b_{5,3} & a_{5,4} & b_{5,4} \\ a_{6,1} & b_{6,1} & a_{6,2} & b_{6,2} & a_{6,3} & b_{6,3} & a_{6,4} & b_{6,4} \\ a_{7,1} & b_{7,1} & a_{7,2} & b_{7,2} & a_{7,3} & b_{7,3} & a_{7,4} & b_{7,4} \\ a_{8,1} & b_{8,1} & a_{8,2} & b_{8,2} & a_{8,3} & b_{8,3} & a_{8,4} & b_{8,4} \\ \end{array} \right)$

(rM[#, {1, -1}] & /@ Reverse[bigA]) // MatrixForm

$\left( \begin{array}{cccccccc} a_{8,4} & -b_{8,4} & a_{8,3} & -b_{8,3} & a_{8,2} & -b_{8,2} & a_{8,1} & -b_{8,1} \\ a_{7,4} & -b_{7,4} & a_{7,3} & -b_{7,3} & a_{7,2} & -b_{7,2} & a_{7,1} & -b_{7,1} \\ a_{6,4} & -b_{6,4} & a_{6,3} & -b_{6,3} & a_{6,2} & -b_{6,2} & a_{6,1} & -b_{6,1} \\ a_{5,4} & -b_{5,4} & a_{5,3} & -b_{5,3} & a_{5,2} & -b_{5,2} & a_{5,1} & -b_{5,1} \\ a_{4,4} & -b_{4,4} & a_{4,3} & -b_{4,3} & a_{4,2} & -b_{4,2} & a_{4,1} & -b_{4,1} \\ a_{3,4} & -b_{3,4} & a_{3,3} & -b_{3,3} & a_{3,2} & -b_{3,2} & a_{3,1} & -b_{3,1} \\ a_{2,4} & -b_{2,4} & a_{2,3} & -b_{2,3} & a_{2,2} & -b_{2,2} & a_{2,1} & -b_{2,1} \\ a_{1,4} & -b_{1,4} & a_{1,3} & -b_{1,3} & a_{1,2} & -b_{1,2} & a_{1,1} & -b_{1,1} \\ \end{array} \right)$

share|improve this answer
    
Thanks! This is what I call fancy code! It works just fine, but I'm still trying to understand it... I'm new to the "Slot", Reverse, and Rotate functions... Thanks again! –  jrojasqu Feb 17 '13 at 18:13
    
Sorry! I made a big mistake, or in fact, I forgot to precise that the matrix A dimension isn't even... –  jrojasqu Feb 17 '13 at 19:53
    
I really don't mean to be annoying... My problem is that I wasn't clear enough with what I needed. I edited my initial question, and I hope that it is clear enough now... –  jrojasqu Feb 17 '13 at 20:58
    
Ok, just give me some minutes, I'm editing the question, I think it will be clearer by then! –  jrojasqu Feb 17 '13 at 21:46
    
There it is, I hope I am now clear enough to be helped! –  jrojasqu Feb 17 '13 at 21:58

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.