Basic for loop in Matlab - matlab

I have a simple question in Matlab. How can I creat a for loop that will choose the value from a vector for which the result is smallest and write the chosen value from vector into .txt file? For example , if I have:
T = 100;
W = 20;
h = [h1 h2 h3 ... ];
y = 2*T*W/h;
I want to create loop that will search vector h for a value that will provide minimum value of y and write the chosen h into .txt file.
Any help would be greatly appreciated. Thanks

For loop:
min_y = 2*T*W/h(1);
h_chosen = 1;
for i = 2:length(h)
if min_y > 2*T*W/h(i)
min_y = 2*T*W/h(i);
h_chosen = i;
end
end
Much faster than for-loop:
[~, idx] = min(arrayfun(#(i) 2*T*W/h(i), 1:length(h)));
h_chosen = h(idx);
Write to .txt file: (http://www.mathworks.com/help/matlab/ref/fprintf.html)
fileID = fopen('min_h.txt','w');
fprintf(fileID, '%d\n', h_chosen);

Related

MATLAB to Scilab conversion: mfile2sci error "File contains no instruction"

I am very new to Scilab, but so far have not been able to find an answer (either here or via google) to my question. I'm sure it's a simple solution, but I'm at a loss. I have a lot of MATLAB scripts I wrote in grad school, but now that I'm out of school, I no longer have access to MATLAB (and can't justify the cost). Scilab looked like the best open alternative. I'm trying to convert my .m files to Scilab compatible versions using mfile2sci, but when running the mfile2sci GUI, I get the error/message shown below. Attached is the original code from the M-file, in case it's relevant.
I Searched Stack Overflow and companion sites, Google, Scilab documentation.
The M-file code follows (it's a super basic MATLAB script as part of an old homework question -- I chose it as it's the shortest, most straightforward M-file I had):
Mmax = 15;
N = 20;
T = 2000;
%define upper limit for sparsity of signal
smax = 15;
mNE = zeros(smax,Mmax);
mESR= zeros(smax,Mmax);
for M = 1:Mmax
aNormErr = zeros(smax,1);
aSz = zeros(smax,1);
ESR = zeros(smax,1);
for s=1:smax % for-loop to loop script smax times
normErr = zeros(1,T);
vESR = zeros(1,T);
sz = zeros(1,T);
for t=1:T %for-loop to carry out 2000 trials per s-value
esr = 0;
A = randn(M,N); % generate random MxN matrix
[M,N] = size(A);
An = zeros(M,N); % initialize normalized matrix
for h = 1:size(A,2) % normalize columns of matrix A
V = A(:,h)/norm(A(:,h));
An(:,h) = V;
end
A = An; % replace A with its column-normalized counterpart
c = randperm(N,s); % create random support vector with s entries
x = zeros(N,1); % initialize vector x
for i = 1:size(c,2)
val = (10-1)*rand + 1;% generate interval [1,10]
neg = mod(randi(10),2); % include [-10,-1]
if neg~=0
val = -1*val;
end
x(c(i)) = val; %replace c(i)th value of x with the nonzero value
end
y = A*x; % generate measurement vector (y)
R = y;
S = []; % initialize array to store selected columns of A
indx = []; % vector to store indices of selected columns
coeff = zeros(1,s); % vector to store coefficients of approx.
stop = 10; % init. stop condition
in = 0; % index variable
esr = 0;
xhat = zeros(N,1); % intialize estimated x signal
while (stop>0.5 && size(S,2)<smax)
%MAX = abs(A(:,1)'*R);
maxV = zeros(1,N);
for i = 1:size(A,2)
maxV(i) = abs(A(:,i)'*R);
end
in = find(maxV == max(maxV));
indx = [indx in];
S = [S A(:,in)];
coeff = [coeff R'*S(:,size(S,2))]; % update coefficient vector
for w=1:size(S,2)
r = y - ((R'*S(:,w))*S(:,w)); % update residuals
if norm(r)<norm(R)
index = w;
end
R = r;
stop = norm(R); % update stop condition
end
for j=1:size(S,2) % place coefficients into xhat at correct indices
xhat(indx(j))=coeff(j);
end
nE = norm(x-xhat)/norm(x); % calculate normalized error for this estimate
%esr = 0;
indx = sort(indx);
c = sort(c);
if isequal(indx,c)
esr = esr+1;
end
end
vESR(t) = esr;
sz(t) = size(S,2);
normErr(t) = nE;
end
%avsz = sum(sz)/T;
aSz(s) = sum(sz)/T;
%aESR = sum(vESR)/T;
ESR(s) = sum(vESR)/T;
%avnormErr = sum(normErr)/T; % produce average normalized error for these run
aNormErr(s) = sum(normErr)/T; % add new avnormErr to vector of all av norm errors
end
% just put this here to view the vector
mNE(:,M) = aNormErr;
mESR(:,M) = ESR;
% had an 'end' placed here, might've been unmatched
mNE%reshape(mNE,[],Mmax)
mESR%reshape(mESR,[],Mmax)]
figure
dimx = [1 Mmax];
dimy = [1 smax];
imagesc(dimx,dimy,mESR)
colormap gray
strESR = sprintf('Average ESR, N=%d',N);
title(strESR);
xlabel('M');
ylabel('s');
strNE = sprintf('Average Normed Error, N=%d',N);
figure
imagesc(dimx,dimy,mNE)
colormap gray
title(strNE)
xlabel('M');
ylabel('s');
The command used (and results) follow:
--> mfile2sci
ans =
[]
****** Beginning of mfile2sci() session ******
File to convert: C:/Users/User/Downloads/WTF_new.m
Result file path: C:/Users/User/DOWNLO~1/
Recursive mode: OFF
Only double values used in M-file: NO
Verbose mode: 3
Generate formatted code: NO
M-file reading...
M-file reading: Done
Syntax modification...
Syntax modification: Done
File contains no instruction, no translation made...
****** End of mfile2sci() session ******
To convert the foo.m file one has to enter
mfile2sci <path>/foo.m
where stands for the path of the directoty where foo.m is. The result is written in /foo.sci
Remove the ```` at the begining of each line, the conversion will proceed normally ?. However, don't expect to obtain a working .sci file as the m2sci converter is (to me) still an experimental tool !

"Variable in a parfor cannot be classified" MATLAB

I am trying to convert my code over to run with parfor, since as it is it takes a long time to run on its own. However I keep getting this error. I have search around on the website and have read people with similar problems, but none of those answers seem to fix my problem. This is my code:
r = 5;
Mu = 12.57e-9;
Nu = 12e6;
I = 1.8;
const = pi*Nu*Mu*r*I;
a = 55;
b = 69;
c = 206;
[m,n,p] = size(Lesion_Visible);
A = zeros(m,n,p);
parpool(2)
syms k
parfor J = 1:m
for I = 1:n
for K = 1:p
if Lesion_Visible(J,I,K) ~= 0
Theta = atand((J-b)/(I-a));
Rho = abs((I-a)/cosd(Theta))*0.05;
Z = abs(c-K)*0.05;
E = vpa(const*int(abs(besselj(0,Rho*k)*exp(-Z*k)*besselj(0,r*k)),0,20),5);
A (J,I,K) = E;
end
end
end
end
I'm trying to calculate the electric field in specific position on an array and matlab give me the error "The variable A in a parfor cannot be classified". I need help. Thanks.
As classification of variables in parfor loop is not permitted, you should try to save the output of each loop in a variable & then save the final output into the desired variable, A in your case!
This should do the job-
parfor J = 1:m
B=zeros(n,p); %create a padding matrix of two dimension
for I = 1:n
C=zeros(p); %create a padding matrix of one dimension
for K = 1:p
if Lesion_Visible(J,I,K) ~= 0
Theta = atand((J-b)./(I-a));
Rho = abs((I-a)./cosd(Theta))*0.05;
Z = abs(c-K).*0.05;
E = vpa(const.*int(abs(besselj(0,Rho.*k).*exp(-Z.*k).*besselj(0,r.*k)),0,20),5);
C(K) = E; %save output of innnermost loop to the padded matrix C
end
end
B(I,:)=C; % save the output to dim1 I of matrix B
end
A(J,:,:)=B; save the output to dim1 J of final matrix A
end
Go through the following for better understanding-
http://www.mathworks.com/help/distcomp/classification-of-variables-in-parfor-loops.html
http://in.mathworks.com/help/distcomp/sliced-variable.html

Reading multiple text files with two columns in MATLAB

I want to read multiple text files. Each text file has two columns. All the two columns of all text files have same rows. I want to know, in MATLAB, how to read each text file then read each column one by one, subtract one column data from the other column and then read the next file and so on. I have written the following code but I am missing some step in the code. I appreciate your support. Thank you all.
for k = 1:9
filename = sprintf('Data_F_Ind000%d.txt',k);
a(:,k) = load(filename);
x = a(:,1)};
y = a(:,2);
z = x - y;
end
data = cell(9,1) ;
diff_data = cell(9,1) ;
for k = 1:9
filename = sprintf('Data_F_Ind000%d.txt',k);
a = load(filename);
data{i} = a ;
x = a(:,1)};
y = a(:,2);
diff_data{i} = x - y;
end
You can do this multiple ways. I imagine that you want to do something with z instead of just throwing it away every time. I would do this by taking advantage of an access pattern.
numFiles = 9;
numRows = ....; % not required but used to preallocate the a matrix
pattern = 1:2:numFiles * 2; % create a vector of 1 3 5 ...
a = zeros(numRows, numFiles * 2);
z = zeros(numRows, numFiles);
for k = 1:numFiles
fileName = sprintf('Data_F_Ind000%d.txt, 'k');
a(:,pattern(k):pattern(k) + 1) = load(fileName);
z(:,k) = a(:,pattern(k)) - a(:,pattern(k) + 1);
end
This is untested and is clearly missing some data but the intent should be clear. You don't need to preallocate variables but it helps speed calculations so I try to do it whenever possible.

How to plot a function of multiple variables in Matlab?

I'm trying to figure out a way to make a plot of a function in Matlab that accepts k parameters and returns a 3D point. Currently I've got this working for two variables m and n. How can I expand this process to any number of parameters?
K = zeros(360*360, number);
for m = 0:5:359
for n = 1:5:360
K(m*360 + n, 1) = cosd(m)+cosd(m+n);
K(m*360 + n, 2) = sind(m)+sind(m+n);
K(m*360 + n, 3) = cosd(m)+sind(m+n);
end
end
K(all(K==0,2),:)=[];
plot3(K(:,1),K(:,2),K(:,3),'.');
end
The code you see above is for a similar problem but not exactly the same.
Most of the time you can do this in a vectorized manner by using ndgrid.
[M, N] = ndgrid(0:5:359, 1:5:360);
X = cosd(M)+cosd(M+N);
Y = sind(M)+sind(M+N);
Z = cosd(M)+sind(M+N);
allZero = (X==0)&(Y==0)&(Z==0); % This ...
X(allZero) = []; % does not ...
Y(allZero) = []; % do ...
Z(allZero) = []; % anything.
plot3(X,Y,Z,'b.');
A little explanation:
The call [M, N] = ndgrid(0:5:359, 1:5:360); generates all combinations, where M is an element of 0:5:359 and N is an element of 1:5:360. This will be in the form of two matrices M and N. If you want you can reshape these matrices to vectors by using M = M(:); N = N(:);, but this isn't needed here.
If you were to have yet another variable, you would use: [M, N, P] = ndgrid(0:5:359, 1:5:360, 10:5:1000).
By the way: The code part where you delete the entry [0,0,0] doesn't do anything here, because this value doesn't appear. I see you only needed it, because you were allocating a lot more memory than you actually needed. Here are two versions of your original code, that are not as good as the ndgrid version, but preferable to your original one:
m = 0:5:359;
n = 1:5:360;
K = zeros(length(m)*length(n), 3);
for i = 1:length(m)
for j = 1:length(n)
nextRow = (i-1)*length(n) + j;
K(nextRow, 1) = cosd(m(i)) + cosd(m(i)+n(j));
K(nextRow, 2) = sind(m(i)) + sind(m(i)+n(j));
K(nextRow, 3) = cosd(m(i)) + sind(m(i)+n(j));
end
end
Or simpler, but a bit slower:
K = [];
for m = 0:5:359
for n = 1:5:360
K(end+1,1:3) = 0;
K(end, 1) = cosd(m)+cosd(m+n);
K(end, 2) = sind(m)+sind(m+n);
K(end, 3) = cosd(m)+sind(m+n);
end
end

What is the fastest way of appending an element to an array?

This is a follow-up question to How to append an element to an array in MATLAB? That question addressed how to append an element to an array. Two approaches are discussed there:
A = [A elem] % for a row array
A = [A; elem] % for a column array
and
A(end+1) = elem;
The second approach has the obvious advantage of being compatible with both row and column arrays.
However, this question is: which of the two approaches is fastest? My intuition tells me that the second one is, but I'd like some evidence for or against that. Any idea?
The second approach (A(end+1) = elem) is faster
According to the benchmarks below (run with the timeit benchmarking function from File Exchange), the second approach (A(end+1) = elem) is faster and should therefore be preferred.
Interestingly, though, the performance gap between the two approaches is much narrower in older versions of MATLAB than it is in more recent versions.
R2008a
R2013a
Benchmark code
function benchmark
n = logspace(2, 5, 40);
% n = logspace(2, 4, 40);
tf = zeros(size(n));
tg = tf;
for k = 1 : numel(n)
x = rand(round(n(k)), 1);
f = #() append(x);
tf(k) = timeit(f);
g = #() addtoend(x);
tg(k) = timeit(g);
end
figure
hold on
plot(n, tf, 'bo')
plot(n, tg, 'ro')
hold off
xlabel('input size')
ylabel('time (s)')
leg = legend('y = [y, x(k)]', 'y(end + 1) = x(k)');
set(leg, 'Location', 'NorthWest');
end
% Approach 1: y = [y, x(k)];
function y = append(x)
y = [];
for k = 1 : numel(x);
y = [y, x(k)];
end
end
% Approach 2: y(end + 1) = x(k);
function y = addtoend(x)
y = [];
for k = 1 : numel(x);
y(end + 1) = x(k);
end
end
How about this?
function somescript
RStime = timeit(#RowSlow)
CStime = timeit(#ColSlow)
RFtime = timeit(#RowFast)
CFtime = timeit(#ColFast)
function RowSlow
rng(1)
A = zeros(1,2);
for i = 1:1e5
A = [A rand(1,1)];
end
end
function ColSlow
rng(1)
A = zeros(2,1);
for i = 1:1e5
A = [A; rand(1,1)];
end
end
function RowFast
rng(1)
A = zeros(1,2);
for i = 1:1e5
A(end+1) = rand(1,1);
end
end
function ColFast
rng(1)
A = zeros(2,1);
for i = 1:1e5
A(end+1) = rand(1,1);
end
end
end
For my machine, this yields the following timings:
RStime =
30.4064
CStime =
29.1075
RFtime =
0.3318
CFtime =
0.3351
The orientation of the vector does not seem to matter that much, but the second approach is about a factor 100 faster on my machine.
In addition to the fast growing method pointing out above (i.e., A(k+1)), you can also get a speed increase from increasing the array size by some multiple, so that allocations become less as the size increases.
On my laptop using R2014b, a conditional doubling of size results in about a factor of 6 speed increase:
>> SO
GATime =
0.0288
DWNTime =
0.0048
In a real application, the size of A would needed to be limited to the needed size or the unfilled results filtered out in some way.
The Code for the SO function is below. I note that I switched to cos(k) since, for some unknown reason, there is a large difference in performance between rand() and rand(1,1) on my machine. But I don't think this affects the outcome too much.
function [] = SO()
GATime = timeit(#GrowAlways)
DWNTime = timeit(#DoubleWhenNeeded)
end
function [] = DoubleWhenNeeded()
A = 0;
sizeA = 1;
for k = 1:1E5
if ((k+1) > sizeA)
A(2*sizeA) = 0;
sizeA = 2*sizeA;
end
A(k+1) = cos(k);
end
end
function [] = GrowAlways()
A = 0;
for k = 1:1E5
A(k+1) = cos(k);
end
end