Laguerre's method to obtain poly roots - matlab

I have to write using Laguerre's method a piece of code to find real and complex roots of poly:
f(x)=a4x4+a3x3+a2x2+a1x+a0 , [a4 a3 a2 a1 a0]=[-2 5 5 2 1]
I got something:
function y = laguerre (x,coef)
tol = 10^(-10);
%polynomial order
n = length(coef);
i = 0;
while (abs(polyval(coef,x)) > tol)
i = i + 1
x
polyval(coef,x)
%second derivative
a=polyval(polyder(polyder(coef)), x);
%first derivative
b=polyval(polyder(coef), x);
%polynomial value
c=polyval(coef, x);
%square root
r = sqrt((n-1)*[(n-1)*b^2-n*a*c]);
d1 = b + r;
d2 = b - r;
%highest abs value denominator chosen
if (abs(d1) > abs(d2))
d = d1;
else
d = d2;
end
%next iteration value obtained
z = n*c/d;
x = x - z;
end
i = i + 1
x
polyval(coef,x)
y = x;
return
end
and I want to draw and/ or obtain my roots:
coef = [-2 5 5 2 1];
fh = #poly;
%diary on
%plot of the function
figure(1);
fplot(fh, [-500 500]);
hold on;
figure(2);
fplot(fh, [-1.5 3]);
hold on;
%roots obtained using MM2
%z1(1) = MM2(-500,coef);
%z1(2) = MM2(500,coef);
%z1(3) = MM2(1 + i, coef);
%z1(4) = MM2(0 - 2i, coef);
%roots obtained using Laguerre's
%z2(1) = laguerre(-500,coef);
z2(2) = laguerre(500,coef);
%z2(3) = laguerre(1 + i, coef);
%z2(4) = laguerre(0 - 2i, coef);
%additional points on plot
p = [z1(1) z2(2)];
plot(p,[0 0],'r*');
legend('function','zeros');
hold off;
figure(1);
plot(p,[0 0],'r*');
plot([-500 500],[0 0], 'b*');
legend('function','zeros','START points');
diary off;
hold off;
As you see, some part of code is commented because I really don't know how to move on. I got many warnings. I got one error in 1st part of the code. I am looking for some tips or direction what to do.

Your code works perfectly well, you should get the roots
x=-500 => x=-0.6694729, p(x)=-8.882D-16 in 9 steps
x= 500 => x=3.3489712, p(x)=1.621D-14 in 8 steps
x=1 + i => x=-0.0897491+i*0.4636332, p(x)=i*8.327D-17 in 4 steps
x=0 - 2i => x=-0.0897491-i*0.4636332, p(x)=i*5.551D-17 in 4 steps
To illustrate the bigger picture, the iteration map for the Laguerre method with initial values in [-4,4]+[-4,4]*i looks like
Every color shade represents one step. There is nothing nefarious in this polynomial preventing convergence of the method.
To compare with, the Halley iteration map is
and the Newton fractal

Related

find nearest point to a fitting line and the neighborhood of it in Matlab

Supposed I have two random double array, which means that one x coordinate might have multiple y value.
X = randi([-10 10],1,1000);
Y = randi([-10 10],1,1000);
Then I give a line equation: y=ax+b.
I want to find the nearest point to the nearest point to the line based on every x point. And when I find this point, I will find it's neighborhood points within specific range. Please forgive my poor English, maybe following picture can help more.
Because I have a lot of data points, I hope there is an efficient way to deal with this problem.
if your X's are discrete you can try something like:
xrng = [-10 10];
yrng = [-10 10];
a = rand;
b = rand;
f = #(x) a*x + b;
X = randi(xrng,1,1000);
Y = randi(yrng,1,1000);
ezplot(f,xrng);
hold on;
plot(X,Y,'.');
xx = xrng(1):xrng(2);
nbrSz = 2;
nx = diff(xrng);
nearestIdx = zeros(nx,1);
nbrIdxs = cell(nx,1);
for ii = 1:nx
x = xx(ii);
y = f(x);
idx = find(X == x);
[~,idxidx] = min(abs(y - Y(idx)));
nearestIdx(ii) = idx(idxidx);
nbrIdxIdxs = abs(Y(nearestIdx(ii)) - Y(idx)) <= nbrSz;
nbrIdxs{ii} = idx(nbrIdxIdxs);
plot(X(nearestIdx(ii)),Y(nearestIdx(ii)),'og');
plot(X(nearestIdx(ii)) + [0 0],Y(nearestIdx(ii)) + [-nbrSz nbrSz],'g')
plot(X(nbrIdxs{ii}),Y(nbrIdxs{ii}),'sy')
end

Plotting a 2d vector on 3d axes in matlab

