Firstly I'm new to matlab programming. Here is my doubt. I would like to break the loop when the cells in this matrix is either empty or a NaN. Matlab suggesting not to have isempty and isnan in same line. The error i get is "Attempted to access coordinates(10,1); index out of bounds because size(coordinates)=[9,8].". I'm messing up somewhere, could someone help on this? Thanks.
n_b=0;
n_nodes=0;
for j=1:2:10
for i=1:1:10
if (isempty(coordinates(i,j))) or (isnan(coordinates(i,j)))
break
else
disp(coordinates(i,j));
n_nodes=n_nodes+1;
end
end
n_b=n_b+1;
if (n_b==4) % break at four columns
break
end
end
The problem is with this lines:
for j=1:2:10
for i=1:1:10
You are trying to access coordinates that do not exist. Try this:
for j = 1:2:size(coordinates,2)
for i = 1:size(coordinates,1)
This will always stop before the matrix ends.
Also, delete the isempty() check from your condition, as it never fulfills, together with the or which is not a valid MATLAB syntax (should be ||).
Here is how you full code should look:
n_b = 0;
n_nodes = 0;
for j = 1:2:size(coordinates,2)
for i = 1:size(coordinates,1)
if isnan(coordinates(i,j))
break
else
disp(coordinates(i,j));
n_nodes = n_nodes+1;
end
end
n_b = n_b+1;
if (n_b==4) % break at four columns
break
end
end
Related
This is my attempt of a simple example (it seems pointless) but the idea is bigger than this simple code.
During a for loop, if something happens, I want to skip this step of the for loop and then add an extra step on the end.
I am trying to create a list of numbers, that do not include the number 8.
If the code creates an 8, this will mean that exitflag is equal to 1.
Can I adapt this program so that if the exitflag=1, the it will remove that result and add another loop.
The code:
for i = 1:1000
j = 1+round(rand*10)
if j == 8
exitflag = 1
else
exitflag = 0
end
storeexit(i)=exitflag;
storej(i)=j;
end
sum(storeexit)
I would ideally like a list of numbers, 1000 long which does not contain an 8.
If what you want to do is 1000 iterations of the loop, but repeat a loop iteration if you don't like its result, instead of tagging the repeat at the end, what you can do is loop inside the for loop until you do like the result of that iteration:
stores = zeros(1000,1); % Note that it is important to preallocate arrays, even in toy examples :)
for i = 1:1000
success = false; % MATLAB has no do..while loop, this is slightly more awkward....
while ~success
j = 1+round(rand*10);
success = j ~= 8;
end
storej(i) = j; % j guaranteed to not be 8
end
No.
With for loop, the number of loops is determined on the loop start and it is not dynamic.
For doing what you want, you need to use a while loop.
I am trying to force a for loop to restart if a condition is not stratified. I can do it with while since I want the loop to run for a certain number of iterations. I tried to set iter=iter-1 inside the if statement but it did not work. Any suggestions?
R=2*10^3;
lamda= 0.00001;
h=100;
a = 9.6117;
b = 0.1581;
for iter=1:10
M=poissrnd(lamda*R^2);
xx=R*rand(1,M);
yy=R*rand(1,M);
zz=ones(1,M)*h;
BS=[xx' yy' zz'];
user=[0,0, 0];
s=pdist2(BS(:,1:2),user(1,1:2));
anga=atand(h./s);
PL=1./(1+(a*exp(b*(a-anga))));
berRV=binornd(1,PL);
if berRV(1)==1
% do something
else
% repeat
end
end
You can accomplish this by using a while loop, with a comparison to whether the number of needed results have been identified. See the comment about saving your found values, as you hadn't specified what needs to be done when the condition you're searching for is satisfied.
R=2*10^3;
lamda= 0.00001;
h=100;
a = 9.6117;
b = 0.1581;
total_results_found = 0;
needed_results_found = 10;
while total_results_found < needed_results_found
M=poissrnd(lamda*R^2);
xx=R*rand(1,M);
yy=R*rand(1,M);
zz=ones(1,M)*h;
BS=[xx' yy' zz'];
user=[0,0, 0];
s=pdist2(BS(:,1:2),user(1,1:2));
anga=atand(h./s);
PL=1./(1+(a*exp(b*(a-anga))));
berRV=binornd(1,PL);
if berRV(1)==1
% save the result here
% iterate the counter
total_results_found = total_results_found + 1;
end
end
The simplest approach here would be with a while loop inside the for loop:
for iter=1:10
berRV(1) = 0
while berRV(1)~=1
% original loop code here
end
% do something
end
[Sadly, MATLAB does not have a do...while loop, it would make the above a little cleaner.]
While the other two solutions are perfectly valid, I wanted to give you another solution, which I think is the closest to the logic you provided in the question.
for iter=1:10
while 1
% loop code here
if berRV(1) == 1
break
end
end
end
The idea is similar to the one Cris presents, namely that you repeat the body of the for-loop until some condition is met. The difference lies solely in how you terminate the while loop,
Suppose we are running an infinite for loop in MATLAB, and we want to store the iterative values in a vector. How can we declare the vector without knowing the size of it?
z=??
for i=1:inf
z(i,1)=i;
if(condition)%%condition is met then break out of the loop
break;
end;
end;
Please note first that this is bad practise, and you should preallocate where possible.
That being said, using the end keyword is the best option for extending arrays by a single element:
z = [];
for ii = 1:x
z(end+1, 1) = ii; % Index to the (end+1)th position, extending the array
end
You can also concatenate results from previous iterations, this tends to be slower since you have the assignment variable on both sides of the equals operator
z = [];
for ii = 1:x
z = [z; ii];
end
Sadar commented that directly indexing out of bounds (as other answers are suggesting) is depreciated by MathWorks, I'm not sure on a source for this.
If your condition computation is separate from the output computation, you could get the required size first
k = 0;
while ~condition
condition = true; % evaluate the condition here
k = k + 1;
end
z = zeros( k, 1 ); % now we can pre-allocate
for ii = 1:k
z(ii) = ii; % assign values
end
Depending on your use case you might not know the actual number of iterations and therefore vector elements, but you might know the maximum possible number of iterations. As said before, resizing a vector in each loop iteration could be a real performance bottleneck, you might consider something like this:
maxNumIterations = 12345;
myVector = zeros(maxNumIterations, 1);
for n = 1:maxNumIterations
myVector(n) = someFunctionReturningTheDesiredValue(n);
if(condition)
vecLength = n;
break;
end
end
% Resize the vector to the length that has actually been filled
myVector = myVector(1:vecLength);
By the way, I'd give you the advice to NOT getting used to use i as an index in Matlab programs as this will mask the imaginary unit i. I ran into some nasty bugs in complex calculations inside loops by doing so, so I would advise to just take n or any other letter of your choice as your go-to loop index variable name even if you are not dealing with complex values in your functions ;)
You can just declare an empty matrix with
z = []
This will create a 0x0 matrix which will resize when you write data to it.
In your case it will grow to a vector ix1.
Keep in mind that this is much slower than initializing your vector beforehand with the zeros(dim,dim) function.
So if there is any way to figure out the max value of i you should initialize it withz = zeros(i,1)
cheers,
Simon
You can initialize z to be an empty array, it'll expand automatically during looping ...something like:
z = [];
for i = 1:Inf
z(i) = i;
if (condition)
break;
end
end
However this looks nasty (and throws a warning: Warning: FOR loop index is too large. Truncating to 9223372036854775807), I would do here a while (true) or the condition itself and increment manually.
z = [];
i = 0;
while !condition
i=i+1;
z[i]=i;
end
And/or if your example is really what you need at the end, replace the re-creation of the array with something like:
while !condition
i=i+1;
end
z = 1:i;
As mentioned in various times in this thread the resizing of an array is very processing intensive, and could take a lot of time.
If processing time is not an issue:
Then something like #Wolfie mentioned would be good enough. In each iteration the array length will be increased and that is that:
z = [];
for ii = 1:x
%z = [z; ii];
z(end+1) = ii % Best way
end
If processing time is an issue:
If the processing time is a large factor, and you want it to run as smooth as possible, then you need to preallocating.If you have a rough idea of the maximum number of iterations that will run then you can use #PluginPenguin's suggestion. But there could still be a change of hitting that preset limit, which will break (or severely slow down) the program.
My suggestion:
If your loop is running infinitely until you stop it, you could do occasional resizing. Essentially extending the size as you go, but only doing it once in a while. For example every 100 loops:
z = zeros(100,1);
for i=1:inf
z(i,1)=i;
fprintf("%d,\t%d\n",i,length(z)); % See it working
if i+1 >= length(z) %The array as run out of space
%z = [z; zeros(100,1)]; % Extend this array (note the semi-colon)
z((length(z)+100),1) = 0; % Seems twice as fast as the commented method
end
if(condition)%%condition is met then break out of the loop
break;
end;
end
This means that the loop can run forever, the array will increase with it, but only every once in a while. This means that the processing time hit will be minimal.
Edit:
As #Cris kindly mentioned MATLAB already does what I proposed internally. This makes two of my comments completely wrong. So the best will be to follow what #Wolfie and #Cris said with:
z(end+1) = i
Hope this helps!
I am trying to make my program work. It is for prime numbers.
Below is my function then my main program
I believe this is the right formatting, (obviously I'm probably wrong cause its not working) and I have been trying to fix it to no avail. Any help will be most appreciated and an explanation of what I am doing wrong (I am pretty sure it has to do with subtle formatting) would be great too.
function [answer,primefactors ] = primey1 (N)
for i=2:(N-1)
A(i-1)=rem(N,i);
end
A;
if(all(A)==1)
answer=['Yes']
primefactors=[1,N]
elseif(all(A)==0)
answer=['No']
fac=[]
for i=2:N
q=0;
while N/i==floor(N/i)
N=N/i;
q=q+1;
end
if q>0
fac=[fac,i]
if N==1
break
primefactors=[fac]
end
end
end
end
endfunction
As noted by Magla, MATLAB comes with the primes and factor functions, which you can at least use to compare your implementation with and/or check your outcomes.
Anyway, as for your code, try this:
function [answer, primefactors] = primey1(N)
% Use vectorization for simple cases such as these:
A = rem(N,2:N-1);
if all(A)
answer = 'Yes';
primefactors = [1,N];
% Re-wrote this entire section. There were a bunch of things wrong with it:
% the order of commands was wrong, variables were not assigned for some N,
% etc. Just compare the two implementations
else
answer = 'No';
primefactors = [];
for ii = 2:N
q = 0;
while N/ii == floor(N/ii)
N = N/ii;
q = q+1;
end
if q > 0
primefactors = [primefactors,ii]; %#ok<AGROW>
if N==1
break;
end
end
end
end
end
Matlab has a factor function that does what your code is trying to do
p = factor(10)
returns 2, 5
and
p = factor(11)
returns 11.
All you have is to test for length
if length(p) == 1
is true for prime numbers.
The solution as offered by #Rody should do the job, in theory even more efficient than this, however to illustrate the concept of initialization, I would recommend you to initialize the output variables of your function right after the function start. In your case this would mean that I recommend starting the code like this:
function [answer, primefactors] = primey1(N)
% Function to determine whether a number is prime and which prime factors it has
% Assign default values
answer = 'No';
primefactors = [];
I have an array (M) of matrices. I perform an operation on the matrix in the ith position, and it adds three more matrices to my array in the (3i-1), (3i) and (3i+1)th positions. I want to continue this process until I reach the jth position in the array, where j is such that all matrices in the (j+1)th position and onwards have appeared already somewhere between positions 1 and j (inclusive).
EDIT: I've been asked to clarify what I mean. I am unable to write code that makes my algorithm terminate when I want it to as explained above. If I knew a proper way of searching through an array of matrices to check if a given matrix is contained, then I could do it. I tried the following:
done = 0;
ii = 1
while done ~= 1
%operation on matrix in ith position omitted, but this is where it goes
for jj = ii+1:numel(M)
for kk = 1:ii
if M{jj} == M{kk};
done = done + 1/(numel(M) - ii);
break
end
end
end
if done ~= 1
done = 0;
end
ii = ii + 1
end
The problem I have with this (as I'm sure you can see) is that if the process goes on for too long, rounding errors stop ever allowing done = 1, and the algorithm doesn't terminate. I tried getting round this by introducing thresholds, something like
while abs(done - 1) > thresh
and
if abs(done - 1) > thresh
done = 0;
end
This makes the algorithm work more often, but I don't have a 'one size fits all' threshold that I could use (the process could continue for arbitrarily many steps), so it still ends up breaking.
What can I do to fix this?
Thanks
Why don't you initialize done at 0, keep your while done==0 loop, and instead of computing done as a sum of elements, check if your condition (finding if the matrix already exists) is verified for all jj, something like this:
alldone=zeros(numel(M)-ii,1);
for jj = ii+1:numel(M)
for kk = 1:ii
if isequal(M{jj},M{kk})
alldone(jj-ii) = 1
break
end
end
end
done=prod(alldone);
There is probably a more elegant way to code this, though.
For instance, you could add early termination:
while done==0
done=1;
for jj = ii+1:numel(M)
match_success=0;
for kk = 1:ii
if isequal(M{jj},M{kk})
match_success=1;
break
end
end
if match_success==0
done=0;
break;
end
end
end
At the beginning of each loop, the algorithm assumes it is going to succeed and stop there (hence the done=1). Then for each jj, we create a match_success which will be set to 1 only if a match is found for M{jj}. If the match is found, we break and go to the next j. If no match if found for j, match_success is left to 0, done is initialized to 0 and the while loop continues. I haven't checked it, but I think it should work.
This is just a simple tweak, but again, more thought can probably speed up this whole code a lot.