I am trying to write a program that will find the outline of a figure by finding if points around an original point is within a boundary of the original point. I have tried to write a section that will prevent points to look at points already included in the outline (using variables a,b,c,d). The current code I have is
while 1
[m M] = size(already_boxed);
x=0;
for n = 1:m
a=0;
b=0;
c=0;
d=0;
for w = 1:m
if already_boxed(w,:) == [(already_boxed(n,1)+1), already_boxed(n,2)]
a=1;
end
if already_boxed(w,:) == [(already_boxed(n,1)-1), already_boxed(n,2)]
b=1;
end
if already_boxed(w,:) == [already_boxed(n,1), (already_boxed(n,2)+1)]
c=1;
end
if already_boxed(w,:) == [already_boxed(n,1), (already_boxed(n,2)-1)]
d=1;
end
end
if a==0
if subimages((already_boxed(n,1)+1), already_boxed(n,2))<subimages(already_boxed(n,1),already_boxed(n,2))*0.9 && subimages((already_boxed(n,1)+1), already_boxed(n,2))>subimages(already_boxed(n,1),already_boxed(n,2))*1.1
already_boxed = [already_boxed; (already_boxed(n,1)+1), already_boxed(n,2)];
x=1;
end
end
if b ==0
if subimages((already_boxed(n,1)-1), already_boxed(n,2))<subimages(already_boxed(n,1),already_boxed(n,2))*0.9 && subimages((already_boxed(n,1)-1), already_boxed(n,2))>subimages(already_boxed(n,1),already_boxed(n,2))*1.1
already_boxed = [already_boxed; (already_boxed(n,1)-1), already_boxed(n,2)];
x=1;
end
end
if c==0
if subimages(already_boxed(n,1), (already_boxed(n,2)+1))<subimages(already_boxed(n,1),already_boxed(n,2))*0.9 && subimages(already_boxed(n,1), (already_boxed(n,2)+1))>subimages(already_boxed(n,1),already_boxed(n,2))*1.1
already_boxed = [already_boxed; already_boxed(n,1), (already_boxed(n,2)+1)];
x=1;
end
end
if d ==0
if subimages(already_boxed(n,1), (already_boxed(n,2)-1))<subimages(already_boxed(n,1),already_boxed(n,2))*0.9 && subimages(already_boxed(n,1), (already_boxed(n,2)-1))>subimages(already_boxed(n,1),already_boxed(n,2))*1.1
already_boxed = [already_boxed; already_boxed(n,1), (already_boxed(n,2)-1)];
x=1;
end
end
end
if x == 0
break
end
end
Right now, the code will go on forever since it keeps on checking points that are in the online. For example, the variable 'already_boxed' will contain the doubles:
119,288
120,288
118,288
119,289
119,287
119,288
I don't know why 119,288 shows up twice, and I only want it to show up once. How can I fix this?
Related
Using this method, I should be able to get eigenvalues by getting the greatest value in each iteration.
But, what my code enables to get is only the first eingenvalue (and not necessarily the greatest) and I don't know where is the problem.
function [Vect,Vp]=PID(A,precision)
nbVal= 50;
[n,m]=size(A);
X=zeros(n,1);
X(1,1)=1;
Vect=zeros(n,min(n,nbVal));
Vp=zeros(1,min(n,nbVal));
XG=zeros(1,n);
j=1;
for i=1:min(nbVal,n)
Y = rand(n,1);
while (max(abs(Y/norm(Y)-X/norm(X))>=precision))
X=Y/norm(Y);
Y=A*X;
end
Vect(:,i)=X;
% To prevent a division by 0
while (X(j,1)==0 && j<=n)
j = j + 1;
end
if X(j,1)~=0
Vp(1,i) =Y(j,1)/X(j,1);
end
% Wielandt Deflation
YG= rand(1,n);
while (max(abs(YG/norm(YG)-XG/norm(XG)))>=precision )
XG=YG/norm(YG);
YG=XG*A;
end
A2=A-Vp(1,i)*(X*XG)/(XG*X);
A=A2;
end
end
I wrote the below code to estimate a specific value of epsilon and the code should stop the simulation when the condition becomes true (i.e. w(t)-f < error). Unfortunately the code didn't stop when the condition became true.
clear;clc;
tic
m=360; n=20; d=240; l=240;error=1e-5;RF=1.8;erin=0;
error_alt=(5e-4)*180/pi;
deltheta=2*pi/m; delz=1/n;
pin=0;f=1;
s=(d*d)/(l*l);
R=1/deltheta^2;
cor=(deltheta^2/delz^2)*s;
x=0:deltheta:2*pi;
y=0:delz:1;
iter=1000;
sum=zeros(iter);
[epsilon]=0.01:0.01:0.9;
[theta]=0:deltheta:2*pi;
p0=zeros(m+1,n+1);
p=zeros(m+1,n+1);
cc=zeros(m+1,n+1);
mm=zeros(m+1,n+1);
wr=zeros(length(epsilon));
wt=zeros(length(epsilon));
w=zeros(length(epsilon));
for t=1:length(epsilon)
h=zeros(m+1);
p0=zeros(m+1,n+1);
p=zeros(m+1,n+1);
cc=zeros(m+1,n+1);
mm=zeros(m+1,n+1);
wt(t)=0;wr(t)=0;w(t)=0;
phi1(t)=0;phi(t)=0;
for i=1:m+1
h(i)=1+epsilon(t).*cos(theta(i));
end
sum(1)=0;
phi1(t)=atan(sqrt(1.0-epsilon(t).^2)./epsilon(t));
phi1(t)=m+1-(phi1(t)*180/pi);
for k=1:iter
sumij=0.0;
at=round(phi1(t));
for j=2:n
for i=(at-9):(at+9);
p0(i,j)=pin;
end
end
for j=2:n
p0(m+1,j)=p0(1,j);
end
for j=2:n
for i=1:m
if (i==1)
h1=1+epsilon(t).*cos(theta(i)+0.5*deltheta);
h2=1+epsilon(t).*cos(theta(i)-0.5*deltheta);
conh=h1-h2;
const=2*(1+cor)*R*h(i)^3;
A=3*h(i)^2*R*conh/const;
C=h(i)^3*R/const;
E=h(i)^3*R*cor/const;
G=-3*sqrt(R)*conh/const;
p(i,j)=(C+A/2)*p0(i+1,j)+(C-A/2)*p0(m,j)+E*(p0(i,j+1)+p0(i,j-1))+G;
else
conh=(h(i+1)-h(i-1))/2;
const=2*(1+cor)*R*h(i)^3;
A=3*h(i)^2*R*conh/const;
C=h(i)^3*R/const;
E=h(i)^3*R*cor/const;
G=-3*sqrt(R)*conh/const;
p(i,j)=(C+A/2)*p0(i+1,j)+(C-A/2)*p0(i-1,j)+E*(p0(i,j+1)+p0(i,j-1))+G;
end
if p(i,j)<0
p(i,j)=0.0;
else
sumij=sumij+p(i,j);
end
end
end
for j=2:n
p(m+1,j)=p(1,j);
end
for j=2:n
for i=(at-9):(at+9)
p(i,j)=pin;
end
end
sum(k+1)=sumij;
errorp=abs(sum(k+1)-sum(k))/abs(sum(k+1));
if (errorp > error)
for j=2:n
for i=1:m
p0(i,j)=RF*p(i,j)+(1-RF)*p0(i,j);
end
end
else
end
end
for j=2:n
for i=2:m
cc(i,j)=p(i,j).*sin(theta(i));
mm(i,j)=p(i,j).*cos(theta(i));
end
end
wr(t)=trapz(y,trapz(x,cc));
wt(t)=trapz(y,trapz(x,mm));
w(t)=sqrt(wr(t).^2+wt(t).^2);
phi(t) = atan2(wt(t), wr(t));
phi(t)=m+1+(phi(t)*180/pi);
erin=abs(phi(t)-phi1(t))/abs(phi(t));
if (erin > error_alt)
phi1=RF*phi+(1-RF)*phi1;
at=round(phi1);
else
if abs((w(t)-f)) < error
break
end
end
if abs((w(t)-f)) < error
epsilon(t)
break
end
end
iterations=k;
itera=epsilon;
figure(1)
surf(p)
figure(2)
plot(p)
toc
You are looking for the keywork return.
The difference between break and return is that
As said in the documentation, break is used to exit a loop.
return will exit the function.
Even thought return is built to exit functions, it also work in scripts.
So in your example, you should replace break by return
if abs((w(t)-f)) < error
return
end
Note that this keywork works no matter how deep you are in a nested loop. As an example :
for ii = 1:2
for jj = 1:2
for kk = 1:2
disp(kk)
return
end
end
end
1
while the break keyword will only end one loop :
for ii = 1:2
for jj = 1:2
for kk = 1:2
disp(kk)
break
end
end
end
1
1
1
1
I have a while loop within an else statement. while the condition in the while loop is true I have the variable k decreasing (k=k-1). I want for the while loop to stop before k==0. I have tried placing the while loop within another while loop (while k>1) thinking maybe that would cancel the inner loop if k dropped to 1. Any thoughts?
if yada yada
do thing1
else
while k>1
while x==true
k=k-1;
do thing2
end
end
end
Doesn't this do the trick?
if yada yada
x = f(x) %// If you don't have anything here, you should use "if ~yada yada"
%// instead of "else"
else
while k>1 && x == true %// BTW: Lower case t in true
x = g(y) %// I hope you have something more than "k=k-1" in this loop
k = k-1;
end
end
You could add this sentence to be the last thing on your innermost while
if k <= 1
break;
Since your while-loop is basically achieving a counter-increment, I would highly recommend replacing it (actually, both of them) with a for-loop. In addition to being much more readable, it will allow Matlab to apply optimizations which will result in much faster execution times. See here:
yadayada = false;
x = true;
if yadayada
else
kmax = 5; % or whichever maximum value you want k to have
for k = kmax:-1:2 % have k start at kmax, decrement by 1 each time, until k==2
fprintf('k = %d\n', k);
% do something useful in the loop
if ~x
break;
end
end
end
Output:
k = 5
k = 4
k = 3
k = 2
range = min(x):0.0001:max(x);
N = numel(range);
x = sort(x);
hit = 0;
i=1;
for j = 1:(N-1)
if range(j) <= x(i) && x(i) < range(j+1)
hit = hit + 1;
i = i+1;
if x(i) == x(i-1)
while x(i) == x(i-1) % If there are more than one of the same
hit = hit + 1; % numbers in succession, this allows x and
i = i+1; % hit to carry on incrementing.
end %while
end %if
end %if
end %for
disp(hit)
This code compares 'range' and 'x'. It checks to see if 'x' is between values in 'range', if so the 'hit' counter gets incremented and so does the current value of 'x'.
Problem is, on some random values of x (as far as I can tell they are random), although they should satisfy the inequality in the 'IF' statement, the 'IF' statement gets ignored, the for loop continues and thus the final 'hit' value is wrong.
'x' is usually a 1D array about a million or so wide.
for this example, let
`x = [-2.1792 -2.1759 -2.1758 -2.1748 -2.1658 -2.1648 -2.1646 -2.1604 -2.1603 -2.1550]`
'hit' should equal '10' but instead outputs '2' since it decides to skip the 'IF' statement at 'j=35'.
To clarify. When 'j=35', range(j) = -2.1758 and i=3 meaning x(i)=-2.1758
I'm pretty sure that:
range(j) <= x(i) && x(i) < range(j+1)
-2.1758 <= -2.1758 && -2.1758 < -2.1757 %**edited, meant -2.1757 not -2.1759**
Is true.
I hope I'm just doing something silly here that I can't see. Sorry if it's a badly formatted question, it's my first here.
Cheers in advance.
A subsequent number x(i) could pass this test:
if range(j) <= x(i) && x(i) < range(j+1)
Without actually being equal to its neighbor:
if x(i) == x(i-1)
It could be infinitesimally larger and thus you move to the next j and it is out of range. Your inner while needs the same condition as the outer if. And you can skip the if COND while COND and just do while COND since it will work the same.
Would the following code not be simpler, faster, and give the same result?
x = sort(x)
hit = sum(diff(x)==0);
So I had a problem in which I needed to find roots using the bisect method:
Function:
function [ c,k ] = bisect(f,a,b,tol)
k=0;
while b-a > tol
c=(a+b)/2;
if sign(f(c)) == sign(f(b))
b=c;
else
a=c;
end
k=k+1;
end
Script:
f = #(x) (((1800).*log((160000)./(160000 - (x.*2600))) - (9.812).*x)./750) - 1;
a = 10;
b = 50;
tol = 1e-4;
[root, iter] = bisect(f,a,b,tol);
fprintf(' iterations = %i root = %15.10e ' ,iter, root);
This works perfectly, now I need to use an embedded function in Matlab to find the value of c for different values of q (in the above example q is a fixed number 2600) from 2000 to 3000 in increments of 10 and plot x vs q. In order to do this I have the following script:
function myFunction
h = 10;
a = 10;
b = 50;
tol = 1e-4;
function y = f(x)
y = (((1800).*log((160000)./(160000 - (x.*q))) - (9.812).*x)./750) - 1;
end
for q = (2000:h:3000)
k=0;
while b-a > tol
c=(a+b)/2;
if sign(f(c)) == sign(f(b))
b=c;
cArray(q) = c;
else
a=c;
cArray(q) = c;
end
k=k+1;
end
end
plot(q,cArray)
end
This code has no errors but when I run it there is no graph. Can someone please help me with this issue? I don't even know if my code to find c vs q is correct.
Major issues with your myFunction code:
The endpoints a,b should be reset within the for loop, so that the root search begins anew.
Using q as index in cArray(q) results in a too-large array filled with zeros for indices below 2000. You need an index variable to keep track of that array. (I used j below)
plot(q,cArray) should be plot(2000:h:3000,cArray), because q is not an array, it's a scalar.
Minor issues:
You never used k
You assign to cArray(q) within the while loop; this only needs to be done once the loop has ran.
Corrected function:
function myFunction
h = 10;
tol = 1e-4;
function y = f(x)
y = (((1800).*log((160000)./(160000 - (x.*q))) - (9.812).*x)./750) - 1;
end
j = 0;
for q = 2000:h:3000
a = 10;
b = 50;
while b-a > tol
c=(a+b)/2;
if sign(f(c)) == sign(f(b))
b=c;
else
a=c;
end
end
j=j+1;
cArray(j)=c;
end
plot(2000:h:3000,cArray)
end
and its output: