4D array with elements only on one side of the diagonal

Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
5 replies · 2K views
schniefen
Messages
177
Reaction score
4
TL;DR
Is it possible to initialize a 4D array with only elements on one side of the diagonal?
Given the parameters ##n## and ##m##, I'd like to initialize a ##n \times n ## 4D array where each entry is an ##m \times m ## matrix, and where each column of the matrix is an array of type numpy.linspace(0,1,m). Furthermore, I'd only like to have entries on the diagonal and above it, or only on the diagonal and below it. Is there a possible one-liner for this? The reason for this peculiarly shaped array is that I only need half of the matrices in the full array, but at the same time I’d like to keep the structure the array gives, i.e. the matrices on the second row belong to a “group” and this “group” consists of exactly as many matrices there are in the row of the array made up of only matrices on the diagonal and above or below it. The same goes for the columns.
 
Physics news on Phys.org
Which diagonal are you referring to?

It sounds like your structure is not so much a 4D array as a 2D array of matrices - ie a n x n array of elements, each of which is a m x m matrix.

Although not clear, it sounds like you mean the diagonal of the n x n array, rather than a diagonal of a m x m matrix, or a diagonal hyperplane of a 4D hyper-rectangle (which is a complicated beast).

If that's correct, it gives rise to another necessary clarification: what do you mean by "only ... have entries on the diagonal and above it". Do you mean to not have any matrices below the diagonal or perhaps to have all zeroes or NAs in those matrices? If you mean not to have any, I suspect the best structure for you is a nested list, as follows:
- item 1 is a n-element list of m x m matrices
- item 2 is a (n-1)-element list of m x m matrices
.
.
.
- item n is a 2-element list of m x m matrices (ie containing two such matrices)
- item n is a 1-element list of m x m matrices (ie containing one m x m matrix)

Item k of that top-level list is the k-th row of the top-level n x n array.

Is that the sort of thing you want?
 
  • Like
Likes   Reactions: schniefen
You are right, a matrix with matrices as elements. I said 4D because in numpy arrays one can specify up to 4 indices if I’m not wrong, and this will give one a matrix of matrices. And yes, the diagonal referred to is the diagonal of the matrix of matrices. If not having any entries below or above this diagonal is more efficient than having simply empty matrices, than a nested list is probably the way to go. Would this list then be a list of numpy arrays, and if so, how would one initialize that?
 
I guess numpy 4D arrays only gives a column vector of matrices, and not a matrix of matrices.
 
You can have an array of dimension [itex](\frac12n(n+1),m,m)[/itex], in which the [itex](i,j)[/itex]th matrix is at position [itex]j + \frac12i(i+1)[/itex] of the first index, where [itex]0 \leq j \leq i < n[/itex]. You can initialize this as follows:
Python:
>>> import numpy as np
>>> n = 3
>>> m = 2
>>> arr = np.zeros([int(n*(n+1)/2),m,m])
for i in range(0,int(n*(n+1)/2)):
   for j in range(0,m):
	   arr[i,:,j] = np.linspace(0,1,2)

	   
>>> arr
array([[[0., 0.],
        [1., 1.]],

       [[0., 0.],
        [1., 1.]],

       [[0., 0.],
        [1., 1.]],

       [[0., 0.],
        [1., 1.]],

       [[0., 0.],
        [1., 1.]],

       [[0., 0.],
        [1., 1.]]])

With a four-dimensional array you can still do
Python:
arr = np.zeros([n,n,m,m])
for i in range(0,n):
   for j in range(i,n):  # or range(0, i+1) for a lower triangular array
      for k in range(0, m):
         arr[i,j,:,k] = np.linspace(0,1,m)
 
  • Like
Likes   Reactions: schniefen
pasmith said:
With a four-dimensional array you can still do
Python:
arr = np.zeros([n,n,m,m])
for i in range(0,n):
   for j in range(i,n):  # or range(0, i+1) for a lower triangular array
      for k in range(0, m):
         arr[i,j,:,k] = np.linspace(0,1,m)
As you comment in the code, this is an upper triangular matrix of matrices. The matrices that only have 0 elements will not be used, but maybe having it this way is more efficient compared to constructing some kind of list of list of matrices with n-1 entries in the first list, n-2 matrices in the second, ...