How to reduce its execution time and why the value of e is a column vector?

I have the following piece of code.
clc;clear all;
c = 340;
f = 3400;
d = c/f/2;
T = 1;
Sig = 2;
M = 6;
N = 7;
theta = linspace(-60, 60, Sig);
p = 6;
SNR = 10;
Fc=[2*10^3:2*10^3/(Sig-1):5*10^3];
T_Vector=1/f;
p_N = [0:M/p:M*(N-1)/p];
p_M = [0:N:(M-1)*N];
P = union(p_N,p_M);
A = zeros(length(P),Sig);
SigVec = zeros(Sig,T);
for Q = 1:Sig
A(:,Q) = exp(-j*P'*2*pi*d*sin(theta(Q)*pi/180)*f/c);
SigVec(Q,:) = exp(1j*2*pi*Fc(Q).*T_Vector);
end
%%%%%%%%%%%%%%%%%%
% xo calculation
%%%%%%%%%%%%%%%%%%
xo = A*SigVec;
%%%%%%%%%%%%%%%%%%%%%%%%%%
% xe calculation
%%%%%%%%%%%%%%%%%%%%%%%%%
b=theta;
for Q = 1:Sig
Ae(:,Q) = exp(-j*P'*2*pi*d*sin(b(Q)*pi/180)*f/c);
SigVec_est(Q,:) = exp(1j*2*pi*Fc(Q).*T_Vector);
end
xe = Ae*SigVec_est;
%%%%%%%%%%%%%%%%%
% MSE
%%%%%%%%%%%%%%%%
e = mean(abs(xo-xe).^2,2)
I want to reduce its execution time. Further, I want a single value of e as zero but it gives me a column vector of e.

1 Comment

Can you replace "Just the for-loops here by using concept of vectorization?". Leave the rest of the code, just replace the two for-loops here.

Sign in to comment.

 Accepted Answer

you are taking the mean over the second dimension of a column vector (which has a second dimension of length 1)

1 Comment

Thanks a lot for your guidance dear Walter Roberson. Yes you are right. When I removed the 2 after comma, it gives single value of e now.

Sign in to comment.

More Answers (1)

@Sadiq Akbar: OK. See below.
Note that SigVec has T columns because of its pre-allocation, but that SigVec_est has one column because it was not pre-allocated in the original code. I've kept them like that (change T to something > 1 to see the difference).
clc;clear all;
c = 340;
f = 3400;
d = c/f/2;
T = 1;
Sig = 2;
M = 6;
N = 7;
theta = linspace(-60, 60, Sig);
p = 6;
SNR = 10;
Fc=[2*10^3:2*10^3/(Sig-1):5*10^3];
T_Vector=1/f;
p_N = [0:M/p:M*(N-1)/p];
p_M = [0:N:(M-1)*N];
P = union(p_N,p_M);
% A = zeros(length(P),Sig);
% SigVec = zeros(Sig,T);
%
% for Q = 1:Sig
% A(:,Q) = exp(-j*P'*2*pi*d*sin(theta(Q)*pi/180)*f/c);
% SigVec(Q,:) = exp(1j*2*pi*Fc(Q).*T_Vector);
% end
A = exp(-1j*P(:)*2*pi*d.*sin(theta*pi/180)*f/c);
SigVec = exp(1j*2*pi*Fc(:).*T_Vector*ones(1,T));
%%%%%%%%%%%%%%%%%%
% xo calculation
%%%%%%%%%%%%%%%%%%
xo = A*SigVec;
%%%%%%%%%%%%%%%%%%%%%%%%%%
% xe calculation
%%%%%%%%%%%%%%%%%%%%%%%%%
b=theta;
% for Q = 1:Sig
% Ae(:,Q) = exp(-j*P'*2*pi*d*sin(b(Q)*pi/180)*f/c);
% SigVec_est(Q,:) = exp(1j*2*pi*Fc(Q).*T_Vector);
% end
Ae = exp(-1j*P(:)*2*pi*d.*sin(b*pi/180)*f/c);
SigVec_est = exp(1j*2*pi*Fc(:).*T_Vector);
xe = Ae*SigVec_est;
%%%%%%%%%%%%%%%%%
% MSE
%%%%%%%%%%%%%%%%
e = mean(abs(xo-xe).^2,2)
e = 12×1
0 0 0 0 0 0 0 0 0 0

14 Comments

Thanks a lot dear Voss for your help. It works well but when I make a function from it and try to call it from my main function, then it gives the following error:
Error using *
Incorrect dimensions for matrix multiplication. Check that the number of columns in
the first matrix matches the number of rows in the second matrix. To operate on each
element of the matrix individually, use TIMES (.*) for elementwise multiplication.
Error in VectorizedByVoss (line 36)
xo = A*SigVec;
Error in mainVoss>@(b)VectorizedByVoss(b,u) (line 19)
[best,fmin,time]=fpa(10,0.8,200,dim,lb,ub,@(b)VectorizedByVoss(b,u));
Error in fpa (line 44)
Fitness(i)=fun(Sol(i,:));%--------------------(1)
Error in mainVoss (line 19)
[best,fmin,time]=fpa(10,0.8,200,dim,lb,ub,@(b)VectorizedByVoss(b,u));
Related documentation
All my files are in the attachment. You just run the m-file "mainVoss.m". And see the above error.
P = union(p_N,p_M);
p_N and p_M are built up from constants assigned inside the function, with values independent of the inputs (the inputs are b and u in this context.) So P will have a size independent of the inputs, but the details of the size could vary if you changed the constants. More duplicates could occur (or you could end up with non-integral values that might not exactly match due to round-off errors in calculations.) In this case it ends up having 12 elements.
theta=u;
You are passing in a row vector 1 x 6 so theta becomes 1 x 6
A = exp(-1j*P(:)*2*pi*d.*sin(theta*pi/180)*f/c);
With P being 1 x 12, P(:) is 12 x 1, giving A 12 rows. Meanwhile theta is the 1 x 6 passed in, so A will have 6 columns. A will therefore becomes 12 x 6.
Fc=[2*10^3:2*10^3/(Sig-1):5*10^3];
with Sig being assigned inside the function, Fc works out as being 1 x 8.
SigVec = exp(1j*2*pi*Fc(:).*T_Vector*ones(1,T));
T is 1, T_vector is a scalar. With Fc being 1 x 8, Fc(:) will be 8 x 1, and there is only a single column in the other variables in the calculation. So SigVec will be 8 x 1.
xo = A*SigVec;
So you are doing matrix multiplication between an 12 x 6 and an 8 x 1. There is no way to make that fit.
What size were you expecting as the output stored in xo ?
You run into exactly the same problems with xe = Ae*SigVec_est with Ae being the same size as A and SigVec_est being the same size as SigVec .
Thanks a lot dear Walter Roberson for your response. Actually xo depends on P. If P has 12 elements, then xo must be 12 x 1. Likewise A also depends on P and Sig. In short: if P has 12 elements and Sig is 2, then
A must be 12 x 2 and SigVec must be 2 x 1 so that xo is 12 x 1. Likewise if P has 12 elements and Sig=6, then A must be 12 x 6 and SigVec must be 6 x 1 so that xo is again 12 x 1.
But if we change M=4; and N=3 such that P has 6 elements,and if Sig is say fro example 10 i.e., Sig=10, then A must be 6 x 10 and SigVec must be 10 x 1 so that to get xo as 6 x 1. I hope its clear now.
In order for xo to become a column vector with the same number of entries as P, then Fc must have the same number of rows as the number of columns in SigVec . So you need to make your SigVec have 6 columns. Consider using linspace() instead of the colon operator.
Thanks a lot dear Walter Roberson for your help. I did the change and it worked well. But the problem is that now it returns a wrong estimated vector. I expect from it that it should return a simlar estimated vector exactly like u or if not exactly u, then nearly equal to u. But it doesn't do so. You run it yourself. All are in the attachment here.You just run "mainVoss.m" and check the command window for u and two1. u is my desired vector and two1 is the estimated vector. Check it yourself.
I did not expect it to work, as it is not at all clear to me how the columns of the u input just happen to correspond to the frequencies you are building in SigVec . Like if that is a given fact, that the different u entries correspond to different frequency, then I would have expected that the function would take an additional parameter that is the frequency vector.
Thanks for your guidance dear Walter Roberson. I visited the link you shared. I studued the whole page. I understood but very little as I am not too much expert in Matlab. That says (according to my understanding) that if you want to find more parameters than one, then you need to define the anonymous function. Yes, I want to find more than one parameters e.g., if u=[-30 30], then it means I have to estimate both these two i.e., -30 and 30. Likewise if u=[-15 15 -20 20], then it means I have to estimate all these 4 parameters i.e., -15, 15, -20 and 20. Likewise if u=[-20 20 -35 35 -40 40], then I have to estimate all these 6 parameters and so on. But if my function is not anonymous like they mention, then how can we make it anonymous function? Please help me in that.
If you have defined something in a non-anonymous function, using a function statement, then you can create a non-anonymous function handle to it by prefixing the function name with @ . Or you can create an anonymous function from it by using @(varargin)FunctionName(varargin{:})
For example,
handle_to_anonyous_defined_inline = @(x) sin(x.^2)
handle_to_non_anonymous = @non_anonymous
handle_to_non_anonymous_made_anonymous = @(varargin) non_anonymous(varargin{:});
function y = non_anonymous(x)
y = sin(x.^2);
end
What I am suggesting is something like
Fc_start = 2*10^3;
Fc_end = 5*10^3;
Fc = linspace(Fc_start, Fc_end, length(u));
for n=1:Runs %------------(2)
nn=nn+1;
[best,fmin,time]=fpa(10,0.8,200,dim,lb,ub,@(b)VectorizedByVoss(b,u,Fc));
and
function e = VectorizedByVoss(b,u,Fc)
and delete
Fc=[2*10^3:2*10^3/(Sig-1):5*10^3];
In this way, you could guarantee that your frequency array has the same number of elements as u has.
But possibly what you need is in terms of the size of P. You could pre-calculate P in mainVoss and calculate Fc in terms of the size of P, and pass the two of them together into VectorizedByVoss, using the same technique I show above.
Thanks a lot dear Walter Roberson for your kind guidance. Yes, when I did your suggested changes, now it works well. But again, sometimes it estimates the values correctly and sometimes wrongly. Let me share the code that I changed according to your suggestionsThe codes are here in the attachment.
You just run the 'mainVoss.m' several times, so you will observe that the estimated vector two1 displayed in the command window is sometimes identical to u and sometimes not. Also when I increase the number of elements in u, the chances of correctly estimating the estimated vector two1 decreases. So what else can we do so that it estimates it correctly.
If you could guarantee that the estimated values matched the exact values, then the calculation would not be an estimate and would instead be a different (possibly shorter) way of calculating the exact values.
Unless you are generating an error message, then the problem is now one of verifying that you are using the correct mathematics for your calculations. Which is not something that I get involved with.
Ok thank you very much dear Walter Roberson for your kind responses and help.
Thank you also dear Voss for your responses and help.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!