Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Flattening a hypermatrix into an ordinary matrix

15 views
Skip to first unread message

car...@colorado.edu

unread,
Jun 1, 2012, 5:21:40 AM6/1/12
to
I have an n x n hypermatrix, the entries of which are m x m blocks.
For example A below (m=3, n=2):

A11={{B11,B12,B13},{B21,B22,B23},{B31,B32,B33}};
A12={{C11,C12,C13},{C21,C22,C23},{C31,C32,C33}};
A21={{D11,D12,D13},{D21,D22,D23},{D31,D32,D33}};
A22={{E11,E12,E13},{E21,E22,E23},{E31,E32,E33}};
A={{ A11,A12},{A21,A22}};

I want to convert this to an ordinary n*m x n*m matrix.
For the example I want A to become

{{B11,B12,B13,C11,C12,C13},{B21,B22,B23,C21,C22,C23},
{B31,B32,B33,C31,C32,C33},{D11,D12,D13,E11,E12,E13},
{D21,D22,D23,E21,E22,E23},{D31,D32,D33,E31,E32,E33}}

This can be easily done with C style loops as

AA=Table[0,{m*n},{m*n}];
For [i=1,i<=n,i++, For[j=1,j<=n,j++,
For [k=1,k<=m,k++, For [l=1,l<=m,l++,
AA[[m*(i-1)+k,m*(j-1)+l]]=A[[i,j,k,l]]
]]]];

but is there a more elegant way using Flatten?
(Flatten[A,1] doesnt do it.) It should work also for blocks
of varying size for future use.

Bill Rowe

unread,
Jun 2, 2012, 5:44:12 AM6/2/12
to
On 6/1/12 at 5:19 AM, car...@colorado.edu wrote:

>I have an n x n hypermatrix, the entries of which are m x m blocks.
>For example A below (m=3, n=2):

>A11={{B11,B12,B13},{B21,B22,B23},{B31,B32,B33}};
>A12={{C11,C12,C13},{C21,C22,C23},{C31,C32,C33}};
>A21={{D11,D12,D13},{D21,D22,D23},{D31,D32,D33}};
>A22={{E11,E12,E13},{E21,E22,E23},{E31,E32,E33}}; A={{
>A11,A12},{A21,A22}};

>I want to convert this to an ordinary n*m x n*m matrix. For the
>example I want A to become

>{{B11,B12,B13,C11,C12,C13},{B21,B22,B23,C21,C22,C23},
>{B31,B32,B33,C31,C32,C33},{D11,D12,D13,E11,E12,E13},
>{D21,D22,D23,E21,E22,E23},{D31,D32,D33,E31,E32,E33}}

>This can be easily done with C style loops as

<snip>

>but is there a more elegant way using Flatten?

Better would be to use ArrayFlatten which is specifically
designed for this task, i.e.,

In[6]:= ArrayFlatten[a]

Out[6]=
{{b11, b12, b13, c11, c12, c13}, {b21, b22, b23, c21, c22, c23},
{b31, b32, b33, c31, c32, c33}, {d11, d12, d13, e11, e12, e13},
{d21, d22, d23, e21, e22, e23}, {d31, d32, d33, e31, e32, e33}}


da...@wolfram.com

unread,
Jun 2, 2012, 5:45:14 AM6/2/12
to
In[449]:= ArrayFlatten[A]

Out[449]= {{B11, B12, B13, C11, C12, C13}, {B21, B22, B23, C21, C22,
C23}, {B31, B32, B33, C31, C32, C33}, {D11, D12, D13, E11, E12,
E13}, {D21, D22, D23, E21, E22, E23}, {D31, D32, D33, E31, E32,
E33}}