I have three vectors x,y,t. For each combination x,y,t there is a (u,v) value associated with it. How to plot this in matlab? Actually I'm trying to plot the solution of 2d hyperbolic equation
vt = A1vx + A2vy where A1 and A2 are 2*2 matrices and v is a 2*1 vector. I was trying scatter3 and quiver3 but being new to matlab I'm not able to represent the solution correctly.
In the below code I have plot at only a particular time-level. How to show the complete solution in just one plot? Any help?
A1 = [5/3 2/3; 1/3 4/3];
A2 = [-1 -2; -1 0];
M = 10;
N = 40;
delta_x = 1/M;
delta_y = delta_x;
delta_t = 1/N;
x_points = 0:delta_x:1;
y_points = 0:delta_y:1;
t_points = 0:delta_t:1;
u = zeros(M+1,M+1,N+1,2);
for i=1:M+1,
for j=1:M+1,
u(i,j,1,1) = (sin(pi*x_points(i)))*sin(2*pi*y_points(j)) ;
u(i,j,1,2) = cos(2*pi*x_points(i));
end
end
for j=1:M+1,
for t=1:N+1,
u(M+1,j,t,1) = sin(2*t);
u(M+1,j,t,2) = cos(2*t);
end
end
for i=1:M+1
for t=1:N+1
u(i,1,t,1) = sin(2*t);
u(i,M+1,t,2) = sin(5*t) ;
end
end
Rx = delta_t/delta_x;
Ry = delta_t/delta_y;
for t=2:N+1
v = zeros(M+1,M+1,2);
for i=2:M,
for j=2:M,
A = [(u(i+1,j,t-1,1) - u(i-1,j,t-1,1)) ; (u(i+1,j,t-1,2) - u(i-1,j,t-1,2))];
B = [(u(i+1,j,t-1,1) -2*u(i,j,t-1,1) +u(i-1,j,t-1,1)) ; (u(i+1,j,t-1,2) -2*u(i,j,t-1,2) +u(i-1,j,t-1,2))];
C = [u(i,j,t-1,1) ; u(i,j,t-1,2)];
v(i,j,:) = C + Rx*A1*A/2 + Rx*Rx*A1*A1*B/2;
end
end
for i=2:M,
for j=2:M,
A = [(v(i,j+1,1) - v(i,j-1,1)) ; (v(i,j+1,2) - v(i,j-1,2)) ];
B = [(v(i,j+1,1) - 2*v(i,j,1) +v(i,j-1,1)) ; (v(i,j+1,2) - 2*v(i,j,2) +v(i,j-1,2))];
C = [v(i,j,1) ; v(i,j,2)];
u(i,j,t,:) = C + Ry*A2*A/2 + Ry*Ry*A2*A2*B/2;
end
end
if j==2
u(i,1,t,2) = u(i,2,t,2);
end
if j==M
u(i,M+1,t,1) = u(i,M,t,1);
end
if i==2
u(1,j,t,:) = u(2,j,t,:) ;
end
end
time_level = 2;
quiver(x_points, y_points, u(:,:,time_level,1), u(:,:,time_level,2))
You can plot it in 3D, but personally I think it would be hard to make sense of.
There's a quiver3 equivalent for your plotting function. z-axis in this case would be time (say, equally spaced), and z components of the vectors would be zero. Unlike 2D version of this function, it does not support passing in coordinate vectors, so you need to create the grid explicitly using meshgrid:
sz = size(u);
[X, Y, Z] = meshgrid(x_points, y_points, 1:sz(3));
quiver3(X, Y, Z, u(:,:,:,1), u(:,:,:,2), zeros(sz(1:3)));
You may also color each timescale differently by plotting them one at a time, but it's still hard to make sense of the results:
figure(); hold('all');
for z = 1:sz(3)
[X, Y, Z] = meshgrid(x_points, y_points, z);
quiver3(X, Y, Z, u(:,:,z,1), u(:,:,z,2), zeros([sz(1:2),1]));
end

MATLAB: data points won't connect?

