# 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}]


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:

• I agree. It's much easier to see what is going on here. In my case, I find neverthess that I need to add a '1,' before 'j,k' in u[[j,k]], i.e.: Join @@ Table[ u[[1, j, k]], {j, NLevel}, {k, j + 1, NLevel}] // MatrixForm, otherwise I get an error. I think this has to do with the extra pair of brackets that Mathematica likes to put around P and u. – Mirella Oct 21 '15 at 18:05

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]