It's a simple problem I am having, but a little hard to explain.
I have a while loop that looks like this;
(Not the actual code)
x = [1;2;3;4]
while size(x(:,1),1) > 1
%Do stuff
%When a condition is met move it to the bottom to be processed last
%In this case "2"
x = [x; x(2,:)];
%Remove the original line for two
x(2,:) = [];
end
However it exits on the third iteration instead of the fourth missing the last row.
My theory is, the original size of x is 4 going into the while loop. By adding a row and deleting another matlab thinks that the variable is now size == 3 and exits when 3 variables are removed.
It doesn't make much sense to me. The code is confidential so I can't share the actual code, but if necessary I could attempt to replicate the error with code I can share.
I'm hoping someone has a magical answer.
Thanks
I got it, sorry to bug everyone. It needs to be a >= 1 then it will also process the last item in the list. The example code, while it was an infinite loop, would never process the last item in the list.
Related
I have been asked to obtain the first 15 triplets according to this series and this code ought to work. However, it does only produce a table (15*3) filled with zero rather than the 15 Pythagorean triplets? Any help will be welcome.
A = zeros(15, 3);
ii = 1;
for c = 5:120
c2=c^2;
for a=1:c-1
a2=a^2;
for b=a:c-1
if c2-(a2+b^2) == 0
A(ii,1) = a;
A(ii,2) = b;
A(ii,3) = c;
ii=ii+1;
if A(15, 1) ~= 0
flag = 1;
break
end
end
end
if flag == 1
break
end
end
if flag == 1
break
end
end
T1 = array2table(A);
disp(T1)
So, the code generated a correct table on application-restart before failing on all subsequent attempts. And, now I notice that the code runs successfully only for the first time after every relaunch of the application. (Resolved, thanks Dan Pollard.)
Also, interested in knowing if there is any way to not write an upper limit (120) into the code.
I don't think your if statement is ever satisfied. For example, for c=5, you'd expect a=3, b=4 to be a triplet. But you're only letting a and b go up to floor(sqrt(c-1)), which is 2.
Do you mean to let a and b go up to floor(sqrt(c2-1))?
Edit As the question has changed.
When you run the code, Matlab creates all the variables which you assign, and stores them in the workspace. This can be useful, but here it's hurting you as you have the variable flag which is stored as 1. This means that when the code runs, it checks if flag==1 after the first run through b, which it is, so the code ends. Resolve this by placing clear; at the beginning of your script.
There isn't a practical way to remove the upper limit on c. Matlab has the built-in variable Inf but at best Matlab won't let you use it in that context. Realistically you could just replace the 120 with a really large number, but this will take more time and more memory as the number gets bigger. Computers have a finite RAM to store matlab arrays in though, and there are infinitely many pythagorean triples, so doing the calculation without an upper limit will fail in some way.
I've been trying to figure this out myself and also searched here. The fact that I am not quite sure what the problem is isn't helping with this. I have previously found good help in answers to other people here, so I hope that you can help me.
I have a dataset (2000x1100) that consists of 1's and 0's, where each row represents one datapoint over time (columns).
I am trying to find sequences of 0's for each row and exclude those that are below a specific length. I have already found helpful answers here that allowed me to do this (thanks!).
'test' is a reduced test dataset that I am using to test the code.
for j = 1:size(test,1)
testThresh(j,:) = diff([1 test(j,:)]);
startIndex = find(testThresh(j,:) < 0);
if isempty(startIndex)
continue
j = j+1;
end
endIndex = find(testThresh(j,:) > 0)-1;
if numel(endIndex) == 1
for m = 1:size(startIndex,2)
duration = (endIndex(m)-startIndex(m))+1;
threshold = (duration < 10);
startIndexC = startIndex(threshold);
endIndexC = endIndex(threshold);
end
else
duration = (endIndex(j,:)-startIndex(j,:))+1;
threshold = (duration < 10);
startIndexC = startIndex(threshold);
endIndexC = endIndex(threshold);
end
..
I would later replace the below-threshold sequences of 0's with 1's.
The code works fine until I happen to have a row that doesn't contain any 0's. It would skip to the next row as supposed to, but there it will result in an error:
Attempted to access endIndex(2,:); index out of bounds because size(endIndex)=[1,4].
I don't really understand why this causes an error. There isn't any problem with this specific row if it isn't preceded by a no-zero-containing row.
I assume that encountering a row w/o 0 does something to the allowed size of the array. I don't really know how to get around it. I can't pre-allocate because I don't know the size the variable will reach in each iteration (I tried anyway and it didn't help).
I also tried to say that numel(endIndex) >= 1 otherwise skip to next step. That also didn't work. I probably made a really silly mistake, but I am still quite new to Matlab and just can't figure it out.
I hope anyone can help with this!
Any help is greatly appreciated!
Edit:
duration = (endIndex(1,:)-startIndex(1,:))+1;
This is very stupid. I am ashamed. Thanks for pointing this out.
Just for reasons of completion since I wasn't specific enough of what I want to accomplish (sorry about that): I want to determine the start, end and length of stretches of 0's within a lot of 1's. If the length of any of these stretches is below the threshold of 10 (i.e. too short for my purposes to be considered) I want to disregard it.
Pretty simple, and I thought I knew what I was doing, but apparently not. Anyways.
I need to find the first element in a vector that is less than a specific value. Here is the code that I have been using:
t = 0:0.01:5;
u = ((2)*exp(-10.*t).*cos((4.*sqrt(6)).*t) + ((5)./sqrt(6)).*exp(-10.*t).*sin((4.*sqrt(6)).*t));
for a = 1:size(u)
if u(a) < (0.05)
disp(a)
break
end
end
The value that I'm trying to find is the first element less than 0.05, however, when I run my code, I don't get anything.
What could I be doing wrong?
Thanks!
#user2994291 has correctly pointed out where your loop based solution is going wrong (+1).
However I would also add that what you are trying to do can simply be accomplished by:
find(u < 0.05, 1, 'first')
Technically, the third input is not necessary - you could just use:
find(u < 0.05, 1)
However, I seem to recall reading at some point that find will work faster if you provide the third input.
The upper bound of your for loop is probably equal to 1.
In your case, u is a row vector (can't say 100% for sure in MATLAB as I only have access to GNU Octave right now), but calling size(u) will probably give back [1 501] as an answer. Your for-loop will select 1 as upper bound.
Try replacing size(u) with size(u,2) or, even better, with length(u). I get a = 24 as an answer.
Edit:
from your questions I assume you are a MATLAB beginner, therefore I strongly advise you to look into the built-in debugger (you can add breakpoints by clicking on the left vertical bar next to the desired line of code), this would have helped you identify the error with ease and will save you a lot of time in the future.
Instead of concatening results to this, Is there other way to do the following, I mean the loop will persist but vector=[vector,sum(othervector)]; can be gotten in any other way?
vector=[];
while a - b ~= 0
othervector = sum(something') %returns a vector like [ 1 ; 3 ]
vector=[vector,sum(othervector)];
...
end
vector=vector./100
Well, this really depends on what you are trying to do. Starting from this code, you might need to think about the actions you are doing and if you can change that behavior. Since the snippet of code you present shows little dependencies (i.e. how are a, b, something and vector related), I think we can only present vague solutions.
I suspect you want to get rid of the code to circumvent the effect of constantly moving the array around by concatenating your new results into it.
First of all, just make sure that the slowest portion of your application is caused by this. Take a look at the Matlab profiler. If that portion of your code is not a major time hog, don't bother spending a lot of time on improving it (and just say to mlint to ignore that line of code).
If you can analyse your code enough to ensure that you have a constant number of iterations, you can preallocate your variables and prevent any performance penalty (i.e. write a for loop in the worst case, or better yet really vectorized code). Or if you can `factor out' some variables, this might help also (move any loop invariants outside of the loop). So that might look something like this:
vector = zeros(1,100);
while a - b ~= 0
othervector = sum(something);
vector(iIteration) = sum(othervector);
iIteration = iIteration + 1;
end
If the nature of your code doesn't allow this (e.g. you are iterating to attain convergence; in that case, beware of checking equality of doubles: always include a tolerance), there are some tricks you can perform to improve performance, but most of them are just rules of thumb or trying to make the best of a bad situation. In this last case, you might add some maintenance code to get slightly better performance (but what you gain in time consumption, you lose in memory usage).
Let's say, you expect the code to run 100*n iterations most of the time, you might try to do something like this:
iIteration = 0;
expectedIterations = 100;
vector = [];
while a - b ~= 0
if mod(iIteration,expectedIterations) == 0
vector = [vector zeros(1,expectedIterations)];
end
iIteration = iIteration + 1;
vector(iIteration) = sum(sum(something));
...
end
vector = vector(1:iIteration); % throw away uninitialized
vector = vector/100;
It might not look pretty, but instead of resizing the array every iteration, the array only gets resized every 100th iteration. I haven't run this piece of code, but I've used very similar code in a former project.
If you want to optimize for speed, you should preallocate the vector and have a counter for the index as #Egon answered already.
If you just want to have a different way of writing vector=[vector,sum(othervector)];, you could use vector(end + 1) = sum(othervector); instead.
I have been happily using MATLAB to solve some project Euler problems. Yesterday, I wrote some code to solve one of these problems (14). When I write code containing long loops I always test the code by running it with short loops. If it runs fine and it does what it's supposed to do I assume this will also be the case when the length of the loop is longer.
This assumption turned out to be wrong. While executing the code below, MATLAB ran out of memory somewhere around the 75000th iteration.
c=1;
e=1000000;
for s=c:e
n=s;
t=1;
while n>1
a(s,t)=n;
if mod(n,2) == 0
n=n/2;
else
n=3*n+1;
end
a(s,t+1)=n;
t=t+1;
end
end
What can I do to prevent this from happening? Do I need to clear variables or free up memory somewhere in the process? Will saving the resulting matrix a to the hard drive help?
Here is the solution, staying as close as possible to your code (which is very close, the main difference is that you only need a 1D matrix):
c=1;
e=1000000;
a=zeros(e,1);
for s=c:e
n=s;
t=1;
while n>1
if mod(n,2) == 0
n=n/2;
else
n=3*n+1;
end
t=t+1;
end
a(s)=t;
end
[f g]=max(a);
This takes a few seconds (note the preallocation), and the result g unlocks the Euler 14 door.
Simply put, there's not enough memory to hold the matrix a.
Why are you making a two-dimensional matrix here anyway? You're storing information that you can compute just as fast as looking it up.
There's a much better thing to memoize here.
EDIT: Looking again, you're not even using the stuff you put in that matrix! Why are you bothering to create it?
The code appears to be storing every sequence in a different row of a matrix. The number of columns of that matrix will be equal to the length of the longest sequence currently found. This means that a sequence of two numbers will be padded with a bunch of right hand zeros.
I am sure you can see how this is incredibly inefficient. That may be the point of the exercise, or it will be for you in this implementation.
Better is to keep a variable like "Seed of longest solution found" which would store the seed for the longest solution. I would also keep a "length of longest solution found" keep the length. As you try every new seed, if it wins the title of longest, then update those variables.
This will keep only what you need in memory.
Short Answer:Use a 2d sparse matrix instead.
Long Answer: http://www.mathworks.com/access/helpdesk/help/techdoc/ref/sparse.html