(I was actually surprised to learn that ArrayFlatten did this "out of the box", so to speak. But then, I'm easily surprised.)

Daniel Lichtblau
Wolfram Research

Ray Koopman

unread,
Jun 2, 2012, 5:45:44 AM6/2/12
to
Flatten /@ Flatten[Transpose[A,{1,3,2,4}],1]

will also do it and is a little cleaner than my previous suggestion.

Nasser M. Abbasi

unread,
Jun 2, 2012, 5:49:19 AM6/2/12
to
May be a Flatten/Table/Join combination?

-----------------------
m=3;n=2;
Flatten[Table[Join[A[[j,1,i]],A[[j,2,i]]],{j,1,n},{i,1,m}],1]
---------------------------

{{B11, B12, B13, C11, C12, C13}, {B21, B22, B23, C21, C22, C23},
{B31,B32, B33, C31, C32, C33}, {D11, D12, D13, E11, E12, E13},
{D21, D22, D23, E21, E22, E23}, {D31, D32, D33, E31, E32, E33}}

--Nasser




Ray Koopman

unread,
Jun 2, 2012, 5:49:49 AM6/2/12
to
On Jun 1, 2:21 am, car...@colorado.edu wrote:
In[1]:=
A11 = {{B11,B12,B13},{B21,B22,B23},{B31,B32,B33}};
A12 = {{C11,C12,C13},{C21,C22,C23},{C31,C32,C33}};
A21 = {{D11,D12,D13},{D21,D22,D23},{D31,D32,D33}};
A22 = {{E11,E12,E13},{E21,E22,E23},{E31,E32,E33}};
A = {{ A11,A12},{A21,A22}};

In[6]:=
Flatten[Map[Flatten,Transpose[A,{1,3,2,4}],{2}],1]

Out[6]=

Sseziwa Mukasa

unread,
Jun 2, 2012, 5:50:20 AM6/2/12
to
ArrayFlatten[{{A11,A12},{A21,A22}}]

Regards,
Sseziwa

Oleksandr Rasputinov

unread,
Jun 2, 2012, 5:51:21 AM6/2/12
to
Yes; you can use:

Flatten[A, {{1, 3}, {2, 4}}]

{{B11, B12, B13, C11, C12, C13}, {B21, B22, B23, C21, C22, C23},
{B31, B32, B33, C31, C32, C33}, {D11, D12, D13, E11, E12, E13},
{D21, D22, D23, E21, E22, E23}, {D31, D32, D33, E31, E32, E33}}

which flattens together levels 1 and 3 to form level 1 in the result, and
levels 2 and 4 to form level 2. (I often find it helpful to look at
Dimensions[A], which is {2, 2, 3, 3}, to figure out what is needed in
cases like this.)

Since the Flatten documentation is rather terse, for a more detailed
description of how this works, I'd suggest having a look at Leonid
Shifrin's answer at:

http://mathematica.stackexchange.com/questions/119/flatten-command-matrix-as-second-argument

Szabolcs Horvát

unread,
Jun 2, 2012, 5:51:52 AM6/2/12
to
You're looking for ArrayFlatten[A].

For more complex uses of Flatten, you might enjoy reading this guide:

http://mathematica.stackexchange.com/questions/119/flatten-command-matrix-as-second-argument


--
Szabolcs Horvát
Visit Mathematica.SE: http://mathematica.stackexchange.com/

Andrzej Kozlowski

unread,
Jun 2, 2012, 5:52:22 AM6/2/12
to



On 1 Jun 2012, at 11:19, car...@colorado.edu wrote:

> I have an n x n hypermatrix, the entries of which are m x m blocks.
> For example A below (m=3, n=2):
>
> A11={{B11,B12,B13},{B21,B22,B23},{B31,B32,B33}};
> A12={{C11,C12,C13},{C21,C22,C23},{C31,C32,C33}};
> A21={{D11,D12,D13},{D21,D22,D23},{D31,D32,D33}};
> A22={{E11,E12,E13},{E21,E22,E23},{E31,E32,E33}};
> A={{ A11,A12},{A21,A22}};
>
> I want to convert this to an ordinary n*m x n*m matrix.
> For the example I want A to become
>
> {{B11,B12,B13,C11,C12,C13},{B21,B22,B23,C21,C22,C23},
> {B31,B32,B33,C31,C32,C33},{D11,D12,D13,E11,E12,E13},
> {D21,D22,D23,E21,E22,E23},{D31,D32,D33,E31,E32,E33}}
>
> This can be easily done with C style loops as
>
> AA=Table[0,{m*n},{m*n}];
> For [i=1,i<=n,i++, For[j=1,j<=n,j++,
> For [k=1,k<=m,k++, For [l=1,l<=m,l++,
> AA[[m*(i-1)+k,m*(j-1)+l]]=A[[i,j,k,l]]
> ]]]];
>
> but is there a more elegant way using Flatten?
> (Flatten[A,1] doesnt do it.) It should work also for blocks
> of varying size for future use.
>

ArrayFlatten[A] is exactly for this purpose.

Andrzej Kozlowski

Bob Hanlon

unread,
Jun 2, 2012, 5:52:53 AM6/2/12
to
Use Join @@@ Flatten[Transpose /@ A, 1]

A11 = {{B11, B12, B13}, {B21, B22, B23}, {B31, B32, B33}};
A12 = {{C11, C12, C13}, {C21, C22, C23}, {C31, C32, C33}};
A21 = {{D11, D12, D13}, {D21, D22, D23}, {D31, D32, D33}};
A22 = {{E11, E12, E13}, {E21, E22, E23}, {E31, E32, E33}};
A = {{A11, A12}, {A21, A22}};

m = 3; n = 2;

AA = Table[0, {m*n}, {m*n}];
For[i = 1, i <= n, i++,
For[j = 1, j <= n, j++,
For[k = 1, k <= m, k++,
For[l = 1, l <= m, l++,
AA[[m*(i - 1) + k, m*(j - 1) + l]] = A[[i, j, k, l]]]]]]

AA == Join @@@ Flatten[Transpose /@ A, 1]

True

Extending to m=3 and n=3

A13 = A11;
A23 = A21;
A31 = {{F11, F12, F13}, {F21, F22, F23}, {F31, F32, F33}};
A32 = {{G11, G12, G13}, {G21, G22, G23}, {G31, G32, G33}};
A33 = A31;
A = {{A11, A12, A13}, {A21, A22, A23}, {A31, A32, A33}};

m = 3; n = 3;

AA = Table[0, {m*n}, {m*n}];
For[i = 1, i <= n, i++,
For[j = 1, j <= n, j++,
For[k = 1, k <= m, k++,
For[l = 1, l <= m, l++,
AA[[m*(i - 1) + k, m*(j - 1) + l]] = A[[i, j, k, l]]]]]]

AA == Join @@@ Flatten[Transpose /@ A, 1]

True


Bob Hanlon

Nasser M. Abbasi

unread,
Jun 3, 2012, 4:59:44 AM6/3/12
to
yes, I also forgot above ArrayFaltten.

so many Mathematica functions, so little time.

--Nasser

car...@colorado.edu

unread,
Jun 3, 2012, 5:04:52 AM6/3/12
to
Thanks! This seems to work fine, even for variable size blocks. For
example
(this comes from an actual fluid-structure interaction FEM simulation)

A={{{{B11}},{{C11}},{{D11,D12}},{{E11}},{{F11}}},
{{{G11},{G12}},{{H11},{H12}},{{I11,I12},{I21,I22}},{{J11},{J12}},
{{K11},{K12}}},
{{{L11}},{{M11}},{{N11,N12}},{{O11}},{{P11}}},
{{{Q11}},{{R11}},{{S11,S12}},{{T11}},{{U11}}},
{{{V11}},{{W11}},{{X11,X12}},{{Y11}},{{Z11}}}};

AA = Join @@@ Flatten[Transpose /@ A, 1] ; Print["AA=",AA//
MatrixForm];

I can't use ArrayFlatten since it does not exist in versions of
Mathematica
such as 4 or 5, which some of my off-campus students use (they were
licensed
by their employers long ago)

0 new messages