I have created a program in Matlab to try to find the root of f(x) = exp(2x) + 3x - 4 (the function "fopg1" in my code). My code is as follows:
format long
tic;
for dum=1:1000;
x(1) = 0.5;
x(2) = 0.4;
err_tol = 1e-8;
iteration(1) = 1;
n = 3;
while err_estimate > err_tol
iteration(n) = n;
x(n) = x(n-1) - fopg1(x(n-2)) * ((x(n-1) - x(n-2)) / (fopg1(x(n-1)) - fopg1(x(n-2))));
err_estimate(n) = abs(x(n) - x(n-1));
n = n + 1;
end
%end
time = toc;
avgtime = time/1000;
A = [iteration' x' err_estimate' tbd'];
f = '%2i %13.9f %13.9f %7.3f'; compose(f,A)
Unfortunately this does not converge. I feel like it should. Is there a flaw in my program or does it in fact not converge? Thanks in advance.
Maarten
I answered a very similar question here a few days ago. Using the same code, without an iterations limit and with an increased tolerance (1e-8 as per your example), I detect the expected convergence of exp(2x) + 3x - 4 using the secant method:
clear();
clc();
com = Inf;
i = 2;
err_tol = 1e-8;
f = #(x) exp(2*x) + 3*x - 4;
x(1) = 0.5;
x(2) = 0.4;
while (abs(com) > err_tol)
com = f(x(i)) * (x(i) - x(i-1)) / (f(x(i)) - f(x(i-1)));
x(i+1)= x(i) - com;
i = i + 1;
n = n - 1;
end
display(['Root X = ' num2str(x(end))]);
The message I receive is: Root X = 0.47369. It shouldn't be hard for you to implement your additional data within this code.
I am trying to find out the root of an equation constraint using Newton's Method (open to any other method). The equation constraint is dependent on the roots of a quadratic equation which has one unknown term. The equation descriptions (quadratic and constraint) are shown below. The roots of the quadratic equation are assumed to be p1 and p2.
x^2 + x*(c1*unknown/2 + C1*c2)/(c1*c2*c3*unknown/2) + 1/(c1*c2*c3*u/2) = 0
with constraint
(1/(p2-p1))*(exp(-0.3*p2) - 1)*(c1*c2 - p2) - (exp(-0.3*p1) - 1)*(c1*c2 - p1) - 0.04 = 0
I am wondering if there are any other approximation methods to solve this problem if Newton's Method is not going to do so.
Matlab Code
p0=10*10^6;
Cc=0.65*10^-6;Rp=100*10^3;Cp=55*10^-9; z1=1/(Cp*Rp);
N = 100;error = 0.02;
syms 'x'
a = 1;
b = ((Cc*(x/2+Rp))/(Cc*Cp*Rp*x/2));
c = 1/(Cc*Cp*Rp*x/2);
poles1 = (-b + sqrt(b^2 - 4*a*c))/(2*a);
poles2 = (-b - sqrt(b^2 - 4*a*c))/(2*a);
p1_subterm = (exp(-0.3*poles1) - 1)*(z1 - poles1);
p2_subterm = (exp(-0.3*poles2) - 1)*(z1- poles2);
f(x) = (1/(poles2 - poles1))*p2_subterm - p2_subterm - 0.04;
df = diff(f);
while i <= N
p = p0-(f(p0)/df(p0))
if (abs(p - p0)/abs(p)) < error
fprintf('Solution is %f \n', double(p))
return
end
i = i + 1;
p0 = p;
end
fprintf('Solution did not converge within %d iterations \n', N)
I don't think your code for f(x) corresponds to the equation listed above: In the MATLAB code 1/(poles2-poles1) multiplies both the exp((...)poles2) and the exp((...)poles1) terms and you have 1/(c1*c2) - poles1 instead of c1*c2 - poles1.
I have not checked through the poles1 and poles2 terms as I find the 10 sets of parenthesis intimidating. It would suggest making your code more readable by breaking up each of those equations in to a number of shorter, clearer lines.
Noting that we can multiply the quadratic by c1*c2*c3*unknown,
(c1*c2*c3*unknown)*x^2 + x*2*(c1*unknown/2 + C1*c2) + 2 = 0
then you can write the poles and f code as
% Here unknown is x
syms 'x'
a = c1*c2*c3*x;
b = c1*x + 2*c1*c2;
c = 2;
poles1 = (-b + sqrt(b^2 - 4*a*c))/(2*a);
poles2 = (-b - sqrt(b^2 - 4*a*c))/(2*a);
p1_subterm = (exp(-0.3*poles1) - 1)*(c1*c2 - poles1);
p2_subterm = (exp(-0.3*poles2) - 1)*(c1*c2 - poles2);
f(x) = (1/(poles2 - poles1))*p2_subterm - p2_subterm - 0.04;
I have a mathematical function E which I want to minimize. I get from solving this 16 possible solutions x1, x2, ..., x16, only two of which that actually minimize the function (located at a minimum). Using a for loop, I can then plug all of these 16 solutions into the original function, and select the solutions I need by applying some criteria via if statements (plotting E vs E(x) if x is real and positive, if first derivative of E is below a threshold, and if the second derivative of E is positive).
That way I only plot the solutions I'm interested in. However, I would now like to extract the relevant x that I plot. Here's a sample MATLAB code that plots the way I just described. I want to extract the thetas that I actually end up plotting. How to do that?
format long
theta_s = 0.77944100;
sigma = 0.50659500;
Delta = 0.52687700;
%% Defining the coefficients of the 4th degree polynomial
alpha = cos(2*theta_s);
beta = sin(2*theta_s);
gamma = 2*Delta^2/sigma^2;
a = -gamma^2 - beta^2*Delta^2 - alpha^2*Delta^2 + 2*alpha*Delta*gamma;
b = 2*alpha*gamma - 2*Delta*gamma - 2*alpha^2*Delta + 2*alpha*Delta^2 -...
2*beta^2*Delta;
c = 2*gamma^2 - 2*alpha*Delta*gamma - 2*gamma - alpha^2 + 4*alpha*Delta +...
beta^2*Delta^2 - beta^2 - Delta^2;
d = -2*alpha*gamma + 2*Delta*gamma + 2*alpha + 2*beta^2*Delta - 2*Delta;
e = beta^2 - gamma^2 + 2*gamma - 1;
%% Solve the polynomial numerically.
P = [a b c d e];
R = roots(P);
%% Solve r = cos(2x) for x: x = n*pi +- 1/2 * acos(r). Using n = 0 and 1.
theta = [1/2.*acos(R) -1/2.*acos(R) pi+1/2.*acos(R) pi-1/2.*acos(R)];
figure;
hold on;
x = 0:1/1000:2*pi;
y_1 = sigma*cos(x - theta_s) + sqrt(1 + Delta*cos(2*x));
y_2 = sigma*cos(x - theta_s) - sqrt(1 + Delta*cos(2*x));
plot(x,y_1,'black');
plot(x,y_2,'black');
grid on;
%% Plot theta if real, if positive, if 1st derivative is ~zero, and if 2nd derivative is positive
for j=1:numel(theta);
A = isreal(theta(j));
x_j = theta(j);
y_j = sigma*cos(x_j - theta_s) + sqrt(1 + Delta*cos(2*x_j));
FirstDer = sigma* sin(theta(j) - theta_s) + Delta*sin(2*theta(j))/...
sqrt(1 + Delta*cos(2*theta(j)));
SecDer = -sigma*cos(theta(j)-theta_s) - 2*Delta*cos(2*theta(j))/...
(1 + Delta*cos(2*theta(j)))^(1/2) - Delta^2 * (sin(2*theta(j)))^2/...
(1 + Delta*cos(2*theta(j)))^(3/2);
if A == 1 && x_j>=0 && FirstDer < 1E-7 && SecDer > 0
plot(x_j,y_j,['o','blue'])
end
end
After you finish all plotting, get the axes handle:
ax = gca;
then write:
X = get(ax.Children,{'XData'});
And X will be cell array of all the x-axis values from all lines in the graph. One cell for each line.
For the code above:
X =
[1.961054062875753]
[4.514533853417446]
[1x6284 double]
[1x6284 double]
(First, the code all worked. Thanks for the effort there.)
There are options here. A are couple below
Record the values as you generate them
Within the "success" if statement, simply record the values. See edits to your code below.
This would always be the preferred option for me, it just seems much more efficient.
xyResults = zeros(0,2); %%% INITIALIZE HERE
for j=1:numel(theta);
A = isreal(theta(j));
x_j = theta(j);
y_j = sigma*cos(x_j - theta_s) + sqrt(1 + Delta*cos(2*x_j));
FirstDer = sigma* sin(theta(j) - theta_s) + Delta*sin(2*theta(j))/...
sqrt(1 + Delta*cos(2*theta(j)));
SecDer = -sigma*cos(theta(j)-theta_s) - 2*Delta*cos(2*theta(j))/...
(1 + Delta*cos(2*theta(j)))^(1/2) - Delta^2 * (sin(2*theta(j)))^2/...
(1 + Delta*cos(2*theta(j)))^(3/2);
if A == 1 && x_j>=0 && FirstDer < 1E-7 && SecDer > 0
xyResults(end+1,:) = [x_j y_j]; %%%% RECORD HERE
plot(x_j,y_j,['o','blue'])
end
end
Get the result from the graphics objects
You can get the data you want from the actual graphics objects. This would be the option if there was just no way to capture the data as it was generated.
%First find the objects witht the data you want
% (Ideally you could record handles to the lines as you generated
% them above. But then you could also simply record the answer, so
% let's assume that direct record is not possible.)
% (BTW, 'findobj' is an underused, powerful function.)
h = findobj(0,'Marker','o','Color','b','type','line')
%Then get the `xdata` filed from each
capturedXdata = get(h,'XData');
capturedXdata =
2×1 cell array
[1.96105406287575]
[4.51453385341745]
%Then get the `ydata` filed from each
capturedYdata = get(h,'YData');
capturedYdata =
2×1 cell array
[1.96105406287575]
[4.51453385341745]
I have a 1024*1024*51 matrix. I'll do calculations to change some value of the matrix within for loops (change the value of matrix for each iteration). I find that the computing speed gets slower and slower and finally my computer gets into trouble.However the size of the matrix doesn't change. Anyone can shed some light on this problem?
function ActiveContours3D(method,grad,im,mu,nu,lambda1,lambda2,TimeSteps)
epsilon = 10e-10;
tic
fid=fopen('Chr18_z_25of25tiles-C=0_c0_n000.raw','rb','ieee-le');
Xdim = 1024;
Ydim = 1024;
Zdim = 51;
A = fread(fid,[Xdim Ydim*Zdim],'int16');
A = double(A);
size_of_A = size(A)
for(i=1:Zdim)
u0_color(:,:,i) = A(1 : Xdim , (i-1)*Ydim+1 : i*Ydim);
end
fclose(fid)
time = toc
[M,N,P,color] = size(u0_color);
size(u0_color );
u0_color = double(u0_color); % Convert u0_color values to double;
u0 = u0_color(:,:,:,1); % Define the Grayscale volumetric image.
u0_color = uint8(u0_color); % Necessary for color visualization
x = 1:M;
y = 1:N;
z = 1:P;
dx = 1
dy = 1
dz = 1
dim_approx = 2*M*N*P / sqrt(M*N*P);
if(method == 'Explicit')
dt = 0.9 / ((2*mu/(dx^2)) + (2*mu/(dy^2)) + (2*mu/(dz^2))) % 90% CFL
elseif(method == 'Implicit')
dt = (10e7) * 0.9 / ((2*mu/(dx^2)) + (2*mu/(dy^2)) + (2*mu/(dz^2)))
end
[X,Y,Z] = meshgrid(x,y,z);
x0 = (M+1)/2;
y0 = (N+1)/2;
z0 = (P+1)/2;
r0 = min(min(M,N),P)/3;
phi = sqrt((X-x0).^2 + (Y-y0).^2 + (Z-z0).^2) - r0;
phi_visualize = phi; % Use this for visualization in 3D
phi = permute(phi,[2,1,3]); % Use this for computations in 3D
write_to_binary_file(phi_visualize,0); % record initial conditions
tic
for(n=1:TimeSteps)
n
c1 = C1_3d(u0,phi);
c2 = C2_3d(u0,phi);
% x
phi_xp = [phi(2:M,:,:); phi(M,:,:)]; % vertical concatenation
phi_xm = [phi(1,:,:); phi(1:M-1,:,:)]; % (since x values are rows)
% cat(1,A,B) is the same as [A;B]
Dx_m = (phi - phi_xm)/dx; % first derivatives
Dx_p = (phi_xp - phi)/dx;
Dxx = (Dx_p - Dx_m)/dx; % second derivative
% y
phi_yp = [phi(:,2:N,:) phi(:,N,:)]; % horizontal concatenation
phi_ym = [phi(:,1,:) phi(:,1:N-1,:)]; % (since y values are columns)
% cat(2,A,B) is the same as [A,B]
Dy_m = (phi - phi_ym)/dy;
Dy_p = (phi_yp - phi)/dy;
Dyy = (Dy_p - Dy_m)/dy;
% z
phi_zp = cat(3,phi(:,:,2:P),phi(:,:,P));
phi_zm = cat(3,phi(:,:,1) ,phi(:,:,1:P-1));
Dz_m = (phi - phi_zm)/dz;
Dz_p = (phi_zp - phi)/dz;
Dzz = (Dz_p - Dz_m)/dz;
% x,y,z
Dx_0 = (phi_xp - phi_xm) / (2*dx);
Dy_0 = (phi_yp - phi_ym) / (2*dy);
Dz_0 = (phi_zp - phi_zm) / (2*dz);
phi_xp_yp = [phi_xp(:,2:N,:) phi_xp(:,N,:)];
phi_xp_ym = [phi_xp(:,1,:) phi_xp(:,1:N-1,:)];
phi_xm_yp = [phi_xm(:,2:N,:) phi_xm(:,N,:)];
phi_xm_ym = [phi_xm(:,1,:) phi_xm(:,1:N-1,:)];
phi_xp_zp = cat(3,phi_xp(:,:,2:P),phi_xp(:,:,P));
phi_xp_zm = cat(3,phi_xp(:,:,1) ,phi_xp(:,:,1:P-1));
phi_xm_zp = cat(3,phi_xm(:,:,2:P),phi_xm(:,:,P));
phi_xm_zm = cat(3,phi_xm(:,:,1) ,phi_xm(:,:,1:P-1));
phi_yp_zp = cat(3,phi_yp(:,:,2:P),phi_yp(:,:,P));
phi_yp_zm = cat(3,phi_yp(:,:,1) ,phi_yp(:,:,1:P-1));
phi_ym_zp = cat(3,phi_ym(:,:,2:P),phi_ym(:,:,P));
phi_ym_zm = cat(3,phi_ym(:,:,1) ,phi_ym(:,:,1:P-1));
if(grad == 'Dirac')
Grad = DiracDelta(phi); % Dirac delta
%Grad = 1;
elseif(grad == 'Grad ')
Grad = (((Dx_0.^2)+(Dy_0.^2)+(Dz_0.^2)).^(1/2)); % |grad phi|
end
if(method == 'Explicit')
% CURVATURE: *mu*k|grad phi|* (central differences):
K = zeros(M,N,P);
Dxy = (phi_xp_yp - phi_xp_ym - phi_xm_yp + phi_xm_ym) / (4*dx*dy);
Dxz = (phi_xp_zp - phi_xp_zm - phi_xm_zp + phi_xm_zm) / (4*dx*dz);
Dyz = (phi_yp_zp - phi_yp_zm - phi_ym_zp + phi_ym_zm) / (4*dy*dz);
K = ( (Dx_0.^2).*Dyy - 2*Dx_0.*Dy_0.*Dxy + (Dy_0.^2).*Dxx ...
+ (Dx_0.^2).*Dzz - 2*Dx_0.*Dz_0.*Dxz + (Dz_0.^2).*Dxx ...
+ (Dy_0.^2).*Dzz - 2*Dy_0.*Dz_0.*Dyz + (Dz_0.^2).*Dyy) ./ ((Dx_0.^2 + Dy_0.^2 + Dz_0.^2).^(3/2) + epsilon);
phi_temp = phi + dt * Grad .* ( mu.*K + lambda1*(u0 - c1).^2 - lambda2*(u0 - c2).^2 );
elseif(method == 'Implicit')
C1x = 1 ./ sqrt(Dx_p.^2 + Dy_0.^2 + Dz_0.^2 + (10e-7)^2);
C2x = 1 ./ sqrt(Dx_m.^2 + Dy_0.^2 + Dz_0.^2 + (10e-7)^2);
C3y = 1 ./ sqrt(Dx_0.^2 + Dy_p.^2 + Dz_0.^2 + (10e-7)^2);
C4y = 1 ./ sqrt(Dx_0.^2 + Dy_m.^2 + Dz_0.^2 + (10e-7)^2);
C5z = 1 ./ sqrt(Dx_0.^2 + Dy_0.^2 + Dz_p.^2 + (10e-7)^2);
C6z = 1 ./ sqrt(Dx_0.^2 + Dy_0.^2 + Dz_m.^2 + (10e-7)^2);
% m = (dt/(dx*dy)) * Grad .* mu; % 2D
m = (dt/(dx*dy)) * Grad .* mu;
C = 1 + m.*(C1x + C2x + C3y + C4y + C5z + C6z);
C1x_2x = C1x.*phi_xp + C2x.*phi_xm;
C3y_4y = C3y.*phi_yp + C4y.*phi_ym;
C5z_6z = C5z.*phi_zp + C6z.*phi_zm;
phi_temp = (1 ./ C) .* ( phi + m.*(C1x_2x+C3y_4y) + (dt*Grad).*(lambda1*(u0 - c1).^2) - (dt*Grad).*(lambda2*(u0 - c2).^2) );
end
phi = phi_temp;
phi_visualize = permute(phi,[2,1,3]);
write_to_binary_file(phi_visualize,n); % record
end
time = toc
n = n
T = dt*n
clear
clear all
In general Matlab keeps track of all the variables in the form of matrix. When you work with lot of variables with many dimensions the RAM memory will be allocated for storing this variable. Hence on working with lots of variables that is gonna run for multiple iterations it is better to clear the variable from the memory. To do so use the command
clear variable_name_1, variable_name_2,... variable_name_3;
Although keeping all the variables keeps the code to look organised, however when you face such issues try clearing the unwanted variables.
Check this link to use clear command in detail: http://www.mathworks.in/help/matlab/ref/clear.html
I have written the following code in order to try to plot the following integral against values of r, but MATLAB gives me an error -- is fun too long? am I going wrong somewhere else?
figure(1); %f_1
r = 0:0.001:50;
q = zeros(1, size(r));
for m = 1:numel(r)
fun = #(t) ((-3*(r(m).^3)*sin(3*t) + 2*(r(m)^2)*cos(2*t) + 7*r(m)*cos(t) -2*sin(t))*(-6*(r(m)^3)*sin(3*t) + 2*(r(m)^3)*cos(3*t) - 3*(r(m)^4)*cos(4*t) - 2*(r(m)^3)*sin(3*t) + 2*(r(m)^2)*cos(2*t) + 7*(r(m)^2)*sin(2*t))) - ((3*(r(m).^3).*cos(3*t) + 2*(r(m).^2).*sin(2*t) + 7*r(m).*sin(t) - 2*r(m).*cos(t))*(-6*(r(m).^3).*cos(3*t) + 2*(r(m).^3).*sin(3*t) + 3*(r(m).^4).*sin(4*t) - 2* (r(m).^3).*cos(3*t) - 2*(r(m).^2).*sin(2*t) + 7*(r(m).^2).*cos(2*t)))./((-3*(r(m).^3).*sin(3.*t) + 2*(r(m).^2)*cos(2.*t) + 7*r(m).*cos(t) - 2*sin(t)).^2 + (3*(r(m).^3).*cos(3*t) + 2*(r(m).^2).*sin(2*t) + 7*r(m).*sin(t) - 2*r(m).*cos(t)).^2);
q(m) = quad(fun, 0, 2*pi);
end
The error I get is
Error using * Inner matrix dimensions must agree.
Error in #(t)......
Error in quad (line 76) y = f(x, varargin{:});
I'll show you a way you may proceed, based on a retained r and fun (I did not pick all the terms of the native function):
r = 0:0.1:50;
q = zeros(size(r));
for ii = 1:numel(r)
fun = #(t) (-3.*(r(ii).^3).*sin(3.*t) + 2.*(r(ii).^2).*cos(2.*t) + 7.*r(ii).*cos(t) -2.*sin(t));
q(ii) = quad(fun,0,2.*pi);
end
Since your r is quite huge (50001 elements if I remember right), I'd go for parfor insted of simple for loop, too.
EDIT
As alternative solution, you could achieve the same results without any anonymous function, by following this way:
r = 0:.01:50;
fun1 = zeros(size(r));
t = 0:.001:(2*pi);
for ii = 1:numel(r)
fun1(ii) = trapz(t,(-3.*(r(ii).^3).*sin(3.*t) + 2.*(r(ii).^2).*cos(2.*t) + 7.*r(ii).*cos(t) -2.*sin(t)));
end