How can I define a 3d array from a 2d array that depends on a parameter?

Question:

I have a matrix with 2 dimensions

M = np.array([[0.5+t, 1, 1],
              [0.5, 0.5, t],
              [0.5, 1-t, 0.5]])

I want to compute some properties of this matrix for several values of $t$. I could do it witn a for loop but I was wondering if there’s a way of doing it without a loop. For example creating a 3d array where every slide of that array is a 2d array containg the matrix M for a given t.

The loop implementation will we something like this.

import numpy as np

def M(t: float):
    return np.array([[0.5+t, 1, 1], [0.5, 0.5, t], [0.5, 1-t, 0.5]])

t_vec = np.linspace(0, 1, num=100)

norm = np.zeros_like(t_vec)
for i, t in enumerate(t_vec):
    matrix = M(t)
    norm[i] = np.linalg.norm(matrix)

In this case I wanted to compute the 2 norm of the matrix an store all the values in an array.

Asked By: Pablo Gonzalez

||

Answers:

You can create base matrix without t values and then add t values ‘mask’ multiplied by the values you want to use. For example:

M_base = np.array(
    [[0.5, 1,   1  ],
     [0.5, 0.5, 0  ],
     [0.5, 1,   0.5]])
t = np.array(
    [[ 1,  0,  0],
     [ 0,  0,  1],
     [ 0, -1,  0]])

t_values = np.linspace(0, 1, num=100)

M = M_base + t*t_values[:, np.newaxis, np.newaxis]

norm = np.linalg.norm(M, axis=(1, 2))
Answered By: maciek97x

I would recommend to use 2 arrays, one for M, one for t:

M = np.array([[0.5, 1.0, 1.0],
              [0.5, 0.5, 0.0],
              [0.5, 1.0, 0.5]])
t =  np.array([[1,  0, 0],
               [0,  0, 1],
               [0, -1, 0]])

Then:

M+t

M+t*2

# etc.

Or, in a vectorial way:

t_vec = np.linspace(0, 1, num=100)

out = M+t*t_vec[:,None,None]

norm = np.linalg.norm(M, axis=(1, 2))
Answered By: mozway

The others answers do what you want to do. I put this answer only to have a faster way.

Let’s say you have two matrix:

N = np.array([[0.5, 1.0, 1.0],
              [0.5, 0.5, 0.0],
              [0.5, 1.0, 0.5]])
T = np.array([[1,  0, 0],
              [0,  0, 1],
              [0, -1, 0]])

Then, for given t, M = N + t * T.

The numpy.linalg.norm(M) can be described as numpy.sqrt(numpy.sum(M**2)). Therefore, to compute the norm for many t I would do:

t_vec = np.linspace(0, 1, 100)
sumNT = np.sum(N*T)
sumN2 = np.sum(N**2)
sumT2 = np.sum(T**2)
# Once M**2 = (N+t*T)**2 = N**2 + 2*t * N*T + t**2 * T**2
sumM2 = sumN2 + 2*t_vec * sumNT + t_vec**2 * sumT2 
norm = np.sqrt(sumM2)
Answered By: Carlos Adir
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.