# How to select elements in a tensor conditional upon their indices

I have a tensor, u, of rank one, meaning that I have a matrix whose elements are themselves matrices. I would like to select, and make a list of, only those sub-matrices whose indices comply with the condition j < k, i.e. the row index is always smaller than the column index.

This effectively corresponds to strictly upper-triangularising the tensor. Once I select the correct sub-matrices, I would like them to appear in a list sorted row by row. I.e., if each sub-matrix is called aXX, where XX are the row and column indices, and the tensor has dimensions NxN, then I want the list to look like this:

a12, a13, a14 ..., a1N, a23, a24, ..., a2N, a34, ..., a3N, ..., a(N-1)N.


I have tried using UpperTriangularize[] to no avail. I suspect the answer must be using Select[] or Pick[], but I am unsure of how to implement the condition based on testing the indices of the tensor. Any ideas would be much appreciated.

Here is my code which generates u. NLevel is the same as N that I mentioned above, and can be varied with each run of the programme.

 P = Table[SparseArray[{{j, k} -> 1}, {NLevel, NLevel}], {j, NLevel}, {k, NLevel}]
u = Table[P[[1, j, k]] + P[[1, k, j]], {j, NLevel}, {k, NLevel}]

-

You can also use Part:

NLevel = 3;
P = Table[SparseArray[{{j, k} -> 1}, {NLevel, NLevel}], {j, NLevel}, {k, NLevel}];

P[[##]] & @@@ Subsets[Range@Length@P, {2}] // Normal

(* {{{0, 1, 0}, {0, 0, 0}, {0, 0, 0}},
{{0, 0, 1}, {0, 0, 0}, {0, 0, 0}},
{{0, 0, 0}, {0, 0, 1}, {0, 0, 0}}} *)


Instead of Subsets[Range@Length@P, {2}] we can also use SparseArray[UpperTriangularize[ConstantArray[1, {NLevel, NLevel}], 1]]["NonzeroPositions"].

-

I believe this does what you want (using your u example without the MatrixForm formatting):

Normal@Extract[#, Sort@Join[Array[{#, #} &, Length@#], Subsets[Range@Length@#, {2}]]] &[u]

(*
{{{2, 0, 0}, {0, 0, 0}, {0, 0, 0}}, {{0, 1, 0}, {1, 0, 0}, {0, 0, 0}},
{{0, 0, 1}, {0, 0, 0}, {1, 0, 0}}, {{0, 0, 0}, {0, 2, 0}, {0, 0, 0}},
{{0, 0, 0}, {0, 0, 1}, {0, 1, 0}}, {{0, 0, 0}, {0, 0, 0}, {0, 0, 2}}}
*)


Edit: Sorry, I think I misread your question. If it's strictly upper,

Normal@Extract[#, Subsets[Range@Length@#, {2}]] &[u]

-

I think the following solution is easier to follow:

Join @@ Table[ u[[j,k]] , {j, NLevel}, {k, j + 1, NLevel}]


The Table part should be self-explanatory: it iterates through $a_{jk}$ for pairs $j < k$. However, it does not return a list of matrices. It returns a list of lists of matrices. These need to be joined together into a single list, which is what Join @@ does.

References:

-
Out of all three answers, this one almost works. What I mean is that I find I have to stick in a '1,' before 'j,k' in u[[j,k]],i.e.: Join @@ Table[ u[[1, j, k]], {j, NLevel}, {k, j + 1, NLevel}] // MatrixForm I don't know why the other solutions don't work (at least in my version of Mathematica, version 9.0) - but all I get when I execute the commands is {}. –  Mirella Jul 2 '14 at 15:02
Also, with the above modified solution, I get the correct matrices, but they are chopped up into separate columns, and they appear one beneath the other, not next to each other... –  Mirella Jul 2 '14 at 15:13