I only have about two weeks of experience with programming/Matlab, so I'm just a beginner. In my code I would like to plot mu as a function of alpha. When I display mu it shows the 10 values of mu for each value of alpha. However, when I plot the graph it gives the values of mu as seperate points. But I want the points to be connected with just one line. How can I solve this problem?
n=40; %number of months
p=0.23; %probability of success
num_of_simulations=100;
s=rng; x = rand(1,n)<p;
rng(s);
hold on;
for alpha=0.01:0.01:0.1;
for i=1:num_of_simulations
x = rand(1,n)<p;
S0=5000; %initial value
Y(1)=S0*alpha; %deposit
for k=1
if x(1,1)==1;
S(1, i)=S0+2*Y(1);
else
S(1, i)=S0-Y(1);
end
end
for k=2:n
Y(k)=S(k-1, i)*alpha;
if x(1,k)==1;
S(k, i)=S(k-1, i)+2*Y(k);
else
S(k, i)=S(k-1, i)-Y(k);
end
end
Sn(i)=S(n,i); %end value for each simulations
end
mu=mean(Sn);
disp(mu);
plot(alpha,mu);
end
The reason your points aren't connected is because you plot each point separately. If we take a different approach and take alpha = 0.01:0.01:0.1; out of the for loop definition and then change the for loop definition to for j=1:numel(alpha) we can still loop over every element of alpha. Now we need to change each use of alpha in the loop to alpha(j) so that we are referring to the current element of alpha and not every element. Following on from this we need to change mu to mu(j). What this means is that when the entire loop has finished we have all of the values of alpha and mu stored and 1 call to plot(alpha, mu) will plot the data with the points connected as in
This also enables us to remove hold on; too as we only plot once.
I've included the complete edited code here for you to see. The changes are minuscule and should make sense.
clear all
close all
n = 40; %number of months
p = 0.23; %probability of success
num_of_simulations = 100;
s = rng;
x = rand(1, n) < p;
rng(s);
alpha = 0.01:0.01:0.1;
for j = 1:numel(alpha)
for i = 1:num_of_simulations
x = rand(1, n) < p;
S0 = 5000; %initial value
Y(1) = S0*alpha(j); %deposit
for k = 1
if x(1, 1) == 1;
S(1, i) = S0 + 2*Y(1);
else
S(1, i) = S0 - Y(1);
end
end
for k = 2:n
Y(k) = S(k-1, i)*alpha(j);
if x(1, k) == 1;
S(k, i) = S(k-1, i) + 2*Y(k);
else
S(k, i) = S(k-1, i) - Y(k);
end
end
Sn(i) = S(n, i); %end value for each simulations
end
mu(j) = mean(Sn);
disp(mu(j));
end
plot(alpha, mu);

How to replace the Laplace variable in a transfer function with a number/value? T(s) -> T(jw)?

Was wondering how I could achieve this in Matlab:
T(s) = 1/(s+1) -> T(jw) = 1/(jw+1)
Setting s = jw doesn't help.
For better understanding:
R(s) = some transfer function
L(s) = some transfer function
T(s) = R(s) * L(s)
value_at_jw = T(jw)
You basically want to evaluate your transfer function at a certain frequency.
The result would be a complex number.
You can't just substitute s with a frequency, you would need to create a polynomial or an anonymous function out from your denominator and numerator. Which is one way, an interesting one. Another very simple way is to use the outputs of the bode function:
Imagine a transfer function G and a frequency value jw you want to insert for 's':
G = tf([2 1 ], [1 1 1])
jw = 1i*2000 % or easier without the complex "i"
G =
2 s + 1
-----------
s^2 + s + 1
Now you want to know magnitude and phase for the frequency s = jw
[mag,phase] = bode( G, imag(jw) ) % or just w
The rest is math, you now have magnitude and phase=angle of your complex result. A complex number of form z = a + bi can be created as follows:
z = mag*( cos(phase)+1i*sin(phase) )
returns:
z = -4.3522e-04 - 9.0032e-04i
If you have Matlab's control systems toolbox installed ($$$), you can do a sort of symbolic computations by defining transfer functions, either by giving the polynomial coefficients with tf or as a system factored in poles and zeros using zpk:
>> R = tf([1], [1, 1])
Transfer function:
1
-----
s + 1
>> L = zpk([1,2],[3,4,5], 6)
Zero/pole/gain:
6 (s-1) (s-2)
-----------------
(s-3) (s-4) (s-5)
You can convert between these two formats, and they can be used for simple math:
>> R * L
Zero/pole/gain:
6 (s-1) (s-2)
-----------------------
(s+1) (s-3) (s-4) (s-5)
A complex frequency response, finally, can be obtained using freqresp:
>> f = logspace(-2, 2, 200);
>> frequency_response = squeeze(freqresp(T, f, 'Hz'));
>> subplot(211)
>> loglog(f, abs(frequency_response))
>> subplot(212)
>> semilogx(f, angle(frequency_response))
Here are two ways.
wmax = 20;
dw = 0.1;
w = -wmax:dw:wmax;
T = 1./(1 + j*w);
subplot(2,1,1)
hold on
grid on
p = plot(w, abs(T))
title('Magnitude')
subplot(2,1,2)
hold on
grid on
p = plot(w, angle(T))
title('Phase')
// or
H = freqs(1, [1 1], w);
figure
subplot(2,1,1)
hold on
grid on
p = plot(w, abs(H))
title('Magnitude')
subplot(2,1,2)
hold on
grid on
p = plot(w, angle(H))
title('Phase')
The result is, of course, identical
Hope that helps.

