Vectorization of Conditions( inside Loop) - matlab

For faster implementation , I would like to vectorize below matlab code :
A=randi([0 1],20,20);
B=zeros(20);
for row = 5:15
for column = 5:15
if(A(row,column)==1 && (A(row+1,column)~=1 ||A(row,column+1)~=1))
B(row,column)=1;
end
end
end
How can I do that?

Just calculate all A(row, column)==1 and such at once for the whole loop, then use ordinary boolean operations. This should work just fine for the case you presented (though short-circuiting stuff operates a little bit differently, so this might not be always possible).
row = 5:15;
col = 5:15;
firstCond = A(row, col) == 1;
secondCond = A(row+1, col) ~= 1;
thirdCond = A(row, col+1) ~= 1;
allCond = firstCond & (secondCond | thirdCond);
B(row, col) = double(allCond);

I hope this one will work for you.
A=randi([0 1],20,20);
B=zeros(20);
z = find(A(5:15,5:15) == 1 & (A(6:16,5:15)~=1 | A(5:15,6:16)~=1));
y = B(5:15,5:15);
y(z) = 1;
B(5:15,5:15) = y;

Related

MATLAB — How to eliminate equal matrices that are created randomly inside loop?

The code segment I'm working on is given below:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
while i <= 10 %number of iterations
ind = randi([1 NphaseSteps],10,10);
inField{i} = phases(ind);
save('inField.mat', 'inField')
i = i + 1;
end
Now, what I want is to keep track of these randomly created matrices "inField{i}" and eliminate the ones that are equal to each other. I know that I can use "if" condition but since I'm new to programming I don't know how to use it more efficiently so that it doesn't take too much time. So, I need your help for a fast working program that does the job. Thanks in advance.
My actual code segment (after making the changes suggested by #bisherbas) is the following. Note that I actually want to use the variable "inField" inside the loop for every random created matrix and the loop advances only if the result satisfies a specific condition. So, I think the answer given by #bisherbas doesn't really eliminate the equal inField matrices before they are used in the calculation. This is, of course, my fault since I didn't declare that in the beginning.
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
nIterations = 5;
inField = cell(1,nIterations);
i = 1;
j = 1;
while i <= nIterations % number of iterations
ind = randi([1 NphaseSteps],TMsize,TMsize);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
j = j+1;
outField{i} = TM * inField{i};
outI = abs(outField{i}).^2;
targetIafter{i} = abs(outField{i}(focusX,focusY)).^2;
middleI = targetIafter{i} / 2;
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
if mod(j-1,10^6) == 0
fprintf('The number of random matrices tried is: %d million \n',(j-1)/10^6)
end
end
Additionally, I've written a seemingly long expression for my loop condition:
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
Here I want a maximum element at some point (focusX, focusY) in the outField matrix. So the first condition decides whether the focus point has the maximum element for the matrix. But I additionally want all other elements to be smaller than a specific number (middleI) and that's why the second part of the if condition is written. However, I'm not very comfortable with this second condition and I'm open to any helps.
Try this:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
inField = cell(1,NphaseSteps);
while i <= NphaseSteps %number of iterations
ind = randi([1 NphaseSteps],NphaseSteps,NphaseSteps);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
save('inField.mat', 'inField')
i = i + 1;
end
Read more on cellfun here:
https://www.mathworks.com/help/matlab/ref/cellfun.html

if statement to skip certain values in loop

I have a range of X and Y values, and I have a domain that I don't want to calculate the values of nodes within. I want to have an if statement within a loop in Matlab to skip these.
For example:
Range: X = [1:20] and Y = [1:20].
I want to ignore nodes in this range: X = [5:7] and Y = [12:14].
I think the code should be something like this:
for X=1:20
for Y=1:20
if X=5:7 & Y=12:14
return
end
% the operation here !
T(X,Y) = lab lab lab
end
end
However, I'm not sure how to properly write the condition.
You could use ismember or a combination of any and == for the condition, and continue is the command for skipping to the next loop index...
% ismember example
for X = 1:20
for Y = 1:20
if ismember( X, 5:7 ) && ismember( Y, 12:14 )
continue
end
% your loop operations
end
end
In this case, you could replace the if condition with
if any( X == 5:7 ) && any( Y == 12:14 )
I propose an alternative to Wolfie's solution to generate all indices in advance, and then apply a single loop:
Xvect = repmat(X, length(Y), 1);
Yvect = repmat(Y, 1, length(X));
Xvect = Xvect(:);
Yvect = Yvect(:);
Xis5to7 = (Xvect >= 5) & (Xvect <= 7);
Yis12to14 = (Yvect >= 12) & (Yvect <= 14);
XYcomb = ~(Xis5to7 & Yis12to14); % This is the range to exclude, negate it.
allX = Xvect(XYcomb);
allY = Yvect(XYcomb);
(par)for i = 1 : length(allX);
X = allX(i);
Y = allY(i);
Ltemp(i) = ...;
end
L(XYcomb) = Ltemp;
The advantage is to have combinations (allX, allY) displayed up front plus due to a single loop it is very suitable to make a parfor out of it.

Double loop for each column per row in matlab

The following code does what it should and works of one column.
%% Working loop
z = HongKongPrices(1:end,114);
zeros = false(size(z));
r = size(z,1);
c = size(z,2);
for i = 5:r
if z(i) == z(i-4) && z(i) == z(i-3)
zeros(i-3:i) = 1
end
end
z(zeros) = NaN
I am trying to execute the for-loop on a per column basis for HongKongPrices, however the following code fails (I am starting with three columns for time reasons).
%% Non workling loop
z = HongKongPrices(1:end,[80 85 115]);
zeros = false(size(z));
r = size(z,1);
c = size(z,2);
for k = 1:c
x = z(1:end,k)
for i = 5:r
if x(i) == x(i-4) && x(i) == x(i-3)
zeros(i-3:i) = 1
end
end
end
x(zeros) = NaN
You don't need the variable x at all. You can use logical indexing in you if statement. Instead of x(i), use x(i,k) and so on. Of course you have to do the same with zeros.
z = HongKongPrices(1:end,[80 85 115]);
zeros = false(size(z));
r = size(z,1);
c = size(z,2);
for k = 1:c
for i = 5:r
if z(i,k) == z(i-4,k) && z(i,k) == z(i-3,k);
zeros(i-3:i,k) = 1
end
end
end
z(zeros) = NaN;
PS: zeros is a Matlab function, so it would be better to use another variable name. Like this you won't be able to use the zeros function in your code.

Octave vectorize loop: for i = 1:size(v,1) v(i,y(i)) = 1; end

Assume:
v = zeros(4,3)
and
y = [1;2;1;3]
Any way to do the following:
for i = 1:size(v,1)
v(i,y(i)) = 1;
end
in a vectorized fashion?
For example, the following does not work:
v(:,y) = 1
TIA
Not sure if this fits your purposes:
v(full(sparse(1:size(v, 1), y, true))) = 1
This is a duplicate, I've seen it asked a few times for Matlab. But I can't find them now. Here is one way using linear indexing, which you can find using the sub2ind function:
v(sub2ind(size(v), (1:length(y))', y)) = 1
Breaking it down
colIndex = y;
rowIndex = 1:length(y);
linearIndex = sub2ind(size(v), rowIndex', colIndex);
v(linearIndex) = 1;

How to correct " Subscript indices must either be real positive integers or logicals." in Matlab in my code?

I am very new in Matlab. I made a for loop with i to m ,and j to n. I wrote this code to take a submatrix of a matrix but it keeps giving me this error
Subscript indices must either be real positive integers or logicals.
this is the code
for i=1:m,
for j = 1:n,
display(i);
display(j);
edgeil = 2;
edgeib = 2;
edgejb = 2;
edgejl = 2;
if((i-CenteriSE)< 0)
edgeib = CenteriSE - (-1)*(i-CenteriSE);
end
if((i+ CenteriSE)> m)
temp = i+ CenteriSE - m;
edgeil = CenteriSE - temp;
end
if((j-CenterjSE)< 0)
edgejb = CenterjSE- (-1)*(j-CenterjSE);
end
if((j+ CenterjSE)> n)
temp2 = j+ CenterjSE - n;
edgejl = CenterjSE - temp2;
end
bok1 = round(edgeib);
bok2 = round(edgeil);
bok3 = round(edgejb);
bok4 = round(edgejl);
display(bok1);
display(bok2);
if( (bok1 == round(bok1)) && (bok2 == round(bok2)) && (bok3 == round(bok3)) && (bok4 == round(bok4)))
B = circles(i-round(bok1):i+round(bok2),j-round(bok3):j+round(bok4));
end
I wrote that if statement and round s to correct it but it doesnt work. Please help me how can I fix this?
well, it's simple. first let's just remove all the clutter. you say CenteriSE=2, so this statement
edgeib = CenteriSE - (-1)*(i-CenteriSE); is equivalent to edgeib=i for i=1.
Now if you go to your last statement, B = circles(i-round(bok1):i+round(bok2),j-round(bok3):j+round(bok4));, you're doing i-round(bok1), which is just i-i=0 when i=1. Matlab's indexing start from 1, and this is why you get this error.