Gze
Gze

Reputation: 408

On the division of each array by its norm in Python

Suppose I have a matrix H of size 4 x 4, and a vector y of size 4 x 1, I need to get the results of (h'/norm(h, 'fro')) * y in Python, where h is the columns of matrix H and h' is the transpose of every column of matrix H. For example in MATLAB I did it straightforwardly as below:

clear all 
clc 

H = [0.0937 + 1.5453i,  -0.1910 - 0.3741i,   1.4420 + 0.6273i,   0.0518 - 0.4653i; ...
    0.8537 + 0.9905i,  -0.2910 + 0.0131i,   0.2993 - 0.5929i,   0.6426 + 0.4098i;...
    0.3722 - 0.3470i,   0.0449 - 0.2985i,  -0.7595 - 0.1346i,  -1.2782 + 0.1877i; ...
    -0.8256 + 0.5255i,  -0.5318 - 0.0624i,  -0.5467 - 0.4118i,   0.0772 + 0.9888i]; 
y = [0.1037 + 0.1302i; 0.3676 - 0.0198i; 0.2380 + 0.2824i; 0.0557 - 0.4222i];
re = []; 
for ii = 1 : size(H,2)
    nn = H(:,ii);
    tt = (nn'/norm(nn,'fro') * y)
    re = [re tt]
end 

But in Python it gives an error! I gave a try as below:

import numpy as np

h = np.array([[0.0937 + 1.5453j,  -0.1910 - 0.3741j,   1.4420 + 0.6273j,   0.0518 - 0.4653j],
   [0.8537 + 0.9905j,  -0.2910 + 0.0131j,  0.2993 - 0.5929j,   0.6426 + 0.4098j],
  [0.3722 - 0.3470j,   0.0449 - 0.2985j,  -0.7595 - 0.1346j,  -1.2782 + 0.1877j],
  [-0.8256 + 0.5255j,  -0.5318 - 0.0624j,  -0.5467 - 0.4118j,   0.0772 + 0.9888j]])

y = np.array([[0.1037 + 0.1302j], [0.3676 - 0.0198j], [0.2380 + 0.2824j], [0.0557 - 0.4222j]])

n = 3
re= np.zeros((1, 4), dtype=np.complex)
for ii in range(n):
    re[:, ii] = ((np.linalg.pinv(h[:, ii])).transpose() / (np.linalg.norm(np.linalg.pinv(h[:, ii]), 'fro'))).dot(y)

But I get an error when running the last command of re[:, ii] = ((np.linalg.pinv(h[:, ii])).transpose() / (np.linalg.norm(np.linalg.pinv(h[:, ii]), 'fro'))).dot(y), it says:

numpy.linalg.LinAlgError: 1-dimensional array given. Array must be at least two-dimensional

Upvotes: 0

Views: 659

Answers (2)

gboffi
gboffi

Reputation: 25043

I executed your Matlab™ code to get these values for re :

[0.098760-0.009564i, -0.316010+0.408531i, 0.139199+0.203590i, -0.264498-0.323802i]

This Python/Numpy code

import numpy as np
from numpy.linalg import norm
H = np.array(([ 0.0937 + 1.5453j,  -0.1910 - 0.3741j,   1.4420 + 0.6273j,   0.0518 - 0.4653j], 
              [ 0.8537 + 0.9905j,  -0.2910 + 0.0131j,   0.2993 - 0.5929j,   0.6426 + 0.4098j], 
              [ 0.3722 - 0.3470j,   0.0449 - 0.2985j,  -0.7595 - 0.1346j,  -1.2782 + 0.1877j], 
              [-0.8256 + 0.5255j,  -0.5318 - 0.0624j,  -0.5467 - 0.4118j,   0.0772 + 0.9888j]))                         

y = np.array([0.1037 + 0.1302j, 0.3676 - 0.0198j, 0.2380 + 0.2824j, 0.0557 - 0.4222j])                                  

np.conjugate(H/norm(H, axis=0)).T@y

gives

array([ 0.09875966-0.00956369j, -0.31600998+0.40853066j,  0.13919918+0.20358966j, -0.26449838-0.32380165j])

I think that the main issue here is that transposing a complex array in Matlab™ gives you the transpose conjugate, transposing the same array in Numpy does not perform the conjugation. Another issue is that a mat-vec dot product (the @ operator) is row-column, while you need col-col, so we need a transposition too.

Upvotes: 3

Nils
Nils

Reputation: 930

Maybe this will do what you want:

Also in your code n should be equal to 4:

n = 4
for ii in range(n):
    tmp1 = (h[:, ii]).transpose()
    tmp2 = (np.linalg.norm(h[:, ii].transpose()))
    re[:, ii] = (tmp1 / tmp2).dot(y)

Please see if it will achieve the same results as in matlab. I fixed your errors, but I am not sure if that is the correct calculation.

I also deleted the fro from calculating the norm as linalg.norm() is using it by default and specifically adding it causes some trouble. For more details see here:

https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.norm.html

Upvotes: 1

Related Questions