MATLAB - Condition to do something only once every x number of loops - matlab

I am trying to change the value of z by +1 every 750th, 1500th, 2250th,...,etc loop and this is what I have written:
len = 1500000;
y = 750;
z = 1;
for i = 1:len
if (i == [y.*(1:2000)])
z = z + 1;
end
end
Why is the value of z not changing? Can someone tell me what's wrong with my if statement please?

MATLAB only considers an array to be true if all elements are true. So with that in mind, if we look at your conditional for your if statement
i == (y .* (1:2000))
What this returns is an array of 2000 values where they are either all false (in the case where i isn't a multiple of y) and all false except for one true value when it is. Even when there is one true, this still evaluates to false and your if statement will never be evaluated.
A better way to do this is to use mod to check if a given i is a multiple of y
if mod(i, y) == 0
z = z + 1;
end
However, if the only contents of your loop are what you have shown, then you can simply omit the iterations that you don't care about
for i = y:y:len
z = z + 1;
end
If you actually do want to compare the array as you showed though, you'd be best to compute y .* 1:2000 outside of the loop and then use ismember to see if i is in the array
tmp = y .* (1:2000);
for i = 1:len
if ismember(i, tmp)
z = z + 1;
end
end

Related

Matlab: Plotting the conditions output of symbolic solve

I have a loop where I symbolically solve for intervals. Each iteration of the loop gives exactly one interval, for example:
v=[x+1,-x+4];
v = v > 0;
sol=solve(v,x,'ReturnConditions',true);
cond = sol.conditions;
ezplot(cond)
Would I be able to plot the 1x1 symbolic array " cond = -1 < x & x < 4 " at a y value of my choosing? When I use ezplot it always plots at y=1.
Maybe by multiplying the cond by the y value you wish to use. In that case the title must be changed to match the original condition, cond by casting it as a string. In the example below I plotted the condition/region at a height of y = 2. To implement this in the for-loop I'd probably make a y a vector a retrieve one value/cell upon each iteration.
syms x
v = [x+1,-x+4];
v = v > 0;
sol = solve(v,x,'ReturnConditions',true);
cond = sol.conditions;
y = 2;
ezplot(y*cond);
ylim([0 y*1.2]);
title(string(cond));

Plotting the Impulsefunction

so I'm new to Matlab and had to draw the Impulsefunction with y(n) is only 1 if n == 3, else 0. The following code works:
n = -5:5;
f = n; % allocate f
for i = 1 : length(n)
f(i) = dd1(n(i)-3);
end
stem(n, f);
function y = dd1(n)
y = 0;
if n == 0
y = 1;
end
end
But I feel like it's to complicated, so I tried the following:
n = -5:5
stem(n, fo)
function y = fo(n)
y = 0
if n == 3
y=1
end
end
This returns
Not enough input arguments.
Error in alternative>fo (line 5)
if n == 3
Error in alternative (line 2)
stem(n, fo)
I feel like I'm missing something trivial here.
if is no vector-wise operation but expects a single boolean (or at least a scalar that it can cast to a boolean).
But you can do this vector-wise:
lg = n == 3;
This produces a logical (MATLAB's name for boolean) array (because n is an array and not a vector), which is true where n is equal (==) to three. So you don't need a function, because you can make use of MATLAB's ability to work with vectors and arrays implicitly.
(for your code it would be f = (n-3) == 3)
A last hint: if you have a state-space system (ss-object), you can use the function step to get the step-response as a plot.

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.

Finding smallest value for parameterised answer that satisfies condition

I want to find the smallest integer l that satisfies l^2 >= x, and mod(l,2)=0.
In the following example x=75, and hence l=10, since the previous even number doesn't fulfil the inequation: 8^2 <= 75 <= 10^2
I have tried this (ignoring the even-number requirement, which I can't to work):
syms l integer
eqn1 = l^2 >= 75;
% eqn2 = mod(l,2) == 0;
[sol_l, param, cond] = solve(eqn1, l, 'ReturnConditions', true);
But this does not give me anything helpful directly:
sol_l =
k
param =
k
cond =
(75^(1/2) <= k | k <= -75^(1/2)) & in(k, 'integer')
I would like to evaluate the conditions on the parameter and find the smallest value that satisfies the conditions.
Also, I would like to enforce the mod(l,2)=0 condition somehow, but I don't seem to get that work.
Using the solve for this task is like using a cannon to kill a mosquito. Actually, the answer of Lidia Parrilla is good and fast, although it can be simplified as follows:
l = ceil(sqrt(x));
if (mod(x,2) ~= 0)
l = l + 1;
end
% if x = 75, then l = 10
But I would like to point out something that no one else noticed. The condition provided by the solve function for l^2 >= 75 is:
75^(1/2) <= k | k <= -75^(1/2)
and it's absolutely correct. Since l is being raised to the power of 2, and since a negative number raised to the power of 2 produces a positive number, the equation will always have two distinct solutions: a negative one and a positive one.
For x = 75, the solutions will be l = 10 and l = -10. So, if you want to find the smallest number (and a negative number is always smaller than a positive one), the right solution will be:
l = ceil(sqrt(x));
if (mod(x,2) ~= 0)
l = l + 1;
end
l = l * -1;
If you want to return both solutions, the result will be:
l_pos = ceil(sqrt(x));
if (mod(x,2) ~= 0)
l_pos = l_pos + 1;
end
l_neg = l_pos * -1;
l = [l_neg l_pos];
I guess the easiest solution without employing the inequality and solve function would be to find the exact solution to your equation l^2 >= x, and then finding the next even integer. The code would look like this:
x = 75;
y = ceil(sqrt(x)); %Ceil finds the next bigger integer
if(~mod(y,2)) %If it's even, we got the solution
sol = y;
else %If not, get the next integer
sol = y+1;
end
The previous code gives the correct solution to the provided example (x = 75; sol = 10)

MATLAB replacing some elements from a vector

If i have a vector, lets say L=[10;10;10;11;11;13;13] which is associated to another vector X=[1;6;65;34;21;73;14] and I want to create a third vector, Z, with almost all the elements in X, but just replacing a 0 in X when the element (i,j) from L changes. Lets say that the result that I want should look like this Z=[1;6;65;0;21;0;14]
Any ideas how to solve this?
I would be really thankful :)
That's easy:
X = [1;6;65;34;21;73;14];
L = [10;10;10;11;11;13;13];
Z = X;
ind = [false; diff(L)~=0]; %// logical index of values to be set to 0
Z(ind) = 0;
This works by computing a logical index ind = [false; diff(L)~=0] of the elements where a change has ocurred. The initial false is needed because the first element doesn't have a previous one to compare with. The logical index is used to select which values of Z should be set to 0.
This should work
Z = zeros(length(L))
for i = 2:length(L)
if(L(i-1) == L(i)
Z(i) = X(i);
else
Z(i) = 0;
end
end