Least squares circle fitting using MATLAB Optimization Toolbox

I am trying to implement least squares circle fitting following this paper (sorry I can't publish it). The paper states, that we could fit a circle, by calculating the geometric error as the euclidean distance (Xi'') between a specific point (Xi) and the corresponding point on the circle (Xi'). We have three parametres: Xc (a vector of coordinates the center of circle), and R (radius).
I came up with the following MATLAB code (note that I am trying to fit circles, not spheres as it is indicated on the images):
function [ circle ] = fit_circle( X )
% Kör paraméterstruktúra inicializálása
% R - kör sugara
% Xc - kör középpontja
circle.R = NaN;
circle.Xc = [ NaN; NaN ];
% Kezdeti illesztés
% A köz középpontja legyen a súlypont
% A sugara legyen az átlagos négyzetes távolság a középponttól
circle.Xc = mean( X );
d = bsxfun(#minus, X, circle.Xc);
circle.R = mean(bsxfun(#hypot, d(:,1), d(:,2)));
circle.Xc = circle.Xc(1:2)+random('norm', 0, 1, size(circle.Xc));
% Optimalizáció
options = optimset('Jacobian', 'on');
out = lsqnonlin(#ort_error, [circle.Xc(1), circle.Xc(2), circle.R], [], [], options, X);
end
%% Cost function
function [ error, J ] = ort_error( P, X )
%% Calculate error
R = P(3);
a = P(1);
b = P(2);
d = bsxfun(#minus, X, P(1:2)); % X - Xc
n = bsxfun(#hypot, d(:,1), d(:,2)); % || X - Xc ||
res = d - R * bsxfun(#times,d,1./n);
error = zeros(2*size(X,1), 1);
error(1:2:2*size(X,1)) = res(:,1);
error(2:2:2*size(X,1)) = res(:,2);
%% Jacobian
xdR = d(:,1)./n;
ydR = d(:,2)./n;
xdx = bsxfun(#plus,-R./n+(d(:,1).^2*R)./n.^3,1);
ydy = bsxfun(#plus,-R./n+(d(:,2).^2*R)./n.^3,1);
xdy = (d(:,1).*d(:,2)*R)./n.^3;
ydx = xdy;
J = zeros(2*size(X,1), 3);
J(1:2:2*size(X,1),:) = [ xdR, xdx, xdy ];
J(2:2:2*size(X,1),:) = [ ydR, ydx, ydy ];
end
The fitting however is not too good: if I start with the good parameter vector the algorithm terminates at the first step (so there is a local minima where it should be), but if I perturb the starting point (with a noiseless circle) the fitting stops with very large errors. I am sure that I've overlooked something in my implementation.
For what it's worth, I implemented these methods in MATLAB a while ago. However, I did it apparently before I knew about lsqnonlin etc, as it uses a hand-implemented regression. This is probably slow, but may help to compare with your code.
function [x, y, r, sq_error] = circFit ( P )
%# CIRCFIT fits a circle to a set of points using least sqaures
%# P is a 2 x n matrix of points to be fitted
per_error = 0.1/100; % i.e. 0.1%
%# initial estimates
X = mean(P, 2)';
r = sqrt(mean(sum((repmat(X', [1, length(P)]) - P).^2)));
v_cen2points = zeros(size(P));
niter = 0;
%# looping until convergence
while niter < 1 || per_diff > per_error
%# vector from centre to each point
v_cen2points(1, :) = P(1, :) - X(1);
v_cen2points(2, :) = P(2, :) - X(2);
%# distacnes from centre to each point
centre2points = sqrt(sum(v_cen2points.^2));
%# distances from edge of circle to each point
d = centre2points - r;
%# computing 3x3 jacobean matrix J, and solvign matrix eqn.
R = (v_cen2points ./ [centre2points; centre2points])';
J = [ -ones(length(R), 1), -R ];
D_rXY = -J\d';
%# updating centre and radius
r_old = r; X_old = X;
r = r + D_rXY(1);
X = X + D_rXY(2:3)';
%# calculating maximum percentage change in values
per_diff = max(abs( [(r_old - r) / r, (X_old - X) ./ X ])) * 100;
%# prevent endless looping
niter = niter + 1;
if niter > 1000
error('Convergence not met in 1000 iterations!')
end
end
x = X(1);
y = X(2);
sq_error = sum(d.^2);
This is then run with:
X = [1 2 5 7 9 3];
Y = [7 6 8 7 5 7];
[x_centre, y_centre, r] = circFit( [X; Y] )
And plotted with:
[X, Y] = cylinder(r, 100);
scatter(X, Y, 60, '+r'); axis equal
hold on
plot(X(1, :) + x_centre, Y(1, :) + y_centre, '-b', 'LineWidth', 1);
Giving: