I have a dataset of 20 points which I need to enclose in an ellipse. I am trying to do this calculating a biggest distance between the center of ellipse and removing the farthest point, reconstructing a new ellipse and repeating the process again.
Here is the code:
P = [1.397100 0.934550
-0.708828 -3.993403
-0.775017 -0.167091
1.861729 -0.334958
-0.376357 -3.187580
0.294908 -0.765351
0.952188 -1.872313
0.524652 2.972442
0.889532 -0.331162
0.991093 0.278271
0.262071 0.078590
0.901017 0.320209
-0.797258 0.518452
-0.656796 0.268351
0.333667 0.601893
0.762157 0.613208
0.292147 -1.555187
0.122875 -0.860661
0.702863 -3.195442
-1.140430 -1.919686]'
t = 0.001;
K = convhulln(P');
K = unique(K(:));
Q = P(:,K);
[A , C] = MinVolEllipse(Q, t)
figure
plot(P(1,:),P(2,:),'*')
hold on
Ellipse_plot(A,C)
%Rule=size(P',1)
W=P'
v=C'
Cx=v(1)
Cy=v(2)
dist=sqrt((W(:,1)-Cx).^2+(W(:,2)-Cy).^2)
Remove=find(dist==max(dist(:)))
W(Remove,:)=[]
W=W'
Rule=size(W',1)
while Rule>5
W=W';
v=C';
Cx=v(1);
Cy=v(2);
dist=sqrt((W(:,1)-Cx).^2+(W(:,2)-Cy).^2);
Remove=find(dist==max(dist(:)));
W(Remove,:)=[];
W=W';
end
[A , C] = MinVolEllipse(W, t)
figure
plot(W(1,:),W(2,:),'*')
hold on
Ellipse_plot(A,C)
I understand that I did something wrong but now I'm stuck with "Busy" for about 10 minutes. How to properly loop the process?
Thanks!
You need to update the value of Rule
while Rule>5
W=W';
v=C';
Cx=v(1);
Cy=v(2);
dist=sqrt((W(:,1)-Cx).^2+(W(:,2)-Cy).^2);
Remove=find(dist==max(dist(:)));
W(Remove,:)=[];
W=W';
Rule=size(W',1)
end
As a separate point, you perform some redundant operation e.g. the first and the last line of you loop do the inverse operation. Maybe something like this: (Note the code is not tested)
while size(W,1)>5
dist=sqrt((W(:,1)-C(1)).^2+(W(:,2)-C(2)).^2);
% the second returned variable is the location
[~, Remove] = max(dist(:));
W(Remove,:)=[];
end
Related
I am new to Julia and trying to use the Julia package DifferentialEquations to simultaneously solve for several conditions of the same set of coupled ODEs. My system is a model of an experiment and in one of the conditions, I increase the amount of one of the dependent variables at mid-way through the process.
I would like to be able to adjust the condition of this single trajectory, however so far I am only able to adjust all the trajectories at once. Is it possible to access a single one using callbacks? If not, is there a better way to do this?
Here is a simplified example using the lorentz equations for what I want to be doing:
#Differential Equations setup
function lorentz!(du,u,p,t)
a,r,b=p
du[1]= a*(u[2]-u[1])
du[2]=u[1]*(r-u[3])-u[2]
du[3]=u[1]*u[2]-b*u[3];
end
#function to cycle through inital conditions
function prob_func(prob,i,repeat)
remake(prob; u0 = u0_arr[i]);
end
#inputs
t_span=[(0.0,100.0),(0.0,100.0)];
u01=[0.0;1.0;0.0];
u02=[0.0;1.0;0.0];
u0_arr = [u01,u02];
p=[10.,28.,8/3];
#initialising the Ensemble Problem
prob = ODEProblem(lorentz!,u0_arr[1],t_span[1],p);
CombinedProblem = EnsembleProblem(prob,
prob_func = prob_func, #-> (prob),#repeat is a count for how many times the trajectories had been repeated
safetycopy = true # determines whether a safetly deepcopy is called on the prob before the prob_func (sounds best to leave as true for user-given prob_func)
);
#introducing callback
function condition(u,t,repeat)
return 50 .-t
end
function affect!(repeat)
repeat.u[1]=repeat.u[1] +50
end
callback = DifferentialEquations.ContinuousCallback(condition, affect!)
#solving
sim=solve(CombinedProblem,Rosenbrock23(),EnsembleSerial(),trajectories=2,callback=callback);
# Plotting for ease of understanding example
plot(sim[1].t,sim[1][1,:])
plot!(sim[2].t,sim[2][1,:])
I want to produce something like this:
Example_desired_outcome
But this code produces:
Example_current_outcome
Thank you for your help!
You can make that callback dependent on a parameter and make the parameter different between problems. For example:
function f(du,u,p,t)
if p == 0
du[1] = 2u[1]
else
du[1] = -2u[1]
end
du[2] = -u[2]
end
condition(t,u,integrator) = u[2] - 0.5
affect!(integrator) = integrator.prob.p = 1
For more information, check out the FAQ on this topic: https://diffeq.sciml.ai/stable/basics/faq/#Switching-ODE-functions-in-the-middle-of-integration
I'm making a GUI in matlab to calculate ideal shifting points for a racecar.
For this I need to compare 2 single column matrixes.
Fwheel1 =
1.0e+003 *
4.5433
4.6372
4.6770
4.6892
4.7235
4.8064
4.9451
5.0838
5.2300
5.3401
5.4864
5.5454
5.5046
5.4758
5.5028
5.5782
5.6183
5.6663
5.7380
5.8174
5.8940
5.9553
6.0364
6.1075
6.0904
5.9285
5.7654
5.5762
5.3498
5.1766
5.0548
4.8236
4.6538
Fwheel2 =
1.0e+003 *
3.5174
3.5901
3.6209
3.6304
3.6569
3.7211
3.8285
3.9358
4.0490
4.1343
4.2475
4.2932
4.2617
4.2393
4.2602
4.3186
4.3496
4.3868
4.4423
4.5038
4.5631
4.6105
4.6734
4.7284
4.7151
4.5898
4.4635
4.3170
4.1418
4.0077
3.9134
3.7344
3.6029
These are the 2 matrixes. Now what I want is to compare Fwheel1 with Fwheel2. I want to know at which position in the matrix Fwheel2 > Fwheel1.
So output needs to be for example 23.
I hope somebody can help me.
Kind regards
You can do this easily with find.
idx= find( Fwheel2 > Fwheel1);
If you just want the first one, or the first n, you can just
idx= find( Fwheel2 > Fwheel1,n);
for another method,
c=0;
for i=1:33
if Fwheel2(i)>Fwheel1(i)
c=c+1;
b[c]=i
end
end
in the b vector you have your answer
I have the following codes which I wish to have an output matrix Rpp of (10201,3). I run this code (which takes a bit long) then I check the matrix size of Rpp and I see (1,3), I tried so many things I couldn't find any proper way. The logic of the codes is to take the 6 values (contain 4 constant values and 2 variable values (chosen from 101 values)) and make the calculation for 3 different i1 and store every output vector of 3 in a matrix with (101*101 (pairs of those 2 variable values)) rows and 3 (for each i1) columns.
I appreciate your help
Vp1=linspace(3000,3500,101);
Vp2=3850;
rho1=2390;
rho2=2510;
Vs1=linspace(1250,1750,101);
Vs2=2000;
i1=[10 25 40];
Rpp = zeros(length(Vp1)*length(Vs1),length (i1));
for n=1:length(Vp1)*length(Vs1)
for m=1:length (i1)
for l=1:length(Vp1)
for k=1:length(Vs1)
p=sin(i1)/Vp1(l);
i2=asin(p*Vp2);
j1=asin(p*Vs1(k));
j2=asin(p*Vs2);
a=rho2*(1-2*Vs2^2*p.^2)-rho1*(1-2*Vs1(k).^2*p.^2);
b=rho2*(1-2*Vs2^2*p.^2)+2*rho1*Vs1(k)^2*p.^2;
c=rho1*(1-2*Vs1(k)^2*p.^2)+2*rho2*Vs2^2*p.^2;
d=2*(rho2*Vs2^2-rho1*Vs1(k)^2);
E=b.*cos(i1)./Vp1(l)+c.*cos(i2)/Vp2;
F=b.*cos(j1)./Vs1(k)+c.*cos(j2)/Vs2;
G=a-d*(cos(i1)/Vp1(l)).*(cos(j2)/Vs2);
H=a-d*(cos(i2)/Vp2).*(cos(j1)/Vs1(k));
D=E.*F+G.*H.*p.^2;
Rpp=((b.*(cos(i1)/Vp1(l))-c.*cos((i2)/Vp2)).*F-(a+d*((cos(i1)/Vp1(l))).*(cos(j2)/Vs2)).*H.*p.^2)./D
end
end
end
end
Try this. You 2 outer loops didn't do anything. You never used m or n so I killed those 2 loops. Also you just kept overwriting Rpp on every loop so your initialization of Rpp didn't do anything. I added an index var to assign the results to the equation to what I think is the correct part of Rpp.
Vp1=linspace(3000,3500,101);
Vp2=3850;
rho1=2390;
rho2=2510;
Vs1=linspace(1250,1750,101);
Vs2=2000;
i1=[10 25 40];
Rpp = zeros(length(Vp1)*length(Vs1),length (i1));
index = 1;
for l=1:length(Vp1)
for k=1:length(Vs1)
p=sin(i1)/Vp1(l);
i2=asin(p*Vp2);
j1=asin(p*Vs1(k));
j2=asin(p*Vs2);
a=rho2*(1-2*Vs2^2*p.^2)-rho1*(1-2*Vs1(k).^2*p.^2);
b=rho2*(1-2*Vs2^2*p.^2)+2*rho1*Vs1(k)^2*p.^2;
c=rho1*(1-2*Vs1(k)^2*p.^2)+2*rho2*Vs2^2*p.^2;
d=2*(rho2*Vs2^2-rho1*Vs1(k)^2);
E=b.*cos(i1)./Vp1(l)+c.*cos(i2)/Vp2;
F=b.*cos(j1)./Vs1(k)+c.*cos(j2)/Vs2;
G=a-d*(cos(i1)/Vp1(l)).*(cos(j2)/Vs2);
H=a-d*(cos(i2)/Vp2).*(cos(j1)/Vs1(k));
D=E.*F+G.*H.*p.^2;
Rpp(index,:)=((b.*(cos(i1)/Vp1(l))-c.*cos((i2)/Vp2)).*F-(a+d*((cos(i1)/Vp1(l))).*(cos(j2)/Vs2)).*H.*p.^2)./D;
index = index+1;
end
end
Results:
>> size(Rpp)
ans =
10201 3
The way you use the for loop is wrong. You're running the calculation for length(Vp1)*length(Vs1) * length (i1) * length(Vp1) * length(Vs1) times. Here's the correct way. I changed l into lll just so I won't confuse it with the number 1. In each iteration of the first for loop, you're running length(Vs1) times, and you need to assign the result (a 1X3 array) to the Rpp by using a row number specified by k+(lll-1)*length(Vp1).
for lll=1:length(Vp1)
for k=1:length(Vs1)
p=sin(i1)/Vp1(lll);
i2=asin(p*Vp2);
j1=asin(p*Vs1(k));
j2=asin(p*Vs2);
a=rho2*(1-2*Vs2^2*p.^2)-rho1*(1-2*Vs1(k).^2*p.^2);
b=rho2*(1-2*Vs2^2*p.^2)+2*rho1*Vs1(k)^2*p.^2;
c=rho1*(1-2*Vs1(k)^2*p.^2)+2*rho2*Vs2^2*p.^2;
d=2*(rho2*Vs2^2-rho1*Vs1(k)^2);
E=b.*cos(i1)./Vp1(lll)+c.*cos(i2)/Vp2;
F=b.*cos(j1)./Vs1(k)+c.*cos(j2)/Vs2;
G=a-d*(cos(i1)/Vp1(lll)).*(cos(j2)/Vs2);
H=a-d*(cos(i2)/Vp2).*(cos(j1)/Vs1(k));
D=E.*F+G.*H.*p.^2;
Rpp(k+(lll-1)*length(Vp1),:)=((b.*(cos(i1)/Vp1(lll))-c.*cos((i2)/Vp2)).*F-(a+d*((cos(i1)/Vp1(lll))).*(cos(j2)/Vs2)).*H.*p.^2)./D;
end
end
As simple as in title. I have nx1 sized vector p. I'm interested in the maximum value of r = p/foo - floor(p/foo), with foo being a scalar, so I just call:
max_value = max(p/foo-floor(p/foo))
How can I get which value of p gave out max_value?
I thought about calling:
[max_value, max_index] = max(p/foo-floor(p/foo))
but soon I realised that max_index is pretty useless. I'm sorry asking this, real beginner here.
Having dropped the issue to pieces, I realized there's no unique corrispondence between values p and values in my related vector p/foo-floor(p/foo), so there's a logical issue rather than a language one.
However, given my input data, I know that the solution is unique. How can I fix this?
I ended up doing:
result = p(p/foo-floor(p/foo) == max(p/foo-floor(p/foo)))
Looks terrible, so if you know any other way...
Once you have the index, use it:
result = p(max_index)
You can create a new vector with your lets say "transformed" values:
p2 = (p/foo-floor(p/foo))
and then just use find to find the max values on p2:
max_index = find(p2 == max(p2))
that will return the index or indices of p2 with the max value of that operation, and finally just lookup the original value in p
p(max_index)
in 1 line, this is:
p(find((p/foo-floor(p/foo) == max((p/foo-floor(p/foo))))))
which is basically the same thing you did in the end :)
This is quite a simple issue, but I've been struggling with it. sortedd and sortedfinal_d are 8 x 1000 Matrices and I am using the loop below to check if any of the elements in sortedfinal_d lies between two consecutive elements of sortedd, in terms of magnitude. I'm doing this along each row. overall_p is a 8 x 1000 Matrix as well, but at the end of this process I end up having final_p as a Matrix of Zeros. I don't know why this is.
for k=2:1000
for s=1:1000
for j=1:8
if sortedd(j,k) > sortedfinal_d(j,s) && sortedfinal_d(j,s) > sortedd(j,k-1)
final_p(j,s) = overall_p(j,k);
end
end
end
end
EDIT: Added data for the inputs as shown below:
sortedd (first four columns) =
0.219977361620113 0.219996752039812 0.220344444223787 0.220593274018691
0.272807483153955 0.273682693068593 0.273846498221277 0.274060049642900
0.327201460264565 0.327375792227635 0.327572790857546 0.327856448530021
0.380389118311424 0.380845274148177 0.380893687870765 0.381015090963159
0.434832574575088 0.434860658844550 0.435021604722982 0.435119929919457
0.487119089589798 0.488128501559782 0.488207451439073 0.488430455768512
0.540652551559395 0.541303305046034 0.542195194863130 0.542234381085921
0.595254195563241 0.595296064375604 0.595376090156252 0.595377962767971
sortedfinal_d =
0.182086792394190 0.182406508309366 0.182406508309366 0.182808976400818
0.233058295607543 0.233058295607543 0.233158455616954 0.233158455616954
0.286243848617693 0.286357973626582 0.286918095670684 0.287393171241241
0.336938335090164 0.336938335090164 0.337094505106945 0.337669618738100
0.390287818652551 0.390567879874952 0.390567879874952 0.390670502700602
0.446995120903824 0.447270251510681 0.447452123072880 0.447597175111267
0.501060785098551 0.501060785098551 0.501060785098551 0.501060785098551
0.551311219045087 0.551463923687602 0.551463923687602 0.551653815175502
Thanks a lot
Do you have to use loops to accomplish this?
matching_d = sortedfinal_d(:,1:end-1) < sortedd(:,2:end) ...
& sortedd(:,2:end) < sortedfinal_d(:,2:end);
final_p(matching_d) = overall_p(matching_d);
If you can show us a small sample input (say, 1x5 versions of sortedd and sortedfinal_d) and output (the corresponding matching_d) it would be easier for us to help troubleshoot.
If i set your matrices to random numbers, final_p does return some numbers.
So your code works as is. Post your dataset or at least describe the dataset in some detail, this will make it much easier to diagnose the problem.
I have reduced 1000 down to 10 and re-ordered the iteration variables to i, j, k to make it easier to follow:
sortedd = rand(8, 10);
sortedfinal_d = rand(8, 10);
overall_p = rand(8, 10);
for i=2:10
for j=1:10
for k=1:8
if sortedd(k,i) > sortedfinal_d(k,j) && sortedfinal_d(k,j) > sortedd(k,i-1)
final_p(k,j) = overall_p(k,i);
end
end
end
end
final_p